mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
Support for address masking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4882 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
a5a52cf246
commit
2cade6a3f6
|
@ -184,8 +184,9 @@ static inline TranslationBlock *tb_find_fast(void)
|
|||
pc = env->regs[15];
|
||||
#elif defined(TARGET_SPARC)
|
||||
#ifdef TARGET_SPARC64
|
||||
// Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
|
||||
flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
|
||||
// AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
|
||||
flags = ((env->pstate & PS_AM) << 2)
|
||||
| (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
|
||||
| (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
|
||||
#else
|
||||
// FPU enable . Supervisor
|
||||
|
|
|
@ -32,11 +32,21 @@ 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)
|
||||
#ifdef TARGET_SPARC64
|
||||
#ifndef TARGET_ABI32
|
||||
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
|
||||
#else
|
||||
#define ABI32_MASK(addr) do {} while (0)
|
||||
#define AM_CHECK(env1) (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline void address_mask(CPUState *env1, target_ulong *addr)
|
||||
{
|
||||
#ifdef TARGET_SPARC64
|
||||
if (AM_CHECK(env1))
|
||||
*addr &= 0xffffffffULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void raise_exception(int tt)
|
||||
{
|
||||
|
@ -1381,7 +1391,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
|
|||
raise_exception(TT_PRIV_ACT);
|
||||
|
||||
helper_check_align(addr, size - 1);
|
||||
ABI32_MASK(addr);
|
||||
address_mask(env, &addr);
|
||||
|
||||
switch (asi) {
|
||||
case 0x80: // Primary
|
||||
|
@ -1470,7 +1480,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
|
|||
raise_exception(TT_PRIV_ACT);
|
||||
|
||||
helper_check_align(addr, size - 1);
|
||||
ABI32_MASK(addr);
|
||||
address_mask(env, &addr);
|
||||
|
||||
/* Convert to little endian */
|
||||
switch (asi) {
|
||||
|
@ -2330,7 +2340,7 @@ void helper_stdf(target_ulong addr, int mem_idx)
|
|||
break;
|
||||
}
|
||||
#else
|
||||
ABI32_MASK(addr);
|
||||
address_mask(env, &addr);
|
||||
stfq_raw(addr, DT0);
|
||||
#endif
|
||||
}
|
||||
|
@ -2355,7 +2365,7 @@ void helper_lddf(target_ulong addr, int mem_idx)
|
|||
break;
|
||||
}
|
||||
#else
|
||||
ABI32_MASK(addr);
|
||||
address_mask(env, &addr);
|
||||
DT0 = ldfq_raw(addr);
|
||||
#endif
|
||||
}
|
||||
|
@ -2389,7 +2399,7 @@ void helper_ldqf(target_ulong addr, int mem_idx)
|
|||
break;
|
||||
}
|
||||
#else
|
||||
ABI32_MASK(addr);
|
||||
address_mask(env, &addr);
|
||||
u.ll.upper = ldq_raw(addr);
|
||||
u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
|
||||
QT0 = u.q;
|
||||
|
@ -2426,7 +2436,7 @@ void helper_stqf(target_ulong addr, int mem_idx)
|
|||
}
|
||||
#else
|
||||
u.q = QT0;
|
||||
ABI32_MASK(addr);
|
||||
address_mask(env, &addr);
|
||||
stq_raw(addr, u.ll.upper);
|
||||
stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,7 @@ typedef struct DisasContext {
|
|||
int is_br;
|
||||
int mem_idx;
|
||||
int fpu_enabled;
|
||||
int address_mask_32bit;
|
||||
struct TranslationBlock *tb;
|
||||
uint32_t features;
|
||||
} DisasContext;
|
||||
|
@ -201,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)
|
||||
{
|
||||
|
@ -4199,15 +4210,15 @@ 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 */
|
||||
|
@ -4221,7 +4232,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
tcg_gen_helper_0_2(helper_check_align, cpu_addr,
|
||||
r_const); // XXX remove
|
||||
tcg_temp_free(r_const);
|
||||
ABI32_MASK(cpu_addr);
|
||||
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);
|
||||
|
@ -4232,18 +4243,18 @@ 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 */
|
||||
{
|
||||
TCGv r_const;
|
||||
|
||||
ABI32_MASK(cpu_addr);
|
||||
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);
|
||||
|
@ -4254,7 +4265,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
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);
|
||||
|
@ -4356,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 */
|
||||
|
@ -4402,13 +4413,13 @@ 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));
|
||||
|
@ -4443,15 +4454,15 @@ 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 */
|
||||
|
@ -4461,7 +4472,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
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,
|
||||
r_const); // XXX remove
|
||||
|
@ -4522,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 */
|
||||
|
@ -4539,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));
|
||||
|
@ -4739,6 +4750,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
|
|||
#endif
|
||||
} 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);
|
||||
|
|
Loading…
Reference in a new issue