diff options
Diffstat (limited to 'target-xtensa/op_helper.c')
-rw-r--r-- | target-xtensa/op_helper.c | 29 |
1 files changed, 11 insertions, 18 deletions
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 872e5a823b..49e86343ed 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -251,34 +251,27 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm) void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w) { uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); - uint32_t windowstart = env->sregs[WINDOW_START]; - uint32_t m, n; + uint32_t windowstart = xtensa_replicate_windowstart(env) >> + (env->sregs[WINDOW_BASE] + 1); + uint32_t n = ctz32(windowstart) + 1; - if ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) { - return; - } + assert(n <= w); - for (n = 1; ; ++n) { - if (n > w) { - return; - } - if (windowstart & windowstart_bit(windowbase + n, env)) { - break; - } - } - - m = windowbase_bound(windowbase + n, env); rotate_window(env, n); env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | (windowbase << PS_OWB_SHIFT) | PS_EXCM; env->sregs[EPC1] = env->pc = pc; - if (windowstart & windowstart_bit(m + 1, env)) { + switch (ctz32(windowstart >> n)) { + case 0: HELPER(exception)(env, EXC_WINDOW_OVERFLOW4); - } else if (windowstart & windowstart_bit(m + 2, env)) { + break; + case 1: HELPER(exception)(env, EXC_WINDOW_OVERFLOW8); - } else { + break; + default: HELPER(exception)(env, EXC_WINDOW_OVERFLOW12); + break; } } |