diff options
Diffstat (limited to 'target-mips/op_helper.c')
-rw-r--r-- | target-mips/op_helper.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index fe1c9160d5..be75af5e6e 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -275,6 +275,45 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2) } #endif +#ifndef CONFIG_USER_ONLY +#define HELPER_LD_ATOMIC(name, insn) \ +target_ulong helper_##name(target_ulong arg, int mem_idx) \ +{ \ + env->lladdr = do_translate_address(env, arg, 0); \ + env->llval = do_##insn(arg, mem_idx); \ + return env->llval; \ +} +HELPER_LD_ATOMIC(ll, lw) +#ifdef TARGET_MIPS64 +HELPER_LD_ATOMIC(lld, ld) +#endif +#undef HELPER_LD_ATOMIC + +#define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask) \ +target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \ +{ \ + target_long tmp; \ + \ + if (arg2 & almask) { \ + env->CP0_BadVAddr = arg2; \ + helper_raise_exception(EXCP_AdES); \ + } \ + if (do_translate_address(env, arg2, 1) == env->lladdr) { \ + tmp = do_##ld_insn(arg2, mem_idx); \ + if (tmp == env->llval) { \ + do_##st_insn(arg2, arg1, mem_idx); \ + return 1; \ + } \ + } \ + return 0; \ +} +HELPER_ST_ATOMIC(sc, lw, sw, 0x3) +#ifdef TARGET_MIPS64 +HELPER_ST_ATOMIC(scd, ld, sd, 0x7) +#endif +#undef HELPER_ST_ATOMIC +#endif + #ifdef TARGET_WORDS_BIGENDIAN #define GET_LMASK(v) ((v) & 3) #define GET_OFFSET(addr, offset) (addr + (offset)) |