freedreno: drop shader_t
[mesa.git] / src / freedreno / decode / disasm-a2xx.c
1 /*
2 * Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <string.h>
28
29 #include "disasm.h"
30 #include "instr-a2xx.h"
31 #include "rnnutil.h"
32
33 static const char *levels[] = {
34 "",
35 "\t",
36 "\t\t",
37 "\t\t\t",
38 "\t\t\t\t",
39 "\t\t\t\t\t",
40 "\t\t\t\t\t\t",
41 "\t\t\t\t\t\t\t",
42 "\t\t\t\t\t\t\t\t",
43 "\t\t\t\t\t\t\t\t\t",
44 "x",
45 "x",
46 "x",
47 "x",
48 "x",
49 "x",
50 };
51
52 enum debug_t debug;
53
54 static struct rnn *rnn;
55
56 /*
57 * ALU instructions:
58 */
59
60 static const char chan_names[] = {
61 'x', 'y', 'z', 'w',
62 /* these only apply to FETCH dst's: */
63 '0', '1', '?', '_',
64 };
65
66 static void print_srcreg(uint32_t num, uint32_t type,
67 uint32_t swiz, uint32_t negate, uint32_t abs)
68 {
69 if (negate)
70 printf("-");
71 if (abs)
72 printf("|");
73 printf("%c%u", type ? 'R' : 'C', num);
74 if (swiz) {
75 int i;
76 printf(".");
77 for (i = 0; i < 4; i++) {
78 printf("%c", chan_names[(swiz + i) & 0x3]);
79 swiz >>= 2;
80 }
81 }
82 if (abs)
83 printf("|");
84 }
85
86 static void print_dstreg(uint32_t num, uint32_t mask, uint32_t dst_exp)
87 {
88 printf("%s%u", dst_exp ? "export" : "R", num);
89 if (mask != 0xf) {
90 int i;
91 printf(".");
92 for (i = 0; i < 4; i++) {
93 printf("%c", (mask & 0x1) ? chan_names[i] : '_');
94 mask >>= 1;
95 }
96 }
97 }
98
99 static void print_export_comment(uint32_t num, gl_shader_stage type)
100 {
101 const char *name = NULL;
102 switch (type) {
103 case MESA_SHADER_VERTEX:
104 switch (num) {
105 case 62: name = "gl_Position"; break;
106 case 63: name = "gl_PointSize"; break;
107 }
108 break;
109 case MESA_SHADER_FRAGMENT:
110 switch (num) {
111 case 0: name = "gl_FragColor"; break;
112 }
113 break;
114 default:
115 break;
116 }
117 /* if we had a symbol table here, we could look
118 * up the name of the varying..
119 */
120 if (name) {
121 printf("\t; %s", name);
122 }
123 }
124
125 struct {
126 uint32_t num_srcs;
127 const char *name;
128 } vector_instructions[0x20] = {
129 #define INSTR(opc, num_srcs) [opc] = { num_srcs, #opc }
130 INSTR(ADDv, 2),
131 INSTR(MULv, 2),
132 INSTR(MAXv, 2),
133 INSTR(MINv, 2),
134 INSTR(SETEv, 2),
135 INSTR(SETGTv, 2),
136 INSTR(SETGTEv, 2),
137 INSTR(SETNEv, 2),
138 INSTR(FRACv, 1),
139 INSTR(TRUNCv, 1),
140 INSTR(FLOORv, 1),
141 INSTR(MULADDv, 3),
142 INSTR(CNDEv, 3),
143 INSTR(CNDGTEv, 3),
144 INSTR(CNDGTv, 3),
145 INSTR(DOT4v, 2),
146 INSTR(DOT3v, 2),
147 INSTR(DOT2ADDv, 3), // ???
148 INSTR(CUBEv, 2),
149 INSTR(MAX4v, 1),
150 INSTR(PRED_SETE_PUSHv, 2),
151 INSTR(PRED_SETNE_PUSHv, 2),
152 INSTR(PRED_SETGT_PUSHv, 2),
153 INSTR(PRED_SETGTE_PUSHv, 2),
154 INSTR(KILLEv, 2),
155 INSTR(KILLGTv, 2),
156 INSTR(KILLGTEv, 2),
157 INSTR(KILLNEv, 2),
158 INSTR(DSTv, 2),
159 INSTR(MOVAv, 1),
160 }, scalar_instructions[0x40] = {
161 INSTR(ADDs, 1),
162 INSTR(ADD_PREVs, 1),
163 INSTR(MULs, 1),
164 INSTR(MUL_PREVs, 1),
165 INSTR(MUL_PREV2s, 1),
166 INSTR(MAXs, 1),
167 INSTR(MINs, 1),
168 INSTR(SETEs, 1),
169 INSTR(SETGTs, 1),
170 INSTR(SETGTEs, 1),
171 INSTR(SETNEs, 1),
172 INSTR(FRACs, 1),
173 INSTR(TRUNCs, 1),
174 INSTR(FLOORs, 1),
175 INSTR(EXP_IEEE, 1),
176 INSTR(LOG_CLAMP, 1),
177 INSTR(LOG_IEEE, 1),
178 INSTR(RECIP_CLAMP, 1),
179 INSTR(RECIP_FF, 1),
180 INSTR(RECIP_IEEE, 1),
181 INSTR(RECIPSQ_CLAMP, 1),
182 INSTR(RECIPSQ_FF, 1),
183 INSTR(RECIPSQ_IEEE, 1),
184 INSTR(MOVAs, 1),
185 INSTR(MOVA_FLOORs, 1),
186 INSTR(SUBs, 1),
187 INSTR(SUB_PREVs, 1),
188 INSTR(PRED_SETEs, 1),
189 INSTR(PRED_SETNEs, 1),
190 INSTR(PRED_SETGTs, 1),
191 INSTR(PRED_SETGTEs, 1),
192 INSTR(PRED_SET_INVs, 1),
193 INSTR(PRED_SET_POPs, 1),
194 INSTR(PRED_SET_CLRs, 1),
195 INSTR(PRED_SET_RESTOREs, 1),
196 INSTR(KILLEs, 1),
197 INSTR(KILLGTs, 1),
198 INSTR(KILLGTEs, 1),
199 INSTR(KILLNEs, 1),
200 INSTR(KILLONEs, 1),
201 INSTR(SQRT_IEEE, 1),
202 INSTR(MUL_CONST_0, 1),
203 INSTR(MUL_CONST_1, 1),
204 INSTR(ADD_CONST_0, 1),
205 INSTR(ADD_CONST_1, 1),
206 INSTR(SUB_CONST_0, 1),
207 INSTR(SUB_CONST_1, 1),
208 INSTR(SIN, 1),
209 INSTR(COS, 1),
210 INSTR(RETAIN_PREV, 1),
211 #undef INSTR
212 };
213
214 static int disasm_alu(uint32_t *dwords, uint32_t alu_off,
215 int level, int sync, gl_shader_stage type)
216 {
217 instr_alu_t *alu = (instr_alu_t *)dwords;
218
219 printf("%s", levels[level]);
220 if (debug & PRINT_RAW) {
221 printf("%02x: %08x %08x %08x\t", alu_off,
222 dwords[0], dwords[1], dwords[2]);
223 }
224
225 printf(" %sALU:\t", sync ? "(S)" : " ");
226
227 printf("%s", vector_instructions[alu->vector_opc].name);
228
229 if (alu->pred_select & 0x2) {
230 /* seems to work similar to conditional execution in ARM instruction
231 * set, so let's use a similar syntax for now:
232 */
233 printf((alu->pred_select & 0x1) ? "EQ" : "NE");
234 }
235
236 printf("\t");
237
238 print_dstreg(alu->vector_dest, alu->vector_write_mask, alu->export_data);
239 printf(" = ");
240 if (vector_instructions[alu->vector_opc].num_srcs == 3) {
241 print_srcreg(alu->src3_reg, alu->src3_sel, alu->src3_swiz,
242 alu->src3_reg_negate, alu->src3_reg_abs);
243 printf(", ");
244 }
245 print_srcreg(alu->src1_reg, alu->src1_sel, alu->src1_swiz,
246 alu->src1_reg_negate, alu->src1_reg_abs);
247 if (vector_instructions[alu->vector_opc].num_srcs > 1) {
248 printf(", ");
249 print_srcreg(alu->src2_reg, alu->src2_sel, alu->src2_swiz,
250 alu->src2_reg_negate, alu->src2_reg_abs);
251 }
252
253 if (alu->vector_clamp)
254 printf(" CLAMP");
255
256 if (alu->export_data)
257 print_export_comment(alu->vector_dest, type);
258
259 printf("\n");
260
261 if (alu->scalar_write_mask || !alu->vector_write_mask) {
262 /* 2nd optional scalar op: */
263
264 printf("%s", levels[level]);
265 if (debug & PRINT_RAW)
266 printf(" \t");
267
268 if (scalar_instructions[alu->scalar_opc].name) {
269 printf("\t \t%s\t", scalar_instructions[alu->scalar_opc].name);
270 } else {
271 printf("\t \tOP(%u)\t", alu->scalar_opc);
272 }
273
274 print_dstreg(alu->scalar_dest, alu->scalar_write_mask, alu->export_data);
275 printf(" = ");
276 print_srcreg(alu->src3_reg, alu->src3_sel, alu->src3_swiz,
277 alu->src3_reg_negate, alu->src3_reg_abs);
278 // TODO ADD/MUL must have another src?!?
279 if (alu->scalar_clamp)
280 printf(" CLAMP");
281 if (alu->export_data)
282 print_export_comment(alu->scalar_dest, type);
283 printf("\n");
284 }
285
286 return 0;
287 }
288
289
290 /*
291 * FETCH instructions:
292 */
293
294 static void print_fetch_dst(uint32_t dst_reg, uint32_t dst_swiz)
295 {
296 int i;
297 printf("\tR%u.", dst_reg);
298 for (i = 0; i < 4; i++) {
299 printf("%c", chan_names[dst_swiz & 0x7]);
300 dst_swiz >>= 3;
301 }
302 }
303
304 static void print_fetch_vtx(instr_fetch_t *fetch)
305 {
306 instr_fetch_vtx_t *vtx = &fetch->vtx;
307
308 if (vtx->pred_select) {
309 /* seems to work similar to conditional execution in ARM instruction
310 * set, so let's use a similar syntax for now:
311 */
312 printf(vtx->pred_condition ? "EQ" : "NE");
313 }
314
315 print_fetch_dst(vtx->dst_reg, vtx->dst_swiz);
316 printf(" = R%u.", vtx->src_reg);
317 printf("%c", chan_names[vtx->src_swiz & 0x3]);
318
319 const char *fmt = rnn_enumname(rnn, "a2xx_sq_surfaceformat", vtx->format);
320 if (fmt) {
321 printf(" %s", fmt);
322 } else {
323 printf(" TYPE(0x%x)", vtx->format);
324 }
325 printf(" %s", vtx->format_comp_all ? "SIGNED" : "UNSIGNED");
326 if (!vtx->num_format_all)
327 printf(" NORMALIZED");
328 printf(" STRIDE(%u)", vtx->stride);
329 if (vtx->offset)
330 printf(" OFFSET(%u)", vtx->offset);
331 printf(" CONST(%u, %u)", vtx->const_index, vtx->const_index_sel);
332 if (0) {
333 // XXX
334 printf(" src_reg_am=%u", vtx->src_reg_am);
335 printf(" dst_reg_am=%u", vtx->dst_reg_am);
336 printf(" num_format_all=%u", vtx->num_format_all);
337 printf(" signed_rf_mode_all=%u", vtx->signed_rf_mode_all);
338 printf(" exp_adjust_all=%u", vtx->exp_adjust_all);
339 }
340 }
341
342 static void print_fetch_tex(instr_fetch_t *fetch)
343 {
344 static const char *filter[] = {
345 [TEX_FILTER_POINT] = "POINT",
346 [TEX_FILTER_LINEAR] = "LINEAR",
347 [TEX_FILTER_BASEMAP] = "BASEMAP",
348 };
349 static const char *aniso_filter[] = {
350 [ANISO_FILTER_DISABLED] = "DISABLED",
351 [ANISO_FILTER_MAX_1_1] = "MAX_1_1",
352 [ANISO_FILTER_MAX_2_1] = "MAX_2_1",
353 [ANISO_FILTER_MAX_4_1] = "MAX_4_1",
354 [ANISO_FILTER_MAX_8_1] = "MAX_8_1",
355 [ANISO_FILTER_MAX_16_1] = "MAX_16_1",
356 };
357 static const char *arbitrary_filter[] = {
358 [ARBITRARY_FILTER_2X4_SYM] = "2x4_SYM",
359 [ARBITRARY_FILTER_2X4_ASYM] = "2x4_ASYM",
360 [ARBITRARY_FILTER_4X2_SYM] = "4x2_SYM",
361 [ARBITRARY_FILTER_4X2_ASYM] = "4x2_ASYM",
362 [ARBITRARY_FILTER_4X4_SYM] = "4x4_SYM",
363 [ARBITRARY_FILTER_4X4_ASYM] = "4x4_ASYM",
364 };
365 static const char *sample_loc[] = {
366 [SAMPLE_CENTROID] = "CENTROID",
367 [SAMPLE_CENTER] = "CENTER",
368 };
369 instr_fetch_tex_t *tex = &fetch->tex;
370 uint32_t src_swiz = tex->src_swiz;
371 int i;
372
373 if (tex->pred_select) {
374 /* seems to work similar to conditional execution in ARM instruction
375 * set, so let's use a similar syntax for now:
376 */
377 printf(tex->pred_condition ? "EQ" : "NE");
378 }
379
380 print_fetch_dst(tex->dst_reg, tex->dst_swiz);
381 printf(" = R%u.", tex->src_reg);
382 for (i = 0; i < 3; i++) {
383 printf("%c", chan_names[src_swiz & 0x3]);
384 src_swiz >>= 2;
385 }
386 printf(" CONST(%u)", tex->const_idx);
387 if (tex->fetch_valid_only)
388 printf(" VALID_ONLY");
389 if (tex->tx_coord_denorm)
390 printf(" DENORM");
391 if (tex->mag_filter != TEX_FILTER_USE_FETCH_CONST)
392 printf(" MAG(%s)", filter[tex->mag_filter]);
393 if (tex->min_filter != TEX_FILTER_USE_FETCH_CONST)
394 printf(" MIN(%s)", filter[tex->min_filter]);
395 if (tex->mip_filter != TEX_FILTER_USE_FETCH_CONST)
396 printf(" MIP(%s)", filter[tex->mip_filter]);
397 if (tex->aniso_filter != ANISO_FILTER_USE_FETCH_CONST)
398 printf(" ANISO(%s)", aniso_filter[tex->aniso_filter]);
399 if (tex->arbitrary_filter != ARBITRARY_FILTER_USE_FETCH_CONST)
400 printf(" ARBITRARY(%s)", arbitrary_filter[tex->arbitrary_filter]);
401 if (tex->vol_mag_filter != TEX_FILTER_USE_FETCH_CONST)
402 printf(" VOL_MAG(%s)", filter[tex->vol_mag_filter]);
403 if (tex->vol_min_filter != TEX_FILTER_USE_FETCH_CONST)
404 printf(" VOL_MIN(%s)", filter[tex->vol_min_filter]);
405 if (!tex->use_comp_lod) {
406 printf(" LOD(%u)", tex->use_comp_lod);
407 printf(" LOD_BIAS(%u)", tex->lod_bias);
408 }
409 if (tex->use_reg_lod) {
410 printf(" REG_LOD(%u)", tex->use_reg_lod);
411 }
412 if (tex->use_reg_gradients)
413 printf(" USE_REG_GRADIENTS");
414 printf(" LOCATION(%s)", sample_loc[tex->sample_location]);
415 if (tex->offset_x || tex->offset_y || tex->offset_z)
416 printf(" OFFSET(%u,%u,%u)", tex->offset_x, tex->offset_y, tex->offset_z);
417 }
418
419 struct {
420 const char *name;
421 void (*fxn)(instr_fetch_t *cf);
422 } fetch_instructions[] = {
423 #define INSTR(opc, name, fxn) [opc] = { name, fxn }
424 INSTR(VTX_FETCH, "VERTEX", print_fetch_vtx),
425 INSTR(TEX_FETCH, "SAMPLE", print_fetch_tex),
426 INSTR(TEX_GET_BORDER_COLOR_FRAC, "?", print_fetch_tex),
427 INSTR(TEX_GET_COMP_TEX_LOD, "?", print_fetch_tex),
428 INSTR(TEX_GET_GRADIENTS, "?", print_fetch_tex),
429 INSTR(TEX_GET_WEIGHTS, "?", print_fetch_tex),
430 INSTR(TEX_SET_TEX_LOD, "SET_TEX_LOD", print_fetch_tex),
431 INSTR(TEX_SET_GRADIENTS_H, "?", print_fetch_tex),
432 INSTR(TEX_SET_GRADIENTS_V, "?", print_fetch_tex),
433 INSTR(TEX_RESERVED_4, "?", print_fetch_tex),
434 #undef INSTR
435 };
436
437 static int disasm_fetch(uint32_t *dwords, uint32_t alu_off, int level, int sync)
438 {
439 instr_fetch_t *fetch = (instr_fetch_t *)dwords;
440
441 printf("%s", levels[level]);
442 if (debug & PRINT_RAW) {
443 printf("%02x: %08x %08x %08x\t", alu_off,
444 dwords[0], dwords[1], dwords[2]);
445 }
446
447 printf(" %sFETCH:\t", sync ? "(S)" : " ");
448 printf("%s", fetch_instructions[fetch->opc].name);
449 fetch_instructions[fetch->opc].fxn(fetch);
450 printf("\n");
451
452 return 0;
453 }
454
455 /*
456 * CF instructions:
457 */
458
459 static int cf_exec(instr_cf_t *cf)
460 {
461 return (cf->opc == EXEC) ||
462 (cf->opc == EXEC_END) ||
463 (cf->opc == COND_EXEC) ||
464 (cf->opc == COND_EXEC_END) ||
465 (cf->opc == COND_PRED_EXEC) ||
466 (cf->opc == COND_PRED_EXEC_END) ||
467 (cf->opc == COND_EXEC_PRED_CLEAN) ||
468 (cf->opc == COND_EXEC_PRED_CLEAN_END);
469 }
470
471 static int cf_cond_exec(instr_cf_t *cf)
472 {
473 return (cf->opc == COND_EXEC) ||
474 (cf->opc == COND_EXEC_END) ||
475 (cf->opc == COND_PRED_EXEC) ||
476 (cf->opc == COND_PRED_EXEC_END) ||
477 (cf->opc == COND_EXEC_PRED_CLEAN) ||
478 (cf->opc == COND_EXEC_PRED_CLEAN_END);
479 }
480
481 static void print_cf_nop(instr_cf_t *cf)
482 {
483 }
484
485 static void print_cf_exec(instr_cf_t *cf)
486 {
487 printf(" ADDR(0x%x) CNT(0x%x)", cf->exec.address, cf->exec.count);
488 if (cf->exec.yeild)
489 printf(" YIELD");
490 if (cf->exec.vc)
491 printf(" VC(0x%x)", cf->exec.vc);
492 if (cf->exec.bool_addr)
493 printf(" BOOL_ADDR(0x%x)", cf->exec.bool_addr);
494 if (cf->exec.address_mode == ABSOLUTE_ADDR)
495 printf(" ABSOLUTE_ADDR");
496 if (cf_cond_exec(cf))
497 printf(" COND(%d)", cf->exec.condition);
498 }
499
500 static void print_cf_loop(instr_cf_t *cf)
501 {
502 printf(" ADDR(0x%x) LOOP_ID(%d)", cf->loop.address, cf->loop.loop_id);
503 if (cf->loop.address_mode == ABSOLUTE_ADDR)
504 printf(" ABSOLUTE_ADDR");
505 }
506
507 static void print_cf_jmp_call(instr_cf_t *cf)
508 {
509 printf(" ADDR(0x%x) DIR(%d)", cf->jmp_call.address, cf->jmp_call.direction);
510 if (cf->jmp_call.force_call)
511 printf(" FORCE_CALL");
512 if (cf->jmp_call.predicated_jmp)
513 printf(" COND(%d)", cf->jmp_call.condition);
514 if (cf->jmp_call.bool_addr)
515 printf(" BOOL_ADDR(0x%x)", cf->jmp_call.bool_addr);
516 if (cf->jmp_call.address_mode == ABSOLUTE_ADDR)
517 printf(" ABSOLUTE_ADDR");
518 }
519
520 static void print_cf_alloc(instr_cf_t *cf)
521 {
522 static const char *bufname[] = {
523 [SQ_NO_ALLOC] = "NO ALLOC",
524 [SQ_POSITION] = "POSITION",
525 [SQ_PARAMETER_PIXEL] = "PARAM/PIXEL",
526 [SQ_MEMORY] = "MEMORY",
527 };
528 printf(" %s SIZE(0x%x)", bufname[cf->alloc.buffer_select], cf->alloc.size);
529 if (cf->alloc.no_serial)
530 printf(" NO_SERIAL");
531 if (cf->alloc.alloc_mode) // ???
532 printf(" ALLOC_MODE");
533 }
534
535 struct {
536 const char *name;
537 void (*fxn)(instr_cf_t *cf);
538 } cf_instructions[] = {
539 #define INSTR(opc, fxn) [opc] = { #opc, fxn }
540 INSTR(NOP, print_cf_nop),
541 INSTR(EXEC, print_cf_exec),
542 INSTR(EXEC_END, print_cf_exec),
543 INSTR(COND_EXEC, print_cf_exec),
544 INSTR(COND_EXEC_END, print_cf_exec),
545 INSTR(COND_PRED_EXEC, print_cf_exec),
546 INSTR(COND_PRED_EXEC_END, print_cf_exec),
547 INSTR(LOOP_START, print_cf_loop),
548 INSTR(LOOP_END, print_cf_loop),
549 INSTR(COND_CALL, print_cf_jmp_call),
550 INSTR(RETURN, print_cf_jmp_call),
551 INSTR(COND_JMP, print_cf_jmp_call),
552 INSTR(ALLOC, print_cf_alloc),
553 INSTR(COND_EXEC_PRED_CLEAN, print_cf_exec),
554 INSTR(COND_EXEC_PRED_CLEAN_END, print_cf_exec),
555 INSTR(MARK_VS_FETCH_DONE, print_cf_nop), // ??
556 #undef INSTR
557 };
558
559 static void print_cf(instr_cf_t *cf, int level)
560 {
561 printf("%s", levels[level]);
562 if (debug & PRINT_RAW) {
563 uint16_t words[3];
564 memcpy(&words, cf, sizeof(words));
565 printf(" %04x %04x %04x \t",
566 words[0], words[1], words[2]);
567 }
568 printf("%s", cf_instructions[cf->opc].name);
569 cf_instructions[cf->opc].fxn(cf);
570 printf("\n");
571 }
572
573 /*
574 * The adreno shader microcode consists of two parts:
575 * 1) A CF (control-flow) program, at the header of the compiled shader,
576 * which refers to ALU/FETCH instructions that follow it by address.
577 * 2) ALU and FETCH instructions
578 */
579
580 int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, gl_shader_stage type)
581 {
582 instr_cf_t *cfs = (instr_cf_t *)dwords;
583 int idx, max_idx;
584
585 if (!rnn) {
586 rnn = rnn_new(1);
587 rnn_load(rnn, "a2xx");
588 }
589
590 for (idx = 0; ; idx++) {
591 instr_cf_t *cf = &cfs[idx];
592 if (cf_exec(cf)) {
593 max_idx = 2 * cf->exec.address;
594 break;
595 }
596 }
597
598 for (idx = 0; idx < max_idx; idx++) {
599 instr_cf_t *cf = &cfs[idx];
600
601 print_cf(cf, level);
602
603 if (cf_exec(cf)) {
604 uint32_t sequence = cf->exec.serialize;
605 uint32_t i;
606 for (i = 0; i < cf->exec.count; i++) {
607 uint32_t alu_off = (cf->exec.address + i);
608 if (sequence & 0x1) {
609 disasm_fetch(dwords + alu_off * 3, alu_off, level, sequence & 0x2);
610 } else {
611 disasm_alu(dwords + alu_off * 3, alu_off, level, sequence & 0x2, type);
612 }
613 sequence >>= 2;
614 }
615 }
616 }
617
618 return 0;
619 }
620
621 void disasm_set_debug(enum debug_t d)
622 {
623 debug = d;
624 }