Use initial CPU definition structure for some CPU fields instead of copying
[qemu] / target-sparc / translate.c
index 36381c4..3f15fb9 100644 (file)
@@ -38,7 +38,7 @@
                          according to jump_pc[T2] */
 
 /* global register indexes */
-static TCGv cpu_env, cpu_T[2], cpu_regwptr;
+static TCGv cpu_env, cpu_regwptr;
 static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
 static TCGv cpu_psr, cpu_fsr, cpu_pc, cpu_npc, cpu_gregs[8];
 static TCGv cpu_cond, cpu_src1, cpu_src2, cpu_dst, cpu_addr, cpu_val;
@@ -48,6 +48,8 @@ static TCGv cpu_xcc;
 /* local register indexes (only used inside old micro ops) */
 static TCGv cpu_tmp0, cpu_tmp32, cpu_tmp64;
 
+#include "gen-icount.h"
+
 typedef struct DisasContext {
     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
@@ -55,8 +57,9 @@ typedef struct DisasContext {
     int is_br;
     int mem_idx;
     int fpu_enabled;
+    int address_mask_32bit;
     struct TranslationBlock *tb;
-    uint32_t features;
+    sparc_def_t *def;
 } DisasContext;
 
 // This function uses non-native bit order
@@ -199,11 +202,21 @@ static void gen_op_store_QT0_fpr(unsigned int dst)
 #endif
 #endif
 
-#ifdef TARGET_ABI32
-#define ABI32_MASK(addr) tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
+#ifdef TARGET_SPARC64
+#ifndef TARGET_ABI32
+#define AM_CHECK(dc) ((dc)->address_mask_32bit)
 #else
-#define ABI32_MASK(addr)
+#define AM_CHECK(dc) (1)
+#endif
+#endif
+
+static inline void gen_address_mask(DisasContext *dc, TCGv addr)
+{
+#ifdef TARGET_SPARC64
+    if (AM_CHECK(dc))
+        tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
 #endif
+}
 
 static inline void gen_movl_reg_TN(int reg, TCGv tn)
 {
@@ -311,6 +324,7 @@ static inline void gen_cc_NZ_icc(TCGv dst)
     tcg_gen_brcondi_tl(TCG_COND_GE, r_temp, 0, l2);
     tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_NEG);
     gen_set_label(l2);
+    tcg_temp_free(r_temp);
 }
 
 #ifdef TARGET_SPARC64
@@ -335,15 +349,19 @@ static inline void gen_cc_NZ_xcc(TCGv dst)
 */
 static inline void gen_cc_C_add_icc(TCGv dst, TCGv src1)
 {
-    TCGv r_temp;
+    TCGv r_temp1, r_temp2;
     int l1;
 
     l1 = gen_new_label();
-    r_temp = tcg_temp_new(TCG_TYPE_TL);
-    tcg_gen_andi_tl(r_temp, dst, 0xffffffffULL);
-    tcg_gen_brcond_tl(TCG_COND_GEU, dst, src1, l1);
+    r_temp1 = tcg_temp_new(TCG_TYPE_TL);
+    r_temp2 = tcg_temp_new(TCG_TYPE_TL);
+    tcg_gen_andi_tl(r_temp1, dst, 0xffffffffULL);
+    tcg_gen_andi_tl(r_temp2, src1, 0xffffffffULL);
+    tcg_gen_brcond_tl(TCG_COND_GEU, r_temp1, r_temp2, l1);
     tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_CARRY);
     gen_set_label(l1);
+    tcg_temp_free(r_temp1);
+    tcg_temp_free(r_temp2);
 }
 
 #ifdef TARGET_SPARC64
@@ -371,9 +389,10 @@ static inline void gen_cc_V_add_icc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_xori_tl(r_temp, r_temp, -1);
     tcg_gen_xor_tl(cpu_tmp0, src1, dst);
     tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
-    tcg_gen_andi_tl(r_temp, r_temp, (1 << 31));
+    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
     tcg_gen_shri_tl(r_temp, r_temp, 31 - PSR_OVF_SHIFT);
     tcg_gen_trunc_tl_i32(cpu_tmp32, r_temp);
+    tcg_temp_free(r_temp);
     tcg_gen_or_i32(cpu_psr, cpu_psr, cpu_tmp32);
 }
 
@@ -390,13 +409,14 @@ static inline void gen_cc_V_add_xcc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 63));
     tcg_gen_shri_tl(r_temp, r_temp, 63 - PSR_OVF_SHIFT);
     tcg_gen_trunc_tl_i32(cpu_tmp32, r_temp);
+    tcg_temp_free(r_temp);
     tcg_gen_or_i32(cpu_xcc, cpu_xcc, cpu_tmp32);
 }
 #endif
 
 static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
 {
-    TCGv r_temp;
+    TCGv r_temp, r_const;
     int l1;
 
     l1 = gen_new_label();
@@ -406,10 +426,13 @@ static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_xori_tl(r_temp, r_temp, -1);
     tcg_gen_xor_tl(cpu_tmp0, src1, dst);
     tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
-    tcg_gen_andi_tl(r_temp, r_temp, (1 << 31));
+    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
     tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_TOVF));
+    r_const = tcg_const_i32(TT_TOVF);
+    tcg_gen_helper_0_1(raise_exception, r_const);
+    tcg_temp_free(r_const);
     gen_set_label(l1);
+    tcg_temp_free(r_temp);
 }
 
 static inline void gen_cc_V_tag(TCGv src1, TCGv src2)
@@ -427,12 +450,15 @@ static inline void gen_cc_V_tag(TCGv src1, TCGv src2)
 static inline void gen_tag_tv(TCGv src1, TCGv src2)
 {
     int l1;
+    TCGv r_const;
 
     l1 = gen_new_label();
     tcg_gen_or_tl(cpu_tmp0, src1, src2);
     tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_TOVF));
+    r_const = tcg_const_i32(TT_TOVF);
+    tcg_gen_helper_0_1(raise_exception, r_const);
+    tcg_temp_free(r_const);
     gen_set_label(l1);
 }
 
