tcg-i386: Split out tlb load function.

Share some code between qemu_ld and qemu_st.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Richard Henderson 2010-05-21 09:03:03 -07:00 committed by Aurelien Jarno
parent 1a6dc1e406
commit 8516a04467

View File

@ -702,6 +702,74 @@ static void *qemu_st_helpers[4] = {
__stl_mmu,
__stq_mmu,
};
/* Perform the TLB load and compare.
Inputs:
ADDRLO_IDX contains the index into ARGS of the low part of the
address; the high part of the address is at ADDR_LOW_IDX+1.
MEM_INDEX and S_BITS are the memory context and log2 size of the load.
WHICH is the offset into the CPUTLBEntry structure of the slot to read.
This should be offsetof addr_read or addr_write.
Outputs:
LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
positions of the displacements of forward jumps to the TLB miss case.
EAX is loaded with the low part of the address. In the TLB hit case,
it has been adjusted as indicated by the TLB and so is a host address.
In the TLB miss case, it continues to hold a guest address.
EDX is clobbered. */
static void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
int s_bits, const TCGArg *args,
uint8_t **label_ptr, int which)
{
const int addrlo = args[addrlo_idx];
const int r0 = TCG_REG_EAX;
const int r1 = TCG_REG_EDX;
tcg_out_mov(s, r1, addrlo);
tcg_out_mov(s, r0, addrlo);
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
offsetof(CPUState, tlb_table[mem_index][0])
+ which);
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
tcg_out_mov(s, r0, addrlo);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[0] = s->code_ptr;
s->code_ptr++;
if (TARGET_LONG_BITS == 64) {
/* cmp 4(r1), addrhi */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[1] = s->code_ptr;
s->code_ptr++;
}
/* TLB Hit. */
/* add addend(r1), r0 */
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
offsetof(CPUTLBEntry, addend) - which);
}
#endif
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
@ -771,68 +839,29 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc)
{
int addr_reg, addr_reg2 = 0;
int data_reg, data_reg2 = 0;
int r0, r1, mem_index, s_bits;
int addrlo_idx;
#if defined(CONFIG_SOFTMMU)
int mem_index, s_bits;
uint8_t *label_ptr[3];
#endif
data_reg = *args++;
data_reg = args[0];
addrlo_idx = 1;
if (opc == 3) {
data_reg2 = *args++;
data_reg2 = args[1];
addrlo_idx = 2;
}
addr_reg = *args++;
if (TARGET_LONG_BITS == 64) {
addr_reg2 = *args++;
}
mem_index = *args;
s_bits = opc & 3;
r0 = TCG_REG_EAX;
r1 = TCG_REG_EDX;
#if defined(CONFIG_SOFTMMU)
tcg_out_mov(s, r1, addr_reg);
tcg_out_mov(s, r0, addr_reg);
mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
s_bits = opc & 3;
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
offsetof(CPUState,
tlb_table[mem_index][0].addr_read));
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
tcg_out_mov(s, r0, addr_reg);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[0] = s->code_ptr;
s->code_ptr++;
if (TARGET_LONG_BITS == 64) {
/* cmp 4(r1), addr_reg2 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[1] = s->code_ptr;
s->code_ptr++;
}
tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
label_ptr, offsetof(CPUTLBEntry, addr_read));
/* TLB Hit. */
/* add x(r1), r0 */
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_read));
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
@ -851,7 +880,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
#if TARGET_LONG_BITS == 32
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
#else
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
#endif
tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
@ -888,7 +917,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* label2: */
*label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
args[addrlo_idx], GUEST_BASE, opc);
#endif
}
@ -949,70 +979,30 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc)
{
int addr_reg, addr_reg2 = 0;
int data_reg, data_reg2 = 0;
int r0, r1, mem_index, s_bits;
int addrlo_idx;
#if defined(CONFIG_SOFTMMU)
int mem_index, s_bits;
int stack_adjust;
uint8_t *label_ptr[3];
#endif
data_reg = *args++;
data_reg = args[0];
addrlo_idx = 1;
if (opc == 3) {
data_reg2 = *args++;
data_reg2 = args[1];
addrlo_idx = 2;
}
addr_reg = *args++;
if (TARGET_LONG_BITS == 64) {
addr_reg2 = *args++;
}
mem_index = *args;
s_bits = opc;
r0 = TCG_REG_EAX;
r1 = TCG_REG_EDX;
#if defined(CONFIG_SOFTMMU)
tcg_out_mov(s, r1, addr_reg);
tcg_out_mov(s, r0, addr_reg);
mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
s_bits = opc;
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
offsetof(CPUState,
tlb_table[mem_index][0].addr_write));
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
tcg_out_mov(s, r0, addr_reg);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[0] = s->code_ptr;
s->code_ptr++;
if (TARGET_LONG_BITS == 64) {
/* cmp 4(r1), addr_reg2 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[1] = s->code_ptr;
s->code_ptr++;
}
tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
label_ptr, offsetof(CPUTLBEntry, addr_write));
/* TLB Hit. */
/* add x(r1), r0 */
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_write));
tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
@ -1051,13 +1041,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
}
#else
if (opc == 3) {
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
tcg_out_pushi(s, mem_index);
tcg_out_push(s, data_reg2);
tcg_out_push(s, data_reg);
stack_adjust = 12;
} else {
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
switch(opc) {
case 0:
tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
@ -1086,7 +1076,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* label2: */
*label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
tcg_out_qemu_st_direct(s, data_reg, data_reg2,
args[addrlo_idx], GUEST_BASE, opc);
#endif
}