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

View File

@@ -90,7 +90,7 @@ CP_SCRATCH_WRITE:
; test (rep) + flags + non-zero offset with cwrite
; TODO: 0x4 flag is actually pre-increment addressing, handle it as such
mov $02, 0xff
(rep)cwrite $data, [$02 + 0x001], 0x4
(rep)cwrite $data, [$02 + 0x001]!, 0x0
waitin
mov $01, $data
@@ -99,7 +99,7 @@ CP_SET_BIN_DATA5:
sread $02, [$00 + %SP], 0x0
swrite $02, [$00 + %SP], 0x0
mov $02, 7
(rep)swrite $data, [$02 + 1], 0x4
(rep)swrite $data, [$02 + 1]!, 0x0
waitin
mov $01, $data
@@ -172,10 +172,10 @@ mov $06, $data
cpy_header:
breq $06, 0, #cpy_exit
cwrite $03, [$00 + @LOAD_STORE_HI], 0x0
load $07, [$02 + 0x004], 0x4
load $07, [$02 + 0x004]!, 0x0
cwrite $05, [$00 + @LOAD_STORE_HI], 0x0
jump #cpy_header
store $07, [$04 + 0x004], 0x4
store $07, [$04 + 0x004]!, 0x0
cpy_exit:
waitin
mov $01, $data
@@ -189,7 +189,7 @@ mov $02, $data
cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
mov $rem, $data
cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
(rep)store $memdata, [$02 + 0x004], 0x4
(rep)store $memdata, [$02 + 0x004]!, 0x0
waitin
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::
- ``cread $dst, [$off + addr], flags``
- ``cread $dst, [$off + addr]!, flags``
- ``cwrite $src, [$off + addr], flags``
- ``cwrite $src, [$off + addr]!, flags``
Control registers ``0x000`` to ``0x0ff`` are private registers used to control
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.
A value of 4 for ``flags`` is known to be a pre-increment mode that writes the
final address ``$off + addr`` to ``$off``, it's not known what other values do.
The addressing mode with ``!`` is a pre-increment mode that writes the final
address ``$off + addr`` to ``$off``.
For example, the following sequences sets::

View File

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

View File

@@ -603,17 +603,19 @@ SOFTWARE.
</bitset>
<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"/>
<encode>
<map name="FLAGS">src->bit</map>
<map name="PREINCREMENT">src->preincrement</map>
</encode>
</bitset>
<bitset name="#store" extends="#control">
<display>
{REP}store {SRC}, [{OFFSET} + 0x{IMMED}], 0x{FLAGS}
{REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
</display>
<doc>
@@ -643,20 +645,48 @@ SOFTWARE.
<pattern low="27" high="31">10100</pattern>
</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">
<doc>Write to a control register.</doc>
<display>
{REP}cwrite {SRC}, [{OFFSET} + {CONTROLREG}], 0x{FLAGS}
{REP}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</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"/>
<pattern low="27" high="31">10101</pattern>
<encode>
<map name="SRC">src->src1</map>
<map name="OFFSET">src->src2</map>
<map name="CONTROLREG">src->immed</map>
<map name="BASE">src->immed</map>
</encode>
</bitset>
@@ -670,14 +700,33 @@ SOFTWARE.
<gen min="6"/>
</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">
<doc>Write to a SQE register.</doc>
<gen min="6"/>
<display>
{REP}swrite {SRC}, [{OFFSET} + {SQEREG}], 0x{FLAGS}
{REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</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"/>
<pattern pos="15">1</pattern>
<pattern low="27" high="31">10101</pattern>
@@ -685,7 +734,7 @@ SOFTWARE.
<encode>
<map name="SRC">src->src1</map>
<map name="OFFSET">src->src2</map>
<map name="SQEREG">src->immed</map>
<map name="BASE">src->immed</map>
</encode>
</bitset>
@@ -697,7 +746,7 @@ SOFTWARE.
restored.
</doc>
<display>
{REP}load {DST}, [{OFFSET} + 0x{IMMED}], 0x{FLAGS}
{REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
</display>
<field name="IMMED" low="0" high="11" type="hex"/>
@@ -713,15 +762,17 @@ SOFTWARE.
<bitset name="#cread" extends="#control">
<doc>Read from a control register.</doc>
<display>
{REP}cread {DST}, [{OFFSET} + {CONTROLREG}], 0x{FLAGS}
{REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</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"/>
<encode>
<map name="OFFSET">src->src1</map>
<map name="CONTROLREG">src->immed</map>
<map name="BASE">src->immed</map>
</encode>
</bitset>
@@ -742,15 +793,17 @@ SOFTWARE.
<doc>Read from a SQE register.</doc>
<gen min="6"/>
<display>
{REP}sread {DST}, [{OFFSET} + {SQEREG}], 0x{FLAGS}
{REP}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
</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"/>
<encode>
<map name="OFFSET">src->src1</map>
<map name="SQEREG">src->immed</map>
<map name="BASE">src->immed</map>
</encode>
<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 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);
} else if (instr->bit && !emu->quiet) {
printf("unhandled flags: %x\n", instr->bit);
@@ -228,7 +228,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
case OPC_CREAD: {
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);
} else if (instr->bit && !emu->quiet) {
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 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);
} else if (instr->bit && !emu->quiet) {
printf("unhandled flags: %x\n", instr->bit);
@@ -254,7 +254,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
case OPC_SREAD: {
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);
} else if (instr->bit && !emu->quiet) {
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) +
instr->immed;
if (instr->bit == 0x4) {
if (instr->preincrement) {
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed);
} 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) +
instr->immed;
if (instr->bit == 0x4) {
if (instr->preincrement) {
uint32_t src2 = emu_get_gpr_reg(emu, instr->src2);
emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed);
} else if (instr->bit && !emu->quiet) {

View File

@@ -100,6 +100,7 @@ extern YYSTYPE yylval;
"[" return '[';
"]" return ']';
"+" return '+';
"!" return '!';
. 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_SWRITE { new_instr(OPC_SWRITE); }
load_instr: load_op reg ',' '[' reg '+' immediate ']' ',' immediate {
dst($2); src1($5); immed($7); bit($10);
preincrement:
| '!' { 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 {
src1($2); src2($5); immed($7); bit($10);
store_instr: store_op reg ',' '[' reg '+' immediate ']' preincrement ',' immediate {
src1($2); src2($5); immed($7); bit($11);
}
branch_op: T_OP_BRNE { new_instr(OPC_BRNE); }