@@ -440,8 +466,7 @@ static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
 {
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    tcg_gen_add_tl(dst, src1, src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_add_icc(cpu_cc_dst, cpu_cc_src);
@@ -452,6 +477,7 @@ static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_add_xcc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_add_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_addx_cc(TCGv dst, TCGv src1, TCGv src2)
@@ -459,15 +485,14 @@ static inline void gen_op_addx_cc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
     gen_mov_reg_C(cpu_tmp0, cpu_psr);
-    tcg_gen_add_tl(dst, src1, cpu_tmp0);
+    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
     gen_cc_clear_icc();
-    gen_cc_C_add_icc(dst, cpu_cc_src);
+    gen_cc_C_add_icc(cpu_cc_dst, cpu_cc_src);
 #ifdef TARGET_SPARC64
     gen_cc_clear_xcc();
-    gen_cc_C_add_xcc(dst, cpu_cc_src);
+    gen_cc_C_add_xcc(cpu_cc_dst, cpu_cc_src);
 #endif
-    tcg_gen_add_tl(dst, dst, cpu_cc_src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_dst, cpu_cc_src2);
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_add_icc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_add_icc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
@@ -476,14 +501,14 @@ static inline void gen_op_addx_cc(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_add_xcc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_add_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
 {
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    tcg_gen_add_tl(dst, src1, src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_add_icc(cpu_cc_dst, cpu_cc_src);
@@ -495,6 +520,7 @@ static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_add_xcc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_add_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
@@ -502,9 +528,8 @@ static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
     gen_tag_tv(cpu_cc_src, cpu_cc_src2);
-    tcg_gen_add_tl(dst, src1, src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
-    gen_add_tv(dst, cpu_cc_src, cpu_cc_src2);
+    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
+    gen_add_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_add_icc(cpu_cc_dst, cpu_cc_src);
@@ -514,6 +539,7 @@ static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_add_xcc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_add_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 /* old op:
@@ -533,6 +559,8 @@ static inline void gen_cc_C_sub_icc(TCGv src1, TCGv src2)
     tcg_gen_brcond_tl(TCG_COND_GEU, r_temp1, r_temp2, l1);
     tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_CARRY);
     gen_set_label(l1);
+    tcg_temp_free(r_temp1);
+    tcg_temp_free(r_temp2);
 }
 
 #ifdef TARGET_SPARC64
@@ -559,10 +587,11 @@ static inline void gen_cc_V_sub_icc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_xor_tl(r_temp, src1, src2);
     tcg_gen_xor_tl(cpu_tmp0, src1, dst);
     tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
-    tcg_gen_andi_tl(r_temp, r_temp, (1 << 31));
+    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
     tcg_gen_shri_tl(r_temp, r_temp, 31 - PSR_OVF_SHIFT);
     tcg_gen_trunc_tl_i32(cpu_tmp32, r_temp);
     tcg_gen_or_i32(cpu_psr, cpu_psr, cpu_tmp32);
+    tcg_temp_free(r_temp);
 }
 
 #ifdef TARGET_SPARC64
@@ -578,12 +607,13 @@ static inline void gen_cc_V_sub_xcc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_shri_tl(r_temp, r_temp, 63 - PSR_OVF_SHIFT);
     tcg_gen_trunc_tl_i32(cpu_tmp32, r_temp);
     tcg_gen_or_i32(cpu_xcc, cpu_xcc, cpu_tmp32);
+    tcg_temp_free(r_temp);
 }
 #endif
 
 static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
 {
-    TCGv r_temp;
+    TCGv r_temp, r_const;
     int l1;
 
     l1 = gen_new_label();
@@ -592,18 +622,20 @@ static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_xor_tl(r_temp, src1, src2);
     tcg_gen_xor_tl(cpu_tmp0, src1, dst);
     tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
-    tcg_gen_andi_tl(r_temp, r_temp, (1 << 31));
+    tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
     tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_TOVF));
+    r_const = tcg_const_i32(TT_TOVF);
+    tcg_gen_helper_0_1(raise_exception, r_const);
+    tcg_temp_free(r_const);
     gen_set_label(l1);
+    tcg_temp_free(r_temp);
 }
 
 static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
 {
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    tcg_gen_sub_tl(dst, src1, src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_sub_icc(cpu_cc_src, cpu_cc_src2);
@@ -614,6 +646,7 @@ static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_sub_xcc(cpu_cc_src, cpu_cc_src2);
     gen_cc_V_sub_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_subx_cc(TCGv dst, TCGv src1, TCGv src2)
@@ -621,15 +654,14 @@ static inline void gen_op_subx_cc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
     gen_mov_reg_C(cpu_tmp0, cpu_psr);
-    tcg_gen_sub_tl(dst, src1, cpu_tmp0);
+    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
     gen_cc_clear_icc();
-    gen_cc_C_sub_icc(dst, cpu_cc_src);
+    gen_cc_C_sub_icc(cpu_cc_dst, cpu_cc_src);
 #ifdef TARGET_SPARC64
     gen_cc_clear_xcc();
-    gen_cc_C_sub_xcc(dst, cpu_cc_src);
+    gen_cc_C_sub_xcc(cpu_cc_dst, cpu_cc_src);
 #endif
-    tcg_gen_sub_tl(dst, dst, cpu_cc_src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_dst, cpu_cc_src2);
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_sub_icc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_sub_icc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
@@ -638,14 +670,14 @@ static inline void gen_op_subx_cc(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_sub_xcc(cpu_cc_dst, cpu_cc_src);
     gen_cc_V_sub_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
 {
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    tcg_gen_sub_tl(dst, src1, src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_sub_icc(cpu_cc_src, cpu_cc_src2);
@@ -657,6 +689,7 @@ static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_sub_xcc(cpu_cc_src, cpu_cc_src2);
     gen_cc_V_sub_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
@@ -664,9 +697,8 @@ static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
     gen_tag_tv(cpu_cc_src, cpu_cc_src2);
-    tcg_gen_sub_tl(dst, src1, src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
-    gen_sub_tv(dst, cpu_cc_src, cpu_cc_src2);
+    tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
+    gen_sub_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_C_sub_icc(cpu_cc_src, cpu_cc_src2);
@@ -676,6 +708,7 @@ static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
     gen_cc_C_sub_xcc(cpu_cc_src, cpu_cc_src2);
     gen_cc_V_sub_xcc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 #endif
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
@@ -708,12 +741,14 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, y));
     tcg_gen_shri_i32(cpu_tmp32, cpu_tmp32, 1);
     tcg_gen_or_i32(cpu_tmp32, cpu_tmp32, r_temp2);
+    tcg_temp_free(r_temp2);
     tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, y));
 
     // b1 = N ^ V;
     gen_mov_reg_N(cpu_tmp0, cpu_psr);
     gen_mov_reg_V(r_temp, cpu_psr);
     tcg_gen_xor_tl(cpu_tmp0, cpu_tmp0, r_temp);
+    tcg_temp_free(r_temp);
 
     // T0 = (b1 << 31) | (T0 >> 1);
     // src1 = T0;
@@ -722,13 +757,13 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
 
     /* do addition and update flags */
-    tcg_gen_add_tl(dst, cpu_cc_src, cpu_cc_src2);
-    tcg_gen_mov_tl(cpu_cc_dst, dst);
+    tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
 
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     gen_cc_V_add_icc(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
     gen_cc_C_add_icc(cpu_cc_dst, cpu_cc_src);
+    tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
 static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
@@ -745,11 +780,13 @@ static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_shri_i64(r_temp, r_temp2, 32);
     tcg_gen_trunc_i64_i32(r_temp, r_temp);
     tcg_gen_st_i32(r_temp, cpu_env, offsetof(CPUSPARCState, y));
+    tcg_temp_free(r_temp);
 #ifdef TARGET_SPARC64
     tcg_gen_mov_i64(dst, r_temp2);
 #else
     tcg_gen_trunc_i64_tl(dst, r_temp2);
 #endif
+    tcg_temp_free(r_temp2);
 }
 
 static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
@@ -766,21 +803,26 @@ static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_shri_i64(r_temp, r_temp2, 32);
     tcg_gen_trunc_i64_i32(r_temp, r_temp);
     tcg_gen_st_i32(r_temp, cpu_env, offsetof(CPUSPARCState, y));
+    tcg_temp_free(r_temp);
 #ifdef TARGET_SPARC64
     tcg_gen_mov_i64(dst, r_temp2);
 #else
     tcg_gen_trunc_i64_tl(dst, r_temp2);
 #endif
+    tcg_temp_free(r_temp2);
 }
 
 #ifdef TARGET_SPARC64
 static inline void gen_trap_ifdivzero_tl(TCGv divisor)
 {
+    TCGv r_const;
     int l1;
 
     l1 = gen_new_label();
     tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_DIV_ZERO));
+    r_const = tcg_const_i32(TT_DIV_ZERO);
+    tcg_gen_helper_0_1(raise_exception, r_const);
+    tcg_temp_free(r_const);
     gen_set_label(l1);
 }
 
@@ -792,7 +834,7 @@ static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
     l2 = gen_new_label();
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    gen_trap_ifdivzero_tl(src2);
+    gen_trap_ifdivzero_tl(cpu_cc_src2);
     tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc_src, INT64_MIN, l1);
     tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc_src2, -1, l1);
     tcg_gen_movi_i64(dst, INT64_MIN);
@@ -811,8 +853,7 @@ static inline void gen_op_div_cc(TCGv dst)
     gen_cc_clear_icc();
     gen_cc_NZ_icc(cpu_cc_dst);
     l1 = gen_new_label();
-    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, cc_src2));
-    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cc_src2, 0, l1);
     tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_OVF);
     gen_set_label(l1);
 }
@@ -1563,17 +1604,25 @@ static inline void gen_op_fcmpeq(int fccno)
 
 static inline void gen_op_fpexception_im(int fsr_flags)
 {
+    TCGv r_const;
+
     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, ~FSR_FTT_MASK);
     tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_FP_EXCP));
+    r_const = tcg_const_i32(TT_FP_EXCP);
+    tcg_gen_helper_0_1(raise_exception, r_const);
+    tcg_temp_free(r_const);
 }
 
 static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
 {
 #if !defined(CONFIG_USER_ONLY)
     if (!dc->fpu_enabled) {
+        TCGv r_const;
+
         save_state(dc, r_cond);
-        tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_NFPU_INSN));
+        r_const = tcg_const_i32(TT_NFPU_INSN);
+        tcg_gen_helper_0_1(raise_exception, r_const);
+        tcg_temp_free(r_const);
         dc->is_br = 1;
         return 1;
     }
