diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.asm b/src/freedreno/.gitlab-ci/reference/afuc_test.asm index bd3ac583838..93c70878dc9 100644 --- a/src/freedreno/.gitlab-ci/reference/afuc_test.asm +++ b/src/freedreno/.gitlab-ci/reference/afuc_test.asm @@ -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 diff --git a/src/freedreno/.gitlab-ci/traces/afuc_test.asm b/src/freedreno/.gitlab-ci/traces/afuc_test.asm index 3d1997d54e1..c5bb18072bd 100644 --- a/src/freedreno/.gitlab-ci/traces/afuc_test.asm +++ b/src/freedreno/.gitlab-ci/traces/afuc_test.asm @@ -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 diff --git a/src/freedreno/afuc/README.rst b/src/freedreno/afuc/README.rst index e8f5fd35a30..00f99a328c2 100644 --- a/src/freedreno/afuc/README.rst +++ b/src/freedreno/afuc/README.rst @@ -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:: diff --git a/src/freedreno/afuc/afuc.h b/src/freedreno/afuc/afuc.h index 2a2f4157bf6..dc082c9181a 100644 --- a/src/freedreno/afuc/afuc.h +++ b/src/freedreno/afuc/afuc.h @@ -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); diff --git a/src/freedreno/afuc/afuc.xml b/src/freedreno/afuc/afuc.xml index e07ae81bc08..303c472aefd 100644 --- a/src/freedreno/afuc/afuc.xml +++ b/src/freedreno/afuc/afuc.xml @@ -603,17 +603,19 @@ SOFTWARE. - + + src->bit + src->preincrement - {REP}store {SRC}, [{OFFSET} + 0x{IMMED}], 0x{FLAGS} + {REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS} @@ -643,20 +645,48 @@ SOFTWARE. 10100 + + {PREINCREMENT} + + + + + + + 0x{IMMED} + + + + + {CONTROLREG} + + + + src + src + + + + Write to a control register. - {REP}cwrite {SRC}, [{OFFSET} + {CONTROLREG}], 0x{FLAGS} + {REP}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS} - + + + 10101 src->src1 src->src2 - src->immed + src->immed @@ -670,14 +700,33 @@ SOFTWARE. + + + + 0x{IMMED} + + + + + {SQEREG} + + + + src + src + + + Write to a SQE register. - {REP}swrite {SRC}, [{OFFSET} + {SQEREG}], 0x{FLAGS} + {REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS} - + + + 1 10101 @@ -685,7 +734,7 @@ SOFTWARE. src->src1 src->src2 - src->immed + src->immed @@ -697,7 +746,7 @@ SOFTWARE. restored. - {REP}load {DST}, [{OFFSET} + 0x{IMMED}], 0x{FLAGS} + {REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS} @@ -713,15 +762,17 @@ SOFTWARE. Read from a control register. - {REP}cread {DST}, [{OFFSET} + {CONTROLREG}], 0x{FLAGS} + {REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS} - + + + src->src1 - src->immed + src->immed @@ -742,15 +793,17 @@ SOFTWARE. Read from a SQE register. - {REP}sread {DST}, [{OFFSET} + {SQEREG}], 0x{FLAGS} + {REP}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS} - + + + src->src1 - src->immed + src->immed 1 diff --git a/src/freedreno/afuc/emu.c b/src/freedreno/afuc/emu.c index 796b879c4a8..633ba6b76a0 100644 --- a/src/freedreno/afuc/emu.c +++ b/src/freedreno/afuc/emu.c @@ -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) { diff --git a/src/freedreno/afuc/lexer.l b/src/freedreno/afuc/lexer.l index 5ee639a2972..179b5484b67 100644 --- a/src/freedreno/afuc/lexer.l +++ b/src/freedreno/afuc/lexer.l @@ -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(); diff --git a/src/freedreno/afuc/parser.y b/src/freedreno/afuc/parser.y index 5fbfaf2d209..202f45c6ddd 100644 --- a/src/freedreno/afuc/parser.y +++ b/src/freedreno/afuc/parser.y @@ -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); }