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
& 0x3f, 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 /* TODO switch to using reginfo struct everywhere, since more readable
126 * than passing a bunch of bools to print_reg_src
140 static void print_src(struct reginfo
*info
)
142 print_reg_src(info
->reg
, info
->full
, info
->r
, info
->c
, info
->im
,
143 info
->neg
, info
->abs
, info
->addr_rel
);
146 //static void print_dst(struct reginfo *info)
148 // print_reg_dst(info->reg, info->full, info->addr_rel);
151 static void print_instr_cat0(instr_t
*instr
)
153 instr_cat0_t
*cat0
= &instr
->cat0
;
157 printf(" %sp0.%c", cat0
->inv
? "!" : "",
158 component
[cat0
->comp
]);
161 printf(" %sp0.%c, #%d", cat0
->inv
? "!" : "",
162 component
[cat0
->comp
], cat0
->a5xx
.immed
);
166 printf(" #%d", cat0
->a5xx
.immed
);
170 if ((debug
& PRINT_VERBOSE
) && (cat0
->dummy2
|cat0
->dummy3
|cat0
->dummy4
))
171 printf("\t{0: %x,%x,%x}", cat0
->dummy2
, cat0
->dummy3
, cat0
->dummy4
);
174 static void print_instr_cat1(instr_t
*instr
)
176 instr_cat1_t
*cat1
= &instr
->cat1
;
181 if (cat1
->src_type
== cat1
->dst_type
) {
182 if ((cat1
->src_type
== TYPE_S16
) && (((reg_t
)cat1
->dst
).num
== REG_A0
)) {
183 /* special case (nmemonic?): */
186 printf("mov.%s%s", type
[cat1
->src_type
], type
[cat1
->dst_type
]);
189 printf("cov.%s%s", type
[cat1
->src_type
], type
[cat1
->dst_type
]);
198 printf("(pos_infinity)");
200 print_reg_dst((reg_t
)(cat1
->dst
), type_size(cat1
->dst_type
) == 32,
205 /* ugg, have to special case this.. vs print_reg().. */
207 if (type_float(cat1
->src_type
))
208 printf("(%f)", cat1
->fim_val
);
209 else if (type_uint(cat1
->src_type
))
210 printf("0x%08x", cat1
->uim_val
);
212 printf("%d", cat1
->iim_val
);
213 } else if (cat1
->src_rel
&& !cat1
->src_c
) {
214 /* I would just use %+d but trying to make it diff'able with
217 char type
= cat1
->src_rel_c
? 'c' : 'r';
219 printf("%c<a0.x - %d>", type
, -cat1
->off
);
220 else if (cat1
->off
> 0)
221 printf("%c<a0.x + %d>", type
, cat1
->off
);
223 printf("%c<a0.x>", type
);
225 print_reg_src((reg_t
)(cat1
->src
), type_size(cat1
->src_type
) == 32,
226 cat1
->src_r
, cat1
->src_c
, cat1
->src_im
, false, false, false);
229 if ((debug
& PRINT_VERBOSE
) && (cat1
->must_be_0
))
230 printf("\t{1: %x}", cat1
->must_be_0
);
233 static void print_instr_cat2(instr_t
*instr
)
235 instr_cat2_t
*cat2
= &instr
->cat2
;
236 static const char *cond
[] = {
246 switch (_OPC(2, cat2
->opc
)) {
253 printf(".%s", cond
[cat2
->cond
]);
260 print_reg_dst((reg_t
)(cat2
->dst
), cat2
->full
^ cat2
->dst_half
, false);
263 if (cat2
->c1
.src1_c
) {
264 print_reg_src((reg_t
)(cat2
->c1
.src1
), cat2
->full
, cat2
->src1_r
,
265 cat2
->c1
.src1_c
, cat2
->src1_im
, cat2
->src1_neg
,
266 cat2
->src1_abs
, false);
267 } else if (cat2
->rel1
.src1_rel
) {
268 print_reg_src((reg_t
)(cat2
->rel1
.src1
), cat2
->full
, cat2
->src1_r
,
269 cat2
->rel1
.src1_c
, cat2
->src1_im
, cat2
->src1_neg
,
270 cat2
->src1_abs
, cat2
->rel1
.src1_rel
);
272 print_reg_src((reg_t
)(cat2
->src1
), cat2
->full
, cat2
->src1_r
,
273 false, cat2
->src1_im
, cat2
->src1_neg
,
274 cat2
->src1_abs
, false);
277 switch (_OPC(2, cat2
->opc
)) {
292 /* these only have one src reg */
296 if (cat2
->c2
.src2_c
) {
297 print_reg_src((reg_t
)(cat2
->c2
.src2
), cat2
->full
, cat2
->src2_r
,
298 cat2
->c2
.src2_c
, cat2
->src2_im
, cat2
->src2_neg
,
299 cat2
->src2_abs
, false);
300 } else if (cat2
->rel2
.src2_rel
) {
301 print_reg_src((reg_t
)(cat2
->rel2
.src2
), cat2
->full
, cat2
->src2_r
,
302 cat2
->rel2
.src2_c
, cat2
->src2_im
, cat2
->src2_neg
,
303 cat2
->src2_abs
, cat2
->rel2
.src2_rel
);
305 print_reg_src((reg_t
)(cat2
->src2
), cat2
->full
, cat2
->src2_r
,
306 false, cat2
->src2_im
, cat2
->src2_neg
,
307 cat2
->src2_abs
, false);
313 static void print_instr_cat3(instr_t
*instr
)
315 instr_cat3_t
*cat3
= &instr
->cat3
;
316 bool full
= instr_cat3_full(cat3
);
319 print_reg_dst((reg_t
)(cat3
->dst
), full
^ cat3
->dst_half
, false);
321 if (cat3
->c1
.src1_c
) {
322 print_reg_src((reg_t
)(cat3
->c1
.src1
), full
,
323 cat3
->src1_r
, cat3
->c1
.src1_c
, false, cat3
->src1_neg
,
325 } else if (cat3
->rel1
.src1_rel
) {
326 print_reg_src((reg_t
)(cat3
->rel1
.src1
), full
,
327 cat3
->src1_r
, cat3
->rel1
.src1_c
, false, cat3
->src1_neg
,
328 false, cat3
->rel1
.src1_rel
);
330 print_reg_src((reg_t
)(cat3
->src1
), full
,
331 cat3
->src1_r
, false, false, cat3
->src1_neg
,
335 print_reg_src((reg_t
)cat3
->src2
, full
,
336 cat3
->src2_r
, cat3
->src2_c
, false, cat3
->src2_neg
,
339 if (cat3
->c2
.src3_c
) {
340 print_reg_src((reg_t
)(cat3
->c2
.src3
), full
,
341 cat3
->src3_r
, cat3
->c2
.src3_c
, false, cat3
->src3_neg
,
343 } else if (cat3
->rel2
.src3_rel
) {
344 print_reg_src((reg_t
)(cat3
->rel2
.src3
), full
,
345 cat3
->src3_r
, cat3
->rel2
.src3_c
, false, cat3
->src3_neg
,
346 false, cat3
->rel2
.src3_rel
);
348 print_reg_src((reg_t
)(cat3
->src3
), full
,
349 cat3
->src3_r
, false, false, cat3
->src3_neg
,
354 static void print_instr_cat4(instr_t
*instr
)
356 instr_cat4_t
*cat4
= &instr
->cat4
;
359 print_reg_dst((reg_t
)(cat4
->dst
), cat4
->full
^ cat4
->dst_half
, false);
363 print_reg_src((reg_t
)(cat4
->c
.src
), cat4
->full
,
364 cat4
->src_r
, cat4
->c
.src_c
, cat4
->src_im
,
365 cat4
->src_neg
, cat4
->src_abs
, false);
366 } else if (cat4
->rel
.src_rel
) {
367 print_reg_src((reg_t
)(cat4
->rel
.src
), cat4
->full
,
368 cat4
->src_r
, cat4
->rel
.src_c
, cat4
->src_im
,
369 cat4
->src_neg
, cat4
->src_abs
, cat4
->rel
.src_rel
);
371 print_reg_src((reg_t
)(cat4
->src
), cat4
->full
,
372 cat4
->src_r
, false, cat4
->src_im
,
373 cat4
->src_neg
, cat4
->src_abs
, false);
376 if ((debug
& PRINT_VERBOSE
) && (cat4
->dummy1
|cat4
->dummy2
))
377 printf("\t{4: %x,%x}", cat4
->dummy1
, cat4
->dummy2
);
380 static void print_instr_cat5(instr_t
*instr
)
382 static const struct {
383 bool src1
, src2
, samp
, tex
;
385 [opc_op(OPC_ISAM
)] = { true, false, true, true, },
386 [opc_op(OPC_ISAML
)] = { true, true, true, true, },
387 [opc_op(OPC_ISAMM
)] = { true, false, true, true, },
388 [opc_op(OPC_SAM
)] = { true, false, true, true, },
389 [opc_op(OPC_SAMB
)] = { true, true, true, true, },
390 [opc_op(OPC_SAML
)] = { true, true, true, true, },
391 [opc_op(OPC_SAMGQ
)] = { true, false, true, true, },
392 [opc_op(OPC_GETLOD
)] = { true, false, true, true, },
393 [opc_op(OPC_CONV
)] = { true, true, true, true, },
394 [opc_op(OPC_CONVM
)] = { true, true, true, true, },
395 [opc_op(OPC_GETSIZE
)] = { true, false, false, true, },
396 [opc_op(OPC_GETBUF
)] = { false, false, false, true, },
397 [opc_op(OPC_GETPOS
)] = { true, false, false, true, },
398 [opc_op(OPC_GETINFO
)] = { false, false, false, true, },
399 [opc_op(OPC_DSX
)] = { true, false, false, false, },
400 [opc_op(OPC_DSY
)] = { true, false, false, false, },
401 [opc_op(OPC_GATHER4R
)] = { true, false, true, true, },
402 [opc_op(OPC_GATHER4G
)] = { true, false, true, true, },
403 [opc_op(OPC_GATHER4B
)] = { true, false, true, true, },
404 [opc_op(OPC_GATHER4A
)] = { true, false, true, true, },
405 [opc_op(OPC_SAMGP0
)] = { true, false, true, true, },
406 [opc_op(OPC_SAMGP1
)] = { true, false, true, true, },
407 [opc_op(OPC_SAMGP2
)] = { true, false, true, true, },
408 [opc_op(OPC_SAMGP3
)] = { true, false, true, true, },
409 [opc_op(OPC_DSXPP_1
)] = { true, false, false, false, },
410 [opc_op(OPC_DSYPP_1
)] = { true, false, false, false, },
411 [opc_op(OPC_RGETPOS
)] = { false, false, false, false, },
412 [opc_op(OPC_RGETINFO
)] = { false, false, false, false, },
414 instr_cat5_t
*cat5
= &instr
->cat5
;
417 if (cat5
->is_3d
) printf(".3d");
418 if (cat5
->is_a
) printf(".a");
419 if (cat5
->is_o
) printf(".o");
420 if (cat5
->is_p
) printf(".p");
421 if (cat5
->is_s
) printf(".s");
422 if (cat5
->is_s2en
) printf(".s2en");
426 switch (_OPC(5, cat5
->opc
)) {
431 printf("(%s)", type
[cat5
->type
]);
436 for (i
= 0; i
< 4; i
++)
437 if (cat5
->wrmask
& (1 << i
))
438 printf("%c", "xyzw"[i
]);
441 print_reg_dst((reg_t
)(cat5
->dst
), type_size(cat5
->type
) == 32, false);
443 if (info
[cat5
->opc
].src1
) {
445 print_reg_src((reg_t
)(cat5
->src1
), cat5
->full
, false, false, false,
446 false, false, false);
451 print_reg_src((reg_t
)(cat5
->s2en
.src2
), cat5
->full
, false, false, false,
452 false, false, false);
454 print_reg_src((reg_t
)(cat5
->s2en
.src3
), false, false, false, false,
455 false, false, false);
457 if (cat5
->is_o
|| info
[cat5
->opc
].src2
) {
459 print_reg_src((reg_t
)(cat5
->norm
.src2
), cat5
->full
,
460 false, false, false, false, false, false);
462 if (info
[cat5
->opc
].samp
)
463 printf(", s#%d", cat5
->norm
.samp
);
464 if (info
[cat5
->opc
].tex
)
465 printf(", t#%d", cat5
->norm
.tex
);
468 if (debug
& PRINT_VERBOSE
) {
470 if ((debug
& PRINT_VERBOSE
) && (cat5
->s2en
.dummy1
|cat5
->s2en
.dummy2
|cat5
->dummy2
))
471 printf("\t{5: %x,%x,%x}", cat5
->s2en
.dummy1
, cat5
->s2en
.dummy2
, cat5
->dummy2
);
473 if ((debug
& PRINT_VERBOSE
) && (cat5
->norm
.dummy1
|cat5
->dummy2
))
474 printf("\t{5: %x,%x}", cat5
->norm
.dummy1
, cat5
->dummy2
);
479 static void print_instr_cat6(instr_t
*instr
)
481 instr_cat6_t
*cat6
= &instr
->cat6
;
482 char sd
= 0, ss
= 0; /* dst/src address space */
484 struct reginfo dst
, src1
, src2
;
485 int src1off
= 0, dstoff
= 0;
487 memset(&dst
, 0, sizeof(dst
));
488 memset(&src1
, 0, sizeof(src1
));
489 memset(&src2
, 0, sizeof(src2
));
491 switch (_OPC(6, cat6
->opc
)) {
494 dst
.full
= type_size(cat6
->type
) == 32;
495 src1
.full
= type_size(cat6
->type
) == 32;
496 src2
.full
= type_size(cat6
->type
) == 32;
511 src1
.full
= type_size(cat6
->type
) == 32;
512 src2
.full
= type_size(cat6
->type
) == 32;
515 dst
.full
= type_size(cat6
->type
) == 32;
521 switch (_OPC(6, cat6
->opc
)) {
526 printf(".%s", cat6
->ldgb
.typed
? "typed" : "untyped");
527 printf(".%dd", cat6
->ldgb
.d
+ 1);
528 printf(".%s", type
[cat6
->type
]);
529 printf(".%d", cat6
->ldgb
.type_size
+ 1);
532 printf(".%s", cat6
->stgb
.typed
? "typed" : "untyped");
533 printf(".%dd", cat6
->stgb
.d
+ 1);
534 printf(".%s", type
[cat6
->type
]);
535 printf(".%d", cat6
->stgb
.type_size
+ 1);
539 case OPC_ATOMIC_XCHG
:
542 case OPC_ATOMIC_CMPXCHG
:
548 ss
= cat6
->g
? 'g' : 'l';
550 printf(".%s", type
[cat6
->type
]);
553 dst
.im
= cat6
->g
&& !cat6
->dst_off
;
554 printf(".%s", type
[cat6
->type
]);
559 switch (_OPC(6, cat6
->opc
)) {
600 dst
.full
= false; // XXX or inverts??
604 if (_OPC(6, cat6
->opc
) == OPC_STGB
) {
607 memset(&src3
, 0, sizeof(src3
));
609 src1
.reg
= (reg_t
)(cat6
->stgb
.src1
);
610 src2
.reg
= (reg_t
)(cat6
->stgb
.src2
);
611 src2
.im
= cat6
->stgb
.src2_im
;
612 src3
.reg
= (reg_t
)(cat6
->stgb
.src3
);
613 src3
.im
= cat6
->stgb
.src3_im
;
616 printf("g[%u], ", cat6
->stgb
.dst_ssbo
);
623 if (debug
& PRINT_VERBOSE
)
624 printf(" (pad0=%x, pad3=%x)", cat6
->stgb
.pad0
, cat6
->stgb
.pad3
);
629 if ((_OPC(6, cat6
->opc
) == OPC_LDGB
) || is_atomic(_OPC(6, cat6
->opc
))) {
631 src1
.reg
= (reg_t
)(cat6
->ldgb
.src1
);
632 src1
.im
= cat6
->ldgb
.src1_im
;
633 src2
.reg
= (reg_t
)(cat6
->ldgb
.src2
);
634 src2
.im
= cat6
->ldgb
.src2_im
;
635 dst
.reg
= (reg_t
)(cat6
->ldgb
.dst
);
639 printf("g[%u], ", cat6
->ldgb
.src_ssbo
);
644 if (is_atomic(_OPC(6, cat6
->opc
))) {
646 memset(&src3
, 0, sizeof(src3
));
647 src3
.reg
= (reg_t
)(cat6
->ldgb
.src3
);
654 if (debug
& PRINT_VERBOSE
)
655 printf(" (pad0=%x, pad3=%x, mustbe0=%x)", cat6
->ldgb
.pad0
, cat6
->ldgb
.pad3
, cat6
->ldgb
.mustbe0
);
660 dst
.reg
= (reg_t
)(cat6
->c
.dst
);
661 dstoff
= cat6
->c
.off
;
663 dst
.reg
= (reg_t
)(cat6
->d
.dst
);
667 src1
.reg
= (reg_t
)(cat6
->a
.src1
);
668 src1
.im
= cat6
->a
.src1_im
;
669 src2
.reg
= (reg_t
)(cat6
->a
.src2
);
670 src2
.im
= cat6
->a
.src2_im
;
671 src1off
= cat6
->a
.off
;
673 src1
.reg
= (reg_t
)(cat6
->b
.src1
);
674 src1
.im
= cat6
->b
.src1_im
;
675 src2
.reg
= (reg_t
)(cat6
->b
.src2
);
676 src2
.im
= cat6
->b
.src2_im
;
682 /* note: dst might actually be a src (ie. address to store to) */
685 printf("%+d", dstoff
);
694 /* can have a larger than normal immed, so hack: */
696 printf("%u", src1
.reg
.dummy13
);
702 printf("%+d", src1off
);
706 switch (_OPC(6, cat6
->opc
)) {
717 /* size of largest OPC field of all the instruction categories: */
720 static const struct opc_info
{
724 void (*print
)(instr_t
*instr
);
725 } opcs
[1 << (3+NOPC_BITS
)] = {
726 #define OPC(cat, opc, name) [(opc)] = { (cat), (opc), #name, print_instr_cat##cat }
728 OPC(0, OPC_NOP
, nop
),
730 OPC(0, OPC_JUMP
, jump
),
731 OPC(0, OPC_CALL
, call
),
732 OPC(0, OPC_RET
, ret
),
733 OPC(0, OPC_KILL
, kill
),
734 OPC(0, OPC_END
, end
),
735 OPC(0, OPC_EMIT
, emit
),
736 OPC(0, OPC_CUT
, cut
),
737 OPC(0, OPC_CHMASK
, chmask
),
738 OPC(0, OPC_CHSH
, chsh
),
739 OPC(0, OPC_FLOW_REV
, flow_rev
),
745 OPC(2, OPC_ADD_F
, add
.f
),
746 OPC(2, OPC_MIN_F
, min
.f
),
747 OPC(2, OPC_MAX_F
, max
.f
),
748 OPC(2, OPC_MUL_F
, mul
.f
),
749 OPC(2, OPC_SIGN_F
, sign
.f
),
750 OPC(2, OPC_CMPS_F
, cmps
.f
),
751 OPC(2, OPC_ABSNEG_F
, absneg
.f
),
752 OPC(2, OPC_CMPV_F
, cmpv
.f
),
753 OPC(2, OPC_FLOOR_F
, floor
.f
),
754 OPC(2, OPC_CEIL_F
, ceil
.f
),
755 OPC(2, OPC_RNDNE_F
, rndne
.f
),
756 OPC(2, OPC_RNDAZ_F
, rndaz
.f
),
757 OPC(2, OPC_TRUNC_F
, trunc
.f
),
758 OPC(2, OPC_ADD_U
, add
.u
),
759 OPC(2, OPC_ADD_S
, add
.s
),
760 OPC(2, OPC_SUB_U
, sub
.u
),
761 OPC(2, OPC_SUB_S
, sub
.s
),
762 OPC(2, OPC_CMPS_U
, cmps
.u
),
763 OPC(2, OPC_CMPS_S
, cmps
.s
),
764 OPC(2, OPC_MIN_U
, min
.u
),
765 OPC(2, OPC_MIN_S
, min
.s
),
766 OPC(2, OPC_MAX_U
, max
.u
),
767 OPC(2, OPC_MAX_S
, max
.s
),
768 OPC(2, OPC_ABSNEG_S
, absneg
.s
),
769 OPC(2, OPC_AND_B
, and.b
),
770 OPC(2, OPC_OR_B
, or.b
),
771 OPC(2, OPC_NOT_B
, not.b
),
772 OPC(2, OPC_XOR_B
, xor.b
),
773 OPC(2, OPC_CMPV_U
, cmpv
.u
),
774 OPC(2, OPC_CMPV_S
, cmpv
.s
),
775 OPC(2, OPC_MUL_U
, mul
.u
),
776 OPC(2, OPC_MUL_S
, mul
.s
),
777 OPC(2, OPC_MULL_U
, mull
.u
),
778 OPC(2, OPC_BFREV_B
, bfrev
.b
),
779 OPC(2, OPC_CLZ_S
, clz
.s
),
780 OPC(2, OPC_CLZ_B
, clz
.b
),
781 OPC(2, OPC_SHL_B
, shl
.b
),
782 OPC(2, OPC_SHR_B
, shr
.b
),
783 OPC(2, OPC_ASHR_B
, ashr
.b
),
784 OPC(2, OPC_BARY_F
, bary
.f
),
785 OPC(2, OPC_MGEN_B
, mgen
.b
),
786 OPC(2, OPC_GETBIT_B
, getbit
.b
),
787 OPC(2, OPC_SETRM
, setrm
),
788 OPC(2, OPC_CBITS_B
, cbits
.b
),
789 OPC(2, OPC_SHB
, shb
),
790 OPC(2, OPC_MSAD
, msad
),
793 OPC(3, OPC_MAD_U16
, mad
.u16
),
794 OPC(3, OPC_MADSH_U16
, madsh
.u16
),
795 OPC(3, OPC_MAD_S16
, mad
.s16
),
796 OPC(3, OPC_MADSH_M16
, madsh
.m16
),
797 OPC(3, OPC_MAD_U24
, mad
.u24
),
798 OPC(3, OPC_MAD_S24
, mad
.s24
),
799 OPC(3, OPC_MAD_F16
, mad
.f16
),
800 OPC(3, OPC_MAD_F32
, mad
.f32
),
801 OPC(3, OPC_SEL_B16
, sel
.b16
),
802 OPC(3, OPC_SEL_B32
, sel
.b32
),
803 OPC(3, OPC_SEL_S16
, sel
.s16
),
804 OPC(3, OPC_SEL_S32
, sel
.s32
),
805 OPC(3, OPC_SEL_F16
, sel
.f16
),
806 OPC(3, OPC_SEL_F32
, sel
.f32
),
807 OPC(3, OPC_SAD_S16
, sad
.s16
),
808 OPC(3, OPC_SAD_S32
, sad
.s32
),
811 OPC(4, OPC_RCP
, rcp
),
812 OPC(4, OPC_RSQ
, rsq
),
813 OPC(4, OPC_LOG2
, log2
),
814 OPC(4, OPC_EXP2
, exp2
),
815 OPC(4, OPC_SIN
, sin
),
816 OPC(4, OPC_COS
, cos
),
817 OPC(4, OPC_SQRT
, sqrt
),
820 OPC(5, OPC_ISAM
, isam
),
821 OPC(5, OPC_ISAML
, isaml
),
822 OPC(5, OPC_ISAMM
, isamm
),
823 OPC(5, OPC_SAM
, sam
),
824 OPC(5, OPC_SAMB
, samb
),
825 OPC(5, OPC_SAML
, saml
),
826 OPC(5, OPC_SAMGQ
, samgq
),
827 OPC(5, OPC_GETLOD
, getlod
),
828 OPC(5, OPC_CONV
, conv
),
829 OPC(5, OPC_CONVM
, convm
),
830 OPC(5, OPC_GETSIZE
, getsize
),
831 OPC(5, OPC_GETBUF
, getbuf
),
832 OPC(5, OPC_GETPOS
, getpos
),
833 OPC(5, OPC_GETINFO
, getinfo
),
834 OPC(5, OPC_DSX
, dsx
),
835 OPC(5, OPC_DSY
, dsy
),
836 OPC(5, OPC_GATHER4R
, gather4r
),
837 OPC(5, OPC_GATHER4G
, gather4g
),
838 OPC(5, OPC_GATHER4B
, gather4b
),
839 OPC(5, OPC_GATHER4A
, gather4a
),
840 OPC(5, OPC_SAMGP0
, samgp0
),
841 OPC(5, OPC_SAMGP1
, samgp1
),
842 OPC(5, OPC_SAMGP2
, samgp2
),
843 OPC(5, OPC_SAMGP3
, samgp3
),
844 OPC(5, OPC_DSXPP_1
, dsxpp
.1),
845 OPC(5, OPC_DSYPP_1
, dsypp
.1),
846 OPC(5, OPC_RGETPOS
, rgetpos
),
847 OPC(5, OPC_RGETINFO
, rgetinfo
),
851 OPC(6, OPC_LDG
, ldg
),
852 OPC(6, OPC_LDL
, ldl
),
853 OPC(6, OPC_LDP
, ldp
),
854 OPC(6, OPC_STG
, stg
),
855 OPC(6, OPC_STL
, stl
),
856 OPC(6, OPC_STP
, stp
),
857 OPC(6, OPC_STI
, sti
),
858 OPC(6, OPC_G2L
, g2l
),
859 OPC(6, OPC_L2G
, l2g
),
860 OPC(6, OPC_PREFETCH
, prefetch
),
861 OPC(6, OPC_LDLW
, ldlw
),
862 OPC(6, OPC_STLW
, stlw
),
863 OPC(6, OPC_RESFMT
, resfmt
),
864 OPC(6, OPC_RESINFO
, resinfo
),
865 OPC(6, OPC_ATOMIC_ADD
, atomic
.add
),
866 OPC(6, OPC_ATOMIC_SUB
, atomic
.sub
),
867 OPC(6, OPC_ATOMIC_XCHG
, atomic
.xchg
),
868 OPC(6, OPC_ATOMIC_INC
, atomic
.inc
),
869 OPC(6, OPC_ATOMIC_DEC
, atomic
.dec
),
870 OPC(6, OPC_ATOMIC_CMPXCHG
, atomic
.cmpxchg
),
871 OPC(6, OPC_ATOMIC_MIN
, atomic
.min
),
872 OPC(6, OPC_ATOMIC_MAX
, atomic
.max
),
873 OPC(6, OPC_ATOMIC_AND
, atomic
.and),
874 OPC(6, OPC_ATOMIC_OR
, atomic
.or),
875 OPC(6, OPC_ATOMIC_XOR
, atomic
.xor),
876 OPC(6, OPC_LDGB
, ldgb
),
877 OPC(6, OPC_STGB
, stgb
),
878 OPC(6, OPC_STIB
, stib
),
879 OPC(6, OPC_LDC
, ldc
),
880 OPC(6, OPC_LDLV
, ldlv
),
886 #define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr)]))
888 // XXX hack.. probably should move this table somewhere common:
890 const char *ir3_instr_name(struct ir3_instruction
*instr
)
892 if (opc_cat(instr
->opc
) == -1) return "??meta??";
893 return opcs
[instr
->opc
].name
;
896 static void print_instr(uint32_t *dwords
, int level
, int n
)
898 instr_t
*instr
= (instr_t
*)dwords
;
899 uint32_t opc
= instr_opc(instr
);
902 if (debug
& PRINT_VERBOSE
)
903 printf("%s%04d[%08xx_%08xx] ", levels
[level
], n
, dwords
[1], dwords
[0]);
905 /* NOTE: order flags are printed is a bit fugly.. but for now I
906 * try to match the order in llvm-a3xx disassembler for easy
912 if (instr
->ss
&& (instr
->opc_cat
<= 4))
916 if (instr
->repeat
&& (instr
->opc_cat
<= 4)) {
917 printf("(rpt%d)", instr
->repeat
);
918 repeat
= instr
->repeat
;
922 if (instr
->ul
&& ((2 <= instr
->opc_cat
) && (instr
->opc_cat
<= 4)))
925 name
= GETINFO(instr
)->name
;
929 GETINFO(instr
)->print(instr
);
931 printf("unknown(%d,%d)", instr
->opc_cat
, opc
);
937 int disasm_a3xx(uint32_t *dwords
, int sizedwords
, int level
, enum shader_t type
)
941 assert((sizedwords
% 2) == 0);
943 for (i
= 0; i
< sizedwords
; i
+= 2)
944 print_instr(&dwords
[i
], level
, i
/2);