@@ -1595,13 +1644,11 @@ static inline void gen_clear_float_exceptions(void)
 #ifdef TARGET_SPARC64
 static inline TCGv gen_get_asi(int insn, TCGv r_addr)
 {
-    int asi, offset;
+    int asi;
     TCGv r_asi;
 
     if (IS_IMM) {
         r_asi = tcg_temp_new(TCG_TYPE_I32);
-        offset = GET_FIELD(insn, 25, 31);
-        tcg_gen_addi_tl(r_addr, r_addr, offset);
         tcg_gen_ld_i32(r_asi, cpu_env, offsetof(CPUSPARCState, asi));
     } else {
         asi = GET_FIELD(insn, 19, 26);
@@ -1613,75 +1660,94 @@ static inline TCGv gen_get_asi(int insn, TCGv r_addr)
 static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
                               int sign)
 {
-    TCGv r_asi;
+    TCGv r_asi, r_size, r_sign;
 
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_1_4(helper_ld_asi, dst, addr, r_asi,
-                       tcg_const_i32(size), tcg_const_i32(sign));
+    r_size = tcg_const_i32(size);
+    r_sign = tcg_const_i32(sign);
+    tcg_gen_helper_1_4(helper_ld_asi, dst, addr, r_asi, r_size, r_sign);
+    tcg_temp_free(r_sign);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
 {
-    TCGv r_asi;
+    TCGv r_asi, r_size;
 
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_0_4(helper_st_asi, addr, src, r_asi, tcg_const_i32(size));
+    r_size = tcg_const_i32(size);
+    tcg_gen_helper_0_4(helper_st_asi, addr, src, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
 {
-    TCGv r_asi;
+    TCGv r_asi, r_size, r_rd;
 
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_0_4(helper_ldf_asi, addr, r_asi, tcg_const_i32(size),
-                       tcg_const_i32(rd));
+    r_size = tcg_const_i32(size);
+    r_rd = tcg_const_i32(rd);
+    tcg_gen_helper_0_4(helper_ldf_asi, addr, r_asi, r_size, r_rd);
+    tcg_temp_free(r_rd);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
 {
-    TCGv r_asi;
+    TCGv r_asi, r_size, r_rd;
 
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_0_4(helper_stf_asi, addr, r_asi, tcg_const_i32(size),
-                       tcg_const_i32(rd));
+    r_size = tcg_const_i32(size);
+    r_rd = tcg_const_i32(rd);
+    tcg_gen_helper_0_4(helper_stf_asi, addr, r_asi, r_size, r_rd);
+    tcg_temp_free(r_rd);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
 {
-    TCGv r_temp, r_asi;
+    TCGv r_asi, r_size, r_sign;
 
-    r_temp = tcg_temp_new(TCG_TYPE_I32);
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_1_4(helper_ld_asi, r_temp, addr, r_asi,
-                       tcg_const_i32(4), tcg_const_i32(0));
-    tcg_gen_helper_0_4(helper_st_asi, addr, dst, r_asi,
-                       tcg_const_i32(4));
-    tcg_gen_extu_i32_tl(dst, r_temp);
+    r_size = tcg_const_i32(4);
+    r_sign = tcg_const_i32(0);
+    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, r_asi, r_size, r_sign);
+    tcg_temp_free(r_sign);
+    tcg_gen_helper_0_4(helper_st_asi, addr, dst, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
+    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
 }
 
-static inline void gen_ldda_asi(TCGv lo, TCGv hi, TCGv addr, int insn)
+static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
 {
-    TCGv r_asi;
+    TCGv r_asi, r_rd;
 
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, r_asi,
-                       tcg_const_i32(8), tcg_const_i32(0));
-    tcg_gen_andi_i64(lo, cpu_tmp64, 0xffffffffULL);
-    tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
-    tcg_gen_andi_i64(hi, cpu_tmp64, 0xffffffffULL);
+    r_rd = tcg_const_i32(rd);
+    tcg_gen_helper_0_3(helper_ldda_asi, addr, r_asi, r_rd);
+    tcg_temp_free(r_rd);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
 {
-    TCGv r_temp, r_asi;
+    TCGv r_temp, r_asi, r_size;
 
-    r_temp = tcg_temp_new(TCG_TYPE_I32);
+    r_temp = tcg_temp_new(TCG_TYPE_TL);
     gen_movl_reg_TN(rd + 1, r_temp);
     tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, hi,
                        r_temp);
+    tcg_temp_free(r_temp);
     r_asi = gen_get_asi(insn, addr);
-    tcg_gen_helper_0_4(helper_st_asi, addr, cpu_tmp64, r_asi,
-                       tcg_const_i32(8));
+    r_size = tcg_const_i32(8);
+    tcg_gen_helper_0_4(helper_st_asi, addr, cpu_tmp64, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
@@ -1689,10 +1755,12 @@ static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
 {
     TCGv r_val1, r_asi;
 
-    r_val1 = tcg_temp_new(TCG_TYPE_I32);
+    r_val1 = tcg_temp_new(TCG_TYPE_TL);
     gen_movl_reg_TN(rd, r_val1);
     r_asi = gen_get_asi(insn, addr);
     tcg_gen_helper_1_4(helper_cas_asi, dst, addr, r_val1, val2, r_asi);
+    tcg_temp_free(r_asi);
+    tcg_temp_free(r_val1);
 }
 
 static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
@@ -1703,6 +1771,7 @@ static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
     gen_movl_reg_TN(rd, cpu_tmp64);
     r_asi = gen_get_asi(insn, addr);
     tcg_gen_helper_1_4(helper_casx_asi, dst, addr, cpu_tmp64, val2, r_asi);
+    tcg_temp_free(r_asi);
 }
 
 #elif !defined(CONFIG_USER_ONLY)
@@ -1710,74 +1779,93 @@ static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
 static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
                               int sign)
 {
-    int asi;
+    TCGv r_asi, r_size, r_sign;
 
-    asi = GET_FIELD(insn, 19, 26);
-    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, tcg_const_i32(asi),
-                       tcg_const_i32(size), tcg_const_i32(sign));
+    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_size = tcg_const_i32(size);
+    r_sign = tcg_const_i32(sign);
+    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, r_asi, r_size, r_sign);
+    tcg_temp_free(r_sign);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
     tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
 }
 
 static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
 {
-    int asi;
+    TCGv r_asi, r_size;
 
     tcg_gen_extu_tl_i64(cpu_tmp64, src);
-    asi = GET_FIELD(insn, 19, 26);
-    tcg_gen_helper_0_4(helper_st_asi, addr, cpu_tmp64, tcg_const_i32(asi),
-                       tcg_const_i32(size));
+    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_size = tcg_const_i32(size);
+    tcg_gen_helper_0_4(helper_st_asi, addr, cpu_tmp64, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 
 static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
 {
-    int asi;
-    TCGv r_temp;
+    TCGv r_asi, r_size, r_sign;
 
-    r_temp = tcg_temp_new(TCG_TYPE_I32);
-    asi = GET_FIELD(insn, 19, 26);
-    tcg_gen_helper_1_4(helper_ld_asi, r_temp, addr, tcg_const_i32(asi),
-                       tcg_const_i32(4), tcg_const_i32(0));
-    tcg_gen_helper_0_4(helper_st_asi, addr, dst, tcg_const_i32(asi),
-                       tcg_const_i32(4));
-    tcg_gen_extu_i32_tl(dst, r_temp);
+    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_size = tcg_const_i32(4);
+    r_sign = tcg_const_i32(0);
+    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, r_asi, r_size, r_sign);
+    tcg_temp_free(r_sign);
+    tcg_gen_helper_0_4(helper_st_asi, addr, dst, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
+    tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
 }
 
-static inline void gen_ldda_asi(TCGv lo, TCGv hi, TCGv addr, int insn)
+static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
 {
-    int asi;
+    TCGv r_asi, r_size, r_sign;
 
-    asi = GET_FIELD(insn, 19, 26);
-    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, tcg_const_i32(asi),
-                       tcg_const_i32(8), tcg_const_i32(0));
-    tcg_gen_trunc_i64_tl(lo, cpu_tmp64);
+    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_size = tcg_const_i32(8);
+    r_sign = tcg_const_i32(0);
+    tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, r_asi, r_size, r_sign);
+    tcg_temp_free(r_sign);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
+    tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
+    gen_movl_TN_reg(rd + 1, cpu_tmp0);
     tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
     tcg_gen_trunc_i64_tl(hi, cpu_tmp64);
+    gen_movl_TN_reg(rd, hi);
 }
 
 static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
 {
-    int asi;
-    TCGv r_temp;
+    TCGv r_temp, r_asi, r_size;
 
-    r_temp = tcg_temp_new(TCG_TYPE_I32);
+    r_temp = tcg_temp_new(TCG_TYPE_TL);
     gen_movl_reg_TN(rd + 1, r_temp);
     tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, hi, r_temp);
-    asi = GET_FIELD(insn, 19, 26);
-    tcg_gen_helper_0_4(helper_st_asi, addr, cpu_tmp64, tcg_const_i32(asi),
-                       tcg_const_i32(8));
+    tcg_temp_free(r_temp);
+    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_size = tcg_const_i32(8);
+    tcg_gen_helper_0_4(helper_st_asi, addr, cpu_tmp64, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
 }
 #endif
 
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
 static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
 {
-    int asi;
+    TCGv r_val, r_asi, r_size;
 
     gen_ld_asi(dst, addr, insn, 1, 0);
 
-    asi = GET_FIELD(insn, 19, 26);
-    tcg_gen_helper_0_4(helper_st_asi, addr, tcg_const_i64(0xffULL),
-                       tcg_const_i32(asi), tcg_const_i32(1));
+    r_val = tcg_const_i64(0xffULL);
+    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_size = tcg_const_i32(1);
+    tcg_gen_helper_0_4(helper_st_asi, addr, r_val, r_asi, r_size);
+    tcg_temp_free(r_size);
+    tcg_temp_free(r_asi);
+    tcg_temp_free(r_val);
 }
 #endif
 
@@ -1788,11 +1876,9 @@ static inline TCGv get_src1(unsigned int insn, TCGv def)
 
     rs1 = GET_FIELD(insn, 13, 17);
     if (rs1 == 0)
-        //r_rs1 = tcg_const_tl(0);
-        tcg_gen_movi_tl(def, 0);
+        r_rs1 = tcg_const_tl(0); // XXX how to free?
     else if (rs1 < 8)
-        //r_rs1 = cpu_gregs[rs1];
-        tcg_gen_mov_tl(def, cpu_gregs[rs1]);
+        r_rs1 = cpu_gregs[rs1];
     else
         tcg_gen_ld_tl(def, cpu_regwptr, (rs1 - 8) * sizeof(target_ulong));
     return r_rs1;
@@ -1805,11 +1891,11 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
 
     if (IS_IMM) { /* immediate */
         rs2 = GET_FIELDs(insn, 19, 31);
-        r_rs2 = tcg_const_tl((int)rs2);
+        r_rs2 = tcg_const_tl((int)rs2); // XXX how to free?
     } else { /* register */
         rs2 = GET_FIELD(insn, 27, 31);
         if (rs2 == 0)
-            r_rs2 = tcg_const_tl(0);
+            r_rs2 = tcg_const_tl(0); // XXX how to free?
         else if (rs2 < 8)
             r_rs2 = cpu_gregs[rs2];
         else
@@ -1819,10 +1905,10 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
 }
 
 #define CHECK_IU_FEATURE(dc, FEATURE)                      \
-    if (!((dc)->features & CPU_FEATURE_ ## FEATURE))       \
+    if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
         goto illegal_insn;
 #define CHECK_FPU_FEATURE(dc, FEATURE)                     \
-    if (!((dc)->features & CPU_FEATURE_ ## FEATURE))       \
+    if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
         goto nfpu_insn;
 
 /* before an instruction, dc->pc must be static */
@@ -1830,18 +1916,15 @@ static void disas_sparc_insn(DisasContext * dc)
 {
     unsigned int insn, opc, rs1, rs2, rd;
 
+    if (unlikely(loglevel & CPU_LOG_TB_OP))
+        tcg_gen_debug_insn_start(dc->pc);
     insn = ldl_code(dc->pc);
     opc = GET_FIELD(insn, 0, 1);
 
     rd = GET_FIELD(insn, 2, 6);
 
-    cpu_dst = cpu_T[0];
-    cpu_src1 = cpu_T[0]; // const
-    cpu_src2 = cpu_T[1]; // const
-
-    // loads and stores
-    cpu_addr = cpu_T[0];
-    cpu_val = cpu_T[1];
+    cpu_src1 = tcg_temp_new(TCG_TYPE_TL); // const
+    cpu_src2 = tcg_temp_new(TCG_TYPE_TL); // const
 
     switch (opc) {
     case 0:                     /* branches/sethi */
@@ -1914,7 +1997,11 @@ static void disas_sparc_insn(DisasContext * dc)
             case 0x4:           /* SETHI */
                 if (rd) { // nop
                     uint32_t value = GET_FIELD(insn, 10, 31);
-                    gen_movl_TN_reg(rd, tcg_const_tl(value << 10));
+                    TCGv r_const;
+
+                    r_const = tcg_const_tl(value << 10);
+                    gen_movl_TN_reg(rd, r_const);
+                    tcg_temp_free(r_const);
                 }
                 break;
             case 0x0:           /* UNIMPL */
@@ -1927,8 +2014,11 @@ static void disas_sparc_insn(DisasContext * dc)
     case 1:
         /*CALL*/ {
             target_long target = GET_FIELDs(insn, 2, 31) << 2;
+            TCGv r_const;
 
-            gen_movl_TN_reg(15, tcg_const_tl(dc->pc));
+            r_const = tcg_const_tl(dc->pc);
+            gen_movl_TN_reg(15, r_const);
+            tcg_temp_free(r_const);
             target += dc->pc;
             gen_mov_pc_npc(dc, cpu_cond);
             dc->npc = target;
@@ -1974,6 +2064,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_cond(r_cond, 0, cond);
 #endif
                     tcg_gen_helper_0_2(helper_trapcc, cpu_dst, r_cond);
+                    tcg_temp_free(r_cond);
                 }
                 gen_op_next_insn();
                 tcg_gen_exit_tb(0);
@@ -1993,9 +2084,9 @@ static void disas_sparc_insn(DisasContext * dc)
                                        SPARCv8 manual, rdy on the
                                        microSPARC II */
 #endif
-                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                    tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                                   offsetof(CPUSPARCState, y));
-                    gen_movl_TN_reg(rd, cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_tmp0);
                     break;
 #ifdef TARGET_SPARC64
                 case 0x2: /* V9 rdccr */
@@ -2017,11 +2108,18 @@ static void disas_sparc_insn(DisasContext * dc)
                                        offsetof(CPUState, tick));
                         tcg_gen_helper_1_1(helper_tick_get_count, cpu_dst,
                                            r_tickptr);
+                        tcg_temp_free(r_tickptr);
                         gen_movl_TN_reg(rd, cpu_dst);
                     }
                     break;
                 case 0x5: /* V9 rdpc */
-                    gen_movl_TN_reg(rd, tcg_const_tl(dc->pc));
+                    {
+                        TCGv r_const;
+
+                        r_const = tcg_const_tl(dc->pc);
+                        gen_movl_TN_reg(rd, r_const);
+                        tcg_temp_free(r_const);
+                    }
                     break;
                 case 0x6: /* V9 rdfprs */
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
@@ -2034,14 +2132,14 @@ static void disas_sparc_insn(DisasContext * dc)
                 case 0x13: /* Graphics Status */
                     if (gen_trap_ifnofpu(dc, cpu_cond))
                         goto jmp_insn;
-                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                    tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                                   offsetof(CPUSPARCState, gsr));
-                    gen_movl_TN_reg(rd, cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_tmp0);
                     break;
                 case 0x17: /* Tick compare */
-                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                    tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                                   offsetof(CPUSPARCState, tick_cmpr));
-                    gen_movl_TN_reg(rd, cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_tmp0);
                     break;
                 case 0x18: /* System tick */
                     {
@@ -2052,13 +2150,14 @@ static void disas_sparc_insn(DisasContext * dc)
                                        offsetof(CPUState, stick));
                         tcg_gen_helper_1_1(helper_tick_get_count, cpu_dst,
                                            r_tickptr);
+                        tcg_temp_free(r_tickptr);
                         gen_movl_TN_reg(rd, cpu_dst);
                     }
                     break;
                 case 0x19: /* System tick compare */
-                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                    tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                                   offsetof(CPUSPARCState, stick_cmpr));
-                    gen_movl_TN_reg(rd, cpu_dst);
+                    gen_movl_TN_reg(rd, cpu_tmp0);
                     break;
                 case 0x10: /* Performance Control */
                 case 0x11: /* Performance Instrumentation Counter */
@@ -2077,6 +2176,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     goto priv_insn;
                 tcg_gen_helper_1_0(helper_rdpsr, cpu_dst);
 #else
+                CHECK_IU_FEATURE(dc, HYPV);
                 if (!hypervisor(dc))
                     goto priv_insn;
                 rs1 = GET_FIELD(insn, 13, 17);
@@ -2103,9 +2203,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
                     break;
                 case 31: // hstick_cmpr
-                    tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
-                    tcg_gen_st_i32(cpu_tmp32, cpu_env,
-                                   offsetof(CPUSPARCState, hstick_cmpr));
+                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                                  offsetof(CPUSPARCState, hstick_cmpr));
                     break;
                 default:
                     goto illegal_insn;
@@ -2126,8 +2225,9 @@ static void disas_sparc_insn(DisasContext * dc)
                         r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                         tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                        offsetof(CPUState, tsptr));
