mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-15 22:21:57 -06:00
target/xtensa: extract test for window overflow exception
- add ps.callinc to the TB flags, that allows testing all instructions for window overflow statically; - drop gen_window_check* functions; replace them with get_window_check that accepts bitmask of used registers; - add XtensaOpcodeOps::test_overflow that returns bitmask of implicitly used registers; use it for entry and call{,x}{4,8,12}; - drop window overflow test from the entry helper; - drop parameter 0 from translate_[di]cache and use translate_nop for d/i cache opcodes that don't need memory accessibility check; - add bitmask XtensaOpcodeOps::windowed_register_op that marks opcode arguments that refer to windowed registers; - translate windowed_register_op mask to a mask of actually used registers in the disassembly loop; - add check for window overflow right after the check for debug exception; Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
This commit is contained in:
parent
1547781942
commit
6416d16f75
3 changed files with 890 additions and 588 deletions
|
@ -351,6 +351,9 @@ typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
|
||||||
typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
|
typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
|
||||||
const uint32_t arg[],
|
const uint32_t arg[],
|
||||||
const uint32_t par[]);
|
const uint32_t par[]);
|
||||||
|
typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
|
||||||
|
const uint32_t arg[],
|
||||||
|
const uint32_t par[]);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
XTENSA_OP_ILL = 0x1,
|
XTENSA_OP_ILL = 0x1,
|
||||||
|
@ -374,8 +377,10 @@ typedef struct XtensaOpcodeOps {
|
||||||
const char *name;
|
const char *name;
|
||||||
XtensaOpcodeOp translate;
|
XtensaOpcodeOp translate;
|
||||||
XtensaOpcodeBoolTest test_ill;
|
XtensaOpcodeBoolTest test_ill;
|
||||||
|
XtensaOpcodeUintTest test_overflow;
|
||||||
const uint32_t *par;
|
const uint32_t *par;
|
||||||
uint32_t op_flags;
|
uint32_t op_flags;
|
||||||
|
uint32_t windowed_register_op;
|
||||||
} XtensaOpcodeOps;
|
} XtensaOpcodeOps;
|
||||||
|
|
||||||
typedef struct XtensaOpcodeTranslators {
|
typedef struct XtensaOpcodeTranslators {
|
||||||
|
@ -686,6 +691,8 @@ static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch)
|
||||||
#define XTENSA_TBFLAG_WINDOW_SHIFT 15
|
#define XTENSA_TBFLAG_WINDOW_SHIFT 15
|
||||||
#define XTENSA_TBFLAG_YIELD 0x20000
|
#define XTENSA_TBFLAG_YIELD 0x20000
|
||||||
#define XTENSA_TBFLAG_CWOE 0x40000
|
#define XTENSA_TBFLAG_CWOE 0x40000
|
||||||
|
#define XTENSA_TBFLAG_CALLINC_MASK 0x180000
|
||||||
|
#define XTENSA_TBFLAG_CALLINC_SHIFT 19
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
|
static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
|
||||||
target_ulong *cs_base, uint32_t *flags)
|
target_ulong *cs_base, uint32_t *flags)
|
||||||
|
@ -724,6 +731,8 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
|
||||||
uint32_t w = ctz32(windowstart | 0x8);
|
uint32_t w = ctz32(windowstart | 0x8);
|
||||||
|
|
||||||
*flags |= (w << XTENSA_TBFLAG_WINDOW_SHIFT) | XTENSA_TBFLAG_CWOE;
|
*flags |= (w << XTENSA_TBFLAG_WINDOW_SHIFT) | XTENSA_TBFLAG_CWOE;
|
||||||
|
*flags |= extract32(env->sregs[PS], PS_CALLINC_SHIFT,
|
||||||
|
PS_CALLINC_LEN) << XTENSA_TBFLAG_CALLINC_SHIFT;
|
||||||
} else {
|
} else {
|
||||||
*flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT;
|
*flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,12 +253,7 @@ void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
|
||||||
void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
|
void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
|
||||||
{
|
{
|
||||||
int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
|
int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
|
||||||
uint32_t windowstart = xtensa_replicate_windowstart(env) >>
|
|
||||||
(env->sregs[WINDOW_BASE] + 1);
|
|
||||||
|
|
||||||
if (windowstart & ((1 << callinc) - 1)) {
|
|
||||||
HELPER(window_check)(env, pc, callinc);
|
|
||||||
}
|
|
||||||
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
|
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
|
||||||
xtensa_rotate_window(env, callinc);
|
xtensa_rotate_window(env, callinc);
|
||||||
env->sregs[WINDOW_START] |=
|
env->sregs[WINDOW_START] |=
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue