Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_disasm.c
4570 views
1
/*
2
* Copyright (c) 2016 Etnaviv Project
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, sub license,
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
12
* next paragraph) shall be included in all copies or substantial portions
13
* of the 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 NON-INFRINGEMENT. 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
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
* DEALINGS IN THE SOFTWARE.
22
*
23
* Authors:
24
* Christian Gmeiner <[email protected]>
25
*/
26
27
#include "etnaviv_disasm.h"
28
#include "etnaviv_asm.h"
29
30
#include <assert.h>
31
#include <stdbool.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
35
#include "hw/isa.xml.h"
36
#include "util/u_math.h"
37
#include "util/half_float.h"
38
39
struct instr {
40
/* dword0: */
41
uint32_t opc : 6;
42
uint32_t cond : 5;
43
uint32_t sat : 1;
44
uint32_t dst_use : 1;
45
uint32_t dst_amode : 3;
46
uint32_t dst_reg : 7;
47
uint32_t dst_comps : 4;
48
uint32_t tex_id : 5;
49
50
/* dword1: */
51
uint32_t tex_amode : 3;
52
uint32_t tex_swiz : 8;
53
uint32_t src0_use : 1;
54
uint32_t src0_reg : 9;
55
uint32_t type_bit2 : 1;
56
uint32_t src0_swiz : 8;
57
uint32_t src0_neg : 1;
58
uint32_t src0_abs : 1;
59
60
/* dword2: */
61
uint32_t src0_amode : 3;
62
uint32_t src0_rgroup : 3;
63
uint32_t src1_use : 1;
64
uint32_t src1_reg : 9;
65
uint32_t opcode_bit6 : 1;
66
uint32_t src1_swiz : 8;
67
uint32_t src1_neg : 1;
68
uint32_t src1_abs : 1;
69
uint32_t src1_amode : 3;
70
uint32_t type_bit01 : 2;
71
72
/* dword3: */
73
union {
74
struct {
75
uint32_t src1_rgroup : 3;
76
uint32_t src2_use : 1;
77
uint32_t src2_reg : 9;
78
uint32_t sel_0 : 1;
79
uint32_t src2_swiz : 8;
80
uint32_t src2_neg : 1;
81
uint32_t src2_abs : 1;
82
uint32_t sel_1 : 1;
83
uint32_t src2_amode : 3;
84
uint32_t src2_rgroup : 3;
85
uint32_t dst_full : 1;
86
};
87
uint32_t dword3;
88
};
89
};
90
struct opc_operands {
91
struct etna_inst_dst *dst;
92
struct etna_inst_tex *tex;
93
struct etna_inst_src *src0;
94
struct etna_inst_src *src1;
95
struct etna_inst_src *src2;
96
97
int imm;
98
};
99
100
static void
101
printf_type(uint8_t type)
102
{
103
switch(type) {
104
case INST_TYPE_F32:
105
/* as f32 is the default print nothing */
106
break;
107
108
case INST_TYPE_S32:
109
printf(".s32");
110
break;
111
112
case INST_TYPE_S8:
113
printf(".s8");
114
break;
115
116
case INST_TYPE_U16:
117
printf(".u16");
118
break;
119
120
case INST_TYPE_F16:
121
printf(".f16");
122
break;
123
124
case INST_TYPE_S16:
125
printf(".s16");
126
break;
127
128
case INST_TYPE_U32:
129
printf(".u32");
130
break;
131
132
case INST_TYPE_U8:
133
printf(".u8");
134
break;
135
136
default:
137
abort();
138
break;
139
}
140
}
141
142
static void
143
print_condition(uint8_t condition)
144
{
145
switch (condition) {
146
case INST_CONDITION_TRUE:
147
break;
148
149
case INST_CONDITION_GT:
150
printf(".GT");
151
break;
152
153
case INST_CONDITION_LT:
154
printf(".LT");
155
break;
156
157
case INST_CONDITION_GE:
158
printf(".GE");
159
break;
160
161
case INST_CONDITION_LE:
162
printf(".LE");
163
break;
164
165
case INST_CONDITION_EQ:
166
printf(".EQ");
167
break;
168
169
case INST_CONDITION_NE:
170
printf(".NE");
171
break;
172
173
case INST_CONDITION_AND:
174
printf(".AND");
175
break;
176
177
case INST_CONDITION_OR:
178
printf(".OR");
179
break;
180
181
case INST_CONDITION_XOR:
182
printf(".XOR");
183
break;
184
185
case INST_CONDITION_NOT:
186
printf(".NOT");
187
break;
188
189
case INST_CONDITION_NZ:
190
printf(".NZ");
191
break;
192
193
case INST_CONDITION_GEZ:
194
printf(".GEZ");
195
break;
196
197
case INST_CONDITION_GZ:
198
printf(".GZ");
199
break;
200
201
case INST_CONDITION_LEZ:
202
printf(".LEZ");
203
break;
204
205
case INST_CONDITION_LZ:
206
printf(".LZ");
207
break;
208
209
default:
210
abort();
211
break;
212
}
213
}
214
215
static void
216
print_rgroup(uint8_t rgoup)
217
{
218
switch (rgoup) {
219
case INST_RGROUP_TEMP:
220
printf("t");
221
break;
222
223
case INST_RGROUP_INTERNAL:
224
printf("i");
225
break;
226
227
case INST_RGROUP_UNIFORM_0:
228
case INST_RGROUP_UNIFORM_1:
229
printf("u");
230
break;
231
case 4:
232
printf("th");
233
break;
234
}
235
}
236
237
static void
238
print_components(uint8_t components)
239
{
240
if (components == 15)
241
return;
242
243
printf(".");
244
if (components & INST_COMPS_X)
245
printf("x");
246
else
247
printf("_");
248
249
if (components & INST_COMPS_Y)
250
printf("y");
251
else
252
printf("_");
253
254
if (components & INST_COMPS_Z)
255
printf("z");
256
else
257
printf("_");
258
259
if (components & INST_COMPS_W)
260
printf("w");
261
else
262
printf("_");
263
}
264
265
static inline void
266
print_swiz_comp(uint8_t swiz_comp)
267
{
268
switch (swiz_comp) {
269
case INST_SWIZ_COMP_X:
270
printf("x");
271
break;
272
273
case INST_SWIZ_COMP_Y:
274
printf("y");
275
break;
276
277
case INST_SWIZ_COMP_Z:
278
printf("z");
279
break;
280
281
case INST_SWIZ_COMP_W:
282
printf("w");
283
break;
284
285
default:
286
abort();
287
break;
288
}
289
}
290
291
static void
292
print_swiz(uint8_t swiz)
293
{
294
// if a null swizzle
295
if (swiz == 0xe4)
296
return;
297
298
const unsigned x = swiz & 0x3;
299
const unsigned y = (swiz & 0x0C) >> 2;
300
const unsigned z = (swiz & 0x30) >> 4;
301
const unsigned w = (swiz & 0xc0) >> 6;
302
303
printf(".");
304
print_swiz_comp(x);
305
print_swiz_comp(y);
306
print_swiz_comp(z);
307
print_swiz_comp(w);
308
}
309
310
static void
311
print_amode(uint8_t amode)
312
{
313
switch (amode) {
314
case INST_AMODE_DIRECT:
315
/* nothing to output */
316
break;
317
318
case INST_AMODE_ADD_A_X:
319
printf("[a.x]");
320
break;
321
322
case INST_AMODE_ADD_A_Y:
323
printf("[a.y]");
324
break;
325
326
case INST_AMODE_ADD_A_Z:
327
printf("[a.z]");
328
break;
329
330
case INST_AMODE_ADD_A_W:
331
printf("[a.w]");
332
break;
333
334
default:
335
abort();
336
break;
337
}
338
}
339
340
static void
341
print_dst(struct etna_inst_dst *dst, bool sep)
342
{
343
if (dst->use) {
344
printf("t%u", dst->reg);
345
print_amode(dst->amode);
346
print_components(dst->write_mask);
347
} else {
348
printf("void");
349
}
350
351
if (sep)
352
printf(", ");
353
}
354
355
static void
356
print_tex(struct etna_inst_tex *tex, bool sep)
357
{
358
printf("tex%u", tex->id);
359
print_amode(tex->amode);
360
print_swiz(tex->swiz);
361
362
if (sep)
363
printf(", ");
364
}
365
366
static void
367
print_src(struct etna_inst_src *src, bool sep)
368
{
369
if (src->use) {
370
if (src->rgroup == INST_RGROUP_IMMEDIATE) {
371
switch (src->imm_type) {
372
case 0: /* float */
373
printf("%f", uif(src->imm_val << 12));
374
break;
375
case 1: /* signed */
376
printf("%d", ((int) src->imm_val << 12) >> 12);
377
break;
378
case 2: /* unsigned */
379
printf("%d", src->imm_val);
380
break;
381
case 3: /* 16-bit */
382
printf("%f/%.5X", _mesa_half_to_float(src->imm_val), src->imm_val);
383
break;
384
}
385
} else {
386
if (src->neg)
387
printf("-");
388
389
if (src->abs)
390
printf("|");
391
392
if (src->rgroup == INST_RGROUP_UNIFORM_1)
393
src->reg += 128;
394
395
print_rgroup(src->rgroup);
396
printf("%u", src->reg);
397
print_amode(src->amode);
398
print_swiz(src->swiz);
399
400
if (src->abs)
401
printf("|");
402
}
403
} else {
404
printf("void");
405
}
406
407
if (sep)
408
printf(", ");
409
}
410
411
static void
412
print_opc_default(struct opc_operands *operands)
413
{
414
print_dst(operands->dst, true);
415
print_src(operands->src0, true);
416
print_src(operands->src1, true);
417
print_src(operands->src2, false);
418
}
419
420
static void
421
print_opc_mov(struct opc_operands *operands)
422
{
423
// dst (areg)
424
printf("a%u", operands->dst->reg);
425
print_components(operands->dst->write_mask);
426
printf(", ");
427
428
print_src(operands->src0, true);
429
print_src(operands->src1, true);
430
print_src(operands->src2, false);
431
}
432
433
static void
434
print_opc_tex(struct opc_operands *operands)
435
{
436
print_dst(operands->dst, true);
437
print_tex(operands->tex, true);
438
print_src(operands->src0, true);
439
print_src(operands->src1, true);
440
print_src(operands->src2, false);
441
}
442
443
static void
444
print_opc_imm(struct opc_operands *operands)
445
{
446
print_dst(operands->dst, true);
447
print_src(operands->src0, true);
448
print_src(operands->src1, true);
449
printf("label_%04d", operands->imm);
450
}
451
452
#define OPC_BITS 7
453
454
static const struct opc_info {
455
const char *name;
456
void (*print)(struct opc_operands *operands);
457
} opcs[1 << OPC_BITS] = {
458
#define OPC(opc) [INST_OPCODE_##opc] = {#opc, print_opc_default}
459
#define OPC_MOV(opc) [INST_OPCODE_##opc] = {#opc, print_opc_mov}
460
#define OPC_TEX(opc) [INST_OPCODE_##opc] = {#opc, print_opc_tex}
461
#define OPC_IMM(opc) [INST_OPCODE_##opc] = {#opc, print_opc_imm}
462
OPC(NOP),
463
OPC(ADD),
464
OPC(MAD),
465
OPC(MUL),
466
OPC(DST),
467
OPC(DP3),
468
OPC(DP4),
469
OPC(DSX),
470
OPC(DSY),
471
OPC(MOV),
472
OPC_MOV(MOVAR),
473
OPC_MOV(MOVAF),
474
OPC_MOV(MOVAI),
475
OPC(RCP),
476
OPC(RSQ),
477
OPC(LITP),
478
OPC(SELECT),
479
OPC(SET),
480
OPC(EXP),
481
OPC(LOG),
482
OPC(FRC),
483
OPC_IMM(CALL),
484
OPC(RET),
485
OPC_IMM(BRANCH),
486
OPC_TEX(TEXKILL),
487
OPC_TEX(TEXLD),
488
OPC_TEX(TEXLDB),
489
OPC_TEX(TEXLDD),
490
OPC_TEX(TEXLDL),
491
OPC_TEX(TEXLDPCF),
492
OPC_TEX(TEXLDLPCF),
493
OPC_TEX(TEXLDGPCF),
494
OPC(REP),
495
OPC(ENDREP),
496
OPC(LOOP),
497
OPC(ENDLOOP),
498
OPC(SQRT),
499
OPC(SIN),
500
OPC(COS),
501
OPC(FLOOR),
502
OPC(CEIL),
503
OPC(SIGN),
504
OPC(I2F),
505
OPC(F2I),
506
OPC(CMP),
507
OPC(LOAD),
508
OPC(STORE),
509
OPC(IMULLO0),
510
OPC(IMULHI0),
511
OPC(IMADLO0),
512
OPC(IMADHI0),
513
OPC(LEADZERO),
514
OPC(LSHIFT),
515
OPC(RSHIFT),
516
OPC(ROTATE),
517
OPC(OR),
518
OPC(AND),
519
OPC(XOR),
520
OPC(NOT),
521
OPC(DP2),
522
OPC(DIV),
523
OPC(IABS),
524
};
525
526
static void
527
print_instr(uint32_t *dwords, int n, enum debug_t debug)
528
{
529
struct instr *instr = (struct instr *)dwords;
530
const unsigned opc = instr->opc | (instr->opcode_bit6 << 6);
531
const char *name = opcs[opc].name;
532
533
printf("%04d: ", n);
534
if (debug & PRINT_RAW)
535
printf("%08x %08x %08x %08x ", dwords[0], dwords[1], dwords[2],
536
dwords[3]);
537
538
if (name) {
539
540
struct etna_inst_dst dst = {
541
.use = instr->dst_use,
542
.amode = instr->dst_amode,
543
.reg = instr->dst_reg,
544
.write_mask = instr->dst_comps
545
};
546
547
struct etna_inst_tex tex = {
548
.id = instr->tex_id,
549
.amode = instr->tex_amode,
550
.swiz = instr->tex_swiz,
551
};
552
553
struct etna_inst_src src0 = {
554
.use = instr->src0_use,
555
.neg = instr->src0_neg,
556
.abs = instr->src0_abs,
557
.rgroup = instr->src0_rgroup,
558
.reg = instr->src0_reg,
559
.swiz = instr->src0_swiz,
560
.amode = instr->src0_amode,
561
};
562
563
struct etna_inst_src src1 = {
564
.use = instr->src1_use,
565
.neg = instr->src1_neg,
566
.abs = instr->src1_abs,
567
.rgroup = instr->src1_rgroup,
568
.reg = instr->src1_reg,
569
.swiz = instr->src1_swiz,
570
.amode = instr->src1_amode,
571
};
572
573
struct etna_inst_src src2 = {
574
.use = instr->src2_use,
575
.neg = instr->src2_neg,
576
.abs = instr->src2_abs,
577
.rgroup = instr->src2_rgroup,
578
.reg = instr->src2_reg,
579
.swiz = instr->src2_swiz,
580
.amode = instr->src2_amode,
581
};
582
583
int imm = (instr->dword3 & VIV_ISA_WORD_3_SRC2_IMM__MASK)
584
>> VIV_ISA_WORD_3_SRC2_IMM__SHIFT;
585
586
struct opc_operands operands = {
587
.dst = &dst,
588
.tex = &tex,
589
.src0 = &src0,
590
.src1 = &src1,
591
.src2 = &src2,
592
.imm = imm,
593
};
594
595
uint8_t type = instr->type_bit01 | (instr->type_bit2 << 2);
596
597
printf("%s", name);
598
printf_type(type);
599
if (instr->sat)
600
printf(".SAT");
601
print_condition(instr->cond);
602
printf(" ");
603
if (instr->sel_0)
604
printf("SEL_0 ");
605
if (instr->sel_1)
606
printf("SEL_1 ");
607
if (instr->dst_full)
608
printf("DST_FULL ");
609
opcs[opc].print(&operands);
610
} else {
611
printf("unknown (%d)", instr->opc);
612
}
613
614
printf("\n");
615
}
616
617
void
618
etna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug)
619
{
620
unsigned i;
621
622
assert((sizedwords % 2) == 0);
623
624
for (i = 0; i < sizedwords; i += 4)
625
print_instr(&dwords[i], i / 4, debug);
626
}
627
628