• 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 #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