freedreno/afuc: Add syntax for pre-increment addressing

This is inspired by the ARM syntax.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26691>
This commit is contained in:
Connor Abbott
2023-12-12 13:13:06 +01:00
committed by Marge Bot
parent 579227e028
commit 55985b7301
8 changed files with 97 additions and 37 deletions

View File

@@ -52,7 +52,7 @@ mov $01, $data
CP_SCRATCH_WRITE: CP_SCRATCH_WRITE:
mov $02, 0xff mov $02, 0xff
(rep)cwrite $data, [$02 + @RB_RPTR], 0x4 (rep)cwrite $data, [$02 + 0x1]!, 0x0
waitin waitin
mov $01, $data mov $01, $data
@@ -60,7 +60,7 @@ CP_SET_BIN_DATA5:
sread $02, [$00 + %SP], 0x0 sread $02, [$00 + %SP], 0x0
swrite $02, [$00 + %SP], 0x0 swrite $02, [$00 + %SP], 0x0
mov $02, 0x7 mov $02, 0x7
(rep)swrite $data, [$02 + 0x001], 0x4 (rep)swrite $data, [$02 + 0x1]!, 0x0
waitin waitin
mov $01, $data mov $01, $data
@@ -121,10 +121,10 @@ mov $06, $data
l96: l96:
breq $06, 0x0, #l102 breq $06, 0x0, #l102
cwrite $03, [$00 + @LOAD_STORE_HI], 0x0 cwrite $03, [$00 + @LOAD_STORE_HI], 0x0
load $07, [$02 + 0x4], 0x4 load $07, [$02 + 0x4]!, 0x0
cwrite $05, [$00 + @LOAD_STORE_HI], 0x0 cwrite $05, [$00 + @LOAD_STORE_HI], 0x0
jump #l96 jump #l96
store $07, [$04 + 0x4], 0x4 store $07, [$04 + 0x4]!, 0x0
l102: l102:
waitin waitin
mov $01, $data mov $01, $data
@@ -136,7 +136,7 @@ mov $02, $data
cwrite $data, [$00 + @LOAD_STORE_HI], 0x0 cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
mov $rem, $data mov $rem, $data
cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0 cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
(rep)store $memdata, [$02 + 0x4], 0x4 (rep)store $memdata, [$02 + 0x4]!, 0x0
waitin waitin
mov $01, $data mov $01, $data

View File

@@ -90,7 +90,7 @@ CP_SCRATCH_WRITE:
; test (rep) + flags + non-zero offset with cwrite ; test (rep) + flags + non-zero offset with cwrite
; TODO: 0x4 flag is actually pre-increment addressing, handle it as such ; TODO: 0x4 flag is actually pre-increment addressing, handle it as such
mov $02, 0xff mov $02, 0xff
(rep)cwrite $data, [$02 + 0x001], 0x4 (rep)cwrite $data, [$02 + 0x001]!, 0x0
waitin waitin
mov $01, $data mov $01, $data
@@ -99,7 +99,7 @@ CP_SET_BIN_DATA5:
sread $02, [$00 + %SP], 0x0 sread $02, [$00 + %SP], 0x0
swrite $02, [$00 + %SP], 0x0 swrite $02, [$00 + %SP], 0x0
mov $02, 7 mov $02, 7
(rep)swrite $data, [$02 + 1], 0x4 (rep)swrite $data, [$02 + 1]!, 0x0
waitin waitin
mov $01, $data mov $01, $data
@@ -172,10 +172,10 @@ mov $06, $data
cpy_header: cpy_header:
breq $06, 0, #cpy_exit breq $06, 0, #cpy_exit
cwrite $03, [$00 + @LOAD_STORE_HI], 0x0 cwrite $03, [$00 + @LOAD_STORE_HI], 0x0
load $07, [$02 + 0x004], 0x4 load $07, [$02 + 0x004]!, 0x0
cwrite $05, [$00 + @LOAD_STORE_HI], 0x0 cwrite $05, [$00 + @LOAD_STORE_HI], 0x0
jump #cpy_header jump #cpy_header
store $07, [$04 + 0x004], 0x4 store $07, [$04 + 0x004]!, 0x0
cpy_exit: cpy_exit:
waitin waitin
mov $01, $data mov $01, $data
@@ -189,7 +189,7 @@ mov $02, $data
cwrite $data, [$00 + @LOAD_STORE_HI], 0x0 cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
mov $rem, $data mov $rem, $data
cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0 cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
(rep)store $memdata, [$02 + 0x004], 0x4 (rep)store $memdata, [$02 + 0x004]!, 0x0
waitin waitin
mov $01, $data mov $01, $data

