diff --git a/Makefile.target b/Makefile.target
index 1c50bbe..c9815c6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ tcg/tcg.o: cpu.h

 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o ldst_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)

 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 25b4f1a..0b40475 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -580,8 +580,90 @@ void cpu_unassigned_access(CPUState *env1,
target_phys_addr_t addr,
 #if defined(TARGET_SPARC64)
 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
                                            int mmu_idx);
+#endif
+
+#define WRAP_LD(rettype, fn)                                    \
+    rettype cpu_ ## fn (CPUState *env1, target_ulong addr)
+
+WRAP_LD(uint32_t, ldub_kernel);
+WRAP_LD(uint32_t, lduw_kernel);
+WRAP_LD(uint32_t, ldl_kernel);
+WRAP_LD(uint64_t, ldq_kernel);
+
+WRAP_LD(uint32_t, ldub_user);
+WRAP_LD(uint32_t, lduw_user);
+WRAP_LD(uint32_t, ldl_user);
+WRAP_LD(uint64_t, ldq_user);
+
+WRAP_LD(uint64_t, ldfq_kernel);
+WRAP_LD(uint64_t, ldfq_user);
+
+#ifdef TARGET_SPARC64
+WRAP_LD(uint32_t, ldub_hypv);
+WRAP_LD(uint32_t, lduw_hypv);
+WRAP_LD(uint32_t, ldl_hypv);
+WRAP_LD(uint64_t, ldq_hypv);
+
+WRAP_LD(uint64_t, ldfq_hypv);
+
+WRAP_LD(uint32_t, ldub_nucleus);
+WRAP_LD(uint32_t, lduw_nucleus);
+WRAP_LD(uint32_t, ldl_nucleus);
+WRAP_LD(uint64_t, ldq_nucleus);
+
+WRAP_LD(uint32_t, ldub_kernel_secondary);
+WRAP_LD(uint32_t, lduw_kernel_secondary);
+WRAP_LD(uint32_t, ldl_kernel_secondary);
+WRAP_LD(uint64_t, ldq_kernel_secondary);
+
+WRAP_LD(uint32_t, ldub_user_secondary);
+WRAP_LD(uint32_t, lduw_user_secondary);
+WRAP_LD(uint32_t, ldl_user_secondary);
+WRAP_LD(uint64_t, ldq_user_secondary);
+#endif
+#undef WRAP_LD
+
+#define WRAP_ST(datatype, fn)                                           \
+    void cpu_ ## fn (CPUState *env1, target_ulong addr, datatype val)
+
+WRAP_ST(uint32_t, stb_kernel);
+WRAP_ST(uint32_t, stw_kernel);
+WRAP_ST(uint32_t, stl_kernel);
+WRAP_ST(uint64_t, stq_kernel);
+
+WRAP_ST(uint32_t, stb_user);
+WRAP_ST(uint32_t, stw_user);
+WRAP_ST(uint32_t, stl_user);
+WRAP_ST(uint64_t, stq_user);

+WRAP_ST(uint64_t, stfq_kernel);
+WRAP_ST(uint64_t, stfq_user);
+
+#ifdef TARGET_SPARC64
+WRAP_ST(uint32_t, stb_hypv);
+WRAP_ST(uint32_t, stw_hypv);
+WRAP_ST(uint32_t, stl_hypv);
+WRAP_ST(uint64_t, stq_hypv);
+
+WRAP_ST(uint64_t, stfq_hypv);
+
+WRAP_ST(uint32_t, stb_nucleus);
+WRAP_ST(uint32_t, stw_nucleus);
+WRAP_ST(uint32_t, stl_nucleus);
+WRAP_ST(uint64_t, stq_nucleus);
+
+WRAP_ST(uint32_t, stb_kernel_secondary);
+WRAP_ST(uint32_t, stw_kernel_secondary);
+WRAP_ST(uint32_t, stl_kernel_secondary);
+WRAP_ST(uint64_t, stq_kernel_secondary);
+
+WRAP_ST(uint32_t, stb_user_secondary);
+WRAP_ST(uint32_t, stw_user_secondary);
+WRAP_ST(uint32_t, stl_user_secondary);
+WRAP_ST(uint64_t, stq_user_secondary);
 #endif
+
+#undef WRAP_ST
 #endif
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 615ddef..c1b4e65 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -19,11 +19,11 @@ DEF_HELPER_2(wrcwp, void, env, tl)
 DEF_HELPER_3(array8, tl, env, tl, tl)
 DEF_HELPER_3(alignaddr, tl, env, tl, tl)
 DEF_HELPER_1(popc, tl, tl)
-DEF_HELPER_3(ldda_asi, void, tl, int, int)
-DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
-DEF_HELPER_4(stf_asi, void, tl, int, int, int)
-DEF_HELPER_4(cas_asi, tl, tl, tl, tl, i32)
-DEF_HELPER_4(casx_asi, tl, tl, tl, tl, i32)
+DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
+DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
+DEF_HELPER_5(stf_asi, void, env, tl, int, int, int)
+DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
+DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32)
 DEF_HELPER_2(set_softint, void, env, i64)
 DEF_HELPER_2(clear_softint, void, env, i64)
 DEF_HELPER_2(write_softint, void, env, i64)
