cpu: Move the softmmu tlb to CPUNegativeOffsetState
We have for some time had code within the tcg backends to handle large positive offsets from env. This move makes sure that need not happen. Indeed, we are able to assert at build time that simple offsets suffice for all hosts. Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
5e1401969b
commit
269bd5d8f6
@ -429,4 +429,15 @@ static inline CPUNegativeOffsetState *cpu_neg(CPUState *cpu)
|
|||||||
return &arch_cpu->neg;
|
return &arch_cpu->neg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* env_tlb(env)
|
||||||
|
* @env: The architecture environment
|
||||||
|
*
|
||||||
|
* Return the CPUTLB state associated with the environment.
|
||||||
|
*/
|
||||||
|
static inline CPUTLB *env_tlb(CPUArchState *env)
|
||||||
|
{
|
||||||
|
return &env_neg(env)->tlb;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CPU_ALL_H */
|
#endif /* CPU_ALL_H */
|
||||||
|
@ -178,13 +178,14 @@ typedef struct CPUTLBDesc {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Data elements that are per MMU mode, accessed by the fast path.
|
* Data elements that are per MMU mode, accessed by the fast path.
|
||||||
|
* The structure is aligned to aid loading the pair with one insn.
|
||||||
*/
|
*/
|
||||||
typedef struct CPUTLBDescFast {
|
typedef struct CPUTLBDescFast {
|
||||||
/* Contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */
|
/* Contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */
|
||||||
uintptr_t mask;
|
uintptr_t mask;
|
||||||
/* The array of tlb entries itself. */
|
/* The array of tlb entries itself. */
|
||||||
CPUTLBEntry *table;
|
CPUTLBEntry *table;
|
||||||
} CPUTLBDescFast;
|
} CPUTLBDescFast QEMU_ALIGNED(2 * sizeof(void *));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data elements that are shared between all MMU modes.
|
* Data elements that are shared between all MMU modes.
|
||||||
@ -211,28 +212,33 @@ typedef struct CPUTLBCommon {
|
|||||||
/*
|
/*
|
||||||
* The entire softmmu tlb, for all MMU modes.
|
* The entire softmmu tlb, for all MMU modes.
|
||||||
* The meaning of each of the MMU modes is defined in the target code.
|
* The meaning of each of the MMU modes is defined in the target code.
|
||||||
|
* Since this is placed within CPUNegativeOffsetState, the smallest
|
||||||
|
* negative offsets are at the end of the struct.
|
||||||
*/
|
*/
|
||||||
typedef struct CPUTLB {
|
typedef struct CPUTLB {
|
||||||
CPUTLBDescFast f[NB_MMU_MODES];
|
|
||||||
CPUTLBDesc d[NB_MMU_MODES];
|
|
||||||
CPUTLBCommon c;
|
CPUTLBCommon c;
|
||||||
|
CPUTLBDesc d[NB_MMU_MODES];
|
||||||
|
CPUTLBDescFast f[NB_MMU_MODES];
|
||||||
} CPUTLB;
|
} CPUTLB;
|
||||||
|
|
||||||
/* There are target-specific members named "tlb". This is temporary. */
|
/* This will be used by TCG backends to compute offsets. */
|
||||||
#define CPU_COMMON CPUTLB tlb_;
|
#define TLB_MASK_TABLE_OFS(IDX) \
|
||||||
#define env_tlb(ENV) (&(ENV)->tlb_)
|
((int)offsetof(ArchCPU, neg.tlb.f[IDX]) - (int)offsetof(ArchCPU, env))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define CPU_COMMON /* Nothing */
|
typedef struct CPUTLB { } CPUTLB;
|
||||||
|
|
||||||
#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */
|
#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */
|
||||||
|
|
||||||
|
#define CPU_COMMON /* Nothing */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure must be placed in ArchCPU immedately
|
* This structure must be placed in ArchCPU immedately
|
||||||
* before CPUArchState, as a field named "neg".
|
* before CPUArchState, as a field named "neg".
|
||||||
*/
|
*/
|
||||||
typedef struct CPUNegativeOffsetState {
|
typedef struct CPUNegativeOffsetState {
|
||||||
|
CPUTLB tlb;
|
||||||
IcountDecr icount_decr;
|
IcountDecr icount_decr;
|
||||||
} CPUNegativeOffsetState;
|
} CPUNegativeOffsetState;
|
||||||
|
|
||||||
|
@ -1637,9 +1637,9 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
|
|||||||
label->label_ptr[0] = label_ptr;
|
label->label_ptr[0] = label_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We expect to use a 24-bit unsigned offset from ENV. */
|
/* We expect to use a 7-bit scaled negative offset from ENV. */
|
||||||
QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_.f[NB_MMU_MODES - 1].table)
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
> 0xffffff);
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -512);
|
||||||
|
|
||||||
/* Load and compare a TLB entry, emitting the conditional jump to the
|
/* Load and compare a TLB entry, emitting the conditional jump to the
|
||||||
slow path for the failure case, which will be patched later when finalizing
|
slow path for the failure case, which will be patched later when finalizing
|
||||||
@ -1649,8 +1649,9 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp opc,
|
|||||||
tcg_insn_unit **label_ptr, int mem_index,
|
tcg_insn_unit **label_ptr, int mem_index,
|
||||||
bool is_read)
|
bool is_read)
|
||||||
{
|
{
|
||||||
int mask_ofs = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
int table_ofs = offsetof(CPUArchState, tlb_.f[mem_index].table);
|
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
|
||||||
|
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
|
||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
unsigned s_bits = opc & MO_SIZE;
|
unsigned s_bits = opc & MO_SIZE;
|
||||||
unsigned a_mask = (1u << a_bits) - 1;
|
unsigned a_mask = (1u << a_bits) - 1;
|
||||||
@ -1659,24 +1660,6 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp opc,
|
|||||||
TCGType mask_type;
|
TCGType mask_type;
|
||||||
uint64_t compare_mask;
|
uint64_t compare_mask;
|
||||||
|
|
||||||
if (table_ofs > 0xfff) {
|
|
||||||
int table_hi = table_ofs & ~0xfff;
|
|
||||||
int mask_hi = mask_ofs & ~0xfff;
|
|
||||||
|
|
||||||
table_base = TCG_REG_X1;
|
|
||||||
if (mask_hi == table_hi) {
|
|
||||||
mask_base = table_base;
|
|
||||||
} else if (mask_hi) {
|
|
||||||
mask_base = TCG_REG_X0;
|
|
||||||
tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64,
|
|
||||||
mask_base, TCG_AREG0, mask_hi);
|
|
||||||
}
|
|
||||||
tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64,
|
|
||||||
table_base, TCG_AREG0, table_hi);
|
|
||||||
mask_ofs -= mask_hi;
|
|
||||||
table_ofs -= table_hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask_type = (TARGET_PAGE_BITS + CPU_TLB_DYN_MAX_BITS > 32
|
mask_type = (TARGET_PAGE_BITS + CPU_TLB_DYN_MAX_BITS > 32
|
||||||
? TCG_TYPE_I64 : TCG_TYPE_I32);
|
? TCG_TYPE_I64 : TCG_TYPE_I32);
|
||||||
|
|
||||||
|
@ -1220,9 +1220,9 @@ static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
|
|||||||
|
|
||||||
#define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
|
#define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
|
||||||
|
|
||||||
/* We expect to use a 20-bit unsigned offset from ENV. */
|
/* We expect to use an 9-bit sign-magnitude negative offset from ENV. */
|
||||||
QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_.f[NB_MMU_MODES - 1].table)
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
> 0xfffff);
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -256);
|
||||||
|
|
||||||
/* Load and compare a TLB entry, leaving the flags set. Returns the register
|
/* Load and compare a TLB entry, leaving the flags set. Returns the register
|
||||||
containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
|
containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
|
||||||
@ -1232,39 +1232,15 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
|||||||
{
|
{
|
||||||
int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
|
int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
|
||||||
: offsetof(CPUTLBEntry, addr_write));
|
: offsetof(CPUTLBEntry, addr_write));
|
||||||
int mask_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
int table_off = offsetof(CPUArchState, tlb_.f[mem_index].table);
|
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||||
TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
|
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||||
unsigned s_bits = opc & MO_SIZE;
|
unsigned s_bits = opc & MO_SIZE;
|
||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
|
|
||||||
if (table_off > 0xfff) {
|
|
||||||
int mask_hi = mask_off & ~0xfff;
|
|
||||||
int table_hi = table_off & ~0xfff;
|
|
||||||
int rot;
|
|
||||||
|
|
||||||
table_base = TCG_REG_R2;
|
|
||||||
if (mask_hi == table_hi) {
|
|
||||||
mask_base = table_base;
|
|
||||||
} else if (mask_hi) {
|
|
||||||
mask_base = TCG_REG_TMP;
|
|
||||||
rot = encode_imm(mask_hi);
|
|
||||||
assert(rot >= 0);
|
|
||||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, mask_base, TCG_AREG0,
|
|
||||||
rotl(mask_hi, rot) | (rot << 7));
|
|
||||||
}
|
|
||||||
rot = encode_imm(table_hi);
|
|
||||||
assert(rot >= 0);
|
|
||||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, table_base, TCG_AREG0,
|
|
||||||
rotl(table_hi, rot) | (rot << 7));
|
|
||||||
|
|
||||||
mask_off -= mask_hi;
|
|
||||||
table_off -= table_hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP, mask_base, mask_off);
|
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP, TCG_AREG0, mask_off);
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R2, table_base, table_off);
|
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R2, TCG_AREG0, table_off);
|
||||||
|
|
||||||
/* Extract the tlb index from the address into TMP. */
|
/* Extract the tlb index from the address into TMP. */
|
||||||
tcg_out_dat_reg(s, COND_AL, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, addrlo,
|
tcg_out_dat_reg(s, COND_AL, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, addrlo,
|
||||||
|
@ -1730,10 +1730,12 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
|||||||
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
|
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
|
||||||
|
|
||||||
tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, r0, TCG_AREG0,
|
tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, r0, TCG_AREG0,
|
||||||
offsetof(CPUArchState, tlb_.f[mem_index].mask));
|
TLB_MASK_TABLE_OFS(mem_index) +
|
||||||
|
offsetof(CPUTLBDescFast, mask));
|
||||||
|
|
||||||
tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r0, TCG_AREG0,
|
tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r0, TCG_AREG0,
|
||||||
offsetof(CPUArchState, tlb_.f[mem_index].table));
|
TLB_MASK_TABLE_OFS(mem_index) +
|
||||||
|
offsetof(CPUTLBDescFast, table));
|
||||||
|
|
||||||
/* If the required alignment is at least as large as the access, simply
|
/* 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
|
copy the address and mask. For lesser alignments, check that we don't
|
||||||
|
@ -1202,6 +1202,10 @@ static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We expect to use a 16-bit negative offset from ENV. */
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -32768);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform the tlb comparison operation.
|
* Perform the tlb comparison operation.
|
||||||
* The complete host address is placed in BASE.
|
* The complete host address is placed in BASE.
|
||||||
@ -1215,42 +1219,17 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
|
|||||||
unsigned s_bits = opc & MO_SIZE;
|
unsigned s_bits = opc & MO_SIZE;
|
||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
int mem_index = get_mmuidx(oi);
|
int mem_index = get_mmuidx(oi);
|
||||||
int mask_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
int table_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||||
|
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||||
int add_off = offsetof(CPUTLBEntry, addend);
|
int add_off = offsetof(CPUTLBEntry, addend);
|
||||||
int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
|
int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
|
||||||
: offsetof(CPUTLBEntry, addr_write));
|
: offsetof(CPUTLBEntry, addr_write));
|
||||||
TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
|
|
||||||
target_ulong mask;
|
target_ulong mask;
|
||||||
|
|
||||||
if (table_off > 0x7fff) {
|
|
||||||
int mask_hi = mask_off - (int16_t)mask_off;
|
|
||||||
int table_hi = table_off - (int16_t)table_off;
|
|
||||||
|
|
||||||
table_base = TCG_TMP1;
|
|
||||||
if (likely(mask_hi == table_hi)) {
|
|
||||||
mask_base = table_base;
|
|
||||||
tcg_out_opc_imm(s, OPC_LUI, mask_base, TCG_REG_ZERO, mask_hi >> 16);
|
|
||||||
tcg_out_opc_reg(s, ALIAS_PADD, mask_base, mask_base, TCG_AREG0);
|
|
||||||
mask_off -= mask_hi;
|
|
||||||
table_off -= mask_hi;
|
|
||||||
} else {
|
|
||||||
if (mask_hi != 0) {
|
|
||||||
mask_base = TCG_TMP0;
|
|
||||||
tcg_out_opc_imm(s, OPC_LUI,
|
|
||||||
mask_base, TCG_REG_ZERO, mask_hi >> 16);
|
|
||||||
tcg_out_opc_reg(s, ALIAS_PADD,
|
|
||||||
mask_base, mask_base, TCG_AREG0);
|
|
||||||
}
|
|
||||||
table_off -= mask_off;
|
|
||||||
mask_off -= mask_hi;
|
|
||||||
tcg_out_opc_imm(s, ALIAS_PADDI, table_base, mask_base, mask_off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, mask_base, mask_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, table_base, table_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
|
||||||
|
|
||||||
/* Extract the TLB index from the address into TMP3. */
|
/* Extract the TLB index from the address into TMP3. */
|
||||||
tcg_out_opc_sa(s, ALIAS_TSRL, TCG_TMP3, addrl,
|
tcg_out_opc_sa(s, ALIAS_TSRL, TCG_TMP3, addrl,
|
||||||
|
@ -1498,6 +1498,10 @@ static void * const qemu_st_helpers[16] = {
|
|||||||
[MO_BEQ] = helper_be_stq_mmu,
|
[MO_BEQ] = helper_be_stq_mmu,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* We expect to use a 16-bit negative offset from ENV. */
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -32768);
|
||||||
|
|
||||||
/* Perform the TLB load and compare. Places the result of the comparison
|
/* Perform the TLB load and compare. Places the result of the comparison
|
||||||
in CR7, loads the addend of the TLB into R3, and returns the register
|
in CR7, loads the addend of the TLB into R3, and returns the register
|
||||||
containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
|
containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
|
||||||
@ -1510,31 +1514,15 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp opc,
|
|||||||
= (is_read
|
= (is_read
|
||||||
? offsetof(CPUTLBEntry, addr_read)
|
? offsetof(CPUTLBEntry, addr_read)
|
||||||
: offsetof(CPUTLBEntry, addr_write));
|
: offsetof(CPUTLBEntry, addr_write));
|
||||||
int mask_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
int table_off = offsetof(CPUArchState, tlb_.f[mem_index].table);
|
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||||
TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
|
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||||
unsigned s_bits = opc & MO_SIZE;
|
unsigned s_bits = opc & MO_SIZE;
|
||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
|
|
||||||
if (table_off > 0x7fff) {
|
|
||||||
int mask_hi = mask_off - (int16_t)mask_off;
|
|
||||||
int table_hi = table_off - (int16_t)table_off;
|
|
||||||
|
|
||||||
table_base = TCG_REG_R4;
|
|
||||||
if (mask_hi == table_hi) {
|
|
||||||
mask_base = table_base;
|
|
||||||
} else if (mask_hi) {
|
|
||||||
mask_base = TCG_REG_R3;
|
|
||||||
tcg_out32(s, ADDIS | TAI(mask_base, TCG_AREG0, mask_hi >> 16));
|
|
||||||
}
|
|
||||||
tcg_out32(s, ADDIS | TAI(table_base, TCG_AREG0, table_hi >> 16));
|
|
||||||
mask_off -= mask_hi;
|
|
||||||
table_off -= table_hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, mask_base, mask_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0, mask_off);
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R4, table_base, table_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R4, TCG_AREG0, table_off);
|
||||||
|
|
||||||
/* Extract the page index, shifted into place for tlb index. */
|
/* Extract the page index, shifted into place for tlb index. */
|
||||||
if (TCG_TARGET_REG_BITS == 32) {
|
if (TCG_TARGET_REG_BITS == 32) {
|
||||||
|
@ -962,6 +962,10 @@ static void * const qemu_st_helpers[16] = {
|
|||||||
/* We don't support oversize guests */
|
/* We don't support oversize guests */
|
||||||
QEMU_BUILD_BUG_ON(TCG_TARGET_REG_BITS < TARGET_LONG_BITS);
|
QEMU_BUILD_BUG_ON(TCG_TARGET_REG_BITS < TARGET_LONG_BITS);
|
||||||
|
|
||||||
|
/* We expect to use a 12-bit negative offset from ENV. */
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
|
||||||
|
|
||||||
static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl,
|
static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl,
|
||||||
TCGReg addrh, TCGMemOpIdx oi,
|
TCGReg addrh, TCGMemOpIdx oi,
|
||||||
tcg_insn_unit **label_ptr, bool is_load)
|
tcg_insn_unit **label_ptr, bool is_load)
|
||||||
@ -971,32 +975,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl,
|
|||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
tcg_target_long compare_mask;
|
tcg_target_long compare_mask;
|
||||||
int mem_index = get_mmuidx(oi);
|
int mem_index = get_mmuidx(oi);
|
||||||
int mask_off, table_off;
|
int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
|
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
|
||||||
|
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
|
||||||
TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
|
TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
|
||||||
|
|
||||||
mask_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
|
||||||
table_off = offsetof(CPUArchState, tlb_.f[mem_index].table);
|
|
||||||
if (table_off > 0x7ff) {
|
|
||||||
int mask_hi = mask_off - sextreg(mask_off, 0, 12);
|
|
||||||
int table_hi = table_off - sextreg(table_off, 0, 12);
|
|
||||||
|
|
||||||
if (likely(mask_hi == table_hi)) {
|
|
||||||
mask_base = table_base = TCG_REG_TMP1;
|
|
||||||
tcg_out_opc_upper(s, OPC_LUI, mask_base, mask_hi);
|
|
||||||
tcg_out_opc_reg(s, OPC_ADD, mask_base, mask_base, TCG_AREG0);
|
|
||||||
mask_off -= mask_hi;
|
|
||||||
table_off -= mask_hi;
|
|
||||||
} else {
|
|
||||||
mask_base = TCG_REG_TMP0;
|
|
||||||
table_base = TCG_REG_TMP1;
|
|
||||||
tcg_out_opc_upper(s, OPC_LUI, mask_base, mask_hi);
|
|
||||||
tcg_out_opc_reg(s, OPC_ADD, mask_base, mask_base, TCG_AREG0);
|
|
||||||
table_off -= mask_off;
|
|
||||||
mask_off -= mask_hi;
|
|
||||||
tcg_out_opc_imm(s, OPC_ADDI, table_base, mask_base, mask_off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, mask_base, mask_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, mask_base, mask_off);
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, table_base, table_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, table_base, table_off);
|
||||||
|
|
||||||
|
@ -1538,9 +1538,9 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp opc, TCGReg data,
|
|||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
#include "tcg-ldst.inc.c"
|
#include "tcg-ldst.inc.c"
|
||||||
|
|
||||||
/* We're expecting to use a 20-bit signed offset on the tlb memory ops. */
|
/* We're expecting to use a 20-bit negative offset on the tlb memory ops. */
|
||||||
QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_.f[NB_MMU_MODES - 1].table)
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
> 0x7ffff);
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 19));
|
||||||
|
|
||||||
/* Load and compare a TLB entry, leaving the flags set. Loads the TLB
|
/* Load and compare a TLB entry, leaving the flags set. Loads the TLB
|
||||||
addend into R2. Returns a register with the santitized guest address. */
|
addend into R2. Returns a register with the santitized guest address. */
|
||||||
@ -1551,8 +1551,9 @@ static TCGReg tcg_out_tlb_read(TCGContext* s, TCGReg addr_reg, TCGMemOp opc,
|
|||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
unsigned s_mask = (1 << s_bits) - 1;
|
unsigned s_mask = (1 << s_bits) - 1;
|
||||||
unsigned a_mask = (1 << a_bits) - 1;
|
unsigned a_mask = (1 << a_bits) - 1;
|
||||||
int mask_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
int table_off = offsetof(CPUArchState, tlb_.f[mem_index].table);
|
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||||
|
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||||
int ofs, a_off;
|
int ofs, a_off;
|
||||||
uint64_t tlb_mask;
|
uint64_t tlb_mask;
|
||||||
|
|
||||||
|
@ -1062,6 +1062,11 @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
|
|
||||||
|
/* We expect to use a 13-bit negative offset from ENV. */
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
|
||||||
|
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 12));
|
||||||
|
|
||||||
/* Perform the TLB load and compare.
|
/* Perform the TLB load and compare.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
@ -1078,9 +1083,9 @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
|
|||||||
static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
|
static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
|
||||||
TCGMemOp opc, int which)
|
TCGMemOp opc, int which)
|
||||||
{
|
{
|
||||||
int mask_off = offsetof(CPUArchState, tlb_.f[mem_index].mask);
|
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
|
||||||
int table_off = offsetof(CPUArchState, tlb_.f[mem_index].table);
|
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
|
||||||
TCGReg base = TCG_AREG0;
|
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
|
||||||
const TCGReg r0 = TCG_REG_O0;
|
const TCGReg r0 = TCG_REG_O0;
|
||||||
const TCGReg r1 = TCG_REG_O1;
|
const TCGReg r1 = TCG_REG_O1;
|
||||||
const TCGReg r2 = TCG_REG_O2;
|
const TCGReg r2 = TCG_REG_O2;
|
||||||
@ -1088,26 +1093,9 @@ static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
|
|||||||
unsigned a_bits = get_alignment_bits(opc);
|
unsigned a_bits = get_alignment_bits(opc);
|
||||||
tcg_target_long compare_mask;
|
tcg_target_long compare_mask;
|
||||||
|
|
||||||
if (!check_fit_i32(table_off, 13)) {
|
|
||||||
int table_hi;
|
|
||||||
|
|
||||||
base = r1;
|
|
||||||
if (table_off <= 2 * 0xfff) {
|
|
||||||
table_hi = 0xfff;
|
|
||||||
tcg_out_arithi(s, base, TCG_AREG0, table_hi, ARITH_ADD);
|
|
||||||
} else {
|
|
||||||
table_hi = table_off & ~0x3ff;
|
|
||||||
tcg_out_sethi(s, base, table_hi);
|
|
||||||
tcg_out_arith(s, base, TCG_AREG0, base, ARITH_ADD);
|
|
||||||
}
|
|
||||||
mask_off -= table_hi;
|
|
||||||
table_off -= table_hi;
|
|
||||||
tcg_debug_assert(check_fit_i32(mask_off, 13));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, r0, base, mask_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, r0, TCG_AREG0, mask_off);
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, r1, base, table_off);
|
tcg_out_ld(s, TCG_TYPE_PTR, r1, TCG_AREG0, table_off);
|
||||||
|
|
||||||
/* Extract the page index, shifted into place for tlb index. */
|
/* Extract the page index, shifted into place for tlb index. */
|
||||||
tcg_out_arithi(s, r2, addr, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
|
tcg_out_arithi(s, r2, addr, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
|
||||||
|
Loading…
Reference in New Issue
Block a user