View File

@@ -224,7 +224,9 @@ Control registers are a special register space that can only be read/written
directly by CP through ``cread``/``cwrite`` instructions:: directly by CP through ``cread``/``cwrite`` instructions::
- ``cread $dst, [$off + addr], flags`` - ``cread $dst, [$off + addr], flags``
- ``cread $dst, [$off + addr]!, flags``
- ``cwrite $src, [$off + addr], flags`` - ``cwrite $src, [$off + addr], flags``
- ``cwrite $src, [$off + addr]!, flags``
Control registers ``0x000`` to ``0x0ff`` are private registers used to control Control registers ``0x000`` to ``0x0ff`` are private registers used to control
the CP, for example to indicate where to read from memory or (normal) the CP, for example to indicate where to read from memory or (normal)
@@ -235,8 +237,8 @@ packets.
In cases where no offset is needed, ``$00`` is frequently used as the offset. In cases where no offset is needed, ``$00`` is frequently used as the offset.
A value of 4 for ``flags`` is known to be a pre-increment mode that writes the The addressing mode with ``!`` is a pre-increment mode that writes the final
final address ``$off + addr`` to ``$off``, it's not known what other values do. address ``$off + addr`` to ``$off``.
For example, the following sequences sets:: For example, the following sequences sets::

View File

@@ -176,6 +176,7 @@ struct afuc_instr {
bool has_bit : 1; bool has_bit : 1;
bool is_literal : 1; bool is_literal : 1;
bool rep : 1; bool rep : 1;
bool preincrement : 1;
}; };
void print_control_reg(uint32_t id); void print_control_reg(uint32_t id);

View File