@@ -31,7 +31,7 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64)
 DEF_HELPER_1(tick_get_count, i64, ptr)
 DEF_HELPER_2(tick_set_limit, void, ptr, i64)
 #endif
-DEF_HELPER_2(check_align, void, tl, i32)
+DEF_HELPER_3(check_align, void, env, tl, i32)
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_1(save, void, env)
 DEF_HELPER_1(restore, void, env)
@@ -39,13 +39,13 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
 DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
 DEF_HELPER_3(sdiv, tl, env, tl, tl)
 DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
-DEF_HELPER_2(stdf, void, tl, int)
-DEF_HELPER_2(lddf, void, tl, int)
-DEF_HELPER_2(ldqf, void, tl, int)
-DEF_HELPER_2(stqf, void, tl, int)
+DEF_HELPER_3(stdf, void, env, tl, int)
+DEF_HELPER_3(lddf, void, env, tl, int)
+DEF_HELPER_3(ldqf, void, env, tl, int)
+DEF_HELPER_3(stqf, void, env, tl, int)
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
-DEF_HELPER_4(st_asi, void, tl, i64, int, int)
+DEF_HELPER_5(ld_asi, i64, env, tl, int, int, int)
+DEF_HELPER_5(st_asi, void, env, tl, i64, int, int)
 #endif
 DEF_HELPER_2(ldfsr, void, env, i32)
 DEF_HELPER_1(check_ieee_exceptions, void, env)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 1fb3996..f5e52b2 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -18,13 +18,8 @@
  */

 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"

-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
-
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
 //#define DEBUG_UNALIGNED
@@ -71,16 +66,6 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)

-#if !defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                 int is_exec, int is_asi, int size);
-#else
-#ifdef TARGET_SPARC64
-static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
-                                 int is_asi, int size);
-#endif
-#endif
-
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 /* Calculates TSB pointer value for fault page size 8k or 64k */
 static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
@@ -302,8 +287,8 @@ static inline int is_translating_asi(int asi)
 #endif
 }

-static inline target_ulong asi_address_mask(CPUState *env1,
-                                            int asi, target_ulong addr)
+static inline target_ulong asi_address_mask(CPUState *env, int asi,
+                                            target_ulong addr)
 {
     if (is_translating_asi(asi)) {
         return address_mask(env, addr);
@@ -312,7 +297,7 @@ static inline target_ulong asi_address_mask(CPUState *env1,
     }
 }

-void helper_check_align(target_ulong addr, uint32_t align)
+void helper_check_align(CPUState *env, target_ulong addr, uint32_t align)
 {
     if (addr & align) {
 #ifdef DEBUG_UNALIGNED
@@ -374,7 +359,8 @@ static void dump_asi(const char *txt, target_ulong
addr, int asi, int size,

 /* Leon3 cache control */

-static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
+static void leon3_cache_control_st(CPUState *env, target_ulong addr,
+                                   uint64_t val, int size)
 {
     DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n",
                           addr, val, size);
@@ -406,7 +392,8 @@ static void leon3_cache_control_st(target_ulong
addr, uint64_t val, int size)
     };
 }

-static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
+static uint64_t leon3_cache_control_ld(CPUState *env, target_ulong addr,
+                                       int size)
 {
     uint64_t ret = 0;

@@ -438,14 +425,15 @@ static uint64_t
leon3_cache_control_ld(target_ulong addr, int size)
     return ret;
 }

-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUState *env, target_ulong addr, int asi, int size,
+                       int sign)
 {
     uint64_t ret = 0;
 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
     uint32_t last_addr = addr;
 #endif

-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     switch (asi) {
     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
@@ -453,7 +441,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi,
int size, int sign)
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
             if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
-                ret = leon3_cache_control_ld(addr, size);
+                ret = leon3_cache_control_ld(env, addr, size);
             }
             break;
         case 0x01c00a00: /* MXCC control register */
@@ -554,34 +542,34 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
     case 0xa: /* User data access */
         switch (size) {
         case 1:
-            ret = ldub_user(addr);
+            ret = cpu_ldub_user(env, addr);
             break;
         case 2:
-            ret = lduw_user(addr);
+            ret = cpu_lduw_user(env, addr);
             break;
         default:
         case 4:
-            ret = ldl_user(addr);
+            ret = cpu_ldl_user(env, addr);
             break;
         case 8:
-            ret = ldq_user(addr);
+            ret = cpu_ldq_user(env, addr);
             break;
         }
         break;
     case 0xb: /* Supervisor data access */
         switch (size) {
         case 1:
-            ret = ldub_kernel(addr);
+            ret = cpu_ldub_kernel(env, addr);
             break;
         case 2:
-            ret = lduw_kernel(addr);
+            ret = cpu_lduw_kernel(env, addr);
             break;
         default:
         case 4:
-            ret = ldl_kernel(addr);
+            ret = cpu_ldl_kernel(env, addr);
             break;
         case 8:
-            ret = ldq_kernel(addr);
+            ret = cpu_ldq_kernel(env, addr);
             break;
         }
         break;
@@ -671,7 +659,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi,
int size, int sign)
         break;
     case 8: /* User code access, XXX */
     default:
-        do_unassigned_access(addr, 0, 0, asi, size);
+        cpu_unassigned_access(env, addr, 0, 0, asi, size);
         ret = 0;
         break;
     }
