Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_disasm.c
4570 views
/*1* Copyright (c) 2016 Etnaviv Project2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22* Authors:23* Christian Gmeiner <[email protected]>24*/2526#include "etnaviv_disasm.h"27#include "etnaviv_asm.h"2829#include <assert.h>30#include <stdbool.h>31#include <stdio.h>32#include <stdlib.h>3334#include "hw/isa.xml.h"35#include "util/u_math.h"36#include "util/half_float.h"3738struct instr {39/* dword0: */40uint32_t opc : 6;41uint32_t cond : 5;42uint32_t sat : 1;43uint32_t dst_use : 1;44uint32_t dst_amode : 3;45uint32_t dst_reg : 7;46uint32_t dst_comps : 4;47uint32_t tex_id : 5;4849/* dword1: */50uint32_t tex_amode : 3;51uint32_t tex_swiz : 8;52uint32_t src0_use : 1;53uint32_t src0_reg : 9;54uint32_t type_bit2 : 1;55uint32_t src0_swiz : 8;56uint32_t src0_neg : 1;57uint32_t src0_abs : 1;5859/* dword2: */60uint32_t src0_amode : 3;61uint32_t src0_rgroup : 3;62uint32_t src1_use : 1;63uint32_t src1_reg : 9;64uint32_t opcode_bit6 : 1;65uint32_t src1_swiz : 8;66uint32_t src1_neg : 1;67uint32_t src1_abs : 1;68uint32_t src1_amode : 3;69uint32_t type_bit01 : 2;7071/* dword3: */72union {73struct {74uint32_t src1_rgroup : 3;75uint32_t src2_use : 1;76uint32_t src2_reg : 9;77uint32_t sel_0 : 1;78uint32_t src2_swiz : 8;79uint32_t src2_neg : 1;80uint32_t src2_abs : 1;81uint32_t sel_1 : 1;82uint32_t src2_amode : 3;83uint32_t src2_rgroup : 3;84uint32_t dst_full : 1;85};86uint32_t dword3;87};88};89struct opc_operands {90struct etna_inst_dst *dst;91struct etna_inst_tex *tex;92struct etna_inst_src *src0;93struct etna_inst_src *src1;94struct etna_inst_src *src2;9596int imm;97};9899static void100printf_type(uint8_t type)101{102switch(type) {103case INST_TYPE_F32:104/* as f32 is the default print nothing */105break;106107case INST_TYPE_S32:108printf(".s32");109break;110111case INST_TYPE_S8:112printf(".s8");113break;114115case INST_TYPE_U16:116printf(".u16");117break;118119case INST_TYPE_F16:120printf(".f16");121break;122123case INST_TYPE_S16:124printf(".s16");125break;126127case INST_TYPE_U32:128printf(".u32");129break;130131case INST_TYPE_U8:132printf(".u8");133break;134135default:136abort();137break;138}139}140141static void142print_condition(uint8_t condition)143{144switch (condition) {145case INST_CONDITION_TRUE:146break;147148case INST_CONDITION_GT:149printf(".GT");150break;151152case INST_CONDITION_LT:153printf(".LT");154break;155156case INST_CONDITION_GE:157printf(".GE");158break;159160case INST_CONDITION_LE:161printf(".LE");162break;163164case INST_CONDITION_EQ:165printf(".EQ");166break;167168case INST_CONDITION_NE:169printf(".NE");170break;171172case INST_CONDITION_AND:173printf(".AND");174break;175176case INST_CONDITION_OR:177printf(".OR");178break;179180case INST_CONDITION_XOR:181printf(".XOR");182break;183184case INST_CONDITION_NOT:185printf(".NOT");186break;187188case INST_CONDITION_NZ:189printf(".NZ");190break;191192case INST_CONDITION_GEZ:193printf(".GEZ");194break;195196case INST_CONDITION_GZ:197printf(".GZ");198break;199200case INST_CONDITION_LEZ:201printf(".LEZ");202break;203204case INST_CONDITION_LZ:205printf(".LZ");206break;207208default:209abort();210break;211}212}213214static void215print_rgroup(uint8_t rgoup)216{217switch (rgoup) {218case INST_RGROUP_TEMP:219printf("t");220break;221222case INST_RGROUP_INTERNAL:223printf("i");224break;225226case INST_RGROUP_UNIFORM_0:227case INST_RGROUP_UNIFORM_1:228printf("u");229break;230case 4:231printf("th");232break;233}234}235236static void237print_components(uint8_t components)238{239if (components == 15)240return;241242printf(".");243if (components & INST_COMPS_X)244printf("x");245else246printf("_");247248if (components & INST_COMPS_Y)249printf("y");250else251printf("_");252253if (components & INST_COMPS_Z)254printf("z");255else256printf("_");257258if (components & INST_COMPS_W)259printf("w");260else261printf("_");262}263264static inline void265print_swiz_comp(uint8_t swiz_comp)266{267switch (swiz_comp) {268case INST_SWIZ_COMP_X:269printf("x");270break;271272case INST_SWIZ_COMP_Y:273printf("y");274break;275276case INST_SWIZ_COMP_Z:277printf("z");278break;279280case INST_SWIZ_COMP_W:281printf("w");282break;283284default:285abort();286break;287}288}289290static void291print_swiz(uint8_t swiz)292{293// if a null swizzle294if (swiz == 0xe4)295return;296297const unsigned x = swiz & 0x3;298const unsigned y = (swiz & 0x0C) >> 2;299const unsigned z = (swiz & 0x30) >> 4;300const unsigned w = (swiz & 0xc0) >> 6;301302printf(".");303print_swiz_comp(x);304print_swiz_comp(y);305print_swiz_comp(z);306print_swiz_comp(w);307}308309static void310print_amode(uint8_t amode)311{312switch (amode) {313case INST_AMODE_DIRECT:314/* nothing to output */315break;316317case INST_AMODE_ADD_A_X:318printf("[a.x]");319break;320321case INST_AMODE_ADD_A_Y:322printf("[a.y]");323break;324325case INST_AMODE_ADD_A_Z:326printf("[a.z]");327break;328329case INST_AMODE_ADD_A_W:330printf("[a.w]");331break;332333default:334abort();335break;336}337}338339static void340print_dst(struct etna_inst_dst *dst, bool sep)341{342if (dst->use) {343printf("t%u", dst->reg);344print_amode(dst->amode);345print_components(dst->write_mask);346} else {347printf("void");348}349350if (sep)351printf(", ");352}353354static void355print_tex(struct etna_inst_tex *tex, bool sep)356{357printf("tex%u", tex->id);358print_amode(tex->amode);359print_swiz(tex->swiz);360361if (sep)362printf(", ");363}364365static void366print_src(struct etna_inst_src *src, bool sep)367{368if (src->use) {369if (src->rgroup == INST_RGROUP_IMMEDIATE) {370switch (src->imm_type) {371case 0: /* float */372printf("%f", uif(src->imm_val << 12));373break;374case 1: /* signed */375printf("%d", ((int) src->imm_val << 12) >> 12);376break;377case 2: /* unsigned */378printf("%d", src->imm_val);379break;380case 3: /* 16-bit */381printf("%f/%.5X", _mesa_half_to_float(src->imm_val), src->imm_val);382break;383}384} else {385if (src->neg)386printf("-");387388if (src->abs)389printf("|");390391if (src->rgroup == INST_RGROUP_UNIFORM_1)392src->reg += 128;393394print_rgroup(src->rgroup);395printf("%u", src->reg);396print_amode(src->amode);397print_swiz(src->swiz);398399if (src->abs)400printf("|");401}402} else {403printf("void");404}405406if (sep)407printf(", ");408}409410static void411print_opc_default(struct opc_operands *operands)412{413print_dst(operands->dst, true);414print_src(operands->src0, true);415print_src(operands->src1, true);416print_src(operands->src2, false);417}418419static void420print_opc_mov(struct opc_operands *operands)421{422// dst (areg)423printf("a%u", operands->dst->reg);424print_components(operands->dst->write_mask);425printf(", ");426427print_src(operands->src0, true);428print_src(operands->src1, true);429print_src(operands->src2, false);430}431432static void433print_opc_tex(struct opc_operands *operands)434{435print_dst(operands->dst, true);436print_tex(operands->tex, true);437print_src(operands->src0, true);438print_src(operands->src1, true);439print_src(operands->src2, false);440}441442static void443print_opc_imm(struct opc_operands *operands)444{445print_dst(operands->dst, true);446print_src(operands->src0, true);447print_src(operands->src1, true);448printf("label_%04d", operands->imm);449}450451#define OPC_BITS 7452453static const struct opc_info {454const char *name;455void (*print)(struct opc_operands *operands);456} opcs[1 << OPC_BITS] = {457#define OPC(opc) [INST_OPCODE_##opc] = {#opc, print_opc_default}458#define OPC_MOV(opc) [INST_OPCODE_##opc] = {#opc, print_opc_mov}459#define OPC_TEX(opc) [INST_OPCODE_##opc] = {#opc, print_opc_tex}460#define OPC_IMM(opc) [INST_OPCODE_##opc] = {#opc, print_opc_imm}461OPC(NOP),462OPC(ADD),463OPC(MAD),464OPC(MUL),465OPC(DST),466OPC(DP3),467OPC(DP4),468OPC(DSX),469OPC(DSY),470OPC(MOV),471OPC_MOV(MOVAR),472OPC_MOV(MOVAF),473OPC_MOV(MOVAI),474OPC(RCP),475OPC(RSQ),476OPC(LITP),477OPC(SELECT),478OPC(SET),479OPC(EXP),480OPC(LOG),481OPC(FRC),482OPC_IMM(CALL),483OPC(RET),484OPC_IMM(BRANCH),485OPC_TEX(TEXKILL),486OPC_TEX(TEXLD),487OPC_TEX(TEXLDB),488OPC_TEX(TEXLDD),489OPC_TEX(TEXLDL),490OPC_TEX(TEXLDPCF),491OPC_TEX(TEXLDLPCF),492OPC_TEX(TEXLDGPCF),493OPC(REP),494OPC(ENDREP),495OPC(LOOP),496OPC(ENDLOOP),497OPC(SQRT),498OPC(SIN),499OPC(COS),500OPC(FLOOR),501OPC(CEIL),502OPC(SIGN),503OPC(I2F),504OPC(F2I),505OPC(CMP),506OPC(LOAD),507OPC(STORE),508OPC(IMULLO0),509OPC(IMULHI0),510OPC(IMADLO0),511OPC(IMADHI0),512OPC(LEADZERO),513OPC(LSHIFT),514OPC(RSHIFT),515OPC(ROTATE),516OPC(OR),517OPC(AND),518OPC(XOR),519OPC(NOT),520OPC(DP2),521OPC(DIV),522OPC(IABS),523};524525static void526print_instr(uint32_t *dwords, int n, enum debug_t debug)527{528struct instr *instr = (struct instr *)dwords;529const unsigned opc = instr->opc | (instr->opcode_bit6 << 6);530const char *name = opcs[opc].name;531532printf("%04d: ", n);533if (debug & PRINT_RAW)534printf("%08x %08x %08x %08x ", dwords[0], dwords[1], dwords[2],535dwords[3]);536537if (name) {538539struct etna_inst_dst dst = {540.use = instr->dst_use,541.amode = instr->dst_amode,542.reg = instr->dst_reg,543.write_mask = instr->dst_comps544};545546struct etna_inst_tex tex = {547.id = instr->tex_id,548.amode = instr->tex_amode,549.swiz = instr->tex_swiz,550};551552struct etna_inst_src src0 = {553.use = instr->src0_use,554.neg = instr->src0_neg,555.abs = instr->src0_abs,556.rgroup = instr->src0_rgroup,557.reg = instr->src0_reg,558.swiz = instr->src0_swiz,559.amode = instr->src0_amode,560};561562struct etna_inst_src src1 = {563.use = instr->src1_use,564.neg = instr->src1_neg,565.abs = instr->src1_abs,566.rgroup = instr->src1_rgroup,567.reg = instr->src1_reg,568.swiz = instr->src1_swiz,569.amode = instr->src1_amode,570};571572struct etna_inst_src src2 = {573.use = instr->src2_use,574.neg = instr->src2_neg,575.abs = instr->src2_abs,576.rgroup = instr->src2_rgroup,577.reg = instr->src2_reg,578.swiz = instr->src2_swiz,579.amode = instr->src2_amode,580};581582int imm = (instr->dword3 & VIV_ISA_WORD_3_SRC2_IMM__MASK)583>> VIV_ISA_WORD_3_SRC2_IMM__SHIFT;584585struct opc_operands operands = {586.dst = &dst,587.tex = &tex,588.src0 = &src0,589.src1 = &src1,590.src2 = &src2,591.imm = imm,592};593594uint8_t type = instr->type_bit01 | (instr->type_bit2 << 2);595596printf("%s", name);597printf_type(type);598if (instr->sat)599printf(".SAT");600print_condition(instr->cond);601printf(" ");602if (instr->sel_0)603printf("SEL_0 ");604if (instr->sel_1)605printf("SEL_1 ");606if (instr->dst_full)607printf("DST_FULL ");608opcs[opc].print(&operands);609} else {610printf("unknown (%d)", instr->opc);611}612613printf("\n");614}615616void617etna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug)618{619unsigned i;620621assert((sizedwords % 2) == 0);622623for (i = 0; i < sizedwords; i += 4)624print_instr(&dwords[i], i / 4, debug);625}626627628