2 * Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
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:
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
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
30 #include <util/u_debug.h>
33 #include "instr-a3xx.h"
35 static enum debug_t debug
;
37 #define printf debug_printf
39 static const char *levels
[] = {
58 static const char *component
= "xyzw";
60 static const char *type
[] = {
71 static void print_reg(reg_t reg
, bool full
, bool r
, bool c
, bool im
,
72 bool neg
, bool abs
, bool addr_rel
)
74 const char type
= c
? 'c' : 'r';
76 // XXX I prefer - and || for neg/abs, but preserving format used
77 // by libllvm-a3xx for easy diffing..
90 printf("%d", reg
.iim_val
);
91 } else if (addr_rel
) {
92 /* I would just use %+d but trying to make it diff'able with
96 printf("%s%c<a0.x - %d>", full
? "" : "h", type
, -reg
.iim_val
);
97 else if (reg
.iim_val
> 0)
98 printf("%s%c<a0.x + %d>", full
? "" : "h", type
, reg
.iim_val
);
100 printf("%s%c<a0.x>", full
? "" : "h", type
);
101 } else if ((reg
.num
== REG_A0
) && !c
) {
102 printf("a0.%c", component
[reg
.comp
]);
103 } else if ((reg
.num
== REG_P0
) && !c
) {
104 printf("p0.%c", component
[reg
.comp
]);
106 printf("%s%c%d.%c", full
? "" : "h", type
, reg
.num
, component
[reg
.comp
]);
111 /* current instruction repeat flag: */
112 static unsigned repeat
;
114 static void print_reg_dst(reg_t reg
, bool full
, bool addr_rel
)
116 print_reg(reg
, full
, false, false, false, false, false, addr_rel
);
119 static void print_reg_src(reg_t reg
, bool full
, bool r
, bool c
, bool im
,
120 bool neg
, bool abs
, bool addr_rel
)
122 print_reg(reg
, full
, r
, c
, im
, neg
, abs
, addr_rel
);
125 static void print_instr_cat0(instr_t
*instr
)
127 instr_cat0_t
*cat0
= &instr
->cat0
;
131 printf(" %sp0.%c", cat0
->inv
? "!" : "",
132 component
[cat0
->comp
]);
135 printf(" %sp0.%c, #%d", cat0
->inv
? "!" : "",
136 component
[cat0
->comp
], cat0
->immed
);
140 printf(" #%d", cat0
->immed
);
144 if ((debug
& PRINT_VERBOSE
) && (cat0
->dummy1
|cat0
->dummy2
|cat0
->dummy3
|cat0
->dummy4
))
145 printf("\t{0: %x,%x,%x,%x}", cat0
->dummy1
, cat0
->dummy2
, cat0
->dummy3
, cat0
->dummy4
);
148 static void print_instr_cat1(instr_t
*instr
)
150 instr_cat1_t
*cat1
= &instr
->cat1
;
155 if (cat1
->src_type
== cat1
->dst_type
) {
156 if ((cat1
->src_type
== TYPE_S16
) && (((reg_t
)cat1
->dst
).num
== REG_A0
)) {
157 /* special case (nmemonic?): */
160 printf("mov.%s%s", type
[cat1
->src_type
], type
[cat1
->dst_type
]);
163 printf("cov.%s%s", type
[cat1
->src_type
], type
[cat1
->dst_type
]);
172 printf("(pos_infinity)");
174 print_reg_dst((reg_t
)(cat1
->dst
), type_size(cat1
->dst_type
) == 32,
179 /* ugg, have to special case this.. vs print_reg().. */
181 if (type_float(cat1
->src_type
))
182 printf("(%f)", cat1
->fim_val
);
184 printf("%d", cat1
->iim_val
);
185 } else if (cat1
->src_rel
&& !cat1
->src_c
) {
186 /* I would just use %+d but trying to make it diff'able with
189 char type
= cat1
->src_rel_c
? 'c' : 'r';
191 printf("%c<a0.x - %d>", type
, -cat1
->off
);
192 else if (cat1
->off
> 0)
193 printf("%c<a0.x + %d>", type
, cat1
->off
);
197 print_reg_src((reg_t
)(cat1
->src
), type_size(cat1
->src_type
) == 32,
198 cat1
->src_r
, cat1
->src_c
, cat1
->src_im
, false, false, false);
201 if ((debug
& PRINT_VERBOSE
) && (cat1
->must_be_0
))
202 printf("\t{1: %x}", cat1
->must_be_0
);
205 static void print_instr_cat2(instr_t
*instr
)
207 instr_cat2_t
*cat2
= &instr
->cat2
;
208 static const char *cond
[] = {
225 printf(".%s", cond
[cat2
->cond
]);
232 print_reg_dst((reg_t
)(cat2
->dst
), cat2
->full
^ cat2
->dst_half
, false);
235 if (cat2
->c1
.src1_c
) {
236 print_reg_src((reg_t
)(cat2
->c1
.src1
), cat2
->full
, cat2
->src1_r
,
237 cat2
->c1
.src1_c
, cat2
->src1_im
, cat2
->src1_neg
,
238 cat2
->src1_abs
, false);
239 } else if (cat2
->rel1
.src1_rel
) {
240 print_reg_src((reg_t
)(cat2
->rel1
.src1
), cat2
->full
, cat2
->src1_r
,
241 cat2
->rel1
.src1_c
, cat2
->src1_im
, cat2
->src1_neg
,
242 cat2
->src1_abs
, cat2
->rel1
.src1_rel
);
244 print_reg_src((reg_t
)(cat2
->src1
), cat2
->full
, cat2
->src1_r
,
245 false, cat2
->src1_im
, cat2
->src1_neg
,
246 cat2
->src1_abs
, false);
264 /* these only have one src reg */
268 if (cat2
->c2
.src2_c
) {
269 print_reg_src((reg_t
)(cat2
->c2
.src2
), cat2
->full
, cat2
->src2_r
,
270 cat2
->c2
.src2_c
, cat2
->src2_im
, cat2
->src2_neg
,
271 cat2
->src2_abs
, false);
272 } else if (cat2
->rel2
.src2_rel
) {
273 print_reg_src((reg_t
)(cat2
->rel2
.src2
), cat2
->full
, cat2
->src2_r
,
274 cat2
->rel2
.src2_c
, cat2
->src2_im
, cat2
->src2_neg
,
275 cat2
->src2_abs
, cat2
->rel2
.src2_rel
);
277 print_reg_src((reg_t
)(cat2
->src2
), cat2
->full
, cat2
->src2_r
,
278 false, cat2
->src2_im
, cat2
->src2_neg
,
279 cat2
->src2_abs
, false);
285 static void print_instr_cat3(instr_t
*instr
)
287 instr_cat3_t
*cat3
= &instr
->cat3
;
288 bool full
= instr_cat3_full(cat3
);
291 print_reg_dst((reg_t
)(cat3
->dst
), full
^ cat3
->dst_half
, false);
293 if (cat3
->c1
.src1_c
) {
294 print_reg_src((reg_t
)(cat3
->c1
.src1
), full
,
295 cat3
->src1_r
, cat3
->c1
.src1_c
, false, cat3
->src1_neg
,
297 } else if (cat3
->rel1
.src1_rel
) {
298 print_reg_src((reg_t
)(cat3
->rel1
.src1
), full
,
299 cat3
->src1_r
, cat3
->rel1
.src1_c
, false, cat3
->src1_neg
,
300 false, cat3
->rel1
.src1_rel
);
302 print_reg_src((reg_t
)(cat3
->src1
), full
,
303 cat3
->src1_r
, false, false, cat3
->src1_neg
,
307 print_reg_src((reg_t
)cat3
->src2
, full
,
308 cat3
->src2_r
, cat3
->src2_c
, false, cat3
->src2_neg
,
311 if (cat3
->c2
.src3_c
) {
312 print_reg_src((reg_t
)(cat3
->c2
.src3
), full
,
313 cat3
->src3_r
, cat3
->c2
.src3_c
, false, cat3
->src3_neg
,
315 } else if (cat3
->rel2
.src3_rel
) {
316 print_reg_src((reg_t
)(cat3
->rel2
.src3
), full
,
317 cat3
->src3_r
, cat3
->rel2
.src3_c
, false, cat3
->src3_neg
,
318 false, cat3
->rel2
.src3_rel
);
320 print_reg_src((reg_t
)(cat3
->src3
), full
,
321 cat3
->src3_r
, false, false, cat3
->src3_neg
,
326 static void print_instr_cat4(instr_t
*instr
)
328 instr_cat4_t
*cat4
= &instr
->cat4
;
331 print_reg_dst((reg_t
)(cat4
->dst
), cat4
->full
^ cat4
->dst_half
, false);
335 print_reg_src((reg_t
)(cat4
->c
.src
), cat4
->full
,
336 cat4
->src_r
, cat4
->c
.src_c
, cat4
->src_im
,
337 cat4
->src_neg
, cat4
->src_abs
, false);
338 } else if (cat4
->rel
.src_rel
) {
339 print_reg_src((reg_t
)(cat4
->rel
.src
), cat4
->full
,
340 cat4
->src_r
, cat4
->rel
.src_c
, cat4
->src_im
,
341 cat4
->src_neg
, cat4
->src_abs
, cat4
->rel
.src_rel
);
343 print_reg_src((reg_t
)(cat4
->src
), cat4
->full
,
344 cat4
->src_r
, false, cat4
->src_im
,
345 cat4
->src_neg
, cat4
->src_abs
, false);
348 if ((debug
& PRINT_VERBOSE
) && (cat4
->dummy1
|cat4
->dummy2
))
349 printf("\t{4: %x,%x}", cat4
->dummy1
, cat4
->dummy2
);
352 static void print_instr_cat5(instr_t
*instr
)
354 static const struct {
355 bool src1
, src2
, samp
, tex
;
357 [OPC_ISAM
] = { true, false, true, true, },
358 [OPC_ISAML
] = { true, true, true, true, },
359 [OPC_ISAMM
] = { true, false, true, true, },
360 [OPC_SAM
] = { true, false, true, true, },
361 [OPC_SAMB
] = { true, true, true, true, },
362 [OPC_SAML
] = { true, true, true, true, },
363 [OPC_SAMGQ
] = { true, false, true, true, },
364 [OPC_GETLOD
] = { true, false, true, true, },
365 [OPC_CONV
] = { true, true, true, true, },
366 [OPC_CONVM
] = { true, true, true, true, },
367 [OPC_GETSIZE
] = { true, false, false, true, },
368 [OPC_GETBUF
] = { false, false, false, true, },
369 [OPC_GETPOS
] = { true, false, false, true, },
370 [OPC_GETINFO
] = { false, false, false, true, },
371 [OPC_DSX
] = { true, false, false, false, },
372 [OPC_DSY
] = { true, false, false, false, },
373 [OPC_GATHER4R
] = { true, false, true, true, },
374 [OPC_GATHER4G
] = { true, false, true, true, },
375 [OPC_GATHER4B
] = { true, false, true, true, },
376 [OPC_GATHER4A
] = { true, false, true, true, },
377 [OPC_SAMGP0
] = { true, false, true, true, },
378 [OPC_SAMGP1
] = { true, false, true, true, },
379 [OPC_SAMGP2
] = { true, false, true, true, },
380 [OPC_SAMGP3
] = { true, false, true, true, },
381 [OPC_DSXPP_1
] = { true, false, false, false, },
382 [OPC_DSYPP_1
] = { true, false, false, false, },
383 [OPC_RGETPOS
] = { false, false, false, false, },
384 [OPC_RGETINFO
] = { false, false, false, false, },
386 instr_cat5_t
*cat5
= &instr
->cat5
;
389 if (cat5
->is_3d
) printf(".3d");
390 if (cat5
->is_a
) printf(".a");
391 if (cat5
->is_o
) printf(".o");
392 if (cat5
->is_p
) printf(".p");
393 if (cat5
->is_s
) printf(".s");
394 if (cat5
->is_s2en
) printf(".s2en");
403 printf("(%s)", type
[cat5
->type
]);
408 for (i
= 0; i
< 4; i
++)
409 if (cat5
->wrmask
& (1 << i
))
410 printf("%c", "xyzw"[i
]);
413 print_reg_dst((reg_t
)(cat5
->dst
), type_size(cat5
->type
) == 32, false);
415 if (info
[cat5
->opc
].src1
) {
417 print_reg_src((reg_t
)(cat5
->src1
), cat5
->full
, false, false, false,
418 false, false, false);
423 print_reg_src((reg_t
)(cat5
->s2en
.src2
), cat5
->full
, false, false, false,
424 false, false, false);
426 print_reg_src((reg_t
)(cat5
->s2en
.src3
), false, false, false, false,
427 false, false, false);
429 if (cat5
->is_o
|| info
[cat5
->opc
].src2
) {
431 print_reg_src((reg_t
)(cat5
->norm
.src2
), cat5
->full
,
432 false, false, false, false, false, false);
434 if (info
[cat5
->opc
].samp
)
435 printf(", s#%d", cat5
->norm
.samp
);
436 if (info
[cat5
->opc
].tex
)
437 printf(", t#%d", cat5
->norm
.tex
);
440 if (debug
& PRINT_VERBOSE
) {
442 if ((debug
& PRINT_VERBOSE
) && (cat5
->s2en
.dummy1
|cat5
->s2en
.dummy2
|cat5
->dummy2
))
443 printf("\t{5: %x,%x,%x}", cat5
->s2en
.dummy1
, cat5
->s2en
.dummy2
, cat5
->dummy2
);
445 if ((debug
& PRINT_VERBOSE
) && (cat5
->norm
.dummy1
|cat5
->dummy2
))
446 printf("\t{5: %x,%x}", cat5
->norm
.dummy1
, cat5
->dummy2
);
451 static int32_t u2i(uint32_t val
, int nbits
)
453 return ((val
>> (nbits
-1)) * ~((1 << nbits
) - 1)) | val
;
456 static void print_instr_cat6(instr_t
*instr
)
458 instr_cat6_t
*cat6
= &instr
->cat6
;
460 printf(".%s ", type
[cat6
->type
]);
468 /* load instructions: */
469 print_reg_dst((reg_t
)(cat6
->a
.dst
), type_size(cat6
->type
) == 32, false);
485 print_reg_src((reg_t
)(cat6
->a
.src
), true,
486 false, false, false, false, false, false);
488 printf("%+d", cat6
->a
.off
);
492 /* similar to load instructions: */
494 print_reg_src((reg_t
)(cat6
->a
.src
), true,
495 false, false, false, false, false, false);
497 printf("%+d", cat6
->a
.off
);
504 /* store instructions: */
518 print_reg_dst((reg_t
)(cat6
->b
.dst
), true, false);
519 if (cat6
->b
.off
|| cat6
->b
.off_hi
)
520 printf("%+d", u2i((cat6
->b
.off_hi
<< 8) | cat6
->b
.off
, 13));
523 print_reg_src((reg_t
)(cat6
->b
.src
), type_size(cat6
->type
) == 32,
524 false, false, false, false, false, false);
528 /* sti has same encoding as other store instructions, but
529 * slightly different syntax:
531 print_reg_dst((reg_t
)(cat6
->b
.dst
), false /* XXX is it always half? */, false);
532 if (cat6
->b
.off
|| cat6
->b
.off_hi
)
533 printf("%+d", u2i((cat6
->b
.off_hi
<< 8) | cat6
->b
.off
, 13));
535 print_reg_src((reg_t
)(cat6
->b
.src
), type_size(cat6
->type
) == 32,
536 false, false, false, false, false, false);
540 printf(", %d", cat6
->iim_val
);
542 if (debug
& PRINT_VERBOSE
) {
546 /* load instructions: */
547 if (cat6
->a
.dummy1
|cat6
->a
.dummy2
|cat6
->a
.dummy3
)
548 printf("\t{6: %x,%x,%x}", cat6
->a
.dummy1
, cat6
->a
.dummy2
, cat6
->a
.dummy3
);
549 if ((cat6
->a
.must_be_one1
!= 1) || (cat6
->a
.must_be_one2
!= 1))
550 printf("{?? %d,%d ??}", cat6
->a
.must_be_one1
, cat6
->a
.must_be_one2
);
555 /* store instructions: */
556 if (cat6
->b
.dummy1
|cat6
->b
.dummy2
)
557 printf("\t{6: %x,%x}", cat6
->b
.dummy1
, cat6
->b
.dummy2
);
558 if ((cat6
->b
.must_be_one1
!= 1) || (cat6
->b
.must_be_one2
!= 1) ||
559 (cat6
->b
.must_be_zero1
!= 0))
560 printf("{?? %d,%d,%d ??}", cat6
->b
.must_be_one1
, cat6
->b
.must_be_one2
,
561 cat6
->b
.must_be_zero1
);
567 /* size of largest OPC field of all the instruction categories: */
574 void (*print
)(instr_t
*instr
);
575 } opcs
[1 << (3+NOPC_BITS
)] = {
576 #define OPC(cat, opc, name) [((cat) << NOPC_BITS) | (opc)] = { (cat), (opc), #name, print_instr_cat##cat }
578 OPC(0, OPC_NOP
, nop
),
580 OPC(0, OPC_JUMP
, jump
),
581 OPC(0, OPC_CALL
, call
),
582 OPC(0, OPC_RET
, ret
),
583 OPC(0, OPC_KILL
, kill
),
584 OPC(0, OPC_END
, end
),
585 OPC(0, OPC_EMIT
, emit
),
586 OPC(0, OPC_CUT
, cut
),
587 OPC(0, OPC_CHMASK
, chmask
),
588 OPC(0, OPC_CHSH
, chsh
),
589 OPC(0, OPC_FLOW_REV
, flow_rev
),
595 OPC(2, OPC_ADD_F
, add
.f
),
596 OPC(2, OPC_MIN_F
, min
.f
),
597 OPC(2, OPC_MAX_F
, max
.f
),
598 OPC(2, OPC_MUL_F
, mul
.f
),
599 OPC(2, OPC_SIGN_F
, sign
.f
),
600 OPC(2, OPC_CMPS_F
, cmps
.f
),
601 OPC(2, OPC_ABSNEG_F
, absneg
.f
),
602 OPC(2, OPC_CMPV_F
, cmpv
.f
),
603 OPC(2, OPC_FLOOR_F
, floor
.f
),
604 OPC(2, OPC_CEIL_F
, ceil
.f
),
605 OPC(2, OPC_RNDNE_F
, rndne
.f
),
606 OPC(2, OPC_RNDAZ_F
, rndaz
.f
),
607 OPC(2, OPC_TRUNC_F
, trunc
.f
),
608 OPC(2, OPC_ADD_U
, add
.u
),
609 OPC(2, OPC_ADD_S
, add
.s
),
610 OPC(2, OPC_SUB_U
, sub
.u
),
611 OPC(2, OPC_SUB_S
, sub
.s
),
612 OPC(2, OPC_CMPS_U
, cmps
.u
),
613 OPC(2, OPC_CMPS_S
, cmps
.s
),
614 OPC(2, OPC_MIN_U
, min
.u
),
615 OPC(2, OPC_MIN_S
, min
.s
),
616 OPC(2, OPC_MAX_U
, max
.u
),
617 OPC(2, OPC_MAX_S
, max
.s
),
618 OPC(2, OPC_ABSNEG_S
, absneg
.s
),
619 OPC(2, OPC_AND_B
, and.b
),
620 OPC(2, OPC_OR_B
, or.b
),
621 OPC(2, OPC_NOT_B
, not.b
),
622 OPC(2, OPC_XOR_B
, xor.b
),
623 OPC(2, OPC_CMPV_U
, cmpv
.u
),
624 OPC(2, OPC_CMPV_S
, cmpv
.s
),
625 OPC(2, OPC_MUL_U
, mul
.u
),
626 OPC(2, OPC_MUL_S
, mul
.s
),
627 OPC(2, OPC_MULL_U
, mull
.u
),
628 OPC(2, OPC_BFREV_B
, bfrev
.b
),
629 OPC(2, OPC_CLZ_S
, clz
.s
),
630 OPC(2, OPC_CLZ_B
, clz
.b
),
631 OPC(2, OPC_SHL_B
, shl
.b
),
632 OPC(2, OPC_SHR_B
, shr
.b
),
633 OPC(2, OPC_ASHR_B
, ashr
.b
),
634 OPC(2, OPC_BARY_F
, bary
.f
),
635 OPC(2, OPC_MGEN_B
, mgen
.b
),
636 OPC(2, OPC_GETBIT_B
, getbit
.b
),
637 OPC(2, OPC_SETRM
, setrm
),
638 OPC(2, OPC_CBITS_B
, cbits
.b
),
639 OPC(2, OPC_SHB
, shb
),
640 OPC(2, OPC_MSAD
, msad
),
643 OPC(3, OPC_MAD_U16
, mad
.u16
),
644 OPC(3, OPC_MADSH_U16
, madsh
.u16
),
645 OPC(3, OPC_MAD_S16
, mad
.s16
),
646 OPC(3, OPC_MADSH_M16
, madsh
.m16
),
647 OPC(3, OPC_MAD_U24
, mad
.u24
),
648 OPC(3, OPC_MAD_S24
, mad
.s24
),
649 OPC(3, OPC_MAD_F16
, mad
.f16
),
650 OPC(3, OPC_MAD_F32
, mad
.f32
),
651 OPC(3, OPC_SEL_B16
, sel
.b16
),
652 OPC(3, OPC_SEL_B32
, sel
.b32
),
653 OPC(3, OPC_SEL_S16
, sel
.s16
),
654 OPC(3, OPC_SEL_S32
, sel
.s32
),
655 OPC(3, OPC_SEL_F16
, sel
.f16
),
656 OPC(3, OPC_SEL_F32
, sel
.f32
),
657 OPC(3, OPC_SAD_S16
, sad
.s16
),
658 OPC(3, OPC_SAD_S32
, sad
.s32
),
661 OPC(4, OPC_RCP
, rcp
),
662 OPC(4, OPC_RSQ
, rsq
),
663 OPC(4, OPC_LOG2
, log2
),
664 OPC(4, OPC_EXP2
, exp2
),
665 OPC(4, OPC_SIN
, sin
),
666 OPC(4, OPC_COS
, cos
),
667 OPC(4, OPC_SQRT
, sqrt
),
670 OPC(5, OPC_ISAM
, isam
),
671 OPC(5, OPC_ISAML
, isaml
),
672 OPC(5, OPC_ISAMM
, isamm
),
673 OPC(5, OPC_SAM
, sam
),
674 OPC(5, OPC_SAMB
, samb
),
675 OPC(5, OPC_SAML
, saml
),
676 OPC(5, OPC_SAMGQ
, samgq
),
677 OPC(5, OPC_GETLOD
, getlod
),
678 OPC(5, OPC_CONV
, conv
),
679 OPC(5, OPC_CONVM
, convm
),
680 OPC(5, OPC_GETSIZE
, getsize
),
681 OPC(5, OPC_GETBUF
, getbuf
),
682 OPC(5, OPC_GETPOS
, getpos
),
683 OPC(5, OPC_GETINFO
, getinfo
),
684 OPC(5, OPC_DSX
, dsx
),
685 OPC(5, OPC_DSY
, dsy
),
686 OPC(5, OPC_GATHER4R
, gather4r
),
687 OPC(5, OPC_GATHER4G
, gather4g
),
688 OPC(5, OPC_GATHER4B
, gather4b
),
689 OPC(5, OPC_GATHER4A
, gather4a
),
690 OPC(5, OPC_SAMGP0
, samgp0
),
691 OPC(5, OPC_SAMGP1
, samgp1
),
692 OPC(5, OPC_SAMGP2
, samgp2
),
693 OPC(5, OPC_SAMGP3
, samgp3
),
694 OPC(5, OPC_DSXPP_1
, dsxpp
.1),
695 OPC(5, OPC_DSYPP_1
, dsypp
.1),
696 OPC(5, OPC_RGETPOS
, rgetpos
),
697 OPC(5, OPC_RGETINFO
, rgetinfo
),
701 OPC(6, OPC_LDG
, ldg
),
702 OPC(6, OPC_LDL
, ldl
),
703 OPC(6, OPC_LDP
, ldp
),
704 OPC(6, OPC_STG
, stg
),
705 OPC(6, OPC_STL
, stl
),
706 OPC(6, OPC_STP
, stp
),
707 OPC(6, OPC_STI
, sti
),
708 OPC(6, OPC_G2L
, g2l
),
709 OPC(6, OPC_L2G
, l2g
),
710 OPC(6, OPC_PREFETCH
, prefetch
),
711 OPC(6, OPC_LDLW
, ldlw
),
712 OPC(6, OPC_STLW
, stlw
),
713 OPC(6, OPC_RESFMT
, resfmt
),
714 OPC(6, OPC_RESINFO
, resinf
),
715 OPC(6, OPC_ATOMIC_ADD_L
, atomic
.add
.l
),
716 OPC(6, OPC_ATOMIC_SUB_L
, atomic
.sub
.l
),
717 OPC(6, OPC_ATOMIC_XCHG_L
, atomic
.xchg
.l
),
718 OPC(6, OPC_ATOMIC_INC_L
, atomic
.inc
.l
),
719 OPC(6, OPC_ATOMIC_DEC_L
, atomic
.dec
.l
),
720 OPC(6, OPC_ATOMIC_CMPXCHG_L
, atomic
.cmpxchg
.l
),
721 OPC(6, OPC_ATOMIC_MIN_L
, atomic
.min
.l
),
722 OPC(6, OPC_ATOMIC_MAX_L
, atomic
.max
.l
),
723 OPC(6, OPC_ATOMIC_AND_L
, atomic
.and.l
),
724 OPC(6, OPC_ATOMIC_OR_L
, atomic
.or.l
),
725 OPC(6, OPC_ATOMIC_XOR_L
, atomic
.xor.l
),
726 OPC(6, OPC_LDGB_TYPED_4D
, ldgb
.typed
.4d
),
727 OPC(6, OPC_STGB_4D_4
, stgb
.4d
.4),
728 OPC(6, OPC_STIB
, stib
),
729 OPC(6, OPC_LDC_4
, ldc
.4),
730 OPC(6, OPC_LDLV
, ldlv
),
736 #define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr)]))
738 // XXX hack.. probably should move this table somewhere common:
740 const char *ir3_instr_name(struct ir3_instruction
*instr
)
742 if (instr
->category
== -1) return "??meta??";
743 return opcs
[(instr
->category
<< NOPC_BITS
) | instr
->opc
].name
;
746 static void print_instr(uint32_t *dwords
, int level
, int n
)
748 instr_t
*instr
= (instr_t
*)dwords
;
749 uint32_t opc
= instr_opc(instr
);
752 if (debug
& PRINT_VERBOSE
)
753 printf("%s%04d[%08xx_%08xx] ", levels
[level
], n
, dwords
[1], dwords
[0]);
755 /* NOTE: order flags are printed is a bit fugly.. but for now I
756 * try to match the order in llvm-a3xx disassembler for easy
762 if (instr
->ss
&& (instr
->opc_cat
<= 4))
766 if (instr
->repeat
&& (instr
->opc_cat
<= 4)) {
767 printf("(rpt%d)", instr
->repeat
);
768 repeat
= instr
->repeat
;
772 if (instr
->ul
&& ((2 <= instr
->opc_cat
) && (instr
->opc_cat
<= 4)))
775 name
= GETINFO(instr
)->name
;
779 GETINFO(instr
)->print(instr
);
781 printf("unknown(%d,%d)", instr
->opc_cat
, opc
);
787 int disasm_a3xx(uint32_t *dwords
, int sizedwords
, int level
, enum shader_t type
)
791 assert((sizedwords
% 2) == 0);
793 for (i
= 0; i
< sizedwords
; i
+= 2)
794 print_instr(&dwords
[i
], level
, i
/2);