~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/freedreno/ir3/disasm-a3xx.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

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