ir3/isa: fix (dis)asm of ldg.a/stg.a on a6xx
We currently assume the implicit offset shift is always 2. However, this
shift is actually based on the type, making sure the offset fields are
in units of the type size. The full offset calculation is as follows:
((SRC2<<SRC2_SHIFT) + OFF)<<TYPE_SHIFT
Where SRC2, SRC2_SHIFT, and OFF are instruction fields while TYPE_SHIFT
is implicit and derived from the TYPE field.
This commit implements (dis)assembly support for this, adopting the
syntax used by the blob.
Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33503>
This commit is contained in:
@@ -305,6 +305,11 @@ static bool resolve_labels(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned cat6_type_shift()
|
||||
{
|
||||
return util_logbase2(type_size(instr->cat6.type) / 8);
|
||||
}
|
||||
|
||||
#ifdef YYDEBUG
|
||||
int yydebug;
|
||||
#endif
|
||||
@@ -782,7 +787,7 @@ static void print_token(FILE *file, int type, YYSTYPE value)
|
||||
%type <tok> cat4_opc
|
||||
%type <tok> cat5_opc cat5_samp cat5_tex cat5_type
|
||||
%type <type> type
|
||||
%type <unum> const_val
|
||||
%type <unum> const_val cat6_src_shift
|
||||
|
||||
%error-verbose
|
||||
|
||||
@@ -1240,25 +1245,36 @@ cat6_dst_offset: offset { instr->cat6.dst_offset = $1; }
|
||||
|
||||
cat6_immed: integer { instr->cat6.iim_val = $1; }
|
||||
|
||||
cat6_a6xx_global_address_pt3:
|
||||
'<' '<' integer offset '<' '<' integer {
|
||||
assert($7 == 2);
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $3 - 2;
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $4;
|
||||
}
|
||||
| '+' cat6_reg_or_immed {
|
||||
// Dummy src to smooth the difference between a6xx and a7xx
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = 0;
|
||||
}
|
||||
cat6_src_shift: '<' '<' integer {$$ = $3;}
|
||||
| {$$ = 0;}
|
||||
|
||||
cat6_a6xx_global_address_pt2:
|
||||
'(' src offset ')' '<' '<' integer {
|
||||
assert($7 == 2);
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = 0;
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $3;
|
||||
'(' '(' '(' src cat6_src_shift ')' offset ')' '<' '<' integer ')' {
|
||||
illegal_syntax_from(7, "pre-a7xx global offset syntax");
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $5;
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $7;
|
||||
}
|
||||
| '(' '(' src cat6_src_shift offset ')' '<' '<' integer ')' {
|
||||
illegal_syntax_from(7, "pre-a7xx global offset syntax");
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $4;
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $5;
|
||||
}
|
||||
| '(' src cat6_src_shift ')' {
|
||||
illegal_syntax_from(7, "pre-a7xx global offset syntax");
|
||||
// The shift contains the implicit type shift, subtract it.
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $3 - cat6_type_shift();
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = 0;
|
||||
}
|
||||
| src offset {
|
||||
if (variant->compiler->gen < 7) {
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = 0;
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $2;
|
||||
} else {
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = $2;
|
||||
// Dummy src to smooth the difference between a6xx and a7xx
|
||||
new_src(0, IR3_REG_IMMED)->uim_val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
| src cat6_a6xx_global_address_pt3
|
||||
|
||||
cat6_a6xx_global_address:
|
||||
src_reg_or_const '+' cat6_a6xx_global_address_pt2
|
||||
|
||||
@@ -205,9 +205,9 @@ static const struct test {
|
||||
// TODO is this a real instruction? Or float -6.0 ?
|
||||
// INSTR_6XX(c0c00000_00000000, "stg.f16 g[hr0.x], hr0.x, hr0.x", .parse_fail=true),
|
||||
/* dEQP-GLES31.functional.tessellation.invariance.outer_edge_symmetry.isolines_equal_spacing_ccw */
|
||||
INSTR_6XX(c0d20906_02800004, "stg.a.f32 g[r1.x+(r1.z)<<2], r0.z, 2"), /* stg.a.f32 g[r1.x+(r1.z<<2)], r0.z, 2 */
|
||||
INSTR_6XX(c0da052e_01800042, "stg.a.s32 g[r0.z+(r11.z)<<2], r8.y, 1"), /* stg.a.s32 g[r0.z+(r11.z<<2)], r8.y, 1 */
|
||||
INSTR_6XX(c0dc052e_01800042, "stg.a.u8 g[r0.z+(r11.z)<<2], hr8.y, 1"),
|
||||
INSTR_6XX(c0d20906_02800004, "stg.a.f32 g[r1.x+(r1.z<<2)], r0.z, 2"),
|
||||
INSTR_6XX(c0da052e_01800042, "stg.a.s32 g[r0.z+(r11.z<<2)], r8.y, 1"),
|
||||
INSTR_6XX(c0dc052e_01800042, "stg.a.u8 g[r0.z+r11.z], hr8.y, 1"),
|
||||
INSTR_6XX(c0ca0505_03800042, "stg.s32 g[r0.z+5], r8.y, 3"),
|
||||
INSTR_6XX(c0ca0500_03800042, "stg.s32 g[r0.z], r8.y, 3"),
|
||||
INSTR_6XX(c0ca0531_03800242, "stg.s32 g[r0.z+305], r8.y, 3"),
|
||||
@@ -220,30 +220,29 @@ static const struct test {
|
||||
INSTR_7XX(c0260207_00630100, "resbase.untyped.1d.u32.1.imm.base0 r1.w, 1"), /* resbase.u32.1d.mode4.base0 r1.w, 1 */
|
||||
|
||||
/* Customely crafted */
|
||||
INSTR_6XX(c0d61104_01800228, "stg.a.u32 g[r2.x+(r1.x+1)<<2], r5.x, 1"),
|
||||
INSTR_6XX(c0d61104_01802628, "stg.a.u32 g[r2.x+r1.x<<4+3<<2], r5.x, 1"),
|
||||
INSTR_6XX(c0d61104_01800228, "stg.a.u32 g[r2.x+((r1.x+1)<<2)], r5.x, 1"),
|
||||
INSTR_6XX(c0d61104_01802628, "stg.a.u32 g[r2.x+(((r1.x<<2)+3)<<2)], r5.x, 1"),
|
||||
|
||||
INSTR_7XX(c0d20505_07bfc006, "stg.a.f32 g[r0.z+r1.y+255], r0.w, 7"),
|
||||
INSTR_7XX(c0d20507_04812006, "stg.a.f32 g[c0.z+r1.w+4], r0.w, 4"),
|
||||
|
||||
INSTR_6XX(c0020011_04c08023, "ldg.a.f32 r4.y, g[r0.z+(r4.y)<<2], 4"), /* ldg.a.f32 r4.y, g[r0.z+(r4.y<<2)], 4 */
|
||||
INSTR_6XX(c0060006_01c18017, "ldg.a.u32 r1.z, g[r1.z+(r2.w)<<2], 1"), /* ldg.a.u32 r1.z, g[r1.z+(r2.w<<2)], 1 */
|
||||
INSTR_6XX(c0020011_04c08023, "ldg.a.f32 r4.y, g[r0.z+(r4.y<<2)], 4"),
|
||||
INSTR_6XX(c0060006_01c18017, "ldg.a.u32 r1.z, g[r1.z+(r2.w<<2)], 1"),
|
||||
INSTR_6XX(c0060006_0181800f, "ldg.u32 r1.z, g[r1.z+7], 1"),
|
||||
INSTR_6XX(c0060006_01818001, "ldg.u32 r1.z, g[r1.z], 1"),
|
||||
INSTR_6XX(c0060003_0180c269, "ldg.u32 r0.w, g[r0.w+308], 1"),
|
||||
INSTR_6XX(c0040003_0180c269, "ldg.u16 hr0.w, g[r0.w+308], 1"),
|
||||
|
||||
/* Found in TCS/TES shaders of GTA V */
|
||||
INSTR_6XX(c0020007_03c1420f, "ldg.a.f32 r1.w, g[r1.y+(r1.w+1)<<2], 3"), /* ldg.a.f32 r1.w, g[r1.y+((r1.w+1)<<2)], 3 */
|
||||
INSTR_6XX(c0020007_03c1420f, "ldg.a.f32 r1.w, g[r1.y+((r1.w+1)<<2)], 3"),
|
||||
|
||||
/* Customely crafted */
|
||||
INSTR_6XX(c0020007_03c1740f, "ldg.a.f32 r1.w, g[r1.y+r1.w<<5+2<<2], 3"),
|
||||
INSTR_6XX(c0020007_03c1740f, "ldg.a.f32 r1.w, g[r1.y+(((r1.w<<3)+2)<<2)], 3"),
|
||||
|
||||
INSTR_6XX(c0020011_04c08023, "ldg.a.f32 r4.y, g[r0.z+(r4.y)<<2], 4"), /* ldg.a.f32 r4.y, g[r0.z+(r4.y<<2)], 4 */
|
||||
INSTR_6XX(c0060006_01c18017, "ldg.a.u32 r1.z, g[r1.z+(r2.w)<<2], 1"), /* ldg.a.u32 r1.z, g[r1.z+(r2.w<<2)], 1 */
|
||||
INSTR_6XX(c0000006_01c18017, "ldg.a.f16 hr1.z, g[r1.z+(r2.w)<<2], 1"),
|
||||
INSTR_6XX(c0000006_01c18017, "ldg.a.f16 hr1.z, g[r1.z+(r2.w<<1)], 1"),
|
||||
INSTR_6XX(c0060006_0181800f, "ldg.u32 r1.z, g[r1.z+7], 1"),
|
||||
INSTR_6XX(c0060006_01818001, "ldg.u32 r1.z, g[r1.z], 1"),
|
||||
INSTR_6XX(c0060006_01c1b017, "ldg.a.u32 r1.z, g[r1.z+(r2.w<<5)], 1"),
|
||||
|
||||
INSTR_7XX(c0020411_04c08023, "ldg.a.f32 r4.y, g[r0.z+r4.y+2], 4"),
|
||||
INSTR_7XX(c0004006_01c1a017, "ldg.a.f16 hr1.z, g[c1.z+r2.w+32], 1"),
|
||||
|
||||
@@ -79,6 +79,14 @@ SOFTWARE.
|
||||
<!-- TODO pull more fields up to this level, when they are common across sub-encodings -->
|
||||
</bitset>
|
||||
|
||||
<expr name="#cat6-type-shift">
|
||||
{TYPE} >= 6 ? 0 /* u8 */ : ({TYPE_HALF} ? 1 : 2);
|
||||
</expr>
|
||||
|
||||
<expr name="#cat6-full-shift">
|
||||
{TYPE_SHIFT} + {SRC2_SHIFT}
|
||||
</expr>
|
||||
|
||||
<bitset name="#instruction-cat6-ldg" extends="#instruction-cat6-a3xx">
|
||||
<pattern pos="0" >1</pattern>
|
||||
<field low="14" high="21" name="SRC1" type="#cat6-src-const-or-gpr">
|
||||
@@ -117,35 +125,64 @@ SOFTWARE.
|
||||
<bitset name="ldg.a" extends="#instruction-cat6-ldg">
|
||||
<doc>
|
||||
LoaD Global
|
||||
|
||||
The 64b base address is stored in SRC1 (least significant bits)
|
||||
and SRC1+1 (most significant bits).
|
||||
|
||||
An offset is added to the base address that is calculated as
|
||||
follows:
|
||||
((SRC2<<SRC2_SHIFT) + OFF)<<TYPE_SHIFT
|
||||
|
||||
TYPE_SHIFT is implicitly given by the TYPE field; it ensures
|
||||
that the offset is in units of the type. Note that non
|
||||
type-aligned accesses are still supported if SRC1 is not
|
||||
aligned.
|
||||
|
||||
Note that although SRC2 is 32b, the calculation above does not
|
||||
cause any 32b overflows: it behaves as if all values are
|
||||
zero-extended to 64b first.
|
||||
</doc>
|
||||
|
||||
<gen min="600" max="699"/>
|
||||
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} {TYPE_HALF}{DST}, g[{SRC1}+({SRC2}{OFF})<<{SRC2_BYTE_SHIFT}], {SIZE}
|
||||
{SY}{JP}{NAME}.{TYPE} {TYPE_HALF}{DST}, g[{SRC1}+((({SRC2}<<{SRC2_SHIFT}){OFF})<<{TYPE_SHIFT})], {SIZE}
|
||||
</display>
|
||||
|
||||
<override>
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} {TYPE_HALF}{DST}, g[{SRC1}+{SRC2}<<{SRC2_BYTE_SHIFT}{OFF}<<2], {SIZE}
|
||||
{SY}{JP}{NAME}.{TYPE} {TYPE_HALF}{DST}, g[{SRC1}+{SRC2}{OFF}], {SIZE}
|
||||
</display>
|
||||
<expr>{SRC2_ADD_DWORD_SHIFT} > 0</expr>
|
||||
<expr>{TYPE_SHIFT} == 0</expr>
|
||||
</override>
|
||||
|
||||
<override>
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} {TYPE_HALF}{DST}, g[{SRC1}+({SRC2}<<{FULL_SHIFT})], {SIZE}
|
||||
</display>
|
||||
<expr>{OFF} == 0</expr>
|
||||
</override>
|
||||
|
||||
<override>
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} {TYPE_HALF}{DST}, g[{SRC1}+(({SRC2}{OFF})<<{TYPE_SHIFT})], {SIZE}
|
||||
</display>
|
||||
<expr>{SRC2_SHIFT} == 0</expr>
|
||||
</override>
|
||||
|
||||
<field low="1" high="8" name="SRC2" type="#reg-gpr"/>
|
||||
<field low="9" high="10" name="OFF" type="uoffset"/>
|
||||
<assert pos="11" >0</assert>
|
||||
<field low="12" high="13" name="SRC2_ADD_DWORD_SHIFT" type="uint"/>
|
||||
<field low="12" high="13" name="SRC2_SHIFT" type="uint"/>
|
||||
<pattern pos="22" >1</pattern> <!-- Reg offset ldg form -->
|
||||
<pattern low="41" high="48">xxxxxxxx</pattern>
|
||||
|
||||
<derived name="SRC2_BYTE_SHIFT" width="3" type="uint">
|
||||
<expr>{SRC2_ADD_DWORD_SHIFT} + 2</expr>
|
||||
</derived>
|
||||
<derived name="TYPE_SHIFT" type="uint" expr="#cat6-type-shift"/>
|
||||
<derived name="FULL_SHIFT" type="uint" expr="#cat6-full-shift"/>
|
||||
|
||||
<encode>
|
||||
<map name="SRC2">src->srcs[1]</map>
|
||||
<map name="SRC2_ADD_DWORD_SHIFT">extract_reg_uim(src->srcs[2])</map>
|
||||
<map name="SRC2_SHIFT">extract_reg_uim(src->srcs[2])</map>
|
||||
<map name="OFF">extract_reg_uim(src->srcs[3])</map>
|
||||
<map name="SIZE">extract_reg_uim(src->srcs[4])</map>
|
||||
</encode>
|
||||
@@ -260,28 +297,43 @@ SOFTWARE.
|
||||
<bitset name="stg.a" extends="#instruction-cat6-stg">
|
||||
<doc>
|
||||
STore Global
|
||||
|
||||
See the doc of ldg.a for how the address is calculated.
|
||||
</doc>
|
||||
|
||||
<gen min="600" max="699"/>
|
||||
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} g[{SRC1}+({SRC2}{OFF})<<{DST_BYTE_SHIFT}], {TYPE_HALF}{SRC3}, {SIZE}
|
||||
{SY}{JP}{NAME}.{TYPE} g[{SRC1}+((({SRC2}<<{SRC2_SHIFT}){OFF})<<{TYPE_SHIFT})], {TYPE_HALF}{SRC3}, {SIZE}
|
||||
</display>
|
||||
|
||||
<override>
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} g[{SRC1}+{SRC2}<<{DST_BYTE_SHIFT}{OFF}<<2], {TYPE_HALF}{SRC3}, {SIZE}
|
||||
{SY}{JP}{NAME}.{TYPE} g[{SRC1}+{SRC2}{OFF}], {TYPE_HALF}{SRC3}, {SIZE}
|
||||
</display>
|
||||
<expr>{SRC2_ADD_DWORD_SHIFT} > 0</expr>
|
||||
<expr>{TYPE_SHIFT} == 0</expr>
|
||||
</override>
|
||||
|
||||
<derived name="DST_BYTE_SHIFT" width="3" type="uint">
|
||||
<expr>{SRC2_ADD_DWORD_SHIFT} + 2</expr>
|
||||
</derived>
|
||||
<override>
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} g[{SRC1}+({SRC2}<<{FULL_SHIFT})], {TYPE_HALF}{SRC3}, {SIZE}
|
||||
</display>
|
||||
<expr>{OFF} == 0</expr>
|
||||
</override>
|
||||
|
||||
<override>
|
||||
<display>
|
||||
{SY}{JP}{NAME}.{TYPE} g[{SRC1}+(({SRC2}{OFF})<<{TYPE_SHIFT})], {TYPE_HALF}{SRC3}, {SIZE}
|
||||
</display>
|
||||
<expr>{SRC2_SHIFT} == 0</expr>
|
||||
</override>
|
||||
|
||||
<derived name="TYPE_SHIFT" type="uint" expr="#cat6-type-shift"/>
|
||||
<derived name="FULL_SHIFT" type="uint" expr="#cat6-full-shift"/>
|
||||
|
||||
<field low="9" high="10" name="OFF" type="uoffset"/>
|
||||
<assert pos="11" >0</assert>
|
||||
<field low="12" high="13" name="SRC2_ADD_DWORD_SHIFT" type="uint"/>
|
||||
<field low="12" high="13" name="SRC2_SHIFT" type="uint"/>
|
||||
<pattern low="14" high="21">xxxxxxxx</pattern>
|
||||
<pattern low="22" high="23">1x</pattern>
|
||||
<field low="32" high="39" name="SRC2" type="#reg-gpr"/>
|
||||
@@ -289,7 +341,7 @@ SOFTWARE.
|
||||
|
||||
<encode>
|
||||
<map name="SRC2">src->srcs[1]</map>
|
||||
<map name="SRC2_ADD_DWORD_SHIFT">extract_reg_uim(src->srcs[2])</map>
|
||||
<map name="SRC2_SHIFT">extract_reg_uim(src->srcs[2])</map>
|
||||
<map name="OFF">extract_reg_uim(src->srcs[3])</map>
|
||||
<map name="SRC3">src->srcs[4]</map>
|
||||
<map name="SIZE">extract_reg_uim(src->srcs[5])</map>
|
||||
|
||||
Reference in New Issue
Block a user