/* ARM memory operations. */ void helper_ld(uint32_t); /* Load from address T1 into T0. */ #define MEM_LD_OP(name) \ void OPPROTO glue(op_ld##name,MEMSUFFIX)(void) \ { \ T0 = glue(ld##name,MEMSUFFIX)(T1); \ FORCE_RET(); \ } MEM_LD_OP(ub) MEM_LD_OP(sb) MEM_LD_OP(uw) MEM_LD_OP(sw) MEM_LD_OP(l) #undef MEM_LD_OP /* Store T0 to address T1. */ #define MEM_ST_OP(name) \ void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \ { \ glue(st##name,MEMSUFFIX)(T1, T0); \ FORCE_RET(); \ } MEM_ST_OP(b) MEM_ST_OP(w) MEM_ST_OP(l) #undef MEM_ST_OP /* Swap T0 with memory at address T1. */ /* ??? Is this exception safe? */ #define MEM_SWP_OP(name, lname) \ void OPPROTO glue(op_swp##name,MEMSUFFIX)(void) \ { \ uint32_t tmp; \ cpu_lock(); \ tmp = glue(ld##lname,MEMSUFFIX)(T1); \ glue(st##name,MEMSUFFIX)(T1, T0); \ T0 = tmp; \ cpu_unlock(); \ FORCE_RET(); \ } MEM_SWP_OP(b, ub) MEM_SWP_OP(l, l) #undef MEM_SWP_OP /* Load-locked, store exclusive. */ #define EXCLUSIVE_OP(suffix, ldsuffix) \ void OPPROTO glue(op_ld##suffix##ex,MEMSUFFIX)(void) \ { \ cpu_lock(); \ helper_mark_exclusive(env, T1); \ T0 = glue(ld##ldsuffix,MEMSUFFIX)(T1); \ cpu_unlock(); \ FORCE_RET(); \ } \ \ void OPPROTO glue(op_st##suffix##ex,MEMSUFFIX)(void) \ { \ int failed; \ cpu_lock(); \ failed = helper_test_exclusive(env, T1); \ /* ??? Is it safe to hold the cpu lock over a store? */ \ if (!failed) { \ glue(st##suffix,MEMSUFFIX)(T1, T0); \ } \ T0 = failed; \ cpu_unlock(); \ FORCE_RET(); \ } EXCLUSIVE_OP(b, ub) EXCLUSIVE_OP(w, uw) EXCLUSIVE_OP(l, l) #undef EXCLUSIVE_OP /* Load exclusive T0:T1 from address T1. */ void OPPROTO glue(op_ldqex,MEMSUFFIX)(void) { cpu_lock(); helper_mark_exclusive(env, T1); T0 = glue(ldl,MEMSUFFIX)(T1); T1 = glue(ldl,MEMSUFFIX)((T1 + 4)); cpu_unlock(); FORCE_RET(); } /* Store exclusive T0:T2 to address T1. */ void OPPROTO glue(op_stqex,MEMSUFFIX)(void) { int failed; cpu_lock(); failed = helper_test_exclusive(env, T1); /* ??? Is it safe to hold the cpu lock over a store? */ if (!failed) { glue(stl,MEMSUFFIX)(T1, T0); glue(stl,MEMSUFFIX)((T1 + 4), T2); } T0 = failed; cpu_unlock(); FORCE_RET(); } /* Floating point load/store. Address is in T1 */ #define VFP_MEM_OP(p, w) \ void OPPROTO glue(op_vfp_ld##p,MEMSUFFIX)(void) \ { \ FT0##p = glue(ldf##w,MEMSUFFIX)(T1); \ FORCE_RET(); \ } \ void OPPROTO glue(op_vfp_st##p,MEMSUFFIX)(void) \ { \ glue(stf##w,MEMSUFFIX)(T1, FT0##p); \ FORCE_RET(); \ } VFP_MEM_OP(s,l) VFP_MEM_OP(d,q) #undef VFP_MEM_OP /* iwMMXt load/store. Address is in T1 */ #define MMX_MEM_OP(name, ldname) \ void OPPROTO glue(op_iwmmxt_ld##name,MEMSUFFIX)(void) \ { \ M0 = glue(ld##ldname,MEMSUFFIX)(T1); \ FORCE_RET(); \ } \ void OPPROTO glue(op_iwmmxt_st##name,MEMSUFFIX)(void) \ { \ glue(st##name,MEMSUFFIX)(T1, M0); \ FORCE_RET(); \ } MMX_MEM_OP(b, ub) MMX_MEM_OP(w, uw) MMX_MEM_OP(l, l) MMX_MEM_OP(q, q) #undef MMX_MEM_OP #undef MEMSUFFIX