2d5ae62a64a3563bf7705667087c72e6f586ad1a
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
;
290 // XXX is this based on opc or some other bit?
299 case OPC_SAD_S32
: // really??
305 print_reg_dst((reg_t
)(cat3
->dst
), full
^ cat3
->dst_half
, false);
307 if (cat3
->c1
.src1_c
) {
308 print_reg_src((reg_t
)(cat3
->c1
.src1
), full
,
309 cat3
->src1_r
, cat3
->c1
.src1_c
, false, cat3
->src1_neg
,
311 } else if (cat3
->rel1
.src1_rel
) {
312 print_reg_src((reg_t
)(cat3
->rel1
.src1
), full
,
313 cat3
->src1_r
, cat3
->rel1
.src1_c
, false, cat3
->src1_neg
,
314 false, cat3
->rel1
.src1_rel
);
316 print_reg_src((reg_t
)(cat3
->src1
), full
,
317 cat3
->src1_r
, false, false, cat3
->src1_neg
,
321 print_reg_src((reg_t
)cat3
->src2
, full
,
322 cat3
->src2_r
, cat3
->src2_c
, false, cat3
->src2_neg
,
325 if (cat3
->c2
.src3_c
) {
326 print_reg_src((reg_t
)(cat3
->c2
.src3
), full
,
327 cat3
->src3_r
, cat3
->c2
.src3_c
, false, cat3
->src3_neg
,
329 } else if (cat3
->rel2
.src3_rel
) {
330 print_reg_src((reg_t
)(cat3
->rel2
.src3
), full
,
331 cat3
->src3_r
, cat3
->rel2
.src3_c
, false, cat3
->src3_neg
,
332 false, cat3
->rel2
.src3_rel
);
334 print_reg_src((reg_t
)(cat3
->src3
), full
,
335 cat3
->src3_r
, false, false, cat3
->src3_neg
,
340 static void print_instr_cat4(instr_t
*instr
)
342 instr_cat4_t
*cat4
= &instr
->cat4
;
345 print_reg_dst((reg_t
)(cat4
->dst
), cat4
->full
^ cat4
->dst_half
, false);
349 print_reg_src((reg_t
)(cat4
->c
.src
), cat4
->full
,
350 cat4
->src_r
, cat4
->c
.src_c
, cat4
->src_im
,
351 cat4
->src_neg
, cat4
->src_abs
, false);
352 } else if (cat4
->rel
.src_rel
) {
353 print_reg_src((reg_t
)(cat4
->rel
.src
), cat4
->full
,
354 cat4
->src_r
, cat4
->rel
.src_c
, cat4
->src_im
,
355 cat4
->src_neg
, cat4
->src_abs
, cat4
->rel
.src_rel
);
357 print_reg_src((reg_t
)(cat4
->src
), cat4
->full
,
358 cat4
->src_r
, false, cat4
->src_im
,
359 cat4
->src_neg
, cat4
->src_abs
, false);
362 if ((debug
& PRINT_VERBOSE
) && (cat4
->dummy1
|cat4
->dummy2
))
363 printf("\t{4: %x,%x}", cat4
->dummy1
, cat4
->dummy2
);
366 static void print_instr_cat5(instr_t
*instr
)
368 static const struct {
369 bool src1
, src2
, samp
, tex
;
371 [OPC_ISAM
] = { true, false, true, true, },
372 [OPC_ISAML
] = { true, true, true, true, },
373 [OPC_ISAMM
] = { true, false, true, true, },
374 [OPC_SAM
] = { true, false, true, true, },
375 [OPC_SAMB
] = { true, true, true, true, },
376 [OPC_SAML
] = { true, true, true, true, },
377 [OPC_SAMGQ
] = { true, false, true, true, },
378 [OPC_GETLOD
] = { true, false, true, true, },
379 [OPC_CONV
] = { true, true, true, true, },
380 [OPC_CONVM
] = { true, true, true, true, },
381 [OPC_GETSIZE
] = { true, false, false, true, },
382 [OPC_GETBUF
] = { false, false, false, true, },
383 [OPC_GETPOS
] = { true, false, false, true, },
384 [OPC_GETINFO
] = { false, false, false, true, },
385 [OPC_DSX
] = { true, false, false, false, },
386 [OPC_DSY
] = { true, false, false, false, },
387 [OPC_GATHER4R
] = { true, false, true, true, },
388 [OPC_GATHER4G
] = { true, false, true, true, },
389 [OPC_GATHER4B
] = { true, false, true, true, },
390 [OPC_GATHER4A
] = { true, false, true, true, },
391 [OPC_SAMGP0
] = { true, false, true, true, },
392 [OPC_SAMGP1
] = { true, false, true, true, },
393 [OPC_SAMGP2
] = { true, false, true, true, },
394 [OPC_SAMGP3
] = { true, false, true, true, },
395 [OPC_DSXPP_1
] = { true, false, false, false, },
396 [OPC_DSYPP_1
] = { true, false, false, false, },
397 [OPC_RGETPOS
] = { false, false, false, false, },
398 [OPC_RGETINFO
] = { false, false, false, false, },
400 instr_cat5_t
*cat5
= &instr
->cat5
;
403 if (cat5
->is_3d
) printf(".3d");
404 if (cat5
->is_a
) printf(".a");
405 if (cat5
->is_o
) printf(".o");
406 if (cat5
->is_p
) printf(".p");
407 if (cat5
->is_s
) printf(".s");
408 if (cat5
->is_s2en
) printf(".s2en");
417 printf("(%s)", type
[cat5
->type
]);
422 for (i
= 0; i
< 4; i
++)
423 if (cat5
->wrmask
& (1 << i
))
424 printf("%c", "xyzw"[i
]);
427 print_reg_dst((reg_t
)(cat5
->dst
), type_size(cat5
->type
) == 32, false);
429 if (info
[cat5
->opc
].src1
) {
431 print_reg_src((reg_t
)(cat5
->src1
), cat5
->full
, false, false, false,
432 false, false, false);
437 print_reg_src((reg_t
)(cat5
->s2en
.src2
), cat5
->full
, false, false, false,
438 false, false, false);
440 print_reg_src((reg_t
)(cat5
->s2en
.src3
), false, false, false, false,
441 false, false, false);
443 if (cat5
->is_o
|| info
[cat5
->opc
].src2
) {
445 print_reg_src((reg_t
)(cat5
->norm
.src2
), cat5
->full
,
446 false, false, false, false, false, false);
448 if (info
[cat5
->opc
].samp
)
449 printf(", s#%d", cat5
->norm
.samp
);
450 if (info
[cat5
->opc
].tex
)
451 printf(", t#%d", cat5
->norm
.tex
);
454 if (debug
& PRINT_VERBOSE
) {
456 if ((debug
& PRINT_VERBOSE
) && (cat5
->s2en
.dummy1
|cat5
->s2en
.dummy2
|cat5
->dummy2
))
457 printf("\t{5: %x,%x,%x}", cat5
->s2en
.dummy1
, cat5
->s2en
.dummy2
, cat5
->dummy2
);
459 if ((debug
& PRINT_VERBOSE
) && (cat5
->norm
.dummy1
|cat5
->dummy2
))
460 printf("\t{5: %x,%x}", cat5
->norm
.dummy1
, cat5
->dummy2
);
465 static int32_t u2i(uint32_t val
, int nbits
)
467 return ((val
>> (nbits
-1)) * ~((1 << nbits
) - 1)) | val
;
470 static void print_instr_cat6(instr_t
*instr
)
472 instr_cat6_t
*cat6
= &instr
->cat6
;
474 printf(".%s ", type
[cat6
->type
]);
482 /* load instructions: */
483 print_reg_dst((reg_t
)(cat6
->a
.dst
), type_size(cat6
->type
) == 32, false);
499 print_reg_src((reg_t
)(cat6
->a
.src
), true,
500 false, false, false, false, false, false);
502 printf("%+d", cat6
->a
.off
);
506 /* similar to load instructions: */
508 print_reg_src((reg_t
)(cat6
->a
.src
), true,
509 false, false, false, false, false, false);
511 printf("%+d", cat6
->a
.off
);
518 /* store instructions: */
532 print_reg_dst((reg_t
)(cat6
->b
.dst
), true, false);
533 if (cat6
->b
.off
|| cat6
->b
.off_hi
)
534 printf("%+d", u2i((cat6
->b
.off_hi
<< 8) | cat6
->b
.off
, 13));
537 print_reg_src((reg_t
)(cat6
->b
.src
), type_size(cat6
->type
) == 32,
538 false, false, false, false, false, false);
542 /* sti has same encoding as other store instructions, but
543 * slightly different syntax:
545 print_reg_dst((reg_t
)(cat6
->b
.dst
), false /* XXX is it always half? */, false);
546 if (cat6
->b
.off
|| cat6
->b
.off_hi
)
547 printf("%+d", u2i((cat6
->b
.off_hi
<< 8) | cat6
->b
.off
, 13));
549 print_reg_src((reg_t
)(cat6
->b
.src
), type_size(cat6
->type
) == 32,
550 false, false, false, false, false, false);
554 printf(", %d", cat6
->iim_val
);
556 if (debug
& PRINT_VERBOSE
) {
560 /* load instructions: */
561 if (cat6
->a
.dummy1
|cat6
->a
.dummy2
|cat6
->a
.dummy3
)
562 printf("\t{6: %x,%x,%x}", cat6
->a
.dummy1
, cat6
->a
.dummy2
, cat6
->a
.dummy3
);
563 if ((cat6
->a
.must_be_one1
!= 1) || (cat6
->a
.must_be_one2
!= 1))
564 printf("{?? %d,%d ??}", cat6
->a
.must_be_one1
, cat6
->a
.must_be_one2
);
569 /* store instructions: */
570 if (cat6
->b
.dummy1
|cat6
->b
.dummy2
)
571 printf("\t{6: %x,%x}", cat6
->b
.dummy1
, cat6
->b
.dummy2
);
572 if ((cat6
->b
.must_be_one1
!= 1) || (cat6
->b
.must_be_one2
!= 1) ||
573 (cat6
->b
.must_be_zero1
!= 0))
574 printf("{?? %d,%d,%d ??}", cat6
->b
.must_be_one1
, cat6
->b
.must_be_one2
,
575 cat6
->b
.must_be_zero1
);
581 /* size of largest OPC field of all the instruction categories: */
588 void (*print
)(instr_t
*instr
);
589 } opcs
[1 << (3+NOPC_BITS
)] = {
590 #define OPC(cat, opc, name) [((cat) << NOPC_BITS) | (opc)] = { (cat), (opc), #name, print_instr_cat##cat }
592 OPC(0, OPC_NOP
, nop
),
594 OPC(0, OPC_JUMP
, jump
),
595 OPC(0, OPC_CALL
, call
),
596 OPC(0, OPC_RET
, ret
),
597 OPC(0, OPC_KILL
, kill
),
598 OPC(0, OPC_END
, end
),
599 OPC(0, OPC_EMIT
, emit
),
600 OPC(0, OPC_CUT
, cut
),
601 OPC(0, OPC_CHMASK
, chmask
),
602 OPC(0, OPC_CHSH
, chsh
),
603 OPC(0, OPC_FLOW_REV
, flow_rev
),
609 OPC(2, OPC_ADD_F
, add
.f
),
610 OPC(2, OPC_MIN_F
, min
.f
),
611 OPC(2, OPC_MAX_F
, max
.f
),
612 OPC(2, OPC_MUL_F
, mul
.f
),
613 OPC(2, OPC_SIGN_F
, sign
.f
),
614 OPC(2, OPC_CMPS_F
, cmps
.f
),
615 OPC(2, OPC_ABSNEG_F
, absneg
.f
),
616 OPC(2, OPC_CMPV_F
, cmpv
.f
),
617 OPC(2, OPC_FLOOR_F
, floor
.f
),
618 OPC(2, OPC_CEIL_F
, ceil
.f
),
619 OPC(2, OPC_RNDNE_F
, rndne
.f
),
620 OPC(2, OPC_RNDAZ_F
, rndaz
.f
),
621 OPC(2, OPC_TRUNC_F
, trunc
.f
),
622 OPC(2, OPC_ADD_U
, add
.u
),
623 OPC(2, OPC_ADD_S
, add
.s
),
624 OPC(2, OPC_SUB_U
, sub
.u
),
625 OPC(2, OPC_SUB_S
, sub
.s
),
626 OPC(2, OPC_CMPS_U
, cmps
.u
),
627 OPC(2, OPC_CMPS_S
, cmps
.s
),
628 OPC(2, OPC_MIN_U
, min
.u
),
629 OPC(2, OPC_MIN_S
, min
.s
),
630 OPC(2, OPC_MAX_U
, max
.u
),
631 OPC(2, OPC_MAX_S
, max
.s
),
632 OPC(2, OPC_ABSNEG_S
, absneg
.s
),
633 OPC(2, OPC_AND_B
, and.b
),
634 OPC(2, OPC_OR_B
, or.b
),
635 OPC(2, OPC_NOT_B
, not.b
),
636 OPC(2, OPC_XOR_B
, xor.b
),
637 OPC(2, OPC_CMPV_U
, cmpv
.u
),
638 OPC(2, OPC_CMPV_S
, cmpv
.s
),
639 OPC(2, OPC_MUL_U
, mul
.u
),
640 OPC(2, OPC_MUL_S
, mul
.s
),
641 OPC(2, OPC_MULL_U
, mull
.u
),
642 OPC(2, OPC_BFREV_B
, bfrev
.b
),
643 OPC(2, OPC_CLZ_S
, clz
.s
),
644 OPC(2, OPC_CLZ_B
, clz
.b
),
645 OPC(2, OPC_SHL_B
, shl
.b
),
646 OPC(2, OPC_SHR_B
, shr
.b
),
647 OPC(2, OPC_ASHR_B
, ashr
.b
),
648 OPC(2, OPC_BARY_F
, bary
.f
),
649 OPC(2, OPC_MGEN_B
, mgen
.b
),
650 OPC(2, OPC_GETBIT_B
, getbit
.b
),
651 OPC(2, OPC_SETRM
, setrm
),
652 OPC(2, OPC_CBITS_B
, cbits
.b
),
653 OPC(2, OPC_SHB
, shb
),
654 OPC(2, OPC_MSAD
, msad
),
657 OPC(3, OPC_MAD_U16
, mad
.u16
),
658 OPC(3, OPC_MADSH_U16
, madsh
.u16
),
659 OPC(3, OPC_MAD_S16
, mad
.s16
),
660 OPC(3, OPC_MADSH_M16
, madsh
.m16
),
661 OPC(3, OPC_MAD_U24
, mad
.u24
),
662 OPC(3, OPC_MAD_S24
, mad
.s24
),
663 OPC(3, OPC_MAD_F16
, mad
.f16
),
664 OPC(3, OPC_MAD_F32
, mad
.f32
),
665 OPC(3, OPC_SEL_B16
, sel
.b16
),
666 OPC(3, OPC_SEL_B32
, sel
.b32
),
667 OPC(3, OPC_SEL_S16
, sel
.s16
),
668 OPC(3, OPC_SEL_S32
, sel
.s32
),
669 OPC(3, OPC_SEL_F16
, sel
.f16
),
670 OPC(3, OPC_SEL_F32
, sel
.f32
),
671 OPC(3, OPC_SAD_S16
, sad
.s16
),
672 OPC(3, OPC_SAD_S32
, sad
.s32
),
675 OPC(4, OPC_RCP
, rcp
),
676 OPC(4, OPC_RSQ
, rsq
),
677 OPC(4, OPC_LOG2
, log2
),
678 OPC(4, OPC_EXP2
, exp2
),
679 OPC(4, OPC_SIN
, sin
),
680 OPC(4, OPC_COS
, cos
),
681 OPC(4, OPC_SQRT
, sqrt
),
684 OPC(5, OPC_ISAM
, isam
),
685 OPC(5, OPC_ISAML
, isaml
),
686 OPC(5, OPC_ISAMM
, isamm
),
687 OPC(5, OPC_SAM
, sam
),
688 OPC(5, OPC_SAMB
, samb
),
689 OPC(5, OPC_SAML
, saml
),
690 OPC(5, OPC_SAMGQ
, samgq
),
691 OPC(5, OPC_GETLOD
, getlod
),
692 OPC(5, OPC_CONV
, conv
),
693 OPC(5, OPC_CONVM
, convm
),
694 OPC(5, OPC_GETSIZE
, getsize
),
695 OPC(5, OPC_GETBUF
, getbuf
),
696 OPC(5, OPC_GETPOS
, getpos
),
697 OPC(5, OPC_GETINFO
, getinfo
),
698 OPC(5, OPC_DSX
, dsx
),
699 OPC(5, OPC_DSY
, dsy
),
700 OPC(5, OPC_GATHER4R
, gather4r
),
701 OPC(5, OPC_GATHER4G
, gather4g
),
702 OPC(5, OPC_GATHER4B
, gather4b
),
703 OPC(5, OPC_GATHER4A
, gather4a
),
704 OPC(5, OPC_SAMGP0
, samgp0
),
705 OPC(5, OPC_SAMGP1
, samgp1
),
706 OPC(5, OPC_SAMGP2
, samgp2
),
707 OPC(5, OPC_SAMGP3
, samgp3
),
708 OPC(5, OPC_DSXPP_1
, dsxpp
.1),
709 OPC(5, OPC_DSYPP_1
, dsypp
.1),
710 OPC(5, OPC_RGETPOS
, rgetpos
),
711 OPC(5, OPC_RGETINFO
, rgetinfo
),
715 OPC(6, OPC_LDG
, ldg
),
716 OPC(6, OPC_LDL
, ldl
),
717 OPC(6, OPC_LDP
, ldp
),
718 OPC(6, OPC_STG
, stg
),
719 OPC(6, OPC_STL
, stl
),
720 OPC(6, OPC_STP
, stp
),
721 OPC(6, OPC_STI
, sti
),
722 OPC(6, OPC_G2L
, g2l
),
723 OPC(6, OPC_L2G
, l2g
),
724 OPC(6, OPC_PREFETCH
, prefetch
),
725 OPC(6, OPC_LDLW
, ldlw
),
726 OPC(6, OPC_STLW
, stlw
),
727 OPC(6, OPC_RESFMT
, resfmt
),
728 OPC(6, OPC_RESINFO
, resinf
),
729 OPC(6, OPC_ATOMIC_ADD_L
, atomic
.add
.l
),
730 OPC(6, OPC_ATOMIC_SUB_L
, atomic
.sub
.l
),
731 OPC(6, OPC_ATOMIC_XCHG_L
, atomic
.xchg
.l
),
732 OPC(6, OPC_ATOMIC_INC_L
, atomic
.inc
.l
),
733 OPC(6, OPC_ATOMIC_DEC_L
, atomic
.dec
.l
),
734 OPC(6, OPC_ATOMIC_CMPXCHG_L
, atomic
.cmpxchg
.l
),
735 OPC(6, OPC_ATOMIC_MIN_L
, atomic
.min
.l
),
736 OPC(6, OPC_ATOMIC_MAX_L
, atomic
.max
.l
),
737 OPC(6, OPC_ATOMIC_AND_L
, atomic
.and.l
),
738 OPC(6, OPC_ATOMIC_OR_L
, atomic
.or.l
),
739 OPC(6, OPC_ATOMIC_XOR_L
, atomic
.xor.l
),
740 OPC(6, OPC_LDGB_TYPED_4D
, ldgb
.typed
.4d
),
741 OPC(6, OPC_STGB_4D_4
, stgb
.4d
.4),
742 OPC(6, OPC_STIB
, stib
),
743 OPC(6, OPC_LDC_4
, ldc
.4),
744 OPC(6, OPC_LDLV
, ldlv
),
750 #define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | getopc(instr)]))
752 static uint32_t getopc(instr_t
*instr
)
754 switch (instr
->opc_cat
) {
755 case 0: return instr
->cat0
.opc
;
757 case 2: return instr
->cat2
.opc
;
758 case 3: return instr
->cat3
.opc
;
759 case 4: return instr
->cat4
.opc
;
760 case 5: return instr
->cat5
.opc
;
761 case 6: return instr
->cat6
.opc
;
766 static void print_instr(uint32_t *dwords
, int level
, int n
)
768 instr_t
*instr
= (instr_t
*)dwords
;
769 uint32_t opc
= getopc(instr
);
772 printf("%s%04d[%08xx_%08xx] ", levels
[level
], n
, dwords
[1], dwords
[0]);
775 /* print unknown bits: */
776 if (debug
& PRINT_RAW
)
777 printf("[%08xx_%08xx] ", dwords
[1] & 0x001ff800, dwords
[0] & 0x00000000);
779 if (debug
& PRINT_VERBOSE
)
780 printf("%d,%02d ", instr
->opc_cat
, opc
);
783 /* NOTE: order flags are printed is a bit fugly.. but for now I
784 * try to match the order in llvm-a3xx disassembler for easy
790 if (instr
->ss
&& (instr
->opc_cat
<= 4))
794 if (instr
->repeat
&& (instr
->opc_cat
<= 4)) {
795 printf("(rpt%d)", instr
->repeat
);
796 repeat
= instr
->repeat
;
800 if (instr
->ul
&& ((2 <= instr
->opc_cat
) && (instr
->opc_cat
<= 4)))
803 name
= GETINFO(instr
)->name
;
807 GETINFO(instr
)->print(instr
);
809 printf("unknown(%d,%d)", instr
->opc_cat
, opc
);
815 int disasm_a3xx(uint32_t *dwords
, int sizedwords
, int level
, enum shader_t type
)
819 assert((sizedwords
% 2) == 0);
821 for (i
= 0; i
< sizedwords
; i
+= 2)
822 print_instr(&dwords
[i
], level
, i
/2);