Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/pp/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 "util/half_float.h"2728#include "ppir.h"29#include "codegen.h"3031typedef struct {32char *name;33unsigned srcs;34} asm_op;3536static void37print_swizzle(uint8_t swizzle)38{39if (swizzle == 0xE4)40return;4142printf(".");43for (unsigned i = 0; i < 4; i++, swizzle >>= 2)44printf("%c", "xyzw"[swizzle & 3]);45}4647static void48print_mask(uint8_t mask)49{50if (mask == 0xF)51return;5253printf(".");54if (mask & 1) printf("x");55if (mask & 2) printf("y");56if (mask & 4) printf("z");57if (mask & 8) printf("w");58}5960static void61print_reg(ppir_codegen_vec4_reg reg, const char *special)62{63if (special) {64printf("%s", special);65} else {66switch (reg)67{68case ppir_codegen_vec4_reg_constant0:69printf("^const0");70break;71case ppir_codegen_vec4_reg_constant1:72printf("^const1");73break;74case ppir_codegen_vec4_reg_texture:75printf("^texture");76break;77case ppir_codegen_vec4_reg_uniform:78printf("^uniform");79break;80default:81printf("$%u", reg);82break;83}84}85}8687static void88print_vector_source(ppir_codegen_vec4_reg reg, const char *special,89uint8_t swizzle, bool abs, bool neg)90{91if (neg)92printf("-");93if (abs)94printf("abs(");9596print_reg(reg, special);97print_swizzle(swizzle);9899if (abs)100printf(")");101}102103static void104print_source_scalar(unsigned reg, const char *special, bool abs, bool neg)105{106if (neg)107printf("-");108if (abs)109printf("abs(");110111print_reg(reg >> 2, special);112if (!special)113printf(".%c", "xyzw"[reg & 3]);114115if (abs)116printf(")");117}118119static void120print_varying_source(ppir_codegen_field_varying *varying)121{122switch (varying->imm.alignment) {123case 0:124printf("%u.%c", varying->imm.index >> 2,125"xyzw"[varying->imm.index & 3]);126break;127case 1: {128const char *c[2] = {"xy", "zw"};129printf("%u.%s", varying->imm.index >> 1, c[varying->imm.index & 1]);130break;131}132default:133printf("%u", varying->imm.index);134break;135}136137if (varying->imm.offset_vector != 15) {138unsigned reg = (varying->imm.offset_vector << 2) +139varying->imm.offset_scalar;140printf("+");141print_source_scalar(reg, NULL, false, false);142}143}144145static void146print_outmod(ppir_codegen_outmod modifier)147{148switch (modifier)149{150case ppir_codegen_outmod_clamp_fraction:151printf(".sat");152break;153case ppir_codegen_outmod_clamp_positive:154printf(".pos");155break;156case ppir_codegen_outmod_round:157printf(".int");158break;159default:160break;161}162}163164static void165print_dest_scalar(unsigned reg)166{167printf("$%u", reg >> 2);168printf(".%c ", "xyzw"[reg & 3]);169}170171static void172print_const(unsigned const_num, uint16_t *val)173{174printf("const%u", const_num);175for (unsigned i = 0; i < 4; i++)176printf(" %f", _mesa_half_to_float(val[i]));177}178179static void180print_const0(void *code, unsigned offset)181{182(void) offset;183184print_const(0, code);185}186187static void188print_const1(void *code, unsigned offset)189{190(void) offset;191192print_const(1, code);193}194195static void196print_varying(void *code, unsigned offset)197{198(void) offset;199ppir_codegen_field_varying *varying = code;200201printf("load");202203bool perspective = varying->imm.source_type < 2 && varying->imm.perspective;204if (perspective)205{206printf(".perspective");207switch (varying->imm.perspective)208{209case 2:210printf(".z");211break;212case 3:213printf(".w");214break;215default:216printf(".unknown");217break;218}219}220221printf(".v ");222223switch (varying->imm.dest)224{225case ppir_codegen_vec4_reg_discard:226printf("^discard");227break;228default:229printf("$%u", varying->imm.dest);230break;231}232print_mask(varying->imm.mask);233printf(" ");234235switch (varying->imm.source_type) {236case 1:237print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,238varying->reg.absolute, varying->reg.negate);239break;240case 2:241switch (varying->imm.perspective) {242case 0:243printf("cube(");244print_varying_source(varying);245printf(")");246break;247case 1:248printf("cube(");249print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,250varying->reg.absolute, varying->reg.negate);251printf(")");252break;253case 2:254printf("normalize(");255print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,256varying->reg.absolute, varying->reg.negate);257printf(")");258break;259default:260printf("gl_FragCoord");261break;262}263break;264case 3:265if (varying->imm.perspective)266printf("gl_FrontFacing");267else268printf("gl_PointCoord");269break;270default:271print_varying_source(varying);272break;273}274}275276static void277print_sampler(void *code, unsigned offset)278{279(void) offset;280ppir_codegen_field_sampler *sampler = code;281282printf("texld");283if (sampler->lod_bias_en)284printf(".b");285286switch (sampler->type) {287case ppir_codegen_sampler_type_2d:288printf(".2d");289break;290case ppir_codegen_sampler_type_cube:291printf(".cube");292break;293default:294printf("_t%u", sampler->type);295break;296}297298printf(" %u", sampler->index);299300if (sampler->offset_en)301{302printf("+");303print_source_scalar(sampler->index_offset, NULL, false, false);304}305306if (sampler->lod_bias_en)307{308printf(" ");309print_source_scalar(sampler->lod_bias, NULL, false, false);310}311}312313static void314print_uniform(void *code, unsigned offset)315{316(void) offset;317ppir_codegen_field_uniform *uniform = code;318319printf("load.");320321switch (uniform->source) {322case ppir_codegen_uniform_src_uniform:323printf("u");324break;325case ppir_codegen_uniform_src_temporary:326printf("t");327break;328default:329printf(".u%u", uniform->source);330break;331}332333int16_t index = uniform->index;334switch (uniform->alignment) {335case 2:336printf(" %d", index);337break;338case 1:339printf(" %d.%s", index / 2, (index & 1) ? "zw" : "xy");340break;341default:342printf(" %d.%c", index / 4, "xyzw"[index & 3]);343break;344}345346if (uniform->offset_en) {347printf("+");348print_source_scalar(uniform->offset_reg, NULL, false, false);349}350}351352#define CASE(_name, _srcs) \353[ppir_codegen_vec4_mul_op_##_name] = { \354.name = #_name, \355.srcs = _srcs \356}357358static const asm_op vec4_mul_ops[] = {359[0 ... 7] = {360.name = "mul",361.srcs = 2362},363CASE(not, 1),364CASE(and, 2),365CASE(or, 2),366CASE(xor, 2),367CASE(ne, 2),368CASE(gt, 2),369CASE(ge, 2),370CASE(eq, 2),371CASE(min, 2),372CASE(max, 2),373CASE(mov, 1),374};375376#undef CASE377378static void379print_vec4_mul(void *code, unsigned offset)380{381(void) offset;382ppir_codegen_field_vec4_mul *vec4_mul = code;383384asm_op op = vec4_mul_ops[vec4_mul->op];385386if (op.name)387printf("%s", op.name);388else389printf("op%u", vec4_mul->op);390print_outmod(vec4_mul->dest_modifier);391printf(".v0 ");392393if (vec4_mul->mask) {394printf("$%u", vec4_mul->dest);395print_mask(vec4_mul->mask);396printf(" ");397}398399print_vector_source(vec4_mul->arg0_source, NULL,400vec4_mul->arg0_swizzle,401vec4_mul->arg0_absolute,402vec4_mul->arg0_negate);403404if (vec4_mul->op < 8 && vec4_mul->op != 0) {405printf("<<%u", vec4_mul->op);406}407408printf(" ");409410if (op.srcs > 1) {411print_vector_source(vec4_mul->arg1_source, NULL,412vec4_mul->arg1_swizzle,413vec4_mul->arg1_absolute,414vec4_mul->arg1_negate);415}416}417418#define CASE(_name, _srcs) \419[ppir_codegen_vec4_acc_op_##_name] = { \420.name = #_name, \421.srcs = _srcs \422}423424static const asm_op vec4_acc_ops[] = {425CASE(add, 2),426CASE(fract, 1),427CASE(ne, 2),428CASE(gt, 2),429CASE(ge, 2),430CASE(eq, 2),431CASE(floor, 1),432CASE(ceil, 1),433CASE(min, 2),434CASE(max, 2),435CASE(sum3, 1),436CASE(sum4, 1),437CASE(dFdx, 2),438CASE(dFdy, 2),439CASE(sel, 2),440CASE(mov, 1),441};442443#undef CASE444445static void446print_vec4_acc(void *code, unsigned offset)447{448(void) offset;449ppir_codegen_field_vec4_acc *vec4_acc = code;450451asm_op op = vec4_acc_ops[vec4_acc->op];452453if (op.name)454printf("%s", op.name);455else456printf("op%u", vec4_acc->op);457print_outmod(vec4_acc->dest_modifier);458printf(".v1 ");459460if (vec4_acc->mask) {461printf("$%u", vec4_acc->dest);462print_mask(vec4_acc->mask);463printf(" ");464}465466print_vector_source(vec4_acc->arg0_source, vec4_acc->mul_in ? "^v0" : NULL,467vec4_acc->arg0_swizzle,468vec4_acc->arg0_absolute,469vec4_acc->arg0_negate);470471if (op.srcs > 1) {472printf(" ");473print_vector_source(vec4_acc->arg1_source, NULL,474vec4_acc->arg1_swizzle,475vec4_acc->arg1_absolute,476vec4_acc->arg1_negate);477}478}479480#define CASE(_name, _srcs) \481[ppir_codegen_float_mul_op_##_name] = { \482.name = #_name, \483.srcs = _srcs \484}485486static const asm_op float_mul_ops[] = {487[0 ... 7] = {488.name = "mul",489.srcs = 2490},491CASE(not, 1),492CASE(and, 2),493CASE(or, 2),494CASE(xor, 2),495CASE(ne, 2),496CASE(gt, 2),497CASE(ge, 2),498CASE(eq, 2),499CASE(min, 2),500CASE(max, 2),501CASE(mov, 1),502};503504#undef CASE505506static void507print_float_mul(void *code, unsigned offset)508{509(void) offset;510ppir_codegen_field_float_mul *float_mul = code;511512asm_op op = float_mul_ops[float_mul->op];513514if (op.name)515printf("%s", op.name);516else517printf("op%u", float_mul->op);518print_outmod(float_mul->dest_modifier);519printf(".s0 ");520521if (float_mul->output_en)522print_dest_scalar(float_mul->dest);523524print_source_scalar(float_mul->arg0_source, NULL,525float_mul->arg0_absolute,526float_mul->arg0_negate);527528if (float_mul->op < 8 && float_mul->op != 0) {529printf("<<%u", float_mul->op);530}531532if (op.srcs > 1) {533printf(" ");534535print_source_scalar(float_mul->arg1_source, NULL,536float_mul->arg1_absolute,537float_mul->arg1_negate);538}539}540541#define CASE(_name, _srcs) \542[ppir_codegen_float_acc_op_##_name] = { \543.name = #_name, \544.srcs = _srcs \545}546547static const asm_op float_acc_ops[] = {548CASE(add, 2),549CASE(fract, 1),550CASE(ne, 2),551CASE(gt, 2),552CASE(ge, 2),553CASE(eq, 2),554CASE(floor, 1),555CASE(ceil, 1),556CASE(min, 2),557CASE(max, 2),558CASE(dFdx, 2),559CASE(dFdy, 2),560CASE(sel, 2),561CASE(mov, 1),562};563564#undef CASE565566static void567print_float_acc(void *code, unsigned offset)568{569(void) offset;570ppir_codegen_field_float_acc *float_acc = code;571572asm_op op = float_acc_ops[float_acc->op];573574if (op.name)575printf("%s", op.name);576else577printf("op%u", float_acc->op);578print_outmod(float_acc->dest_modifier);579printf(".s1 ");580581if (float_acc->output_en)582print_dest_scalar(float_acc->dest);583584print_source_scalar(float_acc->arg0_source, float_acc->mul_in ? "^s0" : NULL,585float_acc->arg0_absolute,586float_acc->arg0_negate);587588if (op.srcs > 1) {589printf(" ");590print_source_scalar(float_acc->arg1_source, NULL,591float_acc->arg1_absolute,592float_acc->arg1_negate);593}594}595596#define CASE(_name, _srcs) \597[ppir_codegen_combine_scalar_op_##_name] = { \598.name = #_name, \599.srcs = _srcs \600}601602static const asm_op combine_ops[] = {603CASE(rcp, 1),604CASE(mov, 1),605CASE(sqrt, 1),606CASE(rsqrt, 1),607CASE(exp2, 1),608CASE(log2, 1),609CASE(sin, 1),610CASE(cos, 1),611CASE(atan, 1),612CASE(atan2, 1),613};614615#undef CASE616617static void618print_combine(void *code, unsigned offset)619{620(void) offset;621ppir_codegen_field_combine *combine = code;622623if (combine->scalar.dest_vec &&624combine->scalar.arg1_en) {625/* This particular combination can only be valid for scalar * vector626* multiplies, and the opcode field is reused for something else.627*/628printf("mul");629} else {630asm_op op = combine_ops[combine->scalar.op];631632if (op.name)633printf("%s", op.name);634else635printf("op%u", combine->scalar.op);636}637638if (!combine->scalar.dest_vec)639print_outmod(combine->scalar.dest_modifier);640printf(".s2 ");641642if (combine->scalar.dest_vec) {643printf("$%u", combine->vector.dest);644print_mask(combine->vector.mask);645} else {646print_dest_scalar(combine->scalar.dest);647}648printf(" ");649650print_source_scalar(combine->scalar.arg0_src, NULL,651combine->scalar.arg0_absolute,652combine->scalar.arg0_negate);653printf(" ");654655if (combine->scalar.arg1_en) {656if (combine->scalar.dest_vec) {657print_vector_source(combine->vector.arg1_source, NULL,658combine->vector.arg1_swizzle,659false, false);660} else {661print_source_scalar(combine->scalar.arg1_src, NULL,662combine->scalar.arg1_absolute,663combine->scalar.arg1_negate);664}665}666}667668static void669print_temp_write(void *code, unsigned offset)670{671(void) offset;672ppir_codegen_field_temp_write *temp_write = code;673674if (temp_write->fb_read.unknown_0 == 0x7) {675if (temp_write->fb_read.source)676printf("fb_color");677else678printf("fb_depth");679printf(" $%u", temp_write->fb_read.dest);680681return;682}683684printf("store.t");685686int16_t index = temp_write->temp_write.index;687switch (temp_write->temp_write.alignment) {688case 2:689printf(" %d", index);690break;691case 1:692printf(" %d.%s", index / 2, (index & 1) ? "zw" : "xy");693break;694default:695printf(" %d.%c", index / 4, "xyzw"[index & 3]);696break;697}698699if (temp_write->temp_write.offset_en) {700printf("+");701print_source_scalar(temp_write->temp_write.offset_reg,702NULL, false, false);703}704705printf(" ");706707if (temp_write->temp_write.alignment) {708print_reg(temp_write->temp_write.source >> 2, NULL);709} else {710print_source_scalar(temp_write->temp_write.source, NULL, false, false);711}712}713714static void715print_branch(void *code, unsigned offset)716{717ppir_codegen_field_branch *branch = code;718719if (branch->discard.word0 == PPIR_CODEGEN_DISCARD_WORD0 &&720branch->discard.word1 == PPIR_CODEGEN_DISCARD_WORD1 &&721branch->discard.word2 == PPIR_CODEGEN_DISCARD_WORD2) {722printf("discard");723return;724}725726727const char* cond[] = {728"nv", "lt", "eq", "le",729"gt", "ne", "ge", "" ,730};731732unsigned cond_mask = 0;733cond_mask |= (branch->branch.cond_lt ? 1 : 0);734cond_mask |= (branch->branch.cond_eq ? 2 : 0);735cond_mask |= (branch->branch.cond_gt ? 4 : 0);736printf("branch");737if (cond_mask != 0x7) {738printf(".%s ", cond[cond_mask]);739print_source_scalar(branch->branch.arg0_source, NULL, false, false);740printf(" ");741print_source_scalar(branch->branch.arg1_source, NULL, false, false);742}743744printf(" %d", branch->branch.target + offset);745}746747typedef void (*print_field_func)(void *, unsigned);748749static const print_field_func print_field[ppir_codegen_field_shift_count] = {750[ppir_codegen_field_shift_varying] = print_varying,751[ppir_codegen_field_shift_sampler] = print_sampler,752[ppir_codegen_field_shift_uniform] = print_uniform,753[ppir_codegen_field_shift_vec4_mul] = print_vec4_mul,754[ppir_codegen_field_shift_float_mul] = print_float_mul,755[ppir_codegen_field_shift_vec4_acc] = print_vec4_acc,756[ppir_codegen_field_shift_float_acc] = print_float_acc,757[ppir_codegen_field_shift_combine] = print_combine,758[ppir_codegen_field_shift_temp_write] = print_temp_write,759[ppir_codegen_field_shift_branch] = print_branch,760[ppir_codegen_field_shift_vec4_const_0] = print_const0,761[ppir_codegen_field_shift_vec4_const_1] = print_const1,762};763764static const int ppir_codegen_field_size[] = {76534, 62, 41, 43, 30, 44, 31, 30, 41, 73, 64, 64766};767768static void769bitcopy(char *src, char *dst, unsigned bits, unsigned src_offset)770{771src += src_offset / 8;772src_offset %= 8;773774for (int b = bits; b > 0; b -= 8, src++, dst++) {775unsigned char out = ((unsigned char) *src) >> src_offset;776if (src_offset > 0 && src_offset + b > 8)777out |= ((unsigned char) *(src + 1)) << (8 - src_offset);778*dst = (char) out;779}780}781782void783ppir_disassemble_instr(uint32_t *instr, unsigned offset)784{785ppir_codegen_ctrl *ctrl = (ppir_codegen_ctrl *) instr;786787char *instr_code = (char *) (instr + 1);788unsigned bit_offset = 0;789bool first = true;790for (unsigned i = 0; i < ppir_codegen_field_shift_count; i++) {791char code[12];792793if (!((ctrl->fields >> i) & 1))794continue;795796unsigned bits = ppir_codegen_field_size[i];797bitcopy(instr_code, code, bits, bit_offset);798799if (first)800first = false;801else802printf(", ");803804print_field[i](code, offset);805806bit_offset += bits;807}808809if (ctrl->sync)810printf(", sync");811if (ctrl->stop)812printf(", stop");813814printf("\n");815}816817818819