aboutsummaryrefslogtreecommitdiff
path: root/target-xtensa/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-xtensa/op_helper.c')
-rw-r--r--target-xtensa/op_helper.c29
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;
}
}