diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.asm b/src/freedreno/.gitlab-ci/reference/afuc_test.asm
index 93c70878dc9..0bbdf37a4ba 100644
--- a/src/freedreno/.gitlab-ci/reference/afuc_test.asm
+++ b/src/freedreno/.gitlab-ci/reference/afuc_test.asm
@@ -2,37 +2,37 @@
; Version: 01000001
[01000001]
-[0100007e]
+[01000081]
mov $01, 0x830 ; CP_SQE_INSTR_BASE
mov $02, 0x2
-cwrite $01, [$00 + @REG_READ_ADDR], 0x0
-cwrite $02, [$00 + @REG_READ_DWORDS], 0x0
+cwrite $01, [$00 + @REG_READ_ADDR]
+cwrite $02, [$00 + @REG_READ_DWORDS]
mov $01, $regdata
mov $02, $regdata
add $01, $01, 0x4
addhi $02, $02, 0x0
mov $03, 0x1
-cwrite $01, [$00 + @MEM_READ_ADDR], 0x0
-cwrite $02, [$00 + @MEM_READ_ADDR+0x1], 0x0
-cwrite $03, [$00 + @MEM_READ_DWORDS], 0x0
+cwrite $01, [$00 + @MEM_READ_ADDR]
+cwrite $02, [$00 + @MEM_READ_ADDR+0x1]
+cwrite $03, [$00 + @MEM_READ_DWORDS]
rot $04, $memdata, 0x8
ushr $04, $04, 0x6
sub $04, $04, 0x4
add $01, $01, $04
addhi $02, $02, 0x0
mov $rem, 0x80
-cwrite $01, [$00 + @MEM_READ_ADDR], 0x0
-cwrite $02, [$00 + @MEM_READ_ADDR+0x1], 0x0
-cwrite $02, [$00 + @LOAD_STORE_HI], 0x0
-cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
-cwrite $00, [$00 + @PACKET_TABLE_WRITE_ADDR], 0x0
-(rep)cwrite $memdata, [$00 + @PACKET_TABLE_WRITE], 0x0
+cwrite $01, [$00 + @MEM_READ_ADDR]
+cwrite $02, [$00 + @MEM_READ_ADDR+0x1]
+cwrite $02, [$00 + @LOAD_STORE_HI]
+cwrite $rem, [$00 + @MEM_READ_DWORDS]
+cwrite $00, [$00 + @PACKET_TABLE_WRITE_ADDR]
+(rep)cwrite $memdata, [$00 + @PACKET_TABLE_WRITE]
mov $02, 0x883 ; CP_SCRATCH[0].REG
mov $03, 0xbeef
mov $04, 0xdead << 16
or $03, $03, $04
-cwrite $02, [$00 + @REG_WRITE_ADDR], 0x0
-cwrite $03, [$00 + @REG_WRITE], 0x0
+cwrite $02, [$00 + @REG_WRITE_ADDR]
+cwrite $03, [$00 + @REG_WRITE]
waitin
mov $01, $data
@@ -52,48 +52,53 @@ mov $01, $data
CP_SCRATCH_WRITE:
mov $02, 0xff
-(rep)cwrite $data, [$02 + 0x1]!, 0x0
+(rep)cwrite $data, [$02 + 0x1]!
+waitin
+mov $01, $data
+
+CP_SET_DRAW_STATE:
+(rep)(sds2)cwrite $data, [$00 + @DRAW_STATE_SET_HDR]
waitin
mov $01, $data
CP_SET_BIN_DATA5:
-sread $02, [$00 + %SP], 0x0
-swrite $02, [$00 + %SP], 0x0
+sread $02, [$00 + %SP]
+swrite $02, [$00 + %SP]
mov $02, 0x7
-(rep)swrite $data, [$02 + 0x1]!, 0x0
+(rep)swrite $data, [$02 + 0x1]!
waitin
mov $01, $data
CP_SET_SECURE_MODE:
mov $02, $data
-setsecure $02, #l58
-l56:
-jump #l56
+setsecure $02, #l61
+l59:
+jump #l59
nop
-l58:
+l61:
waitin
mov $01, $data
-fxn60:
-l60:
+fxn63:
+l63:
cmp $04, $02, $03
-breq $04, b0, #l67
-brne $04, b1, #l65
-breq $04, b2, #l60
+breq $04, b0, #l70
+brne $04, b1, #l68
+breq $04, b2, #l63
sub $03, $03, $02
-l65:
-jump #l60
+l68:
+jump #l63
sub $02, $02, $03
-l67:
+l70:
ret
nop
CP_REG_RMW:
-cwrite $data, [$00 + @REG_READ_ADDR], 0x0
+cwrite $data, [$00 + @REG_READ_ADDR]
add $02, $regdata, 0x42
addhi $03, $00, $regdata
sub $02, $02, $regdata
-call #fxn60
+call #fxn63
subhi $03, $03, $regdata
and $02, $02, $regdata
or $02, $02, 0x1
@@ -118,39 +123,39 @@ mov $03, $data
mov $04, $data
mov $05, $data
mov $06, $data
-l96:
-breq $06, 0x0, #l102
-cwrite $03, [$00 + @LOAD_STORE_HI], 0x0
-load $07, [$02 + 0x4]!, 0x0
-cwrite $05, [$00 + @LOAD_STORE_HI], 0x0
-jump #l96
-store $07, [$04 + 0x4]!, 0x0
-l102:
+l99:
+breq $06, 0x0, #l105
+cwrite $03, [$00 + @LOAD_STORE_HI]
+load $07, [$02 + 0x4]!
+cwrite $05, [$00 + @LOAD_STORE_HI]
+jump #l99
+store $07, [$04 + 0x4]!
+l105:
waitin
mov $01, $data
CP_MEM_TO_MEM:
-cwrite $data, [$00 + @MEM_READ_ADDR], 0x0
-cwrite $data, [$00 + @MEM_READ_ADDR+0x1], 0x0
+cwrite $data, [$00 + @MEM_READ_ADDR]
+cwrite $data, [$00 + @MEM_READ_ADDR+0x1]
mov $02, $data
-cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
+cwrite $data, [$00 + @LOAD_STORE_HI]
mov $rem, $data
-cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
-(rep)store $memdata, [$02 + 0x4]!, 0x0
+cwrite $rem, [$00 + @MEM_READ_DWORDS]
+(rep)store $memdata, [$02 + 0x4]!
waitin
mov $01, $data
IN_PREEMPT:
-cread $02, [$00 + 0x101], 0x0
-brne $02, 0x1, #l122
+cread $02, [$00 + 0x101]
+brne $02, 0x1, #l125
nop
-preemptleave #l56
+preemptleave #l59
nop
nop
nop
waitin
mov $01, $data
-l122:
+l125:
iret
nop
@@ -208,7 +213,6 @@ CP_SET_BIN_DATA5_OFFSET:
CP_SET_CONSTANT:
CP_SET_CTXSWITCH_IB:
CP_SET_DRAW_INIT_FLAGS:
-CP_SET_DRAW_STATE:
CP_SET_MARKER:
CP_SET_MODE:
CP_SET_PROTECTED_MODE:
@@ -275,131 +279,131 @@ UNKN96:
UNKN97:
waitin
mov $01, $data
-[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]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[00000074]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[00000048]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[00000033]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
[00000025]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
-[0000007c]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[00000030]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
[00000022]
-[0000007c]
-[0000007c]
-[0000007c]
+[0000007f]
+[0000007f]
+[0000007f]
[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]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[00000039]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000006b]
+[0000007f]
+[0000005e]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
+[0000007f]
diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.fw b/src/freedreno/.gitlab-ci/reference/afuc_test.fw
index 9d04c143a1f..70fc6b36b78 100644
Binary files a/src/freedreno/.gitlab-ci/reference/afuc_test.fw and b/src/freedreno/.gitlab-ci/reference/afuc_test.fw differ
diff --git a/src/freedreno/.gitlab-ci/traces/afuc_test.asm b/src/freedreno/.gitlab-ci/traces/afuc_test.asm
index c5bb18072bd..e8d6f8b2b42 100644
--- a/src/freedreno/.gitlab-ci/traces/afuc_test.asm
+++ b/src/freedreno/.gitlab-ci/traces/afuc_test.asm
@@ -32,8 +32,8 @@ loc02:
; packet table loading:
mov $01, 0x0830 ; CP_SQE_INSTR_BASE
mov $02, 0x0002
-cwrite $01, [$00 + @REG_READ_ADDR], 0x0
-cwrite $02, [$00 + @REG_READ_DWORDS], 0x0
+cwrite $01, [$00 + @REG_READ_ADDR]
+cwrite $02, [$00 + @REG_READ_DWORDS]
; move hi/lo of SQE fw addrs to registers:
mov $01, $regdata
mov $02, $regdata
@@ -41,9 +41,9 @@ mov $02, $regdata
add $01, $01, 0x0004
addhi $02, $02, 0x0000
mov $03, 0x0001
-cwrite $01, [$00 + @MEM_READ_ADDR], 0x0
-cwrite $02, [$00 + @MEM_READ_ADDR+0x1], 0x0
-cwrite $03, [$00 + @MEM_READ_DWORDS], 0x0
+cwrite $01, [$00 + @MEM_READ_ADDR]
+cwrite $02, [$00 + @MEM_READ_ADDR+0x1]
+cwrite $03, [$00 + @MEM_READ_DWORDS]
; read 2nd dword of fw, and add offset (minus 4 because we skipped first dword)
; to base address of sqe fw
rot $04, $memdata, 0x0008
@@ -54,19 +54,19 @@ addhi $02, $02, 0x0000
; load packet table:
mov $rem, 0x0080
-cwrite $01, [$00 + @MEM_READ_ADDR], 0x0
-cwrite $02, [$00 + @MEM_READ_ADDR+0x1], 0x0
-cwrite $02, [$00 + @LOAD_STORE_HI], 0x0
-cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
-cwrite $00, [$00 + @PACKET_TABLE_WRITE_ADDR], 0x0
-(rep)cwrite $memdata, [$00 + @PACKET_TABLE_WRITE], 0x0
+cwrite $01, [$00 + @MEM_READ_ADDR]
+cwrite $02, [$00 + @MEM_READ_ADDR+0x1]
+cwrite $02, [$00 + @LOAD_STORE_HI]
+cwrite $rem, [$00 + @MEM_READ_DWORDS]
+cwrite $00, [$00 + @PACKET_TABLE_WRITE_ADDR]
+(rep)cwrite $memdata, [$00 + @PACKET_TABLE_WRITE]
mov $02, 0x883
mov $03, 0xbeef
mov $04, 0xdead << 16
or $03, $03, $04
-cwrite $02, [$00 + @REG_WRITE_ADDR], 0x0
-cwrite $03, [$00 + @REG_WRITE], 0x0
+cwrite $02, [$00 + @REG_WRITE_ADDR]
+cwrite $03, [$00 + @REG_WRITE]
waitin
mov $01, $data
@@ -90,16 +90,22 @@ 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]!, 0x0
+(rep)cwrite $data, [$02 + 0x001]!
+waitin
+mov $01, $data
+
+CP_SET_DRAW_STATE:
+; test (sds)
+(rep)(sds2) cwrite $data, [$00 + @DRAW_STATE_SET_HDR]
waitin
mov $01, $data
CP_SET_BIN_DATA5:
; test SQE registers
-sread $02, [$00 + %SP], 0x0
-swrite $02, [$00 + %SP], 0x0
+sread $02, [$00 + %SP]
+swrite $02, [$00 + %SP]
mov $02, 7
-(rep)swrite $data, [$02 + 1]!, 0x0
+(rep)swrite $data, [$02 + 1]!
waitin
mov $01, $data
@@ -139,7 +145,7 @@ nop
CP_REG_RMW:
; Test various ALU instructions, and read/write $regdata
-cwrite $data, [$00 + @REG_READ_ADDR], 0x0
+cwrite $data, [$00 + @REG_READ_ADDR]
add $02, $regdata, 0x42
addhi $03, $00, $regdata
sub $02, $02, $regdata
@@ -171,11 +177,11 @@ mov $05, $data
mov $06, $data
cpy_header:
breq $06, 0, #cpy_exit
-cwrite $03, [$00 + @LOAD_STORE_HI], 0x0
-load $07, [$02 + 0x004]!, 0x0
-cwrite $05, [$00 + @LOAD_STORE_HI], 0x0
+cwrite $03, [$00 + @LOAD_STORE_HI]
+load $07, [$02 + 0x004]!
+cwrite $05, [$00 + @LOAD_STORE_HI]
jump #cpy_header
-store $07, [$04 + 0x004]!, 0x0
+store $07, [$04 + 0x004]!
cpy_exit:
waitin
mov $01, $data
@@ -183,19 +189,19 @@ mov $01, $data
CP_MEM_TO_MEM:
; implement CP_MEMCPY using mem read control regs
; tests @FOO+0x1 for 64-bit control regs, and reading/writing $rem
-cwrite $data, [$00 + @MEM_READ_ADDR], 0x0
-cwrite $data, [$00 + @MEM_READ_ADDR+1], 0x0
+cwrite $data, [$00 + @MEM_READ_ADDR]
+cwrite $data, [$00 + @MEM_READ_ADDR+1]
mov $02, $data
-cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
+cwrite $data, [$00 + @LOAD_STORE_HI]
mov $rem, $data
-cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
-(rep)store $memdata, [$02 + 0x004]!, 0x0
+cwrite $rem, [$00 + @MEM_READ_DWORDS]
+(rep)store $memdata, [$02 + 0x004]!
waitin
mov $01, $data
UNKN15:
; test preemptleave + iret + conditional branch w/ immed
-cread $02, [$00 + 0x101], 0x0
+cread $02, [$00 + 0x101]
brne $02, 0x0001, #exit_iret
nop
preemptleave #err
@@ -271,7 +277,6 @@ CP_INDIRECT_BUFFER:
CP_INTERRUPT:
CP_EXEC_CS_INDIRECT:
CP_MEM_TO_REG:
-CP_SET_DRAW_STATE:
CP_COND_EXEC:
CP_COND_WRITE5:
CP_EVENT_WRITE:
diff --git a/src/freedreno/afuc/README.rst b/src/freedreno/afuc/README.rst
index 00f99a328c2..9580ff6daa2 100644
--- a/src/freedreno/afuc/README.rst
+++ b/src/freedreno/afuc/README.rst
@@ -552,6 +552,28 @@ Although ``(xmovN)`` is often used in combination with ``(rep)``, it doesn't
have to be. For example, ``(xmov1)mov $data, $data`` moves the next 2 packet
words to 2 successive registers.
+.. _afuc-sds:
+
+Set Draw State
+--------------
+
+``(sdsN)`` is a modifier for ``cwrite`` used to accelerate
+``CP_SET_DRAW_STATE``. For each draw state group to update,
+``CP_SET_DRAW_STATE`` needs to copy 3 words from the packet containing the
+group to update, metadata, and base address plus size. Using the ``(sds2)``
+modifier as well as ``(rep)``, this can be accomplished in a single
+instruction::
+
+ (rep)(sds2)cwrite $data, [$00 + @DRAW_STATE_SET_HDR]
+
+The first word containing the header is written to ``@DRAW_STATE_SET_HDR``, and
+the second and third words containing the draw state base come from reading the
+source again twice and are written directly to the draw state RAM.
+
+In testing with other control registers, ``(sdsN)`` causes the source to be
+read ``N`` extra times and then thrown away. Only when used in combination with
+``@DRAW_STATE_SET_HDR`` do the extra source reads have an effect.
+
Packet Table
============
diff --git a/src/freedreno/afuc/afuc.h b/src/freedreno/afuc/afuc.h
index dc082c9181a..edd59631964 100644
--- a/src/freedreno/afuc/afuc.h
+++ b/src/freedreno/afuc/afuc.h
@@ -167,6 +167,7 @@ struct afuc_instr {
uint8_t shift;
uint8_t bit;
uint8_t xmov;
+ uint8_t sds;
uint32_t literal;
int offset;
const char *label;
diff --git a/src/freedreno/afuc/afuc.xml b/src/freedreno/afuc/afuc.xml
index 303c472aefd..5abc4e514a2 100644
--- a/src/freedreno/afuc/afuc.xml
+++ b/src/freedreno/afuc/afuc.xml
@@ -602,20 +602,30 @@ SOFTWARE.
01110
+
+
+ Used in combination with writing @DRAW_STATE_SET, the source is
+ read the specified number of times and used to set the draw
+ state base.
+
+
+
+
+
+
+
-
-
- {REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
+ {REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}
@@ -624,6 +634,7 @@ SOFTWARE.
restored.
+ 00
@@ -674,16 +685,18 @@ SOFTWARE.
Write to a control register.
- {REP}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
+ {REP}{SDS}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}
+
10101
+
@@ -721,12 +734,13 @@ SOFTWARE.
Write to a SQE register.
- {REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
+ {REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}
+ 00
1
10101
@@ -746,10 +760,11 @@ SOFTWARE.
restored.
- {REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
+ {REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}
+ 00
0
10110
@@ -762,12 +777,13 @@ SOFTWARE.
Read from a control register.
- {REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
+ {REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}
+ 00
@@ -793,12 +809,13 @@ SOFTWARE.
Read from a SQE register.
- {REP}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
+ {REP}{XREG}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}
+ 00
diff --git a/src/freedreno/afuc/emu-ds.c b/src/freedreno/afuc/emu-ds.c
index 39ccf1da3c5..22568a8e536 100644
--- a/src/freedreno/afuc/emu-ds.c
+++ b/src/freedreno/afuc/emu-ds.c
@@ -33,7 +33,7 @@
* Emulation for draw-state (ie. CP_SET_DRAW_STATE) related control registers:
*/
-EMU_CONTROL_REG(DRAW_STATE_SET);
+EMU_CONTROL_REG(DRAW_STATE_SET_HDR);
EMU_CONTROL_REG(DRAW_STATE_SEL);
EMU_CONTROL_REG(DRAW_STATE_ACTIVE_BITMASK);
EMU_CONTROL_REG(DRAW_STATE_HDR);
@@ -48,28 +48,30 @@ emu_get_draw_state_reg(struct emu *emu, unsigned n)
return emu->control_regs.val[n];
}
+void
+emu_set_draw_state_base(struct emu *emu, unsigned n, uint32_t val)
+{
+ struct emu_draw_state *ds = &emu->draw_state;
+
+ unsigned cur_idx = (emu_get_reg32(emu, &DRAW_STATE_SET_HDR) >> 24) & 0x1f;
+ ds->state[cur_idx].base_lohi[n] = val;
+}
+
void
emu_set_draw_state_reg(struct emu *emu, unsigned n, uint32_t val)
{
struct emu_draw_state *ds = &emu->draw_state;
unsigned cur_idx = emu_get_reg32(emu, &DRAW_STATE_SEL);
- if (n == emu_reg_offset(&DRAW_STATE_SET)) {
- if (ds->write_idx == 0) {
- cur_idx = (val >> 24) & 0x1f;
- ds->state[cur_idx].count = val & 0xffff;
- ds->state[cur_idx].mode_mask = (val >> 20) & 0x7;
+ if (n == emu_reg_offset(&DRAW_STATE_SET_HDR)) {
+ cur_idx = (val >> 24) & 0x1f;
+ ds->state[cur_idx].count = val & 0xffff;
+ ds->state[cur_idx].mode_mask = (val >> 20) & 0x7;
- unsigned active_mask = emu_get_reg32(emu, &DRAW_STATE_ACTIVE_BITMASK);
- active_mask |= (1 << cur_idx);
+ unsigned active_mask = emu_get_reg32(emu, &DRAW_STATE_ACTIVE_BITMASK);
+ active_mask |= (1 << cur_idx);
- emu_set_reg32(emu, &DRAW_STATE_ACTIVE_BITMASK, active_mask);
- emu_set_reg32(emu, &DRAW_STATE_SEL, cur_idx);
- } else {
- ds->state[cur_idx].base_lohi[ds->write_idx - 1] = val;
- }
-
- ds->write_idx = (ds->write_idx + 1) % 3;
+ emu_set_reg32(emu, &DRAW_STATE_ACTIVE_BITMASK, active_mask);
} else if (n == emu_reg_offset(&DRAW_STATE_SEL)) {
emu_set_reg32(emu, &DRAW_STATE_HDR, ds->state[val].hdr);
emu_set_reg64(emu, &DRAW_STATE_BASE, ds->state[val].base);
diff --git a/src/freedreno/afuc/emu.c b/src/freedreno/afuc/emu.c
index 633ba6b76a0..4948a1a6824 100644
--- a/src/freedreno/afuc/emu.c
+++ b/src/freedreno/afuc/emu.c
@@ -44,6 +44,7 @@
EMU_SQE_REG(SP);
EMU_SQE_REG(STACK0);
+EMU_CONTROL_REG(DRAW_STATE_SET_HDR);
/**
* AFUC emulator. Currently only supports a6xx
@@ -215,14 +216,24 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
case OPC_CWRITE: {
uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
uint32_t src2 = emu_get_gpr_reg(emu, instr->src2);
+ uint32_t reg = src2 + instr->immed;
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);
+ emu_set_gpr_reg(emu, instr->src2, reg);
}
- emu_set_control_reg(emu, src2 + instr->immed, src1);
+ emu_set_control_reg(emu, reg, src1);
+
+ for (unsigned i = 0; i < instr->sds; i++) {
+ uint32_t src1 = emu_get_gpr_reg(emu, instr->src1);
+
+ /* TODO: There is likely a DRAW_STATE_SET_BASE register on a6xx, as
+ * there is on a7xx, and we should be writing that instead of setting
+ * the base directly.
+ */
+ if (reg == emu_reg_offset(&DRAW_STATE_SET_HDR))
+ emu_set_draw_state_base(emu, i, src1);
+ }
break;
}
case OPC_CREAD: {
@@ -230,8 +241,6 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
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);
}
emu_set_gpr_reg(emu, instr->dst,
@@ -244,8 +253,6 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
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);
}
emu_set_sqe_reg(emu, src2 + instr->immed, src1);
@@ -256,8 +263,6 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
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);
}
emu_set_gpr_reg(emu, instr->dst,
@@ -271,8 +276,6 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
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) {
- printf("unhandled flags: %x\n", instr->bit);
}
uint32_t val = emu_mem_read_dword(emu, addr);
@@ -288,8 +291,6 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
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) {
- printf("unhandled flags: %x\n", instr->bit);
}
uint32_t val = emu_get_gpr_reg(emu, instr->src1);
diff --git a/src/freedreno/afuc/emu.h b/src/freedreno/afuc/emu.h
index 670b79ba098..5d0bf2ebf3d 100644
--- a/src/freedreno/afuc/emu.h
+++ b/src/freedreno/afuc/emu.h
@@ -113,7 +113,6 @@ emu_queue_pop(struct emu_queue *q, uint32_t *val)
*/
struct emu_draw_state {
unsigned prev_draw_state_sel;
- unsigned write_idx;
struct {
union {
uint32_t hdr;
@@ -294,6 +293,7 @@ void emu_set_reg64(struct emu *emu, struct emu_reg *reg, uint64_t val);
/* Draw-state control reg emulation: */
uint32_t emu_get_draw_state_reg(struct emu *emu, unsigned n);
void emu_set_draw_state_reg(struct emu *emu, unsigned n, uint32_t val);
+void emu_set_draw_state_base(struct emu *emu, unsigned n, uint32_t val);
/* Helpers: */
#define printdelta(fmt, ...) afuc_printc(AFUC_ERR, fmt, ##__VA_ARGS__)
diff --git a/src/freedreno/afuc/lexer.l b/src/freedreno/afuc/lexer.l
index 179b5484b67..02ac03f16fc 100644
--- a/src/freedreno/afuc/lexer.l
+++ b/src/freedreno/afuc/lexer.l
@@ -95,6 +95,7 @@ extern YYSTYPE yylval;
"<<" return TOKEN(T_LSHIFT);
"(rep)" return TOKEN(T_REP);
"(xmov"[1-3]")" yylval.num = yytext[5] - '0'; return T_XMOV;
+"(sds"[1-3]")" yylval.num = yytext[4] - '0'; return T_SDS;
"," return ',';
"[" return '[';
diff --git a/src/freedreno/afuc/parser.y b/src/freedreno/afuc/parser.y
index 202f45c6ddd..9157a7d7900 100644
--- a/src/freedreno/afuc/parser.y
+++ b/src/freedreno/afuc/parser.y
@@ -170,6 +170,7 @@ label(const char *str)
%token T_LSHIFT
%token T_REP
%token T_XMOV
+%token T_SDS
%type reg
%type immediate
@@ -190,8 +191,8 @@ instr_or_label: instr_r
| T_LABEL_DECL { decl_label($1); }
/* instructions that can optionally have (rep) flag: */
-instr_r: alu_instr { instr->xmov = 0; }
-| T_XMOV alu_instr { instr->xmov = $1; }
+instr_r: alu_instr { instr->xmov = 0; }
+| T_XMOV alu_instr { instr->xmov = $1; }
| load_instr
| store_instr
@@ -255,21 +256,22 @@ alu_instr: alu_2src_instr
| alu_clrsetbit_instr
| alu_bitfield_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_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); instr->sds = 0; }
+| T_SDS T_OP_CWRITE { new_instr(OPC_CWRITE); instr->sds = $1; }
+| T_OP_SWRITE { new_instr(OPC_SWRITE); }
preincrement:
| '!' { instr->preincrement = true; }
-load_instr: load_op reg ',' '[' reg '+' immediate ']' preincrement ',' immediate {
- dst($2); src1($5); immed($7); bit($11);
+load_instr: load_op reg ',' '[' reg '+' immediate ']' preincrement {
+ dst($2); src1($5); immed($7);
}
-store_instr: store_op reg ',' '[' reg '+' immediate ']' preincrement ',' immediate {
- src1($2); src2($5); immed($7); bit($11);
+store_instr: store_op reg ',' '[' reg '+' immediate ']' preincrement {
+ src1($2); src2($5); immed($7);
}
branch_op: T_OP_BRNE { new_instr(OPC_BRNE); }
diff --git a/src/freedreno/registers/adreno/adreno_control_regs.xml b/src/freedreno/registers/adreno/adreno_control_regs.xml
index 0d28e0985f9..461f39c5ac4 100644
--- a/src/freedreno/registers/adreno/adreno_control_regs.xml
+++ b/src/freedreno/registers/adreno/adreno_control_regs.xml
@@ -130,7 +130,14 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd">
-
+
+
+ This register is written for each state group entry in
+ CP_SET_DRAW_STATE. The value is copied directly from the packet
+ to these registers so the format is identical to the first word.
+ The draw state base is set via the (sds2) modifier.
+
+
Controls whether RB, IB1, or IB2 is executed