freedreno/afuc: Decode (sdsN) modifier

This removes the last unknown flag from read/write instructions.

Because we now handle the write in CP_SET_DRAW_STATE more correctly when
emulating, we also have to update the control register definitions and
draw state emulation code to adjust.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26691>
This commit is contained in:
Connor Abbott 2023-12-12 16:13:07 +01:00 committed by Marge Bot
parent 55985b7301
commit d01be55340
12 changed files with 317 additions and 255 deletions

View file

@ -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]

View file

@ -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:

View file

@ -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
============

View file

@ -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;

View file

@ -602,20 +602,30 @@ SOFTWARE.
<pattern low="27" high="31">01110</pattern>
</bitset>
<enum name="#sds">
<doc>
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.
</doc>
<value val="0" display=""/>
<value val="1" display="(sds1)"/>
<value val="2" display="(sds2)"/>
<value val="3" display="(sds3)"/>
</enum>
<bitset name="#control" extends="#instruction-rep">
<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}]{PREINCREMENT}, 0x{FLAGS}
{REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}
</display>
<doc>
@ -624,6 +634,7 @@ SOFTWARE.
restored.
</doc>
<pattern low="12" high="13">00</pattern>
<field name="IMMED" low="0" high="11" type="hex"/>
<field name="SRC" low="16" high="20" type="#src"/>
@ -674,16 +685,18 @@ SOFTWARE.
<bitset name="#cwrite" extends="#control">
<doc>Write to a control register.</doc>
<display>
{REP}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
{REP}{SDS}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}
</display>
<field name="BASE" low="0" high="11" type="#control-base">
<param name="PREINCREMENT"/>
</field>
<field name="SDS" low="12" high="13" type="#sds"/>
<field name="SRC" low="16" high="20" type="#src"/>
<pattern low="27" high="31">10101</pattern>
<encode>
<map name="SDS">src->sds</map>
<map name="SRC">src->src1</map>
<map name="OFFSET">src->src2</map>
<map name="BASE">src->immed</map>
@ -721,12 +734,13 @@ SOFTWARE.
<doc>Write to a SQE register.</doc>
<gen min="6"/>
<display>
{REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
{REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}
</display>
<field name="BASE" low="0" high="11" type="#sqe-base">
<param name="PREINCREMENT"/>
</field>
<pattern low="12" high="13">00</pattern>
<field name="SRC" low="16" high="20" type="#src"/>
<pattern pos="15">1</pattern>
<pattern low="27" high="31">10101</pattern>
@ -746,10 +760,11 @@ SOFTWARE.
restored.
</doc>
<display>
{REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}, 0x{FLAGS}
{REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}
</display>
<field name="IMMED" low="0" high="11" type="hex"/>
<pattern low="12" high="13">00</pattern>
<pattern pos="15">0</pattern>
<field name="DST" low="16" high="20" type="#dst"/>
<pattern low="27" high="31">10110</pattern>
@ -762,12 +777,13 @@ SOFTWARE.
<bitset name="#cread" extends="#control">
<doc>Read from a control register.</doc>
<display>
{REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
{REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}
</display>
<field name="BASE" low="0" high="11" type="#control-base">
<param name="PREINCREMENT"/>
</field>
<pattern low="12" high="13">00</pattern>
<field name="DST" low="16" high="20" type="#dst"/>
<encode>
@ -793,12 +809,13 @@ SOFTWARE.
<doc>Read from a SQE register.</doc>
<gen min="6"/>
<display>
{REP}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}, 0x{FLAGS}
{REP}{XREG}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}
</display>
<field name="BASE" low="0" high="11" type="#sqe-base">
<param name="PREINCREMENT"/>
</field>
<pattern low="12" high="13">00</pattern>
<field name="DST" low="16" high="20" type="#dst"/>
<encode>

View file

@ -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);

View file

@ -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);

View file

@ -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__)

View file

@ -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 '[';

View file

@ -170,6 +170,7 @@ label(const char *str)
%token <tok> T_LSHIFT
%token <tok> T_REP
%token <num> T_XMOV
%token <num> T_SDS
%type <num> reg
%type <num> 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); }

View file

@ -130,7 +130,14 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd">
</doc>
</reg32>
<reg32 name="DRAW_STATE_ACTIVE_BITMASK" offset="0x049"/>
<reg32 name="DRAW_STATE_SET" offset="0x04a"/>
<doc>
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.
</doc>
<reg32 name="DRAW_STATE_SET_HDR" offset="0x04a"/>
<doc> Controls whether RB, IB1, or IB2 is executed </doc>
<reg32 name="IB_LEVEL" offset="0x054"/>