void HELPER(window_check)(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; if ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) { return; } for (n = 1; ; ++n) { if (n > w) { return; } if (windowstart & windowstart_bit(windowbase + n, env)) { break; } } m = windowbase_bound(windowbase + n, env); rotate_window(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)) { HELPER(exception)(EXC_WINDOW_OVERFLOW4); } else if (windowstart & windowstart_bit(m + 2, env)) { HELPER(exception)(EXC_WINDOW_OVERFLOW8); } else { HELPER(exception)(EXC_WINDOW_OVERFLOW12); } }
void HELPER(entry)(uint32_t pc, uint32_t s, uint32_t imm) { int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT; if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) { qemu_log("Illegal entry instruction(pc = %08x), PS = %08x\n", pc, env->sregs[PS]); HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE); } else { env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - (imm << 3); rotate_window(callinc); env->sregs[WINDOW_START] |= windowstart_bit(env->sregs[WINDOW_BASE], env); } }
uint32_t HELPER(retw)(uint32_t pc) { int n = (env->regs[0] >> 30) & 0x3; int m = 0; uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); uint32_t windowstart = env->sregs[WINDOW_START]; uint32_t ret_pc = 0; if (windowstart & windowstart_bit(windowbase - 1, env)) { m = 1; } else if (windowstart & windowstart_bit(windowbase - 2, env)) { m = 2; } else if (windowstart & windowstart_bit(windowbase - 3, env)) { m = 3; } if (n == 0 || (m != 0 && m != n) || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) { qemu_log("Illegal retw instruction(pc = %08x), " "PS = %08x, m = %d, n = %d\n", pc, env->sregs[PS], m, n); HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE); } else { int owb = windowbase; ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); rotate_window(-n); if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) { env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env); } else { /* window underflow */ env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | (windowbase << PS_OWB_SHIFT) | PS_EXCM; env->sregs[EPC1] = env->pc = pc; if (n == 1) { HELPER(exception)(EXC_WINDOW_UNDERFLOW4); } else if (n == 2) { HELPER(exception)(EXC_WINDOW_UNDERFLOW8); } else if (n == 3) { HELPER(exception)(EXC_WINDOW_UNDERFLOW12); } } } return ret_pc; }
void HELPER(rotw)(uint32_t imm4) { rotate_window(imm4); }
void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4) { rotate_window(env, imm4); }