diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 9f83e002d8..cb2b38d56f 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -33,6 +33,12 @@ do { printf("ASI: " fmt , ##args); } while (0) #define DPRINTF_ASI(fmt, args...) do {} while (0) #endif +#ifdef TARGET_ABI32 +#define ABI32_MASK(addr) do { (addr) &= 0xffffffffULL; } while (0) +#else +#define ABI32_MASK(addr) do {} while (0) +#endif + void raise_exception(int tt) { env->exception_index = tt; @@ -55,8 +61,13 @@ void helper_trapcc(target_ulong nb_trap, target_ulong do_trap) void helper_check_align(target_ulong addr, uint32_t align) { - if (addr & align) + if (addr & align) { +#ifdef DEBUG_UNALIGNED + printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx + "\n", addr, env->pc); +#endif raise_exception(TT_UNALIGNED); + } } #define F_HELPER(name, p) void helper_f##name##p(void) @@ -832,6 +843,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) uint32_t last_addr = addr; #endif + helper_check_align(addr, size - 1); switch (asi) { case 2: /* SuperSparc MXCC registers */ switch (addr) { @@ -1030,6 +1042,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) { + helper_check_align(addr, size - 1); switch(asi) { case 2: /* SuperSparc MXCC registers */ switch (addr) { @@ -1335,6 +1348,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) if (asi < 0x80) raise_exception(TT_PRIV_ACT); + helper_check_align(addr, size - 1); + ABI32_MASK(addr); + switch (asi) { case 0x80: // Primary case 0x82: // Primary no-fault @@ -1421,6 +1437,9 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) if (asi < 0x80) raise_exception(TT_PRIV_ACT); + helper_check_align(addr, size - 1); + ABI32_MASK(addr); + /* Convert to little endian */ switch (asi) { case 0x88: // Primary LE @@ -1491,6 +1510,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); + helper_check_align(addr, size - 1); switch (asi) { case 0x10: // As if user primary case 0x18: // As if user primary LE @@ -1714,6 +1734,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); + helper_check_align(addr, size - 1); /* Convert to little endian */ switch (asi) { case 0x0c: // Nucleus Little Endian (LE) @@ -2009,6 +2030,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) unsigned int i; target_ulong val; + helper_check_align(addr, 3); switch (asi) { case 0xf0: // Block load primary case 0xf1: // Block load secondary @@ -2018,10 +2040,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) raise_exception(TT_ILL_INSN); return; } - if (addr & 0x3f) { - raise_exception(TT_UNALIGNED); - return; - } + helper_check_align(addr, 0x3f); for (i = 0; i < 16; i++) { *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0); addr += 4; @@ -2052,6 +2071,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) unsigned int i; target_ulong val = 0; + helper_check_align(addr, 3); switch (asi) { case 0xf0: // Block store primary case 0xf1: // Block store secondary @@ -2061,10 +2081,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) raise_exception(TT_ILL_INSN); return; } - if (addr & 0x3f) { - raise_exception(TT_UNALIGNED); - return; - } + helper_check_align(addr, 0x3f); for (i = 0; i < 16; i++) { val = *(uint32_t *)&env->fpr[rd++]; helper_st_asi(addr, val, asi & 0x8f, 4); @@ -2183,55 +2200,53 @@ uint64_t helper_pack64(target_ulong high, target_ulong low) return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff); } -#ifdef TARGET_ABI32 -#define ADDR(x) ((x) & 0xffffffff) -#else -#define ADDR(x) (x) -#endif - void helper_stdf(target_ulong addr, int mem_idx) { + helper_check_align(addr, 7); #if !defined(CONFIG_USER_ONLY) switch (mem_idx) { case 0: - stfq_user(ADDR(addr), DT0); + stfq_user(addr, DT0); break; case 1: - stfq_kernel(ADDR(addr), DT0); + stfq_kernel(addr, DT0); break; #ifdef TARGET_SPARC64 case 2: - stfq_hypv(ADDR(addr), DT0); + stfq_hypv(addr, DT0); break; #endif default: break; } #else - stfq_raw(ADDR(addr), DT0); + ABI32_MASK(addr); + stfq_raw(addr, DT0); #endif } void helper_lddf(target_ulong addr, int mem_idx) { + helper_check_align(addr, 7); #if !defined(CONFIG_USER_ONLY) switch (mem_idx) { case 0: - DT0 = ldfq_user(ADDR(addr)); + DT0 = ldfq_user(addr); break; case 1: - DT0 = ldfq_kernel(ADDR(addr)); + DT0 = ldfq_kernel(addr); break; #ifdef TARGET_SPARC64 case 2: - DT0 = ldfq_hypv(ADDR(addr)); + DT0 = ldfq_hypv(addr); break; #endif default: break; } #else - DT0 = ldfq_raw(ADDR(addr)); + ABI32_MASK(addr); + DT0 = ldfq_raw(addr); #endif } @@ -2240,22 +2255,23 @@ void helper_ldqf(target_ulong addr, int mem_idx) // XXX add 128 bit load CPU_QuadU u; + helper_check_align(addr, 7); #if !defined(CONFIG_USER_ONLY) switch (mem_idx) { case 0: - u.ll.upper = ldq_user(ADDR(addr)); - u.ll.lower = ldq_user(ADDR(addr + 8)); + u.ll.upper = ldq_user(addr); + u.ll.lower = ldq_user(addr + 8); QT0 = u.q; break; case 1: - u.ll.upper = ldq_kernel(ADDR(addr)); - u.ll.lower = ldq_kernel(ADDR(addr + 8)); + u.ll.upper = ldq_kernel(addr); + u.ll.lower = ldq_kernel(addr + 8); QT0 = u.q; break; #ifdef TARGET_SPARC64 case 2: - u.ll.upper = ldq_hypv(ADDR(addr)); - u.ll.lower = ldq_hypv(ADDR(addr + 8)); + u.ll.upper = ldq_hypv(addr); + u.ll.lower = ldq_hypv(addr + 8); QT0 = u.q; break; #endif @@ -2263,8 +2279,9 @@ void helper_ldqf(target_ulong addr, int mem_idx) break; } #else - u.ll.upper = ldq_raw(ADDR(addr)); - u.ll.lower = ldq_raw(ADDR(addr + 8)); + ABI32_MASK(addr); + u.ll.upper = ldq_raw(addr); + u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL); QT0 = u.q; #endif } @@ -2274,23 +2291,24 @@ void helper_stqf(target_ulong addr, int mem_idx) // XXX add 128 bit store CPU_QuadU u; + helper_check_align(addr, 7); #if !defined(CONFIG_USER_ONLY) switch (mem_idx) { case 0: u.q = QT0; - stq_user(ADDR(addr), u.ll.upper); - stq_user(ADDR(addr + 8), u.ll.lower); + stq_user(addr, u.ll.upper); + stq_user(addr + 8, u.ll.lower); break; case 1: u.q = QT0; - stq_kernel(ADDR(addr), u.ll.upper); - stq_kernel(ADDR(addr + 8), u.ll.lower); + stq_kernel(addr, u.ll.upper); + stq_kernel(addr + 8, u.ll.lower); break; #ifdef TARGET_SPARC64 case 2: u.q = QT0; - stq_hypv(ADDR(addr), u.ll.upper); - stq_hypv(ADDR(addr + 8), u.ll.lower); + stq_hypv(addr, u.ll.upper); + stq_hypv(addr + 8, u.ll.lower); break; #endif default: @@ -2298,13 +2316,12 @@ void helper_stqf(target_ulong addr, int mem_idx) } #else u.q = QT0; - stq_raw(ADDR(addr), u.ll.upper); - stq_raw(ADDR(addr + 8), u.ll.lower); + ABI32_MASK(addr); + stq_raw(addr, u.ll.upper); + stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower); #endif } -#undef ADDR - void helper_ldfsr(void) { int rnd_mode; @@ -2833,12 +2850,32 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user, #define SHIFT 3 #include "softmmu_template.h" +/* XXX: make it generic ? */ +static void cpu_restore_state2(void *retaddr) +{ + TranslationBlock *tb; + unsigned long pc; + + if (retaddr) { + /* now we have a real cpu fault */ + pc = (unsigned long)retaddr; + tb = tb_find_pc(pc); + if (tb) { + /* the PC is inside the translated code. It means that we have + a virtual CPU fault */ + cpu_restore_state(tb, env, pc, (void *)(long)env->cond); + } + } +} + static void do_unaligned_access(target_ulong addr, int is_write, int is_user, void *retaddr) { #ifdef DEBUG_UNALIGNED - printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc); + printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx + "\n", addr, env->pc); #endif + cpu_restore_state2(retaddr); raise_exception(TT_UNALIGNED); } @@ -2848,9 +2885,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user, /* XXX: fix it to restore all registers */ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) { - TranslationBlock *tb; int ret; - unsigned long pc; CPUState *saved_env; /* XXX: hack to restore env in all cases, even if not called from @@ -2860,16 +2895,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { - if (retaddr) { - /* now we have a real cpu fault */ - pc = (unsigned long)retaddr; - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, pc, (void *)env->cond); - } - } + cpu_restore_state2(retaddr); cpu_loop_exit(); } env = saved_env; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index aff92bd62e..7b0363d6f0 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3945,7 +3945,6 @@ static void disas_sparc_insn(DisasContext * dc) { unsigned int xop = GET_FIELD(insn, 7, 12); - save_state(dc, cpu_cond); cpu_src1 = get_src1(insn, cpu_src1); if (xop == 0x3c || xop == 0x3e) { @@ -3968,7 +3967,6 @@ static void disas_sparc_insn(DisasContext * dc) (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { switch (xop) { case 0x0: /* load unsigned word */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); ABI32_MASK(cpu_addr); tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx); break; @@ -3977,7 +3975,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx); break; case 0x2: /* load unsigned halfword */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); ABI32_MASK(cpu_addr); tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx); break; @@ -3985,7 +3982,9 @@ static void disas_sparc_insn(DisasContext * dc) if (rd & 1) goto illegal_insn; else { - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + save_state(dc, cpu_cond); + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); // XXX remove ABI32_MASK(cpu_addr); tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); @@ -4001,7 +4000,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); break; case 0xa: /* load signed halfword */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); ABI32_MASK(cpu_addr); tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx); break; @@ -4012,7 +4010,6 @@ static void disas_sparc_insn(DisasContext * dc) break; case 0x0f: /* swap register with memory. Also atomically */ CHECK_IU_FEATURE(dc, SWAP); - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_movl_reg_TN(rd, cpu_val); ABI32_MASK(cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); @@ -4027,7 +4024,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0); break; case 0x11: /* load unsigned byte alternate */ @@ -4037,6 +4034,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0); break; case 0x12: /* load unsigned halfword alternate */ @@ -4046,7 +4044,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0); break; case 0x13: /* load double word alternate */ @@ -4058,7 +4056,7 @@ static void disas_sparc_insn(DisasContext * dc) #endif if (rd & 1) goto illegal_insn; - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + save_state(dc, cpu_cond); gen_ldda_asi(cpu_tmp0, cpu_val, cpu_addr, insn); gen_movl_TN_reg(rd + 1, cpu_tmp0); break; @@ -4069,6 +4067,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1); break; case 0x1a: /* load signed halfword alternate */ @@ -4078,7 +4077,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1); break; case 0x1d: /* ldstuba -- XXX: should be atomically */ @@ -4088,6 +4087,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif + save_state(dc, cpu_cond); gen_ldstub_asi(cpu_val, cpu_addr, insn); break; case 0x1f: /* swap reg with alt. memory. Also atomically */ @@ -4098,7 +4098,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_movl_reg_TN(rd, cpu_val); gen_swap_asi(cpu_val, cpu_addr, insn); break; @@ -4112,38 +4112,36 @@ static void disas_sparc_insn(DisasContext * dc) #endif #ifdef TARGET_SPARC64 case 0x08: /* V9 ldsw */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); ABI32_MASK(cpu_addr); tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx); break; case 0x0b: /* V9 ldx */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); ABI32_MASK(cpu_addr); tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x18: /* V9 ldswa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1); break; case 0x1b: /* V9 ldxa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + save_state(dc, cpu_cond); gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0); break; case 0x2d: /* V9 prefetch, no effect */ goto skip_move; case 0x30: /* V9 ldfa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_ldf_asi(cpu_addr, insn, 4, rd); goto skip_move; case 0x33: /* V9 lddfa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd)); goto skip_move; case 0x3d: /* V9 prefetcha, no effect */ goto skip_move; case 0x32: /* V9 ldqfa */ CHECK_FPU_FEATURE(dc, FLOAT128); - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd)); goto skip_move; #endif @@ -4157,15 +4155,16 @@ static void disas_sparc_insn(DisasContext * dc) } else if (xop >= 0x20 && xop < 0x24) { if (gen_trap_ifnofpu(dc, cpu_cond)) goto jmp_insn; + save_state(dc, cpu_cond); switch (xop) { case 0x20: /* load fpreg */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + ABI32_MASK(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 */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + ABI32_MASK(cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUState, ft0)); @@ -4173,14 +4172,10 @@ static void disas_sparc_insn(DisasContext * dc) break; case 0x22: /* load quad fpreg */ CHECK_FPU_FEATURE(dc, FLOAT128); - tcg_gen_helper_0_2(helper_check_align, cpu_addr, - tcg_const_i32(7)); tcg_gen_helper_0_2(helper_ldqf, cpu_addr, dc->mem_idx); gen_op_store_QT0_fpr(QFPREG(rd)); break; case 0x23: /* load double fpreg */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, - tcg_const_i32(7)); tcg_gen_helper_0_2(helper_lddf, cpu_addr, tcg_const_i32(dc->mem_idx)); gen_op_store_DT0_fpr(DFPREG(rd)); @@ -4193,7 +4188,6 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_reg_TN(rd, cpu_val); switch (xop) { case 0x4: /* store word */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); ABI32_MASK(cpu_addr); tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); break; @@ -4202,7 +4196,6 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx); break; case 0x6: /* store halfword */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); ABI32_MASK(cpu_addr); tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx); break; @@ -4212,7 +4205,10 @@ static void disas_sparc_insn(DisasContext * dc) else { TCGv r_low; - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + save_state(dc, cpu_cond); + ABI32_MASK(cpu_addr); + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); // XXX remove r_low = tcg_temp_new(TCG_TYPE_I32); gen_movl_reg_TN(rd + 1, r_low); tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, cpu_val, @@ -4228,7 +4224,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + save_state(dc, cpu_cond); gen_st_asi(cpu_val, cpu_addr, insn, 4); break; case 0x15: /* store byte alternate */ @@ -4238,6 +4234,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif + save_state(dc, cpu_cond); gen_st_asi(cpu_val, cpu_addr, insn, 1); break; case 0x16: /* store halfword alternate */ @@ -4247,7 +4244,7 @@ static void disas_sparc_insn(DisasContext * dc) if (!supervisor(dc)) goto priv_insn; #endif - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); + save_state(dc, cpu_cond); gen_st_asi(cpu_val, cpu_addr, insn, 2); break; case 0x17: /* store double word alternate */ @@ -4260,19 +4257,18 @@ static void disas_sparc_insn(DisasContext * dc) if (rd & 1) goto illegal_insn; else { - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + save_state(dc, cpu_cond); gen_stda_asi(cpu_val, cpu_addr, insn, rd); } break; #endif #ifdef TARGET_SPARC64 case 0x0e: /* V9 stx */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); ABI32_MASK(cpu_addr); tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x1e: /* V9 stxa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + save_state(dc, cpu_cond); gen_st_asi(cpu_val, cpu_addr, insn, 8); break; #endif @@ -4282,17 +4278,16 @@ static void disas_sparc_insn(DisasContext * dc) } else if (xop > 0x23 && xop < 0x28) { if (gen_trap_ifnofpu(dc, cpu_cond)) goto jmp_insn; + save_state(dc, cpu_cond); switch (xop) { case 0x24: /* store fpreg */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); + ABI32_MASK(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 */ -#ifdef CONFIG_USER_ONLY - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); -#endif + ABI32_MASK(cpu_addr); tcg_gen_helper_0_0(helper_stfsr); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUState, ft0)); @@ -4302,8 +4297,6 @@ static void disas_sparc_insn(DisasContext * dc) #ifdef TARGET_SPARC64 /* V9 stqf, store quad fpreg */ 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)); tcg_gen_helper_0_2(helper_stqf, cpu_addr, dc->mem_idx); break; @@ -4320,8 +4313,6 @@ static void disas_sparc_insn(DisasContext * dc) #endif #endif case 0x27: /* store double fpreg */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, - tcg_const_i32(7)); gen_op_load_fpr_DT0(DFPREG(rd)); tcg_gen_helper_0_2(helper_stdf, cpu_addr, tcg_const_i32(dc->mem_idx)); @@ -4330,10 +4321,10 @@ static void disas_sparc_insn(DisasContext * dc) goto illegal_insn; } } else if (xop > 0x33 && xop < 0x3f) { + save_state(dc, cpu_cond); switch (xop) { #ifdef TARGET_SPARC64 case 0x34: /* V9 stfa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_op_load_fpr_FT0(rd); gen_stf_asi(cpu_addr, insn, 4, rd); break; @@ -4345,17 +4336,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd)); break; case 0x37: /* V9 stdfa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_op_load_fpr_DT0(DFPREG(rd)); gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); break; case 0x3c: /* V9 casa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); gen_cas_asi(cpu_val, cpu_addr, cpu_val, insn, rd); gen_movl_TN_reg(rd, cpu_val); break; case 0x3e: /* V9 casxa */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); gen_casx_asi(cpu_val, cpu_addr, cpu_val, insn, rd); gen_movl_TN_reg(rd, cpu_val); break;