target/xtensa: extract test for window underflow exception

- mark retw and retw.n instructions;
- extract window inderflow test from retw helper;
- put underflow exception check generation right after the overflow
  check;

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
This commit is contained in:
Max Filippov 2018-08-30 17:55:33 -07:00
parent 6416d16f75
commit f473019a97
3 changed files with 25 additions and 9 deletions

View File

@ -6,6 +6,7 @@ DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
DEF_HELPER_2(wsr_windowbase, void, env, i32)
DEF_HELPER_4(entry, void, env, i32, i32, i32)
DEF_HELPER_2(test_ill_retw, void, env, i32)
DEF_HELPER_2(test_underflow_retw, void, env, i32)
DEF_HELPER_2(retw, i32, env, i32)
DEF_HELPER_2(rotw, void, env, i32)
DEF_HELPER_3(window_check, noreturn, env, i32, i32)

View File

@ -310,19 +310,15 @@ void HELPER(test_ill_retw)(CPUXtensaState *env, uint32_t pc)
}
}
uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
void HELPER(test_underflow_retw)(CPUXtensaState *env, uint32_t pc)
{
int n = (env->regs[0] >> 30) & 0x3;
uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
uint32_t windowstart = env->sregs[WINDOW_START];
uint32_t ret_pc = 0;
ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
if (!(env->sregs[WINDOW_START] &
windowstart_bit(env->sregs[WINDOW_BASE] - n, env))) {
uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
xtensa_rotate_window(env, -n);
if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) {
env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
} else {
xtensa_rotate_window(env, -n);
/* window underflow */
env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
(windowbase << PS_OWB_SHIFT) | PS_EXCM;
@ -336,6 +332,16 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12);
}
}
}
uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
{
int n = (env->regs[0] >> 30) & 0x3;
uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
xtensa_rotate_window(env, -n);
env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
return ret_pc;
}

View File

@ -1071,6 +1071,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
return;
}
if (op_flags & XTENSA_OP_UNDERFLOW) {
TCGv_i32 tmp = tcg_const_i32(dc->pc);
gen_helper_test_underflow_retw(cpu_env, tmp);
tcg_temp_free(tmp);
}
for (slot = 0; slot < slots; ++slot) {
XtensaOpcodeOps *ops = slot_prop[slot].ops;
@ -3485,10 +3492,12 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "retw",
.translate = translate_retw,
.test_ill = test_ill_retw,
.op_flags = XTENSA_OP_UNDERFLOW,
}, {
.name = "retw.n",
.translate = translate_retw,
.test_ill = test_ill_retw,
.op_flags = XTENSA_OP_UNDERFLOW,
}, {
.name = "rfdd",
.op_flags = XTENSA_OP_ILL,