@@ -603,17 +603,19 @@ SOFTWARE.
</bitset> </bitset>
<bitset name="#control" extends="#instruction-rep"> <bitset name="#control" extends="#instruction-rep">
<field name="FLAGS" low="12" high="14" type="hex"/> <field name="FLAGS" low="12" high="13" type="hex"/>
<field name="PREINCREMENT" pos="14" type="bool" display="!"/>
<field name="OFFSET" low="21" high="25" type="#src"/> <field name="OFFSET" low="21" high="25" type="#src"/>
<encode> <encode>
<map name="FLAGS">src->bit</map> <map name="FLAGS">src->bit</map>
<map name="PREINCREMENT">src->preincrement</map>
</encode> </encode>
</bitset> </bitset>
<bitset name="#store" extends="#control"> <bitset name="#store" extends="#control">
<display> <display>
{REP}store {SRC}, [{OFFSET} + 0x{IMMED}], 0x{FLAGS} {REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
</display> </display>
<doc> <doc>
@@ -643,20 +645,48 @@ SOFTWARE.
<pattern low="27" high="31">10100</pattern> <pattern low="27" high="31">10100</pattern>
</bitset> </bitset>
<expr name="#pre-increment">
{PREINCREMENT}
</expr>
<bitset name="#control-base" size="12">
<!--
In pre-increment mode, the register is usually in the offset
instead of the base, so always print it as an immediate.
-->
<override expr="#pre-increment">
<display>
0x{IMMED}
</display>
<field name="IMMED" low="0" high="11" type="hex"/>
</override>
<display>
{CONTROLREG}
</display>
<field name="CONTROLREG" low="0" high="11" type="custom"/>
<encode type="uint32_t">
<map name="IMMED">src</map>
<map name="CONTROLREG">src</map>
</encode>
<decode/>
</bitset>
<bitset name="#cwrite" extends="#control"> <bitset name="#cwrite" extends="#control">
<doc>Write to a control register.</doc> <doc>Write to a control register.</doc>
<display> <display>
{REP}cwrite {SRC}, [{OFFSET} + {CONTROLREG}], 0x{FLAGS} {REP}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</display> </display>
<field name="CONTROLREG" low="0" high="11" type="custom"/> <field name="BASE" low="0" high="11" type="#control-base">
<param name="PREINCREMENT"/>
</field>
<field name="SRC" low="16" high="20" type="#src"/> <field name="SRC" low="16" high="20" type="#src"/>
<pattern low="27" high="31">10101</pattern> <pattern low="27" high="31">10101</pattern>
<encode> <encode>
<map name="SRC">src->src1</map> <map name="SRC">src->src1</map>
<map name="OFFSET">src->src2</map> <map name="OFFSET">src->src2</map>
<map name="CONTROLREG">src->immed</map> <map name="BASE">src->immed</map>
</encode> </encode>
</bitset> </bitset>
@@ -670,14 +700,33 @@ SOFTWARE.
<gen min="6"/> <gen min="6"/>
</bitset> </bitset>
<bitset name="#sqe-base" size="12">
<override expr="#pre-increment">
<display>
0x{IMMED}
</display>
<field name="IMMED" low="0" high="11" type="uint"/>
</override>
<display>
{SQEREG}
</display>
<field name="SQEREG" low="0" high="11" type="custom"/>
<encode type="uint32_t">
<map name="IMMED">src</map>
<map name="SQEREG">src</map>
</encode>
</bitset>
<bitset name="swrite" extends="#control"> <bitset name="swrite" extends="#control">
<doc>Write to a SQE register.</doc> <doc>Write to a SQE register.</doc>
<gen min="6"/> <gen min="6"/>
<display> <display>
{REP}swrite {SRC}, [{OFFSET} + {SQEREG}], 0x{FLAGS} {REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</display> </display>
<field name="SQEREG" low="0" high="11" type="custom"/> <field name="BASE" low="0" high="11" type="#sqe-base">
<param name="PREINCREMENT"/>
</field>
<field name="SRC" low="16" high="20" type="#src"/> <field name="SRC" low="16" high="20" type="#src"/>
<pattern pos="15">1</pattern> <pattern pos="15">1</pattern>
<pattern low="27" high="31">10101</pattern> <pattern low="27" high="31">10101</pattern>
@@ -685,7 +734,7 @@ SOFTWARE.
<encode> <encode>
<map name="SRC">src->src1</map> <map name="SRC">src->src1</map>
<map name="OFFSET">src->src2</map> <map name="OFFSET">src->src2</map>
<map name="SQEREG">src->immed</map> <map name="BASE">src->immed</map>
</encode> </encode>
</bitset> </bitset>
@@ -697,7 +746,7 @@ SOFTWARE.
restored. restored.
</doc> </doc>
<display> <display>
{REP}load {DST}, [{OFFSET} + 0x{IMMED}], 0x{FLAGS} {REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
</display> </display>
<field name="IMMED" low="0" high="11" type="hex"/> <field name="IMMED" low="0" high="11" type="hex"/>
@@ -713,15 +762,17 @@ SOFTWARE.
<bitset name="#cread" extends="#control"> <bitset name="#cread" extends="#control">
<doc>Read from a control register.</doc> <doc>Read from a control register.</doc>
<display> <display>
{REP}cread {DST}, [{OFFSET} + {CONTROLREG}], 0x{FLAGS} {REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</display> </display>
<field name="CONTROLREG" low="0" high="11" type="custom"/> <field name="BASE" low="0" high="11" type="#control-base">
<param name="PREINCREMENT"/>
</field>
<field name="DST" low="16" high="20" type="#dst"/> <field name="DST" low="16" high="20" type="#dst"/>
<encode> <encode>
<map name="OFFSET">src->src1</map> <map name="OFFSET">src->src1</map>
<map name="CONTROLREG">src->immed</map> <map name="BASE">src->immed</map>
</encode> </encode>
</bitset> </bitset>
@@ -742,15 +793,17 @@ SOFTWARE.
<doc>Read from a SQE register.</doc> <doc>Read from a SQE register.</doc>
<gen min="6"/> <gen min="6"/>
<display> <display>
{REP}sread {DST}, [{OFFSET} + {SQEREG}], 0x{FLAGS} {REP}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</display> </display>
<field name="SQEREG" low="0" high="11" type="custom"/> <field name="BASE" low="0" high="11" type="#sqe-base">
<param name="PREINCREMENT"/>
</field>
<field name="DST" low="16" high="20" type="#dst"/> <field name="DST" low="16" high="20" type="#dst"/>
<encode> <encode>
<map name="OFFSET">src->src1</map> <map name="OFFSET">src->src1</map>
<map name="SQEREG">src->immed</map> <map name="BASE">src->immed</map>
</encode> </encode>
<pattern pos="15">1</pattern> <pattern pos="15">1</pattern>

View File

@@ -216,7 +216,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
uint32_t src2 = emu_get_gpr_reg(emu, instr->src2); uint32_t src2 = emu_get_gpr_reg(emu, instr->src2);
if (instr->bit == 0x4) { if (instr->preincrement) {
emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed); emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed);
} else if (instr->bit && !emu->quiet) { } else if (instr->bit && !emu->quiet) {
printf("unhandled flags: %x\n", instr->bit); printf("unhandled flags: %x\n", instr->bit);
@@ -228,7 +228,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
case OPC_CREAD: { case OPC_CREAD: {
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
if (instr->bit == 0x4) { if (instr->preincrement) {
emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed); emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed);
} else if (instr->bit && !emu->quiet) { } else if (instr->bit && !emu->quiet) {
printf("unhandled flags: %x\n", instr->bit); printf("unhandled flags: %x\n", instr->bit);
@@ -242,7 +242,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
uint32_t src2 = emu_get_gpr_reg(emu, instr->src2); uint32_t src2 = emu_get_gpr_reg(emu, instr->src2);
if (instr->bit == 0x4) { if (instr->preincrement) {
emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed); emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed);
} else if (instr->bit && !emu->quiet) { } else if (instr->bit && !emu->quiet) {
printf("unhandled flags: %x\n", instr->bit); printf("unhandled flags: %x\n", instr->bit);
@@ -254,7 +254,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
case OPC_SREAD: { case OPC_SREAD: {
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
if (instr->bit == 0x4) { if (instr->preincrement) {
emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed); emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed);
} else if (instr->bit && !emu->quiet) { } else if (instr->bit && !emu->quiet) {
printf("unhandled flags: %x\n", instr->bit); printf("unhandled flags: %x\n", instr->bit);
@@ -268,7 +268,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
uintptr_t addr = load_store_addr(emu, instr->src1) + uintptr_t addr = load_store_addr(emu, instr->src1) +
instr->immed; instr->immed;
if (instr->bit == 0x4) { if (instr->preincrement) {
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed); emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed);
} else if (instr->bit && !emu->quiet) { } else if (instr->bit && !emu->quiet) {
@@ -285,7 +285,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
uintptr_t addr = load_store_addr(emu, instr->src2) + uintptr_t addr = load_store_addr(emu, instr->src2) +
instr->immed; instr->immed;
if (instr->bit == 0x4) { if (instr->preincrement) {
uint32_t src2 = emu_get_gpr_reg(emu, instr->src2); uint32_t src2 = emu_get_gpr_reg(emu, instr->src2);
emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed); emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed);
} else if (instr->bit && !emu->quiet) { } else if (instr->bit && !emu->quiet) {

View File

@@ -100,6 +100,7 @@ extern YYSTYPE yylval;
"[" return '['; "[" return '[';
"]" return ']'; "]" return ']';
"+" return '+'; "+" return '+';
"!" return '!';
. fprintf(stderr, "error at line %d: Unknown token: %s\n", yyget_lineno(), yytext); yyterminate(); . fprintf(stderr, "error at line %d: Unknown token: %s\n", yyget_lineno(), yytext); yyterminate();

View File

@@ -262,11 +262,14 @@ store_op: T_OP_STORE { new_instr(OPC_STORE); }
| T_OP_CWRITE { new_instr(OPC_CWRITE); } | T_OP_CWRITE { new_instr(OPC_CWRITE); }
| T_OP_SWRITE { new_instr(OPC_SWRITE); } | T_OP_SWRITE { new_instr(OPC_SWRITE); }
load_instr: load_op reg ',' '[' reg '+' immediate ']' ',' immediate { preincrement:
dst($2); src1($5); immed($7); bit($10); | '!' { instr->preincrement = true; }
load_instr: load_op reg ',' '[' reg '+' immediate ']' preincrement ',' immediate {
dst($2); src1($5); immed($7); bit($11);
} }
store_instr: store_op reg ',' '[' reg '+' immediate ']' ',' immediate { store_instr: store_op reg ',' '[' reg '+' immediate ']' preincrement ',' immediate {
src1($2); src2($5); immed($7); bit($10); src1($2); src2($5); immed($7); bit($11);
} }
branch_op: T_OP_BRNE { new_instr(OPC_BRNE); } branch_op: T_OP_BRNE { new_instr(OPC_BRNE); }