xref: /aosp_15_r20/external/mesa3d/src/freedreno/ir3/disasm-a3xx.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2013 Rob Clark <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include <assert.h>
7*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
8*61046927SAndroid Build Coastguard Worker #include <stdint.h>
9*61046927SAndroid Build Coastguard Worker #include <stdio.h>
10*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
11*61046927SAndroid Build Coastguard Worker #include <string.h>
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker #include <util/log.h>
14*61046927SAndroid Build Coastguard Worker #include <util/u_debug.h>
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker #include "freedreno/isa/ir3-isa.h"
17*61046927SAndroid Build Coastguard Worker 
18*61046927SAndroid Build Coastguard Worker #include "disasm.h"
19*61046927SAndroid Build Coastguard Worker #include "instr-a3xx.h"
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker static enum debug_t debug;
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker static const char *levels[] = {
24*61046927SAndroid Build Coastguard Worker    "",
25*61046927SAndroid Build Coastguard Worker    "\t",
26*61046927SAndroid Build Coastguard Worker    "\t\t",
27*61046927SAndroid Build Coastguard Worker    "\t\t\t",
28*61046927SAndroid Build Coastguard Worker    "\t\t\t\t",
29*61046927SAndroid Build Coastguard Worker    "\t\t\t\t\t",
30*61046927SAndroid Build Coastguard Worker    "\t\t\t\t\t\t",
31*61046927SAndroid Build Coastguard Worker    "\t\t\t\t\t\t\t",
32*61046927SAndroid Build Coastguard Worker    "\t\t\t\t\t\t\t\t",
33*61046927SAndroid Build Coastguard Worker    "\t\t\t\t\t\t\t\t\t",
34*61046927SAndroid Build Coastguard Worker    "x",
35*61046927SAndroid Build Coastguard Worker    "x",
36*61046927SAndroid Build Coastguard Worker    "x",
37*61046927SAndroid Build Coastguard Worker    "x",
38*61046927SAndroid Build Coastguard Worker    "x",
39*61046927SAndroid Build Coastguard Worker    "x",
40*61046927SAndroid Build Coastguard Worker };
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker struct disasm_ctx {
43*61046927SAndroid Build Coastguard Worker    FILE *out;
44*61046927SAndroid Build Coastguard Worker    struct isa_decode_options *options;
45*61046927SAndroid Build Coastguard Worker    unsigned level;
46*61046927SAndroid Build Coastguard Worker    unsigned extra_cycles;
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker    /**
49*61046927SAndroid Build Coastguard Worker     * nop_count/has_end used to detect the real end of shader.  Since
50*61046927SAndroid Build Coastguard Worker     * in some cases there can be a epilogue following an `end` we look
51*61046927SAndroid Build Coastguard Worker     * for a sequence of `nop`s following the `end`
52*61046927SAndroid Build Coastguard Worker     */
53*61046927SAndroid Build Coastguard Worker    int nop_count; /* number of nop's since non-nop instruction: */
54*61046927SAndroid Build Coastguard Worker    bool has_end;  /* have we seen end instruction */
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker    int cur_n;       /* current instr # */
57*61046927SAndroid Build Coastguard Worker    int cur_opc_cat; /* current opc_cat */
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker    int sfu_delay;
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker    /**
62*61046927SAndroid Build Coastguard Worker     * State accumulated decoding fields of the current instruction,
63*61046927SAndroid Build Coastguard Worker     * handled after decoding is complete (ie. at start of next instr)
64*61046927SAndroid Build Coastguard Worker     */
65*61046927SAndroid Build Coastguard Worker    struct {
66*61046927SAndroid Build Coastguard Worker       bool ss;
67*61046927SAndroid Build Coastguard Worker       uint8_t nop;
68*61046927SAndroid Build Coastguard Worker       uint8_t repeat;
69*61046927SAndroid Build Coastguard Worker    } last;
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker    /**
72*61046927SAndroid Build Coastguard Worker     * State accumulated decoding fields of src or dst register
73*61046927SAndroid Build Coastguard Worker     */
74*61046927SAndroid Build Coastguard Worker    struct {
75*61046927SAndroid Build Coastguard Worker       bool half;
76*61046927SAndroid Build Coastguard Worker       bool r;
77*61046927SAndroid Build Coastguard Worker       enum {
78*61046927SAndroid Build Coastguard Worker          FILE_GPR = 1,
79*61046927SAndroid Build Coastguard Worker          FILE_CONST = 2,
80*61046927SAndroid Build Coastguard Worker       } file;
81*61046927SAndroid Build Coastguard Worker       unsigned num;
82*61046927SAndroid Build Coastguard Worker    } reg;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    struct shader_stats *stats;
85*61046927SAndroid Build Coastguard Worker };
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker static void
print_stats(struct disasm_ctx * ctx)88*61046927SAndroid Build Coastguard Worker print_stats(struct disasm_ctx *ctx)
89*61046927SAndroid Build Coastguard Worker {
90*61046927SAndroid Build Coastguard Worker    if (ctx->options->gpu_id >= 600) {
91*61046927SAndroid Build Coastguard Worker       /* handle MERGEREGS case.. this isn't *entirely* accurate, as
92*61046927SAndroid Build Coastguard Worker        * you can have shader stages not using merged register file,
93*61046927SAndroid Build Coastguard Worker        * but it is good enough for a guestimate:
94*61046927SAndroid Build Coastguard Worker        */
95*61046927SAndroid Build Coastguard Worker       unsigned n = (ctx->stats->halfreg + 1) / 2;
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker       ctx->stats->halfreg = 0;
98*61046927SAndroid Build Coastguard Worker       ctx->stats->fullreg = MAX2(ctx->stats->fullreg, n);
99*61046927SAndroid Build Coastguard Worker    }
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    unsigned instructions = ctx->cur_n + ctx->extra_cycles + 1;
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    fprintf(ctx->out, "%sStats:\n", levels[ctx->level]);
104*61046927SAndroid Build Coastguard Worker    fprintf(ctx->out,
105*61046927SAndroid Build Coastguard Worker            "%s- shaderdb: %u instr, %u nops, %u non-nops, %u mov, %u cov\n",
106*61046927SAndroid Build Coastguard Worker            levels[ctx->level], instructions, ctx->stats->nops,
107*61046927SAndroid Build Coastguard Worker            instructions - ctx->stats->nops, ctx->stats->mov_count,
108*61046927SAndroid Build Coastguard Worker            ctx->stats->cov_count);
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    fprintf(ctx->out,
111*61046927SAndroid Build Coastguard Worker            "%s- shaderdb: %u last-baryf, %d half, %d full, %u constlen\n",
112*61046927SAndroid Build Coastguard Worker            levels[ctx->level], ctx->stats->last_baryf,
113*61046927SAndroid Build Coastguard Worker            DIV_ROUND_UP(ctx->stats->halfreg, 4),
114*61046927SAndroid Build Coastguard Worker            DIV_ROUND_UP(ctx->stats->fullreg, 4),
115*61046927SAndroid Build Coastguard Worker            DIV_ROUND_UP(ctx->stats->constlen, 4));
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    fprintf(
118*61046927SAndroid Build Coastguard Worker       ctx->out,
119*61046927SAndroid Build Coastguard Worker       "%s- shaderdb: %u cat0, %u cat1, %u cat2, %u cat3, %u cat4, %u cat5, %u cat6, %u cat7\n",
120*61046927SAndroid Build Coastguard Worker       levels[ctx->level], ctx->stats->instrs_per_cat[0],
121*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[1], ctx->stats->instrs_per_cat[2],
122*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[3], ctx->stats->instrs_per_cat[4],
123*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[5], ctx->stats->instrs_per_cat[6],
124*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[7]);
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker    fprintf(ctx->out, "%s- shaderdb: %u sstall, %u (ss), %u (sy)\n",
127*61046927SAndroid Build Coastguard Worker            levels[ctx->level], ctx->stats->sstall, ctx->stats->ss,
128*61046927SAndroid Build Coastguard Worker            ctx->stats->sy);
129*61046927SAndroid Build Coastguard Worker }
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker static const struct opc_info {
132*61046927SAndroid Build Coastguard Worker    const char *name;
133*61046927SAndroid Build Coastguard Worker } opcs[1 << (3 + NOPC_BITS)] = {
134*61046927SAndroid Build Coastguard Worker #define OPC(cat, opc, name) [(opc)] = {#name}
135*61046927SAndroid Build Coastguard Worker    /* clang-format off */
136*61046927SAndroid Build Coastguard Worker    /* category 0: */
137*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_NOP,          nop),
138*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BR,           br),
139*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BRAC,         brac),
140*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BRAA,         braa),
141*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BRAO,         brao),
142*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BALL,         ball),
143*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BANY,         bany),
144*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_JUMP,         jump),
145*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_CALL,         call),
146*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_RET,          ret),
147*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_KILL,         kill),
148*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_DEMOTE,       demote),
149*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_END,          end),
150*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_EMIT,         emit),
151*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_CUT,          cut),
152*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_CHMASK,       chmask),
153*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_CHSH,         chsh),
154*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_FLOW_REV,     flow_rev),
155*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_PREDT,        predt),
156*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_PREDF,        predf),
157*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_PREDE,        prede),
158*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_BKT,          bkt),
159*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_STKS,         stks),
160*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_STKR,         stkr),
161*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_XSET,         xset),
162*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_XCLR,         xclr),
163*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_GETLAST,      getlast),
164*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_GETONE,       getone),
165*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_DBG,          dbg),
166*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_SHPS,         shps),
167*61046927SAndroid Build Coastguard Worker    OPC(0, OPC_SHPE,         shpe),
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    /* category 1: */
170*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_MOV,          ),
171*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_MOVMSK,       movmsk),
172*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_SWZ,          swz),
173*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_SCT,          sct),
174*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_GAT,          gat),
175*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_BALLOT_MACRO, ballot.macro),
176*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_ANY_MACRO,    any.macro),
177*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_ALL_MACRO,    all.macro),
178*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_ELECT_MACRO,  elect.macro),
179*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_READ_COND_MACRO, read_cond.macro),
180*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_READ_FIRST_MACRO, read_first.macro),
181*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_SCAN_MACRO, scan.macro),
182*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_SCAN_CLUSTERS_MACRO, scan_clusters.macro),
183*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_SHPS_MACRO, shps.macro),
184*61046927SAndroid Build Coastguard Worker    OPC(1, OPC_PUSH_CONSTS_LOAD_MACRO, push_consts_load.macro),
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    /* category 2: */
187*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_ADD_F,        add.f),
188*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MIN_F,        min.f),
189*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MAX_F,        max.f),
190*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MUL_F,        mul.f),
191*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SIGN_F,       sign.f),
192*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CMPS_F,       cmps.f),
193*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_ABSNEG_F,     absneg.f),
194*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CMPV_F,       cmpv.f),
195*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_FLOOR_F,      floor.f),
196*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CEIL_F,       ceil.f),
197*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_RNDNE_F,      rndne.f),
198*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_RNDAZ_F,      rndaz.f),
199*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_TRUNC_F,      trunc.f),
200*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_ADD_U,        add.u),
201*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_ADD_S,        add.s),
202*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SUB_U,        sub.u),
203*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SUB_S,        sub.s),
204*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CMPS_U,       cmps.u),
205*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CMPS_S,       cmps.s),
206*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MIN_U,        min.u),
207*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MIN_S,        min.s),
208*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MAX_U,        max.u),
209*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MAX_S,        max.s),
210*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_ABSNEG_S,     absneg.s),
211*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_AND_B,        and.b),
212*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_OR_B,         or.b),
213*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_NOT_B,        not.b),
214*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_XOR_B,        xor.b),
215*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CMPV_U,       cmpv.u),
216*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CMPV_S,       cmpv.s),
217*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MUL_U24,      mul.u24),
218*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MUL_S24,      mul.s24),
219*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MULL_U,       mull.u),
220*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_BFREV_B,      bfrev.b),
221*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CLZ_S,        clz.s),
222*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CLZ_B,        clz.b),
223*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SHL_B,        shl.b),
224*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SHR_B,        shr.b),
225*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_ASHR_B,       ashr.b),
226*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_BARY_F,       bary.f),
227*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MGEN_B,       mgen.b),
228*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_GETBIT_B,     getbit.b),
229*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SETRM,        setrm),
230*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_CBITS_B,      cbits.b),
231*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_SHB,          shb),
232*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_MSAD,         msad),
233*61046927SAndroid Build Coastguard Worker    OPC(2, OPC_FLAT_B,       flat.b),
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    /* category 3: */
236*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MAD_U16,      mad.u16),
237*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MADSH_U16,    madsh.u16),
238*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MAD_S16,      mad.s16),
239*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MADSH_M16,    madsh.m16),
240*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MAD_U24,      mad.u24),
241*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MAD_S24,      mad.s24),
242*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MAD_F16,      mad.f16),
243*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_MAD_F32,      mad.f32),
244*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SEL_B16,      sel.b16),
245*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SEL_B32,      sel.b32),
246*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SEL_S16,      sel.s16),
247*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SEL_S32,      sel.s32),
248*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SEL_F16,      sel.f16),
249*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SEL_F32,      sel.f32),
250*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SAD_S16,      sad.s16),
251*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SAD_S32,      sad.s32),
252*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SHRM,         shrm),
253*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SHLM,         shlm),
254*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SHRG,         shrg),
255*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_SHLG,         shlg),
256*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_ANDG,         andg),
257*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_DP2ACC,       dp2acc),
258*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_DP4ACC,       dp4acc),
259*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_WMM,          wmm),
260*61046927SAndroid Build Coastguard Worker    OPC(3, OPC_WMM_ACCU,     wmm.accu),
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    /* category 4: */
263*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_RCP,          rcp),
264*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_RSQ,          rsq),
265*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_LOG2,         log2),
266*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_EXP2,         exp2),
267*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_SIN,          sin),
268*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_COS,          cos),
269*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_SQRT,         sqrt),
270*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_HRSQ,         hrsq),
271*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_HLOG2,        hlog2),
272*61046927SAndroid Build Coastguard Worker    OPC(4, OPC_HEXP2,        hexp2),
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker    /* category 5: */
275*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_ISAM,         isam),
276*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_ISAML,        isaml),
277*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_ISAMM,        isamm),
278*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAM,          sam),
279*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAMB,         samb),
280*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAML,         saml),
281*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAMGQ,        samgq),
282*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GETLOD,       getlod),
283*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_CONV,         conv),
284*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_CONVM,        convm),
285*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GETSIZE,      getsize),
286*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GETBUF,       getbuf),
287*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GETPOS,       getpos),
288*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GETINFO,      getinfo),
289*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_DSX,          dsx),
290*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_DSY,          dsy),
291*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GATHER4R,     gather4r),
292*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GATHER4G,     gather4g),
293*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GATHER4B,     gather4b),
294*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_GATHER4A,     gather4a),
295*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAMGP0,       samgp0),
296*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAMGP1,       samgp1),
297*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAMGP2,       samgp2),
298*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_SAMGP3,       samgp3),
299*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_DSXPP_1,      dsxpp.1),
300*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_DSYPP_1,      dsypp.1),
301*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_RGETPOS,      rgetpos),
302*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_RGETINFO,     rgetinfo),
303*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_BRCST_ACTIVE, brcst.active),
304*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_QUAD_SHUFFLE_BRCST, quad_shuffle.brcst),
305*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_QUAD_SHUFFLE_HORIZ, quad_shuffle.horiz),
306*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_QUAD_SHUFFLE_VERT,  quad_shuffle.vert),
307*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_QUAD_SHUFFLE_DIAG,  quad_shuffle.diag),
308*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_TCINV,        tcinv),
309*61046927SAndroid Build Coastguard Worker    /* macros are needed here for ir3_print */
310*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_DSXPP_MACRO,  dsxpp.macro),
311*61046927SAndroid Build Coastguard Worker    OPC(5, OPC_DSYPP_MACRO,  dsypp.macro),
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    /* category 6: */
315*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDG,          ldg),
316*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDG_A,        ldg.a),
317*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDL,          ldl),
318*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDP,          ldp),
319*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STG,          stg),
320*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STG_A,        stg.a),
321*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STL,          stl),
322*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STP,          stp),
323*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDIB,         ldib),
324*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_G2L,          g2l),
325*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_L2G,          l2g),
326*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_PREFETCH,     prefetch),
327*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDLW,         ldlw),
328*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STLW,         stlw),
329*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_RESFMT,       resfmt),
330*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_RESINFO,      resinfo),
331*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_ADD,     atomic.add),
332*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_SUB,     atomic.sub),
333*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_XCHG,    atomic.xchg),
334*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_INC,     atomic.inc),
335*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_DEC,     atomic.dec),
336*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_CMPXCHG, atomic.cmpxchg),
337*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_MIN,     atomic.min),
338*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_MAX,     atomic.max),
339*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_AND,     atomic.and),
340*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_OR,      atomic.or),
341*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_XOR,     atomic.xor),
342*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_ADD,     atomic.b.add),
343*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_SUB,     atomic.b.sub),
344*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_XCHG,    atomic.b.xchg),
345*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_INC,     atomic.b.inc),
346*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_DEC,     atomic.b.dec),
347*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_CMPXCHG, atomic.b.cmpxchg),
348*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_MIN,     atomic.b.min),
349*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_MAX,     atomic.b.max),
350*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_AND,     atomic.b.and),
351*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_OR,      atomic.b.or),
352*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_B_XOR,     atomic.b.xor),
353*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_ADD,     atomic.s.add),
354*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_SUB,     atomic.s.sub),
355*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_XCHG,    atomic.s.xchg),
356*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_INC,     atomic.s.inc),
357*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_DEC,     atomic.s.dec),
358*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_CMPXCHG, atomic.s.cmpxchg),
359*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_MIN,     atomic.s.min),
360*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_MAX,     atomic.s.max),
361*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_AND,     atomic.s.and),
362*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_OR,      atomic.s.or),
363*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_S_XOR,     atomic.s.xor),
364*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_ADD,     atomic.g.add),
365*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_SUB,     atomic.g.sub),
366*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_XCHG,    atomic.g.xchg),
367*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_INC,     atomic.g.inc),
368*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_DEC,     atomic.g.dec),
369*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_CMPXCHG, atomic.g.cmpxchg),
370*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_MIN,     atomic.g.min),
371*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_MAX,     atomic.g.max),
372*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_AND,     atomic.g.and),
373*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_OR,      atomic.g.or),
374*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ATOMIC_G_XOR,     atomic.g.xor),
375*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDGB,         ldgb),
376*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STGB,         stgb),
377*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STIB,         stib),
378*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDC,          ldc),
379*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDLV,         ldlv),
380*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_PIPR,         pipr),
381*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_PIPC,         pipc),
382*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_EMIT2,        emit),
383*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_ENDLS,        endls),
384*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_GETSPID,      getspid),
385*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_GETWID,       getwid),
386*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_GETFIBERID,   getfiberid),
387*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STC,          stc),
388*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_STSC,         stsc),
389*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDC_K,        ldc.k),
390*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_LDG_K,        ldg.k),
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_SPILL_MACRO,  spill.macro),
393*61046927SAndroid Build Coastguard Worker    OPC(6, OPC_RELOAD_MACRO, reload.macro),
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    OPC(7, OPC_BAR,          bar),
396*61046927SAndroid Build Coastguard Worker    OPC(7, OPC_FENCE,        fence),
397*61046927SAndroid Build Coastguard Worker    OPC(7, OPC_LOCK,         lock),
398*61046927SAndroid Build Coastguard Worker    OPC(7, OPC_UNLOCK,       unlock),
399*61046927SAndroid Build Coastguard Worker /* clang-format on */
400*61046927SAndroid Build Coastguard Worker #undef OPC
401*61046927SAndroid Build Coastguard Worker };
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker const char *
disasm_a3xx_instr_name(opc_t opc)404*61046927SAndroid Build Coastguard Worker disasm_a3xx_instr_name(opc_t opc)
405*61046927SAndroid Build Coastguard Worker {
406*61046927SAndroid Build Coastguard Worker    if (opc_cat(opc) == OPC_META)
407*61046927SAndroid Build Coastguard Worker       return "??meta??";
408*61046927SAndroid Build Coastguard Worker    return opcs[opc].name;
409*61046927SAndroid Build Coastguard Worker }
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker static void
disasm_field_cb(void * d,const char * field_name,struct isa_decode_value * val)412*61046927SAndroid Build Coastguard Worker disasm_field_cb(void *d, const char *field_name, struct isa_decode_value *val)
413*61046927SAndroid Build Coastguard Worker {
414*61046927SAndroid Build Coastguard Worker    struct disasm_ctx *ctx = d;
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    if (!strcmp(field_name, "NAME")) {
417*61046927SAndroid Build Coastguard Worker       if (!strcmp("nop", val->str)) {
418*61046927SAndroid Build Coastguard Worker          if (ctx->has_end) {
419*61046927SAndroid Build Coastguard Worker             ctx->nop_count++;
420*61046927SAndroid Build Coastguard Worker             if (ctx->nop_count > 3) {
421*61046927SAndroid Build Coastguard Worker                ctx->options->stop = true;
422*61046927SAndroid Build Coastguard Worker             }
423*61046927SAndroid Build Coastguard Worker          }
424*61046927SAndroid Build Coastguard Worker          ctx->stats->nops += 1 + ctx->last.repeat;
425*61046927SAndroid Build Coastguard Worker       } else {
426*61046927SAndroid Build Coastguard Worker          ctx->nop_count = 0;
427*61046927SAndroid Build Coastguard Worker       }
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker       if (!strcmp("end", val->str)) {
430*61046927SAndroid Build Coastguard Worker          ctx->has_end = true;
431*61046927SAndroid Build Coastguard Worker          ctx->nop_count = 0;
432*61046927SAndroid Build Coastguard Worker       } else if (!strcmp("chsh", val->str)) {
433*61046927SAndroid Build Coastguard Worker          ctx->options->stop = true;
434*61046927SAndroid Build Coastguard Worker       } else if (!strcmp("bary.f", val->str)) {
435*61046927SAndroid Build Coastguard Worker          ctx->stats->last_baryf = ctx->cur_n;
436*61046927SAndroid Build Coastguard Worker       }
437*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "REPEAT")) {
438*61046927SAndroid Build Coastguard Worker       ctx->extra_cycles += val->num;
439*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[ctx->cur_opc_cat] += val->num;
440*61046927SAndroid Build Coastguard Worker       ctx->last.repeat = val->num;
441*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "NOP")) {
442*61046927SAndroid Build Coastguard Worker       ctx->extra_cycles += val->num;
443*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[0] += val->num;
444*61046927SAndroid Build Coastguard Worker       ctx->stats->nops += val->num;
445*61046927SAndroid Build Coastguard Worker       ctx->last.nop = val->num;
446*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "SY")) {
447*61046927SAndroid Build Coastguard Worker       ctx->stats->sy += val->num;
448*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "SS")) {
449*61046927SAndroid Build Coastguard Worker       ctx->stats->ss += val->num;
450*61046927SAndroid Build Coastguard Worker       ctx->last.ss = !!val->num;
451*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "CONST")) {
452*61046927SAndroid Build Coastguard Worker       ctx->reg.num = val->num;
453*61046927SAndroid Build Coastguard Worker       ctx->reg.file = FILE_CONST;
454*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "GPR")) {
455*61046927SAndroid Build Coastguard Worker       /* don't count GPR regs r48.x (shared) or higher: */
456*61046927SAndroid Build Coastguard Worker       if (val->num < 48) {
457*61046927SAndroid Build Coastguard Worker          ctx->reg.num = val->num;
458*61046927SAndroid Build Coastguard Worker          ctx->reg.file = FILE_GPR;
459*61046927SAndroid Build Coastguard Worker       }
460*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "SRC_R") || !strcmp(field_name, "SRC1_R") ||
461*61046927SAndroid Build Coastguard Worker               !strcmp(field_name, "SRC2_R") || !strcmp(field_name, "SRC3_R")) {
462*61046927SAndroid Build Coastguard Worker       ctx->reg.r = val->num;
463*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "DST")) {
464*61046927SAndroid Build Coastguard Worker       /* Dest register is always repeated
465*61046927SAndroid Build Coastguard Worker        *
466*61046927SAndroid Build Coastguard Worker        * Note that this doesn't really properly handle instructions
467*61046927SAndroid Build Coastguard Worker        * that write multiple components.. the old disasm didn't handle
468*61046927SAndroid Build Coastguard Worker        * that case either.
469*61046927SAndroid Build Coastguard Worker        */
470*61046927SAndroid Build Coastguard Worker       ctx->reg.r = true;
471*61046927SAndroid Build Coastguard Worker    } else if (strstr(field_name, "HALF")) {
472*61046927SAndroid Build Coastguard Worker       ctx->reg.half = val->num;
473*61046927SAndroid Build Coastguard Worker    } else if (!strcmp(field_name, "SWIZ")) {
474*61046927SAndroid Build Coastguard Worker       unsigned num = (ctx->reg.num << 2) | val->num;
475*61046927SAndroid Build Coastguard Worker       if (ctx->reg.r)
476*61046927SAndroid Build Coastguard Worker          num += ctx->last.repeat;
477*61046927SAndroid Build Coastguard Worker 
478*61046927SAndroid Build Coastguard Worker       if (ctx->reg.file == FILE_CONST) {
479*61046927SAndroid Build Coastguard Worker          ctx->stats->constlen = MAX2(ctx->stats->constlen, num);
480*61046927SAndroid Build Coastguard Worker       } else if (ctx->reg.file == FILE_GPR) {
481*61046927SAndroid Build Coastguard Worker          if (ctx->reg.half) {
482*61046927SAndroid Build Coastguard Worker             ctx->stats->halfreg = MAX2(ctx->stats->halfreg, num);
483*61046927SAndroid Build Coastguard Worker          } else {
484*61046927SAndroid Build Coastguard Worker             ctx->stats->fullreg = MAX2(ctx->stats->fullreg, num);
485*61046927SAndroid Build Coastguard Worker          }
486*61046927SAndroid Build Coastguard Worker       }
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker       memset(&ctx->reg, 0, sizeof(ctx->reg));
489*61046927SAndroid Build Coastguard Worker    }
490*61046927SAndroid Build Coastguard Worker }
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker /**
493*61046927SAndroid Build Coastguard Worker  * Handle stat updates dealt with at the end of instruction decoding,
494*61046927SAndroid Build Coastguard Worker  * ie. before beginning of next instruction
495*61046927SAndroid Build Coastguard Worker  */
496*61046927SAndroid Build Coastguard Worker static void
disasm_handle_last(struct disasm_ctx * ctx)497*61046927SAndroid Build Coastguard Worker disasm_handle_last(struct disasm_ctx *ctx)
498*61046927SAndroid Build Coastguard Worker {
499*61046927SAndroid Build Coastguard Worker    if (ctx->last.ss) {
500*61046927SAndroid Build Coastguard Worker       ctx->stats->sstall += ctx->sfu_delay;
501*61046927SAndroid Build Coastguard Worker       ctx->sfu_delay = 0;
502*61046927SAndroid Build Coastguard Worker    }
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker    if (ctx->cur_opc_cat == 4) {
505*61046927SAndroid Build Coastguard Worker       ctx->sfu_delay = 10;
506*61046927SAndroid Build Coastguard Worker    } else {
507*61046927SAndroid Build Coastguard Worker       int n = MIN2(ctx->sfu_delay, 1 + ctx->last.repeat + ctx->last.nop);
508*61046927SAndroid Build Coastguard Worker       ctx->sfu_delay -= n;
509*61046927SAndroid Build Coastguard Worker    }
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker    memset(&ctx->last, 0, sizeof(ctx->last));
512*61046927SAndroid Build Coastguard Worker }
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker static void
disasm_instr_cb(void * d,unsigned n,void * instr)515*61046927SAndroid Build Coastguard Worker disasm_instr_cb(void *d, unsigned n, void *instr)
516*61046927SAndroid Build Coastguard Worker {
517*61046927SAndroid Build Coastguard Worker    struct disasm_ctx *ctx = d;
518*61046927SAndroid Build Coastguard Worker    uint32_t *dwords = (uint32_t *)instr;
519*61046927SAndroid Build Coastguard Worker    uint64_t val = dwords[1];
520*61046927SAndroid Build Coastguard Worker    val = val << 32;
521*61046927SAndroid Build Coastguard Worker    val |= dwords[0];
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker    unsigned opc_cat = val >> 61;
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker    /* There are some cases where we can get instr_cb called multiple
526*61046927SAndroid Build Coastguard Worker     * times per instruction (like when we need an extra line for branch
527*61046927SAndroid Build Coastguard Worker     * target labels), don't update stats in these cases:
528*61046927SAndroid Build Coastguard Worker     */
529*61046927SAndroid Build Coastguard Worker    if (n != ctx->cur_n) {
530*61046927SAndroid Build Coastguard Worker       if (n > 0) {
531*61046927SAndroid Build Coastguard Worker          disasm_handle_last(ctx);
532*61046927SAndroid Build Coastguard Worker       }
533*61046927SAndroid Build Coastguard Worker       ctx->stats->instrs_per_cat[opc_cat]++;
534*61046927SAndroid Build Coastguard Worker       ctx->cur_n = n;
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker       /* mov vs cov stats are a bit harder to fish out of the field
537*61046927SAndroid Build Coastguard Worker        * names, because current ir3-cat1.xml doesn't use {NAME} for
538*61046927SAndroid Build Coastguard Worker        * this distinction.  So for now just handle this case with
539*61046927SAndroid Build Coastguard Worker        * some hand-coded parsing:
540*61046927SAndroid Build Coastguard Worker        */
541*61046927SAndroid Build Coastguard Worker       if (opc_cat == 1) {
542*61046927SAndroid Build Coastguard Worker          unsigned opc = (val >> 57) & 0x3;
543*61046927SAndroid Build Coastguard Worker          unsigned src_type = (val >> 50) & 0x7;
544*61046927SAndroid Build Coastguard Worker          unsigned dst_type = (val >> 46) & 0x7;
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker          if (opc == 0) {
547*61046927SAndroid Build Coastguard Worker             if (src_type == dst_type) {
548*61046927SAndroid Build Coastguard Worker                ctx->stats->mov_count++;
549*61046927SAndroid Build Coastguard Worker             } else {
550*61046927SAndroid Build Coastguard Worker                ctx->stats->cov_count++;
551*61046927SAndroid Build Coastguard Worker             }
552*61046927SAndroid Build Coastguard Worker          }
553*61046927SAndroid Build Coastguard Worker       }
554*61046927SAndroid Build Coastguard Worker    }
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    ctx->cur_opc_cat = opc_cat;
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker    if (debug & PRINT_RAW) {
559*61046927SAndroid Build Coastguard Worker       fprintf(ctx->out, "%s:%d:%04d:%04d[%08xx_%08xx] ", levels[ctx->level],
560*61046927SAndroid Build Coastguard Worker               opc_cat, n, ctx->extra_cycles + n, dwords[1], dwords[0]);
561*61046927SAndroid Build Coastguard Worker    }
562*61046927SAndroid Build Coastguard Worker }
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker int
disasm_a3xx_stat(uint32_t * dwords,int sizedwords,int level,FILE * out,unsigned gpu_id,struct shader_stats * stats)565*61046927SAndroid Build Coastguard Worker disasm_a3xx_stat(uint32_t *dwords, int sizedwords, int level, FILE *out,
566*61046927SAndroid Build Coastguard Worker                  unsigned gpu_id, struct shader_stats *stats)
567*61046927SAndroid Build Coastguard Worker {
568*61046927SAndroid Build Coastguard Worker    struct isa_decode_options decode_options = {
569*61046927SAndroid Build Coastguard Worker       .gpu_id = gpu_id,
570*61046927SAndroid Build Coastguard Worker       .show_errors = true,
571*61046927SAndroid Build Coastguard Worker       .max_errors = 5,
572*61046927SAndroid Build Coastguard Worker       .branch_labels = true,
573*61046927SAndroid Build Coastguard Worker       .field_cb = disasm_field_cb,
574*61046927SAndroid Build Coastguard Worker       .pre_instr_cb = disasm_instr_cb,
575*61046927SAndroid Build Coastguard Worker    };
576*61046927SAndroid Build Coastguard Worker    struct disasm_ctx ctx = {
577*61046927SAndroid Build Coastguard Worker       .out = out,
578*61046927SAndroid Build Coastguard Worker       .level = level,
579*61046927SAndroid Build Coastguard Worker       .options = &decode_options,
580*61046927SAndroid Build Coastguard Worker       .stats = stats,
581*61046927SAndroid Build Coastguard Worker       .cur_n = -1,
582*61046927SAndroid Build Coastguard Worker    };
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker    memset(stats, 0, sizeof(*stats));
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker    decode_options.cbdata = &ctx;
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker    ir3_isa_disasm(dwords, sizedwords * 4, out, &decode_options);
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker    disasm_handle_last(&ctx);
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker    if (debug & PRINT_STATS)
593*61046927SAndroid Build Coastguard Worker       print_stats(&ctx);
594*61046927SAndroid Build Coastguard Worker 
595*61046927SAndroid Build Coastguard Worker    return 0;
596*61046927SAndroid Build Coastguard Worker }
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker void
disasm_a3xx_set_debug(enum debug_t d)599*61046927SAndroid Build Coastguard Worker disasm_a3xx_set_debug(enum debug_t d)
600*61046927SAndroid Build Coastguard Worker {
601*61046927SAndroid Build Coastguard Worker    debug = d;
602*61046927SAndroid Build Coastguard Worker }
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker #include <setjmp.h>
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker static bool jmp_env_valid;
607*61046927SAndroid Build Coastguard Worker static jmp_buf jmp_env;
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker void
ir3_assert_handler(const char * expr,const char * file,int line,const char * func)610*61046927SAndroid Build Coastguard Worker ir3_assert_handler(const char *expr, const char *file, int line,
611*61046927SAndroid Build Coastguard Worker                    const char *func)
612*61046927SAndroid Build Coastguard Worker {
613*61046927SAndroid Build Coastguard Worker    mesa_loge("%s:%u: %s: Assertion `%s' failed.", file, line, func, expr);
614*61046927SAndroid Build Coastguard Worker    if (jmp_env_valid)
615*61046927SAndroid Build Coastguard Worker       longjmp(jmp_env, 1);
616*61046927SAndroid Build Coastguard Worker    abort();
617*61046927SAndroid Build Coastguard Worker }
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker #define TRY(x)                                                                 \
620*61046927SAndroid Build Coastguard Worker    do {                                                                        \
621*61046927SAndroid Build Coastguard Worker       assert(!jmp_env_valid);                                                  \
622*61046927SAndroid Build Coastguard Worker       if (setjmp(jmp_env) == 0) {                                              \
623*61046927SAndroid Build Coastguard Worker          jmp_env_valid = true;                                                 \
624*61046927SAndroid Build Coastguard Worker          x;                                                                    \
625*61046927SAndroid Build Coastguard Worker       }                                                                        \
626*61046927SAndroid Build Coastguard Worker       jmp_env_valid = false;                                                   \
627*61046927SAndroid Build Coastguard Worker    } while (0)
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker int
disasm_a3xx(uint32_t * dwords,int sizedwords,int level,FILE * out,unsigned gpu_id)630*61046927SAndroid Build Coastguard Worker disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out,
631*61046927SAndroid Build Coastguard Worker             unsigned gpu_id)
632*61046927SAndroid Build Coastguard Worker {
633*61046927SAndroid Build Coastguard Worker    struct shader_stats stats;
634*61046927SAndroid Build Coastguard Worker    return disasm_a3xx_stat(dwords, sizedwords, level, out, gpu_id, &stats);
635*61046927SAndroid Build Coastguard Worker }
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker int
try_disasm_a3xx(uint32_t * dwords,int sizedwords,int level,FILE * out,unsigned gpu_id)638*61046927SAndroid Build Coastguard Worker try_disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out,
639*61046927SAndroid Build Coastguard Worker                 unsigned gpu_id)
640*61046927SAndroid Build Coastguard Worker {
641*61046927SAndroid Build Coastguard Worker    struct shader_stats stats;
642*61046927SAndroid Build Coastguard Worker    int ret = -1;
643*61046927SAndroid Build Coastguard Worker    TRY(ret = disasm_a3xx_stat(dwords, sizedwords, level, out, gpu_id, &stats));
644*61046927SAndroid Build Coastguard Worker    return ret;
645*61046927SAndroid Build Coastguard Worker }
646