mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
freedreno/afuc: Decode (peek) modifier
This is an educated guess based on the location it is used in (CP_INDIRECT_BUFFER). Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26771>
This commit is contained in:
parent
f88c269148
commit
443e8b89ca
8 changed files with 65 additions and 14 deletions
|
|
@ -585,6 +585,19 @@ 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.
|
||||
|
||||
.. _afuc-peek:
|
||||
|
||||
Peek
|
||||
----
|
||||
|
||||
``(peek)`` is valid on ALU instructions without an immediate. It modifies what
|
||||
``$data`` (and possibly ``$memdata`` and ``$regdata``) do by making them avoid
|
||||
consuming the word. The next read to ``$data`` will return the same thing. This
|
||||
is used solely by ``CP_INDIRECT_BUFFER`` to test if there is a subsequent IB
|
||||
that can be prefetched while the first IB is executed without actually
|
||||
consuming the header for the next packet. It is introduced on a7xx, and
|
||||
replaces the use of a special control register.
|
||||
|
||||
Packet Table
|
||||
============
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ struct afuc_instr {
|
|||
bool is_literal : 1;
|
||||
bool rep : 1;
|
||||
bool preincrement : 1;
|
||||
bool peek : 1;
|
||||
};
|
||||
|
||||
void print_control_reg(uint32_t id);
|
||||
|
|
|
|||
|
|
@ -150,15 +150,20 @@ SOFTWARE.
|
|||
|
||||
<bitset name="#alu-2src" extends="#instruction-rep">
|
||||
<display>
|
||||
{REP}{XMOV}{NAME} {DST}, {SRC1}, {SRC2}
|
||||
{REP}{XMOV}{PEEK}{NAME} {DST}, {SRC1}, {SRC2}
|
||||
</display>
|
||||
|
||||
<pattern low="5" high="8">xxxx</pattern>
|
||||
<pattern low="5" high="7">xxx</pattern>
|
||||
<field name="PEEK" pos="8" type="bool" display="(peek)"/>
|
||||
<field name="XMOV" low="9" high="10" type="#xmov"/>
|
||||
<field name="DST" low="11" high="15" type="#dst"/>
|
||||
<field name="SRC2" low="16" high="20" type="#src"/>
|
||||
<field name="SRC1" low="21" high="25" type="#src"/>
|
||||
<pattern low="27" high="31">10011</pattern>
|
||||
|
||||
<encode>
|
||||
<map name="PEEK">src->peek</map>
|
||||
</encode>
|
||||
</bitset>
|
||||
|
||||
<bitset name="#alu-1src" extends="#instruction-rep">
|
||||
|
|
@ -254,7 +259,7 @@ SOFTWARE.
|
|||
<override>
|
||||
<expr>{SRC1} == 0</expr>
|
||||
<display>
|
||||
{REP}{XMOV}mov {DST}, {SRC2}
|
||||
{REP}{XMOV}{PEEK}mov {DST}, {SRC2}
|
||||
</display>
|
||||
</override>
|
||||
<pattern low="0" high="4">00110</pattern>
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ get_reg_addr(struct emu *emu)
|
|||
|
||||
/* Handle reads for special streaming regs: */
|
||||
static uint32_t
|
||||
emu_get_fifo_reg(struct emu *emu, unsigned n)
|
||||
emu_get_fifo_reg(struct emu *emu, unsigned n, bool peek)
|
||||
{
|
||||
/* TODO the fifo regs are slurping out of a FIFO that the hw is filling
|
||||
* in parallel.. we can use `struct emu_queue` to emulate what is actually
|
||||
|
|
@ -203,7 +203,7 @@ emu_get_fifo_reg(struct emu *emu, unsigned n)
|
|||
unsigned read_dwords = emu_get_reg32(emu, &MEM_READ_DWORDS);
|
||||
uintptr_t read_addr = emu_get_reg64(emu, &MEM_READ_ADDR);
|
||||
|
||||
if (read_dwords > 0) {
|
||||
if (read_dwords > 0 && !peek) {
|
||||
emu_set_reg32(emu, &MEM_READ_DWORDS, read_dwords - 1);
|
||||
emu_set_reg64(emu, &MEM_READ_ADDR, read_addr + 4);
|
||||
}
|
||||
|
|
@ -221,7 +221,7 @@ emu_get_fifo_reg(struct emu *emu, unsigned n)
|
|||
* REG_READ_ADDR, it just ends up with a single value written
|
||||
* into the FIFO that $regdata is consuming from:
|
||||
*/
|
||||
if (read_dwords > 0) {
|
||||
if (read_dwords > 0 && !peek) {
|
||||
emu_set_reg32(emu, ®_READ_DWORDS, read_dwords - 1);
|
||||
emu_set_reg32(emu, ®_READ_ADDR, read_addr + 1);
|
||||
}
|
||||
|
|
@ -234,9 +234,14 @@ emu_get_fifo_reg(struct emu *emu, unsigned n)
|
|||
assert(rem >= 0);
|
||||
|
||||
uint32_t val;
|
||||
if (emu_queue_pop(&emu->roq, &val)) {
|
||||
emu_set_gpr_reg(emu, REG_REM, --rem);
|
||||
return val;
|
||||
if (peek) {
|
||||
if (emu_queue_peek(&emu->roq, &val))
|
||||
return val;
|
||||
} else {
|
||||
if (emu_queue_pop(&emu->roq, &val)) {
|
||||
emu_set_gpr_reg(emu, REG_REM, --rem);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/* If FIFO is empty, prompt for more input: */
|
||||
|
|
@ -301,7 +306,7 @@ emu_set_fifo_reg(struct emu *emu, unsigned n, uint32_t val)
|
|||
}
|
||||
|
||||
uint32_t
|
||||
emu_get_gpr_reg(struct emu *emu, unsigned n)
|
||||
emu_get_gpr_reg_alu(struct emu *emu, unsigned n, bool peek)
|
||||
{
|
||||
assert(n < ARRAY_SIZE(emu->gpr_regs.val));
|
||||
|
||||
|
|
@ -312,12 +317,18 @@ emu_get_gpr_reg(struct emu *emu, unsigned n)
|
|||
case REG_MEMDATA:
|
||||
case REG_REGDATA:
|
||||
case REG_DATA:
|
||||
return emu_get_fifo_reg(emu, n);
|
||||
return emu_get_fifo_reg(emu, n, peek);
|
||||
default:
|
||||
return emu->gpr_regs.val[n];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
emu_get_gpr_reg(struct emu *emu, unsigned n)
|
||||
{
|
||||
return emu_get_gpr_reg_alu(emu, n, false);
|
||||
}
|
||||
|
||||
void
|
||||
emu_set_gpr_reg(struct emu *emu, unsigned n, uint32_t val)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
|
|||
uint32_t val = emu_alu(emu, instr->opc,
|
||||
emu_get_gpr_reg(emu, instr->src1),
|
||||
instr->has_immed ? instr->immed :
|
||||
emu_get_gpr_reg(emu, instr->src2));
|
||||
emu_get_gpr_reg_alu(emu, instr->src2, instr->peek));
|
||||
emu_set_gpr_reg(emu, instr->dst, val);
|
||||
|
||||
if (instr->xmov) {
|
||||
|
|
|
|||
|
|
@ -108,6 +108,17 @@ emu_queue_pop(struct emu_queue *q, uint32_t *val)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
emu_queue_peek(struct emu_queue *q, uint32_t *val)
|
||||
{
|
||||
if (!q->count)
|
||||
return false;
|
||||
|
||||
*val = q->fifo[q->tail];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw-state (ie. CP_SET_DRAW_STATE) related emulation
|
||||
*/
|
||||
|
|
@ -249,6 +260,7 @@ void emu_dump_state_change(struct emu *emu);
|
|||
/* Registers: */
|
||||
uint32_t emu_get_gpr_reg(struct emu *emu, unsigned n);
|
||||
void emu_set_gpr_reg(struct emu *emu, unsigned n, uint32_t val);
|
||||
uint32_t emu_get_gpr_reg_alu(struct emu *emu, unsigned n, bool peek);
|
||||
|
||||
void emu_set_gpu_reg(struct emu *emu, unsigned n, uint32_t val);
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ extern YYSTYPE yylval;
|
|||
"(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;
|
||||
"(peek)" return TOKEN(T_PEEK);
|
||||
|
||||
"," return ',';
|
||||
"[" return '[';
|
||||
|
|
|
|||
|
|
@ -169,11 +169,14 @@ label(const char *str)
|
|||
%token <tok> T_OP_SETSECURE
|
||||
%token <tok> T_LSHIFT
|
||||
%token <tok> T_REP
|
||||
%token <tok> T_PEEK
|
||||
%token <num> T_XMOV
|
||||
%token <num> T_SDS
|
||||
|
||||
%type <num> reg
|
||||
%type <num> immediate
|
||||
%type <num> xmov
|
||||
%type <num> peek
|
||||
|
||||
%error-verbose
|
||||
|
||||
|
|
@ -190,9 +193,14 @@ instr_or_label: instr_r
|
|||
| other_instr
|
||||
| T_LABEL_DECL { decl_label($1); }
|
||||
|
||||
xmov: T_XMOV { $$ = $1; }
|
||||
| { $$ = 0; }
|
||||
|
||||
peek: T_PEEK { $$ = 1; }
|
||||
| { $$ = 0; }
|
||||
|
||||
/* instructions that can optionally have (rep) flag: */
|
||||
instr_r: alu_instr { instr->xmov = 0; }
|
||||
| T_XMOV alu_instr { instr->xmov = $1; }
|
||||
instr_r: xmov peek alu_instr { instr->xmov = $1; instr->peek = $2; }
|
||||
| load_instr
|
||||
| store_instr
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue