[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH for-4.0 v2 32/37] tcg/arm: Set TCG_TARGET_HAS_MEMORY
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH for-4.0 v2 32/37] tcg/arm: Set TCG_TARGET_HAS_MEMORY_BSWAP to false for user-only |
Date: |
Fri, 23 Nov 2018 15:45:53 +0100 |
Letting the generic code emit any bswaps allows us to avoid reserving
an extra register for CONFIG_USER_ONLY. For SOFTMMU, where we have
free call-clobbered registers anyway, leaving the bswap in the out-of-line
thunk maximizes code sharing.
Signed-off-by: Richard Henderson <address@hidden>
---
tcg/arm/tcg-target.h | 4 ++
tcg/arm/tcg-target.inc.c | 129 +++++++++++++--------------------------
2 files changed, 48 insertions(+), 85 deletions(-)
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 7a4c55d66d..a05310a684 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -131,7 +131,11 @@ enum {
};
#define TCG_TARGET_DEFAULT_MO (0)
+#ifdef CONFIG_SOFTMMU
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
+#else
+#define TCG_TARGET_HAS_MEMORY_BSWAP 0
+#endif
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
{
diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
index 5a15f6a546..898701f105 100644
--- a/tcg/arm/tcg-target.inc.c
+++ b/tcg/arm/tcg-target.inc.c
@@ -270,15 +270,6 @@ static const char
*target_parse_constraint(TCGArgConstraint *ct,
ct->u.regs = 0xffff;
break;
- /* qemu_st address & data */
- case 's':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffff;
- /* r0-r1 doing the byte swapping, so don't use these */
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
- break;
-
default:
return NULL;
}
@@ -1363,6 +1354,7 @@ static inline void tcg_out_qemu_ld_index(TCGContext *s,
TCGMemOp opc,
TCGReg addrlo, TCGReg addend)
{
TCGMemOp bswap = opc & MO_BSWAP;
+ assert(USING_SOFTMMU || !bswap);
switch (opc & MO_SSIZE) {
case MO_UB:
@@ -1386,7 +1378,6 @@ static inline void tcg_out_qemu_ld_index(TCGContext *s,
TCGMemOp opc,
}
break;
case MO_UL:
- default:
tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
if (bswap) {
tcg_out_bswap32(s, COND_AL, datalo, datalo);
@@ -1416,6 +1407,8 @@ static inline void tcg_out_qemu_ld_index(TCGContext *s,
TCGMemOp opc,
}
}
break;
+ default:
+ g_assert_not_reached();
}
}
@@ -1424,6 +1417,7 @@ static inline void tcg_out_qemu_ld_direct(TCGContext *s,
TCGMemOp opc,
TCGReg addrlo)
{
TCGMemOp bswap = opc & MO_BSWAP;
+ assert(!USING_SOFTMMU && !bswap);
switch (opc & MO_SSIZE) {
case MO_UB:
@@ -1434,47 +1428,24 @@ static inline void tcg_out_qemu_ld_direct(TCGContext
*s, TCGMemOp opc,
break;
case MO_UW:
tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
- if (bswap) {
- tcg_out_bswap16(s, COND_AL, datalo, datalo);
- }
break;
case MO_SW:
- if (bswap) {
- tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
- tcg_out_bswap16s(s, COND_AL, datalo, datalo);
- } else {
- tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
- }
+ tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
break;
case MO_UL:
- default:
tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
- if (bswap) {
- tcg_out_bswap32(s, COND_AL, datalo, datalo);
- }
break;
case MO_Q:
- {
- TCGReg dl = (bswap ? datahi : datalo);
- TCGReg dh = (bswap ? datalo : datahi);
-
- /* Avoid ldrd for user-only emulation, to handle unaligned. */
- if (USING_SOFTMMU && use_armv6_instructions
- && (dl & 1) == 0 && dh == dl + 1) {
- tcg_out_ldrd_8(s, COND_AL, dl, addrlo, 0);
- } else if (dl == addrlo) {
- tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
- tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
- } else {
- tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
- tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
- }
- if (bswap) {
- tcg_out_bswap32(s, COND_AL, dl, dl);
- tcg_out_bswap32(s, COND_AL, dh, dh);
- }
+ if (datalo == addrlo) {
+ tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4);
+ tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
+ } else {
+ tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
+ tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4);
}
break;
+ default:
+ g_assert_not_reached();
}
}
@@ -1485,19 +1456,18 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg
*args, bool is64)
TCGReg datalo __attribute__((unused));
TCGReg datahi __attribute__((unused));
TCGMemOpIdx oi;
- TCGMemOp opc;
datalo = *args++;
datahi = (is64 ? *args++ : 0);
addrlo = *args++;
addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
oi = *args++;
- opc = get_memop(oi);
#ifdef CONFIG_SOFTMMU
add_ldst_ool_label(s, true, is64, oi, R_ARM_PC24, 0);
tcg_out_bl_noaddr(s, COND_AL);
#else
+ TCGMemOp opc = get_memop(oi);
if (guest_base) {
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, TCG_REG_TMP);
@@ -1512,6 +1482,7 @@ static inline void tcg_out_qemu_st_index(TCGContext *s,
int cond, TCGMemOp opc,
TCGReg addrlo, TCGReg addend)
{
TCGMemOp bswap = opc & MO_BSWAP;
+ assert(USING_SOFTMMU || !bswap);
switch (opc & MO_SIZE) {
case MO_8:
@@ -1526,7 +1497,6 @@ static inline void tcg_out_qemu_st_index(TCGContext *s,
int cond, TCGMemOp opc,
}
break;
case MO_32:
- default:
if (bswap) {
tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
tcg_out_st32_r(s, cond, TCG_REG_R0, addrlo, addend);
@@ -1535,20 +1505,32 @@ static inline void tcg_out_qemu_st_index(TCGContext *s,
int cond, TCGMemOp opc,
}
break;
case MO_64:
- /* Avoid strd for user-only emulation, to handle unaligned. */
if (bswap) {
- tcg_out_bswap32(s, cond, TCG_REG_R0, datahi);
- tcg_out_st32_rwb(s, cond, TCG_REG_R0, addend, addrlo);
- tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
- tcg_out_st32_12(s, cond, TCG_REG_R0, addend, 4);
- } else if (USING_SOFTMMU && use_armv6_instructions
- && (datalo & 1) == 0 && datahi == datalo + 1) {
+ /*
+ * Assert inputs are where I think, for the softmmu thunk.
+ * One pair of R0/R1 or R2/R3 will be free and call-clobbered,
+ * which allows the use of STRD below. Note the bswaps also
+ * reverse the lo/hi registers to swap the two words.
+ */
+ tcg_debug_assert(addend == TCG_REG_TMP);
+ tcg_debug_assert(datalo == TCG_REG_R4);
+ tcg_debug_assert(datahi == TCG_REG_R5);
+ datalo = addrlo == TCG_REG_R1 ? TCG_REG_R2 : TCG_REG_R0;
+ datahi = datalo + 1;
+ tcg_out_bswap32(s, cond, datalo, TCG_REG_R5);
+ tcg_out_bswap32(s, cond, datahi, TCG_REG_R4);
+ }
+ /* Avoid strd for user-only emulation, to handle unaligned. */
+ if (USING_SOFTMMU && use_armv6_instructions
+ && (datalo & 1) == 0 && datahi == datalo + 1) {
tcg_out_strd_r(s, cond, datalo, addrlo, addend);
} else {
tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
tcg_out_st32_12(s, cond, datahi, addend, 4);
}
break;
+ default:
+ g_assert_not_reached();
}
}
@@ -1557,43 +1539,25 @@ static inline void tcg_out_qemu_st_direct(TCGContext
*s, TCGMemOp opc,
TCGReg addrlo)
{
TCGMemOp bswap = opc & MO_BSWAP;
+ assert(!USING_SOFTMMU && !bswap);
switch (opc & MO_SIZE) {
case MO_8:
tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
break;
case MO_16:
- if (bswap) {
- tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
- tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
- } else {
- tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
- }
+ tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
break;
case MO_32:
- default:
- if (bswap) {
- tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
- tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
- } else {
- tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
- }
+ tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
break;
case MO_64:
/* Avoid strd for user-only emulation, to handle unaligned. */
- if (bswap) {
- tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datahi);
- tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
- tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
- tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 4);
- } else if (USING_SOFTMMU && use_armv6_instructions
- && (datalo & 1) == 0 && datahi == datalo + 1) {
- tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
- } else {
- tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
- tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
- }
+ tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
+ tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
break;
+ default:
+ g_assert_not_reached();
}
}
@@ -1604,19 +1568,18 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg
*args, bool is64)
TCGReg datalo __attribute__((unused));
TCGReg datahi __attribute__((unused));
TCGMemOpIdx oi;
- TCGMemOp opc;
datalo = *args++;
datahi = (is64 ? *args++ : 0);
addrlo = *args++;
addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
oi = *args++;
- opc = get_memop(oi);
#ifdef CONFIG_SOFTMMU
add_ldst_ool_label(s, false, is64, oi, R_ARM_PC24, 0);
tcg_out_bl_noaddr(s, COND_AL);
#else
+ TCGMemOp opc = get_memop(oi);
if (guest_base) {
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
@@ -2055,11 +2018,9 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode
op)
{
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
- static const TCGTargetOpDef s_s = { .args_ct_str = { "s", "s" } };
static const TCGTargetOpDef a_b = { .args_ct_str = { "a", "b" } };
static const TCGTargetOpDef c_b = { .args_ct_str = { "c", "b" } };
static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
- static const TCGTargetOpDef s_s_s = { .args_ct_str = { "s", "s", "s" } };
static const TCGTargetOpDef a_c_d = { .args_ct_str = { "a", "c", "d" } };
static const TCGTargetOpDef a_b_b = { .args_ct_str = { "a", "b", "b" } };
static const TCGTargetOpDef e_c_d = { .args_ct_str = { "e", "c", "d" } };
@@ -2072,8 +2033,6 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode
op)
= { .args_ct_str = { "r", "r", "rIK" } };
static const TCGTargetOpDef r_r_r_r
= { .args_ct_str = { "r", "r", "r", "r" } };
- static const TCGTargetOpDef s_s_s_s
- = { .args_ct_str = { "s", "s", "s", "s" } };
static const TCGTargetOpDef a_b_c_d
= { .args_ct_str = { "a", "b", "c", "d" } };
static const TCGTargetOpDef e_f_c_d
@@ -2175,7 +2134,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode
op)
}
case INDEX_op_qemu_st_i32:
if (!USING_SOFTMMU) {
- return TARGET_LONG_BITS == 32 ? &s_s : &s_s_s;
+ return TARGET_LONG_BITS == 32 ? &r_r : &r_r_r;
} else if (TARGET_LONG_BITS == 32) {
return &c_b; /* temps available r0, r3, r12 */
} else {
@@ -2183,7 +2142,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode
op)
}
case INDEX_op_qemu_st_i64:
if (!USING_SOFTMMU) {
- return TARGET_LONG_BITS == 32 ? &s_s_s : &s_s_s_s;
+ return TARGET_LONG_BITS == 32 ? &r_r_r : &r_r_r_r;
} else if (TARGET_LONG_BITS == 32) {
return &e_f_b; /* temps available r0, r2, r3, r12 */
} else {
--
2.17.2
- [Qemu-devel] [PATCH for-4.0 v2 23/37] tcg/ppc: Change TCG_TARGET_CALL_ALIGN_ARGS to bool, (continued)
- [Qemu-devel] [PATCH for-4.0 v2 23/37] tcg/ppc: Change TCG_TARGET_CALL_ALIGN_ARGS to bool, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 25/37] tcg/ppc: Use TCG_TARGET_NEED_LDST_OOL_LABELS, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 28/37] tcg/optimize: Optimize bswap, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 21/37] tcg/ppc: Split out tcg_out_call_int, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 26/37] tcg: Clean up generic bswap32, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 19/37] tcg/arm: Use TCG_TARGET_NEED_LDST_OOL_LABELS, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 30/37] tcg/i386: Adjust TCG_TARGET_HAS_MEMORY_BSWAP, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 33/37] tcg/i386: Propagate is64 to tcg_out_qemu_ld_direct, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 35/37] tcg/i386: Add setup_guest_base_seg for FreeBSD, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 37/37] tcg/i386: Remove L constraint, Richard Henderson, 2018/11/23
- [Qemu-devel] [PATCH for-4.0 v2 32/37] tcg/arm: Set TCG_TARGET_HAS_MEMORY_BSWAP to false for user-only,
Richard Henderson <=
- Re: [Qemu-devel] [PATCH for-4.0 v2 00/37] tcg: Assorted cleanups, no-reply, 2018/11/23
- Re: [Qemu-devel] [PATCH for-4.0 v2 00/37] tcg: Assorted cleanups, Emilio G. Cota, 2018/11/25