• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 };
517 
518 static void
print_instr(uint32_t * dwords,int n,enum debug_t debug)519 print_instr(uint32_t *dwords, int n, enum debug_t debug)
520 {
521    struct instr *instr = (struct instr *)dwords;
522    const unsigned opc = instr->opc | (instr->opcode_bit6 << 6);
523    const char *name = opcs[opc].name;
524 
525    printf("%04d: ", n);
526    if (debug & PRINT_RAW)
527       printf("%08x %08x %08x %08x  ", dwords[0], dwords[1], dwords[2],
528              dwords[3]);
529 
530    if (name) {
531 
532       struct dst_operand dst = {
533          .use = instr->dst_use,
534          .amode = instr->dst_amode,
535          .reg = instr->dst_reg,
536          .comps = instr->dst_comps
537       };
538 
539       struct tex_operand tex = {
540          .id = instr->tex_id,
541          .amode = instr->tex_amode,
542          .swiz = instr->tex_swiz,
543       };
544 
545       struct src_operand src0 = {
546          .use = instr->src0_use,
547          .neg = instr->src0_neg,
548          .abs = instr->src0_abs,
549          .rgroup = instr->src0_rgroup,
550          .reg = instr->src0_reg,
551          .swiz = instr->src0_swiz,
552          .amode = instr->src0_amode,
553       };
554 
555       struct src_operand src1 = {
556          .use = instr->src1_use,
557          .neg = instr->src1_neg,
558          .abs = instr->src1_abs,
559          .rgroup = instr->src1_rgroup,
560          .reg = instr->src1_reg,
561          .swiz = instr->src1_swiz,
562          .amode = instr->src1_amode,
563       };
564 
565       struct src_operand src2 = {
566          .use = instr->src2_use,
567          .neg = instr->src2_neg,
568          .abs = instr->src2_abs,
569          .rgroup = instr->src2_rgroup,
570          .reg = instr->src2_reg,
571          .swiz = instr->src2_swiz,
572          .amode = instr->src2_amode,
573       };
574 
575       int imm = (instr->dword3 & VIV_ISA_WORD_3_SRC2_IMM__MASK)
576                 >> VIV_ISA_WORD_3_SRC2_IMM__SHIFT;
577 
578       struct opc_operands operands = {
579          .dst = &dst,
580          .tex = &tex,
581          .src0 = &src0,
582          .src1 = &src1,
583          .src2 = &src2,
584          .imm = imm,
585       };
586 
587       uint8_t type = instr->type_bit01 | (instr->type_bit2 << 2);
588 
589       printf("%s", name);
590       printf_type(type);
591       if (instr->sat)
592          printf(".SAT");
593       print_condition(instr->cond);
594       printf(" ");
595       opcs[opc].print(&operands);
596    } else {
597       printf("unknown (%d)", instr->opc);
598    }
599 
600    printf("\n");
601 }
602 
603 void
etna_disasm(uint32_t * dwords,int sizedwords,enum debug_t debug)604 etna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug)
605 {
606    unsigned i;
607 
608    assert((sizedwords % 2) == 0);
609 
610    for (i = 0; i < sizedwords; i += 4)
611       print_instr(&dwords[i], i / 4, debug);
612 }
613