mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-tcg-20231023' of https://gitlab.com/rth7680/qemu into staging
tcg: Drop unused tcg_temp_free define
tcg: Introduce tcg_use_softmmu
tcg: Optimize past conditional branches
tcg: Use constant zero when expanding with divu2
tcg: Add negsetcondi
tcg: Define MO_TL
tcg: Export tcg_gen_ext_{i32,i64,tl}
target/*: Use tcg_gen_ext_*
tcg/ppc: Enable direct branching tcg_out_goto_tb with TCG_REG_TB
tcg/ppc: Use ADDPCIS for power9
tcg/ppc: Use prefixed instructions for power10
tcg/ppc: Disable TCG_REG_TB for Power9/Power10
tcg/ppc: Enable direct branching tcg_out_goto_tb with TCG_REG_TB
tcg/ppc: Use ADDPCIS for power9
tcg/ppc: Use prefixed instructions for power10
tcg/ppc: Disable TCG_REG_TB for Power9/Power10
# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmU2t18dHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV9uXQgAhT1mDy5sg7mfSWuc
# X7i54C3n6Ykyra0HDG47dt4G0gkACEs7tDkllHIxhqTPKCrzpevyZEoyigr2MEOa
# 3GCwxvJORb27Ql2aiM1K8cdlEbzcrx+RZbl4lwqZpZbmMUbz/ZQI4xPEAf2yKdfB
# jTzi+Iu6ziPVqVQrg6fTm1I7YgQI85qcfKxi5lBaXgSfxPXGSlLeDw9Y8QjLHXRx
# nSiGpWiUd5TkqZgLIctShDbK4NEHcvjXUTW4rMWU9l5Cjdf9ZIhxcCxgKTXtOxBi
# 9tUdGOiup2HudOFf+DpQorzWpwRwy3NGpUF7n+WmevQZ1Qh8uNKsveFB0uuqObLg
# zlTI2Q==
# =lgiT
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 23 Oct 2023 11:11:43 PDT
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F
* tag 'pull-tcg-20231023' of https://gitlab.com/rth7680/qemu: (38 commits)
target/xtensa: Use tcg_gen_sextract_i32
target/tricore: Use tcg_gen_*extract_tl
target/rx: Use tcg_gen_ext_i32
target/m68k: Use tcg_gen_ext_i32
target/i386: Use tcg_gen_ext_tl
target/arm: Use tcg_gen_ext_i64
tcg: Define MO_TL
tcg: Export tcg_gen_ext_{i32,i64,tl}
tcg: add negsetcondi
target/i386: Use i128 for 128 and 256-bit loads and stores
tcg: Add tcg_gen_{ld,st}_i128
tcg: Optimize past conditional branches
tcg: Use constant zero when expanding with divu2
tcg: drop unused tcg_temp_free define
tcg/s390x: Use tcg_use_softmmu
tcg/riscv: Use tcg_use_softmmu
tcg/riscv: Do not reserve TCG_GUEST_BASE_REG for guest_base zero
tcg/ppc: Use tcg_use_softmmu
tcg/mips: Use tcg_use_softmmu
tcg/loongarch64: Use tcg_use_softmmu
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -29,12 +29,14 @@ typedef uint32_t target_ulong;
|
||||
#define TARGET_FMT_lx "%08x"
|
||||
#define TARGET_FMT_ld "%d"
|
||||
#define TARGET_FMT_lu "%u"
|
||||
#define MO_TL MO_32
|
||||
#elif TARGET_LONG_SIZE == 8
|
||||
typedef int64_t target_long;
|
||||
typedef uint64_t target_ulong;
|
||||
#define TARGET_FMT_lx "%016" PRIx64
|
||||
#define TARGET_FMT_ld "%" PRId64
|
||||
#define TARGET_FMT_lu "%" PRIu64
|
||||
#define MO_TL MO_64
|
||||
#else
|
||||
#error TARGET_LONG_SIZE undefined
|
||||
#endif
|
||||
|
||||
@@ -346,6 +346,8 @@ void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
|
||||
TCGv_i32 arg1, int32_t arg2);
|
||||
void tcg_gen_negsetcond_i32(TCGCond cond, TCGv_i32 ret,
|
||||
TCGv_i32 arg1, TCGv_i32 arg2);
|
||||
void tcg_gen_negsetcondi_i32(TCGCond cond, TCGv_i32 ret,
|
||||
TCGv_i32 arg1, int32_t arg2);
|
||||
void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
|
||||
TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2);
|
||||
void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
|
||||
@@ -359,6 +361,7 @@ void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg);
|
||||
void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg);
|
||||
void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg);
|
||||
void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg);
|
||||
void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc);
|
||||
void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags);
|
||||
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg);
|
||||
void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg);
|
||||
@@ -544,6 +547,8 @@ void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
|
||||
TCGv_i64 arg1, int64_t arg2);
|
||||
void tcg_gen_negsetcond_i64(TCGCond cond, TCGv_i64 ret,
|
||||
TCGv_i64 arg1, TCGv_i64 arg2);
|
||||
void tcg_gen_negsetcondi_i64(TCGCond cond, TCGv_i64 ret,
|
||||
TCGv_i64 arg1, int64_t arg2);
|
||||
void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
|
||||
TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2);
|
||||
void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
|
||||
@@ -560,6 +565,7 @@ void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg);
|
||||
void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg);
|
||||
void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg);
|
||||
void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg);
|
||||
void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc);
|
||||
void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags);
|
||||
void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags);
|
||||
void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg);
|
||||
@@ -747,6 +753,9 @@ void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src);
|
||||
void tcg_gen_extr_i128_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i128 arg);
|
||||
void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi);
|
||||
|
||||
void tcg_gen_ld_i128(TCGv_i128 ret, TCGv_ptr base, tcg_target_long offset);
|
||||
void tcg_gen_st_i128(TCGv_i128 val, TCGv_ptr base, tcg_target_long offset);
|
||||
|
||||
static inline void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi)
|
||||
{
|
||||
tcg_gen_deposit_i64(ret, lo, hi, 32, 32);
|
||||
|
||||
@@ -52,7 +52,6 @@ static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1,
|
||||
typedef TCGv_i32 TCGv;
|
||||
#define tcg_temp_new() tcg_temp_new_i32()
|
||||
#define tcg_global_mem_new tcg_global_mem_new_i32
|
||||
#define tcg_temp_free tcg_temp_free_i32
|
||||
#define tcgv_tl_temp tcgv_i32_temp
|
||||
#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i32
|
||||
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32
|
||||
@@ -60,7 +59,6 @@ typedef TCGv_i32 TCGv;
|
||||
typedef TCGv_i64 TCGv;
|
||||
#define tcg_temp_new() tcg_temp_new_i64()
|
||||
#define tcg_global_mem_new tcg_global_mem_new_i64
|
||||
#define tcg_temp_free tcg_temp_free_i64
|
||||
#define tcgv_tl_temp tcgv_i64_temp
|
||||
#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i64
|
||||
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i64
|
||||
@@ -201,6 +199,7 @@ DEF_ATOMIC2(tcg_gen_atomic_umax_fetch, i64)
|
||||
#define tcg_gen_setcond_tl tcg_gen_setcond_i64
|
||||
#define tcg_gen_setcondi_tl tcg_gen_setcondi_i64
|
||||
#define tcg_gen_negsetcond_tl tcg_gen_negsetcond_i64
|
||||
#define tcg_gen_negsetcondi_tl tcg_gen_negsetcondi_i64
|
||||
#define tcg_gen_mul_tl tcg_gen_mul_i64
|
||||
#define tcg_gen_muli_tl tcg_gen_muli_i64
|
||||
#define tcg_gen_div_tl tcg_gen_div_i64
|
||||
@@ -220,6 +219,7 @@ DEF_ATOMIC2(tcg_gen_atomic_umax_fetch, i64)
|
||||
#define tcg_gen_ext16s_tl tcg_gen_ext16s_i64
|
||||
#define tcg_gen_ext32u_tl tcg_gen_ext32u_i64
|
||||
#define tcg_gen_ext32s_tl tcg_gen_ext32s_i64
|
||||
#define tcg_gen_ext_tl tcg_gen_ext_i64
|
||||
#define tcg_gen_bswap16_tl tcg_gen_bswap16_i64
|
||||
#define tcg_gen_bswap32_tl tcg_gen_bswap32_i64
|
||||
#define tcg_gen_bswap64_tl tcg_gen_bswap64_i64
|
||||
@@ -319,6 +319,7 @@ DEF_ATOMIC2(tcg_gen_atomic_umax_fetch, i64)
|
||||
#define tcg_gen_setcond_tl tcg_gen_setcond_i32
|
||||
#define tcg_gen_setcondi_tl tcg_gen_setcondi_i32
|
||||
#define tcg_gen_negsetcond_tl tcg_gen_negsetcond_i32
|
||||
#define tcg_gen_negsetcondi_tl tcg_gen_negsetcondi_i32
|
||||
#define tcg_gen_mul_tl tcg_gen_mul_i32
|
||||
#define tcg_gen_muli_tl tcg_gen_muli_i32
|
||||
#define tcg_gen_div_tl tcg_gen_div_i32
|
||||
@@ -338,6 +339,7 @@ DEF_ATOMIC2(tcg_gen_atomic_umax_fetch, i64)
|
||||
#define tcg_gen_ext16s_tl tcg_gen_ext16s_i32
|
||||
#define tcg_gen_ext32u_tl tcg_gen_mov_i32
|
||||
#define tcg_gen_ext32s_tl tcg_gen_mov_i32
|
||||
#define tcg_gen_ext_tl tcg_gen_ext_i32
|
||||
#define tcg_gen_bswap16_tl tcg_gen_bswap16_i32
|
||||
#define tcg_gen_bswap32_tl(D, S, F) tcg_gen_bswap32_i32(D, S)
|
||||
#define tcg_gen_bswap_tl tcg_gen_bswap32_i32
|
||||
|
||||
+6
-2
@@ -488,11 +488,9 @@ struct TCGContext {
|
||||
int nb_ops;
|
||||
TCGType addr_type; /* TCG_TYPE_I32 or TCG_TYPE_I64 */
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
int page_mask;
|
||||
uint8_t page_bits;
|
||||
uint8_t tlb_dyn_max_bits;
|
||||
#endif
|
||||
uint8_t insn_start_words;
|
||||
TCGBar guest_mo;
|
||||
|
||||
@@ -573,6 +571,12 @@ static inline bool temp_readonly(TCGTemp *ts)
|
||||
return ts->kind >= TEMP_FIXED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
extern bool tcg_use_softmmu;
|
||||
#else
|
||||
#define tcg_use_softmmu true
|
||||
#endif
|
||||
|
||||
extern __thread TCGContext *tcg_ctx;
|
||||
extern const void *tcg_code_gen_epilogue;
|
||||
extern uintptr_t tcg_splitwx_diff;
|
||||
|
||||
@@ -1324,41 +1324,8 @@ static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
|
||||
int extsize = extract32(option, 0, 2);
|
||||
bool is_signed = extract32(option, 2, 1);
|
||||
|
||||
if (is_signed) {
|
||||
switch (extsize) {
|
||||
case 0:
|
||||
tcg_gen_ext8s_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
case 1:
|
||||
tcg_gen_ext16s_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
case 2:
|
||||
tcg_gen_ext32s_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
case 3:
|
||||
tcg_gen_mov_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (extsize) {
|
||||
case 0:
|
||||
tcg_gen_ext8u_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
case 1:
|
||||
tcg_gen_ext16u_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
case 2:
|
||||
tcg_gen_ext32u_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
case 3:
|
||||
tcg_gen_mov_i64(tcg_out, tcg_in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift) {
|
||||
tcg_gen_shli_i64(tcg_out, tcg_out, shift);
|
||||
}
|
||||
tcg_gen_ext_i64(tcg_out, tcg_in, extsize | (is_signed ? MO_SIGN : 0));
|
||||
tcg_gen_shli_i64(tcg_out, tcg_out, shift);
|
||||
}
|
||||
|
||||
static inline void gen_check_sp_alignment(DisasContext *s)
|
||||
|
||||
+32
-59
@@ -701,33 +701,11 @@ static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot)
|
||||
|
||||
static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
|
||||
{
|
||||
switch (size) {
|
||||
case MO_8:
|
||||
if (sign) {
|
||||
tcg_gen_ext8s_tl(dst, src);
|
||||
} else {
|
||||
tcg_gen_ext8u_tl(dst, src);
|
||||
}
|
||||
return dst;
|
||||
case MO_16:
|
||||
if (sign) {
|
||||
tcg_gen_ext16s_tl(dst, src);
|
||||
} else {
|
||||
tcg_gen_ext16u_tl(dst, src);
|
||||
}
|
||||
return dst;
|
||||
#ifdef TARGET_X86_64
|
||||
case MO_32:
|
||||
if (sign) {
|
||||
tcg_gen_ext32s_tl(dst, src);
|
||||
} else {
|
||||
tcg_gen_ext32u_tl(dst, src);
|
||||
}
|
||||
return dst;
|
||||
#endif
|
||||
default:
|
||||
if (size == MO_TL) {
|
||||
return src;
|
||||
}
|
||||
tcg_gen_ext_tl(dst, src, size | (sign ? MO_SIGN : 0));
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void gen_extu(MemOp ot, TCGv reg)
|
||||
@@ -2918,59 +2896,54 @@ static inline void gen_stq_env_A0(DisasContext *s, int offset)
|
||||
|
||||
static inline void gen_ldo_env_A0(DisasContext *s, int offset, bool align)
|
||||
{
|
||||
MemOp atom = (s->cpuid_ext_features & CPUID_EXT_AVX
|
||||
? MO_ATOM_IFALIGN : MO_ATOM_IFALIGN_PAIR);
|
||||
MemOp mop = MO_128 | MO_LE | atom | (align ? MO_ALIGN_16 : 0);
|
||||
int mem_index = s->mem_index;
|
||||
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index,
|
||||
MO_LEUQ | (align ? MO_ALIGN_16 : 0));
|
||||
tcg_gen_st_i64(s->tmp1_i64, tcg_env, offset + offsetof(XMMReg, XMM_Q(0)));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 8);
|
||||
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
tcg_gen_st_i64(s->tmp1_i64, tcg_env, offset + offsetof(XMMReg, XMM_Q(1)));
|
||||
TCGv_i128 t = tcg_temp_new_i128();
|
||||
|
||||
tcg_gen_qemu_ld_i128(t, s->A0, mem_index, mop);
|
||||
tcg_gen_st_i128(t, tcg_env, offset);
|
||||
}
|
||||
|
||||
static inline void gen_sto_env_A0(DisasContext *s, int offset, bool align)
|
||||
{
|
||||
MemOp atom = (s->cpuid_ext_features & CPUID_EXT_AVX
|
||||
? MO_ATOM_IFALIGN : MO_ATOM_IFALIGN_PAIR);
|
||||
MemOp mop = MO_128 | MO_LE | atom | (align ? MO_ALIGN_16 : 0);
|
||||
int mem_index = s->mem_index;
|
||||
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, offset + offsetof(XMMReg, XMM_Q(0)));
|
||||
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index,
|
||||
MO_LEUQ | (align ? MO_ALIGN_16 : 0));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 8);
|
||||
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, offset + offsetof(XMMReg, XMM_Q(1)));
|
||||
tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
TCGv_i128 t = tcg_temp_new_i128();
|
||||
|
||||
tcg_gen_ld_i128(t, tcg_env, offset);
|
||||
tcg_gen_qemu_st_i128(t, s->A0, mem_index, mop);
|
||||
}
|
||||
|
||||
static void gen_ldy_env_A0(DisasContext *s, int offset, bool align)
|
||||
{
|
||||
MemOp mop = MO_128 | MO_LE | MO_ATOM_IFALIGN_PAIR;
|
||||
int mem_index = s->mem_index;
|
||||
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index,
|
||||
MO_LEUQ | (align ? MO_ALIGN_32 : 0));
|
||||
tcg_gen_st_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(0)));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 8);
|
||||
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
tcg_gen_st_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(1)));
|
||||
TCGv_i128 t0 = tcg_temp_new_i128();
|
||||
TCGv_i128 t1 = tcg_temp_new_i128();
|
||||
|
||||
tcg_gen_qemu_ld_i128(t0, s->A0, mem_index, mop | (align ? MO_ALIGN_32 : 0));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 16);
|
||||
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
tcg_gen_st_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(2)));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 24);
|
||||
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
tcg_gen_st_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(3)));
|
||||
tcg_gen_qemu_ld_i128(t1, s->tmp0, mem_index, mop);
|
||||
|
||||
tcg_gen_st_i128(t0, tcg_env, offset + offsetof(YMMReg, YMM_X(0)));
|
||||
tcg_gen_st_i128(t1, tcg_env, offset + offsetof(YMMReg, YMM_X(1)));
|
||||
}
|
||||
|
||||
static void gen_sty_env_A0(DisasContext *s, int offset, bool align)
|
||||
{
|
||||
MemOp mop = MO_128 | MO_LE | MO_ATOM_IFALIGN_PAIR;
|
||||
int mem_index = s->mem_index;
|
||||
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(0)));
|
||||
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index,
|
||||
MO_LEUQ | (align ? MO_ALIGN_32 : 0));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 8);
|
||||
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(1)));
|
||||
tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
TCGv_i128 t = tcg_temp_new_i128();
|
||||
|
||||
tcg_gen_ld_i128(t, tcg_env, offset + offsetof(YMMReg, YMM_X(0)));
|
||||
tcg_gen_qemu_st_i128(t, s->A0, mem_index, mop | (align ? MO_ALIGN_32 : 0));
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 16);
|
||||
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(2)));
|
||||
tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
tcg_gen_addi_tl(s->tmp0, s->A0, 24);
|
||||
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, offset + offsetof(YMMReg, YMM_Q(3)));
|
||||
tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
|
||||
tcg_gen_ld_i128(t, tcg_env, offset + offsetof(YMMReg, YMM_X(1)));
|
||||
tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop);
|
||||
}
|
||||
|
||||
#include "decode-new.h"
|
||||
|
||||
+3
-20
@@ -520,21 +520,9 @@ static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
|
||||
{
|
||||
switch (opsize) {
|
||||
case OS_BYTE:
|
||||
if (sign) {
|
||||
tcg_gen_ext8s_i32(res, val);
|
||||
} else {
|
||||
tcg_gen_ext8u_i32(res, val);
|
||||
}
|
||||
break;
|
||||
case OS_WORD:
|
||||
if (sign) {
|
||||
tcg_gen_ext16s_i32(res, val);
|
||||
} else {
|
||||
tcg_gen_ext16u_i32(res, val);
|
||||
}
|
||||
break;
|
||||
case OS_LONG:
|
||||
tcg_gen_mov_i32(res, val);
|
||||
tcg_gen_ext_i32(res, val, opsize | (sign ? MO_SIGN : 0));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
@@ -1072,15 +1060,10 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
|
||||
tmp = tcg_temp_new();
|
||||
switch (opsize) {
|
||||
case OS_BYTE:
|
||||
tcg_gen_ext8s_i32(tmp, reg);
|
||||
gen_helper_exts32(tcg_env, fp, tmp);
|
||||
break;
|
||||
case OS_WORD:
|
||||
tcg_gen_ext16s_i32(tmp, reg);
|
||||
gen_helper_exts32(tcg_env, fp, tmp);
|
||||
break;
|
||||
case OS_LONG:
|
||||
gen_helper_exts32(tcg_env, fp, reg);
|
||||
tcg_gen_ext_i32(tmp, reg, opsize | MO_SIGN);
|
||||
gen_helper_exts32(tcg_env, fp, tmp);
|
||||
break;
|
||||
case OS_SINGLE:
|
||||
gen_helper_extf32(tcg_env, fp, reg);
|
||||
|
||||
@@ -492,13 +492,11 @@ static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
|
||||
/* mov.<bwl> rs,rd */
|
||||
static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
|
||||
{
|
||||
static void (* const mov[])(TCGv ret, TCGv arg) = {
|
||||
tcg_gen_ext8s_i32, tcg_gen_ext16s_i32, tcg_gen_mov_i32,
|
||||
};
|
||||
TCGv tmp, mem, addr;
|
||||
|
||||
if (a->lds == 3 && a->ldd == 3) {
|
||||
/* mov.<bwl> rs,rd */
|
||||
mov[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
|
||||
tcg_gen_ext_i32(cpu_regs[a->rd], cpu_regs[a->rs], a->sz | MO_SIGN);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -570,10 +568,7 @@ static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a)
|
||||
/* movu.<bw> rs,rd */
|
||||
static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a)
|
||||
{
|
||||
static void (* const ext[])(TCGv ret, TCGv arg) = {
|
||||
tcg_gen_ext8u_i32, tcg_gen_ext16u_i32,
|
||||
};
|
||||
ext[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
|
||||
tcg_gen_ext_i32(cpu_regs[a->rd], cpu_regs[a->rs], a->sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6542,28 +6542,16 @@ static void decode_rrpw_extract_insert(DisasContext *ctx)
|
||||
switch (op2) {
|
||||
case OPC2_32_RRPW_EXTR:
|
||||
if (width == 0) {
|
||||
tcg_gen_movi_tl(cpu_gpr_d[r3], 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos + width <= 32) {
|
||||
/* optimize special cases */
|
||||
if ((pos == 0) && (width == 8)) {
|
||||
tcg_gen_ext8s_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
} else if ((pos == 0) && (width == 16)) {
|
||||
tcg_gen_ext16s_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
} else {
|
||||
tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 32 - pos - width);
|
||||
tcg_gen_sari_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], 32 - width);
|
||||
}
|
||||
tcg_gen_movi_tl(cpu_gpr_d[r3], 0);
|
||||
} else if (pos + width <= 32) {
|
||||
tcg_gen_sextract_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], pos, width);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_RRPW_EXTR_U:
|
||||
if (width == 0) {
|
||||
tcg_gen_movi_tl(cpu_gpr_d[r3], 0);
|
||||
} else {
|
||||
tcg_gen_shri_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], pos);
|
||||
tcg_gen_andi_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], ~0u >> (32-width));
|
||||
tcg_gen_extract_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], pos, width);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_RRPW_IMASK:
|
||||
|
||||
@@ -2262,17 +2262,7 @@ static void translate_salt(DisasContext *dc, const OpcodeArg arg[],
|
||||
static void translate_sext(DisasContext *dc, const OpcodeArg arg[],
|
||||
const uint32_t par[])
|
||||
{
|
||||
int shift = 31 - arg[2].imm;
|
||||
|
||||
if (shift == 24) {
|
||||
tcg_gen_ext8s_i32(arg[0].out, arg[1].in);
|
||||
} else if (shift == 16) {
|
||||
tcg_gen_ext16s_i32(arg[0].out, arg[1].in);
|
||||
} else {
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_shli_i32(tmp, arg[1].in, shift);
|
||||
tcg_gen_sari_i32(arg[0].out, tmp, shift);
|
||||
}
|
||||
tcg_gen_sextract_i32(arg[0].out, arg[1].in, 0, arg[2].imm + 1);
|
||||
}
|
||||
|
||||
static uint32_t test_exceptions_simcall(DisasContext *dc,
|
||||
|
||||
@@ -77,9 +77,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
|
||||
#define TCG_REG_TMP2 TCG_REG_X30
|
||||
#define TCG_VEC_TMP0 TCG_REG_V31
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
#define TCG_REG_GUEST_BASE TCG_REG_X28
|
||||
#endif
|
||||
|
||||
static bool reloc_pc26(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
|
||||
{
|
||||
@@ -1664,97 +1662,98 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
s_bits == MO_128);
|
||||
a_mask = (1 << h->aa.align) - 1;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
unsigned s_mask = (1u << s_bits) - 1;
|
||||
unsigned mem_index = get_mmuidx(oi);
|
||||
TCGReg addr_adj;
|
||||
TCGType mask_type;
|
||||
uint64_t compare_mask;
|
||||
if (tcg_use_softmmu) {
|
||||
unsigned s_mask = (1u << s_bits) - 1;
|
||||
unsigned mem_index = get_mmuidx(oi);
|
||||
TCGReg addr_adj;
|
||||
TCGType mask_type;
|
||||
uint64_t compare_mask;
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
mask_type = (s->page_bits + s->tlb_dyn_max_bits > 32
|
||||
? TCG_TYPE_I64 : TCG_TYPE_I32);
|
||||
|
||||
/* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {tmp0,tmp1}. */
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8);
|
||||
tcg_out_insn(s, 3314, LDP, TCG_REG_TMP0, TCG_REG_TMP1, TCG_AREG0,
|
||||
tlb_mask_table_ofs(s, mem_index), 1, 0);
|
||||
|
||||
/* Extract the TLB index from the address into X0. */
|
||||
tcg_out_insn(s, 3502S, AND_LSR, mask_type == TCG_TYPE_I64,
|
||||
TCG_REG_TMP0, TCG_REG_TMP0, addr_reg,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
|
||||
/* Add the tlb_table pointer, forming the CPUTLBEntry address in TMP1. */
|
||||
tcg_out_insn(s, 3502, ADD, 1, TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP0);
|
||||
|
||||
/* Load the tlb comparator into TMP0, and the fast path addend into TMP1. */
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP1,
|
||||
is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write));
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include the alignment
|
||||
* bits within the address. For unaligned access, we check that we don't
|
||||
* cross pages using the address of the last byte of the access.
|
||||
*/
|
||||
if (a_mask >= s_mask) {
|
||||
addr_adj = addr_reg;
|
||||
} else {
|
||||
addr_adj = TCG_REG_TMP2;
|
||||
tcg_out_insn(s, 3401, ADDI, addr_type,
|
||||
addr_adj, addr_reg, s_mask - a_mask);
|
||||
}
|
||||
compare_mask = (uint64_t)s->page_mask | a_mask;
|
||||
|
||||
/* Store the page mask part of the address into TMP2. */
|
||||
tcg_out_logicali(s, I3404_ANDI, addr_type, TCG_REG_TMP2,
|
||||
addr_adj, compare_mask);
|
||||
|
||||
/* Perform the address comparison. */
|
||||
tcg_out_cmp(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2, 0);
|
||||
|
||||
/* If not equal, we jump to the slow path. */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
||||
|
||||
h->base = TCG_REG_TMP1;
|
||||
h->index = addr_reg;
|
||||
h->index_ext = addr_type;
|
||||
#else
|
||||
if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/* tst addr, #mask */
|
||||
tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, a_mask);
|
||||
mask_type = (s->page_bits + s->tlb_dyn_max_bits > 32
|
||||
? TCG_TYPE_I64 : TCG_TYPE_I32);
|
||||
|
||||
/* b.ne slow_path */
|
||||
/* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {tmp0,tmp1}. */
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8);
|
||||
tcg_out_insn(s, 3314, LDP, TCG_REG_TMP0, TCG_REG_TMP1, TCG_AREG0,
|
||||
tlb_mask_table_ofs(s, mem_index), 1, 0);
|
||||
|
||||
/* Extract the TLB index from the address into X0. */
|
||||
tcg_out_insn(s, 3502S, AND_LSR, mask_type == TCG_TYPE_I64,
|
||||
TCG_REG_TMP0, TCG_REG_TMP0, addr_reg,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
|
||||
/* Add the tlb_table pointer, forming the CPUTLBEntry address. */
|
||||
tcg_out_insn(s, 3502, ADD, 1, TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP0);
|
||||
|
||||
/* Load the tlb comparator into TMP0, and the fast path addend. */
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP1,
|
||||
is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write));
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include
|
||||
* the alignment bits within the address. For unaligned access,
|
||||
* we check that we don't cross pages using the address of the
|
||||
* last byte of the access.
|
||||
*/
|
||||
if (a_mask >= s_mask) {
|
||||
addr_adj = addr_reg;
|
||||
} else {
|
||||
addr_adj = TCG_REG_TMP2;
|
||||
tcg_out_insn(s, 3401, ADDI, addr_type,
|
||||
addr_adj, addr_reg, s_mask - a_mask);
|
||||
}
|
||||
compare_mask = (uint64_t)s->page_mask | a_mask;
|
||||
|
||||
/* Store the page mask part of the address into TMP2. */
|
||||
tcg_out_logicali(s, I3404_ANDI, addr_type, TCG_REG_TMP2,
|
||||
addr_adj, compare_mask);
|
||||
|
||||
/* Perform the address comparison. */
|
||||
tcg_out_cmp(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2, 0);
|
||||
|
||||
/* If not equal, we jump to the slow path. */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
||||
}
|
||||
|
||||
if (guest_base || addr_type == TCG_TYPE_I32) {
|
||||
h->base = TCG_REG_GUEST_BASE;
|
||||
h->base = TCG_REG_TMP1;
|
||||
h->index = addr_reg;
|
||||
h->index_ext = addr_type;
|
||||
} else {
|
||||
h->base = addr_reg;
|
||||
h->index = TCG_REG_XZR;
|
||||
h->index_ext = TCG_TYPE_I64;
|
||||
if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/* tst addr, #mask */
|
||||
tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, a_mask);
|
||||
|
||||
/* b.ne slow_path */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
||||
}
|
||||
|
||||
if (guest_base || addr_type == TCG_TYPE_I32) {
|
||||
h->base = TCG_REG_GUEST_BASE;
|
||||
h->index = addr_reg;
|
||||
h->index_ext = addr_type;
|
||||
} else {
|
||||
h->base = addr_reg;
|
||||
h->index = TCG_REG_XZR;
|
||||
h->index_ext = TCG_TYPE_I64;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ldst;
|
||||
}
|
||||
@@ -3117,16 +3116,16 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
|
||||
CPU_TEMP_BUF_NLONGS * sizeof(long));
|
||||
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
/*
|
||||
* Note that XZR cannot be encoded in the address base register slot,
|
||||
* as that actually encodes SP. Depending on the guest, we may need
|
||||
* to zero-extend the guest address via the address index register slot,
|
||||
* therefore we need to load even a zero guest base into a register.
|
||||
*/
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
|
||||
#endif
|
||||
if (!tcg_use_softmmu) {
|
||||
/*
|
||||
* Note that XZR cannot be encoded in the address base register slot,
|
||||
* as that actually encodes SP. Depending on the guest, we may need
|
||||
* to zero-extend the guest address via the address index register slot,
|
||||
* therefore we need to load even a zero guest base into a register.
|
||||
*/
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
|
||||
}
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
|
||||
|
||||
+97
-106
@@ -89,9 +89,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
|
||||
|
||||
#define TCG_REG_TMP TCG_REG_R12
|
||||
#define TCG_VEC_TMP TCG_REG_Q15
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
#define TCG_REG_GUEST_BASE TCG_REG_R11
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
COND_EQ = 0x0,
|
||||
@@ -356,14 +354,8 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
* r0-r3 will be overwritten when reading the tlb entry (system-mode only);
|
||||
* r14 will be overwritten by the BLNE branching to the slow path.
|
||||
*/
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define ALL_QLDST_REGS \
|
||||
(ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1) | \
|
||||
(1 << TCG_REG_R2) | (1 << TCG_REG_R3) | \
|
||||
(1 << TCG_REG_R14)))
|
||||
#else
|
||||
#define ALL_QLDST_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_R14))
|
||||
#endif
|
||||
(ALL_GENERAL_REGS & ~((tcg_use_softmmu ? 0xf : 0) | (1 << TCG_REG_R14)))
|
||||
|
||||
/*
|
||||
* ARM immediates for ALU instructions are made of an unsigned 8-bit
|
||||
@@ -1387,113 +1379,115 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
MemOp opc = get_memop(oi);
|
||||
unsigned a_mask;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
*h = (HostAddress){
|
||||
.cond = COND_AL,
|
||||
.base = addrlo,
|
||||
.index = TCG_REG_R1,
|
||||
.index_scratch = true,
|
||||
};
|
||||
#else
|
||||
*h = (HostAddress){
|
||||
.cond = COND_AL,
|
||||
.base = addrlo,
|
||||
.index = guest_base ? TCG_REG_GUEST_BASE : -1,
|
||||
.index_scratch = false,
|
||||
};
|
||||
#endif
|
||||
if (tcg_use_softmmu) {
|
||||
*h = (HostAddress){
|
||||
.cond = COND_AL,
|
||||
.base = addrlo,
|
||||
.index = TCG_REG_R1,
|
||||
.index_scratch = true,
|
||||
};
|
||||
} else {
|
||||
*h = (HostAddress){
|
||||
.cond = COND_AL,
|
||||
.base = addrlo,
|
||||
.index = guest_base ? TCG_REG_GUEST_BASE : -1,
|
||||
.index_scratch = false,
|
||||
};
|
||||
}
|
||||
|
||||
h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
|
||||
a_mask = (1 << h->aa.align) - 1;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write);
|
||||
int fast_off = tlb_mask_table_ofs(s, mem_index);
|
||||
unsigned s_mask = (1 << (opc & MO_SIZE)) - 1;
|
||||
TCGReg t_addr;
|
||||
if (tcg_use_softmmu) {
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write);
|
||||
int fast_off = tlb_mask_table_ofs(s, mem_index);
|
||||
unsigned s_mask = (1 << (opc & MO_SIZE)) - 1;
|
||||
TCGReg t_addr;
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
|
||||
/* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {r0,r1}. */
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 4);
|
||||
tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_AREG0, fast_off);
|
||||
/* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {r0,r1}. */
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 4);
|
||||
tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_AREG0, fast_off);
|
||||
|
||||
/* Extract the tlb index from the address into R0. */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_AND, TCG_REG_R0, TCG_REG_R0, addrlo,
|
||||
SHIFT_IMM_LSR(s->page_bits - CPU_TLB_ENTRY_BITS));
|
||||
/* Extract the tlb index from the address into R0. */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_AND, TCG_REG_R0, TCG_REG_R0, addrlo,
|
||||
SHIFT_IMM_LSR(s->page_bits - CPU_TLB_ENTRY_BITS));
|
||||
|
||||
/*
|
||||
* Add the tlb_table pointer, creating the CPUTLBEntry address in R1.
|
||||
* Load the tlb comparator into R2/R3 and the fast path addend into R1.
|
||||
*/
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
if (cmp_off == 0) {
|
||||
if (s->addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ld32_rwb(s, COND_AL, TCG_REG_R2, TCG_REG_R1, TCG_REG_R0);
|
||||
/*
|
||||
* Add the tlb_table pointer, creating the CPUTLBEntry address in R1.
|
||||
* Load the tlb comparator into R2/R3 and the fast path addend into R1.
|
||||
*/
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
if (cmp_off == 0) {
|
||||
if (s->addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ld32_rwb(s, COND_AL, TCG_REG_R2,
|
||||
TCG_REG_R1, TCG_REG_R0);
|
||||
} else {
|
||||
tcg_out_ldrd_rwb(s, COND_AL, TCG_REG_R2,
|
||||
TCG_REG_R1, TCG_REG_R0);
|
||||
}
|
||||
} else {
|
||||
tcg_out_ldrd_rwb(s, COND_AL, TCG_REG_R2, TCG_REG_R1, TCG_REG_R0);
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
|
||||
TCG_REG_R1, TCG_REG_R1, TCG_REG_R0, 0);
|
||||
if (s->addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R1, cmp_off);
|
||||
} else {
|
||||
tcg_out_ldrd_8(s, COND_AL, TCG_REG_R2, TCG_REG_R1, cmp_off);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
|
||||
TCG_REG_R1, TCG_REG_R1, TCG_REG_R0, 0);
|
||||
if (s->addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R1, cmp_off);
|
||||
|
||||
/* Load the tlb addend. */
|
||||
tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R1,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/*
|
||||
* Check alignment, check comparators.
|
||||
* Do this in 2-4 insns. Use MOVW for v7, if possible,
|
||||
* to reduce the number of sequential conditional instructions.
|
||||
* Almost all guests have at least 4k pages, which means that we need
|
||||
* to clear at least 9 bits even for an 8-byte memory, which means it
|
||||
* isn't worth checking for an immediate operand for BIC.
|
||||
*
|
||||
* For unaligned accesses, test the page of the last unit of alignment.
|
||||
* This leaves the least significant alignment bits unchanged, and of
|
||||
* course must be zero.
|
||||
*/
|
||||
t_addr = addrlo;
|
||||
if (a_mask < s_mask) {
|
||||
t_addr = TCG_REG_R0;
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, t_addr,
|
||||
addrlo, s_mask - a_mask);
|
||||
}
|
||||
if (use_armv7_instructions && s->page_bits <= 16) {
|
||||
tcg_out_movi32(s, COND_AL, TCG_REG_TMP, ~(s->page_mask | a_mask));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_BIC, TCG_REG_TMP,
|
||||
t_addr, TCG_REG_TMP, 0);
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
|
||||
TCG_REG_R2, TCG_REG_TMP, 0);
|
||||
} else {
|
||||
tcg_out_ldrd_8(s, COND_AL, TCG_REG_R2, TCG_REG_R1, cmp_off);
|
||||
if (a_mask) {
|
||||
tcg_debug_assert(a_mask <= 0xff);
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, a_mask);
|
||||
}
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP, 0, t_addr,
|
||||
SHIFT_IMM_LSR(s->page_bits));
|
||||
tcg_out_dat_reg(s, (a_mask ? COND_EQ : COND_AL), ARITH_CMP,
|
||||
0, TCG_REG_R2, TCG_REG_TMP,
|
||||
SHIFT_IMM_LSL(s->page_bits));
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the tlb addend. */
|
||||
tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R1,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/*
|
||||
* Check alignment, check comparators.
|
||||
* Do this in 2-4 insns. Use MOVW for v7, if possible,
|
||||
* to reduce the number of sequential conditional instructions.
|
||||
* Almost all guests have at least 4k pages, which means that we need
|
||||
* to clear at least 9 bits even for an 8-byte memory, which means it
|
||||
* isn't worth checking for an immediate operand for BIC.
|
||||
*
|
||||
* For unaligned accesses, test the page of the last unit of alignment.
|
||||
* This leaves the least significant alignment bits unchanged, and of
|
||||
* course must be zero.
|
||||
*/
|
||||
t_addr = addrlo;
|
||||
if (a_mask < s_mask) {
|
||||
t_addr = TCG_REG_R0;
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, t_addr,
|
||||
addrlo, s_mask - a_mask);
|
||||
}
|
||||
if (use_armv7_instructions && s->page_bits <= 16) {
|
||||
tcg_out_movi32(s, COND_AL, TCG_REG_TMP, ~(s->page_mask | a_mask));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_BIC, TCG_REG_TMP,
|
||||
t_addr, TCG_REG_TMP, 0);
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R2, TCG_REG_TMP, 0);
|
||||
} else {
|
||||
if (a_mask) {
|
||||
tcg_debug_assert(a_mask <= 0xff);
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, a_mask);
|
||||
if (s->addr_type != TCG_TYPE_I32) {
|
||||
tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0, TCG_REG_R3, addrhi, 0);
|
||||
}
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP, 0, t_addr,
|
||||
SHIFT_IMM_LSR(s->page_bits));
|
||||
tcg_out_dat_reg(s, (a_mask ? COND_EQ : COND_AL), ARITH_CMP,
|
||||
0, TCG_REG_R2, TCG_REG_TMP,
|
||||
SHIFT_IMM_LSL(s->page_bits));
|
||||
}
|
||||
|
||||
if (s->addr_type != TCG_TYPE_I32) {
|
||||
tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0, TCG_REG_R3, addrhi, 0);
|
||||
}
|
||||
#else
|
||||
if (a_mask) {
|
||||
} else if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
@@ -1505,7 +1499,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
/* tst addr, #mask */
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, a_mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ldst;
|
||||
}
|
||||
@@ -2931,12 +2924,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
if (guest_base) {
|
||||
if (!tcg_use_softmmu && guest_base) {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_out_b_reg(s, COND_AL, tcg_target_call_iarg_regs[1]);
|
||||
|
||||
|
||||
+98
-100
@@ -153,11 +153,8 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
|
||||
# define ALL_VECTOR_REGS 0x00ff0000u
|
||||
# define ALL_BYTEL_REGS 0x0000000fu
|
||||
#endif
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
# define SOFTMMU_RESERVE_REGS ((1 << TCG_REG_L0) | (1 << TCG_REG_L1))
|
||||
#else
|
||||
# define SOFTMMU_RESERVE_REGS 0
|
||||
#endif
|
||||
#define SOFTMMU_RESERVE_REGS \
|
||||
(tcg_use_softmmu ? (1 << TCG_REG_L0) | (1 << TCG_REG_L1) : 0)
|
||||
|
||||
/* For 64-bit, we always know that CMOV is available. */
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
@@ -1933,7 +1930,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static HostAddress x86_guest_base = {
|
||||
.index = -1
|
||||
};
|
||||
@@ -1949,6 +1946,7 @@ static inline int setup_guest_base_seg(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#define setup_guest_base_seg setup_guest_base_seg
|
||||
#elif defined(__x86_64__) && \
|
||||
(defined (__FreeBSD__) || defined (__FreeBSD_kernel__))
|
||||
# include <machine/sysarch.h>
|
||||
@@ -1959,13 +1957,14 @@ static inline int setup_guest_base_seg(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#define setup_guest_base_seg setup_guest_base_seg
|
||||
#endif
|
||||
#else
|
||||
static inline int setup_guest_base_seg(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* setup_guest_base_seg */
|
||||
#endif /* !SOFTMMU */
|
||||
# define x86_guest_base (*(HostAddress *)({ qemu_build_not_reached(); NULL; }))
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
#ifndef setup_guest_base_seg
|
||||
# define setup_guest_base_seg() 0
|
||||
#endif
|
||||
|
||||
#define MIN_TLB_MASK_TABLE_OFS INT_MIN
|
||||
|
||||
@@ -1984,94 +1983,94 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
MemOp s_bits = opc & MO_SIZE;
|
||||
unsigned a_mask;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
h->index = TCG_REG_L0;
|
||||
h->ofs = 0;
|
||||
h->seg = 0;
|
||||
#else
|
||||
*h = x86_guest_base;
|
||||
#endif
|
||||
if (tcg_use_softmmu) {
|
||||
h->index = TCG_REG_L0;
|
||||
h->ofs = 0;
|
||||
h->seg = 0;
|
||||
} else {
|
||||
*h = x86_guest_base;
|
||||
}
|
||||
h->base = addrlo;
|
||||
h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, s_bits == MO_128);
|
||||
a_mask = (1 << h->aa.align) - 1;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
int cmp_ofs = is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write);
|
||||
TCGType ttype = TCG_TYPE_I32;
|
||||
TCGType tlbtype = TCG_TYPE_I32;
|
||||
int trexw = 0, hrexw = 0, tlbrexw = 0;
|
||||
unsigned mem_index = get_mmuidx(oi);
|
||||
unsigned s_mask = (1 << s_bits) - 1;
|
||||
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
|
||||
int tlb_mask;
|
||||
if (tcg_use_softmmu) {
|
||||
int cmp_ofs = is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write);
|
||||
TCGType ttype = TCG_TYPE_I32;
|
||||
TCGType tlbtype = TCG_TYPE_I32;
|
||||
int trexw = 0, hrexw = 0, tlbrexw = 0;
|
||||
unsigned mem_index = get_mmuidx(oi);
|
||||
unsigned s_mask = (1 << s_bits) - 1;
|
||||
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
|
||||
int tlb_mask;
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 64) {
|
||||
ttype = s->addr_type;
|
||||
trexw = (ttype == TCG_TYPE_I32 ? 0 : P_REXW);
|
||||
if (TCG_TYPE_PTR == TCG_TYPE_I64) {
|
||||
hrexw = P_REXW;
|
||||
if (s->page_bits + s->tlb_dyn_max_bits > 32) {
|
||||
tlbtype = TCG_TYPE_I64;
|
||||
tlbrexw = P_REXW;
|
||||
if (TCG_TARGET_REG_BITS == 64) {
|
||||
ttype = s->addr_type;
|
||||
trexw = (ttype == TCG_TYPE_I32 ? 0 : P_REXW);
|
||||
if (TCG_TYPE_PTR == TCG_TYPE_I64) {
|
||||
hrexw = P_REXW;
|
||||
if (s->page_bits + s->tlb_dyn_max_bits > 32) {
|
||||
tlbtype = TCG_TYPE_I64;
|
||||
tlbrexw = P_REXW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tcg_out_mov(s, tlbtype, TCG_REG_L0, addrlo);
|
||||
tcg_out_shifti(s, SHIFT_SHR + tlbrexw, TCG_REG_L0,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
tcg_out_mov(s, tlbtype, TCG_REG_L0, addrlo);
|
||||
tcg_out_shifti(s, SHIFT_SHR + tlbrexw, TCG_REG_L0,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
|
||||
tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, TCG_REG_L0, TCG_AREG0,
|
||||
fast_ofs + offsetof(CPUTLBDescFast, mask));
|
||||
tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, TCG_REG_L0, TCG_AREG0,
|
||||
fast_ofs + offsetof(CPUTLBDescFast, mask));
|
||||
|
||||
tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L0, TCG_AREG0,
|
||||
fast_ofs + offsetof(CPUTLBDescFast, table));
|
||||
tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L0, TCG_AREG0,
|
||||
fast_ofs + offsetof(CPUTLBDescFast, table));
|
||||
|
||||
/*
|
||||
* If the required alignment is at least as large as the access, simply
|
||||
* copy the address and mask. For lesser alignments, check that we don't
|
||||
* cross pages for the complete access.
|
||||
*/
|
||||
if (a_mask >= s_mask) {
|
||||
tcg_out_mov(s, ttype, TCG_REG_L1, addrlo);
|
||||
} else {
|
||||
tcg_out_modrm_offset(s, OPC_LEA + trexw, TCG_REG_L1,
|
||||
addrlo, s_mask - a_mask);
|
||||
}
|
||||
tlb_mask = s->page_mask | a_mask;
|
||||
tgen_arithi(s, ARITH_AND + trexw, TCG_REG_L1, tlb_mask, 0);
|
||||
/*
|
||||
* If the required alignment is at least as large as the access,
|
||||
* simply copy the address and mask. For lesser alignments,
|
||||
* check that we don't cross pages for the complete access.
|
||||
*/
|
||||
if (a_mask >= s_mask) {
|
||||
tcg_out_mov(s, ttype, TCG_REG_L1, addrlo);
|
||||
} else {
|
||||
tcg_out_modrm_offset(s, OPC_LEA + trexw, TCG_REG_L1,
|
||||
addrlo, s_mask - a_mask);
|
||||
}
|
||||
tlb_mask = s->page_mask | a_mask;
|
||||
tgen_arithi(s, ARITH_AND + trexw, TCG_REG_L1, tlb_mask, 0);
|
||||
|
||||
/* cmp 0(TCG_REG_L0), TCG_REG_L1 */
|
||||
tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw,
|
||||
TCG_REG_L1, TCG_REG_L0, cmp_ofs);
|
||||
|
||||
/* jne slow_path */
|
||||
tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
s->code_ptr += 4;
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 && s->addr_type == TCG_TYPE_I64) {
|
||||
/* cmp 4(TCG_REG_L0), addrhi */
|
||||
tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, TCG_REG_L0, cmp_ofs + 4);
|
||||
/* cmp 0(TCG_REG_L0), TCG_REG_L1 */
|
||||
tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw,
|
||||
TCG_REG_L1, TCG_REG_L0, cmp_ofs);
|
||||
|
||||
/* jne slow_path */
|
||||
tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
|
||||
ldst->label_ptr[1] = s->code_ptr;
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
s->code_ptr += 4;
|
||||
}
|
||||
|
||||
/* TLB Hit. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_L0, TCG_REG_L0,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
#else
|
||||
if (a_mask) {
|
||||
if (TCG_TARGET_REG_BITS == 32 && s->addr_type == TCG_TYPE_I64) {
|
||||
/* cmp 4(TCG_REG_L0), addrhi */
|
||||
tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi,
|
||||
TCG_REG_L0, cmp_ofs + 4);
|
||||
|
||||
/* jne slow_path */
|
||||
tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
|
||||
ldst->label_ptr[1] = s->code_ptr;
|
||||
s->code_ptr += 4;
|
||||
}
|
||||
|
||||
/* TLB Hit. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_L0, TCG_REG_L0,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
} else if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
@@ -2085,7 +2084,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
s->code_ptr += 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ldst;
|
||||
}
|
||||
@@ -4140,35 +4138,35 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
tcg_out_push(s, tcg_target_callee_save_regs[i]);
|
||||
}
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
/* jmp *tb. */
|
||||
tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP,
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4
|
||||
+ stack_addend);
|
||||
#else
|
||||
# if !defined(CONFIG_SOFTMMU)
|
||||
if (guest_base) {
|
||||
if (!tcg_use_softmmu && guest_base) {
|
||||
int seg = setup_guest_base_seg();
|
||||
if (seg != 0) {
|
||||
x86_guest_base.seg = seg;
|
||||
} else if (guest_base == (int32_t)guest_base) {
|
||||
x86_guest_base.ofs = guest_base;
|
||||
} else {
|
||||
assert(TCG_TARGET_REG_BITS == 64);
|
||||
/* Choose R12 because, as a base, it requires a SIB byte. */
|
||||
x86_guest_base.index = TCG_REG_R12;
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, x86_guest_base.index, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, x86_guest_base.index);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
/* jmp *tb. */
|
||||
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
|
||||
#endif
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32) {
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
/* jmp *tb. */
|
||||
tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP,
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4
|
||||
+ stack_addend);
|
||||
} else {
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
/* jmp *tb. */
|
||||
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return path for goto_ptr. Set return value to 0, a-la exit_tb,
|
||||
|
||||
@@ -165,10 +165,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
|
||||
return TCG_REG_A0 + slot;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
#define USE_GUEST_BASE (guest_base != 0)
|
||||
#define TCG_GUEST_BASE_REG TCG_REG_S1
|
||||
#endif
|
||||
|
||||
#define TCG_CT_CONST_ZERO 0x100
|
||||
#define TCG_CT_CONST_S12 0x200
|
||||
@@ -908,76 +905,77 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
|
||||
a_bits = h->aa.align;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
unsigned s_bits = opc & MO_SIZE;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
|
||||
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
|
||||
if (tcg_use_softmmu) {
|
||||
unsigned s_bits = opc & MO_SIZE;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
|
||||
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
|
||||
|
||||
tcg_out_opc_srli_d(s, TCG_REG_TMP2, addr_reg,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
|
||||
tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
|
||||
|
||||
/* Load the tlb comparator and the addend. */
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
|
||||
is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write));
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include the alignment
|
||||
* bits within the address. For unaligned access, we check that we don't
|
||||
* cross pages using the address of the last byte of the access.
|
||||
*/
|
||||
if (a_bits < s_bits) {
|
||||
unsigned a_mask = (1u << a_bits) - 1;
|
||||
unsigned s_mask = (1u << s_bits) - 1;
|
||||
tcg_out_addi(s, addr_type, TCG_REG_TMP1, addr_reg, s_mask - a_mask);
|
||||
} else {
|
||||
tcg_out_mov(s, addr_type, TCG_REG_TMP1, addr_reg);
|
||||
}
|
||||
tcg_out_opc_bstrins_d(s, TCG_REG_TMP1, TCG_REG_ZERO,
|
||||
a_bits, s->page_bits - 1);
|
||||
|
||||
/* Compare masked address with the TLB entry. */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0);
|
||||
|
||||
h->index = TCG_REG_TMP2;
|
||||
#else
|
||||
if (a_bits) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
|
||||
|
||||
tcg_out_opc_srli_d(s, TCG_REG_TMP2, addr_reg,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
|
||||
tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
|
||||
|
||||
/* Load the tlb comparator and the addend. */
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
|
||||
is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write));
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/*
|
||||
* Without micro-architecture details, we don't know which of
|
||||
* bstrpick or andi is faster, so use bstrpick as it's not
|
||||
* constrained by imm field width. Not to say alignments >= 2^12
|
||||
* are going to happen any time soon.
|
||||
* For aligned accesses, we check the first byte and include the
|
||||
* alignment bits within the address. For unaligned access, we
|
||||
* check that we don't cross pages using the address of the last
|
||||
* byte of the access.
|
||||
*/
|
||||
tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1);
|
||||
if (a_bits < s_bits) {
|
||||
unsigned a_mask = (1u << a_bits) - 1;
|
||||
unsigned s_mask = (1u << s_bits) - 1;
|
||||
tcg_out_addi(s, addr_type, TCG_REG_TMP1, addr_reg, s_mask - a_mask);
|
||||
} else {
|
||||
tcg_out_mov(s, addr_type, TCG_REG_TMP1, addr_reg);
|
||||
}
|
||||
tcg_out_opc_bstrins_d(s, TCG_REG_TMP1, TCG_REG_ZERO,
|
||||
a_bits, s->page_bits - 1);
|
||||
|
||||
/* Compare masked address with the TLB entry. */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0);
|
||||
}
|
||||
tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0);
|
||||
|
||||
h->index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
|
||||
#endif
|
||||
h->index = TCG_REG_TMP2;
|
||||
} else {
|
||||
if (a_bits) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/*
|
||||
* Without micro-architecture details, we don't know which of
|
||||
* bstrpick or andi is faster, so use bstrpick as it's not
|
||||
* constrained by imm field width. Not to say alignments >= 2^12
|
||||
* are going to happen any time soon.
|
||||
*/
|
||||
tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1);
|
||||
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0);
|
||||
}
|
||||
|
||||
h->index = guest_base ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
|
||||
}
|
||||
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
h->base = TCG_REG_TMP0;
|
||||
@@ -2272,12 +2270,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
if (USE_GUEST_BASE) {
|
||||
if (!tcg_use_softmmu && guest_base) {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call generated code */
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
+113
-118
@@ -78,13 +78,11 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
|
||||
#define TCG_TMP2 TCG_REG_T8
|
||||
#define TCG_TMP3 TCG_REG_T7
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
#define TCG_GUEST_BASE_REG TCG_REG_S7
|
||||
#endif
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_REG_TB TCG_REG_S6
|
||||
#else
|
||||
#define TCG_REG_TB (qemu_build_not_reached(), TCG_REG_ZERO)
|
||||
#define TCG_REG_TB ({ qemu_build_not_reached(); TCG_REG_ZERO; })
|
||||
#endif
|
||||
|
||||
/* check if we really need so many registers :P */
|
||||
@@ -1279,130 +1277,129 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
a_bits = h->aa.align;
|
||||
a_mask = (1 << a_bits) - 1;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
unsigned s_mask = (1 << s_bits) - 1;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_off = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||
int add_off = offsetof(CPUTLBEntry, addend);
|
||||
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write);
|
||||
if (tcg_use_softmmu) {
|
||||
unsigned s_mask = (1 << s_bits) - 1;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_off = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||
int add_off = offsetof(CPUTLBEntry, addend);
|
||||
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write);
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
|
||||
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
|
||||
|
||||
/* Extract the TLB index from the address into TMP3. */
|
||||
if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, addrlo,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
} else {
|
||||
tcg_out_dsrl(s, TCG_TMP3, addrlo,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
}
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_TMP3, TCG_TMP3, TCG_TMP0);
|
||||
|
||||
/* Add the tlb_table pointer, creating the CPUTLBEntry address in TMP3. */
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
|
||||
/* Load the (low half) tlb comparator. */
|
||||
tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3,
|
||||
cmp_off + HOST_BIG_ENDIAN * 4);
|
||||
} else {
|
||||
tcg_out_ld(s, TCG_TYPE_I64, TCG_TMP0, TCG_TMP3, cmp_off);
|
||||
}
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 64 || addr_type == TCG_TYPE_I32) {
|
||||
/* Load the tlb addend for the fast path. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask the page bits, keeping the alignment bits to compare against.
|
||||
* For unaligned accesses, compare against the end of the access to
|
||||
* verify that it does not cross a page boundary.
|
||||
*/
|
||||
tcg_out_movi(s, addr_type, TCG_TMP1, s->page_mask | a_mask);
|
||||
if (a_mask < s_mask) {
|
||||
if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_opc_imm(s, OPC_ADDIU, TCG_TMP2, addrlo, s_mask - a_mask);
|
||||
} else {
|
||||
tcg_out_opc_imm(s, OPC_DADDIU, TCG_TMP2, addrlo, s_mask - a_mask);
|
||||
}
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
|
||||
} else {
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrlo);
|
||||
}
|
||||
|
||||
/* Zero extend a 32-bit guest address for a 64-bit host. */
|
||||
if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ext32u(s, TCG_TMP2, addrlo);
|
||||
addrlo = TCG_TMP2;
|
||||
}
|
||||
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
|
||||
|
||||
/* Load and test the high half tlb comparator. */
|
||||
if (TCG_TARGET_REG_BITS == 32 && addr_type != TCG_TYPE_I32) {
|
||||
/* delay slot */
|
||||
tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
|
||||
|
||||
/* Load the tlb addend for the fast path. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
|
||||
|
||||
ldst->label_ptr[1] = s->code_ptr;
|
||||
tcg_out_opc_br(s, OPC_BNE, addrhi, TCG_TMP0);
|
||||
}
|
||||
|
||||
/* delay slot */
|
||||
base = TCG_TMP3;
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP3, addrlo);
|
||||
#else
|
||||
if (a_mask && (use_mips32r6_instructions || a_bits != s_bits)) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
|
||||
/* We are expecting a_bits to max out at 7, much lower than ANDI. */
|
||||
tcg_debug_assert(a_bits < 16);
|
||||
tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addrlo, a_mask);
|
||||
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
|
||||
|
||||
/* Extract the TLB index from the address into TMP3. */
|
||||
if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, addrlo,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
} else {
|
||||
tcg_out_dsrl(s, TCG_TMP3, addrlo,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
}
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_TMP3, TCG_TMP3, TCG_TMP0);
|
||||
|
||||
/* Add the tlb_table pointer, creating the CPUTLBEntry address. */
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
|
||||
/* Load the (low half) tlb comparator. */
|
||||
tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3,
|
||||
cmp_off + HOST_BIG_ENDIAN * 4);
|
||||
} else {
|
||||
tcg_out_ld(s, TCG_TYPE_I64, TCG_TMP0, TCG_TMP3, cmp_off);
|
||||
}
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 64 || addr_type == TCG_TYPE_I32) {
|
||||
/* Load the tlb addend for the fast path. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask the page bits, keeping the alignment bits to compare against.
|
||||
* For unaligned accesses, compare against the end of the access to
|
||||
* verify that it does not cross a page boundary.
|
||||
*/
|
||||
tcg_out_movi(s, addr_type, TCG_TMP1, s->page_mask | a_mask);
|
||||
if (a_mask < s_mask) {
|
||||
tcg_out_opc_imm(s, (TCG_TARGET_REG_BITS == 32
|
||||
|| addr_type == TCG_TYPE_I32
|
||||
? OPC_ADDIU : OPC_DADDIU),
|
||||
TCG_TMP2, addrlo, s_mask - a_mask);
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
|
||||
} else {
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrlo);
|
||||
}
|
||||
|
||||
/* Zero extend a 32-bit guest address for a 64-bit host. */
|
||||
if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ext32u(s, TCG_TMP2, addrlo);
|
||||
addrlo = TCG_TMP2;
|
||||
}
|
||||
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
if (use_mips32r6_instructions) {
|
||||
tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
|
||||
} else {
|
||||
tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
|
||||
tcg_out_nop(s);
|
||||
}
|
||||
}
|
||||
tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
|
||||
|
||||
base = addrlo;
|
||||
if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ext32u(s, TCG_REG_A0, base);
|
||||
base = TCG_REG_A0;
|
||||
}
|
||||
if (guest_base) {
|
||||
if (guest_base == (int16_t)guest_base) {
|
||||
tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, base, guest_base);
|
||||
} else {
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, base,
|
||||
TCG_GUEST_BASE_REG);
|
||||
/* Load and test the high half tlb comparator. */
|
||||
if (TCG_TARGET_REG_BITS == 32 && addr_type != TCG_TYPE_I32) {
|
||||
/* delay slot */
|
||||
tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
|
||||
|
||||
/* Load the tlb addend for the fast path. */
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
|
||||
|
||||
ldst->label_ptr[1] = s->code_ptr;
|
||||
tcg_out_opc_br(s, OPC_BNE, addrhi, TCG_TMP0);
|
||||
}
|
||||
|
||||
/* delay slot */
|
||||
base = TCG_TMP3;
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP3, addrlo);
|
||||
} else {
|
||||
if (a_mask && (use_mips32r6_instructions || a_bits != s_bits)) {
|
||||
ldst = new_ldst_label(s);
|
||||
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addrlo;
|
||||
ldst->addrhi_reg = addrhi;
|
||||
|
||||
/* We are expecting a_bits to max out at 7, much lower than ANDI. */
|
||||
tcg_debug_assert(a_bits < 16);
|
||||
tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addrlo, a_mask);
|
||||
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
if (use_mips32r6_instructions) {
|
||||
tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
|
||||
} else {
|
||||
tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
|
||||
tcg_out_nop(s);
|
||||
}
|
||||
}
|
||||
|
||||
base = addrlo;
|
||||
if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ext32u(s, TCG_REG_A0, base);
|
||||
base = TCG_REG_A0;
|
||||
}
|
||||
if (guest_base) {
|
||||
if (guest_base == (int16_t)guest_base) {
|
||||
tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, base, guest_base);
|
||||
} else {
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, base,
|
||||
TCG_GUEST_BASE_REG);
|
||||
}
|
||||
base = TCG_REG_A0;
|
||||
}
|
||||
base = TCG_REG_A0;
|
||||
}
|
||||
#endif
|
||||
|
||||
h->base = base;
|
||||
return ldst;
|
||||
@@ -2465,8 +2462,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
if (guest_base != (int16_t)guest_base) {
|
||||
if (!tcg_use_softmmu && guest_base != (int16_t)guest_base) {
|
||||
/*
|
||||
* The function call abi for n32 and n64 will have loaded $25 (t9)
|
||||
* with the address of the prologue, so we can use that instead
|
||||
@@ -2479,7 +2475,6 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
TCG_TARGET_REG_BITS == 64 ? TCG_REG_T9 : 0);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 64) {
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]);
|
||||
|
||||
+5
-3
@@ -688,12 +688,14 @@ static void finish_folding(OptContext *ctx, TCGOp *op)
|
||||
int i, nb_oargs;
|
||||
|
||||
/*
|
||||
* For an opcode that ends a BB, reset all temp data.
|
||||
* We do no cross-BB optimization.
|
||||
* We only optimize extended basic blocks. If the opcode ends a BB
|
||||
* and is not a conditional branch, reset all temp data.
|
||||
*/
|
||||
if (def->flags & TCG_OPF_BB_END) {
|
||||
memset(&ctx->temps_used, 0, sizeof(ctx->temps_used));
|
||||
ctx->prev_mb = NULL;
|
||||
if (!(def->flags & TCG_OPF_COND_BRANCH)) {
|
||||
memset(&ctx->temps_used, 0, sizeof(ctx->temps_used));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+379
-182
File diff suppressed because it is too large
Load Diff
+97
-92
@@ -1245,105 +1245,110 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
|
||||
aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
|
||||
a_mask = (1u << aa.align) - 1;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
unsigned s_bits = opc & MO_SIZE;
|
||||
unsigned s_mask = (1u << s_bits) - 1;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
|
||||
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
|
||||
int compare_mask;
|
||||
TCGReg addr_adj;
|
||||
if (tcg_use_softmmu) {
|
||||
unsigned s_bits = opc & MO_SIZE;
|
||||
unsigned s_mask = (1u << s_bits) - 1;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
|
||||
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
|
||||
int compare_mask;
|
||||
TCGReg addr_adj;
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
|
||||
|
||||
tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
|
||||
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
|
||||
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include the alignment
|
||||
* bits within the address. For unaligned access, we check that we don't
|
||||
* cross pages using the address of the last byte of the access.
|
||||
*/
|
||||
addr_adj = addr_reg;
|
||||
if (a_mask < s_mask) {
|
||||
addr_adj = TCG_REG_TMP0;
|
||||
tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
|
||||
addr_adj, addr_reg, s_mask - a_mask);
|
||||
}
|
||||
compare_mask = s->page_mask | a_mask;
|
||||
if (compare_mask == sextreg(compare_mask, 0, 12)) {
|
||||
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
|
||||
} else {
|
||||
tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
|
||||
}
|
||||
|
||||
/* Load the tlb comparator and the addend. */
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
|
||||
is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write));
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/* Compare masked address with the TLB entry. */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
|
||||
|
||||
/* TLB Hit - translate address using addend. */
|
||||
if (addr_type != TCG_TYPE_I32) {
|
||||
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
|
||||
} else if (have_zba) {
|
||||
tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
|
||||
} else {
|
||||
tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
|
||||
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, TCG_REG_TMP2);
|
||||
}
|
||||
*pbase = TCG_REG_TMP0;
|
||||
#else
|
||||
TCGReg base;
|
||||
|
||||
if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/* We are expecting alignment max 7, so we can always use andi. */
|
||||
tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
|
||||
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
|
||||
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
|
||||
}
|
||||
tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
|
||||
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
|
||||
|
||||
if (guest_base != 0) {
|
||||
base = TCG_REG_TMP0;
|
||||
if (addr_type != TCG_TYPE_I32) {
|
||||
tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG);
|
||||
} else if (have_zba) {
|
||||
tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG);
|
||||
} else {
|
||||
tcg_out_ext32u(s, base, addr_reg);
|
||||
tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include the
|
||||
* alignment bits within the address. For unaligned access, we
|
||||
* check that we don't cross pages using the address of the last
|
||||
* byte of the access.
|
||||
*/
|
||||
addr_adj = addr_reg;
|
||||
if (a_mask < s_mask) {
|
||||
addr_adj = TCG_REG_TMP0;
|
||||
tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
|
||||
addr_adj, addr_reg, s_mask - a_mask);
|
||||
}
|
||||
} else if (addr_type != TCG_TYPE_I32) {
|
||||
base = addr_reg;
|
||||
compare_mask = s->page_mask | a_mask;
|
||||
if (compare_mask == sextreg(compare_mask, 0, 12)) {
|
||||
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
|
||||
} else {
|
||||
tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
|
||||
tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
|
||||
}
|
||||
|
||||
/* Load the tlb comparator and the addend. */
|
||||
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
|
||||
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
|
||||
is_ld ? offsetof(CPUTLBEntry, addr_read)
|
||||
: offsetof(CPUTLBEntry, addr_write));
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
/* Compare masked address with the TLB entry. */
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
|
||||
|
||||
/* TLB Hit - translate address using addend. */
|
||||
if (addr_type != TCG_TYPE_I32) {
|
||||
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
|
||||
} else if (have_zba) {
|
||||
tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0,
|
||||
addr_reg, TCG_REG_TMP2);
|
||||
} else {
|
||||
tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
|
||||
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0,
|
||||
TCG_REG_TMP0, TCG_REG_TMP2);
|
||||
}
|
||||
*pbase = TCG_REG_TMP0;
|
||||
} else {
|
||||
base = TCG_REG_TMP0;
|
||||
tcg_out_ext32u(s, base, addr_reg);
|
||||
TCGReg base;
|
||||
|
||||
if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/* We are expecting alignment max 7, so we can always use andi. */
|
||||
tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
|
||||
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
|
||||
|
||||
ldst->label_ptr[0] = s->code_ptr;
|
||||
tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
|
||||
}
|
||||
|
||||
if (guest_base != 0) {
|
||||
base = TCG_REG_TMP0;
|
||||
if (addr_type != TCG_TYPE_I32) {
|
||||
tcg_out_opc_reg(s, OPC_ADD, base, addr_reg,
|
||||
TCG_GUEST_BASE_REG);
|
||||
} else if (have_zba) {
|
||||
tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg,
|
||||
TCG_GUEST_BASE_REG);
|
||||
} else {
|
||||
tcg_out_ext32u(s, base, addr_reg);
|
||||
tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
|
||||
}
|
||||
} else if (addr_type != TCG_TYPE_I32) {
|
||||
base = addr_reg;
|
||||
} else {
|
||||
base = TCG_REG_TMP0;
|
||||
tcg_out_ext32u(s, base, addr_reg);
|
||||
}
|
||||
*pbase = base;
|
||||
}
|
||||
*pbase = base;
|
||||
#endif
|
||||
|
||||
return ldst;
|
||||
}
|
||||
@@ -2075,10 +2080,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
|
||||
#endif
|
||||
if (!tcg_use_softmmu && guest_base) {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
|
||||
}
|
||||
|
||||
/* Call generated code */
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
+79
-82
@@ -46,9 +46,7 @@
|
||||
/* A scratch register that may be be used throughout the backend. */
|
||||
#define TCG_TMP0 TCG_REG_R1
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
#define TCG_GUEST_BASE_REG TCG_REG_R13
|
||||
#endif
|
||||
|
||||
/* All of the following instructions are prefixed with their instruction
|
||||
format, and are defined as 8- or 16-bit quantities, even when the two
|
||||
@@ -1768,94 +1766,95 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
|
||||
h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, s_bits == MO_128);
|
||||
a_mask = (1 << h->aa.align) - 1;
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
unsigned s_mask = (1 << s_bits) - 1;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_off = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||
int ofs, a_off;
|
||||
uint64_t tlb_mask;
|
||||
if (tcg_use_softmmu) {
|
||||
unsigned s_mask = (1 << s_bits) - 1;
|
||||
int mem_index = get_mmuidx(oi);
|
||||
int fast_off = tlb_mask_table_ofs(s, mem_index);
|
||||
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||
int ofs, a_off;
|
||||
uint64_t tlb_mask;
|
||||
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
tcg_out_sh64(s, RSY_SRLG, TCG_TMP0, addr_reg, TCG_REG_NONE,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
|
||||
tcg_out_insn(s, RXY, NG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, mask_off);
|
||||
tcg_out_insn(s, RXY, AG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, table_off);
|
||||
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include the alignment
|
||||
* bits within the address. For unaligned access, we check that we don't
|
||||
* cross pages using the address of the last byte of the access.
|
||||
*/
|
||||
a_off = (a_mask >= s_mask ? 0 : s_mask - a_mask);
|
||||
tlb_mask = (uint64_t)s->page_mask | a_mask;
|
||||
if (a_off == 0) {
|
||||
tgen_andi_risbg(s, TCG_REG_R0, addr_reg, tlb_mask);
|
||||
} else {
|
||||
tcg_out_insn(s, RX, LA, TCG_REG_R0, addr_reg, TCG_REG_NONE, a_off);
|
||||
tgen_andi(s, addr_type, TCG_REG_R0, tlb_mask);
|
||||
}
|
||||
|
||||
if (is_ld) {
|
||||
ofs = offsetof(CPUTLBEntry, addr_read);
|
||||
} else {
|
||||
ofs = offsetof(CPUTLBEntry, addr_write);
|
||||
}
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
ofs += HOST_BIG_ENDIAN * 4;
|
||||
tcg_out_insn(s, RX, C, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
|
||||
} else {
|
||||
tcg_out_insn(s, RXY, CG, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
|
||||
}
|
||||
|
||||
tcg_out16(s, RI_BRC | (S390_CC_NE << 4));
|
||||
ldst->label_ptr[0] = s->code_ptr++;
|
||||
|
||||
h->index = TCG_TMP0;
|
||||
tcg_out_insn(s, RXY, LG, h->index, TCG_TMP0, TCG_REG_NONE,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_insn(s, RRE, ALGFR, h->index, addr_reg);
|
||||
h->base = TCG_REG_NONE;
|
||||
} else {
|
||||
h->base = addr_reg;
|
||||
}
|
||||
h->disp = 0;
|
||||
#else
|
||||
if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/* We are expecting a_bits to max out at 7, much lower than TMLL. */
|
||||
tcg_debug_assert(a_mask <= 0xffff);
|
||||
tcg_out_insn(s, RI, TMLL, addr_reg, a_mask);
|
||||
tcg_out_sh64(s, RSY_SRLG, TCG_TMP0, addr_reg, TCG_REG_NONE,
|
||||
s->page_bits - CPU_TLB_ENTRY_BITS);
|
||||
|
||||
tcg_out16(s, RI_BRC | (7 << 4)); /* CC in {1,2,3} */
|
||||
tcg_out_insn(s, RXY, NG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, mask_off);
|
||||
tcg_out_insn(s, RXY, AG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, table_off);
|
||||
|
||||
/*
|
||||
* For aligned accesses, we check the first byte and include the
|
||||
* alignment bits within the address. For unaligned access, we
|
||||
* check that we don't cross pages using the address of the last
|
||||
* byte of the access.
|
||||
*/
|
||||
a_off = (a_mask >= s_mask ? 0 : s_mask - a_mask);
|
||||
tlb_mask = (uint64_t)s->page_mask | a_mask;
|
||||
if (a_off == 0) {
|
||||
tgen_andi_risbg(s, TCG_REG_R0, addr_reg, tlb_mask);
|
||||
} else {
|
||||
tcg_out_insn(s, RX, LA, TCG_REG_R0, addr_reg, TCG_REG_NONE, a_off);
|
||||
tgen_andi(s, addr_type, TCG_REG_R0, tlb_mask);
|
||||
}
|
||||
|
||||
if (is_ld) {
|
||||
ofs = offsetof(CPUTLBEntry, addr_read);
|
||||
} else {
|
||||
ofs = offsetof(CPUTLBEntry, addr_write);
|
||||
}
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
ofs += HOST_BIG_ENDIAN * 4;
|
||||
tcg_out_insn(s, RX, C, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
|
||||
} else {
|
||||
tcg_out_insn(s, RXY, CG, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
|
||||
}
|
||||
|
||||
tcg_out16(s, RI_BRC | (S390_CC_NE << 4));
|
||||
ldst->label_ptr[0] = s->code_ptr++;
|
||||
}
|
||||
|
||||
h->base = addr_reg;
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ext32u(s, TCG_TMP0, addr_reg);
|
||||
h->base = TCG_TMP0;
|
||||
}
|
||||
if (guest_base < 0x80000) {
|
||||
h->index = TCG_REG_NONE;
|
||||
h->disp = guest_base;
|
||||
} else {
|
||||
h->index = TCG_GUEST_BASE_REG;
|
||||
h->index = TCG_TMP0;
|
||||
tcg_out_insn(s, RXY, LG, h->index, TCG_TMP0, TCG_REG_NONE,
|
||||
offsetof(CPUTLBEntry, addend));
|
||||
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_insn(s, RRE, ALGFR, h->index, addr_reg);
|
||||
h->base = TCG_REG_NONE;
|
||||
} else {
|
||||
h->base = addr_reg;
|
||||
}
|
||||
h->disp = 0;
|
||||
} else {
|
||||
if (a_mask) {
|
||||
ldst = new_ldst_label(s);
|
||||
ldst->is_ld = is_ld;
|
||||
ldst->oi = oi;
|
||||
ldst->addrlo_reg = addr_reg;
|
||||
|
||||
/* We are expecting a_bits to max out at 7, much lower than TMLL. */
|
||||
tcg_debug_assert(a_mask <= 0xffff);
|
||||
tcg_out_insn(s, RI, TMLL, addr_reg, a_mask);
|
||||
|
||||
tcg_out16(s, RI_BRC | (7 << 4)); /* CC in {1,2,3} */
|
||||
ldst->label_ptr[0] = s->code_ptr++;
|
||||
}
|
||||
|
||||
h->base = addr_reg;
|
||||
if (addr_type == TCG_TYPE_I32) {
|
||||
tcg_out_ext32u(s, TCG_TMP0, addr_reg);
|
||||
h->base = TCG_TMP0;
|
||||
}
|
||||
if (guest_base < 0x80000) {
|
||||
h->index = TCG_REG_NONE;
|
||||
h->disp = guest_base;
|
||||
} else {
|
||||
h->index = TCG_GUEST_BASE_REG;
|
||||
h->disp = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ldst;
|
||||
}
|
||||
@@ -3453,12 +3452,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
TCG_STATIC_CALL_ARGS_SIZE + TCG_TARGET_CALL_STACK_OFFSET,
|
||||
CPU_TEMP_BUF_NLONGS * sizeof(long));
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
if (guest_base >= 0x80000) {
|
||||
if (!tcg_use_softmmu && guest_base >= 0x80000) {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
|
||||
+17
-11
@@ -34,13 +34,13 @@
|
||||
|
||||
static void check_max_alignment(unsigned a_bits)
|
||||
{
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
/*
|
||||
* The requested alignment cannot overlap the TLB flags.
|
||||
* FIXME: Must keep the count up-to-date with "exec/cpu-all.h".
|
||||
*/
|
||||
tcg_debug_assert(a_bits + 5 <= tcg_ctx->page_bits);
|
||||
#endif
|
||||
if (tcg_use_softmmu) {
|
||||
tcg_debug_assert(a_bits + 5 <= tcg_ctx->page_bits);
|
||||
}
|
||||
}
|
||||
|
||||
static MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
|
||||
@@ -411,10 +411,11 @@ void tcg_gen_qemu_st_i64_chk(TCGv_i64 val, TCGTemp *addr, TCGArg idx,
|
||||
*/
|
||||
static bool use_two_i64_for_i128(MemOp mop)
|
||||
{
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
/* Two softmmu tlb lookups is larger than one function call. */
|
||||
return false;
|
||||
#else
|
||||
if (tcg_use_softmmu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* For user-only, two 64-bit operations may well be smaller than a call.
|
||||
* Determine if that would be legal for the requested atomicity.
|
||||
@@ -432,7 +433,6 @@ static bool use_two_i64_for_i128(MemOp mop)
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void canonicalize_memop_i128_as_i64(MemOp ret[2], MemOp orig)
|
||||
@@ -714,7 +714,7 @@ void tcg_gen_qemu_st_i128_chk(TCGv_i128 val, TCGTemp *addr, TCGArg idx,
|
||||
tcg_gen_qemu_st_i128_int(val, addr, idx, memop);
|
||||
}
|
||||
|
||||
static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
|
||||
void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
|
||||
{
|
||||
switch (opc & MO_SSIZE) {
|
||||
case MO_SB:
|
||||
@@ -729,13 +729,16 @@ static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, MemOp opc)
|
||||
case MO_UW:
|
||||
tcg_gen_ext16u_i32(ret, val);
|
||||
break;
|
||||
default:
|
||||
case MO_UL:
|
||||
case MO_SL:
|
||||
tcg_gen_mov_i32(ret, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
|
||||
void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
|
||||
{
|
||||
switch (opc & MO_SSIZE) {
|
||||
case MO_SB:
|
||||
@@ -756,9 +759,12 @@ static void tcg_gen_ext_i64(TCGv_i64 ret, TCGv_i64 val, MemOp opc)
|
||||
case MO_UL:
|
||||
tcg_gen_ext32u_i64(ret, val);
|
||||
break;
|
||||
default:
|
||||
case MO_UQ:
|
||||
case MO_SQ:
|
||||
tcg_gen_mov_i64(ret, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user