freedreno/afuc: Use SQE registers for call stack
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26691>
This commit is contained in:
@@ -352,6 +352,12 @@ const struct emu_reg_accessor emu_control_accessor = {
|
|||||||
.set = emu_set_control_reg,
|
.set = emu_set_control_reg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct emu_reg_accessor emu_sqe_accessor = {
|
||||||
|
.get_offset = afuc_sqe_reg,
|
||||||
|
.get = emu_get_sqe_reg,
|
||||||
|
.set = emu_set_sqe_reg,
|
||||||
|
};
|
||||||
|
|
||||||
const struct emu_reg_accessor emu_pipe_accessor = {
|
const struct emu_reg_accessor emu_pipe_accessor = {
|
||||||
.get_offset = afuc_pipe_reg,
|
.get_offset = afuc_pipe_reg,
|
||||||
.get = emu_get_pipe_reg,
|
.get = emu_get_pipe_reg,
|
||||||
|
@@ -42,6 +42,9 @@
|
|||||||
#define rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
|
#define rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||||
#define rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
|
#define rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
|
||||||
|
|
||||||
|
EMU_SQE_REG(SP);
|
||||||
|
EMU_SQE_REG(STACK0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AFUC emulator. Currently only supports a6xx
|
* AFUC emulator. Currently only supports a6xx
|
||||||
*
|
*
|
||||||
@@ -317,20 +320,24 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPC_RET: {
|
case OPC_RET: {
|
||||||
assert(emu->call_stack_idx > 0);
|
unsigned sp = emu_get_reg32(emu, &SP);
|
||||||
|
assert(sp > 0);
|
||||||
|
|
||||||
/* counter-part to 'call' instruction, also has a delay slot: */
|
/* counter-part to 'call' instruction, also has a delay slot: */
|
||||||
emu->branch_target = emu->call_stack[--emu->call_stack_idx];
|
emu->branch_target = emu_get_sqe_reg(emu, emu_reg_offset(&STACK0) + sp - 1);
|
||||||
|
emu_set_reg32(emu, &SP, sp - 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPC_CALL: {
|
case OPC_CALL: {
|
||||||
assert(emu->call_stack_idx < ARRAY_SIZE(emu->call_stack));
|
unsigned sp = emu_get_reg32(emu, &SP);
|
||||||
|
assert(sp + emu_reg_offset(&STACK0) < ARRAY_SIZE(emu->sqe_regs.val));
|
||||||
|
|
||||||
/* call looks to have same delay-slot behavior as branch/etc, so
|
/* call looks to have same delay-slot behavior as branch/etc, so
|
||||||
* presumably the return PC is two instructions later:
|
* presumably the return PC is two instructions later:
|
||||||
*/
|
*/
|
||||||
emu->call_stack[emu->call_stack_idx++] = emu->gpr_regs.pc + 2;
|
emu_set_sqe_reg(emu, emu_reg_offset(&STACK0) + sp, emu->gpr_regs.pc + 2);
|
||||||
|
emu_set_reg32(emu, &SP, sp + 1);
|
||||||
emu->branch_target = instr->literal;
|
emu->branch_target = instr->literal;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@@ -198,12 +198,6 @@ struct emu {
|
|||||||
*/
|
*/
|
||||||
uint32_t carry;
|
uint32_t carry;
|
||||||
|
|
||||||
/* call-stack of saved PCs.. I expect this to be a fixed size, but not
|
|
||||||
* sure what the actual size is
|
|
||||||
*/
|
|
||||||
uint32_t call_stack[5];
|
|
||||||
int call_stack_idx;
|
|
||||||
|
|
||||||
/* packet table (aka jmptable) has offsets for pm4 packet handlers: */
|
/* packet table (aka jmptable) has offsets for pm4 packet handlers: */
|
||||||
uint32_t jmptbl[0x80];
|
uint32_t jmptbl[0x80];
|
||||||
|
|
||||||
@@ -282,10 +276,12 @@ struct emu_reg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const struct emu_reg_accessor emu_control_accessor;
|
extern const struct emu_reg_accessor emu_control_accessor;
|
||||||
|
extern const struct emu_reg_accessor emu_sqe_accessor;
|
||||||
extern const struct emu_reg_accessor emu_pipe_accessor;
|
extern const struct emu_reg_accessor emu_pipe_accessor;
|
||||||
extern const struct emu_reg_accessor emu_gpu_accessor;
|
extern const struct emu_reg_accessor emu_gpu_accessor;
|
||||||
|
|
||||||
#define EMU_CONTROL_REG(name) static struct emu_reg name = { #name, &emu_control_accessor, ~0 }
|
#define EMU_CONTROL_REG(name) static struct emu_reg name = { #name, &emu_control_accessor, ~0 }
|
||||||
|
#define EMU_SQE_REG(name) static struct emu_reg name = { #name, &emu_sqe_accessor, ~0 }
|
||||||
#define EMU_PIPE_REG(name) static struct emu_reg name = { #name, &emu_pipe_accessor, ~0 }
|
#define EMU_PIPE_REG(name) static struct emu_reg name = { #name, &emu_pipe_accessor, ~0 }
|
||||||
#define EMU_GPU_REG(name) static struct emu_reg name = { #name, &emu_gpu_accessor, ~0 }
|
#define EMU_GPU_REG(name) static struct emu_reg name = { #name, &emu_gpu_accessor, ~0 }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user