From 1c6c200c0d79329174d19ae694d11f762819eeba Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Wed, 7 Jul 2021 14:40:52 +0300 Subject: [PATCH] ir3: add newly found shlg.b16 instruction Example of blob's output: (nop3) shlg.b16 hr8.x, (r)8, (r)hr8.x, 12 It does: (src2 << src1) | src2 src1 and src2 could be GPRs, relative GPRs, relative consts, or immidiates. However, they could not be plain const registers. Blob does use it in conjuncture with "samgq" instruction. Signed-off-by: Danylo Piliaiev Part-of: --- src/freedreno/.gitlab-ci/reference/crash.log | 2 +- src/freedreno/ir3/disasm-a3xx.c | 1 + src/freedreno/ir3/instr-a3xx.h | 1 + src/freedreno/ir3/ir3.c | 11 +++- src/freedreno/ir3/ir3.h | 2 + src/freedreno/ir3/ir3_lexer.l | 1 + src/freedreno/ir3/ir3_parser.y | 6 +++ src/freedreno/ir3/tests/disasm.c | 3 ++ src/freedreno/isa/encode.c | 6 +-- src/freedreno/isa/ir3-cat3.xml | 80 +++++++++++++++++++++++----- 10 files changed, 95 insertions(+), 18 deletions(-) diff --git a/src/freedreno/.gitlab-ci/reference/crash.log b/src/freedreno/.gitlab-ci/reference/crash.log index bf9eba4..bd197b4 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 3be1a3e..d9b5d21 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 3400d35..e669116 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 b706ee1..e47f1df2 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 3e0b4f0..16986b6 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 c5b263a..cdee9ab 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 ffc0f76..a2bf67d 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 31fcf97..604e969 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 470c7d3..3dd0f6a 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 f59e0aa..5e638e1 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 -- 2.7.4