-                        tcg_gen_ld_tl(cpu_dst, r_tsptr,
+                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
                                       offsetof(trap_state, tpc));
+                        tcg_temp_free(r_tsptr);
                     }
                     break;
                 case 1: // tnpc
@@ -2137,8 +2237,9 @@ static void disas_sparc_insn(DisasContext * dc)
                         r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                         tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                        offsetof(CPUState, tsptr));
-                        tcg_gen_ld_tl(cpu_dst, r_tsptr,
+                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
                                       offsetof(trap_state, tnpc));
+                        tcg_temp_free(r_tsptr);
                     }
                     break;
                 case 2: // tstate
@@ -2148,8 +2249,9 @@ static void disas_sparc_insn(DisasContext * dc)
                         r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                         tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                        offsetof(CPUState, tsptr));
-                        tcg_gen_ld_tl(cpu_dst, r_tsptr,
+                        tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
                                       offsetof(trap_state, tstate));
+                        tcg_temp_free(r_tsptr);
                     }
                     break;
                 case 3: // tt
@@ -2159,8 +2261,9 @@ static void disas_sparc_insn(DisasContext * dc)
                         r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                         tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                        offsetof(CPUState, tsptr));
-                        tcg_gen_ld_i32(cpu_dst, r_tsptr,
+                        tcg_gen_ld_i32(cpu_tmp0, r_tsptr,
                                        offsetof(trap_state, tt));
+                        tcg_temp_free(r_tsptr);
                     }
                     break;
                 case 4: // tick
@@ -2170,72 +2273,75 @@ static void disas_sparc_insn(DisasContext * dc)
                         r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                        offsetof(CPUState, tick));
-                        tcg_gen_helper_1_1(helper_tick_get_count, cpu_dst,
+                        tcg_gen_helper_1_1(helper_tick_get_count, cpu_tmp0,
                                            r_tickptr);
-                        gen_movl_TN_reg(rd, cpu_dst);
+                        gen_movl_TN_reg(rd, cpu_tmp0);
+                        tcg_temp_free(r_tickptr);
                     }
                     break;
                 case 5: // tba