@@ -696,9 +684,10 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
     return ret;
 }

-void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
+void helper_st_asi(CPUState *env, target_ulong addr, uint64_t val, int asi,
+                   int size)
 {
-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     switch (asi) {
     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
@@ -706,7 +695,7 @@ void helper_st_asi(target_ulong addr, uint64_t
val, int asi, int size)
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
             if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
-                leon3_cache_control_st(addr, val, size);
+                leon3_cache_control_st(env, addr, val, size);
             }
             break;

@@ -904,34 +893,34 @@ void helper_st_asi(target_ulong addr, uint64_t
val, int asi, int size)
     case 0xa: /* User data access */
         switch (size) {
         case 1:
-            stb_user(addr, val);
+            cpu_stb_user(env, addr, val);
             break;
         case 2:
-            stw_user(addr, val);
+            cpu_stw_user(env, addr, val);
             break;
         default:
         case 4:
-            stl_user(addr, val);
+            cpu_stl_user(env, addr, val);
             break;
         case 8:
-            stq_user(addr, val);
+            cpu_stq_user(env, addr, val);
             break;
         }
         break;
     case 0xb: /* Supervisor data access */
         switch (size) {
         case 1:
-            stb_kernel(addr, val);
+            cpu_stb_kernel(env, addr, val);
             break;
         case 2:
-            stw_kernel(addr, val);
+            cpu_stw_kernel(env, addr, val);
             break;
         default:
         case 4:
-            stl_kernel(addr, val);
+            cpu_stl_kernel(env, addr, val);
             break;
         case 8:
-            stq_kernel(addr, val);
+            cpu_stq_kernel(env, addr, val);
             break;
         }
         break;
@@ -954,8 +943,8 @@ void helper_st_asi(target_ulong addr, uint64_t
val, int asi, int size)
             uint32_t src = val & ~3, dst = addr & ~3, temp;

             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
-                temp = ldl_kernel(src);
-                stl_kernel(dst, temp);
+                temp = cpu_ldl_kernel(env, src);
+                cpu_stl_kernel(env, dst, temp);
             }
         }
         break;
@@ -967,7 +956,7 @@ void helper_st_asi(target_ulong addr, uint64_t
val, int asi, int size)
             uint32_t dst = addr & 7;

             for (i = 0; i < 32; i += 8, dst += 8) {
-                stq_kernel(dst, val);
+                cpu_stq_kernel(env, dst, val);
             }
         }
         break;
@@ -1058,7 +1047,7 @@ void helper_st_asi(target_ulong addr, uint64_t
val, int asi, int size)
     case 8: /* User code access, XXX */
     case 9: /* Supervisor code access, XXX */
     default:
-        do_unassigned_access(addr, 1, 0, asi, size);
+        cpu_unassigned_access(env, addr, 1, 0, asi, size);
         break;
     }
 #ifdef DEBUG_ASI
@@ -1070,7 +1059,8 @@ void helper_st_asi(target_ulong addr, uint64_t
val, int asi, int size)
 #else /* TARGET_SPARC64 */

 #ifdef CONFIG_USER_ONLY
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUState *env, target_ulong addr, int asi, int size,
+                       int sign)
 {
     uint64_t ret = 0;
 #if defined(DEBUG_ASI)
@@ -1081,7 +1071,7 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
         helper_raise_exception(env, TT_PRIV_ACT);
     }

-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);

     switch (asi) {
@@ -1176,7 +1166,8 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
     return ret;
 }

-void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
+void helper_st_asi(CPUState *env, target_ulong addr, target_ulong val, int asi,
+                   int size)
 {
 #ifdef DEBUG_ASI
     dump_asi("write", addr, asi, size, val);
@@ -1185,7 +1176,7 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
         helper_raise_exception(env, TT_PRIV_ACT);
     }

-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);

     /* Convert to little endian */
@@ -1240,14 +1231,15 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
     case 0x8a: /* Primary no-fault LE, RO */
     case 0x8b: /* Secondary no-fault LE, RO */
     default:
-        do_unassigned_access(addr, 1, 0, 1, size);
+        helper_raise_exception(env, TT_DATA_ACCESS);
         return;
     }
 }

 #else /* CONFIG_USER_ONLY */

-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUState *env, target_ulong addr, int asi, int size,
+                       int sign)
 {
     uint64_t ret = 0;
 #if defined(DEBUG_ASI)
@@ -1263,7 +1255,7 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
         helper_raise_exception(env, TT_PRIV_ACT);
     }

-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);

     /* process nonfaulting loads first */
@@ -1304,17 +1296,17 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
                 case 1:
-                    ret = ldub_hypv(addr);
+                    ret = cpu_ldub_hypv(env, addr);
                     break;
                 case 2:
-                    ret = lduw_hypv(addr);
+                    ret = cpu_lduw_hypv(env, addr);
                     break;
                 case 4:
-                    ret = ldl_hypv(addr);
+                    ret = cpu_ldl_hypv(env, addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_hypv(addr);
+                    ret = cpu_ldq_hypv(env, addr);
                     break;
                 }
             } else {
@@ -1322,33 +1314,33 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
                 if (asi & 1) {
                     switch (size) {
                     case 1:
-                        ret = ldub_kernel_secondary(addr);
+                        ret = cpu_ldub_kernel_secondary(env, addr);
                         break;
                     case 2:
-                        ret = lduw_kernel_secondary(addr);
+                        ret = cpu_lduw_kernel_secondary(env, addr);
                         break;
                     case 4:
-                        ret = ldl_kernel_secondary(addr);
+                        ret = cpu_ldl_kernel_secondary(env, addr);
                         break;
                     default:
                     case 8:
-                        ret = ldq_kernel_secondary(addr);
+                        ret = cpu_ldq_kernel_secondary(env, addr);
                         break;
                     }
                 } else {
                     switch (size) {
                     case 1:
-                        ret = ldub_kernel(addr);
+                        ret = cpu_ldub_kernel(env, addr);
                         break;
                     case 2:
-                        ret = lduw_kernel(addr);
+                        ret = cpu_lduw_kernel(env, addr);
                         break;
                     case 4:
-                        ret = ldl_kernel(addr);
+                        ret = cpu_ldl_kernel(env, addr);
                         break;
                     default:
                     case 8:
-                        ret = ldq_kernel(addr);
+                        ret = cpu_ldq_kernel(env, addr);
                         break;
                     }
                 }
@@ -1358,33 +1350,33 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
             if (asi & 1) {
                 switch (size) {
                 case 1:
-                    ret = ldub_user_secondary(addr);
+                    ret = cpu_ldub_user_secondary(env, addr);
                     break;
                 case 2:
-                    ret = lduw_user_secondary(addr);
+                    ret = cpu_lduw_user_secondary(env, addr);
                     break;
                 case 4:
-                    ret = ldl_user_secondary(addr);
+                    ret = cpu_ldl_user_secondary(env, addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_user_secondary(addr);
+                    ret = cpu_ldq_user_secondary(env, addr);
                     break;
                 }
             } else {
                 switch (size) {
                 case 1:
-                    ret = ldub_user(addr);
+                    ret = cpu_ldub_user(env, addr);
                     break;
                 case 2:
-                    ret = lduw_user(addr);
+                    ret = cpu_lduw_user(env, addr);
                     break;
                 case 4:
-                    ret = ldl_user(addr);
+                    ret = cpu_ldl_user(env, addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_user(addr);
+                    ret = cpu_ldq_user(env, addr);
                     break;
                 }
             }
@@ -1422,17 +1414,17 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
         {
             switch (size) {
             case 1:
-                ret = ldub_nucleus(addr);
+                ret = cpu_ldub_nucleus(env, addr);
                 break;
             case 2:
-                ret = lduw_nucleus(addr);
+                ret = cpu_lduw_nucleus(env, addr);
                 break;
             case 4:
-                ret = ldl_nucleus(addr);
+                ret = cpu_ldl_nucleus(env, addr);
                 break;
             default:
             case 8:
-                ret = ldq_nucleus(addr);
+                ret = cpu_ldq_nucleus(env, addr);
                 break;
             }
             break;
@@ -1553,7 +1545,7 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
     case 0x5f: /* D-MMU demap, WO */
     case 0x77: /* Interrupt vector, WO */
     default:
-        do_unassigned_access(addr, 0, 0, 1, size);
+        cpu_unassigned_access(env, addr, 0, 0, 1, size);
         ret = 0;
         break;
     }
@@ -1606,7 +1598,8 @@ uint64_t helper_ld_asi(target_ulong addr, int
asi, int size, int sign)
     return ret;
 }

-void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
+void helper_st_asi(CPUState *env, target_ulong addr, target_ulong val, int asi,
+                   int size)
 {
 #ifdef DEBUG_ASI
     dump_asi("write", addr, asi, size, val);
@@ -1621,7 +1614,7 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
         helper_raise_exception(env, TT_PRIV_ACT);
     }

-    helper_check_align(addr, size - 1);
+    helper_check_align(env, addr, size - 1);
     addr = asi_address_mask(env, asi, addr);

     /* Convert to little endian */
@@ -1665,17 +1658,17 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
                 case 1:
-                    stb_hypv(addr, val);
+                    cpu_stb_hypv(env, addr, val);
                     break;
                 case 2:
-                    stw_hypv(addr, val);
+                    cpu_stw_hypv(env, addr, val);
                     break;
                 case 4:
-                    stl_hypv(addr, val);
+                    cpu_stl_hypv(env, addr, val);
                     break;
                 case 8:
                 default:
-                    stq_hypv(addr, val);
+                    cpu_stq_hypv(env, addr, val);
                     break;
                 }
             } else {
@@ -1683,33 +1676,33 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
                 if (asi & 1) {
                     switch (size) {
                     case 1:
-                        stb_kernel_secondary(addr, val);
+                        cpu_stb_kernel_secondary(env, addr, val);
                         break;
                     case 2:
-                        stw_kernel_secondary(addr, val);
+                        cpu_stw_kernel_secondary(env, addr, val);
                         break;
                     case 4:
-                        stl_kernel_secondary(addr, val);
+                        cpu_stl_kernel_secondary(env, addr, val);
                         break;
                     case 8:
                     default:
-                        stq_kernel_secondary(addr, val);
+                        cpu_stq_kernel_secondary(env, addr, val);
                         break;
                     }
                 } else {
                     switch (size) {
                     case 1:
-                        stb_kernel(addr, val);
+                        cpu_stb_kernel(env, addr, val);
                         break;
                     case 2:
-                        stw_kernel(addr, val);
+                        cpu_stw_kernel(env, addr, val);
                         break;
                     case 4:
-                        stl_kernel(addr, val);
+                        cpu_stl_kernel(env, addr, val);
                         break;
                     case 8:
                     default:
-                        stq_kernel(addr, val);
+                        cpu_stq_kernel(env, addr, val);
                         break;
                     }
                 }
@@ -1719,33 +1712,33 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
             if (asi & 1) {
                 switch (size) {
                 case 1:
-                    stb_user_secondary(addr, val);
+                    cpu_stb_user_secondary(env, addr, val);
                     break;
                 case 2:
-                    stw_user_secondary(addr, val);
+                    cpu_stw_user_secondary(env, addr, val);
                     break;
                 case 4:
-                    stl_user_secondary(addr, val);
+                    cpu_stl_user_secondary(env, addr, val);
                     break;
                 case 8:
                 default:
-                    stq_user_secondary(addr, val);
+                    cpu_stq_user_secondary(env, addr, val);
                     break;
                 }
             } else {
                 switch (size) {
                 case 1:
-                    stb_user(addr, val);
+                    cpu_stb_user(env, addr, val);
                     break;
                 case 2:
-                    stw_user(addr, val);
+                    cpu_stw_user(env, addr, val);
                     break;
                 case 4:
-                    stl_user(addr, val);
+                    cpu_stl_user(env, addr, val);
                     break;
                 case 8:
                 default:
-                    stq_user(addr, val);
+                    cpu_stq_user(env, addr, val);
                     break;
                 }
             }
@@ -1783,17 +1776,17 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
         {
             switch (size) {
             case 1:
-                stb_nucleus(addr, val);
+                cpu_stb_nucleus(env, addr, val);
                 break;
             case 2:
-                stw_nucleus(addr, val);
+                cpu_stw_nucleus(env, addr, val);
                 break;
             case 4:
-                stl_nucleus(addr, val);
+                cpu_stl_nucleus(env, addr, val);
                 break;
             default:
             case 8:
-                stq_nucleus(addr, val);
+                cpu_stq_nucleus(env, addr, val);
                 break;
             }
             break;
@@ -1985,13 +1978,13 @@ void helper_st_asi(target_ulong addr,
target_ulong val, int asi, int size)
     case 0x8a: /* Primary no-fault LE, RO */
     case 0x8b: /* Secondary no-fault LE, RO */
     default:
-        do_unassigned_access(addr, 1, 0, 1, size);
+        cpu_unassigned_access(env, addr, 1, 0, 1, size);
         return;
     }
 }
 #endif /* CONFIG_USER_ONLY */

