tcg-i386: Split out TLB Hit path from qemu_ld/st.
Splitting out these functions will allow further cleanups. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
96b4cf38f0
commit
be5a4eb7f0
|
@ -704,9 +704,66 @@ static void *qemu_st_helpers[4] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
|
||||||
#define GUEST_BASE 0
|
int base, tcg_target_long ofs, int sizeop)
|
||||||
|
{
|
||||||
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
|
const int bswap = 1;
|
||||||
|
#else
|
||||||
|
const int bswap = 0;
|
||||||
#endif
|
#endif
|
||||||
|
switch (sizeop) {
|
||||||
|
case 0:
|
||||||
|
/* movzbl */
|
||||||
|
tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
|
||||||
|
break;
|
||||||
|
case 0 | 4:
|
||||||
|
/* movsbl */
|
||||||
|
tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* movzwl */
|
||||||
|
tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
|
||||||
|
if (bswap) {
|
||||||
|
tcg_out_rolw_8(s, datalo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1 | 4:
|
||||||
|
/* movswl */
|
||||||
|
tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs);
|
||||||
|
if (bswap) {
|
||||||
|
tcg_out_rolw_8(s, datalo);
|
||||||
|
tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
|
||||||
|
if (bswap) {
|
||||||
|
tcg_out_bswap32(s, datalo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (bswap) {
|
||||||
|
int t = datalo;
|
||||||
|
datalo = datahi;
|
||||||
|
datahi = t;
|
||||||
|
}
|
||||||
|
if (base != datalo) {
|
||||||
|
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
|
||||||
|
tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
|
||||||
|
} else {
|
||||||
|
tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
|
||||||
|
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
|
||||||
|
}
|
||||||
|
if (bswap) {
|
||||||
|
tcg_out_bswap32(s, datalo);
|
||||||
|
tcg_out_bswap32(s, datahi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
|
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
|
||||||
EAX. It will be useful once fixed registers globals are less
|
EAX. It will be useful once fixed registers globals are less
|
||||||
|
@ -714,7 +771,7 @@ static void *qemu_st_helpers[4] = {
|
||||||
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||||
int opc)
|
int opc)
|
||||||
{
|
{
|
||||||
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
|
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
uint8_t *label1_ptr, *label2_ptr;
|
uint8_t *label1_ptr, *label2_ptr;
|
||||||
#endif
|
#endif
|
||||||
|
@ -831,80 +888,74 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||||
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
|
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
|
||||||
offsetof(CPUTLBEntry, addend) -
|
offsetof(CPUTLBEntry, addend) -
|
||||||
offsetof(CPUTLBEntry, addr_read));
|
offsetof(CPUTLBEntry, addr_read));
|
||||||
#else
|
|
||||||
r0 = addr_reg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
|
||||||
bswap = 1;
|
|
||||||
|
/* label2: */
|
||||||
|
*label2_ptr = s->code_ptr - label2_ptr - 1;
|
||||||
#else
|
#else
|
||||||
bswap = 0;
|
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
|
||||||
#endif
|
#endif
|
||||||
switch(opc) {
|
}
|
||||||
|
|
||||||
|
static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
|
||||||
|
int base, tcg_target_long ofs, int sizeop)
|
||||||
|
{
|
||||||
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
|
const int bswap = 1;
|
||||||
|
#else
|
||||||
|
const int bswap = 0;
|
||||||
|
#endif
|
||||||
|
/* ??? Ideally we wouldn't need a scratch register. For user-only,
|
||||||
|
we could perform the bswap twice to restore the original value
|
||||||
|
instead of moving to the scratch. But as it is, the L constraint
|
||||||
|
means that EDX is definitely free here. */
|
||||||
|
int scratch = TCG_REG_EDX;
|
||||||
|
|
||||||
|
switch (sizeop) {
|
||||||
case 0:
|
case 0:
|
||||||
/* movzbl */
|
tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs);
|
||||||
tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE);
|
|
||||||
break;
|
|
||||||
case 0 | 4:
|
|
||||||
/* movsbl */
|
|
||||||
tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* movzwl */
|
|
||||||
tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE);
|
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_rolw_8(s, data_reg);
|
tcg_out_mov(s, scratch, datalo);
|
||||||
}
|
tcg_out_rolw_8(s, scratch);
|
||||||
break;
|
datalo = scratch;
|
||||||
case 1 | 4:
|
|
||||||
/* movswl */
|
|
||||||
tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE);
|
|
||||||
if (bswap) {
|
|
||||||
tcg_out_rolw_8(s, data_reg);
|
|
||||||
|
|
||||||
/* movswl data_reg, data_reg */
|
|
||||||
tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg);
|
|
||||||
}
|
}
|
||||||
|
/* movw */
|
||||||
|
tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
|
||||||
|
datalo, base, ofs);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
|
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap32(s, data_reg);
|
tcg_out_mov(s, scratch, datalo);
|
||||||
|
tcg_out_bswap32(s, scratch);
|
||||||
|
datalo = scratch;
|
||||||
}
|
}
|
||||||
|
tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
int t = data_reg;
|
tcg_out_mov(s, scratch, datahi);
|
||||||
data_reg = data_reg2;
|
tcg_out_bswap32(s, scratch);
|
||||||
data_reg2 = t;
|
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
|
||||||
}
|
tcg_out_mov(s, scratch, datalo);
|
||||||
if (r0 != data_reg) {
|
tcg_out_bswap32(s, scratch);
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
|
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
|
|
||||||
} else {
|
} else {
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
|
tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
|
||||||
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
|
tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
|
||||||
}
|
|
||||||
if (bswap) {
|
|
||||||
tcg_out_bswap32(s, data_reg);
|
|
||||||
tcg_out_bswap32(s, data_reg2);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
tcg_abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
|
||||||
/* label2: */
|
|
||||||
*label2_ptr = s->code_ptr - label2_ptr - 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||||
int opc)
|
int opc)
|
||||||
{
|
{
|
||||||
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
|
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
int stack_adjust;
|
int stack_adjust;
|
||||||
uint8_t *label1_ptr, *label2_ptr;
|
uint8_t *label1_ptr, *label2_ptr;
|
||||||
|
@ -1041,57 +1092,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||||
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
|
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
|
||||||
offsetof(CPUTLBEntry, addend) -
|
offsetof(CPUTLBEntry, addend) -
|
||||||
offsetof(CPUTLBEntry, addr_write));
|
offsetof(CPUTLBEntry, addr_write));
|
||||||
#else
|
|
||||||
r0 = addr_reg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
|
||||||
bswap = 1;
|
|
||||||
#else
|
|
||||||
bswap = 0;
|
|
||||||
#endif
|
|
||||||
switch(opc) {
|
|
||||||
case 0:
|
|
||||||
tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (bswap) {
|
|
||||||
tcg_out_mov(s, r1, data_reg);
|
|
||||||
tcg_out_rolw_8(s, r1);
|
|
||||||
data_reg = r1;
|
|
||||||
}
|
|
||||||
/* movw */
|
|
||||||
tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
|
|
||||||
data_reg, r0, GUEST_BASE);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (bswap) {
|
|
||||||
tcg_out_mov(s, r1, data_reg);
|
|
||||||
tcg_out_bswap32(s, r1);
|
|
||||||
data_reg = r1;
|
|
||||||
}
|
|
||||||
tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (bswap) {
|
|
||||||
tcg_out_mov(s, r1, data_reg2);
|
|
||||||
tcg_out_bswap32(s, r1);
|
|
||||||
tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
|
|
||||||
tcg_out_mov(s, r1, data_reg);
|
|
||||||
tcg_out_bswap32(s, r1);
|
|
||||||
tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
|
|
||||||
} else {
|
|
||||||
tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
|
|
||||||
tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
|
||||||
/* label2: */
|
/* label2: */
|
||||||
*label2_ptr = s->code_ptr - label2_ptr - 1;
|
*label2_ptr = s->code_ptr - label2_ptr - 1;
|
||||||
|
#else
|
||||||
|
tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue