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 <christian.gmeiner@gmail.com>
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
printf_type(uint8_t type)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
print_condition(uint8_t condition)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
print_rgroup(uint8_t rgoup)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
print_components(uint8_t components)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
print_swiz_comp(uint8_t swiz_comp)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
print_swiz(uint8_t swiz)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
print_amode(uint8_t amode)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
print_dst(struct etna_inst_dst * dst,bool sep)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
print_tex(struct etna_inst_tex * tex,bool sep)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
print_src(struct etna_inst_src * src,bool sep)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
print_opc_default(struct opc_operands * operands)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
print_opc_mov(struct opc_operands * operands)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
print_opc_tex(struct opc_operands * operands)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
print_opc_imm(struct opc_operands * operands)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
print_instr(uint32_t * dwords,int n,enum debug_t debug)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
etna_disasm(uint32_t * dwords,int sizedwords,enum debug_t debug)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