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:
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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::
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
|
@@ -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) {
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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); }
|
||||
|
Reference in New Issue
Block a user