diff --git a/src/freedreno/.gitlab-ci/reference/crash.log b/src/freedreno/.gitlab-ci/reference/crash.log index bf9eba41180..bd197b41b43 100644 --- a/src/freedreno/.gitlab-ci/reference/crash.log +++ b/src/freedreno/.gitlab-ci/reference/crash.log @@ -4118,7 +4118,7 @@ shader-blocks: :1:0002:0002[200a00c1x_094864d2x] no match: 200a00c1094864d2 :2:0003:0003[44109084x_4a201507x] no match: 441090844a201507 :4:0004:0004[882fadabx_14a391b1x] (jp)(sat)(rpt1)(ul)rsq hr42.w, (abs)(r)hc108.y ; dontcare bits in rsq: f800014a30000 - :3:0005:0006[6060f068x_7106601ax] (ss)(ul)mad.u16 r26.x, (neg)hr6.z, (neg)hr48.y, (r)hc65.z ; dontcare bits in mad.u16: 2000 + :3:0005:0006[6060f068x_7106601ax] no match: 6060f0687106601a ----------------------------------------------- 8192 (0x2000) bytes 000000: d81251c5 40846422 520c369a 938a16e2 |.Q.."d.@.6.R....| diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c index 3be1a3ef9f0..d9b5d2167dd 100644 --- a/src/freedreno/ir3/disasm-a3xx.c +++ b/src/freedreno/ir3/disasm-a3xx.c @@ -264,6 +264,7 @@ static const struct opc_info { OPC(3, OPC_SEL_F32, sel.f32), OPC(3, OPC_SAD_S16, sad.s16), OPC(3, OPC_SAD_S32, sad.s32), + OPC(3, OPC_SHLG_B16, shlg.b16), /* category 4: */ OPC(4, OPC_RCP, rcp), diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h index 3400d35f03f..e66911679b6 100644 --- a/src/freedreno/ir3/instr-a3xx.h +++ b/src/freedreno/ir3/instr-a3xx.h @@ -192,6 +192,7 @@ typedef enum { OPC_SEL_F32 = _OPC(3, 13), OPC_SAD_S16 = _OPC(3, 14), OPC_SAD_S32 = _OPC(3, 15), + OPC_SHLG_B16 = _OPC(3, 16), /* category 4: */ OPC_RCP = _OPC(4, 0), diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index b706ee163fd..e47f1df22bd 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -799,7 +799,16 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n, break; case 3: valid_flags = ir3_cat3_absneg(instr->opc) | - IR3_REG_CONST | IR3_REG_RELATIV | IR3_REG_SHARED; + IR3_REG_RELATIV | IR3_REG_SHARED; + + if (instr->opc == OPC_SHLG_B16) { + valid_flags |= IR3_REG_IMMED; + /* shlg.b16 can be RELATIV+CONST but not CONST: */ + if (flags & IR3_REG_RELATIV) + valid_flags |= IR3_REG_CONST; + } else { + valid_flags |= IR3_REG_CONST; + } if (flags & ~valid_flags) return false; diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 3e0b4f0420b..16986b6c2e2 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -1243,6 +1243,8 @@ static inline unsigned ir3_cat3_absneg(opc_t opc) case OPC_SEL_B16: case OPC_SEL_B32: + case OPC_SHLG_B16: + default: return 0; } diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index c5b263af910..cdee9ab9c26 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -251,6 +251,7 @@ static int parse_w(const char *str) "sel.f32" return TOKEN(T_OP_SEL_F32); "sad.s16" return TOKEN(T_OP_SAD_S16); "sad.s32" return TOKEN(T_OP_SAD_S32); +"shlg.b16" return TOKEN(T_OP_SHLG_B16); /* category 4: */ "rcp" return TOKEN(T_OP_RCP); diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index ffc0f76b778..a2bf67dbcdc 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -480,6 +480,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_OP_SEL_F32 %token T_OP_SAD_S16 %token T_OP_SAD_S32 +%token T_OP_SHLG_B16 /* category 4: */ %token T_OP_RCP @@ -913,6 +914,7 @@ cat3_opc: T_OP_MAD_U16 { new_instr(OPC_MAD_U16); } | T_OP_SAD_S32 { new_instr(OPC_SAD_S32); } cat3_instr: cat3_opc dst_reg ',' src_reg_or_const_or_rel ',' src_reg_or_const ',' src_reg_or_const_or_rel +| T_OP_SHLG_B16 { new_instr(OPC_SHLG_B16); } dst_reg ',' src_reg_or_rel_or_imm ',' src_reg_or_const ',' src_reg_or_rel_or_imm cat4_opc: T_OP_RCP { new_instr(OPC_RCP); } | T_OP_RSQ { new_instr(OPC_RSQ); } @@ -1194,6 +1196,10 @@ src_reg_or_const_or_rel_or_imm: src_reg_or_const_or_rel | src_reg_flags immediate | immediate +src_reg_or_rel_or_imm: src_reg +| relative +| immediate + offset: { $$ = 0; } | '+' integer { $$ = $2; } | '-' integer { $$ = -$2; } diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index 31fcf97bf4a..604e96904fa 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -118,6 +118,9 @@ static const struct test { INSTR_6XX(63820005_10315030, "mad.f32 r1.y, (neg)c12.x, r1.x, c12.y"), INSTR_6XX(62050009_00091000, "mad.u24 r2.y, c0.x, r2.z, r2.y"), INSTR_6XX(61828008_00081033, "madsh.m16 r2.x, c12.w, r1.y, r2.x"), + INSTR_6XX(65900820_100cb008, "(nop3) shlg.b16 hr8.x, 8, hr8.x, 12"), /* (nop3) shlg.b16 hr8.x, (r)8, (r)hr8.x, 12; */ + INSTR_6XX(65ae085c_0002a001, "(nop3) shlg.b16 hr23.x, hr0.y, hr23.x, hr0.z"), /* not seen in blob */ + INSTR_6XX(65900820_0c0aac05, "(nop3) shlg.b16 hr8.x, hc, hr8.x, hc"), /* not seen in blob */ /* cat4 */ INSTR_6XX(8010000a_00000003, "rcp r2.z, r0.w"), diff --git a/src/freedreno/isa/encode.c b/src/freedreno/isa/encode.c index 470c7d38fa3..3dd0f6ab2fd 100644 --- a/src/freedreno/isa/encode.c +++ b/src/freedreno/isa/encode.c @@ -271,7 +271,7 @@ __multisrc_case(struct encode_state *s, struct ir3_register *reg) typedef enum { REG_CAT3_SRC_GPR, - REG_CAT3_SRC_CONST, + REG_CAT3_SRC_CONST_OR_IMMED, REG_CAT3_SRC_RELATIVE_GPR, REG_CAT3_SRC_RELATIVE_CONST, } reg_cat3_src_t; @@ -285,8 +285,8 @@ __cat3_src_case(struct encode_state *s, struct ir3_register *reg) } else { return REG_CAT3_SRC_RELATIVE_GPR; } - } else if (reg->flags & IR3_REG_CONST) { - return REG_CAT3_SRC_CONST; + } else if (reg->flags & (IR3_REG_CONST | IR3_REG_IMMED)) { + return REG_CAT3_SRC_CONST_OR_IMMED; } else { return REG_CAT3_SRC_GPR; } diff --git a/src/freedreno/isa/ir3-cat3.xml b/src/freedreno/isa/ir3-cat3.xml index f59e0aa099e..5e638e1543e 100644 --- a/src/freedreno/isa/ir3-cat3.xml +++ b/src/freedreno/isa/ir3-cat3.xml @@ -49,7 +49,17 @@ SOFTWARE. - + + + + {IMMED_ENCODING} + + {IMMED} + + + 1 + + {HALF}c{CONST}.{SWIZ} @@ -59,6 +69,7 @@ SOFTWARE. src->num >> 2 src->num & 0x3 + src->uim_val @@ -85,7 +96,7 @@ SOFTWARE. 1 - + {SY}{SS}{JP}{SAT}(nop{NOP}) {UL}{NAME} {DST_HALF}{DST}, {SRC1_NEG}{SRC1}, {SRC2_NEG}{HALF}{SRC2}, {SRC3_NEG}{SRC3} @@ -95,19 +106,8 @@ SOFTWARE. {SY}{SS}{JP}{SAT}{REPEAT}{UL}{NAME} {DST_HALF}{DST}, {SRC1_NEG}{SRC1_R}{SRC1}, {SRC2_NEG}{SRC2_R}{HALF}{SRC2}, {SRC3_NEG}{SRC3_R}{SRC3} - - - - - x - - - @@ -146,6 +146,60 @@ SOFTWARE. + + 0 + + + + + + + + + + + + + + + + The difference is that this cat3 version does not support plain + const registers as src1/src3 but does support inmidiate values. + On the other hand it still supports relative gpr and consts. + + + 1 + + + + + + + + + + + + + + src->srcs[2] + false + + + + + + + (src2 << src1) | src3 + + + + + + 1011 + + + 0000