Path: blob/21.2-virgl/src/gallium/drivers/vc4/vc4_qpu_disasm.c
4570 views
/*1* Copyright © 2014 Broadcom2*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, sublicense,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 the next11* paragraph) shall be included in all copies or substantial portions of the12* 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 NONINFRINGEMENT. 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 OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include <stdbool.h>24#include <stdio.h>2526#include "vc4_qpu.h"27#include "vc4_qpu_defines.h"2829static const char *qpu_add_opcodes[] = {30[QPU_A_NOP] = "nop",31[QPU_A_FADD] = "fadd",32[QPU_A_FSUB] = "fsub",33[QPU_A_FMIN] = "fmin",34[QPU_A_FMAX] = "fmax",35[QPU_A_FMINABS] = "fminabs",36[QPU_A_FMAXABS] = "fmaxabs",37[QPU_A_FTOI] = "ftoi",38[QPU_A_ITOF] = "itof",39[QPU_A_ADD] = "add",40[QPU_A_SUB] = "sub",41[QPU_A_SHR] = "shr",42[QPU_A_ASR] = "asr",43[QPU_A_ROR] = "ror",44[QPU_A_SHL] = "shl",45[QPU_A_MIN] = "min",46[QPU_A_MAX] = "max",47[QPU_A_AND] = "and",48[QPU_A_OR] = "or",49[QPU_A_XOR] = "xor",50[QPU_A_NOT] = "not",51[QPU_A_CLZ] = "clz",52[QPU_A_V8ADDS] = "v8adds",53[QPU_A_V8SUBS] = "v8subs",54};5556static const char *qpu_mul_opcodes[] = {57[QPU_M_NOP] = "nop",58[QPU_M_FMUL] = "fmul",59[QPU_M_MUL24] = "mul24",60[QPU_M_V8MULD] = "v8muld",61[QPU_M_V8MIN] = "v8min",62[QPU_M_V8MAX] = "v8max",63[QPU_M_V8ADDS] = "v8adds",64[QPU_M_V8SUBS] = "v8subs",65};6667static const char *qpu_sig[] = {68[QPU_SIG_SW_BREAKPOINT] = "sig_brk",69[QPU_SIG_NONE] = "",70[QPU_SIG_THREAD_SWITCH] = "sig_switch",71[QPU_SIG_PROG_END] = "sig_end",72[QPU_SIG_WAIT_FOR_SCOREBOARD] = "sig_wait_score",73[QPU_SIG_SCOREBOARD_UNLOCK] = "sig_unlock_score",74[QPU_SIG_LAST_THREAD_SWITCH] = "sig_thread_switch",75[QPU_SIG_COVERAGE_LOAD] = "sig_coverage_load",76[QPU_SIG_COLOR_LOAD] = "sig_color_load",77[QPU_SIG_COLOR_LOAD_END] = "sig_color_load_end",78[QPU_SIG_LOAD_TMU0] = "load_tmu0",79[QPU_SIG_LOAD_TMU1] = "load_tmu1",80[QPU_SIG_ALPHA_MASK_LOAD] = "sig_alpha_mask_load",81[QPU_SIG_SMALL_IMM] = "sig_small_imm",82[QPU_SIG_LOAD_IMM] = "sig_load_imm",83[QPU_SIG_BRANCH] = "sig_branch",84};8586static const char *qpu_pack_mul[] = {87[QPU_PACK_MUL_NOP] = "",88[QPU_PACK_MUL_8888] = ".8888",89[QPU_PACK_MUL_8A] = ".8a",90[QPU_PACK_MUL_8B] = ".8b",91[QPU_PACK_MUL_8C] = ".8c",92[QPU_PACK_MUL_8D] = ".8d",93};9495/* The QPU unpack for A and R4 files can be described the same, it's just that96* the R4 variants are convert-to-float only, with no int support.97*/98static const char *qpu_unpack[] = {99[QPU_UNPACK_NOP] = "",100[QPU_UNPACK_16A] = "16a",101[QPU_UNPACK_16B] = "16b",102[QPU_UNPACK_8D_REP] = "8d_rep",103[QPU_UNPACK_8A] = "8a",104[QPU_UNPACK_8B] = "8b",105[QPU_UNPACK_8C] = "8c",106[QPU_UNPACK_8D] = "8d",107};108109static const char *special_read_a[] = {110"uni",111NULL,112NULL,113"vary",114NULL,115NULL,116"elem",117"nop",118NULL,119"x_pix",120"ms_flags",121NULL,122NULL,123NULL,124NULL,125NULL,126"vpm_read",127"vpm_ld_busy",128"vpm_ld_wait",129"mutex_acq"130};131132static const char *special_read_b[] = {133"uni",134NULL,135NULL,136"vary",137NULL,138NULL,139"qpu",140"nop",141NULL,142"y_pix",143"rev_flag",144NULL,145NULL,146NULL,147NULL,148NULL,149"vpm_read",150"vpm_st_busy",151"vpm_st_wait",152"mutex_acq"153};154155/**156* This has the B-file descriptions for register writes.157*158* Since only a couple of regs are different between A and B, the A overrides159* are in get_special_write_desc().160*/161static const char *special_write[] = {162[QPU_W_ACC0] = "r0",163[QPU_W_ACC1] = "r1",164[QPU_W_ACC2] = "r2",165[QPU_W_ACC3] = "r3",166[QPU_W_TMU_NOSWAP] = "tmu_noswap",167[QPU_W_ACC5] = "r5",168[QPU_W_HOST_INT] = "host_int",169[QPU_W_NOP] = "nop",170[QPU_W_UNIFORMS_ADDRESS] = "uniforms_addr",171[QPU_W_QUAD_XY] = "quad_y",172[QPU_W_MS_FLAGS] = "ms_flags",173[QPU_W_TLB_STENCIL_SETUP] = "tlb_stencil_setup",174[QPU_W_TLB_Z] = "tlb_z",175[QPU_W_TLB_COLOR_MS] = "tlb_color_ms",176[QPU_W_TLB_COLOR_ALL] = "tlb_color_all",177[QPU_W_VPM] = "vpm",178[QPU_W_VPMVCD_SETUP] = "vw_setup",179[QPU_W_VPM_ADDR] = "vw_addr",180[QPU_W_MUTEX_RELEASE] = "mutex_release",181[QPU_W_SFU_RECIP] = "sfu_recip",182[QPU_W_SFU_RECIPSQRT] = "sfu_recipsqrt",183[QPU_W_SFU_EXP] = "sfu_exp",184[QPU_W_SFU_LOG] = "sfu_log",185[QPU_W_TMU0_S] = "tmu0_s",186[QPU_W_TMU0_T] = "tmu0_t",187[QPU_W_TMU0_R] = "tmu0_r",188[QPU_W_TMU0_B] = "tmu0_b",189[QPU_W_TMU1_S] = "tmu1_s",190[QPU_W_TMU1_T] = "tmu1_t",191[QPU_W_TMU1_R] = "tmu1_r",192[QPU_W_TMU1_B] = "tmu1_b",193};194195static const char *qpu_pack_a[] = {196[QPU_PACK_A_NOP] = "",197[QPU_PACK_A_16A] = ".16a",198[QPU_PACK_A_16B] = ".16b",199[QPU_PACK_A_8888] = ".8888",200[QPU_PACK_A_8A] = ".8a",201[QPU_PACK_A_8B] = ".8b",202[QPU_PACK_A_8C] = ".8c",203[QPU_PACK_A_8D] = ".8d",204205[QPU_PACK_A_32_SAT] = ".sat",206[QPU_PACK_A_16A_SAT] = ".16a.sat",207[QPU_PACK_A_16B_SAT] = ".16b.sat",208[QPU_PACK_A_8888_SAT] = ".8888.sat",209[QPU_PACK_A_8A_SAT] = ".8a.sat",210[QPU_PACK_A_8B_SAT] = ".8b.sat",211[QPU_PACK_A_8C_SAT] = ".8c.sat",212[QPU_PACK_A_8D_SAT] = ".8d.sat",213};214215static const char *qpu_cond[] = {216[QPU_COND_NEVER] = ".never",217[QPU_COND_ALWAYS] = "",218[QPU_COND_ZS] = ".zs",219[QPU_COND_ZC] = ".zc",220[QPU_COND_NS] = ".ns",221[QPU_COND_NC] = ".nc",222[QPU_COND_CS] = ".cs",223[QPU_COND_CC] = ".cc",224};225226static const char *qpu_cond_branch[] = {227[QPU_COND_BRANCH_ALL_ZS] = ".all_zs",228[QPU_COND_BRANCH_ALL_ZC] = ".all_zc",229[QPU_COND_BRANCH_ANY_ZS] = ".any_zs",230[QPU_COND_BRANCH_ANY_ZC] = ".any_zc",231[QPU_COND_BRANCH_ALL_NS] = ".all_ns",232[QPU_COND_BRANCH_ALL_NC] = ".all_nc",233[QPU_COND_BRANCH_ANY_NS] = ".any_ns",234[QPU_COND_BRANCH_ANY_NC] = ".any_nc",235[QPU_COND_BRANCH_ALL_CS] = ".all_cs",236[QPU_COND_BRANCH_ALL_CC] = ".all_cc",237[QPU_COND_BRANCH_ANY_CS] = ".any_cs",238[QPU_COND_BRANCH_ANY_CC] = ".any_cc",239[QPU_COND_BRANCH_ALWAYS] = "",240};241242#define DESC(array, index) \243((index >= ARRAY_SIZE(array) || !(array)[index]) ? \244"???" : (array)[index])245246static const char *247get_special_write_desc(int reg, bool is_a)248{249if (is_a) {250switch (reg) {251case QPU_W_QUAD_XY:252return "quad_x";253case QPU_W_VPMVCD_SETUP:254return "vr_setup";255case QPU_W_VPM_ADDR:256return "vr_addr";257}258}259260return special_write[reg];261}262263void264vc4_qpu_disasm_pack_mul(FILE *out, uint32_t pack)265{266fprintf(out, "%s", DESC(qpu_pack_mul, pack));267}268269void270vc4_qpu_disasm_pack_a(FILE *out, uint32_t pack)271{272fprintf(out, "%s", DESC(qpu_pack_a, pack));273}274275void276vc4_qpu_disasm_unpack(FILE *out, uint32_t unpack)277{278if (unpack != QPU_UNPACK_NOP)279fprintf(out, ".%s", DESC(qpu_unpack, unpack));280}281282void283vc4_qpu_disasm_cond(FILE *out, uint32_t cond)284{285fprintf(out, "%s", DESC(qpu_cond, cond));286}287288void289vc4_qpu_disasm_cond_branch(FILE *out, uint32_t cond)290{291fprintf(out, "%s", DESC(qpu_cond_branch, cond));292}293294static void295print_alu_dst(uint64_t inst, bool is_mul)296{297bool is_a = is_mul == ((inst & QPU_WS) != 0);298uint32_t waddr = (is_mul ?299QPU_GET_FIELD(inst, QPU_WADDR_MUL) :300QPU_GET_FIELD(inst, QPU_WADDR_ADD));301const char *file = is_a ? "a" : "b";302uint32_t pack = QPU_GET_FIELD(inst, QPU_PACK);303304if (waddr <= 31)305fprintf(stderr, "r%s%d", file, waddr);306else if (get_special_write_desc(waddr, is_a))307fprintf(stderr, "%s", get_special_write_desc(waddr, is_a));308else309fprintf(stderr, "%s%d?", file, waddr);310311if (is_mul && (inst & QPU_PM)) {312vc4_qpu_disasm_pack_mul(stderr, pack);313} else if (is_a && !(inst & QPU_PM)) {314vc4_qpu_disasm_pack_a(stderr, pack);315}316}317318static void319print_alu_src(uint64_t inst, uint32_t mux, bool is_mul)320{321bool is_a = mux != QPU_MUX_B;322const char *file = is_a ? "a" : "b";323uint32_t raddr = (is_a ?324QPU_GET_FIELD(inst, QPU_RADDR_A) :325QPU_GET_FIELD(inst, QPU_RADDR_B));326uint32_t unpack = QPU_GET_FIELD(inst, QPU_UNPACK);327bool has_si = QPU_GET_FIELD(inst, QPU_SIG) == QPU_SIG_SMALL_IMM;328uint32_t si = QPU_GET_FIELD(inst, QPU_SMALL_IMM);329330if (mux <= QPU_MUX_R5) {331fprintf(stderr, "r%d", mux);332if (has_si && is_mul && si >= QPU_SMALL_IMM_MUL_ROT + 1)333fprintf(stderr, "+%d", si - QPU_SMALL_IMM_MUL_ROT);334} else if (!is_a && has_si) {335if (si <= 15)336fprintf(stderr, "%d", si);337else if (si <= 31)338fprintf(stderr, "%d", -16 + (si - 16));339else if (si <= 39)340fprintf(stderr, "%.1f", (float)(1 << (si - 32)));341else if (si <= 47)342fprintf(stderr, "%f", 1.0f / (1 << (48 - si)));343else344fprintf(stderr, "<bad imm %d>", si);345} else if (raddr <= 31)346fprintf(stderr, "r%s%d", file, raddr);347else {348if (is_a)349fprintf(stderr, "%s", DESC(special_read_a, raddr - 32));350else351fprintf(stderr, "%s", DESC(special_read_b, raddr - 32));352}353354if (((mux == QPU_MUX_A && !(inst & QPU_PM)) ||355(mux == QPU_MUX_R4 && (inst & QPU_PM)))) {356vc4_qpu_disasm_unpack(stderr, unpack);357}358}359360static void361print_add_op(uint64_t inst)362{363uint32_t op_add = QPU_GET_FIELD(inst, QPU_OP_ADD);364uint32_t cond = QPU_GET_FIELD(inst, QPU_COND_ADD);365bool is_mov = (op_add == QPU_A_OR &&366QPU_GET_FIELD(inst, QPU_ADD_A) ==367QPU_GET_FIELD(inst, QPU_ADD_B));368369if (is_mov)370fprintf(stderr, "mov");371else372fprintf(stderr, "%s", DESC(qpu_add_opcodes, op_add));373374if ((inst & QPU_SF) && op_add != QPU_A_NOP)375fprintf(stderr, ".sf");376377if (op_add != QPU_A_NOP)378vc4_qpu_disasm_cond(stderr, cond);379380fprintf(stderr, " ");381print_alu_dst(inst, false);382fprintf(stderr, ", ");383384print_alu_src(inst, QPU_GET_FIELD(inst, QPU_ADD_A), false);385386if (!is_mov) {387fprintf(stderr, ", ");388389print_alu_src(inst, QPU_GET_FIELD(inst, QPU_ADD_B), false);390}391}392393static void394print_mul_op(uint64_t inst)395{396uint32_t op_add = QPU_GET_FIELD(inst, QPU_OP_ADD);397uint32_t op_mul = QPU_GET_FIELD(inst, QPU_OP_MUL);398uint32_t cond = QPU_GET_FIELD(inst, QPU_COND_MUL);399bool is_mov = (op_mul == QPU_M_V8MIN &&400QPU_GET_FIELD(inst, QPU_MUL_A) ==401QPU_GET_FIELD(inst, QPU_MUL_B));402403if (is_mov)404fprintf(stderr, "mov");405else406fprintf(stderr, "%s", DESC(qpu_mul_opcodes, op_mul));407408if ((inst & QPU_SF) && op_add == QPU_A_NOP)409fprintf(stderr, ".sf");410411if (op_mul != QPU_M_NOP)412vc4_qpu_disasm_cond(stderr, cond);413414fprintf(stderr, " ");415print_alu_dst(inst, true);416fprintf(stderr, ", ");417418print_alu_src(inst, QPU_GET_FIELD(inst, QPU_MUL_A), true);419420if (!is_mov) {421fprintf(stderr, ", ");422print_alu_src(inst, QPU_GET_FIELD(inst, QPU_MUL_B), true);423}424}425426static void427print_load_imm(uint64_t inst)428{429uint32_t imm = inst;430uint32_t waddr_add = QPU_GET_FIELD(inst, QPU_WADDR_ADD);431uint32_t waddr_mul = QPU_GET_FIELD(inst, QPU_WADDR_MUL);432uint32_t cond_add = QPU_GET_FIELD(inst, QPU_COND_ADD);433uint32_t cond_mul = QPU_GET_FIELD(inst, QPU_COND_MUL);434435fprintf(stderr, "load_imm ");436437print_alu_dst(inst, false);438if (waddr_add != QPU_W_NOP)439vc4_qpu_disasm_cond(stderr, cond_add);440fprintf(stderr, ", ");441442print_alu_dst(inst, true);443if (waddr_mul != QPU_W_NOP)444vc4_qpu_disasm_cond(stderr, cond_mul);445fprintf(stderr, ", ");446447fprintf(stderr, "0x%08x (%f)", imm, uif(imm));448}449450void451vc4_qpu_disasm(const uint64_t *instructions, int num_instructions)452{453for (int i = 0; i < num_instructions; i++) {454uint64_t inst = instructions[i];455uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);456457switch (sig) {458case QPU_SIG_BRANCH:459fprintf(stderr, "branch");460vc4_qpu_disasm_cond_branch(stderr,461QPU_GET_FIELD(inst,462QPU_BRANCH_COND));463464fprintf(stderr, " %d", (uint32_t)inst);465break;466467case QPU_SIG_LOAD_IMM:468print_load_imm(inst);469break;470default:471if (sig != QPU_SIG_NONE)472fprintf(stderr, "%s ", DESC(qpu_sig, sig));473print_add_op(inst);474fprintf(stderr, " ; ");475print_mul_op(inst);476break;477}478479if (num_instructions != 1)480fprintf(stderr, "\n");481}482}483484485