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