Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/gp/disasm.c
4574 views
/*1* Copyright (c) 2018 Lima Project2*3* Copyright (c) 2013 Codethink (http://www.codethink.co.uk)4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the "Software"),7* to deal in the Software without restriction, including without limitation8* the rights to use, copy, modify, merge, publish, distribute, sub license,9* and/or sell copies of the Software, and to permit persons to whom the10* Software is furnished to do so, subject to the following conditions:11*12* The above copyright notice and this permission notice (including the13* next paragraph) shall be included in all copies or substantial portions14* of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL19* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER20* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING21* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER22* DEALINGS IN THE SOFTWARE.23*24*/2526#include "gpir.h"27#include "codegen.h"2829typedef enum {30unit_acc_0,31unit_acc_1,32unit_mul_0,33unit_mul_1,34unit_pass,35unit_complex,36num_units37} gp_unit;3839static const gpir_codegen_store_src gp_unit_to_store_src[num_units] = {40[unit_acc_0] = gpir_codegen_store_src_acc_0,41[unit_acc_1] = gpir_codegen_store_src_acc_1,42[unit_mul_0] = gpir_codegen_store_src_mul_0,43[unit_mul_1] = gpir_codegen_store_src_mul_1,44[unit_pass] = gpir_codegen_store_src_pass,45[unit_complex] = gpir_codegen_store_src_complex,46};4748static void49print_dest(gpir_codegen_instr *instr, gp_unit unit, unsigned cur_dest_index)50{51printf("^%u", cur_dest_index + unit);5253gpir_codegen_store_src src = gp_unit_to_store_src[unit];5455if (instr->store0_src_x == src ||56instr->store0_src_y == src) {57if (instr->store0_temporary) {58/* Temporary stores ignore the address, and always use whatever's59* stored in address register 0.60*/61printf("/t[addr0]");62} else {63if (instr->store0_varying)64printf("/v");65else66printf("/$");67printf("%u", instr->store0_addr);68}6970printf(".");71if (instr->store0_src_x == src)72printf("x");73if (instr->store0_src_y == src)74printf("y");75}7677if (instr->store1_src_z == src ||78instr->store1_src_w == src) {79if (instr->store1_temporary) {80printf("/t[addr0]");81} else {82if (instr->store1_varying)83printf("/v");84else85printf("/$");86printf("%u", instr->store1_addr);87}8889printf(".");90if (instr->store1_src_z == src)91printf("z");92if (instr->store1_src_w == src)93printf("w");94}9596if (unit == unit_complex) {97switch (instr->complex_op) {98case gpir_codegen_complex_op_temp_store_addr:99printf("/addr0");100break;101case gpir_codegen_complex_op_temp_load_addr_0:102printf("/addr1");103break;104case gpir_codegen_complex_op_temp_load_addr_1:105printf("/addr2");106break;107case gpir_codegen_complex_op_temp_load_addr_2:108printf("/addr3");109break;110default:111break;112}113}114}115116static void117print_src(gpir_codegen_src src, gp_unit unit, unsigned unit_src_num,118gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,119unsigned cur_dest_index)120{121switch (src) {122case gpir_codegen_src_attrib_x:123case gpir_codegen_src_attrib_y:124case gpir_codegen_src_attrib_z:125case gpir_codegen_src_attrib_w:126printf("%c%d.%c", instr->register0_attribute ? 'a' : '$',127instr->register0_addr, "xyzw"[src - gpir_codegen_src_attrib_x]);128break;129130case gpir_codegen_src_register_x:131case gpir_codegen_src_register_y:132case gpir_codegen_src_register_z:133case gpir_codegen_src_register_w:134printf("$%d.%c", instr->register1_addr,135"xyzw"[src - gpir_codegen_src_register_x]);136break;137138case gpir_codegen_src_unknown_0:139case gpir_codegen_src_unknown_1:140case gpir_codegen_src_unknown_2:141case gpir_codegen_src_unknown_3:142printf("unknown%d", src - gpir_codegen_src_unknown_0);143break;144145case gpir_codegen_src_load_x:146case gpir_codegen_src_load_y:147case gpir_codegen_src_load_z:148case gpir_codegen_src_load_w:149printf("t[%d", instr->load_addr);150switch (instr->load_offset) {151case gpir_codegen_load_off_ld_addr_0:152printf("+addr1");153break;154case gpir_codegen_load_off_ld_addr_1:155printf("+addr2");156break;157case gpir_codegen_load_off_ld_addr_2:158printf("+addr3");159break;160case gpir_codegen_load_off_none:161break;162default:163printf("+unk%d", instr->load_offset);164}165printf("].%c", "xyzw"[src - gpir_codegen_src_load_x]);166break;167168case gpir_codegen_src_p1_acc_0:169printf("^%d", cur_dest_index - 1 * num_units + unit_acc_0);170break;171172case gpir_codegen_src_p1_acc_1:173printf("^%d", cur_dest_index - 1 * num_units + unit_acc_1);174break;175176case gpir_codegen_src_p1_mul_0:177printf("^%d", cur_dest_index - 1 * num_units + unit_mul_0);178break;179180case gpir_codegen_src_p1_mul_1:181printf("^%d", cur_dest_index - 1 * num_units + unit_mul_1);182break;183184case gpir_codegen_src_p1_pass:185printf("^%d", cur_dest_index - 1 * num_units + unit_pass);186break;187188case gpir_codegen_src_unused:189printf("unused");190break;191192case gpir_codegen_src_p1_complex: /* Also ident */193switch (unit) {194case unit_acc_0:195case unit_acc_1:196if (unit_src_num == 1) {197printf("0");198return;199}200break;201case unit_mul_0:202case unit_mul_1:203if (unit_src_num == 1) {204printf("1");205return;206}207break;208default:209break;210}211printf("^%d", cur_dest_index - 1 * num_units + unit_complex);212break;213214case gpir_codegen_src_p2_pass:215printf("^%d", cur_dest_index - 2 * num_units + unit_pass);216break;217218case gpir_codegen_src_p2_acc_0:219printf("^%d", cur_dest_index - 2 * num_units + unit_acc_0);220break;221222case gpir_codegen_src_p2_acc_1:223printf("^%d", cur_dest_index - 2 * num_units + unit_acc_1);224break;225226case gpir_codegen_src_p2_mul_0:227printf("^%d", cur_dest_index - 2 * num_units + unit_mul_0);228break;229230case gpir_codegen_src_p2_mul_1:231printf("^%d", cur_dest_index - 2 * num_units + unit_mul_1);232break;233234case gpir_codegen_src_p1_attrib_x:235case gpir_codegen_src_p1_attrib_y:236case gpir_codegen_src_p1_attrib_z:237case gpir_codegen_src_p1_attrib_w:238printf("%c%d.%c", prev_instr->register0_attribute ? 'a' : '$',239prev_instr->register0_addr,240"xyzw"[src - gpir_codegen_src_p1_attrib_x]);241break;242}243}244245static bool246print_mul(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,247unsigned cur_dest_index)248{249bool printed = false;250251switch (instr->mul_op) {252case gpir_codegen_mul_op_mul:253case gpir_codegen_mul_op_complex2:254if (instr->mul0_src0 != gpir_codegen_src_unused &&255instr->mul0_src1 != gpir_codegen_src_unused) {256printed = true;257printf("\t");258if (instr->mul0_src1 == gpir_codegen_src_ident &&259!instr->mul0_neg) {260printf("mov.m0 ");261print_dest(instr, unit_mul_0, cur_dest_index);262printf(" ");263print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,264cur_dest_index);265} else {266if (instr->mul_op == gpir_codegen_mul_op_complex2)267printf("complex2.m0 ");268else269printf("mul.m0 ");270271print_dest(instr, unit_mul_0, cur_dest_index);272printf(" ");273print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,274cur_dest_index);275printf(" ");276if (instr->mul0_neg)277printf("-");278print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,279cur_dest_index);280}281282printf("\n");283}284285if (instr->mul1_src0 != gpir_codegen_src_unused &&286instr->mul1_src1 != gpir_codegen_src_unused) {287printed = true;288printf("\t");289if (instr->mul1_src1 == gpir_codegen_src_ident &&290!instr->mul1_neg) {291printf("mov.m1 ");292print_dest(instr, unit_mul_1, cur_dest_index);293printf(" ");294print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,295cur_dest_index);296} else {297printf("mul.m1 ");298print_dest(instr, unit_mul_1, cur_dest_index);299printf(" ");300print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,301cur_dest_index);302printf(" ");303if (instr->mul1_neg)304printf("-");305print_src(instr->mul1_src1, unit_mul_0, 1, instr, prev_instr,306cur_dest_index);307}308printf("\n");309}310311break;312case gpir_codegen_mul_op_complex1:313printed = true;314printf("\tcomplex1.m01 ");315print_dest(instr, unit_mul_0, cur_dest_index);316printf(" ");317print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,318cur_dest_index);319printf(" ");320print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,321cur_dest_index);322printf(" ");323print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,324cur_dest_index);325printf(" ");326print_src(instr->mul1_src1, unit_mul_1, 1, instr, prev_instr,327cur_dest_index);328printf("\n");329break;330331case gpir_codegen_mul_op_select:332printed = true;333printf("\tsel.m01 ");334print_dest(instr, unit_mul_0, cur_dest_index);335printf(" ");336print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,337cur_dest_index);338printf(" ");339print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,340cur_dest_index);341printf(" ");342print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,343cur_dest_index);344printf("\n");345break;346347default:348printed = true;349printf("\tunknown%u.m01 ", instr->mul_op);350print_dest(instr, unit_mul_0, cur_dest_index);351printf(" ");352print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,353cur_dest_index);354printf(" ");355print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,356cur_dest_index);357printf(" ");358print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,359cur_dest_index);360printf(" ");361print_src(instr->mul1_src1, unit_mul_1, 1, instr, prev_instr,362cur_dest_index);363printf("\n");364break;365}366367return printed;368}369370typedef struct {371const char *name;372unsigned srcs;373} acc_op_info;374375#define CASE(_name, _srcs) \376[gpir_codegen_acc_op_##_name] = { \377.name = #_name, \378.srcs = _srcs \379}380381static const acc_op_info acc_op_infos[8] = {382CASE(add, 2),383CASE(floor, 1),384CASE(sign, 1),385CASE(ge, 2),386CASE(lt, 2),387CASE(min, 2),388CASE(max, 2),389};390391#undef CASE392393static bool394print_acc(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,395unsigned cur_dest_index)396{397bool printed = false;398const acc_op_info op = acc_op_infos[instr->acc_op];399400if (instr->acc0_src0 != gpir_codegen_src_unused) {401printed = true;402printf("\t");403acc_op_info acc0_op = op;404if (instr->acc0_src1 == gpir_codegen_src_ident &&405instr->acc0_src1_neg) {406/* add x, -0 -> mov x */407acc0_op.name = "mov";408acc0_op.srcs = 1;409}410411if (acc0_op.name)412printf("%s.a0 ", acc0_op.name);413else414printf("op%u.a0 ", instr->acc_op);415416print_dest(instr, unit_acc_0, cur_dest_index);417printf(" ");418if (instr->acc0_src0_neg)419printf("-");420print_src(instr->acc0_src0, unit_acc_0, 0, instr, prev_instr,421cur_dest_index);422if (acc0_op.srcs > 1) {423printf(" ");424if (instr->acc0_src1_neg)425printf("-");426print_src(instr->acc0_src1, unit_acc_0, 1, instr, prev_instr,427cur_dest_index);428}429430printf("\n");431}432433if (instr->acc1_src0 != gpir_codegen_src_unused) {434printed = true;435printf("\t");436acc_op_info acc1_op = op;437if (instr->acc1_src1 == gpir_codegen_src_ident &&438instr->acc1_src1_neg) {439/* add x, -0 -> mov x */440acc1_op.name = "mov";441acc1_op.srcs = 1;442}443444if (acc1_op.name)445printf("%s.a1 ", acc1_op.name);446else447printf("op%u.a1 ", instr->acc_op);448449print_dest(instr, unit_acc_1, cur_dest_index);450printf(" ");451if (instr->acc1_src0_neg)452printf("-");453print_src(instr->acc1_src0, unit_acc_1, 0, instr, prev_instr,454cur_dest_index);455if (acc1_op.srcs > 1) {456printf(" ");457if (instr->acc1_src1_neg)458printf("-");459print_src(instr->acc1_src1, unit_acc_1, 1, instr, prev_instr,460cur_dest_index);461}462463printf("\n");464}465466return printed;467}468469static bool470print_pass(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,471unsigned cur_dest_index)472{473if (instr->pass_src == gpir_codegen_src_unused)474return false;475476printf("\t");477478switch (instr->pass_op) {479case gpir_codegen_pass_op_pass:480printf("mov.p ");481break;482case gpir_codegen_pass_op_preexp2:483printf("preexp2.p ");484break;485case gpir_codegen_pass_op_postlog2:486printf("postlog2.p ");487break;488case gpir_codegen_pass_op_clamp:489printf("clamp.p ");490break;491default:492printf("unk%u.p ", instr->pass_op);493}494495print_dest(instr, unit_pass, cur_dest_index);496printf(" ");497print_src(instr->pass_src, unit_pass, 0, instr, prev_instr,498cur_dest_index);499500if (instr->pass_op == gpir_codegen_pass_op_clamp) {501printf(" ");502print_src(gpir_codegen_src_load_x, unit_pass, 1, instr, prev_instr,503cur_dest_index);504printf(" ");505print_src(gpir_codegen_src_load_y, unit_pass, 2, instr, prev_instr,506cur_dest_index);507}508509printf("\n");510511return true;512}513514static bool515print_complex(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,516unsigned cur_dest_index)517{518if (instr->complex_src == gpir_codegen_src_unused)519return false;520521printf("\t");522523switch (instr->complex_op) {524case gpir_codegen_complex_op_nop:525return false;526527case gpir_codegen_complex_op_exp2:528printf("exp2.c ");529break;530case gpir_codegen_complex_op_log2:531printf("log2.c ");532break;533case gpir_codegen_complex_op_rsqrt:534printf("rsqrt.c ");535break;536case gpir_codegen_complex_op_rcp:537printf("rcp.c ");538break;539case gpir_codegen_complex_op_pass:540case gpir_codegen_complex_op_temp_store_addr:541case gpir_codegen_complex_op_temp_load_addr_0:542case gpir_codegen_complex_op_temp_load_addr_1:543case gpir_codegen_complex_op_temp_load_addr_2:544printf("mov.c ");545break;546default:547printf("unk%u.c ", instr->complex_op);548}549550print_dest(instr, unit_complex, cur_dest_index);551printf(" ");552print_src(instr->complex_src, unit_complex, 0, instr, prev_instr,553cur_dest_index);554printf("\n");555556return true;557}558559static void560print_instr(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,561unsigned instr_number, unsigned cur_dest_index)562{563bool printed = false;564printf("%03d:", instr_number);565printed |= print_acc(instr, prev_instr, cur_dest_index);566printed |= print_mul(instr, prev_instr, cur_dest_index);567printed |= print_complex(instr, prev_instr, cur_dest_index);568printed |= print_pass(instr, prev_instr, cur_dest_index);569570if (instr->branch) {571printed = true;572/* The branch condition is taken from the current pass unit result */573printf("\tbranch ^%d %03d\n", cur_dest_index + unit_pass,574instr->branch_target + (instr->branch_target_lo ? 0 : 0x100));575}576577if (instr->unknown_1 != 0) {578printed = true;579printf("\tunknown_1 %u\n", instr->unknown_1);580}581582if (!printed)583printf("\tnop\n");584}585586void587gpir_disassemble_program(gpir_codegen_instr *code, unsigned num_instr)588{589printf("=======disassembly:=======\n");590591unsigned cur_dest_index = 0;592unsigned cur_instr = 0;593for (gpir_codegen_instr *instr = code; cur_instr < num_instr;594instr++, cur_instr++, cur_dest_index += num_units) {595print_instr(instr, instr - 1, cur_instr, cur_dest_index);596}597}598599600601