-                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                    tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                                   offsetof(CPUSPARCState, tbr));
                     break;
                 case 6: // pstate
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, pstate));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 7: // tl
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, tl));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 8: // pil
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, psrpil));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 9: // cwp
-                    tcg_gen_helper_1_0(helper_rdcwp, cpu_dst);
+                    tcg_gen_helper_1_0(helper_rdcwp, cpu_tmp0);
                     break;
                 case 10: // cansave
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, cansave));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 11: // canrestore
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, canrestore));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 12: // cleanwin
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, cleanwin));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 13: // otherwin
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, otherwin));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 14: // wstate
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, wstate));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 16: // UA2005 gl
+                    CHECK_IU_FEATURE(dc, GL);
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, gl));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 26: // UA2005 strand status
+                    CHECK_IU_FEATURE(dc, HYPV);
                     if (!hypervisor(dc))
                         goto priv_insn;
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUSPARCState, ssr));
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                    tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
                     break;
                 case 31: // ver
-                    tcg_gen_ld_tl(cpu_dst, cpu_env,
+                    tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                                   offsetof(CPUSPARCState, version));
                     break;
                 case 15: // fq
@@ -2245,18 +2351,19 @@ static void disas_sparc_insn(DisasContext * dc)
 #else
                 tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                offsetof(CPUSPARCState, wim));
-                tcg_gen_ext_i32_tl(cpu_dst, cpu_tmp32);
+                tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
 #endif
-                gen_movl_TN_reg(rd, cpu_dst);
+                gen_movl_TN_reg(rd, cpu_tmp0);
                 break;
             } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
 #ifdef TARGET_SPARC64
+                save_state(dc, cpu_cond);
                 tcg_gen_helper_0_0(helper_flushw);
 #else
                 if (!supervisor(dc))
                     goto priv_insn;
-                tcg_gen_ld_tl(cpu_dst, cpu_env, offsetof(CPUSPARCState, tbr));
-                gen_movl_TN_reg(rd, cpu_dst);
+                tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, tbr));
+                gen_movl_TN_reg(rd, cpu_tmp0);
 #endif
                 break;
 #endif
@@ -2410,6 +2517,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_op_store_QT0_fpr(QFPREG(rd));
                         break;
                     case 0x69:
+                        CHECK_FPU_FEATURE(dc, FSMULD);
                         gen_op_load_fpr_FT0(rs1);
                         gen_op_load_fpr_FT1(rs2);
                         gen_clear_float_exceptions();
@@ -2654,6 +2762,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         glue(glue(gen_op_store_, size_FDQ), T0_fpr)     \
                             (glue(size_FDQ, FPREG(rd)));                \
                         gen_set_label(l1);                              \
+                        tcg_temp_free(r_cond);                          \
                     }
                     case 0x001: /* V9 fmovscc %fcc0 */
                         FMOVCC(F, 0);
@@ -2712,6 +2821,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         glue(glue(gen_op_store_, size_FDQ), T0_fpr)     \
                             (glue(size_FDQ, FPREG(rd)));                \
                         gen_set_label(l1);                              \
+                        tcg_temp_free(r_cond);                          \
                     }
 
                     case 0x101: /* V9 fmovscc %icc */
@@ -2777,8 +2887,12 @@ static void disas_sparc_insn(DisasContext * dc)
                 if (rs1 == 0) {
                     // or %g0, x, y -> mov T0, x; mov y, T0
                     if (IS_IMM) {       /* immediate */
+                        TCGv r_const;
+
                         rs2 = GET_FIELDs(insn, 19, 31);
-                        gen_movl_TN_reg(rd, tcg_const_tl((int)rs2));
+                        r_const = tcg_const_tl((int)rs2);
+                        gen_movl_TN_reg(rd, r_const);
+                        tcg_temp_free(r_const);
                     } else {            /* register */
                         rs2 = GET_FIELD(insn, 27, 31);
                         gen_movl_reg_TN(rs2, cpu_dst);
@@ -2809,20 +2923,17 @@ static void disas_sparc_insn(DisasContext * dc)
                     if (insn & (1 << 12)) {
                         tcg_gen_shli_i64(cpu_dst, cpu_src1, rs2 & 0x3f);
                     } else {
-                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
-                        tcg_gen_shli_i64(cpu_dst, cpu_dst, rs2 & 0x1f);
+                        tcg_gen_shli_i64(cpu_dst, cpu_src1, rs2 & 0x1f);
                     }
                 } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_TN(rs2, cpu_src2);
                     if (insn & (1 << 12)) {
                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
-                        tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
                     } else {
                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
-                        tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
-                        tcg_gen_shl_i64(cpu_dst, cpu_dst, cpu_tmp0);
                     }
+                    tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
                 }
                 gen_movl_TN_reg(rd, cpu_dst);
             } else if (xop == 0x26) { /* srl, V9 srlx */
@@ -2868,6 +2979,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     } else {
                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
                         tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
+                        tcg_gen_ext_i32_i64(cpu_dst, cpu_dst);
                         tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
                     }
                 }
@@ -2960,8 +3072,10 @@ static void disas_sparc_insn(DisasContext * dc)
                         break;
 #ifdef TARGET_SPARC64
                     case 0xd: /* V9 udivx */
-                        gen_trap_ifdivzero_tl(cpu_src2);
-                        tcg_gen_divu_i64(cpu_dst, cpu_src1, cpu_src2);
+                        tcg_gen_mov_tl(cpu_cc_src, cpu_src1);
+                        tcg_gen_mov_tl(cpu_cc_src2, cpu_src2);
+                        gen_trap_ifdivzero_tl(cpu_cc_src2);
+                        tcg_gen_divu_i64(cpu_dst, cpu_cc_src, cpu_cc_src2);
                         break;
 #endif
                     case 0xe:
@@ -3042,8 +3156,8 @@ static void disas_sparc_insn(DisasContext * dc)
                         {
                             switch(rd) {
                             case 0: /* wry */
-                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
-                                tcg_gen_st_tl(cpu_dst, cpu_env,
+                                tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
+                                tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                               offsetof(CPUSPARCState, y));
                                 break;
 #ifndef TARGET_SPARC64
@@ -3086,8 +3200,8 @@ static void disas_sparc_insn(DisasContext * dc)
                             case 0x13: /* Graphics Status */
                                 if (gen_trap_ifnofpu(dc, cpu_cond))
                                     goto jmp_insn;
-                                tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
-                                tcg_gen_st_tl(cpu_dst, cpu_env,
+                                tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
+                                tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                               offsetof(CPUSPARCState, gsr));
                                 break;
                             case 0x17: /* Tick compare */
@@ -3098,16 +3212,17 @@ static void disas_sparc_insn(DisasContext * dc)
                                 {
                                     TCGv r_tickptr;
 
-                                    tcg_gen_xor_tl(cpu_dst, cpu_src1,
+                                    tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
                                                    cpu_src2);
-                                    tcg_gen_st_tl(cpu_dst, cpu_env,
+                                    tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                                   offsetof(CPUSPARCState,
                                                            tick_cmpr));
                                     r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                    offsetof(CPUState, tick));
                                     tcg_gen_helper_0_2(helper_tick_set_limit,
-                                                       r_tickptr, cpu_dst);
+                                                       r_tickptr, cpu_tmp0);
+                                    tcg_temp_free(r_tickptr);
                                 }
                                 break;
                             case 0x18: /* System tick */
@@ -3125,6 +3240,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                                    offsetof(CPUState, stick));
                                     tcg_gen_helper_0_2(helper_tick_set_count,
                                                        r_tickptr, cpu_dst);
+                                    tcg_temp_free(r_tickptr);
                                 }
                                 break;
                             case 0x19: /* System tick compare */
@@ -3135,16 +3251,17 @@ static void disas_sparc_insn(DisasContext * dc)
                                 {
                                     TCGv r_tickptr;
 
-                                    tcg_gen_xor_tl(cpu_dst, cpu_src1,
+                                    tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
                                                    cpu_src2);
-                                    tcg_gen_st_tl(cpu_dst, cpu_env,
+                                    tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                                   offsetof(CPUSPARCState,
                                                            stick_cmpr));
                                     r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                    offsetof(CPUState, stick));
                                     tcg_gen_helper_0_2(helper_tick_set_limit,
-                                                       r_tickptr, cpu_dst);
+                                                       r_tickptr, cpu_tmp0);
+                                    tcg_temp_free(r_tickptr);
                                 }
                                 break;
 
@@ -3196,7 +3313,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         {
                             if (!supervisor(dc))
                                 goto priv_insn;
-                            tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
+                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
 #ifdef TARGET_SPARC64
                             switch (rd) {
                             case 0: // tpc
@@ -3206,8 +3323,9 @@ static void disas_sparc_insn(DisasContext * dc)
                                     r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                    offsetof(CPUState, tsptr));
-                                    tcg_gen_st_tl(cpu_dst, r_tsptr,
+                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
                                                   offsetof(trap_state, tpc));
+                                    tcg_temp_free(r_tsptr);
                                 }
                                 break;
                             case 1: // tnpc
@@ -3217,8 +3335,9 @@ static void disas_sparc_insn(DisasContext * dc)
                                     r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                    offsetof(CPUState, tsptr));
-                                    tcg_gen_st_tl(cpu_dst, r_tsptr,
+                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
                                                   offsetof(trap_state, tnpc));
+                                    tcg_temp_free(r_tsptr);
                                 }
                                 break;
                             case 2: // tstate
@@ -3228,9 +3347,10 @@ static void disas_sparc_insn(DisasContext * dc)
                                     r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                    offsetof(CPUState, tsptr));
-                                    tcg_gen_st_tl(cpu_dst, r_tsptr,
+                                    tcg_gen_st_tl(cpu_tmp0, r_tsptr,
                                                   offsetof(trap_state,
                                                            tstate));
+                                    tcg_temp_free(r_tsptr);
                                 }
                                 break;
                             case 3: // tt
@@ -3240,8 +3360,9 @@ static void disas_sparc_insn(DisasContext * dc)
                                     r_tsptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tsptr, cpu_env,
                                                    offsetof(CPUState, tsptr));
-                                    tcg_gen_st_i32(cpu_dst, r_tsptr,
+                                    tcg_gen_st_i32(cpu_tmp0, r_tsptr,
                                                    offsetof(trap_state, tt));
+                                    tcg_temp_free(r_tsptr);
                                 }
                                 break;
                             case 4: // tick
@@ -3252,73 +3373,76 @@ static void disas_sparc_insn(DisasContext * dc)
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                    offsetof(CPUState, tick));
                                     tcg_gen_helper_0_2(helper_tick_set_count,
-                                                       r_tickptr, cpu_dst);
+                                                       r_tickptr, cpu_tmp0);
+                                    tcg_temp_free(r_tickptr);
                                 }
                                 break;
                             case 5: // tba
-                                tcg_gen_st_tl(cpu_dst, cpu_env,
+                                tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                               offsetof(CPUSPARCState, tbr));
                                 break;
                             case 6: // pstate
                                 save_state(dc, cpu_cond);
-                                tcg_gen_helper_0_1(helper_wrpstate, cpu_dst);
+                                tcg_gen_helper_0_1(helper_wrpstate, cpu_tmp0);
                                 gen_op_next_insn();
                                 tcg_gen_exit_tb(0);
                                 dc->is_br = 1;
                                 break;
                             case 7: // tl
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState, tl));
                                 break;
                             case 8: // pil
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState,
                                                         psrpil));
                                 break;
                             case 9: // cwp
-                                tcg_gen_helper_0_1(helper_wrcwp, cpu_dst);
+                                tcg_gen_helper_0_1(helper_wrcwp, cpu_tmp0);
                                 break;
                             case 10: // cansave
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState,
                                                         cansave));
                                 break;
                             case 11: // canrestore
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState,
                                                         canrestore));
                                 break;
                             case 12: // cleanwin
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState,
                                                         cleanwin));
                                 break;
                             case 13: // otherwin
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState,
                                                         otherwin));
                                 break;
                             case 14: // wstate
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState,
                                                         wstate));
                                 break;
                             case 16: // UA2005 gl
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                CHECK_IU_FEATURE(dc, GL);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState, gl));
                                 break;
                             case 26: // UA2005 strand status
+                                CHECK_IU_FEATURE(dc, HYPV);
                                 if (!hypervisor(dc))
                                     goto priv_insn;
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState, ssr));
                                 break;
@@ -3326,9 +3450,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                 goto illegal_insn;
                             }
 #else
-                            tcg_gen_andi_tl(cpu_dst, cpu_dst,
-                                            ((1 << NWINDOWS) - 1));
-                            tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                            tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                             tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                            offsetof(CPUSPARCState, wim));
 #endif
@@ -3339,13 +3461,14 @@ static void disas_sparc_insn(DisasContext * dc)
 #ifndef TARGET_SPARC64
                             if (!supervisor(dc))
                                 goto priv_insn;
-                            tcg_gen_xor_tl(cpu_dst, cpu_dst, cpu_src2);
-                            tcg_gen_st_tl(cpu_dst, cpu_env,
+                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
+                            tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                           offsetof(CPUSPARCState, tbr));
 #else
+                            CHECK_IU_FEATURE(dc, HYPV);
                             if (!hypervisor(dc))
                                 goto priv_insn;
-                            tcg_gen_xor_tl(cpu_dst, cpu_dst, cpu_src2);
+                            tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
                             switch (rd) {
                             case 0: // hpstate
                                 // XXX gen_op_wrhpstate();
@@ -3358,12 +3481,12 @@ static void disas_sparc_insn(DisasContext * dc)
                                 // XXX gen_op_wrhtstate();
                                 break;
                             case 3: // hintp
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState, hintp));
                                 break;
                             case 5: // htba
-                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+                                tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                 tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                                offsetof(CPUSPARCState, htba));
                                 break;
@@ -3371,14 +3494,15 @@ static void disas_sparc_insn(DisasContext * dc)
                                 {
                                     TCGv r_tickptr;
 
-                                    tcg_gen_st_tl(cpu_dst, cpu_env,
+                                    tcg_gen_st_tl(cpu_tmp0, cpu_env,
                                                   offsetof(CPUSPARCState,
                                                            hstick_cmpr));
                                     r_tickptr = tcg_temp_new(TCG_TYPE_PTR);
                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
                                                    offsetof(CPUState, hstick));
                                     tcg_gen_helper_0_2(helper_tick_set_limit,
-                                                       r_tickptr, cpu_dst);
+                                                       r_tickptr, cpu_tmp0);
+                                    tcg_temp_free(r_tickptr);
                                 }
                                 break;
                             case 6: // hver readonly
@@ -3413,14 +3537,19 @@ static void disas_sparc_insn(DisasContext * dc)
 
                             tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
                             if (IS_IMM) {       /* immediate */
+                                TCGv r_const;
+
                                 rs2 = GET_FIELD_SPs(insn, 0, 10);
-                                gen_movl_TN_reg(rd, tcg_const_tl((int)rs2));
+                                r_const = tcg_const_tl((int)rs2);
+                                gen_movl_TN_reg(rd, r_const);
+                                tcg_temp_free(r_const);
                             } else {
                                 rs2 = GET_FIELD_SP(insn, 0, 4);
                                 gen_movl_reg_TN(rs2, cpu_tmp0);
                                 gen_movl_TN_reg(rd, cpu_tmp0);
                             }
                             gen_set_label(l1);
+                            tcg_temp_free(r_cond);
                             break;
                         }
                     case 0x2d: /* V9 sdivx */
