From 455ebcccfb346c148bc4e6bebaf2c3e153e9b79a Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Wed, 10 Apr 2024 10:43:38 +0200 Subject: [PATCH] ir3: add encoding for isam.v isam.v is a version of isam that can load multiple components from IBOs. It uses some bits that are used for different purposes in other tex instructions: - bit 50 (.v): .s elsewhere - bit 53 (indicates whether an immediate offset is used): .p elsewhere - bit 18 (.1d when not set, has to be set for .v): 0 elsewhere For this reason, the bitset hierarchy for cat5 had to be reordered a bit. The immediate offset is encoded as an extra (immed) source register and an instruction flag (to be able to make the distinction between offset zero and no offset, although this might not be useful). This also adds a flag for the .1d field. Since this bit is active-low, this flag has inverted semantics: setting it will make .1d inactive. Note that some existing disassembler tests for isam had to be updated because the bit is never set and this is now disassembled as .1d. This matches the blob's disassembler. Signed-off-by: Job Noorman Part-of: --- .../.gitlab-ci/reference/prefetch-test.log | 2 +- src/freedreno/ir3/ir3.h | 11 ++++ src/freedreno/ir3/ir3_lexer.l | 1 + src/freedreno/ir3/ir3_parser.y | 17 ++++-- src/freedreno/ir3/ir3_print.c | 2 + src/freedreno/ir3/tests/disasm.c | 7 ++- src/freedreno/isa/ir3-cat5.xml | 52 +++++++++++++++---- 7 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/freedreno/.gitlab-ci/reference/prefetch-test.log b/src/freedreno/.gitlab-ci/reference/prefetch-test.log index c4f5e76029ab6..afb7a1cd04834 100644 --- a/src/freedreno/.gitlab-ci/reference/prefetch-test.log +++ b/src/freedreno/.gitlab-ci/reference/prefetch-test.log @@ -149157,7 +149157,7 @@ shader-blocks: :0:0047:0057[00000000x_00000000x] nop :3:0048:0058[6d70fe56x_c102890cx] (ss)(jp)(sat)(rpt2)(ul)sel.s16 r21.z, (r)hr, (neg)(r)hr56.y, (neg) ; no match: FIELD: 'sel.s16.SRC3': 0000000000000102 :4:0049:0061[821c4006x_20905a42x] no match: 821c400620905a42 - :5:0050:0062[b002819cx_d601061dx] (sy)isam.a (f16)(x)hr39.x, r3.z, s#0, t#107 ; WARNING: unexpected bits[47:47] in #instruction-cat5: 0000000000000001 vs 0000000000000000, WARNING: unexpected bits[0:7] in #cat5-src2: 0000000000000083 vs 0000000000000000 + :5:0050:0062[b002819cx_d601061dx] (sy)isam.a.1d (f16)(x)hr39.x, r3.z, s#0, t#107 ; WARNING: unexpected bits[47:47] in #instruction-cat5: 0000000000000001 vs 0000000000000000, WARNING: unexpected bits[0:7] in #cat5-src2: 0000000000000083 vs 0000000000000000 :0:0051:0063[19d70515x_81d857bex] no match: 19d7051581d857be :3:0052:0064[7972f999x_e4df0ecbx] (sy)(ss)(jp)(rpt1)(ul)mad.s16 r38.y, (r)hc, (neg)hr57.y, (neg)(r)(last)hr55.w :6:0053:0066[dda7eb4fx_f96f6ddfx] no match: dda7eb4ff96f6ddf diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 52df6e2d287ab..da7c8aedb3455 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -357,6 +357,17 @@ typedef enum ir3_instruction_flags { * (eq) calculations. */ IR3_INSTR_NEEDS_HELPERS = BIT(18), + + /* isam.v */ + IR3_INSTR_V = BIT(19), + + /* isam.1d. Note that .1d is an active-low bit. */ + IR3_INSTR_INV_1D = BIT(20), + + /* isam.v/ldib.b/stib.b can optionally use an immediate offset with one of + * their sources. + */ + IR3_INSTR_IMM_OFFSET = BIT(21), } ir3_instruction_flags; struct ir3_instruction { diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index 9a2e0efdc3553..3df1a98e2e2f7 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -436,6 +436,7 @@ static int parse_reg(const char *str) "s" return 's'; "k" return 'k'; "u" return 'u'; +"v" return 'v'; "base"[0-9]+ ir3_yylval.num = strtol(yytext+4, NULL, 10); return T_BASE; "offset"[0-9]+ ir3_yylval.num = strtol(yytext+6, NULL, 10); return T_OFFSET; "uniform" return T_UNIFORM; diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index a7796bd4ef87a..052a7e1693924 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -716,7 +716,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_MOD_MEM %token T_MOD_RT -%type integer offset +%type integer offset uoffset %type flut_immed %type float %type src dst const cat0_src1 cat0_src2 @@ -1079,8 +1079,9 @@ cat4_instr: cat4_opc dst_reg ',' src_reg_or_const_or_rel_or_imm cat5_opc_dsxypp: T_OP_DSXPP_1 { new_instr(OPC_DSXPP_1)->cat5.type = TYPE_F32; } | T_OP_DSYPP_1 { new_instr(OPC_DSYPP_1)->cat5.type = TYPE_F32; } -cat5_opc: T_OP_ISAM { new_instr(OPC_ISAM); } -| T_OP_ISAML { new_instr(OPC_ISAML); } +cat5_opc_isam: T_OP_ISAM { new_instr(OPC_ISAM)->flags |= IR3_INSTR_INV_1D; } + +cat5_opc: T_OP_ISAML { new_instr(OPC_ISAML); } | T_OP_ISAMM { new_instr(OPC_ISAMM); } | T_OP_SAM { new_instr(OPC_SAM); } | T_OP_SAMB { new_instr(OPC_SAMB); } @@ -1117,6 +1118,7 @@ cat5_flag: '.' T_3D { instr->flags |= IR3_INSTR_3D; } | '.' 'p' { instr->flags |= IR3_INSTR_P; } | '.' 's' { instr->flags |= IR3_INSTR_S; } | '.' T_S2EN { instr->flags |= IR3_INSTR_S2EN; } +| '.' T_1D { instr->flags &= ~IR3_INSTR_INV_1D; } | '.' T_UNIFORM { } | '.' T_NONUNIFORM { instr->flags |= IR3_INSTR_NONUNIF; } | '.' T_BASE { instr->flags |= IR3_INSTR_B; instr->cat5.tex_base = $2; } @@ -1143,6 +1145,9 @@ cat5_instr: cat5_opc_dsxypp cat5_flags dst_reg ',' src_reg | cat5_opc cat5_flags cat5_type dst_reg ',' src_reg ',' cat5_samp_tex_all | cat5_opc cat5_flags cat5_type dst_reg ',' cat5_samp_tex | cat5_opc cat5_flags cat5_type dst_reg +| cat5_opc_isam cat5_flags cat5_type dst_reg ',' src_reg ',' src_reg ',' cat5_samp_tex_all +| cat5_opc_isam cat5_flags cat5_type dst_reg ',' src_reg ',' cat5_samp_tex_all +| cat5_opc_isam '.' 'v' cat5_flags cat5_type dst_reg ',' src_reg src_uoffset ',' cat5_samp_tex_all { instr->flags |= IR3_INSTR_V; } | T_OP_TCINV { new_instr(OPC_TCINV); } cat6_typed: '.' T_UNTYPED { instr->cat6.typed = 0; } @@ -1506,10 +1511,14 @@ src_reg_or_rel_or_imm: src_reg | relative | immediate -offset: { $$ = 0; } +uoffset: { $$ = 0; } | '+' integer { $$ = $2; } + +offset: uoffset | '-' integer { $$ = -$2; } +src_uoffset: uoffset { new_src(0, IR3_REG_IMMED)->uim_val = $1; if ($1) instr->flags |= IR3_INSTR_IMM_OFFSET; } + relative_gpr_src: 'r' '<' T_A0 offset '>' { new_src(0, IR3_REG_RELATIV)->array.offset = $4; } | T_HR '<' T_A0 offset '>' { new_src(0, IR3_REG_RELATIV | IR3_REG_HALF)->array.offset = $4; } diff --git a/src/freedreno/ir3/ir3_print.c b/src/freedreno/ir3/ir3_print.c index 60df5910f43a4..2022ad2cd3a98 100644 --- a/src/freedreno/ir3/ir3_print.c +++ b/src/freedreno/ir3/ir3_print.c @@ -200,6 +200,8 @@ print_instr_name(struct log_stream *stream, struct ir3_instruction *instr, mesa_log_stream_printf(stream, ".p"); if (instr->flags & IR3_INSTR_S) mesa_log_stream_printf(stream, ".s"); + if (instr->flags & IR3_INSTR_V) + mesa_log_stream_printf(stream, ".v"); if (instr->flags & IR3_INSTR_A1EN) mesa_log_stream_printf(stream, ".a1en"); if (instr->flags & IR3_INSTR_U) diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index cea67be42a57c..63219ea481b37 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -181,9 +181,14 @@ static const struct test { INSTR_6XX(a048d107_e0080a07, "isaml.base3 (s32)(x)r1.w, r0.w, r1.y, s#0, a1.x"), INSTR_6XX(a1481606_e4803035, "saml.base0 (f32)(yz)r1.z, r6.z, r6.x, s#36, a1.x"), - INSTR_7XX(a0081f02_e2000001, "isam.base0 (f32)(xyzw)r0.z, r0.x, t#16, a1.x"), + INSTR_7XX(a0081f02_e2040001, "isam.base0 (f32)(xyzw)r0.z, r0.x, t#16, a1.x"), + INSTR_7XX(a0081f02_e2000001, "isam.base0.1d (f32)(xyzw)r0.z, r0.x, t#16, a1.x"), INSTR_7XX(a148310d_e028302c, "saml.base2 (u32)(x)r3.y, hr5.z, hr6.x, t#1, a1.x"), + INSTR_7XX(a00c3101_c2040001, "isam.v.base0 (u32)(x)r0.y, r0.x, s#0, t#1"), + INSTR_7XX(a00c3101_c2000001, "isam.v.base0.1d (u32)(x)r0.y, r0.x, s#0, t#1"), + INSTR_7XX(a02c3f06_c2041003, "isam.v.base0 (u32)(xyzw)r1.z, r0.y+8, s#0, t#1"), + /* dEQP-VK.subgroups.arithmetic.compute.subgroupadd_float */ INSTR_6XX(a7c03102_00100003, "brcst.active.w8 (u32)(x)r0.z, r0.y"), /* brcst.active.w8 (u32)(xOOO)r0.z, r0.y */ /* dEQP-VK.subgroups.quad.graphics.subgroupquadbroadcast_int */ diff --git a/src/freedreno/isa/ir3-cat5.xml b/src/freedreno/isa/ir3-cat5.xml index 9ca1567cc2a9e..a1f34f359d0da 100644 --- a/src/freedreno/isa/ir3-cat5.xml +++ b/src/freedreno/isa/ir3-cat5.xml @@ -56,7 +56,7 @@ SOFTWARE. The "normal" case, ie. not s2en (indirect) and/or bindless - {SY}{JP}{NAME}{3D}{A}{O}{P}{S} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}{SAMP}{TEX} + {SY}{JP}{NAME}{3D}{A}{O}{P}{SV}{1D} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}{SAMP}{TEX} @@ -69,6 +69,7 @@ SOFTWARE. + - 0x + x @@ -94,7 +95,6 @@ SOFTWARE. 0 - @@ -111,7 +111,6 @@ SOFTWARE. src->cat5.tex_base >> 1 !!(src->flags & IR3_INSTR_3D) !!(src->flags & IR3_INSTR_A) - !!(src->flags & IR3_INSTR_S) !!(src->flags & (IR3_INSTR_S2EN | IR3_INSTR_B)) !!(src->flags & IR3_INSTR_O) extract_cat5_DESC_MODE(src) @@ -123,16 +122,20 @@ SOFTWARE. extract_cat5_SRC(src, 1) (src->srcs_count > 0) ? src->srcs[0] : NULL + + + + - + {S2EN_BINDLESS} The s2en (indirect) or bindless case - {SY}{JP}{NAME}{3D}{A}{O}{P}{S}{S2EN}{UNIFORM}{NONUNIFORM}{BASE} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}{SRC3}{A1} + {SY}{JP}{NAME}{3D}{A}{O}{P}{SV}{S2EN}{UNIFORM}{NONUNIFORM}{BASE}{1D} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}{SRC3}{A1} @@ -154,19 +157,37 @@ SOFTWARE. 00 + + + + 0 + + !!(src->flags & IR3_INSTR_S) !!(src->flags & IR3_INSTR_P) - + 00000 + + + + + + + + !!(src->flags & IR3_INSTR_V) + !!(src->flags & IR3_INSTR_INV_1D) + !!(src->flags & IR3_INSTR_IMM_OFFSET) + @@ -485,7 +506,12 @@ SOFTWARE. 101 - + + 0 + 0 + + + The subgroup is divided into (subgroup_size / CLUSTER_SIZE) clusters. For each cluster brcst.active.w does: @@ -539,7 +565,7 @@ SOFTWARE. - + @@ -614,10 +640,18 @@ SOFTWARE. + + {SRC2_IMM_OFFSET} + + {OFF} + + + 00000000 src + extract_reg_uim(src)