On 03/04/2013 04:29 AM, Anthony Green wrote: > +void tlb_fill(CPUMoxieState *env, target_ulong addr, int is_write, int > mmu_idx, > + uintptr_t retaddr) > +{ > + int ret; > + > + ret = cpu_moxie_handle_mmu_fault(env, addr, is_write, mmu_idx); > + if (unlikely(ret)) { > + if (retaddr) { > + cpu_restore_state(env, retaddr); > + } > + } > + cpu_loop_exit(env); > +} > + > +void helper_raise_exception(CPUMoxieState *env, uint32_t pc, int ex) > +{ > + env->exception_index = ex; > + /* Stash the exception type. */ > + env->sregs[2] = ex; > + /* Stash the address where the exception occurred. */ > + env->sregs[5] = pc; > + /* Jump the the exception handline routine. */ > + env->pc = env->sregs[1]; > + cpu_loop_exit(env); > +}
To be fixed later: The cpu_restore_state trick is not exclusive to memory operations. Any kind of runtime exception can use it. Which means... > + > +uint32_t helper_div(CPUMoxieState *env, uint32_t pc, uint32_t a, uint32_t b) > +{ > + if (unlikely(b == 0)) { > + helper_raise_exception(env, pc, MOXIE_EX_DIV0); > + return 0; > + } You need not store to or pass cpu_pc into the division routines. > +DEF_HELPER_4(div, i32, env, i32, i32, i32) > +DEF_HELPER_4(udiv, i32, env, i32, i32, i32) Should use HELPER_FLAGS_4 with TCG_CALL_NO_WG, indicating that the function does not write to tcg global registers. (It does read them, via the exception path.) r~