X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/3b88670664f7902000b83149e7fa1875ad5c6239..a195fdd028370faa54ba3d627f1add8401ac5193:/target-m68k/op_helper.c diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 237fc4cb54..06661f58ca 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -16,17 +16,18 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ -#include "exec.h" -#include "helpers.h" +#include "cpu.h" +#include "exec/helper-proto.h" +#include "exec/cpu_ldst.h" #if defined(CONFIG_USER_ONLY) -void do_interrupt(CPUState *env1) +void m68k_cpu_do_interrupt(CPUState *cs) { - env1->exception_index = -1; + cs->exception_index = -1; } -void do_interrupt_m68k_hardirq(CPUState *env1) +static inline void do_interrupt_m68k_hardirq(CPUM68KState *env) { } @@ -34,68 +35,41 @@ void do_interrupt_m68k_hardirq(CPUState *env1) extern int semihosting_enabled; -#define MMUSUFFIX _mmu - -#define SHIFT 0 -#include "softmmu_template.h" - -#define SHIFT 1 -#include "softmmu_template.h" - -#define SHIFT 2 -#include "softmmu_template.h" - -#define SHIFT 3 -#include "softmmu_template.h" - /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) +void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, + uintptr_t retaddr) { - TranslationBlock *tb; - CPUState *saved_env; - unsigned long pc; int ret; - /* XXX: hack to restore env in all cases, even if not called from - generated code */ - saved_env = env; - env = cpu_single_env; - ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = m68k_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - pc = (unsigned long)retaddr; - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, pc); - } + cpu_restore_state(cs, retaddr); } - cpu_loop_exit(env); + cpu_loop_exit(cs); } - env = saved_env; } -static void do_rte(void) +static void do_rte(CPUM68KState *env) { uint32_t sp; uint32_t fmt; sp = env->aregs[7]; - fmt = ldl_kernel(sp); - env->pc = ldl_kernel(sp + 4); + fmt = cpu_ldl_kernel(env, sp); + env->pc = cpu_ldl_kernel(env, sp + 4); sp |= (fmt >> 28) & 3; env->sr = fmt & 0xffff; m68k_switch_sp(env); env->aregs[7] = sp + 8; } -static void do_interrupt_all(int is_hw) +static void do_interrupt_all(CPUM68KState *env, int is_hw) { + CPUState *cs = CPU(m68k_env_get_cpu(env)); uint32_t sp; uint32_t fmt; uint32_t retaddr; @@ -105,34 +79,34 @@ static void do_interrupt_all(int is_hw) retaddr = env->pc; if (!is_hw) { - switch (env->exception_index) { + switch (cs->exception_index) { case EXCP_RTE: /* Return from an exception. */ - do_rte(); + do_rte(env); return; case EXCP_HALT_INSN: if (semihosting_enabled && (env->sr & SR_S) != 0 && (env->pc & 3) == 0 - && lduw_code(env->pc - 4) == 0x4e71 - && ldl_code(env->pc) == 0x4e7bf000) { + && cpu_lduw_code(env, env->pc - 4) == 0x4e71 + && cpu_ldl_code(env, env->pc) == 0x4e7bf000) { env->pc += 4; do_m68k_semihosting(env, env->dregs[0]); return; } - env->halted = 1; - env->exception_index = EXCP_HLT; - cpu_loop_exit(env); + cs->halted = 1; + cs->exception_index = EXCP_HLT; + cpu_loop_exit(cs); return; } - if (env->exception_index >= EXCP_TRAP0 - && env->exception_index <= EXCP_TRAP15) { + if (cs->exception_index >= EXCP_TRAP0 + && cs->exception_index <= EXCP_TRAP15) { /* Move the PC after the trap instruction. */ retaddr += 2; } } - vector = env->exception_index << 2; + vector = cs->exception_index << 2; sp = env->aregs[7]; @@ -151,47 +125,60 @@ static void do_interrupt_all(int is_hw) /* ??? This could cause MMU faults. */ sp &= ~3; sp -= 4; - stl_kernel(sp, retaddr); + cpu_stl_kernel(env, sp, retaddr); sp -= 4; - stl_kernel(sp, fmt); + cpu_stl_kernel(env, sp, fmt); env->aregs[7] = sp; /* Jump to vector. */ - env->pc = ldl_kernel(env->vbr + vector); + env->pc = cpu_ldl_kernel(env, env->vbr + vector); } -void do_interrupt(CPUState *env1) +void m68k_cpu_do_interrupt(CPUState *cs) { - CPUState *saved_env; + M68kCPU *cpu = M68K_CPU(cs); + CPUM68KState *env = &cpu->env; - saved_env = env; - env = env1; - do_interrupt_all(0); - env = saved_env; + do_interrupt_all(env, 0); } -void do_interrupt_m68k_hardirq(CPUState *env1) +static inline void do_interrupt_m68k_hardirq(CPUM68KState *env) { - CPUState *saved_env; - - saved_env = env; - env = env1; - do_interrupt_all(1); - env = saved_env; + do_interrupt_all(env, 1); } #endif -static void raise_exception(int tt) +bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { - env->exception_index = tt; - cpu_loop_exit(env); + M68kCPU *cpu = M68K_CPU(cs); + CPUM68KState *env = &cpu->env; + + if (interrupt_request & CPU_INTERRUPT_HARD + && ((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) { + /* Real hardware gets the interrupt vector via an IACK cycle + at this point. Current emulated hardware doesn't rely on + this, so we provide/save the vector when the interrupt is + first signalled. */ + cs->exception_index = env->pending_vector; + do_interrupt_m68k_hardirq(env); + return true; + } + return false; } -void HELPER(raise_exception)(uint32_t tt) +static void raise_exception(CPUM68KState *env, int tt) { - raise_exception(tt); + CPUState *cs = CPU(m68k_env_get_cpu(env)); + + cs->exception_index = tt; + cpu_loop_exit(cs); } -void HELPER(divu)(CPUState *env, uint32_t word) +void HELPER(raise_exception)(CPUM68KState *env, uint32_t tt) +{ + raise_exception(env, tt); +} + +void HELPER(divu)(CPUM68KState *env, uint32_t word) { uint32_t num; uint32_t den; @@ -202,14 +189,12 @@ void HELPER(divu)(CPUState *env, uint32_t word) num = env->div1; den = env->div2; /* ??? This needs to make sure the throwing location is accurate. */ - if (den == 0) - raise_exception(EXCP_DIV0); + if (den == 0) { + raise_exception(env, EXCP_DIV0); + } quot = num / den; rem = num % den; flags = 0; - /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses - the address of a symbol, and gcc knows symbols can't have address - zero. */ if (word && quot > 0xffff) flags |= CCF_V; if (quot == 0) @@ -221,7 +206,7 @@ void HELPER(divu)(CPUState *env, uint32_t word) env->cc_dest = flags; } -void HELPER(divs)(CPUState *env, uint32_t word) +void HELPER(divs)(CPUM68KState *env, uint32_t word) { int32_t num; int32_t den; @@ -231,8 +216,9 @@ void HELPER(divs)(CPUState *env, uint32_t word) num = env->div1; den = env->div2; - if (den == 0) - raise_exception(EXCP_DIV0); + if (den == 0) { + raise_exception(env, EXCP_DIV0); + } quot = num / den; rem = num % den; flags = 0;