Home | History | Annotate | Download | only in etnaviv
      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 (at) 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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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