diff --git a/src/compiler/isaspec/isaspec.h b/src/compiler/isaspec/isaspec.h index 63ea6a2f886..2867a0e7a37 100644 --- a/src/compiler/isaspec/isaspec.h +++ b/src/compiler/isaspec/isaspec.h @@ -28,6 +28,7 @@ #include #include +#include "util/bitset.h" #ifdef __cplusplus extern "C" { @@ -81,6 +82,11 @@ struct isa_decode_options { * Callback prior to instruction decode */ void (*instr_cb)(void *data, unsigned n, void *instr); + + /** + * callback for undefined instructions + */ + void (*no_match_cb)(FILE *out, const BITSET_WORD *bitset, size_t size); }; void isa_decode(void *bin, int sz, FILE *out, const struct isa_decode_options *options); diff --git a/src/compiler/isaspec/isaspec_decode_impl.c b/src/compiler/isaspec/isaspec_decode_impl.c index 1938e309870..a7952b1aec6 100644 --- a/src/compiler/isaspec/isaspec_decode_impl.c +++ b/src/compiler/isaspec/isaspec_decode_impl.c @@ -741,7 +741,11 @@ decode(struct decode_state *state, void *bin, int sz) const struct isa_bitset *b = find_bitset(state, __instruction, instr); if (!b) { - print(state, "no match: %"BITSET_FORMAT"\n", BITSET_VALUE(instr.bitset)); + if (state->options->no_match_cb) { + state->options->no_match_cb(state->out, instr.bitset, BITMASK_WORDS); + } else { + print(state, "no match: %"BITSET_FORMAT"\n", BITSET_VALUE(instr.bitset)); + } errors++; continue; } diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h index 78a65e37c4e..ef63928aec8 100644 --- a/src/freedreno/ir3/instr-a3xx.h +++ b/src/freedreno/ir3/instr-a3xx.h @@ -388,6 +388,10 @@ typedef enum { */ OPC_META_PARALLEL_COPY = _OPC(-1, 5), OPC_META_PHI = _OPC(-1, 6), + /* + * A manually encoded opcode + */ + OPC_META_RAW = _OPC(-1, 7) } opc_t; /* clang-format on */ diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index c9ab497a25c..27b73377780 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -420,6 +420,9 @@ struct ir3_instruction { */ gl_system_value sysval; } input; + struct { + uint64_t value; + } raw; }; /* For assigning jump offsets, we need instruction's position: */ diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index 07843a84881..fa86e770ce0 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -96,6 +96,7 @@ static int parse_reg(const char *str) [0-9]+"."[0-9]+ ir3_yylval.flt = strtod(yytext, NULL); return T_FLOAT; [0-9]* ir3_yylval.num = strtoul(yytext, NULL, 0); return T_INT; "0x"[0-9a-fA-F]* ir3_yylval.num = strtoul(yytext, NULL, 0); return T_HEX; +"raw 0x"[0-9a-fA-F]* ir3_yylval.u64 = strtoull(yytext + 4, NULL, 0); return T_RAW; "@localsize" return TOKEN(T_A_LOCALSIZE); "@const" return TOKEN(T_A_CONST); "@buf" return TOKEN(T_A_BUF); diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index 36256d870d1..fa55f2509a4 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -294,6 +294,7 @@ struct ir3 * ir3_parse(struct ir3_shader_variant *v, int tok; int num; uint32_t unum; + uint64_t u64; double flt; const char *str; struct ir3_register *reg; @@ -620,6 +621,8 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_OP_BAR %token T_OP_FENCE +%token T_RAW + /* type qualifiers: */ %token T_TYPE_F16 %token T_TYPE_F32 @@ -805,6 +808,7 @@ instr: iflags cat0_instr | iflags cat5_instr { fixup_cat5_s2en(); } | iflags cat6_instr | iflags cat7_instr +| raw_instr | label label: T_IDENTIFIER ':' { new_label($1); } @@ -1281,6 +1285,8 @@ cat7_barrier: T_OP_BAR { new_instr(OPC_BAR); } cat7_scopes cat7_instr: cat7_barrier +raw_instr: T_RAW {new_instr(OPC_META_RAW)->raw.value = $1;} + src: T_REGISTER { $$ = new_src($1, 0); } | T_A0 { $$ = new_src((61 << 3), IR3_REG_HALF); } | T_A1 { $$ = new_src((61 << 3) + 1, IR3_REG_HALF); } diff --git a/src/freedreno/ir3/ir3_shader.c b/src/freedreno/ir3/ir3_shader.c index f117bd067b2..03be17a9542 100644 --- a/src/freedreno/ir3/ir3_shader.c +++ b/src/freedreno/ir3/ir3_shader.c @@ -783,6 +783,11 @@ find_input_reg_id(struct ir3_shader_variant *so, uint32_t input_idx) return reg; } +void +print_raw(FILE *out, const BITSET_WORD *data, size_t size) { + fprintf(out, "raw 0x%X%X\n", data[0], data[1]); +} + void ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin, FILE *out) { @@ -832,6 +837,7 @@ ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin, FILE *out) .gpu_id = fd_dev_gpu_id(ir->compiler->dev_id), .show_errors = true, .branch_labels = true, + .no_match_cb = print_raw, }); fprintf(out, "; %s: outputs:", type); diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h index 0b82f760af3..32af7f5778b 100644 --- a/src/freedreno/ir3/ir3_shader.h +++ b/src/freedreno/ir3/ir3_shader.h @@ -1139,6 +1139,8 @@ ir3_find_output_regid(const struct ir3_shader_variant *so, unsigned slot) return regid(63, 0); } +void print_raw(FILE *out, const BITSET_WORD *data, size_t size); + void ir3_link_stream_out(struct ir3_shader_linkage *l, const struct ir3_shader_variant *v); diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index 2f49dbde236..6759bef8d6d 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -416,6 +416,7 @@ static const struct test { INSTR_6XX(e0fa0000_00000000, "fence.g.l.r.w"), INSTR_6XX(e09a0000_00000000, "fence.r.w"), INSTR_6XX(f0420000_00000000, "(sy)bar.g"), + INSTR_6XX(ffffffff_ffffffff, "raw 0xFFFFFFFFFFFFFFFF"), /* clang-format on */ }; @@ -462,6 +463,7 @@ main(int argc, char **argv) &(struct isa_decode_options){ .gpu_id = test->gpu_id, .show_errors = true, + .no_match_cb = print_raw, }); fflush(fdisasm); diff --git a/src/freedreno/isa/encode.c b/src/freedreno/isa/encode.c index bcf8f50a70a..b30c65caf5c 100644 --- a/src/freedreno/isa/encode.c +++ b/src/freedreno/isa/encode.c @@ -339,7 +339,12 @@ isa_assemble(struct ir3_shader_variant *v) .instr = instr, }; - const bitmask_t encoded = encode__instruction(&s, NULL, instr); + bitmask_t encoded; + if (instr->opc == OPC_META_RAW) { + encoded = uint64_t_to_bitmask(instr->raw.value); + } else { + encoded = encode__instruction(&s, NULL, instr); + } store_instruction(instrs, encoded); instrs += BITMASK_WORDS; }