@@ -3446,8 +3575,12 @@ static void disas_sparc_insn(DisasContext * dc)
                             tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond],
                                               cpu_src1, 0, l1);
                             if (IS_IMM) {       /* immediate */
+                                TCGv r_const;
+
                                 rs2 = GET_FIELD_SPs(insn, 0, 9);
-                                gen_movl_TN_reg(rd, tcg_const_tl((int)rs2));
+                                r_const = tcg_const_tl((int)rs2);
+                                gen_movl_TN_reg(rd, r_const);
+                                tcg_temp_free(r_const);
                             } else {
                                 rs2 = GET_FIELD_SP(insn, 0, 4);
                                 gen_movl_reg_TN(rs2, cpu_tmp0);
@@ -3935,6 +4068,8 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #ifdef TARGET_SPARC64
             } else if (xop == 0x39) { /* V9 return */
+                TCGv r_const;
+
                 save_state(dc, cpu_cond);
                 cpu_src1 = get_src1(insn, cpu_src1);
                 if (IS_IMM) {   /* immediate */
@@ -3950,8 +4085,9 @@ static void disas_sparc_insn(DisasContext * dc)
                 }
                 tcg_gen_helper_0_0(helper_restore);
                 gen_mov_pc_npc(dc, cpu_cond);
-                tcg_gen_helper_0_2(helper_check_align, cpu_dst,
-                                   tcg_const_i32(3));
+                r_const = tcg_const_i32(3);
+                tcg_gen_helper_0_2(helper_check_align, cpu_dst, r_const);
+                tcg_temp_free(r_const);
                 tcg_gen_mov_tl(cpu_npc, cpu_dst);
                 dc->npc = DYNAMIC_PC;
                 goto jmp_insn;
@@ -3972,10 +4108,16 @@ static void disas_sparc_insn(DisasContext * dc)
                 switch (xop) {
                 case 0x38:      /* jmpl */
                     {
-                        gen_movl_TN_reg(rd, tcg_const_tl(dc->pc));
+                        TCGv r_const;
+
+                        r_const = tcg_const_tl(dc->pc);
+                        gen_movl_TN_reg(rd, r_const);
+                        tcg_temp_free(r_const);
                         gen_mov_pc_npc(dc, cpu_cond);
+                        r_const = tcg_const_i32(3);
                         tcg_gen_helper_0_2(helper_check_align, cpu_dst,
-                                           tcg_const_i32(3));
+                                           r_const);
+                        tcg_temp_free(r_const);
                         tcg_gen_mov_tl(cpu_npc, cpu_dst);
                         dc->npc = DYNAMIC_PC;
                     }
@@ -3983,11 +4125,15 @@ static void disas_sparc_insn(DisasContext * dc)
 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
                 case 0x39:      /* rett, V9 return */
                     {
+                        TCGv r_const;
+
                         if (!supervisor(dc))
                             goto priv_insn;
                         gen_mov_pc_npc(dc, cpu_cond);
+                        r_const = tcg_const_i32(3);
                         tcg_gen_helper_0_2(helper_check_align, cpu_dst,
-                                           tcg_const_i32(3));
+                                           r_const);
+                        tcg_temp_free(r_const);
                         tcg_gen_mov_tl(cpu_npc, cpu_dst);
                         dc->npc = DYNAMIC_PC;
                         tcg_gen_helper_0_0(helper_rett);
@@ -3995,7 +4141,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     goto jmp_insn;
 #endif
                 case 0x3b: /* flush */
-                    if (!((dc)->features & CPU_FEATURE_FLUSH))
+                    if (!((dc)->def->features & CPU_FEATURE_FLUSH))
                         goto unimp_flush;
                     tcg_gen_helper_0_1(helper_flush, cpu_dst);
                     break;
@@ -4045,12 +4191,11 @@ static void disas_sparc_insn(DisasContext * dc)
             unsigned int xop = GET_FIELD(insn, 7, 12);
 
             cpu_src1 = get_src1(insn, cpu_src1);
-            if (xop == 0x3c || xop == 0x3e)
-            {
+            if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
                 rs2 = GET_FIELD(insn, 27, 31);
                 gen_movl_reg_TN(rs2, cpu_src2);
-            }
-            else if (IS_IMM) {       /* immediate */
+                tcg_gen_mov_tl(cpu_addr, cpu_src1);
+            } else if (IS_IMM) {     /* immediate */
                 rs2 = GET_FIELDs(insn, 19, 31);
                 tcg_gen_addi_tl(cpu_addr, cpu_src1, (int)rs2);
             } else {            /* register */
@@ -4066,25 +4211,29 @@ static void disas_sparc_insn(DisasContext * dc)
                 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
                 switch (xop) {
                 case 0x0:       /* load unsigned word */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x1:       /* load unsigned byte */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x2:       /* load unsigned halfword */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x3:       /* load double word */
                     if (rd & 1)
                         goto illegal_insn;
                     else {
+                        TCGv r_const;
+
                         save_state(dc, cpu_cond);
+                        r_const = tcg_const_i32(7);
                         tcg_gen_helper_0_2(helper_check_align, cpu_addr,
-                                           tcg_const_i32(7)); // XXX remove
-                        ABI32_MASK(cpu_addr);
+                                           r_const); // XXX remove
+                        tcg_temp_free(r_const);
+                        gen_address_mask(dc, cpu_addr);
                         tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
                         tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
                         tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL);
@@ -4095,24 +4244,29 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     break;
                 case 0x9:       /* load signed byte */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0xa:       /* load signed halfword */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0xd:       /* ldstub -- XXX: should be atomically */
-                    ABI32_MASK(cpu_addr);
-                    tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
-                    tcg_gen_qemu_st8(tcg_const_tl(0xff), cpu_addr,
-                                     dc->mem_idx);
+                    {
+                        TCGv r_const;
+
+                        gen_address_mask(dc, cpu_addr);
+                        tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
+                        r_const = tcg_const_tl(0xff);
+                        tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
+                        tcg_temp_free(r_const);
+                    }
                     break;
                 case 0x0f:      /* swap register with memory. Also
                                    atomically */
                     CHECK_IU_FEATURE(dc, SWAP);
                     gen_movl_reg_TN(rd, cpu_val);
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
                     tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
                     tcg_gen_extu_i32_tl(cpu_val, cpu_tmp32);
@@ -4158,9 +4312,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     if (rd & 1)
                         goto illegal_insn;
                     save_state(dc, cpu_cond);
-                    gen_ldda_asi(cpu_tmp0, cpu_val, cpu_addr, insn);
-                    gen_movl_TN_reg(rd + 1, cpu_tmp0);
-                    break;
+                    gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
+                    goto skip_move;
                 case 0x19:      /* load signed byte alternate */
 #ifndef TARGET_SPARC64
                     if (IS_IMM)
@@ -4214,11 +4367,11 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #ifdef TARGET_SPARC64
                 case 0x08: /* V9 ldsw */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x0b: /* V9 ldx */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x18: /* V9 ldswa */
@@ -4251,7 +4404,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     goto illegal_insn;
                 }
                 gen_movl_TN_reg(rd, cpu_val);
-#ifdef TARGET_SPARC64
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
             skip_move: ;
 #endif
             } else if (xop >= 0x20 && xop < 0x24) {
@@ -4260,28 +4413,38 @@ static void disas_sparc_insn(DisasContext * dc)
                 save_state(dc, cpu_cond);
                 switch (xop) {
                 case 0x20:      /* load fpreg */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
                     tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUState, fpr[rd]));
                     break;
                 case 0x21:      /* load fsr */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
                     tcg_gen_st_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUState, ft0));
                     tcg_gen_helper_0_0(helper_ldfsr);
                     break;
                 case 0x22:      /* load quad fpreg */
-                    CHECK_FPU_FEATURE(dc, FLOAT128);
-                    tcg_gen_helper_0_2(helper_ldqf, cpu_addr,
-                                       tcg_const_i32(dc->mem_idx));
-                    gen_op_store_QT0_fpr(QFPREG(rd));
+                    {
+                        TCGv r_const;
+
+                        CHECK_FPU_FEATURE(dc, FLOAT128);
+                        r_const = tcg_const_i32(dc->mem_idx);
+                        tcg_gen_helper_0_2(helper_ldqf, cpu_addr, r_const);
+                        tcg_temp_free(r_const);
+                        gen_op_store_QT0_fpr(QFPREG(rd));
+                    }
                     break;
                 case 0x23:      /* load double fpreg */
-                    tcg_gen_helper_0_2(helper_lddf, cpu_addr,
-                                       tcg_const_i32(dc->mem_idx));
-                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    {
+                        TCGv r_const;
+
+                        r_const = tcg_const_i32(dc->mem_idx);
+                        tcg_gen_helper_0_2(helper_lddf, cpu_addr, r_const);
+                        tcg_temp_free(r_const);
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                    }
                     break;
                 default:
                     goto illegal_insn;
@@ -4291,31 +4454,34 @@ static void disas_sparc_insn(DisasContext * dc)
                 gen_movl_reg_TN(rd, cpu_val);
                 switch (xop) {
                 case 0x4: /* store word */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x5: /* store byte */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x6: /* store halfword */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x7: /* store double word */
                     if (rd & 1)
                         goto illegal_insn;
                     else {
-                        TCGv r_low;
+                        TCGv r_low, r_const;
 
                         save_state(dc, cpu_cond);
-                        ABI32_MASK(cpu_addr);
+                        gen_address_mask(dc, cpu_addr);
+                        r_const = tcg_const_i32(7);
                         tcg_gen_helper_0_2(helper_check_align, cpu_addr,
-                                           tcg_const_i32(7)); // XXX remove
-                        r_low = tcg_temp_new(TCG_TYPE_I32);
+                                           r_const); // XXX remove
+                        tcg_temp_free(r_const);
+                        r_low = tcg_temp_new(TCG_TYPE_TL);
                         gen_movl_reg_TN(rd + 1, r_low);
                         tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, cpu_val,
                                            r_low);
+                        tcg_temp_free(r_low);
                         tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
                     }
                     break;
@@ -4367,7 +4533,7 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #ifdef TARGET_SPARC64
                 case 0x0e: /* V9 stx */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x1e: /* V9 stxa */
@@ -4384,13 +4550,13 @@ static void disas_sparc_insn(DisasContext * dc)
                 save_state(dc, cpu_cond);
                 switch (xop) {
                 case 0x24: /* store fpreg */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUState, fpr[rd]));
                     tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
                     break;
                 case 0x25: /* stfsr, V9 stxfsr */
-                    ABI32_MASK(cpu_addr);
+                    gen_address_mask(dc, cpu_addr);
                     tcg_gen_helper_0_0(helper_stfsr);
                     tcg_gen_ld_i32(cpu_tmp32, cpu_env,
                                    offsetof(CPUState, ft0));
@@ -4399,10 +4565,15 @@ static void disas_sparc_insn(DisasContext * dc)
                 case 0x26:
 #ifdef TARGET_SPARC64
                     /* V9 stqf, store quad fpreg */
-                    CHECK_FPU_FEATURE(dc, FLOAT128);
-                    gen_op_load_fpr_QT0(QFPREG(rd));
-                    tcg_gen_helper_0_2(helper_stqf, cpu_addr,
-                                       tcg_const_i32(dc->mem_idx));
+                    {
+                        TCGv r_const;
+
+                        CHECK_FPU_FEATURE(dc, FLOAT128);
+                        gen_op_load_fpr_QT0(QFPREG(rd));
+                        r_const = tcg_const_i32(dc->mem_idx);
+                        tcg_gen_helper_0_2(helper_stqf, cpu_addr, r_const);
+                        tcg_temp_free(r_const);
+                    }
                     break;
 #else /* !TARGET_SPARC64 */
                     /* stdfq, store floating point queue */
@@ -4417,9 +4588,14 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #endif
                 case 0x27: /* store double fpreg */
