Remove someexplicit alignment checks (initial patch by Fabrice Bellard)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4431 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
blueswir1 2008-05-11 19:24:10 +00:00
parent 48318011da
commit c2bc0e3880
2 changed files with 112 additions and 98 deletions

View File

@ -33,6 +33,12 @@ do { printf("ASI: " fmt , ##args); } while (0)
#define DPRINTF_ASI(fmt, args...) do {} while (0) #define DPRINTF_ASI(fmt, args...) do {} while (0)
#endif #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) void raise_exception(int tt)
{ {
env->exception_index = 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) 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); raise_exception(TT_UNALIGNED);
}
} }
#define F_HELPER(name, p) void helper_f##name##p(void) #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; uint32_t last_addr = addr;
#endif #endif
helper_check_align(addr, size - 1);
switch (asi) { switch (asi) {
case 2: /* SuperSparc MXCC registers */ case 2: /* SuperSparc MXCC registers */
switch (addr) { 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) void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
{ {
helper_check_align(addr, size - 1);
switch(asi) { switch(asi) {
case 2: /* SuperSparc MXCC registers */ case 2: /* SuperSparc MXCC registers */
switch (addr) { switch (addr) {
@ -1335,6 +1348,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
if (asi < 0x80) if (asi < 0x80)
raise_exception(TT_PRIV_ACT); raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
ABI32_MASK(addr);
switch (asi) { switch (asi) {
case 0x80: // Primary case 0x80: // Primary
case 0x82: // Primary no-fault 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) if (asi < 0x80)
raise_exception(TT_PRIV_ACT); raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
ABI32_MASK(addr);
/* Convert to little endian */ /* Convert to little endian */
switch (asi) { switch (asi) {
case 0x88: // Primary LE 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))) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT); raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
switch (asi) { switch (asi) {
case 0x10: // As if user primary case 0x10: // As if user primary
case 0x18: // As if user primary LE 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))) || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT); raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
/* Convert to little endian */ /* Convert to little endian */
switch (asi) { switch (asi) {
case 0x0c: // Nucleus Little Endian (LE) 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; unsigned int i;
target_ulong val; target_ulong val;
helper_check_align(addr, 3);
switch (asi) { switch (asi) {
case 0xf0: // Block load primary case 0xf0: // Block load primary
case 0xf1: // Block load secondary 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); raise_exception(TT_ILL_INSN);
return; return;
} }
if (addr & 0x3f) { helper_check_align(addr, 0x3f);
raise_exception(TT_UNALIGNED);
return;
}
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
*(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0); *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
addr += 4; addr += 4;
@ -2052,6 +2071,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
unsigned int i; unsigned int i;
target_ulong val = 0; target_ulong val = 0;
helper_check_align(addr, 3);
switch (asi) { switch (asi) {
case 0xf0: // Block store primary case 0xf0: // Block store primary
case 0xf1: // Block store secondary 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); raise_exception(TT_ILL_INSN);
return; return;
} }
if (addr & 0x3f) { helper_check_align(addr, 0x3f);
raise_exception(TT_UNALIGNED);
return;
}
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
val = *(uint32_t *)&env->fpr[rd++]; val = *(uint32_t *)&env->fpr[rd++];
helper_st_asi(addr, val, asi & 0x8f, 4); 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); 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) void helper_stdf(target_ulong addr, int mem_idx)
{ {
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
switch (mem_idx) { switch (mem_idx) {
case 0: case 0:
stfq_user(ADDR(addr), DT0); stfq_user(addr, DT0);
break; break;
case 1: case 1:
stfq_kernel(ADDR(addr), DT0); stfq_kernel(addr, DT0);
break; break;
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 2: case 2:
stfq_hypv(ADDR(addr), DT0); stfq_hypv(addr, DT0);
break; break;
#endif #endif
default: default:
break; break;
} }
#else #else
stfq_raw(ADDR(addr), DT0); ABI32_MASK(addr);
stfq_raw(addr, DT0);
#endif #endif
} }
void helper_lddf(target_ulong addr, int mem_idx) void helper_lddf(target_ulong addr, int mem_idx)
{ {
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
switch (mem_idx) { switch (mem_idx) {
case 0: case 0:
DT0 = ldfq_user(ADDR(addr)); DT0 = ldfq_user(addr);
break; break;
case 1: case 1:
DT0 = ldfq_kernel(ADDR(addr)); DT0 = ldfq_kernel(addr);
break; break;
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 2: case 2:
DT0 = ldfq_hypv(ADDR(addr)); DT0 = ldfq_hypv(addr);
break; break;
#endif #endif
default: default:
break; break;
} }
#else #else
DT0 = ldfq_raw(ADDR(addr)); ABI32_MASK(addr);
DT0 = ldfq_raw(addr);
#endif #endif
} }
@ -2240,22 +2255,23 @@ void helper_ldqf(target_ulong addr, int mem_idx)
// XXX add 128 bit load // XXX add 128 bit load
CPU_QuadU u; CPU_QuadU u;
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
switch (mem_idx) { switch (mem_idx) {
case 0: case 0:
u.ll.upper = ldq_user(ADDR(addr)); u.ll.upper = ldq_user(addr);
u.ll.lower = ldq_user(ADDR(addr + 8)); u.ll.lower = ldq_user(addr + 8);
QT0 = u.q; QT0 = u.q;
break; break;
case 1: case 1:
u.ll.upper = ldq_kernel(ADDR(addr)); u.ll.upper = ldq_kernel(addr);
u.ll.lower = ldq_kernel(ADDR(addr + 8)); u.ll.lower = ldq_kernel(addr + 8);
QT0 = u.q; QT0 = u.q;
break; break;
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 2: case 2:
u.ll.upper = ldq_hypv(ADDR(addr)); u.ll.upper = ldq_hypv(addr);
u.ll.lower = ldq_hypv(ADDR(addr + 8)); u.ll.lower = ldq_hypv(addr + 8);
QT0 = u.q; QT0 = u.q;
break; break;
#endif #endif
@ -2263,8 +2279,9 @@ void helper_ldqf(target_ulong addr, int mem_idx)
break; break;
} }
#else #else
u.ll.upper = ldq_raw(ADDR(addr)); ABI32_MASK(addr);
u.ll.lower = ldq_raw(ADDR(addr + 8)); u.ll.upper = ldq_raw(addr);
u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
QT0 = u.q; QT0 = u.q;
#endif #endif
} }
@ -2274,23 +2291,24 @@ void helper_stqf(target_ulong addr, int mem_idx)
// XXX add 128 bit store // XXX add 128 bit store
CPU_QuadU u; CPU_QuadU u;
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
switch (mem_idx) { switch (mem_idx) {
case 0: case 0:
u.q = QT0; u.q = QT0;
stq_user(ADDR(addr), u.ll.upper); stq_user(addr, u.ll.upper);
stq_user(ADDR(addr + 8), u.ll.lower); stq_user(addr + 8, u.ll.lower);
break; break;
case 1: case 1:
u.q = QT0; u.q = QT0;
stq_kernel(ADDR(addr), u.ll.upper); stq_kernel(addr, u.ll.upper);
stq_kernel(ADDR(addr + 8), u.ll.lower); stq_kernel(addr + 8, u.ll.lower);
break; break;
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 2: case 2:
u.q = QT0; u.q = QT0;
stq_hypv(ADDR(addr), u.ll.upper); stq_hypv(addr, u.ll.upper);
stq_hypv(ADDR(addr + 8), u.ll.lower); stq_hypv(addr + 8, u.ll.lower);
break; break;
#endif #endif
default: default:
@ -2298,13 +2316,12 @@ void helper_stqf(target_ulong addr, int mem_idx)
} }
#else #else
u.q = QT0; u.q = QT0;
stq_raw(ADDR(addr), u.ll.upper); ABI32_MASK(addr);
stq_raw(ADDR(addr + 8), u.ll.lower); stq_raw(addr, u.ll.upper);
stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
#endif #endif
} }
#undef ADDR
void helper_ldfsr(void) void helper_ldfsr(void)
{ {
int rnd_mode; int rnd_mode;
@ -2833,12 +2850,32 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
#define SHIFT 3 #define SHIFT 3
#include "softmmu_template.h" #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, static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
void *retaddr) void *retaddr)
{ {
#ifdef DEBUG_UNALIGNED #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 #endif
cpu_restore_state2(retaddr);
raise_exception(TT_UNALIGNED); 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 */ /* XXX: fix it to restore all registers */
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
{ {
TranslationBlock *tb;
int ret; int ret;
unsigned long pc;
CPUState *saved_env; CPUState *saved_env;
/* XXX: hack to restore env in all cases, even if not called from /* 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); ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
if (ret) { if (ret) {
if (retaddr) { cpu_restore_state2(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_loop_exit(); cpu_loop_exit();
} }
env = saved_env; env = saved_env;

View File

@ -3945,7 +3945,6 @@ static void disas_sparc_insn(DisasContext * dc)
{ {
unsigned int xop = GET_FIELD(insn, 7, 12); unsigned int xop = GET_FIELD(insn, 7, 12);
save_state(dc, cpu_cond);
cpu_src1 = get_src1(insn, cpu_src1); cpu_src1 = get_src1(insn, cpu_src1);
if (xop == 0x3c || xop == 0x3e) if (xop == 0x3c || xop == 0x3e)
{ {
@ -3968,7 +3967,6 @@ static void disas_sparc_insn(DisasContext * dc)
(xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
switch (xop) { switch (xop) {
case 0x0: /* load unsigned word */ case 0x0: /* load unsigned word */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
break; break;
@ -3977,7 +3975,6 @@ static void disas_sparc_insn(DisasContext * dc)
tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
break; break;
case 0x2: /* load unsigned halfword */ case 0x2: /* load unsigned halfword */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
break; break;
@ -3985,7 +3982,9 @@ static void disas_sparc_insn(DisasContext * dc)
if (rd & 1) if (rd & 1)
goto illegal_insn; goto illegal_insn;
else { 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); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); 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); tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
break; break;
case 0xa: /* load signed halfword */ case 0xa: /* load signed halfword */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
break; break;
@ -4012,7 +4010,6 @@ static void disas_sparc_insn(DisasContext * dc)
break; break;
case 0x0f: /* swap register with memory. Also atomically */ case 0x0f: /* swap register with memory. Also atomically */
CHECK_IU_FEATURE(dc, SWAP); 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); gen_movl_reg_TN(rd, cpu_val);
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); 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)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #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); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
break; break;
case 0x11: /* load unsigned byte alternate */ case 0x11: /* load unsigned byte alternate */
@ -4037,6 +4034,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #endif
save_state(dc, cpu_cond);
gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
break; break;
case 0x12: /* load unsigned halfword alternate */ case 0x12: /* load unsigned halfword alternate */
@ -4046,7 +4044,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #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); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
break; break;
case 0x13: /* load double word alternate */ case 0x13: /* load double word alternate */
@ -4058,7 +4056,7 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
if (rd & 1) if (rd & 1)
goto illegal_insn; 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_ldda_asi(cpu_tmp0, cpu_val, cpu_addr, insn);
gen_movl_TN_reg(rd + 1, cpu_tmp0); gen_movl_TN_reg(rd + 1, cpu_tmp0);
break; break;
@ -4069,6 +4067,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #endif
save_state(dc, cpu_cond);
gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
break; break;
case 0x1a: /* load signed halfword alternate */ case 0x1a: /* load signed halfword alternate */
@ -4078,7 +4077,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #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); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
break; break;
case 0x1d: /* ldstuba -- XXX: should be atomically */ case 0x1d: /* ldstuba -- XXX: should be atomically */
@ -4088,6 +4087,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #endif
save_state(dc, cpu_cond);
gen_ldstub_asi(cpu_val, cpu_addr, insn); gen_ldstub_asi(cpu_val, cpu_addr, insn);
break; break;
case 0x1f: /* swap reg with alt. memory. Also atomically */ case 0x1f: /* swap reg with alt. memory. Also atomically */
@ -4098,7 +4098,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #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_movl_reg_TN(rd, cpu_val);
gen_swap_asi(cpu_val, cpu_addr, insn); gen_swap_asi(cpu_val, cpu_addr, insn);
break; break;
@ -4112,38 +4112,36 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 0x08: /* V9 ldsw */ case 0x08: /* V9 ldsw */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
break; break;
case 0x0b: /* V9 ldx */ case 0x0b: /* V9 ldx */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
break; break;
case 0x18: /* V9 ldswa */ 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); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
break; break;
case 0x1b: /* V9 ldxa */ 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); gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
break; break;
case 0x2d: /* V9 prefetch, no effect */ case 0x2d: /* V9 prefetch, no effect */
goto skip_move; goto skip_move;
case 0x30: /* V9 ldfa */ 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); gen_ldf_asi(cpu_addr, insn, 4, rd);
goto skip_move; goto skip_move;
case 0x33: /* V9 lddfa */ 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)); gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
goto skip_move; goto skip_move;
case 0x3d: /* V9 prefetcha, no effect */ case 0x3d: /* V9 prefetcha, no effect */
goto skip_move; goto skip_move;
case 0x32: /* V9 ldqfa */ case 0x32: /* V9 ldqfa */
CHECK_FPU_FEATURE(dc, FLOAT128); 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)); gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
goto skip_move; goto skip_move;
#endif #endif
@ -4157,15 +4155,16 @@ static void disas_sparc_insn(DisasContext * dc)
} else if (xop >= 0x20 && xop < 0x24) { } else if (xop >= 0x20 && xop < 0x24) {
if (gen_trap_ifnofpu(dc, cpu_cond)) if (gen_trap_ifnofpu(dc, cpu_cond))
goto jmp_insn; goto jmp_insn;
save_state(dc, cpu_cond);
switch (xop) { switch (xop) {
case 0x20: /* load fpreg */ 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_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
tcg_gen_st_i32(cpu_tmp32, cpu_env, tcg_gen_st_i32(cpu_tmp32, cpu_env,
offsetof(CPUState, fpr[rd])); offsetof(CPUState, fpr[rd]));
break; break;
case 0x21: /* load fsr */ 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_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
tcg_gen_st_i32(cpu_tmp32, cpu_env, tcg_gen_st_i32(cpu_tmp32, cpu_env,
offsetof(CPUState, ft0)); offsetof(CPUState, ft0));
@ -4173,14 +4172,10 @@ static void disas_sparc_insn(DisasContext * dc)
break; break;
case 0x22: /* load quad fpreg */ case 0x22: /* load quad fpreg */
CHECK_FPU_FEATURE(dc, FLOAT128); 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); tcg_gen_helper_0_2(helper_ldqf, cpu_addr, dc->mem_idx);
gen_op_store_QT0_fpr(QFPREG(rd)); gen_op_store_QT0_fpr(QFPREG(rd));
break; break;
case 0x23: /* load double fpreg */ 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_gen_helper_0_2(helper_lddf, cpu_addr,
tcg_const_i32(dc->mem_idx)); tcg_const_i32(dc->mem_idx));
gen_op_store_DT0_fpr(DFPREG(rd)); 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); gen_movl_reg_TN(rd, cpu_val);
switch (xop) { switch (xop) {
case 0x4: /* store word */ case 0x4: /* store word */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
break; break;
@ -4202,7 +4196,6 @@ static void disas_sparc_insn(DisasContext * dc)
tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
break; break;
case 0x6: /* store halfword */ case 0x6: /* store halfword */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
break; break;
@ -4212,7 +4205,10 @@ static void disas_sparc_insn(DisasContext * dc)
else { else {
TCGv r_low; 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); r_low = tcg_temp_new(TCG_TYPE_I32);
gen_movl_reg_TN(rd + 1, r_low); gen_movl_reg_TN(rd + 1, r_low);
tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, cpu_val, 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)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #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); gen_st_asi(cpu_val, cpu_addr, insn, 4);
break; break;
case 0x15: /* store byte alternate */ case 0x15: /* store byte alternate */
@ -4238,6 +4234,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #endif
save_state(dc, cpu_cond);
gen_st_asi(cpu_val, cpu_addr, insn, 1); gen_st_asi(cpu_val, cpu_addr, insn, 1);
break; break;
case 0x16: /* store halfword alternate */ case 0x16: /* store halfword alternate */
@ -4247,7 +4244,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif #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); gen_st_asi(cpu_val, cpu_addr, insn, 2);
break; break;
case 0x17: /* store double word alternate */ case 0x17: /* store double word alternate */
@ -4260,19 +4257,18 @@ static void disas_sparc_insn(DisasContext * dc)
if (rd & 1) if (rd & 1)
goto illegal_insn; goto illegal_insn;
else { 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); gen_stda_asi(cpu_val, cpu_addr, insn, rd);
} }
break; break;
#endif #endif
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 0x0e: /* V9 stx */ case 0x0e: /* V9 stx */
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7));
ABI32_MASK(cpu_addr); ABI32_MASK(cpu_addr);
tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
break; break;
case 0x1e: /* V9 stxa */ 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); gen_st_asi(cpu_val, cpu_addr, insn, 8);
break; break;
#endif #endif
@ -4282,17 +4278,16 @@ static void disas_sparc_insn(DisasContext * dc)
} else if (xop > 0x23 && xop < 0x28) { } else if (xop > 0x23 && xop < 0x28) {
if (gen_trap_ifnofpu(dc, cpu_cond)) if (gen_trap_ifnofpu(dc, cpu_cond))
goto jmp_insn; goto jmp_insn;
save_state(dc, cpu_cond);
switch (xop) { switch (xop) {
case 0x24: /* store fpreg */ 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, tcg_gen_ld_i32(cpu_tmp32, cpu_env,
offsetof(CPUState, fpr[rd])); offsetof(CPUState, fpr[rd]));
tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx); tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
break; break;
case 0x25: /* stfsr, V9 stxfsr */ case 0x25: /* stfsr, V9 stxfsr */
#ifdef CONFIG_USER_ONLY ABI32_MASK(cpu_addr);
tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3));
#endif
tcg_gen_helper_0_0(helper_stfsr); tcg_gen_helper_0_0(helper_stfsr);
tcg_gen_ld_i32(cpu_tmp32, cpu_env, tcg_gen_ld_i32(cpu_tmp32, cpu_env,
offsetof(CPUState, ft0)); offsetof(CPUState, ft0));
@ -4302,8 +4297,6 @@ static void disas_sparc_insn(DisasContext * dc)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
/* V9 stqf, store quad fpreg */ /* V9 stqf, store quad fpreg */
CHECK_FPU_FEATURE(dc, FLOAT128); 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_op_load_fpr_QT0(QFPREG(rd));
tcg_gen_helper_0_2(helper_stqf, cpu_addr, dc->mem_idx); tcg_gen_helper_0_2(helper_stqf, cpu_addr, dc->mem_idx);
break; break;
@ -4320,8 +4313,6 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
#endif #endif
case 0x27: /* store double fpreg */ 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)); gen_op_load_fpr_DT0(DFPREG(rd));
tcg_gen_helper_0_2(helper_stdf, cpu_addr, tcg_gen_helper_0_2(helper_stdf, cpu_addr,
tcg_const_i32(dc->mem_idx)); tcg_const_i32(dc->mem_idx));
@ -4330,10 +4321,10 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
} }
} else if (xop > 0x33 && xop < 0x3f) { } else if (xop > 0x33 && xop < 0x3f) {
save_state(dc, cpu_cond);
switch (xop) { switch (xop) {
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 0x34: /* V9 stfa */ 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_op_load_fpr_FT0(rd);
gen_stf_asi(cpu_addr, insn, 4, rd); gen_stf_asi(cpu_addr, insn, 4, rd);
break; break;
@ -4345,17 +4336,14 @@ static void disas_sparc_insn(DisasContext * dc)
gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd)); gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
break; break;
case 0x37: /* V9 stdfa */ 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_op_load_fpr_DT0(DFPREG(rd));
gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
break; break;
case 0x3c: /* V9 casa */ 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_cas_asi(cpu_val, cpu_addr, cpu_val, insn, rd);
gen_movl_TN_reg(rd, cpu_val); gen_movl_TN_reg(rd, cpu_val);
break; break;
case 0x3e: /* V9 casxa */ 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_casx_asi(cpu_val, cpu_addr, cpu_val, insn, rd);
gen_movl_TN_reg(rd, cpu_val); gen_movl_TN_reg(rd, cpu_val);
break; break;