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