-void helper_ldda_asi(target_ulong addr, int asi, int rd)
+void helper_ldda_asi(CPUState *env, target_ulong addr, int asi, int rd)
 {
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
@@ -2006,22 +1999,22 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
 #if !defined(CONFIG_USER_ONLY)
     case 0x24: /* Nucleus quad LDD 128 bit atomic */
     case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
-        helper_check_align(addr, 0xf);
+        helper_check_align(env, addr, 0xf);
         if (rd == 0) {
-            env->gregs[1] = ldq_nucleus(addr + 8);
+            env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
             if (asi == 0x2c) {
                 bswap64s(&env->gregs[1]);
             }
         } else if (rd < 8) {
-            env->gregs[rd] = ldq_nucleus(addr);
-            env->gregs[rd + 1] = ldq_nucleus(addr + 8);
+            env->gregs[rd] = cpu_ldq_nucleus(env, addr);
+            env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
             if (asi == 0x2c) {
                 bswap64s(&env->gregs[rd]);
                 bswap64s(&env->gregs[rd + 1]);
             }
         } else {
-            env->regwptr[rd] = ldq_nucleus(addr);
-            env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
+            env->regwptr[rd] = cpu_ldq_nucleus(env, addr);
+            env->regwptr[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
             if (asi == 0x2c) {
                 bswap64s(&env->regwptr[rd]);
                 bswap64s(&env->regwptr[rd + 1]);
@@ -2030,26 +2023,27 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
         break;
 #endif
     default:
-        helper_check_align(addr, 0x3);
+        helper_check_align(env, addr, 0x3);
         if (rd == 0) {
-            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
+            env->gregs[1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
         } else if (rd < 8) {
-            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
-            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
+            env->gregs[rd] = helper_ld_asi(env, addr, asi, 4, 0);
+            env->gregs[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
         } else {
-            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
-            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
+            env->regwptr[rd] = helper_ld_asi(env, addr, asi, 4, 0);
+            env->regwptr[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
         }
         break;
     }
 }

-void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
+void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
+                    int rd)
 {
     unsigned int i;
     CPU_DoubleU u;

-    helper_check_align(addr, 3);
+    helper_check_align(env, addr, 3);
     addr = asi_address_mask(env, asi, addr);

     switch (asi) {
@@ -2061,10 +2055,10 @@ void helper_ldf_asi(target_ulong addr, int
asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 16; i++) {
-            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
-                                                         0);
+            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(env, addr, asi & 0x8f,
+                                                         4, 0);
             addr += 4;
         }

@@ -2081,10 +2075,10 @@ void helper_ldf_asi(target_ulong addr, int
asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 16; i++) {
-            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x19, 4,
-                                                         0);
+            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(env, addr, asi & 0x19,
+                                                         4, 0);
             addr += 4;
         }

@@ -2096,31 +2090,32 @@ void helper_ldf_asi(target_ulong addr, int
asi, int size, int rd)
     switch (size) {
     default:
     case 4:
-        *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(addr, asi, size, 0);
+        *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(env, addr, asi, size, 0);
         break;
     case 8:
-        u.ll = helper_ld_asi(addr, asi, size, 0);
+        u.ll = helper_ld_asi(env, addr, asi, size, 0);
         *((uint32_t *)&env->fpr[rd++]) = u.l.upper;
         *((uint32_t *)&env->fpr[rd++]) = u.l.lower;
         break;
     case 16:
-        u.ll = helper_ld_asi(addr, asi, 8, 0);
+        u.ll = helper_ld_asi(env, addr, asi, 8, 0);
         *((uint32_t *)&env->fpr[rd++]) = u.l.upper;
         *((uint32_t *)&env->fpr[rd++]) = u.l.lower;
-        u.ll = helper_ld_asi(addr + 8, asi, 8, 0);
+        u.ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
         *((uint32_t *)&env->fpr[rd++]) = u.l.upper;
         *((uint32_t *)&env->fpr[rd++]) = u.l.lower;
         break;
     }
 }

-void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
+void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
+                    int rd)
 {
     unsigned int i;
     target_ulong val = 0;
     CPU_DoubleU u;

-    helper_check_align(addr, 3);
+    helper_check_align(env, addr, 3);
     addr = asi_address_mask(env, asi, addr);

     switch (asi) {
@@ -2134,10 +2129,10 @@ void helper_stf_asi(target_ulong addr, int
asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 16; i++) {
             val = *(uint32_t *)&env->fpr[rd++];
-            helper_st_asi(addr, val, asi & 0x8f, 4);
+            helper_st_asi(env, addr, val, asi & 0x8f, 4);
             addr += 4;
         }

@@ -2154,10 +2149,10 @@ void helper_stf_asi(target_ulong addr, int
asi, int size, int rd)
             helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
-        helper_check_align(addr, 0x3f);
+        helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 16; i++) {
             val = *(uint32_t *)&env->fpr[rd++];
-            helper_st_asi(addr, val, asi & 0x19, 4);
+            helper_st_asi(env, addr, val, asi & 0x19, 4);
             addr += 4;
         }

@@ -2169,65 +2164,66 @@ void helper_stf_asi(target_ulong addr, int
asi, int size, int rd)
     switch (size) {
     default:
     case 4:
-        helper_st_asi(addr, *(uint32_t *)&env->fpr[rd], asi, size);
+        helper_st_asi(env, addr, *(uint32_t *)&env->fpr[rd], asi, size);
         break;
     case 8:
         u.l.upper = *(uint32_t *)&env->fpr[rd++];
         u.l.lower = *(uint32_t *)&env->fpr[rd++];
-        helper_st_asi(addr, u.ll, asi, size);
+        helper_st_asi(env, addr, u.ll, asi, size);
         break;
     case 16:
         u.l.upper = *(uint32_t *)&env->fpr[rd++];
         u.l.lower = *(uint32_t *)&env->fpr[rd++];
-        helper_st_asi(addr, u.ll, asi, 8);
+        helper_st_asi(env, addr, u.ll, asi, 8);
         u.l.upper = *(uint32_t *)&env->fpr[rd++];
         u.l.lower = *(uint32_t *)&env->fpr[rd++];
-        helper_st_asi(addr + 8, u.ll, asi, 8);
+        helper_st_asi(env, addr + 8, u.ll, asi, 8);
         break;
     }
 }

-target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
-                            target_ulong val2, uint32_t asi)
+target_ulong helper_cas_asi(CPUState *env, target_ulong addr,
+                            target_ulong val1, target_ulong val2, uint32_t asi)
 {
     target_ulong ret;

     val2 &= 0xffffffffUL;
-    ret = helper_ld_asi(addr, asi, 4, 0);
+    ret = helper_ld_asi(env, addr, asi, 4, 0);
     ret &= 0xffffffffUL;
     if (val2 == ret) {
-        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
+        helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
     }
     return ret;
 }

-target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
-                             target_ulong val2, uint32_t asi)
+target_ulong helper_casx_asi(CPUState *env, target_ulong addr,
+                             target_ulong val1, target_ulong val2,
+                             uint32_t asi)
 {
     target_ulong ret;

-    ret = helper_ld_asi(addr, asi, 8, 0);
+    ret = helper_ld_asi(env, addr, asi, 8, 0);
     if (val2 == ret) {
-        helper_st_asi(addr, val1, asi, 8);
+        helper_st_asi(env, addr, val1, asi, 8);
     }
     return ret;
 }
 #endif /* TARGET_SPARC64 */

-void helper_stdf(target_ulong addr, int mem_idx)
+void helper_stdf(CPUState *env, target_ulong addr, int mem_idx)
 {
-    helper_check_align(addr, 7);
+    helper_check_align(env, addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
     case MMU_USER_IDX:
-        stfq_user(addr, DT0);
+        cpu_stfq_user(env, addr, DT0);
         break;
     case MMU_KERNEL_IDX:
-        stfq_kernel(addr, DT0);
+        cpu_stfq_kernel(env, addr, DT0);
         break;
 #ifdef TARGET_SPARC64
     case MMU_HYPV_IDX:
-        stfq_hypv(addr, DT0);
+        cpu_stfq_hypv(env, addr, DT0);
         break;
 #endif
     default:
@@ -2239,20 +2235,20 @@ void helper_stdf(target_ulong addr, int mem_idx)
 #endif
 }

-void helper_lddf(target_ulong addr, int mem_idx)
+void helper_lddf(CPUState *env, target_ulong addr, int mem_idx)
 {
-    helper_check_align(addr, 7);
+    helper_check_align(env, addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
     case MMU_USER_IDX:
-        DT0 = ldfq_user(addr);
+        DT0 = cpu_ldfq_user(env, addr);
         break;
     case MMU_KERNEL_IDX:
-        DT0 = ldfq_kernel(addr);
+        DT0 = cpu_ldfq_kernel(env, addr);
         break;
 #ifdef TARGET_SPARC64
     case MMU_HYPV_IDX:
-        DT0 = ldfq_hypv(addr);
+        DT0 = cpu_ldfq_hypv(env, addr);
         break;
 #endif
     default:
@@ -2264,28 +2260,28 @@ void helper_lddf(target_ulong addr, int mem_idx)
 #endif
 }

-void helper_ldqf(target_ulong addr, int mem_idx)
+void helper_ldqf(CPUState *env, target_ulong addr, int mem_idx)
 {
     /* XXX add 128 bit load */
     CPU_QuadU u;

-    helper_check_align(addr, 7);
+    helper_check_align(env, addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
     case MMU_USER_IDX:
-        u.ll.upper = ldq_user(addr);
-        u.ll.lower = ldq_user(addr + 8);
+        u.ll.upper = cpu_ldq_user(env, addr);
+        u.ll.lower = cpu_ldq_user(env, addr + 8);
         QT0 = u.q;
         break;
     case MMU_KERNEL_IDX:
-        u.ll.upper = ldq_kernel(addr);
-        u.ll.lower = ldq_kernel(addr + 8);
+        u.ll.upper = cpu_ldq_kernel(env, addr);
+        u.ll.lower = cpu_ldq_kernel(env, addr + 8);
         QT0 = u.q;
         break;
 #ifdef TARGET_SPARC64
     case MMU_HYPV_IDX:
-        u.ll.upper = ldq_hypv(addr);
-        u.ll.lower = ldq_hypv(addr + 8);
+        u.ll.upper = cpu_ldq_hypv(env, addr);
+        u.ll.lower = cpu_ldq_hypv(env, addr + 8);
         QT0 = u.q;
         break;
 #endif
@@ -2300,29 +2296,29 @@ void helper_ldqf(target_ulong addr, int mem_idx)
 #endif
 }

-void helper_stqf(target_ulong addr, int mem_idx)
+void helper_stqf(CPUState *env, target_ulong addr, int mem_idx)
 {
     /* XXX add 128 bit store */
     CPU_QuadU u;

-    helper_check_align(addr, 7);
+    helper_check_align(env, addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
     case MMU_USER_IDX:
         u.q = QT0;
-        stq_user(addr, u.ll.upper);
-        stq_user(addr + 8, u.ll.lower);
+        cpu_stq_user(env, addr, u.ll.upper);
+        cpu_stq_user(env, addr + 8, u.ll.lower);
         break;
     case MMU_KERNEL_IDX:
         u.q = QT0;
-        stq_kernel(addr, u.ll.upper);
-        stq_kernel(addr + 8, u.ll.lower);
+        cpu_stq_kernel(env, addr, u.ll.upper);
+        cpu_stq_kernel(env, addr + 8, u.ll.lower);
         break;
 #ifdef TARGET_SPARC64
     case MMU_HYPV_IDX:
         u.q = QT0;
-        stq_hypv(addr, u.ll.upper);
-        stq_hypv(addr + 8, u.ll.lower);
+        cpu_stq_hypv(env, addr, u.ll.upper);
+        cpu_stq_hypv(env, addr + 8, u.ll.lower);
         break;
 #endif
     default:
@@ -2336,10 +2332,10 @@ void helper_stqf(target_ulong addr, int mem_idx)
 #endif
 }

-#ifndef TARGET_SPARC64
 #if !defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                 int is_exec, int is_asi, int size)
+#ifndef TARGET_SPARC64
+void cpu_unassigned_access(CPUState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size)
 {
     int fault_type;

@@ -2397,15 +2393,9 @@ static void
do_unassigned_access(target_phys_addr_t addr, int is_write,
         tlb_flush(env, 1);
     }
 }
-#endif
-#else
-#if defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
-                                 int is_asi, int size)
 #else
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
-                                 int is_exec, int is_asi, int size)
-#endif
+void cpu_unassigned_access(CPUState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int is_asi, int size)
 {
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
@@ -2419,16 +2409,4 @@ static void
do_unassigned_access(target_phys_addr_t addr, int is_write,
     }
 }
 #endif
-
-#if !defined(CONFIG_USER_ONLY)
-void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
-                           int is_write, int is_exec, int is_asi, int size)
-{
-    CPUState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    do_unassigned_access(addr, is_write, is_exec, is_asi, size);
-    env = saved_env;
-}
 #endif
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 02b660d..e844947 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3,6 +3,7 @@
 #include "helper.h"

 #if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
                                 void *retaddr);

@@ -71,4 +72,103 @@ void tlb_fill(CPUState *env1, target_ulong addr,
int is_write, int mmu_idx,
     env = saved_env;
 }

-#endif /* !CONFIG_USER_ONLY */
+#define WRAP_LD(rettype, fn)                                    \
+    rettype cpu_ ## fn (CPUState *env1, target_ulong addr)      \
+    {                                                           \
+        CPUState *saved_env;                                    \
+        rettype ret;                                            \
+                                                                \
+        saved_env = env;                                        \
+        env = env1;                                             \
+        ret = fn(addr);                                         \
+        env = saved_env;                                        \
+        return ret;                                             \
+    }
+
+WRAP_LD(uint32_t, ldub_kernel)
+WRAP_LD(uint32_t, lduw_kernel)
+WRAP_LD(uint32_t, ldl_kernel)
+WRAP_LD(uint64_t, ldq_kernel)
+
+WRAP_LD(uint32_t, ldub_user)
+WRAP_LD(uint32_t, lduw_user)
+WRAP_LD(uint32_t, ldl_user)
+WRAP_LD(uint64_t, ldq_user)
+
+WRAP_LD(uint64_t, ldfq_kernel)
+WRAP_LD(uint64_t, ldfq_user)
+#ifdef TARGET_SPARC64
+WRAP_LD(uint32_t, ldub_hypv)
+WRAP_LD(uint32_t, lduw_hypv)
+WRAP_LD(uint32_t, ldl_hypv)
+WRAP_LD(uint64_t, ldq_hypv)
+
+WRAP_LD(uint64_t, ldfq_hypv)
+
+WRAP_LD(uint32_t, ldub_nucleus)
+WRAP_LD(uint32_t, lduw_nucleus)
+WRAP_LD(uint32_t, ldl_nucleus)
+WRAP_LD(uint64_t, ldq_nucleus)
+
+WRAP_LD(uint32_t, ldub_kernel_secondary)
+WRAP_LD(uint32_t, lduw_kernel_secondary)
+WRAP_LD(uint32_t, ldl_kernel_secondary)
+WRAP_LD(uint64_t, ldq_kernel_secondary)
+
+WRAP_LD(uint32_t, ldub_user_secondary)
+WRAP_LD(uint32_t, lduw_user_secondary)
+WRAP_LD(uint32_t, ldl_user_secondary)
+WRAP_LD(uint64_t, ldq_user_secondary)
+#endif
+#undef WRAP_LD
+
+#define WRAP_ST(datatype, fn)                                           \
+    void cpu_ ## fn (CPUState *env1, target_ulong addr, datatype val)   \
+    {                                                                   \
+        CPUState *saved_env;                                            \
+                                                                        \
+        saved_env = env;                                                \
+        env = env1;                                                     \
+        fn(addr, val);                                                  \
+        env = saved_env;                                                \
+    }
+
+WRAP_ST(uint32_t, stb_kernel)
+WRAP_ST(uint32_t, stw_kernel)
+WRAP_ST(uint32_t, stl_kernel)
+WRAP_ST(uint64_t, stq_kernel)
+
+WRAP_ST(uint32_t, stb_user)
+WRAP_ST(uint32_t, stw_user)
+WRAP_ST(uint32_t, stl_user)
+WRAP_ST(uint64_t, stq_user)
+
+WRAP_ST(uint64_t, stfq_kernel)
+WRAP_ST(uint64_t, stfq_user)
+
+#ifdef TARGET_SPARC64
+WRAP_ST(uint32_t, stb_hypv)
+WRAP_ST(uint32_t, stw_hypv)
+WRAP_ST(uint32_t, stl_hypv)
+WRAP_ST(uint64_t, stq_hypv)
+
+WRAP_ST(uint64_t, stfq_hypv)
+
+WRAP_ST(uint32_t, stb_nucleus)
+WRAP_ST(uint32_t, stw_nucleus)
+WRAP_ST(uint32_t, stl_nucleus)
+WRAP_ST(uint64_t, stq_nucleus)
+
+WRAP_ST(uint32_t, stb_kernel_secondary)
+WRAP_ST(uint32_t, stw_kernel_secondary)
+WRAP_ST(uint32_t, stl_kernel_secondary)
+WRAP_ST(uint64_t, stq_kernel_secondary)
+
+WRAP_ST(uint32_t, stb_user_secondary)
+WRAP_ST(uint32_t, stw_user_secondary)
+WRAP_ST(uint32_t, stl_user_secondary)
+WRAP_ST(uint64_t, stq_user_secondary)
+#endif
+
+#undef WRAP_ST
+#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 3fd8383..074967d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1612,7 +1612,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv
addr, int insn, int size,
     r_asi = gen_get_asi(insn, addr);
     r_size = tcg_const_i32(size);
     r_sign = tcg_const_i32(sign);
-    gen_helper_ld_asi(dst, addr, r_asi, r_size, r_sign);
+    gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
     tcg_temp_free_i32(r_sign);
     tcg_temp_free_i32(r_size);
