X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=target-m68k%2Fop_helper.c;h=bbbfd7f130c14d1e093053cf92192fd29c6a285d;hb=30c367ed446b6ea53245589a5cf373578ac075d7;hp=8086238db46b84d221237a08c225d9702c25ccaf;hpb=caf8fe8c32596480b2e2809f29061f4a386de7ae;p=qemu.git diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 8086238db..bbbfd7f13 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -1,6 +1,6 @@ /* * M68K helper routines - * + * * Copyright (c) 2007 CodeSourcery * * This library is free software; you can redistribute it and/or @@ -14,84 +14,80 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library; if not, see . */ -#include "exec.h" +#include "cpu.h" +#include "helper.h" #if defined(CONFIG_USER_ONLY) -void do_interrupt(int is_hw) +void m68k_cpu_do_interrupt(CPUState *cs) { + M68kCPU *cpu = M68K_CPU(cs); + CPUM68KState *env = &cpu->env; + env->exception_index = -1; } +void do_interrupt_m68k_hardirq(CPUM68KState *env) +{ +} + #else extern int semihosting_enabled; +#include "exec/softmmu_exec.h" + #define MMUSUFFIX _mmu -#define GETPC() (__builtin_return_address(0)) #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/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 is_user, void *retaddr) +void tlb_fill(CPUM68KState *env, target_ulong addr, int is_write, int mmu_idx, + uintptr_t retaddr) { - TranslationBlock *tb; - CPUState *saved_env; - target_phys_addr_t 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, is_user, 1); - if (__builtin_expect(ret, 0)) { + ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx); + if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - pc = (target_phys_addr_t)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, NULL); - } + cpu_restore_state(env, retaddr); } - cpu_loop_exit(); + cpu_loop_exit(env); } - 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; } -void do_interrupt(int is_hw) +static void do_interrupt_all(CPUM68KState *env, int is_hw) { + CPUState *cs; uint32_t sp; uint32_t fmt; uint32_t retaddr; @@ -104,21 +100,22 @@ void do_interrupt(int is_hw) switch (env->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; + cs = CPU(m68k_env_get_cpu(env)); + cs->halted = 1; env->exception_index = EXCP_HLT; - cpu_loop_exit(); + cpu_loop_exit(env); return; } if (env->exception_index >= EXCP_TRAP0 @@ -128,30 +125,109 @@ void do_interrupt(int is_hw) } } - /* TODO: Implement USP. */ - sp = env->aregs[7]; - vector = env->exception_index << 2; + sp = env->aregs[7]; + fmt |= 0x40000000; fmt |= (sp & 3) << 28; fmt |= vector << 16; fmt |= env->sr; - /* ??? This could cause MMU faults. */ - sp &= ~3; - sp -= 4; - stl_kernel(sp, retaddr); - sp -= 4; - stl_kernel(sp, fmt); - env->aregs[7] = sp; env->sr |= SR_S; if (is_hw) { env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); env->sr &= ~SR_M; } + m68k_switch_sp(env); + + /* ??? This could cause MMU faults. */ + sp &= ~3; + sp -= 4; + cpu_stl_kernel(env, sp, retaddr); + sp -= 4; + 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 m68k_cpu_do_interrupt(CPUState *cs) +{ + M68kCPU *cpu = M68K_CPU(cs); + CPUM68KState *env = &cpu->env; + + do_interrupt_all(env, 0); } +void do_interrupt_m68k_hardirq(CPUM68KState *env) +{ + do_interrupt_all(env, 1); +} #endif + +static void raise_exception(CPUM68KState *env, int tt) +{ + env->exception_index = tt; + cpu_loop_exit(env); +} + +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; + uint32_t quot; + uint32_t rem; + uint32_t flags; + + num = env->div1; + den = env->div2; + /* ??? This needs to make sure the throwing location is accurate. */ + if (den == 0) { + raise_exception(env, EXCP_DIV0); + } + quot = num / den; + rem = num % den; + flags = 0; + if (word && quot > 0xffff) + flags |= CCF_V; + if (quot == 0) + flags |= CCF_Z; + else if ((int32_t)quot < 0) + flags |= CCF_N; + env->div1 = quot; + env->div2 = rem; + env->cc_dest = flags; +} + +void HELPER(divs)(CPUM68KState *env, uint32_t word) +{ + int32_t num; + int32_t den; + int32_t quot; + int32_t rem; + int32_t flags; + + num = env->div1; + den = env->div2; + if (den == 0) { + raise_exception(env, EXCP_DIV0); + } + quot = num / den; + rem = num % den; + flags = 0; + if (word && quot != (int16_t)quot) + flags |= CCF_V; + if (quot == 0) + flags |= CCF_Z; + else if (quot < 0) + flags |= CCF_N; + env->div1 = quot; + env->div2 = rem; + env->cc_dest = flags; +}