From da3cf26564b3133d7c33d631cb04ad64c04aa0f7 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Tue, 12 Dec 2023 02:19:20 +0100 Subject: [PATCH] freedreno/afuc: Add separate "SQE registers" It seems like starting with a6xx, the SQE has a special register space for reading/writing the state of the processor itself, mainly used for saving/restoring its state in preemption. Add support for disassembling it, removing one of the unknown flags bits. Part-of: --- .../.gitlab-ci/reference/afuc_test.asm | 311 +++++++++--------- .../.gitlab-ci/reference/afuc_test.fw | Bin 996 -> 1020 bytes src/freedreno/.gitlab-ci/traces/afuc_test.asm | 10 +- src/freedreno/afuc/README.rst | 11 + src/freedreno/afuc/afuc.h | 8 + src/freedreno/afuc/afuc.xml | 38 +++ src/freedreno/afuc/asm.c | 7 + src/freedreno/afuc/asm.h | 1 + src/freedreno/afuc/disasm.c | 20 ++ src/freedreno/afuc/emu-regs.c | 15 + src/freedreno/afuc/emu-ui.c | 56 +++- src/freedreno/afuc/emu.c | 26 ++ src/freedreno/afuc/emu.h | 15 +- src/freedreno/afuc/lexer.l | 3 + src/freedreno/afuc/parser.y | 7 + src/freedreno/afuc/util.c | 20 ++ src/freedreno/afuc/util.h | 3 + .../registers/adreno/adreno_control_regs.xml | 32 +- 18 files changed, 420 insertions(+), 163 deletions(-) diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.asm b/src/freedreno/.gitlab-ci/reference/afuc_test.asm index 6d39634487a..bd3ac583838 100644 --- a/src/freedreno/.gitlab-ci/reference/afuc_test.asm +++ b/src/freedreno/.gitlab-ci/reference/afuc_test.asm @@ -2,7 +2,7 @@ ; Version: 01000001 [01000001] -[01000078] +[0100007e] mov $01, 0x830 ; CP_SQE_INSTR_BASE mov $02, 0x2 cwrite $01, [$00 + @REG_READ_ADDR], 0x0 @@ -56,27 +56,35 @@ mov $02, 0xff waitin mov $01, $data -CP_SET_SECURE_MODE: -mov $02, $data -setsecure $02, #l52 -l50: -jump #l50 -nop -l52: +CP_SET_BIN_DATA5: +sread $02, [$00 + %SP], 0x0 +swrite $02, [$00 + %SP], 0x0 +mov $02, 0x7 +(rep)swrite $data, [$02 + 0x001], 0x4 waitin mov $01, $data -fxn54: -l54: +CP_SET_SECURE_MODE: +mov $02, $data +setsecure $02, #l58 +l56: +jump #l56 +nop +l58: +waitin +mov $01, $data + +fxn60: +l60: cmp $04, $02, $03 -breq $04, b0, #l61 -brne $04, b1, #l59 -breq $04, b2, #l54 +breq $04, b0, #l67 +brne $04, b1, #l65 +breq $04, b2, #l60 sub $03, $03, $02 -l59: -jump #l54 +l65: +jump #l60 sub $02, $02, $03 -l61: +l67: ret nop @@ -85,7 +93,7 @@ cwrite $data, [$00 + @REG_READ_ADDR], 0x0 add $02, $regdata, 0x42 addhi $03, $00, $regdata sub $02, $02, $regdata -call #fxn54 +call #fxn60 subhi $03, $03, $regdata and $02, $02, $regdata or $02, $02, 0x1 @@ -110,14 +118,14 @@ mov $03, $data mov $04, $data mov $05, $data mov $06, $data -l90: -breq $06, 0x0, #l96 +l96: +breq $06, 0x0, #l102 cwrite $03, [$00 + @LOAD_STORE_HI], 0x0 load $07, [$02 + 0x4], 0x4 cwrite $05, [$00 + @LOAD_STORE_HI], 0x0 -jump #l90 +jump #l96 store $07, [$04 + 0x4], 0x4 -l96: +l102: waitin mov $01, $data @@ -134,15 +142,15 @@ mov $01, $data IN_PREEMPT: cread $02, [$00 + 0x101], 0x0 -brne $02, 0x1, #l116 +brne $02, 0x1, #l122 nop -preemptleave #l50 +preemptleave #l56 nop nop nop waitin mov $01, $data -l116: +l122: iret nop @@ -196,7 +204,6 @@ CP_REG_WRITE: CP_REG_WR_NO_CTXT: CP_RUN_OPENCL: CP_SCRATCH_TO_REG: -CP_SET_BIN_DATA5: CP_SET_BIN_DATA5_OFFSET: CP_SET_CONSTANT: CP_SET_CTXSWITCH_IB: @@ -268,131 +275,131 @@ UNKN96: UNKN97: waitin mov $01, $data -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[0000006b] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[0000003f] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000025] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000022] -[00000076] -[00000076] -[00000076] -[0000002c] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[00000071] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[00000045] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] [00000030] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000062] -[00000076] -[00000055] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] -[00000076] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[00000025] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[00000022] +[0000007c] +[0000007c] +[0000007c] +[0000002c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[00000036] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[00000068] +[0000007c] +[0000005b] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] +[0000007c] diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.fw b/src/freedreno/.gitlab-ci/reference/afuc_test.fw index e48cb0bde0bf2dcfbea20990a6efc4855922677a..9d04c143a1f33063ecebc58e3be9e40f7248df09 100644 GIT binary patch literal 1020 zcmb`CKTjJ$6vSuu&dUZvas|bKY#$(uQ&6}<6e%2|C~eA~r zLRzIuMg=9~V@d<{K)_2v_Qu(pfM+!h))ZPVe6&KLXN>bSQMmTRJzv4T2J8xohi|n^ zetzlUwi&BM$Z1_E`IIZUYZHH%Q$h_*!|BUGl2sAuMSd=5b{XlX`5Os0B7z$KyNnn vmwv6Mw2ZuLK zUV2Nqm-Rl*;R@GM`PyVh_W}~T4z+lk)y{q*FJJw=s8%)a>DhxwOV?*MZb^yoci!i@ zU0E%$UbeAOdZ})fZErz8RZ+6ttnptM?*RNTgR_|BCAIC&=n>$`@z!($?*f?=8C9;O z8>yQ}j5L#0(neZHJL~e^*Yd$Kb8G)%c9I_HB7-DFaC)AD9XjcWqZ}H-XYS&pcM4ID z$6Y#z>CKt5;_FVt>7On}9wDq_h4E8rF$`49Sw}6K`tswgrdKF_%km$3>odpxX-@sj e@9up+$m{vy9r~ib%lS(!^^2T^kDjR?^u7UlDykj; diff --git a/src/freedreno/.gitlab-ci/traces/afuc_test.asm b/src/freedreno/.gitlab-ci/traces/afuc_test.asm index 089100d2d0a..3d1997d54e1 100644 --- a/src/freedreno/.gitlab-ci/traces/afuc_test.asm +++ b/src/freedreno/.gitlab-ci/traces/afuc_test.asm @@ -94,6 +94,15 @@ mov $02, 0xff waitin mov $01, $data +CP_SET_BIN_DATA5: +; test SQE registers +sread $02, [$00 + %SP], 0x0 +swrite $02, [$00 + %SP], 0x0 +mov $02, 7 +(rep)swrite $data, [$02 + 1], 0x4 +waitin +mov $01, $data + CP_SET_SECURE_MODE: ; test setsecure mov $02, $data @@ -244,7 +253,6 @@ CP_IM_LOAD_IMMEDIATE: CP_BLIT: CP_SET_CONSTANT: CP_SET_BIN_DATA5_OFFSET: -CP_SET_BIN_DATA5: UNKN48: CP_RUN_OPENCL: CP_LOAD_STATE6_GEOM: diff --git a/src/freedreno/afuc/README.rst b/src/freedreno/afuc/README.rst index c9e70e11f8a..e8f5fd35a30 100644 --- a/src/freedreno/afuc/README.rst +++ b/src/freedreno/afuc/README.rst @@ -276,6 +276,17 @@ but on a6xx:: cwrite $0b, [$05 + @IB1_BASE+0x1], 0x0 cwrite $04, [$05 + @IB1_DWORDS], 0x0 +.. _afuc-sqe-regs: + +SQE Registers +============= + +Starting with a6xx, the state of the SQE processor itself can be accessed +through ``sread``/``swrite`` instructions that work identically to +``cread``/``cwrite``. For example, this includes the state of the +``call``/``ret`` stack. This is mainly used during the preemption routine but +it's also used to set the entrypoint for preemption. + .. _afuc-read: Reading Memory and Registers diff --git a/src/freedreno/afuc/afuc.h b/src/freedreno/afuc/afuc.h index c45e89d776f..2a2f4157bf6 100644 --- a/src/freedreno/afuc/afuc.h +++ b/src/freedreno/afuc/afuc.h @@ -103,6 +103,13 @@ typedef enum { OPC_STORE, OPC_LOAD, + /* A6xx added new opcodes that let you read/write the state of the + * SQE processor itself, like the call stack. This is mostly used by + * preemption but is also used to set the preempt routine entrypoint. + */ + OPC_SREAD, + OPC_SWRITE, + OPC_BRNEI, /* relative branch (if $src != immed) */ OPC_BREQI, /* relative branch (if $src == immed) */ OPC_BRNEB, /* relative branch (if bit not set) */ @@ -172,6 +179,7 @@ struct afuc_instr { }; void print_control_reg(uint32_t id); +void print_sqe_reg(uint32_t id); void print_pipe_reg(uint32_t id); #endif /* _AFUC_H_ */ diff --git a/src/freedreno/afuc/afuc.xml b/src/freedreno/afuc/afuc.xml index 80bde72a283..e07ae81bc08 100644 --- a/src/freedreno/afuc/afuc.xml +++ b/src/freedreno/afuc/afuc.xml @@ -670,6 +670,25 @@ SOFTWARE. + + Write to a SQE register. + + + {REP}swrite {SRC}, [{OFFSET} + {SQEREG}], 0x{FLAGS} + + + + + 1 + 10101 + + + src->src1 + src->src2 + src->immed + + + @@ -719,6 +738,25 @@ SOFTWARE. 10111 + + Read from a SQE register. + + + {REP}sread {DST}, [{OFFSET} + {SQEREG}], 0x{FLAGS} + + + + + + + src->src1 + src->immed + + + 1 + 10111 + + diff --git a/src/freedreno/afuc/asm.c b/src/freedreno/afuc/asm.c index 545aac09a54..a38bddf39e0 100644 --- a/src/freedreno/afuc/asm.c +++ b/src/freedreno/afuc/asm.c @@ -210,6 +210,13 @@ parse_control_reg(const char *name) return afuc_control_reg(name + 1); } +unsigned +parse_sqe_reg(const char *name) +{ + /* skip leading "%" */ + return afuc_sqe_reg(name + 1); +} + static void emit_jumptable(int outfd) { diff --git a/src/freedreno/afuc/asm.h b/src/freedreno/afuc/asm.h index fa899fe531c..ced8c6a2546 100644 --- a/src/freedreno/afuc/asm.h +++ b/src/freedreno/afuc/asm.h @@ -90,6 +90,7 @@ parse_bit(const char *str) } unsigned parse_control_reg(const char *name); +unsigned parse_sqe_reg(const char *name); /* string trailing ':' off label: */ static inline const char * diff --git a/src/freedreno/afuc/disasm.c b/src/freedreno/afuc/disasm.c index fd9e0de7b96..4de6def772f 100644 --- a/src/freedreno/afuc/disasm.c +++ b/src/freedreno/afuc/disasm.c @@ -88,6 +88,18 @@ print_control_reg(uint32_t id) } } +void +print_sqe_reg(uint32_t id) +{ + char *name = afuc_sqe_reg_name(id); + if (name) { + printf("@%s", name); + free(name); + } else { + printf("0x%03x", id); + } +} + void print_pipe_reg(uint32_t id) { @@ -118,6 +130,14 @@ field_print_cb(struct isa_print_state *state, const char *field_name, uint64_t v } else { isa_print(state, "0x%03x", (unsigned)val); } + } else if (!strcmp(field_name, "SQEREG")) { + char *name = afuc_sqe_reg_name(val); + if (name) { + isa_print(state, "%%%s", name); + free(name); + } else { + isa_print(state, "0x%03x", (unsigned)val); + } } } diff --git a/src/freedreno/afuc/emu-regs.c b/src/freedreno/afuc/emu-regs.c index 7d6f8b38c4b..cc514453c04 100644 --- a/src/freedreno/afuc/emu-regs.c +++ b/src/freedreno/afuc/emu-regs.c @@ -106,6 +106,21 @@ emu_set_control_reg(struct emu *emu, unsigned n, uint32_t val) } } +uint32_t +emu_get_sqe_reg(struct emu *emu, unsigned n) +{ + assert(n < ARRAY_SIZE(emu->sqe_regs.val)); + return emu->sqe_regs.val[n]; +} + +void +emu_set_sqe_reg(struct emu *emu, unsigned n, uint32_t val) +{ + assert(n < ARRAY_SIZE(emu->sqe_regs.val)); + BITSET_SET(emu->sqe_regs.written, n); + emu->sqe_regs.val[n] = val; +} + static uint32_t emu_get_pipe_reg(struct emu *emu, unsigned n) { diff --git a/src/freedreno/afuc/emu-ui.c b/src/freedreno/afuc/emu-ui.c index 240aac31685..4d2753bf4b0 100644 --- a/src/freedreno/afuc/emu-ui.c +++ b/src/freedreno/afuc/emu-ui.c @@ -223,6 +223,28 @@ dump_control_register(struct emu *emu, unsigned n) } } +static void +dump_sqe_register(struct emu *emu, unsigned n) +{ + printf(" SQE: "); + print_sqe_reg(n); + printf(": "); + if (BITSET_TEST(emu->sqe_regs.written, n)) { + printdelta("%08x\n", emu->sqe_regs.val[n]); + } else { + printf("%08x\n", emu->sqe_regs.val[n]); + } +} + +static void +dump_sqe_registers(struct emu *emu) +{ + for (unsigned i = 0; i < ARRAY_SIZE(emu->sqe_regs.val); i++) { + dump_sqe_register(emu, i); + } +} + + static void dump_gpumem(struct emu *emu, uintptr_t addr) { @@ -289,6 +311,24 @@ emu_dump_control_prompt(struct emu *emu) dump_control_register(emu, offset); } +static void +emu_write_sqe_prompt(struct emu *emu) +{ + clear_line(); + printf(" SQE register (name or offset) and value: "); + + const char *name; + const char *value; + + if (read_two_values(&name, &value)) + return; + + unsigned offset = afuc_sqe_reg(name); + uint32_t val = strtoul(value, NULL, 0); + + emu_set_sqe_reg(emu, offset, val); +} + static void emu_write_gpu_prompt(struct emu *emu) { @@ -364,7 +404,7 @@ emu_dump_prompt(struct emu *emu) { do { clear_line(); - printf(" dump: GPR (r)egisters, (c)ontrol register, (g)pu register, (m)emory: "); + printf(" dump: GPR (r)egisters, (c)ontrol register, (s)qe registers, (g)pu register, (m)emory: "); int c = readchar(); printf("%c\n", c); @@ -375,6 +415,10 @@ emu_dump_prompt(struct emu *emu) */ dump_gpr_registers(emu); break; + } else if (c == 's') { + /* Similarly, just dump all the SQE registers */ + dump_sqe_registers(emu); + break; } else if (c == 'c') { emu_dump_control_prompt(emu); break; @@ -396,7 +440,7 @@ emu_write_prompt(struct emu *emu) { do { clear_line(); - printf(" write: GPR (r)egister, (c)ontrol register, (g)pu register, (m)emory: "); + printf(" write: GPR (r)egister, (c)ontrol register, (s)sqe register, (g)pu register, (m)emory: "); int c = readchar(); printf("%c\n", c); @@ -404,6 +448,9 @@ emu_write_prompt(struct emu *emu) if (c == 'r') { emu_write_gpr_prompt(emu); break; + } else if (c == 's') { + emu_write_sqe_prompt(emu); + break; } else if (c == 'c') { emu_write_control_prompt(emu); break; @@ -512,6 +559,7 @@ void emu_clear_state_change(struct emu *emu) { memset(emu->control_regs.written, 0, sizeof(emu->control_regs.written)); + memset(emu->sqe_regs.written, 0, sizeof(emu->sqe_regs.written)); memset(emu->pipe_regs.written, 0, sizeof(emu->pipe_regs.written)); memset(emu->gpu_regs.written, 0, sizeof(emu->gpu_regs.written)); memset(emu->gpr_regs.written, 0, sizeof(emu->gpr_regs.written)); @@ -543,6 +591,10 @@ emu_dump_state_change(struct emu *emu) dump_control_register(emu, i); } + BITSET_FOREACH_SET (i, emu->sqe_regs.written, EMU_NUM_SQE_REGS) { + dump_sqe_register(emu, i); + } + if (emu->gpumem_written != ~0) { dump_gpumem(emu, emu->gpumem_written); } diff --git a/src/freedreno/afuc/emu.c b/src/freedreno/afuc/emu.c index 2bdda3a5c97..29a482a8748 100644 --- a/src/freedreno/afuc/emu.c +++ b/src/freedreno/afuc/emu.c @@ -235,6 +235,32 @@ emu_instr(struct emu *emu, struct afuc_instr *instr) emu_get_control_reg(emu, src1 + instr->immed)); break; } + case OPC_SWRITE: { + uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); + uint32_t src2 = emu_get_gpr_reg(emu, instr->src2); + + if (instr->bit == 0x4) { + emu_set_gpr_reg(emu, instr->src2, src2 + instr->immed); + } else if (instr->bit && !emu->quiet) { + printf("unhandled flags: %x\n", instr->bit); + } + + emu_set_sqe_reg(emu, src2 + instr->immed, src1); + break; + } + case OPC_SREAD: { + uint32_t src1 = emu_get_gpr_reg(emu, instr->src1); + + if (instr->bit == 0x4) { + emu_set_gpr_reg(emu, instr->src1, src1 + instr->immed); + } else if (instr->bit && !emu->quiet) { + printf("unhandled flags: %x\n", instr->bit); + } + + emu_set_gpr_reg(emu, instr->dst, + emu_get_sqe_reg(emu, src1 + instr->immed)); + break; + } case OPC_LOAD: { uintptr_t addr = load_store_addr(emu, instr->src1) + instr->immed; diff --git a/src/freedreno/afuc/emu.h b/src/freedreno/afuc/emu.h index e978d097aaa..12834ed1b66 100644 --- a/src/freedreno/afuc/emu.h +++ b/src/freedreno/afuc/emu.h @@ -48,6 +48,13 @@ struct emu_control_regs { uint32_t val[EMU_NUM_CONTROL_REGS]; }; +#define EMU_NUM_SQE_REGS 0x10 + +struct emu_sqe_regs { + BITSET_DECLARE(written, EMU_NUM_SQE_REGS); + uint32_t val[EMU_NUM_SQE_REGS]; +}; + #define EMU_NUM_GPU_REGS 0x10000 struct emu_gpu_regs { @@ -166,6 +173,7 @@ struct emu { unsigned gpu_id; struct emu_control_regs control_regs; + struct emu_sqe_regs sqe_regs; struct emu_pipe_regs pipe_regs; struct emu_gpu_regs gpu_regs; struct emu_gpr_regs gpr_regs; @@ -185,7 +193,9 @@ struct emu { /* (r)un mode, don't stop for input until next waitin: */ bool run_mode; - /* carry-bits for add/sub for addhi/subhi */ + /* carry-bits for add/sub for addhi/subhi + * TODO: this is probably in a SQE register somewhere + */ uint32_t carry; /* call-stack of saved PCs.. I expect this to be a fixed size, but not @@ -252,6 +262,9 @@ void emu_set_gpu_reg(struct emu *emu, unsigned n, uint32_t val); uint32_t emu_get_control_reg(struct emu *emu, unsigned n); void emu_set_control_reg(struct emu *emu, unsigned n, uint32_t val); +uint32_t emu_get_sqe_reg(struct emu *emu, unsigned n); +void emu_set_sqe_reg(struct emu *emu, unsigned n, uint32_t val); + /* Register helpers for fixed fxn emulation, to avoid lots of boilerplate * for accessing other pipe/control registers. * diff --git a/src/freedreno/afuc/lexer.l b/src/freedreno/afuc/lexer.l index 9383ea1273e..5ee639a2972 100644 --- a/src/freedreno/afuc/lexer.l +++ b/src/freedreno/afuc/lexer.l @@ -47,6 +47,7 @@ extern YYSTYPE yylval; "$"[a-zA-Z][a-zA-Z0-9]* yylval.num = parse_reg(yytext); return T_REGISTER; "b"[0-9][0-9]* yylval.num = parse_bit(yytext); return T_BIT; "@"[a-zA-Z_][a-zA-Z0-9_]* yylval.num = parse_control_reg(yytext); return T_CONTROL_REG; +"%"[a-zA-Z_][a-zA-Z0-9_]* yylval.num = parse_sqe_reg(yytext); return T_SQE_REG; "#"[a-zA-Z_][a-zA-Z0-9_]* yylval.str = strdup(yytext+1); return T_LABEL_REF; /* label reference */ [a-zA-Z_][a-zA-Z0-9_]*":" yylval.str = parse_label_decl(yytext); return T_LABEL_DECL; /* label declaration */ "["[0-9a-fA-F][0-9a-fA-F]*"]" yylval.num = parse_literal(yytext); return T_LITERAL; @@ -78,6 +79,8 @@ extern YYSTYPE yylval; "mov" return TOKEN(T_OP_MOV); "cwrite" return TOKEN(T_OP_CWRITE); "cread" return TOKEN(T_OP_CREAD); +"swrite" return TOKEN(T_OP_SWRITE); +"sread" return TOKEN(T_OP_SREAD); "store" return TOKEN(T_OP_STORE); "load" return TOKEN(T_OP_LOAD); "brne" return TOKEN(T_OP_BRNE); diff --git a/src/freedreno/afuc/parser.y b/src/freedreno/afuc/parser.y index 39ce7f44c61..5fbfaf2d209 100644 --- a/src/freedreno/afuc/parser.y +++ b/src/freedreno/afuc/parser.y @@ -121,6 +121,7 @@ label(const char *str) %token T_INT %token T_HEX %token T_CONTROL_REG +%token T_SQE_REG %token T_LABEL_DECL %token T_LABEL_REF %token T_LITERAL @@ -153,6 +154,8 @@ label(const char *str) %token T_OP_MOV %token T_OP_CWRITE %token T_OP_CREAD +%token T_OP_SWRITE +%token T_OP_SREAD %token T_OP_STORE %token T_OP_LOAD %token T_OP_BRNE @@ -254,8 +257,10 @@ alu_instr: alu_2src_instr load_op: T_OP_LOAD { new_instr(OPC_LOAD); } | T_OP_CREAD { new_instr(OPC_CREAD); } +| T_OP_SREAD { new_instr(OPC_SREAD); } 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); @@ -286,4 +291,6 @@ immediate: T_HEX | T_INT | T_CONTROL_REG | T_CONTROL_REG '+' immediate { $$ = $1 + $3; } +| T_SQE_REG +| T_SQE_REG '+' immediate { $$ = $1 + $3; } diff --git a/src/freedreno/afuc/util.c b/src/freedreno/afuc/util.c index 65f7560a7ad..3789df46a6b 100644 --- a/src/freedreno/afuc/util.c +++ b/src/freedreno/afuc/util.c @@ -35,6 +35,7 @@ static struct rnndeccontext *ctx; static struct rnndb *db; static struct rnndomain *control_regs; +static struct rnndomain *sqe_regs; static struct rnndomain *pipe_regs; struct rnndomain *dom[2]; static struct rnnenum *pm4_packets; @@ -86,6 +87,24 @@ afuc_control_reg(const char *name) return reg(control_regs, "control", name); } +/** + * Map offset to SQE reg name (or NULL), caller frees + */ +char * +afuc_sqe_reg_name(unsigned id) +{ + return reg_name(sqe_regs, id); +} + +/** + * Map SQE reg name to offset. + */ +unsigned +afuc_sqe_reg(const char *name) +{ + return reg(sqe_regs, "SQE", name); +} + /** * Map offset to control reg name (or NULL), caller frees */ @@ -292,6 +311,7 @@ int afuc_util_init(int gpuver, bool colors) dom[0] = rnn_finddomain(db, name); dom[1] = rnn_finddomain(db, "AXXX"); control_regs = rnn_finddomain(db, control_reg_name); + sqe_regs = rnn_finddomain(db, "A6XX_SQE_REG"); pipe_regs = rnn_finddomain(db, pipe_reg_name); rnndec_varadd(ctx, "chip", variant); diff --git a/src/freedreno/afuc/util.h b/src/freedreno/afuc/util.h index e63de5e2769..f03af7c742d 100644 --- a/src/freedreno/afuc/util.h +++ b/src/freedreno/afuc/util.h @@ -33,6 +33,9 @@ unsigned afuc_control_reg(const char *name); char * afuc_control_reg_name(unsigned id); +unsigned afuc_sqe_reg(const char *name); +char * afuc_sqe_reg_name(unsigned id); + unsigned afuc_pipe_reg(const char *name); char * afuc_pipe_reg_name(unsigned id); bool afuc_pipe_reg_is_void(unsigned id); diff --git a/src/freedreno/registers/adreno/adreno_control_regs.xml b/src/freedreno/registers/adreno/adreno_control_regs.xml index 04697a78c60..0d28e0985f9 100644 --- a/src/freedreno/registers/adreno/adreno_control_regs.xml +++ b/src/freedreno/registers/adreno/adreno_control_regs.xml @@ -4,10 +4,34 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + + Instruction to jump to when the CP is preempted to perform a + context switch, initialized to entry 15 of the jump table at + bootup. + + + + Stack Pointer for call/ret return address stack + + + + + + + + + + + + + @@ -30,12 +54,6 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - - Instruction to jump to when the CP is preempted to perform a - context switch, initialized to entry 15 of the jump table at - bootup. - -