[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 05/15] tcg-sparc: Simplify qemu_ld/st direct memory
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 05/15] tcg-sparc: Simplify qemu_ld/st direct memory paths. |
Date: |
Sun, 25 Mar 2012 15:27:47 -0700 |
Given that we have an opcode for all sizes, all endianness,
turn the functions into a simple table lookup.
Signed-off-by: Richard Henderson <address@hidden>
---
tcg/sparc/tcg-target.c | 209 +++++++++++++-----------------------------------
1 files changed, 56 insertions(+), 153 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 8763b03..1b27626 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -294,6 +294,16 @@ static inline int tcg_target_const_match(tcg_target_long
val,
#define ASI_PRIMARY_LITTLE 0x88
#endif
+#define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
+
+#define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
+
static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
int op)
{
@@ -366,66 +376,46 @@ static inline void tcg_out_movi(TCGContext *s, TCGType
type,
}
}
-static inline void tcg_out_ld_raw(TCGContext *s, int ret,
- tcg_target_long arg)
+static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1,
+ int a2, int op)
{
- tcg_out_sethi(s, ret, arg);
- tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
+ tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
}
-static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
- tcg_target_long arg)
+static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
+ int offset, int op)
{
- if (!check_fit_tl(arg, 10))
- tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL);
- if (TCG_TARGET_REG_BITS == 64) {
- tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
- } else {
- tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
- }
-}
-
-static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset,
int op)
-{
- if (check_fit_tl(offset, 13))
+ if (check_fit_tl(offset, 13)) {
tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
INSN_IMM13(offset));
- else {
+ } else {
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
- tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
- INSN_RS2(addr));
+ tcg_out_ldst_rr(s, ret, addr, TCG_REG_I5, op);
}
}
-static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr,
- int offset, int op, int asi)
-{
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
- tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
- INSN_ASI(asi) | INSN_RS2(addr));
-}
-
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
TCGReg arg1, tcg_target_long arg2)
{
- if (type == TCG_TYPE_I32)
- tcg_out_ldst(s, ret, arg1, arg2, LDUW);
- else
- tcg_out_ldst(s, ret, arg1, arg2, LDX);
+ tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
}
static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
TCGReg arg1, tcg_target_long arg2)
{
- if (type == TCG_TYPE_I32)
- tcg_out_ldst(s, arg, arg1, arg2, STW);
- else
- tcg_out_ldst(s, arg, arg1, arg2, STX);
+ tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
}
+static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
+ tcg_target_long arg)
+{
+ if (!check_fit_tl(arg, 10)) {
+ tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
+ }
+ tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff);
+}
+
+
static inline void tcg_out_sety(TCGContext *s, int rs)
{
tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
@@ -833,76 +823,26 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int
addr, int datalo,
int datahi, int sizeop)
{
#ifdef TARGET_WORDS_BIGENDIAN
- const int bigendian = 1;
+ static const int ld_opc[8] = {
+ LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
+ };
#else
- const int bigendian = 0;
+ static const int ld_opc[8] = {
+ LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
+ };
#endif
- switch (sizeop) {
- case 0:
- /* ldub [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDUB);
- break;
- case 0 | 4:
- /* ldsb [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDSB);
- break;
- case 1:
- if (bigendian) {
- /* lduh [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDUH);
- } else {
- /* lduha [addr] ASI_PRIMARY_LITTLE, datalo */
- tcg_out_ldst_asi(s, datalo, addr, 0, LDUHA, ASI_PRIMARY_LITTLE);
- }
- break;
- case 1 | 4:
- if (bigendian) {
- /* ldsh [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDSH);
- } else {
- /* ldsha [addr] ASI_PRIMARY_LITTLE, datalo */
- tcg_out_ldst_asi(s, datalo, addr, 0, LDSHA, ASI_PRIMARY_LITTLE);
- }
- break;
- case 2:
- if (bigendian) {
- /* lduw [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDUW);
- } else {
- /* lduwa [addr] ASI_PRIMARY_LITTLE, datalo */
- tcg_out_ldst_asi(s, datalo, addr, 0, LDUWA, ASI_PRIMARY_LITTLE);
- }
- break;
- case 2 | 4:
- if (bigendian) {
- /* ldsw [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDSW);
- } else {
- /* ldswa [addr] ASI_PRIMARY_LITTLE, datalo */
- tcg_out_ldst_asi(s, datalo, addr, 0, LDSWA, ASI_PRIMARY_LITTLE);
- }
- break;
- case 3:
- if (TCG_TARGET_REG_BITS == 64) {
- if (bigendian) {
- /* ldx [addr], datalo */
- tcg_out_ldst(s, datalo, addr, 0, LDX);
- } else {
- /* ldxa [addr] ASI_PRIMARY_LITTLE, datalo */
- tcg_out_ldst_asi(s, datalo, addr, 0, LDXA, ASI_PRIMARY_LITTLE);
- }
- } else {
- if (bigendian) {
- tcg_out_ldst(s, datahi, addr, 0, LDUW);
- tcg_out_ldst(s, datalo, addr, 4, LDUW);
- } else {
- tcg_out_ldst_asi(s, datalo, addr, 0, LDUWA,
ASI_PRIMARY_LITTLE);
- tcg_out_ldst_asi(s, datahi, addr, 4, LDUWA,
ASI_PRIMARY_LITTLE);
- }
+
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ /* Load all 64-bits into an O/G register. */
+ int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
+ tcg_out_ldst_rr(s, reg64, addr, TCG_REG_G0, ld_opc[sizeop]);
+ /* Move the two 32-bit pieces into the destination registers. */
+ tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
+ if (reg64 != datalo) {
+ tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
}
- break;
- default:
- tcg_abort();
+ } else {
+ tcg_out_ldst_rr(s, datalo, addr, TCG_REG_G0, ld_opc[sizeop]);
}
}
@@ -1016,55 +956,18 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int
addr, int datalo,
int datahi, int sizeop)
{
#ifdef TARGET_WORDS_BIGENDIAN
- const int bigendian = 1;
+ static const int st_opc[4] = { STB, STH, STW, STX };
#else
- const int bigendian = 0;
+ static const int st_opc[4] = { STB, STH_LE, STW_LE, STX_LE };
#endif
- switch (sizeop) {
- case 0:
- /* stb datalo, [addr] */
- tcg_out_ldst(s, datalo, addr, 0, STB);
- break;
- case 1:
- if (bigendian) {
- /* sth datalo, [addr] */
- tcg_out_ldst(s, datalo, addr, 0, STH);
- } else {
- /* stha datalo, [addr] ASI_PRIMARY_LITTLE */
- tcg_out_ldst_asi(s, datalo, addr, 0, STHA, ASI_PRIMARY_LITTLE);
- }
- break;
- case 2:
- if (bigendian) {
- /* stw datalo, [addr] */
- tcg_out_ldst(s, datalo, addr, 0, STW);
- } else {
- /* stwa datalo, [addr] ASI_PRIMARY_LITTLE */
- tcg_out_ldst_asi(s, datalo, addr, 0, STWA, ASI_PRIMARY_LITTLE);
- }
- break;
- case 3:
- if (TCG_TARGET_REG_BITS == 64) {
- if (bigendian) {
- /* stx datalo, [addr] */
- tcg_out_ldst(s, datalo, addr, 0, STX);
- } else {
- /* stxa datalo, [addr] ASI_PRIMARY_LITTLE */
- tcg_out_ldst_asi(s, datalo, addr, 0, STXA, ASI_PRIMARY_LITTLE);
- }
- } else {
- if (bigendian) {
- tcg_out_ldst(s, datahi, addr, 0, STW);
- tcg_out_ldst(s, datalo, addr, 4, STW);
- } else {
- tcg_out_ldst_asi(s, datalo, addr, 0, STWA, ASI_PRIMARY_LITTLE);
- tcg_out_ldst_asi(s, datahi, addr, 4, STWA, ASI_PRIMARY_LITTLE);
- }
- }
- break;
- default:
- tcg_abort();
+
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ tcg_out_arithi(s, TCG_REG_O0, datalo, 0, SHIFT_SRL);
+ tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
+ tcg_out_arith(s, TCG_REG_O0, TCG_REG_O0, TCG_REG_O2, ARITH_OR);
+ datalo = TCG_REG_O0;
}
+ tcg_out_ldst_rr(s, datalo, addr, TCG_REG_G0, st_opc[sizeop]);
}
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
--
1.7.7.6
- [Qemu-devel] [PATCH 00/15] tcg-sparc improvments, Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 01/15] tcg-sparc: Hack in qemu_ld/st64 for 32-bit., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 02/15] tcg-sparc: Fix ADDX opcode., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 06/15] tcg-sparc: Support GUEST_BASE., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 03/15] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 07/15] tcg-sparc: Steamline qemu_ld/st more., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 09/15] tcg-sparc: Do not use a global register for AREG0., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 05/15] tcg-sparc: Simplify qemu_ld/st direct memory paths.,
Richard Henderson <=
- [Qemu-devel] [PATCH 04/15] tcg-sparc: Fix qemu_ld/st to handle 32-bit host., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 08/15] Avoid declaring the env variable at all if CONFIG_TCG_PASS_AREG0., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 11/15] tcg-sparc: Clean up cruft stemming from attempts to use global registers., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 14/15] tcg-sparc: Add %g/%o registers to alloc_order, Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 10/15] tcg-sparc: Change AREG0 in generated code to %i0., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 12/15] tcg-sparc: Mask shift immediates to avoid illegal insns., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 15/15] tcg-sparc: Fix and enable direct TB chaining., Richard Henderson, 2012/03/25
- [Qemu-devel] [PATCH 13/15] tcg-sparc: Use defines for temporaries., Richard Henderson, 2012/03/25