-                    gen_op_load_fpr_DT0(DFPREG(rd));
-                    tcg_gen_helper_0_2(helper_stdf, cpu_addr,
-                                       tcg_const_i32(dc->mem_idx));
+                    {
+                        TCGv r_const;
+
+                        gen_op_load_fpr_DT0(DFPREG(rd));
+                        r_const = tcg_const_i32(dc->mem_idx);
+                        tcg_gen_helper_0_2(helper_stdf, cpu_addr, r_const);
+                        tcg_temp_free(r_const);
+                    }
                     break;
                 default:
                     goto illegal_insn;
@@ -4433,22 +4609,28 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_stf_asi(cpu_addr, insn, 4, rd);
                     break;
                 case 0x36: /* V9 stqfa */
-                    CHECK_FPU_FEATURE(dc, FLOAT128);
-                    tcg_gen_helper_0_2(helper_check_align, cpu_addr,
-                                       tcg_const_i32(7));
-                    gen_op_load_fpr_QT0(QFPREG(rd));
-                    gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                    {
+                        TCGv r_const;
+
+                        CHECK_FPU_FEATURE(dc, FLOAT128);
+                        r_const = tcg_const_i32(7);
+                        tcg_gen_helper_0_2(helper_check_align, cpu_addr,
+                                           r_const);
+                        tcg_temp_free(r_const);
+                        gen_op_load_fpr_QT0(QFPREG(rd));
+                        gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                    }
                     break;
                 case 0x37: /* V9 stdfa */
                     gen_op_load_fpr_DT0(DFPREG(rd));
                     gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
                     break;
                 case 0x3c: /* V9 casa */
-                    gen_cas_asi(cpu_val, cpu_addr, cpu_val, insn, rd);
+                    gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
                     gen_movl_TN_reg(rd, cpu_val);
                     break;
                 case 0x3e: /* V9 casxa */
-                    gen_casx_asi(cpu_val, cpu_addr, cpu_val, insn, rd);
+                    gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
                     gen_movl_TN_reg(rd, cpu_val);
                     break;
 #else
@@ -4482,20 +4664,38 @@ static void disas_sparc_insn(DisasContext * dc)
  jmp_insn:
     return;
  illegal_insn:
-    save_state(dc, cpu_cond);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_ILL_INSN));
-    dc->is_br = 1;
+    {
+        TCGv r_const;
+
+        save_state(dc, cpu_cond);
+        r_const = tcg_const_i32(TT_ILL_INSN);
+        tcg_gen_helper_0_1(raise_exception, r_const);
+        tcg_temp_free(r_const);
+        dc->is_br = 1;
+    }
     return;
  unimp_flush:
-    save_state(dc, cpu_cond);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_UNIMP_FLUSH));
-    dc->is_br = 1;
+    {
+        TCGv r_const;
+
+        save_state(dc, cpu_cond);
+        r_const = tcg_const_i32(TT_UNIMP_FLUSH);
+        tcg_gen_helper_0_1(raise_exception, r_const);
+        tcg_temp_free(r_const);
+        dc->is_br = 1;
+    }
     return;
 #if !defined(CONFIG_USER_ONLY)
  priv_insn:
-    save_state(dc, cpu_cond);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_PRIV_INSN));
-    dc->is_br = 1;
+    {
+        TCGv r_const;
+
+        save_state(dc, cpu_cond);
+        r_const = tcg_const_i32(TT_PRIV_INSN);
+        tcg_gen_helper_0_1(raise_exception, r_const);
+        tcg_temp_free(r_const);
+        dc->is_br = 1;
+    }
     return;
 #endif
  nfpu_insn:
@@ -4512,24 +4712,28 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #ifndef TARGET_SPARC64
  ncp_insn:
-    save_state(dc, cpu_cond);
-    tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_NCP_INSN));
-    dc->is_br = 1;
+    {
+        TCGv r_const;
+
+        save_state(dc, cpu_cond);
+        r_const = tcg_const_i32(TT_NCP_INSN);
+        tcg_gen_helper_0_1(raise_exception, r_const);
+        tcg_temp_free(r_const);
+        dc->is_br = 1;
+    }
     return;
 #endif
 }
 
-static void tcg_macro_func(TCGContext *s, int macro_id, const int *dead_args)
-{
-}
-
-static inline int gen_intermediate_code_internal(TranslationBlock * tb,
-                                                 int spc, CPUSPARCState *env)
+static inline void gen_intermediate_code_internal(TranslationBlock * tb,
+                                                  int spc, CPUSPARCState *env)
 {
     target_ulong pc_start, last_pc;
     uint16_t *gen_opc_end;
     DisasContext dc1, *dc = &dc1;
     int j, lj = -1;
+    int num_insns;
+    int max_insns;
 
     memset(dc, 0, sizeof(DisasContext));
     dc->tb = tb;
@@ -4538,20 +4742,31 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
     last_pc = dc->pc;
     dc->npc = (target_ulong) tb->cs_base;
     dc->mem_idx = cpu_mmu_index(env);
-    dc->features = env->features;
-    if ((dc->features & CPU_FEATURE_FLOAT)) {
+    dc->def = env->def;
+    if ((dc->def->features & CPU_FEATURE_FLOAT))
         dc->fpu_enabled = cpu_fpu_enabled(env);
-#if defined(CONFIG_USER_ONLY)
-        dc->features |= CPU_FEATURE_FLOAT128;
-#endif
-    } else
+    else
         dc->fpu_enabled = 0;
+#ifdef TARGET_SPARC64
+    dc->address_mask_32bit = env->pstate & PS_AM;
+#endif
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
 
     cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL);
     cpu_tmp32 = tcg_temp_new(TCG_TYPE_I32);
     cpu_tmp64 = tcg_temp_new(TCG_TYPE_I64);
 
+    cpu_dst = tcg_temp_local_new(TCG_TYPE_TL);
+
+    // loads and stores
+    cpu_val = tcg_temp_local_new(TCG_TYPE_TL);
+    cpu_addr = tcg_temp_local_new(TCG_TYPE_TL);
+
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0)
+        max_insns = CF_COUNT_MASK;
+    gen_icount_start();
     do {
         if (env->nb_breakpoints > 0) {
             for(j = 0; j < env->nb_breakpoints; j++) {
@@ -4576,10 +4791,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
                 gen_opc_pc[lj] = dc->pc;
                 gen_opc_npc[lj] = dc->npc;
                 gen_opc_instr_start[lj] = 1;
+                gen_opc_icount[lj] = num_insns;
             }
         }
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+            gen_io_start();
         last_pc = dc->pc;
         disas_sparc_insn(dc);
+        num_insns++;
 
         if (dc->is_br)
             break;
@@ -4598,9 +4817,18 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
             break;
         }
     } while ((gen_opc_ptr < gen_opc_end) &&
-             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
+             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
+             num_insns < max_insns);
 
  exit_gen_loop:
+    tcg_temp_free(cpu_addr);
+    tcg_temp_free(cpu_val);
+    tcg_temp_free(cpu_dst);
+    tcg_temp_free(cpu_tmp64);
+    tcg_temp_free(cpu_tmp32);
+    tcg_temp_free(cpu_tmp0);
+    if (tb->cflags & CF_LAST_IO)
+        gen_io_end();
     if (!dc->is_br) {
         if (dc->pc != DYNAMIC_PC &&
             (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
@@ -4613,6 +4841,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
             tcg_gen_exit_tb(0);
         }
     }
+    gen_icount_end(tb, num_insns);
     *gen_opc_ptr = INDEX_op_end;
     if (spc) {
         j = gen_opc_ptr - gen_opc_buf;
@@ -4628,6 +4857,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
         gen_opc_jump_pc[1] = dc->jump_pc[1];
     } else {
         tb->size = last_pc + 4 - pc_start;
+        tb->icount = num_insns;
     }
 #ifdef DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM) {
@@ -4637,17 +4867,16 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
         fprintf(logfile, "\n");
     }
 #endif
-    return 0;
 }
 
-int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
+void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
 {
-    return gen_intermediate_code_internal(tb, 0, env);
+    gen_intermediate_code_internal(tb, 0, env);
 }
 
-int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
+void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
 {
-    return gen_intermediate_code_internal(tb, 1, env);
+    gen_intermediate_code_internal(tb, 1, env);
 }
 
 void gen_intermediate_code_init(CPUSPARCState *env)
@@ -4669,7 +4898,6 @@ void gen_intermediate_code_init(CPUSPARCState *env)
     if (!inited) {
         inited = 1;
 
-        tcg_set_macro_func(&tcg_ctx, tcg_macro_func);
         cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
         cpu_regwptr = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
                                          offsetof(CPUState, regwptr),
@@ -4679,11 +4907,6 @@ void gen_intermediate_code_init(CPUSPARCState *env)
                                      TCG_AREG0, offsetof(CPUState, xcc),
                                      "xcc");
 #endif
-        /* XXX: T0 and T1 should be temporaries */
-        cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
-                                      TCG_AREG0, offsetof(CPUState, t0), "T0");
-        cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
-                                      TCG_AREG0, offsetof(CPUState, t1), "T1");
         cpu_cond = tcg_global_mem_new(TCG_TYPE_TL,
                                       TCG_AREG0, offsetof(CPUState, cond),
                                       "cond");