* [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends
@ 2014-06-20 14:13 Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 01/25] tcg-ppc: Use uintptr_t in ppc_tb_set_jmp_target Richard Henderson
` (25 more replies)
0 siblings, 26 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
The ppc32 backend isn't getting much love and attention recently, with
all of the improvements coming from me into the ppc64 backend. Let's
reduce the maint burden a bit and combine them.
This does have a few other patches that are not strictly related to the
merge of the backends, such as addition of ELFv2 support, but I think
those come naturally at the point we're merging the two other ABIs from
the 32-bit port.
I've tested this as thouroghly as I can on a Power7 host, both ppc64 and
ppc32 editions. Though of course even with the 32-bit abi a power7 host
will execute 64-bit instructions. Which means if anyone has access to a
proper 32-bit ppc system, I'd be grateful if you could verify I haven't
missed any necessary conditionalization. Tom Musta gave me a Tested-by
for v2 on an ELFv2 system; it might be worth re-doing that just in case.
Full tree at
git://github.com/rth7680/qemu.git tcg-ppc-merge-1
Changes v1-v2:
* mulsh_i32 typo fixed (Uli)
* ppc32 qemu_st_i64 bug fixed
* ppc64 boot problem Tom reported by a generic tcg optimization fix
Changes v2-v3:
* Rebased,
* Dropped patch 26, Streamline USE_DIRECT_JUMP. This seems to have
some timing/flushing issues on 32-bit which I don't have time to
understand at the moment.
r~
Richard Henderson (24):
tcg-ppc: Use uintptr_t in ppc_tb_set_jmp_target
tcg-ppc64: Avoid some hard-codings of TCG_TYPE_I64
tcg-ppc64: Move functions around
tcg-ppc64: Relax register restrictions in tcg_out_mem_long
tcg-ppc64: Use tcg_out_{ld,st,cmp} internally
tcg-ppc64: Make TCG_AREG0 and TCG_REG_CALL_STACK enum constants
tcg-ppc64: Move call macros out of tcg-target.h
tcg-ppc64: Fix TCG_TARGET_CALL_STACK_OFFSET
tcg-ppc64: Better parameterize the stack frame
tcg-ppc64: Use the correct test in tcg_out_call
tcg-ppc64: Support the ppc64 elfv2 ABI
tcg-ppc64: Merge 32-bit ABIs into the prologue / frame code
tcg-ppc64: Fix sub2 implementation
tcg-ppc64: Begin merging ppc32 with ppc64
tcg-ppc64: Merge ppc32 brcond2, setcond2, muluh
tcg-ppc64: Merge ppc32 qemu_ld/st
tcg-ppc64: Merge ppc32 register usage
tcg-ppc64: Support mulsh_i32
tcg-ppc64: Merge ppc32 shifts
tcg-ppc: Remove the backend
tcg-ppc: Rename the tcg/ppc64 backend
qemu/osdep: Remove the need for qemu_init_auxval
tcg-ppc: Merge cache-utils into the backend
tcg-ppc: Use the return address as a base pointer
Ulrich Weigand (1):
tcg-ppc64: Adjust tcg_out_call for ELFv2
configure | 2 +
exec.c | 1 -
include/exec/exec-all.h | 2 +-
include/qemu/cache-utils.h | 44 -
include/qemu/osdep.h | 12 -
linux-user/main.c | 4 -
tcg/ppc/tcg-target.c | 3174 +++++++++++++++++++++++++++-----------------
tcg/ppc/tcg-target.h | 114 +-
tcg/ppc64/tcg-target.c | 2186 ------------------------------
tcg/ppc64/tcg-target.h | 131 --
tcg/tcg.c | 1 -
util/Makefile.objs | 2 +-
util/cache-utils.c | 86 --
util/getauxval.c | 51 +-
vl.c | 4 -
15 files changed, 2080 insertions(+), 3734 deletions(-)
delete mode 100644 include/qemu/cache-utils.h
delete mode 100644 tcg/ppc64/tcg-target.c
delete mode 100644 tcg/ppc64/tcg-target.h
delete mode 100644 util/cache-utils.c
--
1.9.3
^ permalink raw reply [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 01/25] tcg-ppc: Use uintptr_t in ppc_tb_set_jmp_target
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 02/25] tcg-ppc64: Avoid some hard-codings of TCG_TYPE_I64 Richard Henderson
` (24 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/exec/exec-all.h | 2 +-
tcg/ppc/tcg-target.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 3d62d9c..5e5d86e 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -224,7 +224,7 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
/* no need to flush icache explicitly */
}
#elif defined(_ARCH_PPC)
-void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
+void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
#define tb_set_jmp_target1 ppc_tb_set_jmp_target
#elif defined(__i386__) || defined(__x86_64__)
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 436b65b..d64eaa5 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -1318,7 +1318,7 @@ static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), args[5]);
}
-void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
+void ppc_tb_set_jmp_target (uintptr_t jmp_addr, uintptr_t addr)
{
uint32_t *ptr;
long disp = addr - jmp_addr;
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 02/25] tcg-ppc64: Avoid some hard-codings of TCG_TYPE_I64
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 01/25] tcg-ppc: Use uintptr_t in ppc_tb_set_jmp_target Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 03/25] tcg-ppc64: Move functions around Richard Henderson
` (23 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Using more appropriate _PTR or _REG where possible.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index c90ddcd..2f60924 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -24,6 +24,9 @@
#include "tcg-be-ldst.h"
+/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
+#define SZP ((int)sizeof(void *))
+
#define TCG_CT_CONST_S16 0x100
#define TCG_CT_CONST_U16 0x200
#define TCG_CT_CONST_S32 0x400
@@ -701,7 +704,7 @@ static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
if (in_range_b(disp)) {
tcg_out32(s, B | (disp & 0x3fffffc) | mask);
} else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, (uintptr_t)target);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
tcg_out32(s, BCCTR | BO_ALWAYS | mask);
}
@@ -719,7 +722,7 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
intptr_t diff = tcg_pcrel_diff(s, tgt);
if (in_range_b(diff) && toc == (uint32_t)toc) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, toc);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, toc);
tcg_out_b(s, LK, tgt);
} else {
/* Fold the low bits of the constant into the addresses below. */
@@ -731,7 +734,7 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
} else {
ofs = 0;
}
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, arg);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg);
tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R2, ofs));
tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
tcg_out32(s, LD | TAI(TCG_REG_R2, TCG_REG_R2, ofs + 8));
@@ -766,7 +769,7 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
/* For unaligned, or very large offsets, use the indexed form. */
if (offset & align || offset != (int32_t)offset) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, orig);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, orig);
tcg_out32(s, opx | TAB(rt, base, TCG_REG_R2));
return;
}
@@ -1118,7 +1121,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
#ifdef CONFIG_USE_GUEST_BASE
if (GUEST_BASE) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
}
#endif
@@ -1476,7 +1479,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
switch (opc) {
case INDEX_op_exit_tb:
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
tcg_out_b(s, 0, tb_ret_addr);
break;
case INDEX_op_goto_tb:
@@ -1868,7 +1871,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
if (a0 == TCG_REG_R0) {
- tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
+ tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
}
break;
@@ -1900,7 +1903,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out_rlw(s, RLWIMI, a0, a2, 24, 16, 23);
if (a0 == 0) {
- tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
+ tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
}
break;
@@ -1951,7 +1954,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32(s, ADDE | TAB(a1, args[3], args[5]));
}
if (a0 != args[0]) {
- tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
+ tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
}
break;
@@ -1971,7 +1974,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32(s, SUBFE | TAB(a1, args[5], args[4]));
}
if (a0 != args[0]) {
- tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
+ tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
}
break;
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 03/25] tcg-ppc64: Move functions around
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 01/25] tcg-ppc: Use uintptr_t in ppc_tb_set_jmp_target Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 02/25] tcg-ppc64: Avoid some hard-codings of TCG_TYPE_I64 Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 04/25] tcg-ppc64: Relax register restrictions in tcg_out_mem_long Richard Henderson
` (22 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Code movement only. This will allow us to make use of the
other tcg_out_* functions in tidying their implementations.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 1178 ++++++++++++++++++++++++------------------------
1 file changed, 589 insertions(+), 589 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 2f60924..951a392 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -710,39 +710,6 @@ static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
}
}
-static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
-{
-#ifdef __APPLE__
- tcg_out_b(s, LK, target);
-#else
- /* Look through the descriptor. If the branch is in range, and we
- don't have to spend too much effort on building the toc. */
- void *tgt = ((void **)target)[0];
- uintptr_t toc = ((uintptr_t *)target)[1];
- intptr_t diff = tcg_pcrel_diff(s, tgt);
-
- if (in_range_b(diff) && toc == (uint32_t)toc) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, toc);
- tcg_out_b(s, LK, tgt);
- } else {
- /* Fold the low bits of the constant into the addresses below. */
- intptr_t arg = (intptr_t)target;
- int ofs = (int16_t)arg;
-
- if (ofs + 8 < 0x8000) {
- arg -= ofs;
- } else {
- ofs = 0;
- }
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg);
- tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R2, ofs));
- tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
- tcg_out32(s, LD | TAI(TCG_REG_R2, TCG_REG_R2, ofs + 8));
- tcg_out32(s, BCCTR | BO_ALWAYS | LK);
- }
-#endif
-}
-
static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
TCGReg base, tcg_target_long offset)
{
@@ -795,680 +762,713 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
}
}
-static const uint32_t qemu_ldx_opc[16] = {
- [MO_UB] = LBZX,
- [MO_UW] = LHZX,
- [MO_UL] = LWZX,
- [MO_Q] = LDX,
- [MO_SW] = LHAX,
- [MO_SL] = LWAX,
- [MO_BSWAP | MO_UB] = LBZX,
- [MO_BSWAP | MO_UW] = LHBRX,
- [MO_BSWAP | MO_UL] = LWBRX,
- [MO_BSWAP | MO_Q] = LDBRX,
-};
-
-static const uint32_t qemu_stx_opc[16] = {
- [MO_UB] = STBX,
- [MO_UW] = STHX,
- [MO_UL] = STWX,
- [MO_Q] = STDX,
- [MO_BSWAP | MO_UB] = STBX,
- [MO_BSWAP | MO_UW] = STHBRX,
- [MO_BSWAP | MO_UL] = STWBRX,
- [MO_BSWAP | MO_Q] = STDBRX,
-};
-
-static const uint32_t qemu_exts_opc[4] = {
- EXTSB, EXTSH, EXTSW, 0
-};
-
-#if defined (CONFIG_SOFTMMU)
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
- * int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_ld_helpers[16] = {
- [MO_UB] = helper_ret_ldub_mmu,
- [MO_LEUW] = helper_le_lduw_mmu,
- [MO_LEUL] = helper_le_ldul_mmu,
- [MO_LEQ] = helper_le_ldq_mmu,
- [MO_BEUW] = helper_be_lduw_mmu,
- [MO_BEUL] = helper_be_ldul_mmu,
- [MO_BEQ] = helper_be_ldq_mmu,
-};
-
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
- * uintxx_t val, int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_st_helpers[16] = {
- [MO_UB] = helper_ret_stb_mmu,
- [MO_LEUW] = helper_le_stw_mmu,
- [MO_LEUL] = helper_le_stl_mmu,
- [MO_LEQ] = helper_le_stq_mmu,
- [MO_BEUW] = helper_be_stw_mmu,
- [MO_BEUL] = helper_be_stl_mmu,
- [MO_BEQ] = helper_be_stq_mmu,
-};
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+ TCGReg arg1, intptr_t arg2)
+{
+ int opi, opx;
-/* 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
- containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
+ if (type == TCG_TYPE_I32) {
+ opi = LWZ, opx = LWZX;
+ } else {
+ opi = LD, opx = LDX;
+ }
+ tcg_out_mem_long(s, opi, opx, ret, arg1, arg2);
+}
-static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
- int mem_index, bool is_read)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, intptr_t arg2)
{
- int cmp_off
- = (is_read
- ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
- : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
- int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
- TCGReg base = TCG_AREG0;
+ int opi, opx;
- /* Extract the page index, shifted into place for tlb index. */
- if (TARGET_LONG_BITS == 32) {
- /* Zero-extend the address into a place helpful for further use. */
- tcg_out_ext32u(s, TCG_REG_R4, addr_reg);
- addr_reg = TCG_REG_R4;
+ if (type == TCG_TYPE_I32) {
+ opi = STW, opx = STWX;
} else {
- tcg_out_rld(s, RLDICL, TCG_REG_R3, addr_reg,
- 64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
+ opi = STD, opx = STDX;
}
+ tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
+}
- /* Compensate for very large offsets. */
- if (add_off >= 0x8000) {
- /* Most target env are smaller than 32k; none are larger than 64k.
- Simplify the logic here merely to offset by 0x7ff0, giving us a
- range just shy of 64k. Check this assumption. */
- QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
- tlb_table[NB_MMU_MODES - 1][1])
- > 0x7ff0 + 0x7fff);
- tcg_out32(s, ADDI | TAI(TCG_REG_R2, base, 0x7ff0));
- base = TCG_REG_R2;
- cmp_off -= 0x7ff0;
- add_off -= 0x7ff0;
- }
+static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
+ int const_arg2, int cr, TCGType type)
+{
+ int imm;
+ uint32_t op;
- /* Extraction and shifting, part 2. */
- if (TARGET_LONG_BITS == 32) {
- tcg_out_rlw(s, RLWINM, TCG_REG_R3, addr_reg,
- 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
- 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
- 31 - CPU_TLB_ENTRY_BITS);
- } else {
- tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);
+ /* Simplify the comparisons below wrt CMPI. */
+ if (type == TCG_TYPE_I32) {
+ arg2 = (int32_t)arg2;
}
- tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
+ switch (cond) {
+ case TCG_COND_EQ:
+ case TCG_COND_NE:
+ if (const_arg2) {
+ if ((int16_t) arg2 == arg2) {
+ op = CMPI;
+ imm = 1;
+ break;
+ } else if ((uint16_t) arg2 == arg2) {
+ op = CMPLI;
+ imm = 1;
+ break;
+ }
+ }
+ op = CMPL;
+ imm = 0;
+ break;
- /* Load the tlb comparator. */
- tcg_out32(s, LD_ADDR | TAI(TCG_REG_R2, TCG_REG_R3, cmp_off));
+ case TCG_COND_LT:
+ case TCG_COND_GE:
+ case TCG_COND_LE:
+ case TCG_COND_GT:
+ if (const_arg2) {
+ if ((int16_t) arg2 == arg2) {
+ op = CMPI;
+ imm = 1;
+ break;
+ }
+ }
+ op = CMP;
+ imm = 0;
+ break;
- /* Load the TLB addend for use on the fast path. Do this asap
- to minimize any load use delay. */
- tcg_out32(s, LD | TAI(TCG_REG_R3, TCG_REG_R3, add_off));
+ case TCG_COND_LTU:
+ case TCG_COND_GEU:
+ case TCG_COND_LEU:
+ case TCG_COND_GTU:
+ if (const_arg2) {
+ if ((uint16_t) arg2 == arg2) {
+ op = CMPLI;
+ imm = 1;
+ break;
+ }
+ }
+ op = CMPL;
+ imm = 0;
+ break;
- /* Clear the non-page, non-alignment bits from the address. */
- if (TARGET_LONG_BITS == 32) {
- tcg_out_rlw(s, RLWINM, TCG_REG_R0, addr_reg, 0,
- (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
- } else if (!s_bits) {
- tcg_out_rld(s, RLDICR, TCG_REG_R0, addr_reg, 0, 63 - TARGET_PAGE_BITS);
- } else {
- tcg_out_rld(s, RLDICL, TCG_REG_R0, addr_reg,
- 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
- tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
+ default:
+ tcg_abort();
}
+ op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
- tcg_out32(s, CMP | BF(7) | RA(TCG_REG_R0) | RB(TCG_REG_R2) | CMP_L);
-
- return addr_reg;
+ if (imm) {
+ tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
+ } else {
+ if (const_arg2) {
+ tcg_out_movi(s, type, TCG_REG_R0, arg2);
+ arg2 = TCG_REG_R0;
+ }
+ tcg_out32(s, op | RA(arg1) | RB(arg2));
+ }
}
-/* Record the context of a call to the out of line helper code for the slow
- path for a load or store, so that we can later generate the correct
- helper code. */
-static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
- int data_reg, int addr_reg, int mem_index,
- tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
+static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
+ TCGReg dst, TCGReg src)
{
- TCGLabelQemuLdst *label = new_ldst_label(s);
-
- label->is_ld = is_ld;
- label->opc = opc;
- label->datalo_reg = data_reg;
- label->addrlo_reg = addr_reg;
- label->mem_index = mem_index;
- label->raddr = raddr;
- label->label_ptr[0] = label_ptr;
+ tcg_out32(s, (type == TCG_TYPE_I64 ? CNTLZD : CNTLZW) | RS(src) | RA(dst));
+ tcg_out_shri64(s, dst, dst, type == TCG_TYPE_I64 ? 6 : 5);
}
-static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
{
- TCGMemOp opc = lb->opc;
-
- reloc_pc14(lb->label_ptr[0], s->code_ptr);
-
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
-
- /* If the address needed to be zero-extended, we'll have already
- placed it in R4. The only remaining case is 64-bit guest. */
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
-
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
- tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
-
- tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
-
- if (opc & MO_SIGN) {
- uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
- tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
+ /* X != 0 implies X + -1 generates a carry. Extra addition
+ trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C. */
+ if (dst != src) {
+ tcg_out32(s, ADDIC | TAI(dst, src, -1));
+ tcg_out32(s, SUBFE | TAB(dst, dst, src));
} else {
- tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
+ tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
+ tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
}
+}
- tcg_out_b(s, 0, lb->raddr);
+static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
+ bool const_arg2)
+{
+ if (const_arg2) {
+ if ((uint32_t)arg2 == arg2) {
+ tcg_out_xori32(s, TCG_REG_R0, arg1, arg2);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, arg2);
+ tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, TCG_REG_R0));
+ }
+ } else {
+ tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, arg2));
+ }
+ return TCG_REG_R0;
}
-static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
+ TCGArg arg0, TCGArg arg1, TCGArg arg2,
+ int const_arg2)
{
- TCGMemOp opc = lb->opc;
- TCGMemOp s_bits = opc & MO_SIZE;
+ int crop, sh;
- reloc_pc14(lb->label_ptr[0], s->code_ptr);
+ /* Ignore high bits of a potential constant arg2. */
+ if (type == TCG_TYPE_I32) {
+ arg2 = (uint32_t)arg2;
+ }
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
+ /* Handle common and trivial cases before handling anything else. */
+ if (arg2 == 0) {
+ switch (cond) {
+ case TCG_COND_EQ:
+ tcg_out_setcond_eq0(s, type, arg0, arg1);
+ return;
+ case TCG_COND_NE:
+ if (type == TCG_TYPE_I32) {
+ tcg_out_ext32u(s, TCG_REG_R0, arg1);
+ arg1 = TCG_REG_R0;
+ }
+ tcg_out_setcond_ne0(s, arg0, arg1);
+ return;
+ case TCG_COND_GE:
+ tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
+ arg1 = arg0;
+ /* FALLTHRU */
+ case TCG_COND_LT:
+ /* Extract the sign bit. */
+ tcg_out_rld(s, RLDICL, arg0, arg1,
+ type == TCG_TYPE_I64 ? 1 : 33, 63);
+ return;
+ default:
+ break;
+ }
+ }
- /* If the address needed to be zero-extended, we'll have already
- placed it in R4. The only remaining case is 64-bit guest. */
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
+ /* If we have ISEL, we can implement everything with 3 or 4 insns.
+ All other cases below are also at least 3 insns, so speed up the
+ code generator by not considering them and always using ISEL. */
+ if (HAVE_ISEL) {
+ int isel, tab;
- tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
- 0, 64 - (1 << (3 + s_bits)));
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
- tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
- tcg_out_call(s, qemu_st_helpers[opc]);
+ isel = tcg_to_isel[cond];
- tcg_out_b(s, 0, lb->raddr);
-}
-#endif /* SOFTMMU */
+ tcg_out_movi(s, type, arg0, 1);
+ if (isel & 1) {
+ /* arg0 = (bc ? 0 : 1) */
+ tab = TAB(arg0, 0, arg0);
+ isel &= ~1;
+ } else {
+ /* arg0 = (bc ? 1 : 0) */
+ tcg_out_movi(s, type, TCG_REG_R0, 0);
+ tab = TAB(arg0, arg0, TCG_REG_R0);
+ }
+ tcg_out32(s, isel | tab);
+ return;
+ }
-static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
- TCGMemOp opc, int mem_index)
-{
- TCGReg rbase;
- uint32_t insn;
- TCGMemOp s_bits = opc & MO_SIZE;
-#ifdef CONFIG_SOFTMMU
- tcg_insn_unit *label_ptr;
-#endif
+ switch (cond) {
+ case TCG_COND_EQ:
+ arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
+ tcg_out_setcond_eq0(s, type, arg0, arg1);
+ return;
-#ifdef CONFIG_SOFTMMU
- addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
+ case TCG_COND_NE:
+ arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
+ /* Discard the high bits only once, rather than both inputs. */
+ if (type == TCG_TYPE_I32) {
+ tcg_out_ext32u(s, TCG_REG_R0, arg1);
+ arg1 = TCG_REG_R0;
+ }
+ tcg_out_setcond_ne0(s, arg0, arg1);
+ return;
- /* Load a pointer into the current opcode w/conditional branch-link. */
- label_ptr = s->code_ptr;
- tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
+ case TCG_COND_GT:
+ case TCG_COND_GTU:
+ sh = 30;
+ crop = 0;
+ goto crtest;
- rbase = TCG_REG_R3;
-#else /* !CONFIG_SOFTMMU */
- rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
- if (TARGET_LONG_BITS == 32) {
- tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
- addr_reg = TCG_REG_R2;
- }
-#endif
+ case TCG_COND_LT:
+ case TCG_COND_LTU:
+ sh = 29;
+ crop = 0;
+ goto crtest;
- insn = qemu_ldx_opc[opc];
- if (!HAVE_ISA_2_06 && insn == LDBRX) {
- tcg_out32(s, ADDI | TAI(TCG_REG_R0, addr_reg, 4));
- tcg_out32(s, LWBRX | TAB(data_reg, rbase, addr_reg));
- tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
- tcg_out_rld(s, RLDIMI, data_reg, TCG_REG_R0, 32, 0);
- } else if (insn) {
- tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
- } else {
- insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
- tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
- insn = qemu_exts_opc[s_bits];
- tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
- }
+ case TCG_COND_GE:
+ case TCG_COND_GEU:
+ sh = 31;
+ crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
+ goto crtest;
-#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, true, opc, data_reg, addr_reg, mem_index,
- s->code_ptr, label_ptr);
-#endif
+ case TCG_COND_LE:
+ case TCG_COND_LEU:
+ sh = 31;
+ crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
+ crtest:
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+ if (crop) {
+ tcg_out32(s, crop);
+ }
+ tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
+ tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
+ break;
+
+ default:
+ tcg_abort();
+ }
}
-static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
- TCGMemOp opc, int mem_index)
+static void tcg_out_bc(TCGContext *s, int bc, int label_index)
{
- TCGReg rbase;
- uint32_t insn;
-#ifdef CONFIG_SOFTMMU
- tcg_insn_unit *label_ptr;
-#endif
-
-#ifdef CONFIG_SOFTMMU
- addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
-
- /* Load a pointer into the current opcode w/conditional branch-link. */
- label_ptr = s->code_ptr;
- tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
-
- rbase = TCG_REG_R3;
-#else /* !CONFIG_SOFTMMU */
- rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
- if (TARGET_LONG_BITS == 32) {
- tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
- addr_reg = TCG_REG_R2;
- }
-#endif
+ TCGLabel *l = &s->labels[label_index];
- insn = qemu_stx_opc[opc];
- if (!HAVE_ISA_2_06 && insn == STDBRX) {
- tcg_out32(s, STWBRX | SAB(data_reg, rbase, addr_reg));
- tcg_out32(s, ADDI | TAI(TCG_REG_R2, addr_reg, 4));
- tcg_out_shri64(s, TCG_REG_R0, data_reg, 32);
- tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
+ if (l->has_value) {
+ tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
} else {
- tcg_out32(s, insn | SAB(data_reg, rbase, addr_reg));
+ tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
+ tcg_out_bc_noaddr(s, bc);
}
-
-#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, false, opc, data_reg, addr_reg, mem_index,
- s->code_ptr, label_ptr);
-#endif
}
-#define FRAME_SIZE ((int) \
- ((8 /* back chain */ \
- + 8 /* CR */ \
- + 8 /* LR */ \
- + 8 /* compiler doubleword */ \
- + 8 /* link editor doubleword */ \
- + 8 /* TOC save area */ \
- + TCG_STATIC_CALL_ARGS_SIZE \
- + CPU_TEMP_BUF_NLONGS * sizeof(long) \
- + ARRAY_SIZE(tcg_target_callee_save_regs) * 8 \
- + 15) & ~15))
-
-#define REG_SAVE_BOT (FRAME_SIZE - ARRAY_SIZE(tcg_target_callee_save_regs) * 8)
-
-static void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_out_brcond(TCGContext *s, TCGCond cond,
+ TCGArg arg1, TCGArg arg2, int const_arg2,
+ int label_index, TCGType type)
{
- int i;
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+ tcg_out_bc(s, tcg_to_bc[cond], label_index);
+}
- tcg_set_frame(s, TCG_REG_CALL_STACK,
- REG_SAVE_BOT - CPU_TEMP_BUF_NLONGS * sizeof(long),
- CPU_TEMP_BUF_NLONGS * sizeof(long));
-
-#ifndef __APPLE__
- /* First emit adhoc function descriptor */
- tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
- tcg_out64(s, 0); /* toc */
- tcg_out64(s, 0); /* environment pointer */
-#endif
-
- /* Prologue */
- tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
- tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
- tcg_out32(s, STD | SAI(tcg_target_callee_save_regs[i], 1,
- REG_SAVE_BOT + i * 8));
- }
- tcg_out32(s, STD | SAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
-
-#ifdef CONFIG_USE_GUEST_BASE
- if (GUEST_BASE) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
- tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
+ TCGArg dest, TCGArg c1, TCGArg c2, TCGArg v1,
+ TCGArg v2, bool const_c2)
+{
+ /* If for some reason both inputs are zero, don't produce bad code. */
+ if (v1 == 0 && v2 == 0) {
+ tcg_out_movi(s, type, dest, 0);
+ return;
}
-#endif
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
- tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
- tcg_out32(s, BCCTR | BO_ALWAYS);
+ tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
- /* Epilogue */
- tb_ret_addr = s->code_ptr;
+ if (HAVE_ISEL) {
+ int isel = tcg_to_isel[cond];
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
- tcg_out32(s, LD | TAI(tcg_target_callee_save_regs[i], TCG_REG_R1,
- REG_SAVE_BOT + i * 8));
+ /* Swap the V operands if the operation indicates inversion. */
+ if (isel & 1) {
+ int t = v1;
+ v1 = v2;
+ v2 = t;
+ isel &= ~1;
+ }
+ /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand. */
+ if (v2 == 0) {
+ tcg_out_movi(s, type, TCG_REG_R0, 0);
+ }
+ tcg_out32(s, isel | TAB(dest, v1, v2));
+ } else {
+ if (dest == v2) {
+ cond = tcg_invert_cond(cond);
+ v2 = v1;
+ } else if (dest != v1) {
+ if (v1 == 0) {
+ tcg_out_movi(s, type, dest, 0);
+ } else {
+ tcg_out_mov(s, type, dest, v1);
+ }
+ }
+ /* Branch forward over one insn */
+ tcg_out32(s, tcg_to_bc[cond] | 8);
+ if (v2 == 0) {
+ tcg_out_movi(s, type, dest, 0);
+ } else {
+ tcg_out_mov(s, type, dest, v2);
+ }
}
- tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
- tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
- tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
- tcg_out32(s, BCLR | BO_ALWAYS);
}
-static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
- TCGReg arg1, intptr_t arg2)
+void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
{
- int opi, opx;
+ TCGContext s;
- if (type == TCG_TYPE_I32) {
- opi = LWZ, opx = LWZX;
- } else {
- opi = LD, opx = LDX;
- }
- tcg_out_mem_long(s, opi, opx, ret, arg1, arg2);
+ s.code_buf = s.code_ptr = (tcg_insn_unit *)jmp_addr;
+ tcg_out_b(&s, 0, (tcg_insn_unit *)addr);
+ flush_icache_range(jmp_addr, jmp_addr + tcg_current_code_size(&s));
}
-static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
- TCGReg arg1, intptr_t arg2)
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
{
- int opi, opx;
+#ifdef __APPLE__
+ tcg_out_b(s, LK, target);
+#else
+ /* Look through the descriptor. If the branch is in range, and we
+ don't have to spend too much effort on building the toc. */
+ void *tgt = ((void **)target)[0];
+ uintptr_t toc = ((uintptr_t *)target)[1];
+ intptr_t diff = tcg_pcrel_diff(s, tgt);
- if (type == TCG_TYPE_I32) {
- opi = STW, opx = STWX;
+ if (in_range_b(diff) && toc == (uint32_t)toc) {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, toc);
+ tcg_out_b(s, LK, tgt);
} else {
- opi = STD, opx = STDX;
+ /* Fold the low bits of the constant into the addresses below. */
+ intptr_t arg = (intptr_t)target;
+ int ofs = (int16_t)arg;
+
+ if (ofs + 8 < 0x8000) {
+ arg -= ofs;
+ } else {
+ ofs = 0;
+ }
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg);
+ tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R2, ofs));
+ tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
+ tcg_out32(s, LD | TAI(TCG_REG_R2, TCG_REG_R2, ofs + 8));
+ tcg_out32(s, BCCTR | BO_ALWAYS | LK);
}
- tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
+#endif
}
-static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
- int const_arg2, int cr, TCGType type)
-{
- int imm;
- uint32_t op;
+static const uint32_t qemu_ldx_opc[16] = {
+ [MO_UB] = LBZX,
+ [MO_UW] = LHZX,
+ [MO_UL] = LWZX,
+ [MO_Q] = LDX,
+ [MO_SW] = LHAX,
+ [MO_SL] = LWAX,
+ [MO_BSWAP | MO_UB] = LBZX,
+ [MO_BSWAP | MO_UW] = LHBRX,
+ [MO_BSWAP | MO_UL] = LWBRX,
+ [MO_BSWAP | MO_Q] = LDBRX,
+};
- /* Simplify the comparisons below wrt CMPI. */
- if (type == TCG_TYPE_I32) {
- arg2 = (int32_t)arg2;
- }
+static const uint32_t qemu_stx_opc[16] = {
+ [MO_UB] = STBX,
+ [MO_UW] = STHX,
+ [MO_UL] = STWX,
+ [MO_Q] = STDX,
+ [MO_BSWAP | MO_UB] = STBX,
+ [MO_BSWAP | MO_UW] = STHBRX,
+ [MO_BSWAP | MO_UL] = STWBRX,
+ [MO_BSWAP | MO_Q] = STDBRX,
+};
- switch (cond) {
- case TCG_COND_EQ:
- case TCG_COND_NE:
- if (const_arg2) {
- if ((int16_t) arg2 == arg2) {
- op = CMPI;
- imm = 1;
- break;
- } else if ((uint16_t) arg2 == arg2) {
- op = CMPLI;
- imm = 1;
- break;
- }
- }
- op = CMPL;
- imm = 0;
- break;
+static const uint32_t qemu_exts_opc[4] = {
+ EXTSB, EXTSH, EXTSW, 0
+};
- case TCG_COND_LT:
- case TCG_COND_GE:
- case TCG_COND_LE:
- case TCG_COND_GT:
- if (const_arg2) {
- if ((int16_t) arg2 == arg2) {
- op = CMPI;
- imm = 1;
- break;
- }
- }
- op = CMP;
- imm = 0;
- break;
+#if defined (CONFIG_SOFTMMU)
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+ * int mmu_idx, uintptr_t ra)
+ */
+static void * const qemu_ld_helpers[16] = {
+ [MO_UB] = helper_ret_ldub_mmu,
+ [MO_LEUW] = helper_le_lduw_mmu,
+ [MO_LEUL] = helper_le_ldul_mmu,
+ [MO_LEQ] = helper_le_ldq_mmu,
+ [MO_BEUW] = helper_be_lduw_mmu,
+ [MO_BEUL] = helper_be_ldul_mmu,
+ [MO_BEQ] = helper_be_ldq_mmu,
+};
- case TCG_COND_LTU:
- case TCG_COND_GEU:
- case TCG_COND_LEU:
- case TCG_COND_GTU:
- if (const_arg2) {
- if ((uint16_t) arg2 == arg2) {
- op = CMPLI;
- imm = 1;
- break;
- }
- }
- op = CMPL;
- imm = 0;
- break;
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+ * uintxx_t val, int mmu_idx, uintptr_t ra)
+ */
+static void * const qemu_st_helpers[16] = {
+ [MO_UB] = helper_ret_stb_mmu,
+ [MO_LEUW] = helper_le_stw_mmu,
+ [MO_LEUL] = helper_le_stl_mmu,
+ [MO_LEQ] = helper_le_stq_mmu,
+ [MO_BEUW] = helper_be_stw_mmu,
+ [MO_BEUL] = helper_be_stl_mmu,
+ [MO_BEQ] = helper_be_stq_mmu,
+};
- default:
- tcg_abort();
+/* 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
+ containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
+
+static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
+ int mem_index, bool is_read)
+{
+ int cmp_off
+ = (is_read
+ ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
+ : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
+ int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
+ TCGReg base = TCG_AREG0;
+
+ /* Extract the page index, shifted into place for tlb index. */
+ if (TARGET_LONG_BITS == 32) {
+ /* Zero-extend the address into a place helpful for further use. */
+ tcg_out_ext32u(s, TCG_REG_R4, addr_reg);
+ addr_reg = TCG_REG_R4;
+ } else {
+ tcg_out_rld(s, RLDICL, TCG_REG_R3, addr_reg,
+ 64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
}
- op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
- if (imm) {
- tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
+ /* Compensate for very large offsets. */
+ if (add_off >= 0x8000) {
+ /* Most target env are smaller than 32k; none are larger than 64k.
+ Simplify the logic here merely to offset by 0x7ff0, giving us a
+ range just shy of 64k. Check this assumption. */
+ QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
+ tlb_table[NB_MMU_MODES - 1][1])
+ > 0x7ff0 + 0x7fff);
+ tcg_out32(s, ADDI | TAI(TCG_REG_R2, base, 0x7ff0));
+ base = TCG_REG_R2;
+ cmp_off -= 0x7ff0;
+ add_off -= 0x7ff0;
+ }
+
+ /* Extraction and shifting, part 2. */
+ if (TARGET_LONG_BITS == 32) {
+ tcg_out_rlw(s, RLWINM, TCG_REG_R3, addr_reg,
+ 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
+ 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
+ 31 - CPU_TLB_ENTRY_BITS);
} else {
- if (const_arg2) {
- tcg_out_movi(s, type, TCG_REG_R0, arg2);
- arg2 = TCG_REG_R0;
- }
- tcg_out32(s, op | RA(arg1) | RB(arg2));
+ tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);
}
-}
-static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
- TCGReg dst, TCGReg src)
-{
- tcg_out32(s, (type == TCG_TYPE_I64 ? CNTLZD : CNTLZW) | RS(src) | RA(dst));
- tcg_out_shri64(s, dst, dst, type == TCG_TYPE_I64 ? 6 : 5);
-}
+ tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
-static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
-{
- /* X != 0 implies X + -1 generates a carry. Extra addition
- trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C. */
- if (dst != src) {
- tcg_out32(s, ADDIC | TAI(dst, src, -1));
- tcg_out32(s, SUBFE | TAB(dst, dst, src));
+ /* Load the tlb comparator. */
+ tcg_out32(s, LD_ADDR | TAI(TCG_REG_R2, TCG_REG_R3, cmp_off));
+
+ /* Load the TLB addend for use on the fast path. Do this asap
+ to minimize any load use delay. */
+ tcg_out32(s, LD | TAI(TCG_REG_R3, TCG_REG_R3, add_off));
+
+ /* Clear the non-page, non-alignment bits from the address. */
+ if (TARGET_LONG_BITS == 32) {
+ tcg_out_rlw(s, RLWINM, TCG_REG_R0, addr_reg, 0,
+ (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
+ } else if (!s_bits) {
+ tcg_out_rld(s, RLDICR, TCG_REG_R0, addr_reg, 0, 63 - TARGET_PAGE_BITS);
} else {
- tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
- tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
+ tcg_out_rld(s, RLDICL, TCG_REG_R0, addr_reg,
+ 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
+ tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
}
+
+ tcg_out32(s, CMP | BF(7) | RA(TCG_REG_R0) | RB(TCG_REG_R2) | CMP_L);
+
+ return addr_reg;
}
-static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
- bool const_arg2)
+/* Record the context of a call to the out of line helper code for the slow
+ path for a load or store, so that we can later generate the correct
+ helper code. */
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
+ int data_reg, int addr_reg, int mem_index,
+ tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
{
- if (const_arg2) {
- if ((uint32_t)arg2 == arg2) {
- tcg_out_xori32(s, TCG_REG_R0, arg1, arg2);
- } else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, arg2);
- tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, TCG_REG_R0));
- }
- } else {
- tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, arg2));
- }
- return TCG_REG_R0;
+ TCGLabelQemuLdst *label = new_ldst_label(s);
+
+ label->is_ld = is_ld;
+ label->opc = opc;
+ label->datalo_reg = data_reg;
+ label->addrlo_reg = addr_reg;
+ label->mem_index = mem_index;
+ label->raddr = raddr;
+ label->label_ptr[0] = label_ptr;
}
-static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
- TCGArg arg0, TCGArg arg1, TCGArg arg2,
- int const_arg2)
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
- int crop, sh;
+ TCGMemOp opc = lb->opc;
- /* Ignore high bits of a potential constant arg2. */
- if (type == TCG_TYPE_I32) {
- arg2 = (uint32_t)arg2;
- }
+ reloc_pc14(lb->label_ptr[0], s->code_ptr);
- /* Handle common and trivial cases before handling anything else. */
- if (arg2 == 0) {
- switch (cond) {
- case TCG_COND_EQ:
- tcg_out_setcond_eq0(s, type, arg0, arg1);
- return;
- case TCG_COND_NE:
- if (type == TCG_TYPE_I32) {
- tcg_out_ext32u(s, TCG_REG_R0, arg1);
- arg1 = TCG_REG_R0;
- }
- tcg_out_setcond_ne0(s, arg0, arg1);
- return;
- case TCG_COND_GE:
- tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
- arg1 = arg0;
- /* FALLTHRU */
- case TCG_COND_LT:
- /* Extract the sign bit. */
- tcg_out_rld(s, RLDICL, arg0, arg1,
- type == TCG_TYPE_I64 ? 1 : 33, 63);
- return;
- default:
- break;
- }
- }
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
- /* If we have ISEL, we can implement everything with 3 or 4 insns.
- All other cases below are also at least 3 insns, so speed up the
- code generator by not considering them and always using ISEL. */
- if (HAVE_ISEL) {
- int isel, tab;
+ /* If the address needed to be zero-extended, we'll have already
+ placed it in R4. The only remaining case is 64-bit guest. */
+ tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
- tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
+ tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
- isel = tcg_to_isel[cond];
+ tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
- tcg_out_movi(s, type, arg0, 1);
- if (isel & 1) {
- /* arg0 = (bc ? 0 : 1) */
- tab = TAB(arg0, 0, arg0);
- isel &= ~1;
- } else {
- /* arg0 = (bc ? 1 : 0) */
- tcg_out_movi(s, type, TCG_REG_R0, 0);
- tab = TAB(arg0, arg0, TCG_REG_R0);
- }
- tcg_out32(s, isel | tab);
- return;
+ if (opc & MO_SIGN) {
+ uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
+ tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
+ } else {
+ tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
}
- switch (cond) {
- case TCG_COND_EQ:
- arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
- tcg_out_setcond_eq0(s, type, arg0, arg1);
- return;
+ tcg_out_b(s, 0, lb->raddr);
+}
- case TCG_COND_NE:
- arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
- /* Discard the high bits only once, rather than both inputs. */
- if (type == TCG_TYPE_I32) {
- tcg_out_ext32u(s, TCG_REG_R0, arg1);
- arg1 = TCG_REG_R0;
- }
- tcg_out_setcond_ne0(s, arg0, arg1);
- return;
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+ TCGMemOp opc = lb->opc;
+ TCGMemOp s_bits = opc & MO_SIZE;
- case TCG_COND_GT:
- case TCG_COND_GTU:
- sh = 30;
- crop = 0;
- goto crtest;
+ reloc_pc14(lb->label_ptr[0], s->code_ptr);
- case TCG_COND_LT:
- case TCG_COND_LTU:
- sh = 29;
- crop = 0;
- goto crtest;
+ tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
- case TCG_COND_GE:
- case TCG_COND_GEU:
- sh = 31;
- crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
- goto crtest;
+ /* If the address needed to be zero-extended, we'll have already
+ placed it in R4. The only remaining case is 64-bit guest. */
+ tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
- case TCG_COND_LE:
- case TCG_COND_LEU:
- sh = 31;
- crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
- crtest:
- tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
- if (crop) {
- tcg_out32(s, crop);
- }
- tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
- tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
- break;
+ tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
+ 0, 64 - (1 << (3 + s_bits)));
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
+ tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
- default:
- tcg_abort();
- }
+ tcg_out_call(s, qemu_st_helpers[opc]);
+
+ tcg_out_b(s, 0, lb->raddr);
}
+#endif /* SOFTMMU */
-static void tcg_out_bc(TCGContext *s, int bc, int label_index)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+ TCGMemOp opc, int mem_index)
{
- TCGLabel *l = &s->labels[label_index];
+ TCGReg rbase;
+ uint32_t insn;
+ TCGMemOp s_bits = opc & MO_SIZE;
+#ifdef CONFIG_SOFTMMU
+ tcg_insn_unit *label_ptr;
+#endif
- if (l->has_value) {
- tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
+#ifdef CONFIG_SOFTMMU
+ addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
+
+ /* Load a pointer into the current opcode w/conditional branch-link. */
+ label_ptr = s->code_ptr;
+ tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
+
+ rbase = TCG_REG_R3;
+#else /* !CONFIG_SOFTMMU */
+ rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
+ if (TARGET_LONG_BITS == 32) {
+ tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
+ addr_reg = TCG_REG_R2;
+ }
+#endif
+
+ insn = qemu_ldx_opc[opc];
+ if (!HAVE_ISA_2_06 && insn == LDBRX) {
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addr_reg, 4));
+ tcg_out32(s, LWBRX | TAB(data_reg, rbase, addr_reg));
+ tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
+ tcg_out_rld(s, RLDIMI, data_reg, TCG_REG_R0, 32, 0);
+ } else if (insn) {
+ tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
} else {
- tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
- tcg_out_bc_noaddr(s, bc);
+ insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
+ tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
+ insn = qemu_exts_opc[s_bits];
+ tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
}
-}
-static void tcg_out_brcond(TCGContext *s, TCGCond cond,
- TCGArg arg1, TCGArg arg2, int const_arg2,
- int label_index, TCGType type)
-{
- tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
- tcg_out_bc(s, tcg_to_bc[cond], label_index);
+#ifdef CONFIG_SOFTMMU
+ add_qemu_ldst_label(s, true, opc, data_reg, addr_reg, mem_index,
+ s->code_ptr, label_ptr);
+#endif
}
-static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
- TCGArg dest, TCGArg c1, TCGArg c2, TCGArg v1,
- TCGArg v2, bool const_c2)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+ TCGMemOp opc, int mem_index)
{
- /* If for some reason both inputs are zero, don't produce bad code. */
- if (v1 == 0 && v2 == 0) {
- tcg_out_movi(s, type, dest, 0);
- return;
- }
+ TCGReg rbase;
+ uint32_t insn;
+#ifdef CONFIG_SOFTMMU
+ tcg_insn_unit *label_ptr;
+#endif
- tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
+#ifdef CONFIG_SOFTMMU
+ addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
- if (HAVE_ISEL) {
- int isel = tcg_to_isel[cond];
+ /* Load a pointer into the current opcode w/conditional branch-link. */
+ label_ptr = s->code_ptr;
+ tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
- /* Swap the V operands if the operation indicates inversion. */
- if (isel & 1) {
- int t = v1;
- v1 = v2;
- v2 = t;
- isel &= ~1;
- }
- /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand. */
- if (v2 == 0) {
- tcg_out_movi(s, type, TCG_REG_R0, 0);
- }
- tcg_out32(s, isel | TAB(dest, v1, v2));
+ rbase = TCG_REG_R3;
+#else /* !CONFIG_SOFTMMU */
+ rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
+ if (TARGET_LONG_BITS == 32) {
+ tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
+ addr_reg = TCG_REG_R2;
+ }
+#endif
+
+ insn = qemu_stx_opc[opc];
+ if (!HAVE_ISA_2_06 && insn == STDBRX) {
+ tcg_out32(s, STWBRX | SAB(data_reg, rbase, addr_reg));
+ tcg_out32(s, ADDI | TAI(TCG_REG_R2, addr_reg, 4));
+ tcg_out_shri64(s, TCG_REG_R0, data_reg, 32);
+ tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
} else {
- if (dest == v2) {
- cond = tcg_invert_cond(cond);
- v2 = v1;
- } else if (dest != v1) {
- if (v1 == 0) {
- tcg_out_movi(s, type, dest, 0);
- } else {
- tcg_out_mov(s, type, dest, v1);
- }
- }
- /* Branch forward over one insn */
- tcg_out32(s, tcg_to_bc[cond] | 8);
- if (v2 == 0) {
- tcg_out_movi(s, type, dest, 0);
- } else {
- tcg_out_mov(s, type, dest, v2);
- }
+ tcg_out32(s, insn | SAB(data_reg, rbase, addr_reg));
}
+
+#ifdef CONFIG_SOFTMMU
+ add_qemu_ldst_label(s, false, opc, data_reg, addr_reg, mem_index,
+ s->code_ptr, label_ptr);
+#endif
}
-void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
+#define FRAME_SIZE ((int) \
+ ((8 /* back chain */ \
+ + 8 /* CR */ \
+ + 8 /* LR */ \
+ + 8 /* compiler doubleword */ \
+ + 8 /* link editor doubleword */ \
+ + 8 /* TOC save area */ \
+ + TCG_STATIC_CALL_ARGS_SIZE \
+ + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+ + ARRAY_SIZE(tcg_target_callee_save_regs) * 8 \
+ + 15) & ~15))
+
+#define REG_SAVE_BOT (FRAME_SIZE - ARRAY_SIZE(tcg_target_callee_save_regs) * 8)
+
+static void tcg_target_qemu_prologue(TCGContext *s)
{
- TCGContext s;
+ int i;
- s.code_buf = s.code_ptr = (tcg_insn_unit *)jmp_addr;
- tcg_out_b(&s, 0, (tcg_insn_unit *)addr);
- flush_icache_range(jmp_addr, jmp_addr + tcg_current_code_size(&s));
+ tcg_set_frame(s, TCG_REG_CALL_STACK,
+ REG_SAVE_BOT - CPU_TEMP_BUF_NLONGS * sizeof(long),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
+
+#ifndef __APPLE__
+ /* First emit adhoc function descriptor */
+ tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
+ tcg_out64(s, 0); /* toc */
+ tcg_out64(s, 0); /* environment pointer */
+#endif
+
+ /* Prologue */
+ tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
+ tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
+ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
+ tcg_out32(s, STD | SAI(tcg_target_callee_save_regs[i], 1,
+ REG_SAVE_BOT + i * 8));
+ }
+ tcg_out32(s, STD | SAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
+
+#ifdef CONFIG_USE_GUEST_BASE
+ if (GUEST_BASE) {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
+ tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+ }
+#endif
+
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+ tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
+ tcg_out32(s, BCCTR | BO_ALWAYS);
+
+ /* Epilogue */
+ tb_ret_addr = s->code_ptr;
+
+ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
+ tcg_out32(s, LD | TAI(tcg_target_callee_save_regs[i], TCG_REG_R1,
+ REG_SAVE_BOT + i * 8));
+ }
+ tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
+ tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
+ tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
+ tcg_out32(s, BCLR | BO_ALWAYS);
}
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 04/25] tcg-ppc64: Relax register restrictions in tcg_out_mem_long
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (2 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 03/25] tcg-ppc64: Move functions around Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-26 13:29 ` Greg Kurz
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 05/25] tcg-ppc64: Use tcg_out_{ld, st, cmp} internally Richard Henderson
` (21 subsequent siblings)
25 siblings, 1 reply; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
In order to be able to use tcg_out_ld/st sensibly with scratch
registers, assert only when we'd incorrectly clobber a scratch.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 951a392..dbe9c5c 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -714,10 +714,9 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
TCGReg base, tcg_target_long offset)
{
tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
+ bool is_store = false;
TCGReg rs = TCG_REG_R2;
- assert(rt != TCG_REG_R2 && base != TCG_REG_R2);
-
switch (opi) {
case LD: case LWA:
align = 3;
@@ -725,19 +724,22 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
default:
if (rt != TCG_REG_R0) {
rs = rt;
+ break;
}
break;
case STD:
align = 3;
- break;
+ /* FALLTHRU */
case STB: case STH: case STW:
+ is_store = true;
break;
}
/* For unaligned, or very large offsets, use the indexed form. */
if (offset & align || offset != (int32_t)offset) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, orig);
- tcg_out32(s, opx | TAB(rt, base, TCG_REG_R2));
+ tcg_debug_assert(rs != base && (!is_store || rs != rt));
+ tcg_out_movi(s, TCG_TYPE_PTR, rs, orig);
+ tcg_out32(s, opx | TAB(rt, base, rs));
return;
}
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 05/25] tcg-ppc64: Use tcg_out_{ld, st, cmp} internally
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (3 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 04/25] tcg-ppc64: Relax register restrictions in tcg_out_mem_long Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 06/25] tcg-ppc64: Make TCG_AREG0 and TCG_REG_CALL_STACK enum constants Richard Henderson
` (20 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Rather than using tcg_out32 and opcodes directly. This allows us
to remove LD_ADDR and CMP_L macros.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 33 ++++++++++++++-------------------
1 file changed, 14 insertions(+), 19 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index dbe9c5c..17f422e 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -27,6 +27,9 @@
/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
#define SZP ((int)sizeof(void *))
+/* Shorthand for size of a register. */
+#define SZR (TCG_TARGET_REG_BITS / 8)
+
#define TCG_CT_CONST_S16 0x100
#define TCG_CT_CONST_U16 0x200
#define TCG_CT_CONST_S32 0x400
@@ -36,14 +39,6 @@
static tcg_insn_unit *tb_ret_addr;
-#if TARGET_LONG_BITS == 32
-#define LD_ADDR LWZ
-#define CMP_L 0
-#else
-#define LD_ADDR LD
-#define CMP_L (1<<21)
-#endif
-
#ifndef GUEST_BASE
#define GUEST_BASE 0
#endif
@@ -1117,9 +1112,9 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
ofs = 0;
}
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg);
- tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R2, ofs));
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R2, ofs);
tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
- tcg_out32(s, LD | TAI(TCG_REG_R2, TCG_REG_R2, ofs + 8));
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_R2, ofs + SZP);
tcg_out32(s, BCCTR | BO_ALWAYS | LK);
}
#endif
@@ -1231,11 +1226,11 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
/* Load the tlb comparator. */
- tcg_out32(s, LD_ADDR | TAI(TCG_REG_R2, TCG_REG_R3, cmp_off));
+ tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_R2, TCG_REG_R3, cmp_off);
/* Load the TLB addend for use on the fast path. Do this asap
to minimize any load use delay. */
- tcg_out32(s, LD | TAI(TCG_REG_R3, TCG_REG_R3, add_off));
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3, add_off);
/* Clear the non-page, non-alignment bits from the address. */
if (TARGET_LONG_BITS == 32) {
@@ -1249,7 +1244,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
}
- tcg_out32(s, CMP | BF(7) | RA(TCG_REG_R0) | RB(TCG_REG_R2) | CMP_L);
+ tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_TL);
return addr_reg;
}
@@ -1444,10 +1439,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
- tcg_out32(s, STD | SAI(tcg_target_callee_save_regs[i], 1,
- REG_SAVE_BOT + i * 8));
+ tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+ TCG_REG_R1, REG_SAVE_BOT + i * SZR);
}
- tcg_out32(s, STD | SAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
+ tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16);
#ifdef CONFIG_USE_GUEST_BASE
if (GUEST_BASE) {
@@ -1464,10 +1459,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tb_ret_addr = s->code_ptr;
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
- tcg_out32(s, LD | TAI(tcg_target_callee_save_regs[i], TCG_REG_R1,
- REG_SAVE_BOT + i * 8));
+ tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+ TCG_REG_R1, REG_SAVE_BOT + i * SZR);
}
- tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16);
tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
tcg_out32(s, BCLR | BO_ALWAYS);
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 06/25] tcg-ppc64: Make TCG_AREG0 and TCG_REG_CALL_STACK enum constants
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (4 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 05/25] tcg-ppc64: Use tcg_out_{ld, st, cmp} internally Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 07/25] tcg-ppc64: Move call macros out of tcg-target.h Richard Henderson
` (19 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.h | 46 +++++++++++-----------------------------------
1 file changed, 11 insertions(+), 35 deletions(-)
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index f2360c8..57c6abc 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -28,42 +28,20 @@
#define TCG_TARGET_INSN_UNIT_SIZE 4
typedef enum {
- TCG_REG_R0 = 0,
- TCG_REG_R1,
- TCG_REG_R2,
- TCG_REG_R3,
- TCG_REG_R4,
- TCG_REG_R5,
- TCG_REG_R6,
- TCG_REG_R7,
- TCG_REG_R8,
- TCG_REG_R9,
- TCG_REG_R10,
- TCG_REG_R11,
- TCG_REG_R12,
- TCG_REG_R13,
- TCG_REG_R14,
- TCG_REG_R15,
- TCG_REG_R16,
- TCG_REG_R17,
- TCG_REG_R18,
- TCG_REG_R19,
- TCG_REG_R20,
- TCG_REG_R21,
- TCG_REG_R22,
- TCG_REG_R23,
- TCG_REG_R24,
- TCG_REG_R25,
- TCG_REG_R26,
- TCG_REG_R27,
- TCG_REG_R28,
- TCG_REG_R29,
- TCG_REG_R30,
- TCG_REG_R31
+ TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3,
+ TCG_REG_R4, TCG_REG_R5, TCG_REG_R6, TCG_REG_R7,
+ TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, TCG_REG_R11,
+ TCG_REG_R12, TCG_REG_R13, TCG_REG_R14, TCG_REG_R15,
+ TCG_REG_R16, TCG_REG_R17, TCG_REG_R18, TCG_REG_R19,
+ TCG_REG_R20, TCG_REG_R21, TCG_REG_R22, TCG_REG_R23,
+ TCG_REG_R24, TCG_REG_R25, TCG_REG_R26, TCG_REG_R27,
+ TCG_REG_R28, TCG_REG_R29, TCG_REG_R30, TCG_REG_R31,
+
+ TCG_REG_CALL_STACK = TCG_REG_R1,
+ TCG_AREG0 = TCG_REG_R27
} TCGReg;
/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_R1
#define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET 48
@@ -124,8 +102,6 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i64 1
#define TCG_TARGET_HAS_mulsh_i64 1
-#define TCG_AREG0 TCG_REG_R27
-
#define TCG_TARGET_EXTEND_ARGS 1
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 07/25] tcg-ppc64: Move call macros out of tcg-target.h
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (5 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 06/25] tcg-ppc64: Make TCG_AREG0 and TCG_REG_CALL_STACK enum constants Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 08/25] tcg-ppc64: Fix TCG_TARGET_CALL_STACK_OFFSET Richard Henderson
` (18 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
These values are private to tcg.c; we don't need to expose
this nonsense to the translators.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 5 +++++
tcg/ppc64/tcg-target.h | 6 ------
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 17f422e..c5362da 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1406,6 +1406,11 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
#endif
}
+/* Parameters for function call generation, used in tcg.c. */
+#define TCG_TARGET_STACK_ALIGN 16
+#define TCG_TARGET_CALL_STACK_OFFSET 48
+#define TCG_TARGET_EXTEND_ARGS 1
+
#define FRAME_SIZE ((int) \
((8 /* back chain */ \
+ 8 /* CR */ \
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 57c6abc..d3a1b53 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -41,10 +41,6 @@ typedef enum {
TCG_AREG0 = TCG_REG_R27
} TCGReg;
-/* used for function call generation */
-#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET 48
-
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi */
#define TCG_TARGET_HAS_ext16u_i32 0
@@ -102,6 +98,4 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i64 1
#define TCG_TARGET_HAS_mulsh_i64 1
-#define TCG_TARGET_EXTEND_ARGS 1
-
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 08/25] tcg-ppc64: Fix TCG_TARGET_CALL_STACK_OFFSET
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (6 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 07/25] tcg-ppc64: Move call macros out of tcg-target.h Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 09/25] tcg-ppc64: Better parameterize the stack frame Richard Henderson
` (17 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
The calling convention reserves space for the 8 register parameters on
the stack, so using only 6*8=48 as the offset was wrong. We never saw
this bug because we don't have any helpers with more than 5 parameters.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index c5362da..44abf7b 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1408,7 +1408,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
/* Parameters for function call generation, used in tcg.c. */
#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET 48
+#define TCG_TARGET_CALL_STACK_OFFSET ((6 + 8) * SZR)
#define TCG_TARGET_EXTEND_ARGS 1
#define FRAME_SIZE ((int) \
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 09/25] tcg-ppc64: Better parameterize the stack frame
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (7 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 08/25] tcg-ppc64: Fix TCG_TARGET_CALL_STACK_OFFSET Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 10/25] tcg-ppc64: Use the correct test in tcg_out_call Richard Henderson
` (16 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
In preparation for supporting other ABIs.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 64 ++++++++++++++++++++++++++++----------------------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 44abf7b..a198a70 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1408,46 +1408,53 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
/* Parameters for function call generation, used in tcg.c. */
#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET ((6 + 8) * SZR)
#define TCG_TARGET_EXTEND_ARGS 1
-#define FRAME_SIZE ((int) \
- ((8 /* back chain */ \
- + 8 /* CR */ \
- + 8 /* LR */ \
- + 8 /* compiler doubleword */ \
- + 8 /* link editor doubleword */ \
- + 8 /* TOC save area */ \
- + TCG_STATIC_CALL_ARGS_SIZE \
- + CPU_TEMP_BUF_NLONGS * sizeof(long) \
- + ARRAY_SIZE(tcg_target_callee_save_regs) * 8 \
- + 15) & ~15))
+#ifdef _CALL_AIX
+# define LINK_AREA_SIZE (6 * SZR)
+# define LR_OFFSET (1 * SZR)
+# define TCG_TARGET_CALL_STACK_OFFSET (LINK_AREA_SIZE + 8 * SZR)
+#else
+# error
+#endif
+
+#define CPU_TEMP_BUF_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
+#define REG_SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * SZR)
-#define REG_SAVE_BOT (FRAME_SIZE - ARRAY_SIZE(tcg_target_callee_save_regs) * 8)
+#define FRAME_SIZE ((TCG_TARGET_CALL_STACK_OFFSET \
+ + TCG_STATIC_CALL_ARGS_SIZE \
+ + CPU_TEMP_BUF_SIZE \
+ + REG_SAVE_SIZE \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+ & -TCG_TARGET_STACK_ALIGN)
+
+#define REG_SAVE_BOT (FRAME_SIZE - REG_SAVE_SIZE)
static void tcg_target_qemu_prologue(TCGContext *s)
{
int i;
- tcg_set_frame(s, TCG_REG_CALL_STACK,
- REG_SAVE_BOT - CPU_TEMP_BUF_NLONGS * sizeof(long),
- CPU_TEMP_BUF_NLONGS * sizeof(long));
+ tcg_set_frame(s, TCG_REG_CALL_STACK, REG_SAVE_BOT - CPU_TEMP_BUF_SIZE,
+ CPU_TEMP_BUF_SIZE);
-#ifndef __APPLE__
- /* First emit adhoc function descriptor */
- tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
- tcg_out64(s, 0); /* toc */
- tcg_out64(s, 0); /* environment pointer */
+#ifdef _CALL_AIX
+ {
+ void **desc = (void **)s->code_ptr;
+ desc[0] = desc + 2; /* entry point */
+ desc[1] = 0; /* environment pointer */
+ s->code_ptr = (void *)(desc + 2); /* skip over descriptor */
+ }
#endif
/* Prologue */
tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
+
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
TCG_REG_R1, REG_SAVE_BOT + i * SZR);
}
- tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16);
+ tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
#ifdef CONFIG_USE_GUEST_BASE
if (GUEST_BASE) {
@@ -1463,11 +1470,11 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* Epilogue */
tb_ret_addr = s->code_ptr;
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
TCG_REG_R1, REG_SAVE_BOT + i * SZR);
}
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16);
tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
tcg_out32(s, BCLR | BO_ALWAYS);
@@ -2158,19 +2165,20 @@ static DebugFrame debug_frame = {
.cie.id = -1,
.cie.version = 1,
.cie.code_align = 1,
- .cie.data_align = 0x78, /* sleb128 -8 */
+ .cie.data_align = (-SZR & 0x7f), /* sleb128 -SZR */
.cie.return_column = 65,
/* Total FDE size does not include the "len" member. */
.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
.fde_def_cfa = {
- 12, 1, /* DW_CFA_def_cfa r1, ... */
+ 12, TCG_REG_R1, /* DW_CFA_def_cfa r1, ... */
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
(FRAME_SIZE >> 7)
},
.fde_reg_ofs = {
- 0x11, 65, 0x7e, /* DW_CFA_offset_extended_sf, lr, 16 */
+ /* DW_CFA_offset_extended_sf, lr, LR_OFFSET */
+ 0x11, 65, (LR_OFFSET / -SZR) & 0x7f,
}
};
@@ -2181,10 +2189,10 @@ void tcg_register_jit(void *buf, size_t buf_size)
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i, p += 2) {
p[0] = 0x80 + tcg_target_callee_save_regs[i];
- p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * 8)) / 8;
+ p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * SZR)) / SZR;
}
- debug_frame.fde.func_start = (tcg_target_long) buf;
+ debug_frame.fde.func_start = (uintptr_t)buf;
debug_frame.fde.func_len = buf_size;
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 10/25] tcg-ppc64: Use the correct test in tcg_out_call
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (8 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 09/25] tcg-ppc64: Better parameterize the stack frame Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 11/25] tcg-ppc64: Support the ppc64 elfv2 ABI Richard Henderson
` (15 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
The correct test uses the _CALL_AIX macro, not a host-specific macro.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index a198a70..31c3a7a 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1089,9 +1089,7 @@ void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
{
-#ifdef __APPLE__
- tcg_out_b(s, LK, target);
-#else
+#ifdef _CALL_AIX
/* Look through the descriptor. If the branch is in range, and we
don't have to spend too much effort on building the toc. */
void *tgt = ((void **)target)[0];
@@ -1117,6 +1115,8 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_R2, ofs + SZP);
tcg_out32(s, BCCTR | BO_ALWAYS | LK);
}
+#else
+ tcg_out_b(s, LK, target);
#endif
}
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 11/25] tcg-ppc64: Support the ppc64 elfv2 ABI
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (9 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 10/25] tcg-ppc64: Use the correct test in tcg_out_call Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 12/25] tcg-ppc64: Adjust tcg_out_call for ELFv2 Richard Henderson
` (14 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 31c3a7a..d3cc237 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1414,6 +1414,10 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
# define LINK_AREA_SIZE (6 * SZR)
# define LR_OFFSET (1 * SZR)
# define TCG_TARGET_CALL_STACK_OFFSET (LINK_AREA_SIZE + 8 * SZR)
+#elif defined(_CALL_ELF) && _CALL_ELF == 2
+# define LINK_AREA_SIZE (4 * SZR)
+# define LR_OFFSET (1 * SZR)
+# define TCG_TARGET_CALL_STACK_OFFSET LINK_AREA_SIZE
#else
# error
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 12/25] tcg-ppc64: Adjust tcg_out_call for ELFv2
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (10 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 11/25] tcg-ppc64: Support the ppc64 elfv2 ABI Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 13/25] tcg-ppc64: Merge 32-bit ABIs into the prologue / frame code Richard Henderson
` (13 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474, Ulrich Weigand
From: Ulrich Weigand <ulrich.weigand@de.ibm.com>
The new ELFv2 ABI, used by default on powerpc64le-linux hosts,
introduced some changes that are incompatible with code currently
generated by the ppc64 TGC target. In particular, we no longer
use function descriptors.
This patch adds support for the ELFv2 ABI in the ppc64 TGC
function call and function prologue sequences.
Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index d3cc237..635ff98 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1115,6 +1115,23 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_R2, ofs + SZP);
tcg_out32(s, BCCTR | BO_ALWAYS | LK);
}
+#elif defined(_CALL_ELF) && _CALL_ELF == 2
+ intptr_t diff;
+
+ /* In the ELFv2 ABI, we have to set up r12 to contain the destination
+ address, which the callee uses to compute its TOC address. */
+ /* FIXME: when the branch is in range, we could avoid r12 load if we
+ knew that the destination uses the same TOC, and what its local
+ entry point offset is. */
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R12, (intptr_t)target);
+
+ diff = tcg_pcrel_diff(s, target);
+ if (in_range_b(diff)) {
+ tcg_out_b(s, LK, target);
+ } else {
+ tcg_out32(s, MTSPR | RS(TCG_REG_R12) | CTR);
+ tcg_out32(s, BCCTR | BO_ALWAYS | LK);
+ }
#else
tcg_out_b(s, LK, target);
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 13/25] tcg-ppc64: Merge 32-bit ABIs into the prologue / frame code
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (11 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 12/25] tcg-ppc64: Adjust tcg_out_call for ELFv2 Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 14/25] tcg-ppc64: Fix sub2 implementation Richard Henderson
` (12 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 39 ++++++++++++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 7 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 635ff98..8d932eb 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -24,6 +24,10 @@
#include "tcg-be-ldst.h"
+#if defined _CALL_DARWIN || defined __APPLE__
+#define TCG_TARGET_CALL_DARWIN
+#endif
+
/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
#define SZP ((int)sizeof(void *))
@@ -1431,12 +1435,26 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
# define LINK_AREA_SIZE (6 * SZR)
# define LR_OFFSET (1 * SZR)
# define TCG_TARGET_CALL_STACK_OFFSET (LINK_AREA_SIZE + 8 * SZR)
-#elif defined(_CALL_ELF) && _CALL_ELF == 2
-# define LINK_AREA_SIZE (4 * SZR)
-# define LR_OFFSET (1 * SZR)
+#elif TCG_TARGET_REG_BITS == 64
+# if defined(_CALL_ELF) && _CALL_ELF == 2
+# define LINK_AREA_SIZE (4 * SZR)
+# define LR_OFFSET (1 * SZR)
+# endif
+#else /* TCG_TARGET_REG_BITS == 32 */
+# if defined(_CALL_SYSV)
+# define TCG_TARGET_CALL_ALIGN_ARGS 1
+# define LINK_AREA_SIZE (2 * SZR)
+# define LR_OFFSET (1 * SZR)
+# elif defined(TCG_TARGET_CALL_DARWIN)
+# define LINK_AREA_SIZE 24
+# define LR_OFFSET 8
+# endif
+#endif
+#ifndef LR_OFFSET
+# error "Unhandled abi"
+#endif
+#ifndef TCG_TARGET_CALL_STACK_OFFSET
# define TCG_TARGET_CALL_STACK_OFFSET LINK_AREA_SIZE
-#else
-# error
#endif
#define CPU_TEMP_BUF_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
@@ -1469,7 +1487,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* Prologue */
tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
- tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
+ tcg_out32(s, (SZR == 8 ? STDU : STWU)
+ | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
@@ -2169,6 +2188,7 @@ static void tcg_target_init(TCGContext *s)
tcg_add_target_add_op_defs(ppc_op_defs);
}
+#ifdef __ELF__
typedef struct {
DebugFrameCIE cie;
DebugFrameFDEHeader fde;
@@ -2179,7 +2199,11 @@ typedef struct {
/* We're expecting a 2 byte uleb128 encoded value. */
QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
-#define ELF_HOST_MACHINE EM_PPC64
+#if TCG_TARGET_REG_BITS == 64
+# define ELF_HOST_MACHINE EM_PPC64
+#else
+# define ELF_HOST_MACHINE EM_PPC
+#endif
static DebugFrame debug_frame = {
.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
@@ -2218,3 +2242,4 @@ void tcg_register_jit(void *buf, size_t buf_size)
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
+#endif /* __ELF__ */
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 14/25] tcg-ppc64: Fix sub2 implementation
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (12 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 13/25] tcg-ppc64: Merge 32-bit ABIs into the prologue / frame code Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 15/25] tcg-ppc64: Begin merging ppc32 with ppc64 Richard Henderson
` (11 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
All sorts of confusion on argument ordering.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 8d932eb..22cfa1e 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -2009,18 +2009,18 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_sub2_i64:
a0 = args[0], a1 = args[1];
- if (a0 == args[5] || (!const_args[4] && a0 == args[4])) {
+ if (a0 == args[5] || (!const_args[3] && a0 == args[3])) {
a0 = TCG_REG_R0;
}
if (const_args[2]) {
- tcg_out32(s, SUBFIC | TAI(a0, args[3], args[2]));
+ tcg_out32(s, SUBFIC | TAI(a0, args[4], args[2]));
} else {
- tcg_out32(s, SUBFC | TAB(a0, args[3], args[2]));
+ tcg_out32(s, SUBFC | TAB(a0, args[4], args[2]));
}
- if (const_args[4]) {
- tcg_out32(s, (args[4] ? SUBFME : SUBFZE) | RT(a1) | RA(args[5]));
+ if (const_args[3]) {
+ tcg_out32(s, (args[3] ? SUBFME : SUBFZE) | RT(a1) | RA(args[5]));
} else {
- tcg_out32(s, SUBFE | TAB(a1, args[5], args[4]));
+ tcg_out32(s, SUBFE | TAB(a1, args[5], args[3]));
}
if (a0 != args[0]) {
tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
@@ -2146,7 +2146,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_deposit_i64, { "r", "0", "rZ" } },
{ INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
- { INDEX_op_sub2_i64, { "r", "r", "rI", "r", "rZM", "r" } },
+ { INDEX_op_sub2_i64, { "r", "r", "rI", "rZM", "r", "r" } },
{ INDEX_op_mulsh_i64, { "r", "r", "r" } },
{ INDEX_op_muluh_i64, { "r", "r", "r" } },
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 15/25] tcg-ppc64: Begin merging ppc32 with ppc64
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (13 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 14/25] tcg-ppc64: Fix sub2 implementation Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 16/25] tcg-ppc64: Merge ppc32 brcond2, setcond2, muluh Richard Henderson
` (10 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Just enough to compile, assuming you edit config-host.mak manually.
It will still abort at runtime, due to missing brcond2, setcond2, mulu2.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 104 +++++++++++++++++++++++++++++++------------------
tcg/ppc64/tcg-target.h | 20 +++++++---
2 files changed, 81 insertions(+), 43 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 22cfa1e..8152ccf 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -514,9 +514,9 @@ static const uint32_t tcg_to_isel[] = {
[TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
};
-static inline void tcg_out_mov(TCGContext *s, TCGType type,
- TCGReg ret, TCGReg arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
{
+ tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
if (ret != arg) {
tcg_out32(s, OR | SAB(arg, ret, arg));
}
@@ -566,13 +566,14 @@ static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
tcg_target_long arg)
{
+ tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
tcg_out_movi32(s, ret, arg);
} else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
tcg_out32(s, ADDI | TAI(ret, 0, arg));
tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
} else {
- int32_t high = arg >> 32;
+ int32_t high = arg >> 31 >> 1;
tcg_out_movi32(s, ret, high);
if (high) {
tcg_out_shli64(s, ret, ret, 32);
@@ -1984,7 +1985,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
args[3], args[4], const_args[2]);
break;
+#if TCG_TARGET_REG_BITS == 64
case INDEX_op_add2_i64:
+#else
+ case INDEX_op_add2_i32:
+#endif
/* Note that the CA bit is defined based on the word size of the
environment. So in 64-bit mode it's always carry-out of bit 63.
The fallback code using deposit works just as well for 32-bit. */
@@ -2007,7 +2012,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
}
break;
+#if TCG_TARGET_REG_BITS == 64
case INDEX_op_sub2_i64:
+#else
+ case INDEX_op_sub2_i32:
+#endif
a0 = args[0], a1 = args[1];
if (a0 == args[5] || (!const_args[3] && a0 == args[3])) {
a0 = TCG_REG_R0;
@@ -2054,21 +2063,10 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_ld16u_i32, { "r", "r" } },
{ INDEX_op_ld16s_i32, { "r", "r" } },
{ INDEX_op_ld_i32, { "r", "r" } },
- { INDEX_op_ld_i64, { "r", "r" } },
+
{ INDEX_op_st8_i32, { "r", "r" } },
- { INDEX_op_st8_i64, { "r", "r" } },
{ INDEX_op_st16_i32, { "r", "r" } },
- { INDEX_op_st16_i64, { "r", "r" } },
{ INDEX_op_st_i32, { "r", "r" } },
- { INDEX_op_st_i64, { "r", "r" } },
- { INDEX_op_st32_i64, { "r", "r" } },
-
- { INDEX_op_ld8u_i64, { "r", "r" } },
- { INDEX_op_ld8s_i64, { "r", "r" } },
- { INDEX_op_ld16u_i64, { "r", "r" } },
- { INDEX_op_ld16s_i64, { "r", "r" } },
- { INDEX_op_ld32u_i64, { "r", "r" } },
- { INDEX_op_ld32s_i64, { "r", "r" } },
{ INDEX_op_add_i32, { "r", "r", "ri" } },
{ INDEX_op_mul_i32, { "r", "r", "rI" } },
@@ -2090,11 +2088,32 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_rotl_i32, { "r", "r", "ri" } },
{ INDEX_op_rotr_i32, { "r", "r", "ri" } },
- { INDEX_op_brcond_i32, { "r", "ri" } },
- { INDEX_op_brcond_i64, { "r", "ri" } },
-
{ INDEX_op_neg_i32, { "r", "r" } },
{ INDEX_op_not_i32, { "r", "r" } },
+ { INDEX_op_ext8s_i32, { "r", "r" } },
+ { INDEX_op_ext16s_i32, { "r", "r" } },
+ { INDEX_op_bswap16_i32, { "r", "r" } },
+ { INDEX_op_bswap32_i32, { "r", "r" } },
+
+ { INDEX_op_brcond_i32, { "r", "ri" } },
+ { INDEX_op_setcond_i32, { "r", "r", "ri" } },
+ { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } },
+
+ { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+
+#if TCG_TARGET_REG_BITS == 64
+ { INDEX_op_ld8u_i64, { "r", "r" } },
+ { INDEX_op_ld8s_i64, { "r", "r" } },
+ { INDEX_op_ld16u_i64, { "r", "r" } },
+ { INDEX_op_ld16s_i64, { "r", "r" } },
+ { INDEX_op_ld32u_i64, { "r", "r" } },
+ { INDEX_op_ld32s_i64, { "r", "r" } },
+ { INDEX_op_ld_i64, { "r", "r" } },
+
+ { INDEX_op_st8_i64, { "r", "r" } },
+ { INDEX_op_st16_i64, { "r", "r" } },
+ { INDEX_op_st32_i64, { "r", "r" } },
+ { INDEX_op_st_i64, { "r", "r" } },
{ INDEX_op_add_i64, { "r", "r", "rT" } },
{ INDEX_op_sub_i64, { "r", "rI", "rT" } },
@@ -2119,36 +2138,47 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_neg_i64, { "r", "r" } },
{ INDEX_op_not_i64, { "r", "r" } },
-
- { INDEX_op_qemu_ld_i32, { "r", "L" } },
- { INDEX_op_qemu_ld_i64, { "r", "L" } },
- { INDEX_op_qemu_st_i32, { "S", "S" } },
- { INDEX_op_qemu_st_i64, { "S", "S" } },
-
- { INDEX_op_ext8s_i32, { "r", "r" } },
- { INDEX_op_ext16s_i32, { "r", "r" } },
{ INDEX_op_ext8s_i64, { "r", "r" } },
{ INDEX_op_ext16s_i64, { "r", "r" } },
{ INDEX_op_ext32s_i64, { "r", "r" } },
-
- { INDEX_op_setcond_i32, { "r", "r", "ri" } },
- { INDEX_op_setcond_i64, { "r", "r", "ri" } },
- { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } },
- { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } },
-
- { INDEX_op_bswap16_i32, { "r", "r" } },
{ INDEX_op_bswap16_i64, { "r", "r" } },
- { INDEX_op_bswap32_i32, { "r", "r" } },
{ INDEX_op_bswap32_i64, { "r", "r" } },
{ INDEX_op_bswap64_i64, { "r", "r" } },
- { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+ { INDEX_op_brcond_i64, { "r", "ri" } },
+ { INDEX_op_setcond_i64, { "r", "r", "ri" } },
+ { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } },
+
{ INDEX_op_deposit_i64, { "r", "0", "rZ" } },
- { INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
- { INDEX_op_sub2_i64, { "r", "r", "rI", "rZM", "r", "r" } },
{ INDEX_op_mulsh_i64, { "r", "r", "r" } },
{ INDEX_op_muluh_i64, { "r", "r", "r" } },
+#endif
+
+#if TCG_TARGET_REG_BITS == 64
+ { INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
+ { INDEX_op_sub2_i64, { "r", "r", "rI", "rZM", "r", "r" } },
+#else
+ { INDEX_op_add2_i32, { "r", "r", "r", "r", "rI", "rZM" } },
+ { INDEX_op_sub2_i32, { "r", "r", "rI", "rZM", "r", "r" } },
+#endif
+
+#if TCG_TARGET_REG_BITS == 64
+ { INDEX_op_qemu_ld_i32, { "r", "L" } },
+ { INDEX_op_qemu_st_i32, { "S", "S" } },
+ { INDEX_op_qemu_ld_i64, { "r", "L" } },
+ { INDEX_op_qemu_st_i64, { "S", "S" } },
+#elif TARGET_LONG_BITS == 32
+ { INDEX_op_qemu_ld_i32, { "r", "L" } },
+ { INDEX_op_qemu_st_i32, { "S", "S" } },
+ { INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
+ { INDEX_op_qemu_st_i64, { "S", "S", "S" } },
+#else
+ { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
+ { INDEX_op_qemu_st_i32, { "S", "S", "S" } },
+ { INDEX_op_qemu_ld_i64, { "r", "r", "L", "L" } },
+ { INDEX_op_qemu_st_i64, { "S", "S", "S", "S" } },
+#endif
{ -1 },
};
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index d3a1b53..726635f 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -24,6 +24,12 @@
#ifndef TCG_TARGET_PPC64
#define TCG_TARGET_PPC64 1
+#ifdef _ARCH_PPC64
+# define TCG_TARGET_REG_BITS 64
+#else
+# define TCG_TARGET_REG_BITS 32
+#endif
+
#define TCG_TARGET_NB_REGS 32
#define TCG_TARGET_INSN_UNIT_SIZE 4
@@ -44,9 +50,6 @@ typedef enum {
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi */
#define TCG_TARGET_HAS_ext16u_i32 0
-#define TCG_TARGET_HAS_ext8u_i64 0
-#define TCG_TARGET_HAS_ext16u_i64 0
-#define TCG_TARGET_HAS_ext32u_i64 0
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
@@ -65,20 +68,24 @@ typedef enum {
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_deposit_i32 1
#define TCG_TARGET_HAS_movcond_i32 1
-#define TCG_TARGET_HAS_add2_i32 0
-#define TCG_TARGET_HAS_sub2_i32 0
#define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
-#define TCG_TARGET_HAS_trunc_shr_i32 0
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_add2_i32 0
+#define TCG_TARGET_HAS_sub2_i32 0
+#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1
+#define TCG_TARGET_HAS_ext8u_i64 0
+#define TCG_TARGET_HAS_ext16u_i64 0
+#define TCG_TARGET_HAS_ext32u_i64 0
#define TCG_TARGET_HAS_bswap16_i64 1
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
@@ -97,5 +104,6 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i64 0
#define TCG_TARGET_HAS_muluh_i64 1
#define TCG_TARGET_HAS_mulsh_i64 1
+#endif
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 16/25] tcg-ppc64: Merge ppc32 brcond2, setcond2, muluh
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (14 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 15/25] tcg-ppc64: Begin merging ppc32 with ppc64 Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 17/25] tcg-ppc64: Merge ppc32 qemu_ld/st Richard Henderson
` (9 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Now passes tcg_add_target_add_op_defs assertions, but
not complete enough to function.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++-
tcg/ppc64/tcg-target.h | 2 +-
2 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 8152ccf..4b846a2 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -796,6 +796,8 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
int imm;
uint32_t op;
+ tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
+
/* Simplify the comparisons below wrt CMPI. */
if (type == TCG_TYPE_I32) {
arg2 = (int32_t)arg2;
@@ -1083,6 +1085,83 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
}
}
+static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
+ const int *const_args)
+{
+ static const struct { uint8_t bit1, bit2; } bits[] = {
+ [TCG_COND_LT ] = { CR_LT, CR_LT },
+ [TCG_COND_LE ] = { CR_LT, CR_GT },
+ [TCG_COND_GT ] = { CR_GT, CR_GT },
+ [TCG_COND_GE ] = { CR_GT, CR_LT },
+ [TCG_COND_LTU] = { CR_LT, CR_LT },
+ [TCG_COND_LEU] = { CR_LT, CR_GT },
+ [TCG_COND_GTU] = { CR_GT, CR_GT },
+ [TCG_COND_GEU] = { CR_GT, CR_LT },
+ };
+
+ TCGCond cond = args[4], cond2;
+ TCGArg al, ah, bl, bh;
+ int blconst, bhconst;
+ int op, bit1, bit2;
+
+ al = args[0];
+ ah = args[1];
+ bl = args[2];
+ bh = args[3];
+ blconst = const_args[2];
+ bhconst = const_args[3];
+
+ switch (cond) {
+ case TCG_COND_EQ:
+ op = CRAND;
+ goto do_equality;
+ case TCG_COND_NE:
+ op = CRNAND;
+ do_equality:
+ tcg_out_cmp(s, cond, al, bl, blconst, 6, TCG_TYPE_I32);
+ tcg_out_cmp(s, cond, ah, bh, bhconst, 7, TCG_TYPE_I32);
+ tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+ break;
+
+ case TCG_COND_LT:
+ case TCG_COND_LE:
+ case TCG_COND_GT:
+ case TCG_COND_GE:
+ case TCG_COND_LTU:
+ case TCG_COND_LEU:
+ case TCG_COND_GTU:
+ case TCG_COND_GEU:
+ bit1 = bits[cond].bit1;
+ bit2 = bits[cond].bit2;
+ op = (bit1 != bit2 ? CRANDC : CRAND);
+ cond2 = tcg_unsigned_cond(cond);
+
+ tcg_out_cmp(s, cond, ah, bh, bhconst, 6, TCG_TYPE_I32);
+ tcg_out_cmp(s, cond2, al, bl, blconst, 7, TCG_TYPE_I32);
+ tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, bit2));
+ tcg_out32(s, CROR | BT(7, CR_EQ) | BA(6, bit1) | BB(7, CR_EQ));
+ break;
+
+ default:
+ tcg_abort();
+ }
+}
+
+static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
+ const int *const_args)
+{
+ tcg_out_cmp2(s, args + 1, const_args + 1);
+ tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
+ tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, 31, 31, 31);
+}
+
+static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
+ const int *const_args)
+{
+ tcg_out_cmp2(s, args, const_args);
+ tcg_out_bc(s, BC | BI(7, CR_EQ) | BO_COND_TRUE, args[5]);
+}
+
void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
{
TCGContext s;
@@ -1760,11 +1839,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
args[3], TCG_TYPE_I32);
break;
-
case INDEX_op_brcond_i64:
tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
args[3], TCG_TYPE_I64);
break;
+ case INDEX_op_brcond2_i32:
+ tcg_out_brcond2(s, args, const_args);
+ break;
case INDEX_op_neg_i32:
case INDEX_op_neg_i64:
@@ -1886,6 +1967,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
const_args[2]);
break;
+ case INDEX_op_setcond2_i32:
+ tcg_out_setcond2(s, args, const_args);
+ break;
case INDEX_op_bswap16_i32:
case INDEX_op_bswap16_i64:
@@ -2036,6 +2120,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
}
break;
+ case INDEX_op_muluh_i32:
+ tcg_out32(s, MULHWU | TAB(args[0], args[1], args[2]));
+ break;
case INDEX_op_muluh_i64:
tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2]));
break;
@@ -2101,6 +2188,8 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+ { INDEX_op_muluh_i32, { "r", "r", "r" } },
+
#if TCG_TARGET_REG_BITS == 64
{ INDEX_op_ld8u_i64, { "r", "r" } },
{ INDEX_op_ld8s_i64, { "r", "r" } },
@@ -2155,6 +2244,11 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_muluh_i64, { "r", "r", "r" } },
#endif
+#if TCG_TARGET_REG_BITS == 32
+ { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
+ { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
+#endif
+
#if TCG_TARGET_REG_BITS == 64
{ INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
{ INDEX_op_sub2_i64, { "r", "r", "rI", "rZM", "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 726635f..7b90087 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -70,7 +70,7 @@ typedef enum {
#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0
-#define TCG_TARGET_HAS_muluh_i32 0
+#define TCG_TARGET_HAS_muluh_i32 1
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 17/25] tcg-ppc64: Merge ppc32 qemu_ld/st
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (15 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 16/25] tcg-ppc64: Merge ppc32 brcond2, setcond2, muluh Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 18/25] tcg-ppc64: Merge ppc32 register usage Richard Henderson
` (8 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 293 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 209 insertions(+), 84 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 4b846a2..c55339c 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -27,6 +27,9 @@
#if defined _CALL_DARWIN || defined __APPLE__
#define TCG_TARGET_CALL_DARWIN
#endif
+#ifdef _CALL_SYSV
+# define TCG_TARGET_CALL_ALIGN_ARGS 1
+#endif
/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
#define SZP ((int)sizeof(void *))
@@ -1280,7 +1283,8 @@ static void * const qemu_st_helpers[16] = {
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. */
-static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
+static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits,
+ TCGReg addrlo, TCGReg addrhi,
int mem_index, bool is_read)
{
int cmp_off
@@ -1291,13 +1295,15 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
TCGReg base = TCG_AREG0;
/* Extract the page index, shifted into place for tlb index. */
- if (TARGET_LONG_BITS == 32) {
- /* Zero-extend the address into a place helpful for further use. */
- tcg_out_ext32u(s, TCG_REG_R4, addr_reg);
- addr_reg = TCG_REG_R4;
- } else {
- tcg_out_rld(s, RLDICL, TCG_REG_R3, addr_reg,
- 64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
+ if (TCG_TARGET_REG_BITS == 64) {
+ if (TARGET_LONG_BITS == 32) {
+ /* Zero-extend the address into a place helpful for further use. */
+ tcg_out_ext32u(s, TCG_REG_R4, addrlo);
+ addrlo = TCG_REG_R4;
+ } else {
+ tcg_out_rld(s, RLDICL, TCG_REG_R3, addrlo,
+ 64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
+ }
}
/* Compensate for very large offsets. */
@@ -1315,8 +1321,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
}
/* Extraction and shifting, part 2. */
- if (TARGET_LONG_BITS == 32) {
- tcg_out_rlw(s, RLWINM, TCG_REG_R3, addr_reg,
+ if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {
+ tcg_out_rlw(s, RLWINM, TCG_REG_R3, addrlo,
32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
31 - CPU_TLB_ENTRY_BITS);
@@ -1327,69 +1333,101 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
/* Load the tlb comparator. */
- tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_R2, TCG_REG_R3, cmp_off);
+ if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+ tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R4, TCG_REG_R3, cmp_off);
+ tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R2, TCG_REG_R3, cmp_off + 4);
+ } else {
+ tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_R2, TCG_REG_R3, cmp_off);
+ }
/* Load the TLB addend for use on the fast path. Do this asap
to minimize any load use delay. */
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3, add_off);
/* Clear the non-page, non-alignment bits from the address. */
- if (TARGET_LONG_BITS == 32) {
- tcg_out_rlw(s, RLWINM, TCG_REG_R0, addr_reg, 0,
+ if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {
+ tcg_out_rlw(s, RLWINM, TCG_REG_R0, addrlo, 0,
(32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
} else if (!s_bits) {
- tcg_out_rld(s, RLDICR, TCG_REG_R0, addr_reg, 0, 63 - TARGET_PAGE_BITS);
+ tcg_out_rld(s, RLDICR, TCG_REG_R0, addrlo,
+ 0, 63 - TARGET_PAGE_BITS);
} else {
- tcg_out_rld(s, RLDICL, TCG_REG_R0, addr_reg,
+ tcg_out_rld(s, RLDICL, TCG_REG_R0, addrlo,
64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
}
- tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_TL);
+ if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+ tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_I32);
+ tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_R4, 0, 6, TCG_TYPE_I32);
+ tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+ } else {
+ tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_TL);
+ }
- return addr_reg;
+ return addrlo;
}
/* Record the context of a call to the out of line helper code for the slow
path for a load or store, so that we can later generate the correct
helper code. */
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
- int data_reg, int addr_reg, int mem_index,
- tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
+ TCGReg datalo_reg, TCGReg datahi_reg,
+ TCGReg addrlo_reg, TCGReg addrhi_reg,
+ int mem_index, tcg_insn_unit *raddr,
+ tcg_insn_unit *lptr)
{
TCGLabelQemuLdst *label = new_ldst_label(s);
label->is_ld = is_ld;
label->opc = opc;
- label->datalo_reg = data_reg;
- label->addrlo_reg = addr_reg;
+ label->datalo_reg = datalo_reg;
+ label->datahi_reg = datahi_reg;
+ label->addrlo_reg = addrlo_reg;
+ label->addrhi_reg = addrhi_reg;
label->mem_index = mem_index;
label->raddr = raddr;
- label->label_ptr[0] = label_ptr;
+ label->label_ptr[0] = lptr;
}
static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
TCGMemOp opc = lb->opc;
+ TCGReg hi, lo, arg = TCG_REG_R3;
reloc_pc14(lb->label_ptr[0], s->code_ptr);
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
+ tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
- /* If the address needed to be zero-extended, we'll have already
- placed it in R4. The only remaining case is 64-bit guest. */
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
+ lo = lb->addrlo_reg;
+ hi = lb->addrhi_reg;
+ if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+#ifdef TCG_TARGET_CALL_ALIGN_ARGS
+ arg |= 1;
+#endif
+ tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
+ tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
+ } else {
+ /* If the address needed to be zero-extended, we'll have already
+ placed it in R4. The only remaining case is 64-bit guest. */
+ tcg_out_mov(s, TCG_TYPE_TL, arg++, lo);
+ }
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
- tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
+ tcg_out_movi(s, TCG_TYPE_I32, arg++, lb->mem_index);
+ tcg_out32(s, MFSPR | RT(arg) | LR);
tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
- if (opc & MO_SIGN) {
+ lo = lb->datalo_reg;
+ hi = lb->datahi_reg;
+ if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
+ tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_REG_R4);
+ tcg_out_mov(s, TCG_TYPE_I32, hi, TCG_REG_R3);
+ } else if (opc & MO_SIGN) {
uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
- tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
+ tcg_out32(s, insn | RA(lo) | RS(TCG_REG_R3));
} else {
- tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
+ tcg_out_mov(s, TCG_TYPE_REG, lo, TCG_REG_R3);
}
tcg_out_b(s, 0, lb->raddr);
@@ -1399,19 +1437,53 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
TCGMemOp opc = lb->opc;
TCGMemOp s_bits = opc & MO_SIZE;
+ TCGReg hi, lo, arg = TCG_REG_R3;
reloc_pc14(lb->label_ptr[0], s->code_ptr);
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
+ tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
+
+ lo = lb->addrlo_reg;
+ hi = lb->addrhi_reg;
+ if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+#ifdef TCG_TARGET_CALL_ALIGN_ARGS
+ arg |= 1;
+#endif
+ tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
+ tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
+ } else {
+ /* If the address needed to be zero-extended, we'll have already
+ placed it in R4. The only remaining case is 64-bit guest. */
+ tcg_out_mov(s, TCG_TYPE_TL, arg++, lo);
+ }
- /* If the address needed to be zero-extended, we'll have already
- placed it in R4. The only remaining case is 64-bit guest. */
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
+ lo = lb->datalo_reg;
+ hi = lb->datahi_reg;
+ if (TCG_TARGET_REG_BITS == 32) {
+ switch (s_bits) {
+ case MO_64:
+#ifdef TCG_TARGET_CALL_ALIGN_ARGS
+ arg |= 1;
+#endif
+ tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
+ /* FALLTHRU */
+ case MO_32:
+ tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
+ break;
+ default:
+ tcg_out_rlw(s, RLWINM, arg++, lo, 0, 32 - (8 << s_bits), 31);
+ break;
+ }
+ } else {
+ if (s_bits == MO_64) {
+ tcg_out_mov(s, TCG_TYPE_I64, arg++, lo);
+ } else {
+ tcg_out_rld(s, RLDICL, arg++, lo, 0, 64 - (8 << s_bits));
+ }
+ }
- tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
- 0, 64 - (1 << (3 + s_bits)));
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
- tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
+ tcg_out_movi(s, TCG_TYPE_I32, arg++, lb->mem_index);
+ tcg_out32(s, MFSPR | RT(arg) | LR);
tcg_out_call(s, qemu_st_helpers[opc]);
@@ -1419,18 +1491,26 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
}
#endif /* SOFTMMU */
-static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
- TCGMemOp opc, int mem_index)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
{
- TCGReg rbase;
- uint32_t insn;
- TCGMemOp s_bits = opc & MO_SIZE;
+ TCGReg datalo, datahi, addrlo, rbase;
+ TCGReg addrhi __attribute__((unused));
+ TCGMemOp opc, s_bits;
#ifdef CONFIG_SOFTMMU
+ int mem_index;
tcg_insn_unit *label_ptr;
#endif
+ datalo = *args++;
+ datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
+ addrlo = *args++;
+ addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
+ opc = *args++;
+ s_bits = opc & MO_SIZE;
+
#ifdef CONFIG_SOFTMMU
- addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
+ mem_index = *args;
+ addrlo = tcg_out_tlb_read(s, s_bits, addrlo, addrhi, mem_index, true);
/* Load a pointer into the current opcode w/conditional branch-link. */
label_ptr = s->code_ptr;
@@ -1439,44 +1519,71 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
rbase = TCG_REG_R3;
#else /* !CONFIG_SOFTMMU */
rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
- if (TARGET_LONG_BITS == 32) {
- tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
- addr_reg = TCG_REG_R2;
+ if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
+ tcg_out_ext32u(s, TCG_REG_R2, addrlo);
+ addrlo = TCG_REG_R2;
}
#endif
- insn = qemu_ldx_opc[opc];
- if (!HAVE_ISA_2_06 && insn == LDBRX) {
- tcg_out32(s, ADDI | TAI(TCG_REG_R0, addr_reg, 4));
- tcg_out32(s, LWBRX | TAB(data_reg, rbase, addr_reg));
- tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
- tcg_out_rld(s, RLDIMI, data_reg, TCG_REG_R0, 32, 0);
- } else if (insn) {
- tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
+ if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
+ if (opc & MO_BSWAP) {
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+ tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
+ tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
+ } else if (rbase != 0) {
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+ tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
+ tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
+ } else if (addrlo == datahi) {
+ tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
+ tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
+ } else {
+ tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
+ tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
+ }
} else {
- insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
- tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
- insn = qemu_exts_opc[s_bits];
- tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
+ uint32_t insn = qemu_ldx_opc[opc];
+ if (!HAVE_ISA_2_06 && insn == LDBRX) {
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+ tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
+ tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
+ tcg_out_rld(s, RLDIMI, datalo, TCG_REG_R0, 32, 0);
+ } else if (insn) {
+ tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
+ } else {
+ insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
+ tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
+ insn = qemu_exts_opc[s_bits];
+ tcg_out32(s, insn | RA(datalo) | RS(datalo));
+ }
}
#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, true, opc, data_reg, addr_reg, mem_index,
- s->code_ptr, label_ptr);
+ add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo, addrhi,
+ mem_index, s->code_ptr, label_ptr);
#endif
}
-static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
- TCGMemOp opc, int mem_index)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
{
- TCGReg rbase;
- uint32_t insn;
+ TCGReg datalo, datahi, addrlo, rbase;
+ TCGReg addrhi __attribute__((unused));
+ TCGMemOp opc, s_bits;
#ifdef CONFIG_SOFTMMU
+ int mem_index;
tcg_insn_unit *label_ptr;
#endif
+ datalo = *args++;
+ datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
+ addrlo = *args++;
+ addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
+ opc = *args++;
+ s_bits = opc & MO_SIZE;
+
#ifdef CONFIG_SOFTMMU
- addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
+ mem_index = *args;
+ addrlo = tcg_out_tlb_read(s, s_bits, addrlo, addrhi, mem_index, false);
/* Load a pointer into the current opcode w/conditional branch-link. */
label_ptr = s->code_ptr;
@@ -1485,25 +1592,40 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
rbase = TCG_REG_R3;
#else /* !CONFIG_SOFTMMU */
rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
- if (TARGET_LONG_BITS == 32) {
- tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
- addr_reg = TCG_REG_R2;
+ if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
+ tcg_out_ext32u(s, TCG_REG_R2, addrlo);
+ addrlo = TCG_REG_R2;
}
#endif
- insn = qemu_stx_opc[opc];
- if (!HAVE_ISA_2_06 && insn == STDBRX) {
- tcg_out32(s, STWBRX | SAB(data_reg, rbase, addr_reg));
- tcg_out32(s, ADDI | TAI(TCG_REG_R2, addr_reg, 4));
- tcg_out_shri64(s, TCG_REG_R0, data_reg, 32);
- tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
+ if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
+ if (opc & MO_BSWAP) {
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+ tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
+ tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0));
+ } else if (rbase != 0) {
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+ tcg_out32(s, STWX | SAB(datahi, rbase, addrlo));
+ tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0));
+ } else {
+ tcg_out32(s, STW | TAI(datahi, addrlo, 0));
+ tcg_out32(s, STW | TAI(datalo, addrlo, 4));
+ }
} else {
- tcg_out32(s, insn | SAB(data_reg, rbase, addr_reg));
+ uint32_t insn = qemu_stx_opc[opc];
+ if (!HAVE_ISA_2_06 && insn == STDBRX) {
+ tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
+ tcg_out32(s, ADDI | TAI(TCG_REG_R2, addrlo, 4));
+ tcg_out_shri64(s, TCG_REG_R0, datalo, 32);
+ tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
+ } else {
+ tcg_out32(s, insn | SAB(datalo, rbase, addrlo));
+ }
}
#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, false, opc, data_reg, addr_reg, mem_index,
- s->code_ptr, label_ptr);
+ add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
+ mem_index, s->code_ptr, label_ptr);
#endif
}
@@ -1522,7 +1644,6 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
# endif
#else /* TCG_TARGET_REG_BITS == 32 */
# if defined(_CALL_SYSV)
-# define TCG_TARGET_CALL_ALIGN_ARGS 1
# define LINK_AREA_SIZE (2 * SZR)
# define LR_OFFSET (1 * SZR)
# elif defined(TCG_TARGET_CALL_DARWIN)
@@ -1936,12 +2057,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
break;
case INDEX_op_qemu_ld_i32:
+ tcg_out_qemu_ld(s, args, false);
+ break;
case INDEX_op_qemu_ld_i64:
- tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3]);
+ tcg_out_qemu_ld(s, args, true);
break;
case INDEX_op_qemu_st_i32:
+ tcg_out_qemu_st(s, args, false);
+ break;
case INDEX_op_qemu_st_i64:
- tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
+ tcg_out_qemu_st(s, args, true);
break;
case INDEX_op_ext8s_i32:
@@ -2265,12 +2390,12 @@ static const TCGTargetOpDef ppc_op_defs[] = {
#elif TARGET_LONG_BITS == 32
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
{ INDEX_op_qemu_st_i32, { "S", "S" } },
- { INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
+ { INDEX_op_qemu_ld_i64, { "L", "L", "L" } },
{ INDEX_op_qemu_st_i64, { "S", "S", "S" } },
#else
{ INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
{ INDEX_op_qemu_st_i32, { "S", "S", "S" } },
- { INDEX_op_qemu_ld_i64, { "r", "r", "L", "L" } },
+ { INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
{ INDEX_op_qemu_st_i64, { "S", "S", "S", "S" } },
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 18/25] tcg-ppc64: Merge ppc32 register usage
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (16 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 17/25] tcg-ppc64: Merge ppc32 qemu_ld/st Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 19/25] tcg-ppc64: Support mulsh_i32 Richard Henderson
` (7 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Good enough to run some instructions before things go awry.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 61 ++++++++++++++++++++++++++++++++------------------
1 file changed, 39 insertions(+), 22 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index c55339c..a5ad140 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -31,6 +31,16 @@
# define TCG_TARGET_CALL_ALIGN_ARGS 1
#endif
+/* For some memory operations, we need a scratch that isn't R0. For the AIX
+ calling convention, we can re-use the TOC register since we'll be reloading
+ it at every call. Otherwise R12 will do nicely as neither a call-saved
+ register nor a parameter register. */
+#ifdef _CALL_AIX
+# define TCG_REG_TMP1 TCG_REG_R2
+#else
+# define TCG_REG_TMP1 TCG_REG_R12
+#endif
+
/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
#define SZP ((int)sizeof(void *))
@@ -119,6 +129,8 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R31,
TCG_REG_R12, /* call clobbered, non-arguments */
TCG_REG_R11,
+ TCG_REG_R2,
+ TCG_REG_R13,
TCG_REG_R10, /* call clobbered, arguments */
TCG_REG_R9,
TCG_REG_R8,
@@ -141,11 +153,12 @@ static const int tcg_target_call_iarg_regs[] = {
};
static const int tcg_target_call_oarg_regs[] = {
- TCG_REG_R3
+ TCG_REG_R3,
+ TCG_REG_R4
};
static const int tcg_target_callee_save_regs[] = {
-#ifdef __APPLE__
+#ifdef TCG_TARGET_CALL_DARWIN
TCG_REG_R11,
#endif
TCG_REG_R14,
@@ -718,7 +731,7 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
{
tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
bool is_store = false;
- TCGReg rs = TCG_REG_R2;
+ TCGReg rs = TCG_REG_TMP1;
switch (opi) {
case LD: case LWA:
@@ -1184,7 +1197,7 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
intptr_t diff = tcg_pcrel_diff(s, tgt);
if (in_range_b(diff) && toc == (uint32_t)toc) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, toc);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, toc);
tcg_out_b(s, LK, tgt);
} else {
/* Fold the low bits of the constant into the addresses below. */
@@ -1196,10 +1209,10 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
} else {
ofs = 0;
}
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg);
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R2, ofs);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, arg);
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_TMP1, ofs);
tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_R2, ofs + SZP);
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_TMP1, ofs + SZP);
tcg_out32(s, BCCTR | BO_ALWAYS | LK);
}
#elif defined(_CALL_ELF) && _CALL_ELF == 2
@@ -1314,8 +1327,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits,
QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
tlb_table[NB_MMU_MODES - 1][1])
> 0x7ff0 + 0x7fff);
- tcg_out32(s, ADDI | TAI(TCG_REG_R2, base, 0x7ff0));
- base = TCG_REG_R2;
+ tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, base, 0x7ff0));
+ base = TCG_REG_TMP1;
cmp_off -= 0x7ff0;
add_off -= 0x7ff0;
}
@@ -1335,9 +1348,9 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits,
/* Load the tlb comparator. */
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R4, TCG_REG_R3, cmp_off);
- tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R2, TCG_REG_R3, cmp_off + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP1, TCG_REG_R3, cmp_off + 4);
} else {
- tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_R2, TCG_REG_R3, cmp_off);
+ tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP1, TCG_REG_R3, cmp_off);
}
/* Load the TLB addend for use on the fast path. Do this asap
@@ -1358,11 +1371,13 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits,
}
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
- tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_I32);
+ tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,
+ 0, 7, TCG_TYPE_I32);
tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_R4, 0, 6, TCG_TYPE_I32);
tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
} else {
- tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_TL);
+ tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,
+ 0, 7, TCG_TYPE_TL);
}
return addrlo;
@@ -1520,8 +1535,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
#else /* !CONFIG_SOFTMMU */
rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
- tcg_out_ext32u(s, TCG_REG_R2, addrlo);
- addrlo = TCG_REG_R2;
+ tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
+ addrlo = TCG_REG_TMP1;
}
#endif
@@ -1593,8 +1608,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
#else /* !CONFIG_SOFTMMU */
rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
- tcg_out_ext32u(s, TCG_REG_R2, addrlo);
- addrlo = TCG_REG_R2;
+ tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
+ addrlo = TCG_REG_TMP1;
}
#endif
@@ -1615,9 +1630,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
uint32_t insn = qemu_stx_opc[opc];
if (!HAVE_ISA_2_06 && insn == STDBRX) {
tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
- tcg_out32(s, ADDI | TAI(TCG_REG_R2, addrlo, 4));
+ tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, addrlo, 4));
tcg_out_shri64(s, TCG_REG_R0, datalo, 32);
- tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
+ tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_TMP1));
} else {
tcg_out32(s, insn | SAB(datalo, rbase, addrlo));
}
@@ -2428,11 +2443,13 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* mem temp */
-#ifdef __APPLE__
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_R11); /* ??? */
+#if defined(_CALL_SYSV)
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* toc pointer */
#endif
+#if defined(_CALL_SYSV) || TCG_TARGET_REG_BITS == 64
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
+#endif
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); /* mem temp */
tcg_add_target_add_op_defs(ppc_op_defs);
}
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 19/25] tcg-ppc64: Support mulsh_i32
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (17 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 18/25] tcg-ppc64: Merge ppc32 register usage Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 20/25] tcg-ppc64: Merge ppc32 shifts Richard Henderson
` (6 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 5 +++++
tcg/ppc64/tcg-target.h | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index a5ad140..02ee8e2 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -410,6 +410,7 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
#define OR XO31(444)
#define XOR XO31(316)
#define MULLW XO31(235)
+#define MULHW XO31( 75)
#define MULHWU XO31( 11)
#define DIVW XO31(491)
#define DIVWU XO31(459)
@@ -2263,6 +2264,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_muluh_i32:
tcg_out32(s, MULHWU | TAB(args[0], args[1], args[2]));
break;
+ case INDEX_op_mulsh_i32:
+ tcg_out32(s, MULHW | TAB(args[0], args[1], args[2]));
+ break;
case INDEX_op_muluh_i64:
tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2]));
break;
@@ -2329,6 +2333,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_muluh_i32, { "r", "r", "r" } },
+ { INDEX_op_mulsh_i32, { "r", "r", "r" } },
#if TCG_TARGET_REG_BITS == 64
{ INDEX_op_ld8u_i64, { "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 7b90087..066e74b 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -71,7 +71,7 @@ typedef enum {
#define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 1
-#define TCG_TARGET_HAS_mulsh_i32 0
+#define TCG_TARGET_HAS_mulsh_i32 1
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_add2_i32 0
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 20/25] tcg-ppc64: Merge ppc32 shifts
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (18 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 19/25] tcg-ppc64: Support mulsh_i32 Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 21/25] tcg-ppc: Remove the backend Richard Henderson
` (5 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc64/tcg-target.c | 40 ++++++++++++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 02ee8e2..46d5c4c 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -542,6 +542,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
int sh, int mb)
{
+ assert(TCG_TARGET_REG_BITS == 64);
sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);
mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));
tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);
@@ -558,11 +559,21 @@ static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
tcg_out_rld(s, RLDICL, dst, src, 0, 32);
}
+static inline void tcg_out_shli32(TCGContext *s, TCGReg dst, TCGReg src, int c)
+{
+ tcg_out_rlw(s, RLWINM, dst, src, c, 0, 31 - c);
+}
+
static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
{
tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
}
+static inline void tcg_out_shri32(TCGContext *s, TCGReg dst, TCGReg src, int c)
+{
+ tcg_out_rlw(s, RLWINM, dst, src, 32 - c, c, 31);
+}
+
static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
{
tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
@@ -674,6 +685,7 @@ static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
{
int mb, me;
+ assert(TCG_TARGET_REG_BITS == 64);
if ((c & 0xffff) == c) {
tcg_out32(s, ANDI | SAI(src, dst, c));
return;
@@ -786,6 +798,7 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
{
int opi, opx;
+ assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
if (type == TCG_TYPE_I32) {
opi = LWZ, opx = LWZX;
} else {
@@ -799,6 +812,7 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
{
int opi, opx;
+ assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
if (type == TCG_TYPE_I32) {
opi = STW, opx = STWX;
} else {
@@ -887,8 +901,13 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
TCGReg dst, TCGReg src)
{
- tcg_out32(s, (type == TCG_TYPE_I64 ? CNTLZD : CNTLZW) | RS(src) | RA(dst));
- tcg_out_shri64(s, dst, dst, type == TCG_TYPE_I64 ? 6 : 5);
+ if (type == TCG_TYPE_I32) {
+ tcg_out32(s, CNTLZW | RS(src) | RA(dst));
+ tcg_out_shri32(s, dst, dst, 5);
+ } else {
+ tcg_out32(s, CNTLZD | RS(src) | RA(dst));
+ tcg_out_shri64(s, dst, dst, 6);
+ }
}
static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
@@ -926,6 +945,8 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
{
int crop, sh;
+ assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
+
/* Ignore high bits of a potential constant arg2. */
if (type == TCG_TYPE_I32) {
arg2 = (uint32_t)arg2;
@@ -938,7 +959,7 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
tcg_out_setcond_eq0(s, type, arg0, arg1);
return;
case TCG_COND_NE:
- if (type == TCG_TYPE_I32) {
+ if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
tcg_out_ext32u(s, TCG_REG_R0, arg1);
arg1 = TCG_REG_R0;
}
@@ -950,8 +971,11 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
/* FALLTHRU */
case TCG_COND_LT:
/* Extract the sign bit. */
- tcg_out_rld(s, RLDICL, arg0, arg1,
- type == TCG_TYPE_I64 ? 1 : 33, 63);
+ if (type == TCG_TYPE_I32) {
+ tcg_out_shri32(s, arg0, arg1, 31);
+ } else {
+ tcg_out_shri64(s, arg0, arg1, 63);
+ }
return;
default:
break;
@@ -991,7 +1015,7 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
case TCG_COND_NE:
arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
/* Discard the high bits only once, rather than both inputs. */
- if (type == TCG_TYPE_I32) {
+ if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
tcg_out_ext32u(s, TCG_REG_R0, arg1);
arg1 = TCG_REG_R0;
}
@@ -1935,14 +1959,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_shl_i32:
if (const_args[2]) {
- tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
+ tcg_out_shli32(s, args[0], args[1], args[2]);
} else {
tcg_out32(s, SLW | SAB(args[1], args[0], args[2]));
}
break;
case INDEX_op_shr_i32:
if (const_args[2]) {
- tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
+ tcg_out_shri32(s, args[0], args[1], args[2]);
} else {
tcg_out32(s, SRW | SAB(args[1], args[0], args[2]));
}
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 21/25] tcg-ppc: Remove the backend
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (19 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 20/25] tcg-ppc64: Merge ppc32 shifts Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 22/25] tcg-ppc: Rename the tcg/ppc64 backend Richard Henderson
` (4 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Vectoring the 32-bit build to the ppc64 directory.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
configure | 2 +
tcg/ppc/tcg-target.c | 1933 --------------------------------------------------
tcg/ppc/tcg-target.h | 109 ---
3 files changed, 2 insertions(+), 2042 deletions(-)
delete mode 100644 tcg/ppc/tcg-target.c
delete mode 100644 tcg/ppc/tcg-target.h
diff --git a/configure b/configure
index a69e90b..277eab4 100755
--- a/configure
+++ b/configure
@@ -4716,6 +4716,8 @@ elif test "$ARCH" = "s390x" ; then
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES"
elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES"
+elif test "$ARCH" = "ppc" ; then
+ QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/ppc64 $QEMU_INCLUDES"
else
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES"
fi
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
deleted file mode 100644
index d64eaa5..0000000
--- a/tcg/ppc/tcg-target.c
+++ /dev/null
@@ -1,1933 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "tcg-be-ldst.h"
-
-static tcg_insn_unit *tb_ret_addr;
-
-#if defined _CALL_DARWIN || defined __APPLE__
-#define TCG_TARGET_CALL_DARWIN
-#endif
-
-#ifdef TCG_TARGET_CALL_DARWIN
-#define LINKAGE_AREA_SIZE 24
-#define LR_OFFSET 8
-#elif defined _CALL_AIX
-#define LINKAGE_AREA_SIZE 52
-#define LR_OFFSET 8
-#else
-#define LINKAGE_AREA_SIZE 8
-#define LR_OFFSET 4
-#endif
-
-#ifndef GUEST_BASE
-#define GUEST_BASE 0
-#endif
-
-#ifdef CONFIG_USE_GUEST_BASE
-#define TCG_GUEST_BASE_REG 30
-#else
-#define TCG_GUEST_BASE_REG 0
-#endif
-
-#ifndef NDEBUG
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
- "r0",
- "r1",
- "r2",
- "r3",
- "r4",
- "r5",
- "r6",
- "r7",
- "r8",
- "r9",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15",
- "r16",
- "r17",
- "r18",
- "r19",
- "r20",
- "r21",
- "r22",
- "r23",
- "r24",
- "r25",
- "r26",
- "r27",
- "r28",
- "r29",
- "r30",
- "r31"
-};
-#endif
-
-static const int tcg_target_reg_alloc_order[] = {
- TCG_REG_R14,
- TCG_REG_R15,
- TCG_REG_R16,
- TCG_REG_R17,
- TCG_REG_R18,
- TCG_REG_R19,
- TCG_REG_R20,
- TCG_REG_R21,
- TCG_REG_R22,
- TCG_REG_R23,
- TCG_REG_R28,
- TCG_REG_R29,
- TCG_REG_R30,
- TCG_REG_R31,
-#ifdef TCG_TARGET_CALL_DARWIN
- TCG_REG_R2,
-#endif
- TCG_REG_R3,
- TCG_REG_R4,
- TCG_REG_R5,
- TCG_REG_R6,
- TCG_REG_R7,
- TCG_REG_R8,
- TCG_REG_R9,
- TCG_REG_R10,
-#ifndef TCG_TARGET_CALL_DARWIN
- TCG_REG_R11,
-#endif
- TCG_REG_R12,
-#ifndef _CALL_SYSV
- TCG_REG_R13,
-#endif
- TCG_REG_R24,
- TCG_REG_R25,
- TCG_REG_R26,
- TCG_REG_R27
-};
-
-static const int tcg_target_call_iarg_regs[] = {
- TCG_REG_R3,
- TCG_REG_R4,
- TCG_REG_R5,
- TCG_REG_R6,
- TCG_REG_R7,
- TCG_REG_R8,
- TCG_REG_R9,
- TCG_REG_R10
-};
-
-static const int tcg_target_call_oarg_regs[2] = {
- TCG_REG_R3,
- TCG_REG_R4
-};
-
-static const int tcg_target_callee_save_regs[] = {
-#ifdef TCG_TARGET_CALL_DARWIN
- TCG_REG_R11,
- TCG_REG_R13,
-#endif
-#ifdef _CALL_AIX
- TCG_REG_R13,
-#endif
- TCG_REG_R14,
- TCG_REG_R15,
- TCG_REG_R16,
- TCG_REG_R17,
- TCG_REG_R18,
- TCG_REG_R19,
- TCG_REG_R20,
- TCG_REG_R21,
- TCG_REG_R22,
- TCG_REG_R23,
- TCG_REG_R24,
- TCG_REG_R25,
- TCG_REG_R26,
- TCG_REG_R27, /* currently used for the global env */
- TCG_REG_R28,
- TCG_REG_R29,
- TCG_REG_R30,
- TCG_REG_R31
-};
-
-static inline bool in_range_b(tcg_target_long target)
-{
- return target == sextract32(target, 0, 26);
-}
-
-static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
- ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
- assert(in_range_b(disp));
- return disp & 0x3fffffc;
-}
-
-static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
- *pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target);
-}
-
-static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
- ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
- assert(disp == (int16_t) disp);
- return disp & 0xfffc;
-}
-
-static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
- *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
-}
-
-static void patch_reloc(tcg_insn_unit *code_ptr, int type,
- intptr_t value, intptr_t addend)
-{
- tcg_insn_unit *target = (tcg_insn_unit *)value;
-
- assert(addend == 0);
- switch (type) {
- case R_PPC_REL14:
- reloc_pc14(code_ptr, target);
- break;
- case R_PPC_REL24:
- reloc_pc24(code_ptr, target);
- break;
- default:
- tcg_abort();
- }
-}
-
-/* parse target specific constraints */
-static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
-{
- const char *ct_str;
-
- ct_str = *pct_str;
- switch (ct_str[0]) {
- case 'A': case 'B': case 'C': case 'D':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
- break;
- case 'r':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
- break;
-#ifdef CONFIG_SOFTMMU
- case 'L': /* qemu_ld constraint */
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
-#if TARGET_LONG_BITS == 64
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
-#endif
-#endif
- break;
- case 'K': /* qemu_st[8..32] constraint */
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
-#if TARGET_LONG_BITS == 64
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R8);
-#endif
-#endif
- break;
- case 'M': /* qemu_st64 constraint */
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R8);
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R9);
-#endif
- break;
-#else
- case 'L':
- case 'K':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
- break;
- case 'M':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
- break;
-#endif
- default:
- return -1;
- }
- ct_str++;
- *pct_str = ct_str;
- return 0;
-}
-
-/* test if a constant matches the constraint */
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
- const TCGArgConstraint *arg_ct)
-{
- int ct;
-
- ct = arg_ct->ct;
- if (ct & TCG_CT_CONST)
- return 1;
- return 0;
-}
-
-#define OPCD(opc) ((opc)<<26)
-#define XO31(opc) (OPCD(31)|((opc)<<1))
-#define XO19(opc) (OPCD(19)|((opc)<<1))
-
-#define B OPCD(18)
-#define BC OPCD(16)
-#define LBZ OPCD(34)
-#define LHZ OPCD(40)
-#define LHA OPCD(42)
-#define LWZ OPCD(32)
-#define STB OPCD(38)
-#define STH OPCD(44)
-#define STW OPCD(36)
-
-#define ADDIC OPCD(12)
-#define ADDI OPCD(14)
-#define ADDIS OPCD(15)
-#define ORI OPCD(24)
-#define ORIS OPCD(25)
-#define XORI OPCD(26)
-#define XORIS OPCD(27)
-#define ANDI OPCD(28)
-#define ANDIS OPCD(29)
-#define MULLI OPCD( 7)
-#define CMPLI OPCD(10)
-#define CMPI OPCD(11)
-#define SUBFIC OPCD( 8)
-
-#define LWZU OPCD(33)
-#define STWU OPCD(37)
-
-#define RLWIMI OPCD(20)
-#define RLWINM OPCD(21)
-#define RLWNM OPCD(23)
-
-#define BCLR XO19( 16)
-#define BCCTR XO19(528)
-#define CRAND XO19(257)
-#define CRANDC XO19(129)
-#define CRNAND XO19(225)
-#define CROR XO19(449)
-#define CRNOR XO19( 33)
-
-#define EXTSB XO31(954)
-#define EXTSH XO31(922)
-#define ADD XO31(266)
-#define ADDE XO31(138)
-#define ADDC XO31( 10)
-#define AND XO31( 28)
-#define SUBF XO31( 40)
-#define SUBFC XO31( 8)
-#define SUBFE XO31(136)
-#define OR XO31(444)
-#define XOR XO31(316)
-#define MULLW XO31(235)
-#define MULHWU XO31( 11)
-#define DIVW XO31(491)
-#define DIVWU XO31(459)
-#define CMP XO31( 0)
-#define CMPL XO31( 32)
-#define LHBRX XO31(790)
-#define LWBRX XO31(534)
-#define STHBRX XO31(918)
-#define STWBRX XO31(662)
-#define MFSPR XO31(339)
-#define MTSPR XO31(467)
-#define SRAWI XO31(824)
-#define NEG XO31(104)
-#define MFCR XO31( 19)
-#define CNTLZW XO31( 26)
-#define NOR XO31(124)
-#define ANDC XO31( 60)
-#define ORC XO31(412)
-#define EQV XO31(284)
-#define NAND XO31(476)
-#define ISEL XO31( 15)
-
-#define LBZX XO31( 87)
-#define LHZX XO31(279)
-#define LHAX XO31(343)
-#define LWZX XO31( 23)
-#define STBX XO31(215)
-#define STHX XO31(407)
-#define STWX XO31(151)
-
-#define SPR(a,b) ((((a)<<5)|(b))<<11)
-#define LR SPR(8, 0)
-#define CTR SPR(9, 0)
-
-#define SLW XO31( 24)
-#define SRW XO31(536)
-#define SRAW XO31(792)
-
-#define TW XO31(4)
-#define TRAP (TW | TO (31))
-
-#define RT(r) ((r)<<21)
-#define RS(r) ((r)<<21)
-#define RA(r) ((r)<<16)
-#define RB(r) ((r)<<11)
-#define TO(t) ((t)<<21)
-#define SH(s) ((s)<<11)
-#define MB(b) ((b)<<6)
-#define ME(e) ((e)<<1)
-#define BO(o) ((o)<<21)
-
-#define LK 1
-
-#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
-#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
-
-#define BF(n) ((n)<<23)
-#define BI(n, c) (((c)+((n)*4))<<16)
-#define BT(n, c) (((c)+((n)*4))<<21)
-#define BA(n, c) (((c)+((n)*4))<<16)
-#define BB(n, c) (((c)+((n)*4))<<11)
-
-#define BO_COND_TRUE BO (12)
-#define BO_COND_FALSE BO (4)
-#define BO_ALWAYS BO (20)
-
-enum {
- CR_LT,
- CR_GT,
- CR_EQ,
- CR_SO
-};
-
-static const uint32_t tcg_to_bc[] = {
- [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
- [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
- [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
- [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
- [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
- [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
- [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
- [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
- [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
- [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
-};
-
-static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
-{
- if (ret != arg) {
- tcg_out32(s, OR | SAB(arg, ret, arg));
- }
-}
-
-static void tcg_out_movi(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
-{
- if (arg == (int16_t) arg)
- tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
- else {
- tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
- if (arg & 0xffff)
- tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
- }
-}
-
-static void tcg_out_ldst (TCGContext *s, int ret, int addr,
- int offset, int op1, int op2)
-{
- if (offset == (int16_t) offset)
- tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
- tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
- }
-}
-
-static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
-{
- ptrdiff_t disp = tcg_pcrel_diff(s, target);
- if (in_range_b(disp)) {
- tcg_out32(s, B | (disp & 0x3fffffc) | mask);
- } else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
- tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
- tcg_out32(s, BCCTR | BO_ALWAYS | mask);
- }
-}
-
-static void tcg_out_call1(TCGContext *s, tcg_insn_unit *target, int lk)
-{
-#ifdef _CALL_AIX
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, (uintptr_t)target);
- tcg_out32(s, LWZ | RT(TCG_REG_R0) | RA(reg));
- tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
- tcg_out32(s, LWZ | RT(TCG_REG_R2) | RA(reg) | 4);
- tcg_out32(s, BCCTR | BO_ALWAYS | lk);
-#else
- tcg_out_b(s, lk, target);
-#endif
-}
-
-static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
-{
- tcg_out_call1(s, target, LK);
-}
-
-#if defined(CONFIG_SOFTMMU)
-
-static void add_qemu_ldst_label (TCGContext *s,
- bool is_ld,
- TCGMemOp opc,
- int data_reg,
- int data_reg2,
- int addrlo_reg,
- int addrhi_reg,
- int mem_index,
- tcg_insn_unit *raddr,
- tcg_insn_unit *label_ptr)
-{
- TCGLabelQemuLdst *label = new_ldst_label(s);
-
- label->is_ld = is_ld;
- label->opc = opc;
- label->datalo_reg = data_reg;
- label->datahi_reg = data_reg2;
- label->addrlo_reg = addrlo_reg;
- label->addrhi_reg = addrhi_reg;
- label->mem_index = mem_index;
- label->raddr = raddr;
- label->label_ptr[0] = label_ptr;
-}
-
-/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
- * int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_ld_helpers[16] = {
- [MO_UB] = helper_ret_ldub_mmu,
- [MO_LEUW] = helper_le_lduw_mmu,
- [MO_LEUL] = helper_le_ldul_mmu,
- [MO_LEQ] = helper_le_ldq_mmu,
- [MO_BEUW] = helper_be_lduw_mmu,
- [MO_BEUL] = helper_be_ldul_mmu,
- [MO_BEQ] = helper_be_ldq_mmu,
-};
-
-/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
- * uintxx_t val, int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_st_helpers[16] = {
- [MO_UB] = helper_ret_stb_mmu,
- [MO_LEUW] = helper_le_stw_mmu,
- [MO_LEUL] = helper_le_stl_mmu,
- [MO_LEQ] = helper_le_stq_mmu,
- [MO_BEUW] = helper_be_stw_mmu,
- [MO_BEUL] = helper_be_stl_mmu,
- [MO_BEQ] = helper_be_stq_mmu,
-};
-
-static tcg_insn_unit *ld_trampolines[16];
-static tcg_insn_unit *st_trampolines[16];
-
-/* Perform the TLB load and compare. Branches to the slow path, placing the
- address of the branch in *LABEL_PTR. Loads the addend of the TLB into R0.
- Clobbers R1 and R2. */
-
-static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
- TCGReg addrlo, TCGReg addrhi, TCGMemOp s_bits,
- int mem_index, int is_load,
- tcg_insn_unit **label_ptr)
-{
- int cmp_off =
- (is_load
- ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
- : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
- int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
- tcg_insn_unit retranst;
- TCGReg base = TCG_AREG0;
-
- /* Extract the page index, shifted into place for tlb index. */
- tcg_out32(s, (RLWINM
- | RA(r0)
- | RS(addrlo)
- | SH(32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
- | MB(32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
- | ME(31 - CPU_TLB_ENTRY_BITS)));
-
- /* Compensate for very large offsets. */
- if (add_off >= 0x8000) {
- /* Most target env are smaller than 32k; none are larger than 64k.
- Simplify the logic here merely to offset by 0x7ff0, giving us a
- range just shy of 64k. Check this assumption. */
- QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
- tlb_table[NB_MMU_MODES - 1][1])
- > 0x7ff0 + 0x7fff);
- tcg_out32(s, ADDI | RT(r1) | RA(base) | 0x7ff0);
- base = r1;
- cmp_off -= 0x7ff0;
- add_off -= 0x7ff0;
- }
-
- /* Clear the non-page, non-alignment bits from the address. */
- tcg_out32(s, (RLWINM
- | RA(r2)
- | RS(addrlo)
- | SH(0)
- | MB((32 - s_bits) & 31)
- | ME(31 - TARGET_PAGE_BITS)));
-
- tcg_out32(s, ADD | RT(r0) | RA(r0) | RB(base));
- base = r0;
-
- /* Load the tlb comparator. */
- tcg_out32(s, LWZ | RT(r1) | RA(base) | (cmp_off & 0xffff));
-
- tcg_out32(s, CMP | BF(7) | RA(r2) | RB(r1));
-
- if (TARGET_LONG_BITS == 64) {
- tcg_out32(s, LWZ | RT(r1) | RA(base) | ((cmp_off + 4) & 0xffff));
- }
-
- /* Load the tlb addend for use on the fast path.
- Do this asap to minimize load delay. */
- tcg_out32(s, LWZ | RT(r0) | RA(base) | (add_off & 0xffff));
-
- if (TARGET_LONG_BITS == 64) {
- tcg_out32(s, CMP | BF(6) | RA(addrhi) | RB(r1));
- tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
- }
-
- /* Use a conditional branch-and-link so that we load a pointer to
- somewhere within the current opcode, for passing on to the helper.
- This address cannot be used for a tail call, but it's shorter
- than forming an address from scratch. */
- *label_ptr = s->code_ptr;
- retranst = *s->code_ptr & 0xfffc;
- tcg_out32(s, BC | BI(7, CR_EQ) | retranst | BO_COND_FALSE | LK);
-}
-#endif
-
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
-{
- TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
- TCGMemOp opc, bswap;
-#ifdef CONFIG_SOFTMMU
- int mem_index;
- tcg_insn_unit *label_ptr;
-#endif
-
- datalo = *args++;
- datahi = (is64 ? *args++ : 0);
- addrlo = *args++;
- addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
- opc = *args++;
- bswap = opc & MO_BSWAP;
-
-#ifdef CONFIG_SOFTMMU
- mem_index = *args;
- tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
- addrhi, opc & MO_SIZE, mem_index, 0, &label_ptr);
- rbase = TCG_REG_R3;
-#else /* !CONFIG_SOFTMMU */
- rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
-#endif
-
- switch (opc & MO_SSIZE) {
- default:
- case MO_UB:
- tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
- break;
- case MO_SB:
- tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
- tcg_out32(s, EXTSB | RA(datalo) | RS(datalo));
- break;
- case MO_UW:
- tcg_out32(s, (bswap ? LHBRX : LHZX) | TAB(datalo, rbase, addrlo));
- break;
- case MO_SW:
- if (bswap) {
- tcg_out32(s, LHBRX | TAB(datalo, rbase, addrlo));
- tcg_out32(s, EXTSH | RA(datalo) | RS(datalo));
- } else {
- tcg_out32(s, LHAX | TAB(datalo, rbase, addrlo));
- }
- break;
- case MO_UL:
- tcg_out32(s, (bswap ? LWBRX : LWZX) | TAB(datalo, rbase, addrlo));
- break;
- case MO_Q:
- if (bswap) {
- tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
- tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
- tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
- } else if (rbase != 0) {
- tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
- tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
- tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
- } else if (addrlo == datahi) {
- tcg_out32(s, LWZ | RT(datalo) | RA(addrlo) | 4);
- tcg_out32(s, LWZ | RT(datahi) | RA(addrlo));
- } else {
- tcg_out32(s, LWZ | RT(datahi) | RA(addrlo));
- tcg_out32(s, LWZ | RT(datalo) | RA(addrlo) | 4);
- }
- break;
- }
-#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo,
- addrhi, mem_index, s->code_ptr, label_ptr);
-#endif
-}
-
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
-{
- TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
- TCGMemOp opc, bswap, s_bits;
-#ifdef CONFIG_SOFTMMU
- int mem_index;
- tcg_insn_unit *label_ptr;
-#endif
-
- datalo = *args++;
- datahi = (is64 ? *args++ : 0);
- addrlo = *args++;
- addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
- opc = *args++;
- bswap = opc & MO_BSWAP;
- s_bits = opc & MO_SIZE;
-
-#ifdef CONFIG_SOFTMMU
- mem_index = *args;
- tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
- addrhi, s_bits, mem_index, 0, &label_ptr);
- rbase = TCG_REG_R3;
-#else /* !CONFIG_SOFTMMU */
- rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
-#endif
-
- switch (s_bits) {
- case MO_8:
- tcg_out32(s, STBX | SAB(datalo, rbase, addrlo));
- break;
- case MO_16:
- tcg_out32(s, (bswap ? STHBRX : STHX) | SAB(datalo, rbase, addrlo));
- break;
- case MO_32:
- default:
- tcg_out32(s, (bswap ? STWBRX : STWX) | SAB(datalo, rbase, addrlo));
- break;
- case MO_64:
- if (bswap) {
- tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
- tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
- tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0));
- } else if (rbase != 0) {
- tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
- tcg_out32(s, STWX | SAB(datahi, rbase, addrlo));
- tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0));
- } else {
- tcg_out32(s, STW | RS(datahi) | RA(addrlo));
- tcg_out32(s, STW | RS(datalo) | RA(addrlo) | 4);
- }
- break;
- }
-
-#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
- mem_index, s->code_ptr, label_ptr);
-#endif
-}
-
-#if defined(CONFIG_SOFTMMU)
-static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
-{
- TCGReg ir, datalo, datahi;
- TCGMemOp opc = l->opc;
-
- reloc_pc14(l->label_ptr[0], s->code_ptr);
-
- ir = TCG_REG_R4;
- if (TARGET_LONG_BITS == 32) {
- tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrlo_reg);
- } else {
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
- ir |= 1;
-#endif
- tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrhi_reg);
- tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrlo_reg);
- }
- tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
- tcg_out32(s, MFSPR | RT(ir++) | LR);
- tcg_out_b(s, LK, ld_trampolines[opc & ~MO_SIGN]);
-
- datalo = l->datalo_reg;
- switch (opc & MO_SSIZE) {
- case MO_SB:
- tcg_out32(s, EXTSB | RA(datalo) | RS(TCG_REG_R3));
- break;
- case MO_SW:
- tcg_out32(s, EXTSH | RA(datalo) | RS(TCG_REG_R3));
- break;
- default:
- tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R3);
- break;
- case MO_Q:
- datahi = l->datahi_reg;
- if (datalo != TCG_REG_R3) {
- tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
- tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
- } else if (datahi != TCG_REG_R4) {
- tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
- tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
- } else {
- tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R0, TCG_REG_R4);
- tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
- tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R0);
- }
- break;
- }
- tcg_out_b(s, 0, l->raddr);
-}
-
-static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
-{
- TCGReg ir, datalo;
- TCGMemOp opc = l->opc;
-
- reloc_pc14(l->label_ptr[0], s->code_ptr);
-
- ir = TCG_REG_R4;
- if (TARGET_LONG_BITS == 32) {
- tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrlo_reg);
- } else {
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
- ir |= 1;
-#endif
- tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrhi_reg);
- tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrlo_reg);
- }
-
- datalo = l->datalo_reg;
- switch (opc & MO_SIZE) {
- case MO_8:
- tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
- | SH (0) | MB (24) | ME (31)));
- break;
- case MO_16:
- tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
- | SH (0) | MB (16) | ME (31)));
- break;
- default:
- tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
- break;
- case MO_64:
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
- ir |= 1;
-#endif
- tcg_out_mov(s, TCG_TYPE_I32, ir++, l->datahi_reg);
- tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
- break;
- }
- ir++;
-
- tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
- tcg_out32(s, MFSPR | RT(ir++) | LR);
- tcg_out_b(s, LK, st_trampolines[opc]);
- tcg_out_b(s, 0, l->raddr);
-}
-#endif
-
-#ifdef CONFIG_SOFTMMU
-static void emit_ldst_trampoline(TCGContext *s, tcg_insn_unit *ptr)
-{
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
- tcg_out_call1(s, ptr, 0);
-}
-#endif
-
-static void tcg_target_qemu_prologue (TCGContext *s)
-{
- int i, frame_size;
-
- frame_size = 0
- + LINKAGE_AREA_SIZE
- + TCG_STATIC_CALL_ARGS_SIZE
- + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
- + CPU_TEMP_BUF_NLONGS * sizeof(long)
- ;
- frame_size = (frame_size + 15) & ~15;
-
- tcg_set_frame(s, TCG_REG_CALL_STACK, frame_size
- - CPU_TEMP_BUF_NLONGS * sizeof(long),
- CPU_TEMP_BUF_NLONGS * sizeof(long));
-
-#ifdef _CALL_AIX
- {
- uintptr_t addr;
-
- /* First emit adhoc function descriptor */
- addr = (uintptr_t)s->code_ptr + 12;
- tcg_out32(s, addr); /* entry point */
- tcg_out32(s, 0); /* toc */
- tcg_out32(s, 0); /* environment pointer */
- }
-#endif
- tcg_out32 (s, MFSPR | RT (0) | LR);
- tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
- for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
- tcg_out32 (s, (STW
- | RS (tcg_target_callee_save_regs[i])
- | RA (1)
- | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
- )
- );
- tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + LR_OFFSET));
-
-#ifdef CONFIG_USE_GUEST_BASE
- if (GUEST_BASE) {
- tcg_out_movi (s, TCG_TYPE_I32, TCG_GUEST_BASE_REG, GUEST_BASE);
- tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
- }
-#endif
-
- tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
- tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
- tcg_out32 (s, BCCTR | BO_ALWAYS);
- tb_ret_addr = s->code_ptr;
-
- for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
- tcg_out32 (s, (LWZ
- | RT (tcg_target_callee_save_regs[i])
- | RA (1)
- | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
- )
- );
- tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + LR_OFFSET));
- tcg_out32 (s, MTSPR | RS (0) | LR);
- tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
- tcg_out32 (s, BCLR | BO_ALWAYS);
-
-#ifdef CONFIG_SOFTMMU
- for (i = 0; i < 16; ++i) {
- if (qemu_ld_helpers[i]) {
- ld_trampolines[i] = s->code_ptr;
- emit_ldst_trampoline(s, qemu_ld_helpers[i]);
- }
- if (qemu_st_helpers[i]) {
- st_trampolines[i] = s->code_ptr;
- emit_ldst_trampoline(s, qemu_st_helpers[i]);
- }
- }
-#endif
-}
-
-static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
- intptr_t arg2)
-{
- tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
-}
-
-static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
- intptr_t arg2)
-{
- tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
-}
-
-static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
-{
- if (!si && rt == ra)
- return;
-
- if (si == (int16_t) si)
- tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
- else {
- uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
- tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
- tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
- }
-}
-
-static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
- int const_arg2, int cr)
-{
- int imm;
- uint32_t op;
-
- switch (cond) {
- case TCG_COND_EQ:
- case TCG_COND_NE:
- if (const_arg2) {
- if ((int16_t) arg2 == arg2) {
- op = CMPI;
- imm = 1;
- break;
- }
- else if ((uint16_t) arg2 == arg2) {
- op = CMPLI;
- imm = 1;
- break;
- }
- }
- op = CMPL;
- imm = 0;
- break;
-
- case TCG_COND_LT:
- case TCG_COND_GE:
- case TCG_COND_LE:
- case TCG_COND_GT:
- if (const_arg2) {
- if ((int16_t) arg2 == arg2) {
- op = CMPI;
- imm = 1;
- break;
- }
- }
- op = CMP;
- imm = 0;
- break;
-
- case TCG_COND_LTU:
- case TCG_COND_GEU:
- case TCG_COND_LEU:
- case TCG_COND_GTU:
- if (const_arg2) {
- if ((uint16_t) arg2 == arg2) {
- op = CMPLI;
- imm = 1;
- break;
- }
- }
- op = CMPL;
- imm = 0;
- break;
-
- default:
- tcg_abort ();
- }
- op |= BF (cr);
-
- if (imm)
- tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
- else {
- if (const_arg2) {
- tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
- tcg_out32 (s, op | RA (arg1) | RB (0));
- }
- else
- tcg_out32 (s, op | RA (arg1) | RB (arg2));
- }
-
-}
-
-static void tcg_out_bc(TCGContext *s, int bc, int label_index)
-{
- TCGLabel *l = &s->labels[label_index];
-
- if (l->has_value) {
- tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
- } else {
- /* Thanks to Andrzej Zaborowski */
- tcg_insn_unit retrans = *s->code_ptr & 0xfffc;
- tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
- tcg_out32(s, bc | retrans);
- }
-}
-
-static void tcg_out_cr7eq_from_cond (TCGContext *s, const TCGArg *args,
- const int *const_args)
-{
- TCGCond cond = args[4];
- int op;
- struct { int bit1; int bit2; int cond2; } bits[] = {
- [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT },
- [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT },
- [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT },
- [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT },
- [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU },
- [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU },
- [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU },
- [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU },
- }, *b = &bits[cond];
-
- switch (cond) {
- case TCG_COND_EQ:
- case TCG_COND_NE:
- op = (cond == TCG_COND_EQ) ? CRAND : CRNAND;
- tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 6);
- tcg_out_cmp (s, cond, args[1], args[3], const_args[3], 7);
- tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
- break;
- case TCG_COND_LT:
- case TCG_COND_LE:
- case TCG_COND_GT:
- case TCG_COND_GE:
- case TCG_COND_LTU:
- case TCG_COND_LEU:
- case TCG_COND_GTU:
- case TCG_COND_GEU:
- op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
- tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
- tcg_out_cmp (s, tcg_unsigned_cond (cond), args[0], args[2],
- const_args[2], 7);
- tcg_out32 (s, op | BT (7, CR_EQ) | BA (5, CR_EQ) | BB (7, b->bit2));
- tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
- break;
- default:
- tcg_abort();
- }
-}
-
-static void tcg_out_setcond (TCGContext *s, TCGCond cond, TCGArg arg0,
- TCGArg arg1, TCGArg arg2, int const_arg2)
-{
- int crop, sh, arg;
-
- switch (cond) {
- case TCG_COND_EQ:
- if (const_arg2) {
- if (!arg2) {
- arg = arg1;
- }
- else {
- arg = 0;
- if ((uint16_t) arg2 == arg2) {
- tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
- }
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
- tcg_out32 (s, XOR | SAB (arg1, 0, 0));
- }
- }
- }
- else {
- arg = 0;
- tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
- }
- tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
- tcg_out32 (s, (RLWINM
- | RA (arg0)
- | RS (0)
- | SH (27)
- | MB (5)
- | ME (31)
- )
- );
- break;
-
- case TCG_COND_NE:
- if (const_arg2) {
- if (!arg2) {
- arg = arg1;
- }
- else {
- arg = 0;
- if ((uint16_t) arg2 == arg2) {
- tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
- }
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
- tcg_out32 (s, XOR | SAB (arg1, 0, 0));
- }
- }
- }
- else {
- arg = 0;
- tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
- }
-
- if (arg == arg1 && arg1 == arg0) {
- tcg_out32 (s, ADDIC | RT (0) | RA (arg) | 0xffff);
- tcg_out32 (s, SUBFE | TAB (arg0, 0, arg));
- }
- else {
- tcg_out32 (s, ADDIC | RT (arg0) | RA (arg) | 0xffff);
- tcg_out32 (s, SUBFE | TAB (arg0, arg0, arg));
- }
- break;
-
- case TCG_COND_GT:
- case TCG_COND_GTU:
- sh = 30;
- crop = 0;
- goto crtest;
-
- case TCG_COND_LT:
- case TCG_COND_LTU:
- sh = 29;
- crop = 0;
- goto crtest;
-
- case TCG_COND_GE:
- case TCG_COND_GEU:
- sh = 31;
- crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
- goto crtest;
-
- case TCG_COND_LE:
- case TCG_COND_LEU:
- sh = 31;
- crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
- crtest:
- tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
- if (crop) tcg_out32 (s, crop);
- tcg_out32 (s, MFCR | RT (0));
- tcg_out32 (s, (RLWINM
- | RA (arg0)
- | RS (0)
- | SH (sh)
- | MB (31)
- | ME (31)
- )
- );
- break;
-
- default:
- tcg_abort ();
- }
-}
-
-static void tcg_out_setcond2 (TCGContext *s, const TCGArg *args,
- const int *const_args)
-{
- tcg_out_cr7eq_from_cond (s, args + 1, const_args + 1);
- tcg_out32 (s, MFCR | RT (0));
- tcg_out32 (s, (RLWINM
- | RA (args[0])
- | RS (0)
- | SH (31)
- | MB (31)
- | ME (31)
- )
- );
-}
-
-static void tcg_out_movcond (TCGContext *s, TCGCond cond,
- TCGArg dest,
- TCGArg c1, TCGArg c2,
- TCGArg v1, TCGArg v2,
- int const_c2)
-{
- tcg_out_cmp (s, cond, c1, c2, const_c2, 7);
-
- if (1) {
- /* At least here on 7747A bit twiddling hacks are outperformed
- by jumpy code (the testing was not scientific) */
- if (dest == v2) {
- cond = tcg_invert_cond (cond);
- v2 = v1;
- }
- else {
- if (dest != v1) {
- tcg_out_mov (s, TCG_TYPE_I32, dest, v1);
- }
- }
- /* Branch forward over one insn */
- tcg_out32 (s, tcg_to_bc[cond] | 8);
- tcg_out_mov (s, TCG_TYPE_I32, dest, v2);
- }
- else {
- /* isel version, "if (1)" above should be replaced once a way
- to figure out availability of isel on the underlying
- hardware is found */
- int tab, bc;
-
- switch (cond) {
- case TCG_COND_EQ:
- tab = TAB (dest, v1, v2);
- bc = CR_EQ;
- break;
- case TCG_COND_NE:
- tab = TAB (dest, v2, v1);
- bc = CR_EQ;
- break;
- case TCG_COND_LTU:
- case TCG_COND_LT:
- tab = TAB (dest, v1, v2);
- bc = CR_LT;
- break;
- case TCG_COND_GEU:
- case TCG_COND_GE:
- tab = TAB (dest, v2, v1);
- bc = CR_LT;
- break;
- case TCG_COND_LEU:
- case TCG_COND_LE:
- tab = TAB (dest, v2, v1);
- bc = CR_GT;
- break;
- case TCG_COND_GTU:
- case TCG_COND_GT:
- tab = TAB (dest, v1, v2);
- bc = CR_GT;
- break;
- default:
- tcg_abort ();
- }
- tcg_out32 (s, ISEL | tab | ((bc + 28) << 6));
- }
-}
-
-static void tcg_out_brcond (TCGContext *s, TCGCond cond,
- TCGArg arg1, TCGArg arg2, int const_arg2,
- int label_index)
-{
- tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
- tcg_out_bc (s, tcg_to_bc[cond], label_index);
-}
-
-/* XXX: we implement it at the target level to avoid having to
- handle cross basic blocks temporaries */
-static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
- const int *const_args)
-{
- tcg_out_cr7eq_from_cond (s, args, const_args);
- tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), args[5]);
-}
-
-void ppc_tb_set_jmp_target (uintptr_t jmp_addr, uintptr_t addr)
-{
- uint32_t *ptr;
- long disp = addr - jmp_addr;
- unsigned long patch_size;
-
- ptr = (uint32_t *)jmp_addr;
-
- if ((disp << 6) >> 6 != disp) {
- ptr[0] = 0x3c000000 | (addr >> 16); /* lis 0,addr@ha */
- ptr[1] = 0x60000000 | (addr & 0xffff); /* la 0,addr@l(0) */
- ptr[2] = 0x7c0903a6; /* mtctr 0 */
- ptr[3] = 0x4e800420; /* brctr */
- patch_size = 16;
- } else {
- /* patch the branch destination */
- if (disp != 16) {
- *ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */
- patch_size = 4;
- } else {
- ptr[0] = 0x60000000; /* nop */
- ptr[1] = 0x60000000;
- ptr[2] = 0x60000000;
- ptr[3] = 0x60000000;
- patch_size = 16;
- }
- }
- /* flush icache */
- flush_icache_range(jmp_addr, jmp_addr + patch_size);
-}
-
-static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
- const int *const_args)
-{
- switch (opc) {
- case INDEX_op_exit_tb:
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
- tcg_out_b(s, 0, tb_ret_addr);
- break;
- case INDEX_op_goto_tb:
- if (s->tb_jmp_offset) {
- /* direct jump method */
- s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
- s->code_ptr += 4;
- } else {
- tcg_abort ();
- }
- s->tb_next_offset[args[0]] = tcg_current_code_size(s);
- break;
- case INDEX_op_br:
- {
- TCGLabel *l = &s->labels[args[0]];
-
- if (l->has_value) {
- tcg_out_b(s, 0, l->u.value_ptr);
- } else {
- /* Thanks to Andrzej Zaborowski */
- tcg_insn_unit retrans = *s->code_ptr & 0x3fffffc;
- tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
- tcg_out32(s, B | retrans);
- }
- }
- break;
- case INDEX_op_ld8u_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
- break;
- case INDEX_op_ld8s_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
- tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
- break;
- case INDEX_op_ld16u_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
- break;
- case INDEX_op_ld16s_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
- break;
- case INDEX_op_ld_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
- break;
- case INDEX_op_st8_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
- break;
- case INDEX_op_st16_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
- break;
- case INDEX_op_st_i32:
- tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
- break;
-
- case INDEX_op_add_i32:
- if (const_args[2])
- ppc_addi (s, args[0], args[1], args[2]);
- else
- tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
- break;
- case INDEX_op_sub_i32:
- if (const_args[2])
- ppc_addi (s, args[0], args[1], -args[2]);
- else
- tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
- break;
-
- case INDEX_op_and_i32:
- if (const_args[2]) {
- uint32_t c;
-
- c = args[2];
-
- if (!c) {
- tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
- break;
- }
-#ifdef __PPU__
- uint32_t t, n;
- int mb, me;
-
- n = c ^ -(c & 1);
- t = n + (n & -n);
-
- if ((t & (t - 1)) == 0) {
- int lzc, tzc;
-
- if ((c & 0x80000001) == 0x80000001) {
- lzc = clz32 (n);
- tzc = ctz32 (n);
-
- mb = 32 - tzc;
- me = lzc - 1;
- }
- else {
- lzc = clz32 (c);
- tzc = ctz32 (c);
-
- mb = lzc;
- me = 31 - tzc;
- }
-
- tcg_out32 (s, (RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (0)
- | MB (mb)
- | ME (me)
- )
- );
- }
- else
-#endif /* !__PPU__ */
- {
- if ((c & 0xffff) == c)
- tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | c);
- else if ((c & 0xffff0000) == c)
- tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
- | ((c >> 16) & 0xffff));
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, c);
- tcg_out32 (s, AND | SAB (args[1], args[0], 0));
- }
- }
- }
- else
- tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_or_i32:
- if (const_args[2]) {
- if (args[2] & 0xffff) {
- tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
- | (args[2] & 0xffff));
- if (args[2] >> 16)
- tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
- | ((args[2] >> 16) & 0xffff));
- }
- else {
- tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
- | ((args[2] >> 16) & 0xffff));
- }
- }
- else
- tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_xor_i32:
- if (const_args[2]) {
- if ((args[2] & 0xffff) == args[2])
- tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
- | (args[2] & 0xffff));
- else if ((args[2] & 0xffff0000) == args[2])
- tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
- | ((args[2] >> 16) & 0xffff));
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
- tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
- }
- }
- else
- tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_andc_i32:
- tcg_out32 (s, ANDC | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_orc_i32:
- tcg_out32 (s, ORC | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_eqv_i32:
- tcg_out32 (s, EQV | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_nand_i32:
- tcg_out32 (s, NAND | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_nor_i32:
- tcg_out32 (s, NOR | SAB (args[1], args[0], args[2]));
- break;
-
- case INDEX_op_mul_i32:
- if (const_args[2]) {
- if (args[2] == (int16_t) args[2])
- tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
- | (args[2] & 0xffff));
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
- tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
- }
- }
- else
- tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
- break;
-
- case INDEX_op_div_i32:
- tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
- break;
-
- case INDEX_op_divu_i32:
- tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
- break;
-
- case INDEX_op_mulu2_i32:
- if (args[0] == args[2] || args[0] == args[3]) {
- tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
- tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
- tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
- }
- else {
- tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
- tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
- }
- break;
-
- case INDEX_op_shl_i32:
- if (const_args[2]) {
- tcg_out32 (s, (RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (args[2])
- | MB (0)
- | ME (31 - args[2])
- )
- );
- }
- else
- tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_shr_i32:
- if (const_args[2]) {
- tcg_out32 (s, (RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (32 - args[2])
- | MB (args[2])
- | ME (31)
- )
- );
- }
- else
- tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_sar_i32:
- if (const_args[2])
- tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
- else
- tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
- break;
- case INDEX_op_rotl_i32:
- {
- int op = 0
- | RA (args[0])
- | RS (args[1])
- | MB (0)
- | ME (31)
- | (const_args[2] ? RLWINM | SH (args[2])
- : RLWNM | RB (args[2]))
- ;
- tcg_out32 (s, op);
- }
- break;
- case INDEX_op_rotr_i32:
- if (const_args[2]) {
- if (!args[2]) {
- tcg_out_mov (s, TCG_TYPE_I32, args[0], args[1]);
- }
- else {
- tcg_out32 (s, RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (32 - args[2])
- | MB (0)
- | ME (31)
- );
- }
- }
- else {
- tcg_out32 (s, SUBFIC | RT (0) | RA (args[2]) | 32);
- tcg_out32 (s, RLWNM
- | RA (args[0])
- | RS (args[1])
- | RB (0)
- | MB (0)
- | ME (31)
- );
- }
- break;
-
- case INDEX_op_add2_i32:
- if (args[0] == args[3] || args[0] == args[5]) {
- tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
- tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
- tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
- }
- else {
- tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
- tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
- }
- break;
- case INDEX_op_sub2_i32:
- if (args[0] == args[3] || args[0] == args[5]) {
- tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
- tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
- tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
- }
- else {
- tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
- tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
- }
- break;
-
- case INDEX_op_brcond_i32:
- /*
- args[0] = r0
- args[1] = r1
- args[2] = cond
- args[3] = r1 is const
- args[4] = label_index
- */
- tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
- break;
- case INDEX_op_brcond2_i32:
- tcg_out_brcond2(s, args, const_args);
- break;
-
- case INDEX_op_neg_i32:
- tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
- break;
-
- case INDEX_op_not_i32:
- tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
- break;
-
- case INDEX_op_qemu_ld_i32:
- tcg_out_qemu_ld(s, args, 0);
- break;
- case INDEX_op_qemu_ld_i64:
- tcg_out_qemu_ld(s, args, 1);
- break;
- case INDEX_op_qemu_st_i32:
- tcg_out_qemu_st(s, args, 0);
- break;
- case INDEX_op_qemu_st_i64:
- tcg_out_qemu_st(s, args, 1);
- break;
-
- case INDEX_op_ext8s_i32:
- tcg_out32 (s, EXTSB | RS (args[1]) | RA (args[0]));
- break;
- case INDEX_op_ext8u_i32:
- tcg_out32 (s, RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (0)
- | MB (24)
- | ME (31)
- );
- break;
- case INDEX_op_ext16s_i32:
- tcg_out32 (s, EXTSH | RS (args[1]) | RA (args[0]));
- break;
- case INDEX_op_ext16u_i32:
- tcg_out32 (s, RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (0)
- | MB (16)
- | ME (31)
- );
- break;
-
- case INDEX_op_setcond_i32:
- tcg_out_setcond (s, args[3], args[0], args[1], args[2], const_args[2]);
- break;
- case INDEX_op_setcond2_i32:
- tcg_out_setcond2 (s, args, const_args);
- break;
-
- case INDEX_op_bswap16_i32:
- /* Stolen from gcc's builtin_bswap16 */
-
- /* a1 = abcd */
-
- /* r0 = (a1 << 8) & 0xff00 # 00d0 */
- tcg_out32 (s, RLWINM
- | RA (0)
- | RS (args[1])
- | SH (8)
- | MB (16)
- | ME (23)
- );
-
- /* a0 = rotate_left (a1, 24) & 0xff # 000c */
- tcg_out32 (s, RLWINM
- | RA (args[0])
- | RS (args[1])
- | SH (24)
- | MB (24)
- | ME (31)
- );
-
- /* a0 = a0 | r0 # 00dc */
- tcg_out32 (s, OR | SAB (0, args[0], args[0]));
- break;
-
- case INDEX_op_bswap32_i32:
- /* Stolen from gcc's builtin_bswap32 */
- {
- int a0 = args[0];
-
- /* a1 = args[1] # abcd */
-
- if (a0 == args[1]) {
- a0 = 0;
- }
-
- /* a0 = rotate_left (a1, 8) # bcda */
- tcg_out32 (s, RLWINM
- | RA (a0)
- | RS (args[1])
- | SH (8)
- | MB (0)
- | ME (31)
- );
-
- /* a0 = (a0 & ~0xff000000) | ((a1 << 24) & 0xff000000) # dcda */
- tcg_out32 (s, RLWIMI
- | RA (a0)
- | RS (args[1])
- | SH (24)
- | MB (0)
- | ME (7)
- );
-
- /* a0 = (a0 & ~0x0000ff00) | ((a1 << 24) & 0x0000ff00) # dcba */
- tcg_out32 (s, RLWIMI
- | RA (a0)
- | RS (args[1])
- | SH (24)
- | MB (16)
- | ME (23)
- );
-
- if (!a0) {
- tcg_out_mov (s, TCG_TYPE_I32, args[0], a0);
- }
- }
- break;
-
- case INDEX_op_deposit_i32:
- tcg_out32 (s, RLWIMI
- | RA (args[0])
- | RS (args[2])
- | SH (args[3])
- | MB (32 - args[3] - args[4])
- | ME (31 - args[3])
- );
- break;
-
- case INDEX_op_movcond_i32:
- tcg_out_movcond (s, args[5], args[0],
- args[1], args[2],
- args[3], args[4],
- const_args[2]);
- break;
-
- case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
- case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
- case INDEX_op_call: /* Always emitted via tcg_out_call. */
- default:
- tcg_abort();
- }
-}
-
-static const TCGTargetOpDef ppc_op_defs[] = {
- { INDEX_op_exit_tb, { } },
- { INDEX_op_goto_tb, { } },
- { INDEX_op_br, { } },
-
- { INDEX_op_ld8u_i32, { "r", "r" } },
- { INDEX_op_ld8s_i32, { "r", "r" } },
- { INDEX_op_ld16u_i32, { "r", "r" } },
- { INDEX_op_ld16s_i32, { "r", "r" } },
- { INDEX_op_ld_i32, { "r", "r" } },
- { INDEX_op_st8_i32, { "r", "r" } },
- { INDEX_op_st16_i32, { "r", "r" } },
- { INDEX_op_st_i32, { "r", "r" } },
-
- { INDEX_op_add_i32, { "r", "r", "ri" } },
- { INDEX_op_mul_i32, { "r", "r", "ri" } },
- { INDEX_op_div_i32, { "r", "r", "r" } },
- { INDEX_op_divu_i32, { "r", "r", "r" } },
- { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
- { INDEX_op_sub_i32, { "r", "r", "ri" } },
- { INDEX_op_and_i32, { "r", "r", "ri" } },
- { INDEX_op_or_i32, { "r", "r", "ri" } },
- { INDEX_op_xor_i32, { "r", "r", "ri" } },
-
- { INDEX_op_shl_i32, { "r", "r", "ri" } },
- { INDEX_op_shr_i32, { "r", "r", "ri" } },
- { INDEX_op_sar_i32, { "r", "r", "ri" } },
-
- { INDEX_op_rotl_i32, { "r", "r", "ri" } },
- { INDEX_op_rotr_i32, { "r", "r", "ri" } },
-
- { INDEX_op_brcond_i32, { "r", "ri" } },
-
- { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
- { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
- { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
-
- { INDEX_op_neg_i32, { "r", "r" } },
- { INDEX_op_not_i32, { "r", "r" } },
-
- { INDEX_op_andc_i32, { "r", "r", "r" } },
- { INDEX_op_orc_i32, { "r", "r", "r" } },
- { INDEX_op_eqv_i32, { "r", "r", "r" } },
- { INDEX_op_nand_i32, { "r", "r", "r" } },
- { INDEX_op_nor_i32, { "r", "r", "r" } },
-
- { INDEX_op_setcond_i32, { "r", "r", "ri" } },
- { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
-
- { INDEX_op_bswap16_i32, { "r", "r" } },
- { INDEX_op_bswap32_i32, { "r", "r" } },
-
-#if TARGET_LONG_BITS == 32
- { INDEX_op_qemu_ld_i32, { "r", "L" } },
- { INDEX_op_qemu_ld_i64, { "L", "L", "L" } },
- { INDEX_op_qemu_st_i32, { "K", "K" } },
- { INDEX_op_qemu_st_i64, { "M", "M", "M" } },
-#else
- { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
- { INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
- { INDEX_op_qemu_st_i32, { "K", "K", "K" } },
- { INDEX_op_qemu_st_i64, { "M", "M", "M", "M" } },
-#endif
-
- { INDEX_op_ext8s_i32, { "r", "r" } },
- { INDEX_op_ext8u_i32, { "r", "r" } },
- { INDEX_op_ext16s_i32, { "r", "r" } },
- { INDEX_op_ext16u_i32, { "r", "r" } },
-
- { INDEX_op_deposit_i32, { "r", "0", "r" } },
- { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "r" } },
-
- { -1 },
-};
-
-static void tcg_target_init(TCGContext *s)
-{
- tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
- tcg_regset_set32(tcg_target_call_clobber_regs, 0,
- (1 << TCG_REG_R0) |
-#ifdef TCG_TARGET_CALL_DARWIN
- (1 << TCG_REG_R2) |
-#endif
- (1 << TCG_REG_R3) |
- (1 << TCG_REG_R4) |
- (1 << TCG_REG_R5) |
- (1 << TCG_REG_R6) |
- (1 << TCG_REG_R7) |
- (1 << TCG_REG_R8) |
- (1 << TCG_REG_R9) |
- (1 << TCG_REG_R10) |
- (1 << TCG_REG_R11) |
- (1 << TCG_REG_R12)
- );
-
- tcg_regset_clear(s->reserved_regs);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
-#ifndef TCG_TARGET_CALL_DARWIN
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
-#endif
-#ifdef _CALL_SYSV
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13);
-#endif
-
- tcg_add_target_add_op_defs(ppc_op_defs);
-}
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
deleted file mode 100644
index 05069ae..0000000
--- a/tcg/ppc/tcg-target.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef TCG_TARGET_PPC
-#define TCG_TARGET_PPC 1
-
-#define TCG_TARGET_NB_REGS 32
-#define TCG_TARGET_INSN_UNIT_SIZE 4
-
-typedef enum {
- TCG_REG_R0 = 0,
- TCG_REG_R1,
- TCG_REG_R2,
- TCG_REG_R3,
- TCG_REG_R4,
- TCG_REG_R5,
- TCG_REG_R6,
- TCG_REG_R7,
- TCG_REG_R8,
- TCG_REG_R9,
- TCG_REG_R10,
- TCG_REG_R11,
- TCG_REG_R12,
- TCG_REG_R13,
- TCG_REG_R14,
- TCG_REG_R15,
- TCG_REG_R16,
- TCG_REG_R17,
- TCG_REG_R18,
- TCG_REG_R19,
- TCG_REG_R20,
- TCG_REG_R21,
- TCG_REG_R22,
- TCG_REG_R23,
- TCG_REG_R24,
- TCG_REG_R25,
- TCG_REG_R26,
- TCG_REG_R27,
- TCG_REG_R28,
- TCG_REG_R29,
- TCG_REG_R30,
- TCG_REG_R31
-} TCGReg;
-
-/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_R1
-#define TCG_TARGET_STACK_ALIGN 16
-#if defined _CALL_DARWIN || defined __APPLE__
-#define TCG_TARGET_CALL_STACK_OFFSET 24
-#elif defined _CALL_AIX
-#define TCG_TARGET_CALL_STACK_OFFSET 52
-#elif defined _CALL_SYSV
-#define TCG_TARGET_CALL_ALIGN_ARGS 1
-#define TCG_TARGET_CALL_STACK_OFFSET 8
-#else
-#error Unsupported system
-#endif
-
-/* optional instructions */
-#define TCG_TARGET_HAS_div_i32 1
-#define TCG_TARGET_HAS_rem_i32 0
-#define TCG_TARGET_HAS_rot_i32 1
-#define TCG_TARGET_HAS_ext8s_i32 1
-#define TCG_TARGET_HAS_ext16s_i32 1
-#define TCG_TARGET_HAS_ext8u_i32 1
-#define TCG_TARGET_HAS_ext16u_i32 1
-#define TCG_TARGET_HAS_bswap16_i32 1
-#define TCG_TARGET_HAS_bswap32_i32 1
-#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
-#define TCG_TARGET_HAS_andc_i32 1
-#define TCG_TARGET_HAS_orc_i32 1
-#define TCG_TARGET_HAS_eqv_i32 1
-#define TCG_TARGET_HAS_nand_i32 1
-#define TCG_TARGET_HAS_nor_i32 1
-#define TCG_TARGET_HAS_deposit_i32 1
-#define TCG_TARGET_HAS_movcond_i32 1
-#define TCG_TARGET_HAS_mulu2_i32 1
-#define TCG_TARGET_HAS_muls2_i32 0
-#define TCG_TARGET_HAS_muluh_i32 0
-#define TCG_TARGET_HAS_mulsh_i32 0
-
-#define TCG_AREG0 TCG_REG_R27
-
-#define tcg_qemu_tb_exec(env, tb_ptr) \
- ((uintptr_t __attribute__ ((longcall)) \
- (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr)
-
-#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 22/25] tcg-ppc: Rename the tcg/ppc64 backend
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (20 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 21/25] tcg-ppc: Remove the backend Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 23/25] qemu/osdep: Remove the need for qemu_init_auxval Richard Henderson
` (3 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
The other tcg backends that support 32- and 64-bit modes
use the 32-bit name for the port. Follow suit.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
configure | 4 ++--
tcg/{ppc64 => ppc}/tcg-target.c | 0
tcg/{ppc64 => ppc}/tcg-target.h | 0
3 files changed, 2 insertions(+), 2 deletions(-)
rename tcg/{ppc64 => ppc}/tcg-target.c (100%)
rename tcg/{ppc64 => ppc}/tcg-target.h (100%)
diff --git a/configure b/configure
index 277eab4..a803448 100755
--- a/configure
+++ b/configure
@@ -4716,8 +4716,8 @@ elif test "$ARCH" = "s390x" ; then
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES"
elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES"
-elif test "$ARCH" = "ppc" ; then
- QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/ppc64 $QEMU_INCLUDES"
+elif test "$ARCH" = "ppc64" ; then
+ QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/ppc $QEMU_INCLUDES"
else
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES"
fi
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc/tcg-target.c
similarity index 100%
rename from tcg/ppc64/tcg-target.c
rename to tcg/ppc/tcg-target.c
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc/tcg-target.h
similarity index 100%
rename from tcg/ppc64/tcg-target.h
rename to tcg/ppc/tcg-target.h
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 23/25] qemu/osdep: Remove the need for qemu_init_auxval
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (21 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 22/25] tcg-ppc: Rename the tcg/ppc64 backend Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 24/25] tcg-ppc: Merge cache-utils into the backend Richard Henderson
` (2 subsequent siblings)
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
Instead of getting backup auxv data from the env pointer given to main,
read it from /proc/self/auxv. We can do this at any time, so we're not
tied to any ordering wrt a call to qemu_init_auxval from main.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/qemu/osdep.h | 12 ------------
linux-user/main.c | 1 -
util/getauxval.c | 51 +++++++++++++++++++++++++++++++++++++++------------
vl.c | 1 -
4 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index ffb2966..483778d 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -237,18 +237,6 @@ unsigned long qemu_getauxval(unsigned long type);
static inline unsigned long qemu_getauxval(unsigned long type) { return 0; }
#endif
-/**
- * qemu_init_auxval:
- * @envp: the third argument to main
- *
- * If supported and required, locate the auxiliary vector at program startup.
- */
-#if defined(CONFIG_GETAUXVAL) || !defined(__linux__)
-static inline void qemu_init_auxval(char **envp) { }
-#else
-void qemu_init_auxval(char **envp);
-#endif
-
void qemu_set_tty_echo(int fd, bool echo);
#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index a87c6f7..14b7b94 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3829,7 +3829,6 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_QOM);
- qemu_init_auxval(envp);
qemu_cache_utils_init();
if ((envlist = envlist_create()) == NULL) {
diff --git a/util/getauxval.c b/util/getauxval.c
index 476c883..25f48e5 100644
--- a/util/getauxval.c
+++ b/util/getauxval.c
@@ -48,24 +48,51 @@ typedef struct {
static const ElfW_auxv_t *auxv;
-void qemu_init_auxval(char **envp)
+static const ElfW_auxv_t *qemu_init_auxval(void)
{
- /* The auxiliary vector is located just beyond the initial environment. */
- while (*envp++ != NULL) {
- continue;
+ ElfW_auxv_t *a;
+ ssize_t size = 512, r, ofs;
+ int fd;
+
+ /* Allocate some initial storage. Make sure the first entry is set
+ to end-of-list, so that we've got a valid list in case of error. */
+ auxv = a = g_malloc(size);
+ a[0].a_type = 0;
+ a[0].a_val = 0;
+
+ fd = open("/proc/self/auxv", O_RDONLY);
+ if (fd < 0) {
+ return a;
+ }
+
+ /* Read the first SIZE bytes. Hopefully, this covers everything. */
+ r = read(fd, a, size);
+
+ if (r == size) {
+ /* Continue to expand until we do get a partial read. */
+ do {
+ ofs = size;
+ size *= 2;
+ auxv = a = g_realloc(a, size);
+ r = read(fd, (char *)a + ofs, ofs);
+ } while (r == ofs);
}
- auxv = (const ElfW_auxv_t *)envp;
+
+ close(fd);
+ return a;
}
unsigned long qemu_getauxval(unsigned long type)
{
- /* If we were able to find the auxiliary vector, use it. */
- if (auxv) {
- const ElfW_auxv_t *a;
- for (a = auxv; a->a_type != 0; a++) {
- if (a->a_type == type) {
- return a->a_val;
- }
+ const ElfW_auxv_t *a = auxv;
+
+ if (unlikely(a == NULL)) {
+ a = qemu_init_auxval();
+ }
+
+ for (; a->a_type != 0; a++) {
+ if (a->a_type == type) {
+ return a->a_val;
}
}
diff --git a/vl.c b/vl.c
index be69c7f..256287e 100644
--- a/vl.c
+++ b/vl.c
@@ -3029,7 +3029,6 @@ int main(int argc, char **argv, char **envp)
rtc_clock = QEMU_CLOCK_HOST;
- qemu_init_auxval(envp);
qemu_cache_utils_init();
QLIST_INIT (&vm_change_state_head);
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 24/25] tcg-ppc: Merge cache-utils into the backend
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (22 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 23/25] qemu/osdep: Remove the need for qemu_init_auxval Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 25/25] tcg-ppc: Use the return address as a base pointer Richard Henderson
2014-06-20 16:51 ` [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Tom Musta
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
As a "utility", it only supported ppc, and in a way that other
tcg backends provided directly in tcg-target.h. Removing this
disparity is easier now that the two ppc backends are merged.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
exec.c | 1 -
include/qemu/cache-utils.h | 44 ---------------------
linux-user/main.c | 3 --
tcg/ppc/tcg-target.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
tcg/ppc/tcg-target.h | 2 +
tcg/tcg.c | 1 -
util/Makefile.objs | 2 +-
util/cache-utils.c | 86 -----------------------------------------
vl.c | 3 --
9 files changed, 99 insertions(+), 139 deletions(-)
delete mode 100644 include/qemu/cache-utils.h
delete mode 100644 util/cache-utils.c
diff --git a/exec.c b/exec.c
index c3fbbb3..35206fb 100644
--- a/exec.c
+++ b/exec.c
@@ -50,7 +50,6 @@
#include "exec/memory-internal.h"
#include "exec/ram_addr.h"
-#include "qemu/cache-utils.h"
#include "qemu/range.h"
diff --git a/include/qemu/cache-utils.h b/include/qemu/cache-utils.h
deleted file mode 100644
index 211245b..0000000
--- a/include/qemu/cache-utils.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef QEMU_CACHE_UTILS_H
-#define QEMU_CACHE_UTILS_H
-
-#if defined(_ARCH_PPC)
-
-#include <stdint.h> /* uintptr_t */
-
-struct qemu_cache_conf {
- unsigned long dcache_bsize;
- unsigned long icache_bsize;
-};
-
-extern struct qemu_cache_conf qemu_cache_conf;
-
-void qemu_cache_utils_init(void);
-
-/* mildly adjusted code from tcg-dyngen.c */
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
- unsigned long p, start1, stop1;
- unsigned long dsize = qemu_cache_conf.dcache_bsize;
- unsigned long isize = qemu_cache_conf.icache_bsize;
-
- start1 = start & ~(dsize - 1);
- stop1 = (stop + dsize - 1) & ~(dsize - 1);
- for (p = start1; p < stop1; p += dsize) {
- asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
-
- start &= start & ~(isize - 1);
- stop1 = (stop + isize - 1) & ~(isize - 1);
- for (p = start1; p < stop1; p += isize) {
- asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- asm volatile ("isync" : : : "memory");
-}
-
-#else
-#define qemu_cache_utils_init() do { } while (0)
-#endif
-
-#endif /* QEMU_CACHE_UTILS_H */
diff --git a/linux-user/main.c b/linux-user/main.c
index 14b7b94..df1bb0e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -28,7 +28,6 @@
#include "qemu.h"
#include "qemu-common.h"
-#include "qemu/cache-utils.h"
#include "cpu.h"
#include "tcg.h"
#include "qemu/timer.h"
@@ -3829,8 +3828,6 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_QOM);
- qemu_cache_utils_init();
-
if ((envlist = envlist_create()) == NULL) {
(void) fprintf(stderr, "Unable to allocate envlist\n");
exit(1);
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 46d5c4c..e6283e1 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -2538,3 +2538,99 @@ void tcg_register_jit(void *buf, size_t buf_size)
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
#endif /* __ELF__ */
+
+static size_t dcache_bsize = 16;
+static size_t icache_bsize = 16;
+
+void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+ uintptr_t p, start1, stop1;
+ size_t dsize = dcache_bsize;
+ size_t isize = icache_bsize;
+
+ start1 = start & ~(dsize - 1);
+ stop1 = (stop + dsize - 1) & ~(dsize - 1);
+ for (p = start1; p < stop1; p += dsize) {
+ asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
+ }
+ asm volatile ("sync" : : : "memory");
+
+ start &= start & ~(isize - 1);
+ stop1 = (stop + isize - 1) & ~(isize - 1);
+ for (p = start1; p < stop1; p += isize) {
+ asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
+ }
+ asm volatile ("sync" : : : "memory");
+ asm volatile ("isync" : : : "memory");
+}
+
+#if defined _AIX
+#include <sys/systemcfg.h>
+
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+ icache_bsize = _system_configuration.icache_line;
+ dcache_bsize = _system_configuration.dcache_line;
+}
+
+#elif defined __linux__
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+ unsigned long dsize = qemu_getauxval(AT_DCACHEBSIZE);
+ unsigned long isize = qemu_getauxval(AT_ICACHEBSIZE);
+
+ if (dsize == 0 || isize == 0) {
+ if (dsize == 0) {
+ fprintf(stderr, "getauxval AT_DCACHEBSIZE failed\n");
+ }
+ if (isize == 0) {
+ fprintf(stderr, "getauxval AT_ICACHEBSIZE failed\n");
+ }
+ exit(1);
+ }
+ dcache_bsize = dsize;
+ icache_bsize = isize;
+}
+
+#elif defined __APPLE__
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+ size_t len;
+ unsigned cacheline;
+ int name[2] = { CTL_HW, HW_CACHELINE };
+
+ len = sizeof(cacheline);
+ if (sysctl(name, 2, &cacheline, &len, NULL, 0)) {
+ perror("sysctl CTL_HW HW_CACHELINE failed");
+ exit(1);
+ }
+ dcache_bsize = cacheline;
+ icache_bsize = cacheline;
+}
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+ size_t len = 4;
+ unsigned cacheline;
+
+ if (sysctlbyname ("machdep.cacheline_size", &cacheline, &len, NULL, 0)) {
+ fprintf(stderr, "sysctlbyname machdep.cacheline_size failed: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ dcache_bsize = cacheline;
+ icache_bsize = cacheline;
+}
+#endif
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 066e74b..32ac442 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -106,4 +106,6 @@ typedef enum {
#define TCG_TARGET_HAS_mulsh_i64 1
#endif
+void flush_icache_range(uintptr_t start, uintptr_t stop);
+
#endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index dae4b7c..815eec1 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -37,7 +37,6 @@
#endif
#include "qemu-common.h"
-#include "qemu/cache-utils.h"
#include "qemu/host-utils.h"
#include "qemu/timer.h"
diff --git a/util/Makefile.objs b/util/Makefile.objs
index df83b62..6b3c83b 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -1,7 +1,7 @@
util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win32.o
util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o
-util-obj-y += envlist.o path.o host-utils.o cache-utils.o module.o
+util-obj-y += envlist.o path.o host-utils.o module.o
util-obj-y += bitmap.o bitops.o hbitmap.o
util-obj-y += fifo8.o
util-obj-y += acl.o
diff --git a/util/cache-utils.c b/util/cache-utils.c
deleted file mode 100644
index 0470030..0000000
--- a/util/cache-utils.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "qemu-common.h"
-#include "qemu/cache-utils.h"
-
-#if defined(_ARCH_PPC)
-struct qemu_cache_conf qemu_cache_conf = {
- .dcache_bsize = 16,
- .icache_bsize = 16
-};
-
-#if defined _AIX
-#include <sys/systemcfg.h>
-
-void qemu_cache_utils_init(void)
-{
- qemu_cache_conf.icache_bsize = _system_configuration.icache_line;
- qemu_cache_conf.dcache_bsize = _system_configuration.dcache_line;
-}
-
-#elif defined __linux__
-#include "qemu/osdep.h"
-#include "elf.h"
-
-void qemu_cache_utils_init(void)
-{
- unsigned long dsize = qemu_getauxval(AT_DCACHEBSIZE);
- unsigned long isize = qemu_getauxval(AT_ICACHEBSIZE);
-
- if (dsize == 0 || isize == 0) {
- if (dsize == 0) {
- fprintf(stderr, "getauxval AT_DCACHEBSIZE failed\n");
- }
- if (isize == 0) {
- fprintf(stderr, "getauxval AT_ICACHEBSIZE failed\n");
- }
- exit(1);
-
- }
- qemu_cache_conf.dcache_bsize = dsize;
- qemu_cache_conf.icache_bsize = isize;
-}
-
-#elif defined __APPLE__
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-void qemu_cache_utils_init(void)
-{
- size_t len;
- unsigned cacheline;
- int name[2] = { CTL_HW, HW_CACHELINE };
-
- len = sizeof(cacheline);
- if (sysctl(name, 2, &cacheline, &len, NULL, 0)) {
- perror("sysctl CTL_HW HW_CACHELINE failed");
- } else {
- qemu_cache_conf.dcache_bsize = cacheline;
- qemu_cache_conf.icache_bsize = cacheline;
- }
-}
-
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-void qemu_cache_utils_init(void)
-{
- size_t len = 4;
- unsigned cacheline;
-
- if (sysctlbyname ("machdep.cacheline_size", &cacheline, &len, NULL, 0)) {
- fprintf(stderr, "sysctlbyname machdep.cacheline_size failed: %s\n",
- strerror(errno));
- exit(1);
- }
-
- qemu_cache_conf.dcache_bsize = cacheline;
- qemu_cache_conf.icache_bsize = cacheline;
-}
-#endif
-
-#endif /* _ARCH_PPC */
diff --git a/vl.c b/vl.c
index 256287e..242163e 100644
--- a/vl.c
+++ b/vl.c
@@ -82,7 +82,6 @@ int main(int argc, char **argv)
#include "qemu/timer.h"
#include "sysemu/char.h"
#include "qemu/bitmap.h"
-#include "qemu/cache-utils.h"
#include "sysemu/blockdev.h"
#include "hw/block/block.h"
#include "migration/block.h"
@@ -3029,8 +3028,6 @@ int main(int argc, char **argv, char **envp)
rtc_clock = QEMU_CLOCK_HOST;
- qemu_cache_utils_init();
-
QLIST_INIT (&vm_change_state_head);
os_setup_early_signal_handling();
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v3 25/25] tcg-ppc: Use the return address as a base pointer
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (23 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 24/25] tcg-ppc: Merge cache-utils into the backend Richard Henderson
@ 2014-06-20 14:13 ` Richard Henderson
2014-06-20 16:51 ` [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Tom Musta
25 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2014-06-20 14:13 UTC (permalink / raw)
To: qemu-devel; +Cc: tommusta, av1474
This can significantly reduce code size for generation of (some)
64-bit constants. With the side effect that we know for a fact
that exit_tb can use the register to good effect.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/ppc/tcg-target.c | 105 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 93 insertions(+), 12 deletions(-)
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index e6283e1..c83fd9f 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -41,6 +41,30 @@
# define TCG_REG_TMP1 TCG_REG_R12
#endif
+/* For the 64-bit target, we don't like the 5 insn sequence needed to build
+ full 64-bit addresses. Better to have a base register to which we can
+ apply a 32-bit displacement.
+
+ There are generally three items of interest:
+ (1) helper functions in the main executable,
+ (2) TranslationBlock data structures,
+ (3) the return address in the epilogue.
+
+ For user-only, we USE_STATIC_CODE_GEN_BUFFER, so the code_gen_buffer
+ will be inside the main executable, and thus near enough to make a
+ pointer to the epilogue be within 2GB of all helper functions.
+
+ For softmmu, we'll let the kernel choose the address of code_gen_buffer,
+ and odds are it'll be somewhere close to the main malloc arena, and so
+ a pointer to the epilogue will be within 2GB of the TranslationBlocks.
+
+ For --enable-pie, everything will be kinda near everything else,
+ somewhere in high memory.
+
+ Thus we choose to keep the return address in a call-saved register. */
+#define TCG_REG_RA TCG_REG_R31
+#define USE_REG_RA (TCG_TARGET_REG_BITS == 64)
+
/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
#define SZP ((int)sizeof(void *))
@@ -467,6 +491,8 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
#define TW XO31( 4)
#define TRAP (TW | TO(31))
+#define NOP ORI /* ori 0,0,0 */
+
#define RT(r) ((r)<<21)
#define RS(r) ((r)<<21)
#define RA(r) ((r)<<16)
@@ -531,6 +557,9 @@ static const uint32_t tcg_to_isel[] = {
[TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
};
+static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
+ TCGReg base, tcg_target_long offset);
+
static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
{
tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
@@ -601,7 +630,17 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
tcg_out32(s, ADDI | TAI(ret, 0, arg));
tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
} else {
- int32_t high = arg >> 31 >> 1;
+ int32_t high;
+
+ if (USE_REG_RA) {
+ intptr_t diff = arg - (intptr_t)tb_ret_addr;
+ if (diff == (int32_t)diff) {
+ tcg_out_mem_long(s, ADDI, ADD, ret, TCG_REG_RA, diff);
+ return;
+ }
+ }
+
+ high = arg >> 31 >> 1;
tcg_out_movi32(s, ret, high);
if (high) {
tcg_out_shli64(s, ret, ret, 32);
@@ -1714,18 +1753,16 @@ static void tcg_target_qemu_prologue(TCGContext *s)
{
int i;
- tcg_set_frame(s, TCG_REG_CALL_STACK, REG_SAVE_BOT - CPU_TEMP_BUF_SIZE,
- CPU_TEMP_BUF_SIZE);
-
#ifdef _CALL_AIX
- {
- void **desc = (void **)s->code_ptr;
- desc[0] = desc + 2; /* entry point */
- desc[1] = 0; /* environment pointer */
- s->code_ptr = (void *)(desc + 2); /* skip over descriptor */
- }
+ void **desc = (void **)s->code_ptr;
+ desc[0] = desc + 2; /* entry point */
+ desc[1] = 0; /* environment pointer */
+ s->code_ptr = (void *)(desc + 2); /* skip over descriptor */
#endif
+ tcg_set_frame(s, TCG_REG_CALL_STACK, REG_SAVE_BOT - CPU_TEMP_BUF_SIZE,
+ CPU_TEMP_BUF_SIZE);
+
/* Prologue */
tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
tcg_out32(s, (SZR == 8 ? STDU : STWU)
@@ -1746,10 +1783,36 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
- tcg_out32(s, BCCTR | BO_ALWAYS);
+
+ if (USE_REG_RA) {
+#ifdef _CALL_AIX
+ /* Make the caller load the value as the TOC into R2. */
+ tb_ret_addr = s->code_ptr + 2;
+ desc[1] = tb_ret_addr;
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_RA, TCG_REG_R2);
+ tcg_out32(s, BCCTR | BO_ALWAYS);
+#elif defined(_CALL_ELF) && _CALL_ELF == 2
+ /* Compute from the incoming R12 value. */
+ tb_ret_addr = s->code_ptr + 2;
+ tcg_out32(s, ADDI | TAI(TCG_REG_RA, TCG_REG_R12,
+ tcg_ptr_byte_diff(tb_ret_addr, s->code_buf)));
+ tcg_out32(s, BCCTR | BO_ALWAYS);
+#else
+ /* Reserve max 5 insns for the constant load. */
+ tb_ret_addr = s->code_ptr + 6;
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)tb_ret_addr);
+ tcg_out32(s, BCCTR | BO_ALWAYS);
+ while (s->code_ptr < tb_ret_addr) {
+ tcg_out32(s, NOP);
+ }
+#endif
+ } else {
+ tcg_out32(s, BCCTR | BO_ALWAYS);
+ tb_ret_addr = s->code_ptr;
+ }
/* Epilogue */
- tb_ret_addr = s->code_ptr;
+ assert(tb_ret_addr == s->code_ptr);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
@@ -1769,6 +1832,21 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
switch (opc) {
case INDEX_op_exit_tb:
+ if (USE_REG_RA) {
+ ptrdiff_t disp = tcg_pcrel_diff(s, tb_ret_addr);
+
+ /* If we can use a direct branch, otherwise use the value in RA.
+ Note that the direct branch is always forward. If it's in
+ range now, it'll still be in range after the movi. Don't
+ bother about the 20 bytes where the test here fails but it
+ would succeed below. */
+ if (!in_range_b(disp)) {
+ tcg_out32(s, MTSPR | RS(TCG_REG_RA) | CTR);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
+ tcg_out32(s, BCCTR | BO_ALWAYS);
+ break;
+ }
+ }
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
tcg_out_b(s, 0, tb_ret_addr);
break;
@@ -2479,6 +2557,9 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
#endif
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); /* mem temp */
+ if (USE_REG_RA) {
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return addr */
+ }
tcg_add_target_add_op_defs(ppc_op_defs);
}
--
1.9.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
` (24 preceding siblings ...)
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 25/25] tcg-ppc: Use the return address as a base pointer Richard Henderson
@ 2014-06-20 16:51 ` Tom Musta
25 siblings, 0 replies; 28+ messages in thread
From: Tom Musta @ 2014-06-20 16:51 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: av1474
On 6/20/2014 9:13 AM, Richard Henderson wrote:
> Tom Musta gave me a Tested-by
> for v2 on an ELFv2 system; it might be worth re-doing that just in case.
Done.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v3 04/25] tcg-ppc64: Relax register restrictions in tcg_out_mem_long
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 04/25] tcg-ppc64: Relax register restrictions in tcg_out_mem_long Richard Henderson
@ 2014-06-26 13:29 ` Greg Kurz
0 siblings, 0 replies; 28+ messages in thread
From: Greg Kurz @ 2014-06-26 13:29 UTC (permalink / raw)
To: Richard Henderson; +Cc: tommusta, clg, av1474, qemu-devel
On Fri, 20 Jun 2014 07:13:20 -0700
Richard Henderson <rth@twiddle.net> wrote:
> In order to be able to use tcg_out_ld/st sensibly with scratch
> registers, assert only when we'd incorrectly clobber a scratch.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
Hi,
While testing various guest/host combinations for virtio, Cedric hit the following crash with
a x86_64 fedora 20 TCG guest run by a ppc64 or ppc64le upstream QEMU:
[ 0.946484] Unpacking initramfs...
[ 2.371827] Freeing initrd memory: 15620K (ffff88007f0be000 - ffff88007ffff000)
[ 2.372459] PCI-DMA: Using software bounce buffering for IO (SWIOTLB)
[ 2.372818] software IO TLB [mem 0xbbffe000-0xbfffe000] (64MB) mapped at [ffff8800bbffe000-ffff8800bfffdfff]
[ 2.389534] futex hash table entries: 256 (order: 2, 16384 bytes)
[ 2.392753] ------------[ cut here ]------------
[ 2.393213] WARNING: CPU: 0 PID: 25 at kernel/pid.c:278 free_pid+0x14b/0x150()
[ 2.393310] Modules linked in:
[ 2.393310] CPU: 0 PID: 25 Comm: cryptomgr_test Not tainted 3.14.8-200.fc20.x86_64 #1
[ 2.393310] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2.393310] 0000000000000000 00000000a7a5d6ef ffff880138e47d18 ffffffff816f0502
[ 2.393310] 0000000000000000 ffff880138e47d50 ffffffff8108a1cd ffff8800bb599700
[ 2.393310] 0000000000000000 0000000000000046 ffffffff81c444e0 0000000000000000
[ 2.393310] Call Trace:
[ 2.393310] [<ffffffff816f0502>] dump_stack+0x45/0x56
[ 2.393310] [<ffffffff8108a1cd>] warn_slowpath_common+0x7d/0xa0
[ 2.393310] [<ffffffff8108a2fa>] warn_slowpath_null+0x1a/0x20
[ 2.393310] [<ffffffff810aa7cb>] free_pid+0x14b/0x150
[ 2.393310] [<ffffffff810aa82a>] __change_pid+0x5a/0x60
[ 2.393310] [<ffffffff810aad90>] detach_pid+0x10/0x20
[ 2.393310] [<ffffffff8108b393>] release_task+0x353/0x470
[ 2.393310] [<ffffffff8108ca9a>] do_exit+0x5ea/0xa30
[ 2.393310] [<ffffffff81313df0>] ? crypto_unregister_pcomp+0x20/0x20
[ 2.393310] [<ffffffff81100b4f>] __module_put_and_exit+0x2f/0x30
[ 2.393310] [<ffffffff81313e23>] cryptomgr_test+0x33/0x50
[ 2.393310] [<ffffffff810ae2d1>] kthread+0xe1/0x100
[ 2.393310] [<ffffffff810ae1f0>] ? insert_kthread_work+0x40/0x40
[ 2.393310] [<ffffffff8170083c>] ret_from_fork+0x7c/0xb0
[ 2.393310] [<ffffffff810ae1f0>] ? insert_kthread_work+0x40/0x40
[ 2.393310] ---[ end trace c82ee4daf4a04f19 ]---
[ 2.393310] ------------[ cut here ]------------
[ 2.393310] WARNING: CPU: 0 PID: 25 at kernel/workqueue.c:1393 __queue_work+0x2ad/0x310()
[ 2.393310] Modules linked in:
[ 2.393310] CPU: 0 PID: 25 Comm: cryptomgr_test Tainted: G W 3.14.8-200.fc20.x86_64 #1
[ 2.393310] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2.393310] 0000000000000000 00000000a7a5d6ef ffff880138e47cb8 ffffffff816f0502
[ 2.393310] 0000000000000000 ffff880138e47cf0 ffffffff8108a1cd ffff88013fc17e00
[ 2.393310] ffffffff81c44d40 0000000000000400 ffff88013b005a00 0000000000010368
[ 2.393310] Call Trace:
[ 2.393310] [<ffffffff816f0502>] dump_stack+0x45/0x56
[ 2.393310] [<ffffffff8108a1cd>] warn_slowpath_common+0x7d/0xa0
[ 2.393310] [<ffffffff8108a2fa>] warn_slowpath_null+0x1a/0x20
[ 2.393310] [<ffffffff810a484d>] __queue_work+0x2ad/0x310
[ 2.393310] [<ffffffff810a4d67>] queue_work_on+0x27/0x50
[ 2.393310] [<ffffffff810aa6d1>] free_pid+0x51/0x150
[ 2.393310] [<ffffffff810aa82a>] __change_pid+0x5a/0x60
[ 2.393310] [<ffffffff810aad90>] detach_pid+0x10/0x20
[ 2.393310] [<ffffffff8108b393>] release_task+0x353/0x470
[ 2.393310] [<ffffffff8108ca9a>] do_exit+0x5ea/0xa30
[ 2.393310] [<ffffffff81313df0>] ? crypto_unregister_pcomp+0x20/0x20
[ 2.393310] [<ffffffff81100b4f>] __module_put_and_exit+0x2f/0x30
[ 2.393310] [<ffffffff81313e23>] cryptomgr_test+0x33/0x50
[ 2.393310] [<ffffffff810ae2d1>] kthread+0xe1/0x100
[ 2.393310] [<ffffffff810ae1f0>] ? insert_kthread_work+0x40/0x40
[ 2.393310] [<ffffffff8170083c>] ret_from_fork+0x7c/0xb0
[ 2.393310] [<ffffffff810ae1f0>] ? insert_kthread_work+0x40/0x40
[ 2.393310] ---[ end trace c82ee4daf4a04f1a ]---
[ 2.411147] Initialise system trusted keyring
[ 2.412887] audit: initializing netlink subsys (disabled)
[ 2.414491] audit: type=2000 audit(1403786361.413:1): initialized
[ 2.510453] ------------[ cut here ]------------
[ 2.510737] kernel BUG at mm/vmscan.c:3401!
[ 2.511000] invalid opcode: 0000 [#1] SMP
[ 2.511056] Modules linked in:
[ 2.511056] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W 3.14.8-200.fc20.x86_64 #1
[ 2.511056] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2.511056] task: ffff880139b00000 ti: ffff880139a9e000 task.ti: ffff880139a9e000
[ 2.511056] RIP: 0010:[<ffffffff81188711>] [<ffffffff81188711>] kswapd_run+0xc1/0xd0
[ 2.511056] RSP: 0000:ffff880139a9fe08 EFLAGS: 00000246
[ 2.511056] RAX: fffffffffffffff4 RBX: 0000000000000000 RCX: 0000000000000000
[ 2.511056] RDX: 00000000000006ca RSI: ffff880139b00000 RDI: ffff88013b001b00
[ 2.511056] RBP: ffff880139a9fe28 R08: 00000000000173e0 R09: ffff88013fc173e0
[ 2.511056] R10: ffffea0004e4df00 R11: ffffffff810ae161 R12: ffff88013ffe9000
[ 2.511056] R13: 0000000000000000 R14: fffffffffffffff4 R15: 0000000000000000
[ 2.511056] FS: 0000000000000000(0000) GS:ffff88013fc00000(0000) knlGS:0000000000000000
[ 2.511056] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 2.511056] CR2: 0000000000000000 CR3: 0000000001c0c000 CR4: 00000000000006f0
[ 2.511056] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 2.511056] DR3: 0000000000000000 DR6: 0000000000000000 DR7: 0000000000000000
[ 2.511056] Stack:
[ 2.511056] 0000000000000001 0000000000000200 00000000000000fe 0000000000000000
[ 2.511056] ffff880139a9fe48 ffffffff81d5065e 0000000000000000 ffffffff81d5061d
[ 2.511056] ffff880139a9fec0 ffffffff8100216a 0000000000000200 ffff880139a9fec0
[ 2.511056] Call Trace:
[ 2.511056] [<ffffffff81d5065e>] kswapd_init+0x41/0x75
[ 2.511056] [<ffffffff81d5061d>] ? ftrace_define_fields_mm_vmscan_lru_shrink_inactive+0x138/0x138
[ 2.511056] [<ffffffff8100216a>] do_one_initcall+0xfa/0x1b0
[ 2.511056] [<ffffffff810ac225>] ? parse_args+0x225/0x3f0
[ 2.511056] [<ffffffff81d261a3>] kernel_init_freeable+0x1ab/0x247
[ 2.511056] [<ffffffff81d25926>] ? do_early_param+0x88/0x88
[ 2.511056] [<ffffffff816e1690>] ? rest_init+0x80/0x80
[ 2.511056] [<ffffffff816e169e>] kernel_init+0xe/0xf0
[ 2.511056] [<ffffffff8170083c>] ret_from_fork+0x7c/0xb0
[ 2.511056] [<ffffffff816e1690>] ? rest_init+0x80/0x80
[ 2.511056] Code: 2a 44 89 ee 48 c7 c7 20 58 a2 81 31 c0 e8 ad 42 56 00 49 8b 9c 24 d8 3d 01 00 49 c7 84 24 d8 3d 01 00 00 00 00 00 e9 6a ff ff ff <0f> 0b 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55
[ 2.511056] RIP [<ffffffff81188711>] kswapd_run+0xc1/0xd0
[ 2.511056] RSP <ffff880139a9fe08>
[ 2.525816] ---[ end trace c82ee4daf4a04f1b ]---
[ 2.526424] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 2.526424]
[ 2.527124] Kernel Offset: 0x0 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffff9fffffff)
[ 2.527124] general protection fault: fff2 [#2] SMP
[ 2.527124] Modules linked in:
[ 2.527124] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G D W 3.14.8-200.fc20.x86_64 #1
[ 2.527124] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2.527124] task: ffff880139b00000 ti: ffff880139a9e000 task.ti: ffff880139a9e000
[ 2.527124] RIP: 0010:[<ffffffff816ec356>] [<ffffffff816ec356>] panic+0x1a3/0x1e7
[ 2.527124] RSP: 0000:ffff880139a9faf8 EFLAGS: 00000246
[ 2.527124] RAX: 000000000c1f0c1f RBX: ffffffff81a12e20 RCX: 00000000000004ea
[ 2.527124] RDX: 0000000000000c1f RSI: 0000000000000000 RDI: 0000000000000046
[ 2.527124] RBP: ffff880139a9fb68 R08: 0000000000000001 R09: 0000000000000187
[ 2.527124] R10: 0720072007200720 R11: 0720072007200720 R12: 0000000000000000
[ 2.527124] R13: 0000000000000000 R14: 0000000000000000 R15: ffff880139b00000
[ 2.527124] FS: 0000000000000000(0000) GS:ffff88013fc00000(0000) knlGS:0000000000000000
[ 2.527124] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 2.527124] CR2: 0000000000000000 CR3: 0000000001c0c000 CR4: 00000000000006f0
[ 2.527124] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 2.527124] DR3: 0000000000000000 DR6: 0000000000000000 DR7: 0000000000000000
[ 2.527124] Stack:
[ 2.527124] ffff880100000010 ffff880139a9fb78 ffff880139a9fb18 00000000c997aaf8
[ 2.527124] ffff880139b00000 000000000000000b ffff880139b00408 0000000000000019
[ 2.527124] ffffffff81ed9b40 0000000000000099 ffffffff81c444e0 0000000000000000
[ 2.527124] Call Trace:
[ 2.527124] [<ffffffff8108ced1>] do_exit+0xa21/0xa30
[ 2.527124] [<ffffffff816eca1c>] ? printk+0x77/0x8e
[ 2.527124] [<ffffffff816f890c>] oops_end+0x9c/0xe0
[ 2.527124] [<ffffffff81017fdb>] die+0x4b/0x70
[ 2.527124] [<ffffffff816f81a0>] do_trap+0x60/0x170
[ 2.527124] [<ffffffff810150aa>] do_invalid_op+0xaa/0xe0
[ 2.527124] [<ffffffff81188711>] ? kswapd_run+0xc1/0xd0
[ 2.527124] [<ffffffff8118bac0>] ? mem_cgroup_shrink_node_zone+0x160/0x160
[ 2.527124] [<ffffffff816f4579>] ? _cond_resched+0x29/0x40
[ 2.527124] [<ffffffff816f5239>] ? wait_for_completion_killable+0x39/0x180
[ 2.527124] [<ffffffff810bf6a6>] ? try_to_wake_up+0x1e6/0x290
[ 2.527124] [<ffffffff8170201e>] invalid_op+0x1e/0x30
[ 2.527124] [<ffffffff810ae161>] ? kthread_create_on_node+0x141/0x190
[ 2.527124] [<ffffffff81188711>] ? kswapd_run+0xc1/0xd0
[ 2.527124] [<ffffffff811886b0>] ? kswapd_run+0x60/0xd0
[ 2.527124] [<ffffffff81d5065e>] kswapd_init+0x41/0x75
[ 2.527124] [<ffffffff81d5061d>] ? ftrace_define_fields_mm_vmscan_lru_shrink_inactive+0x138/0x138
[ 2.527124] [<ffffffff8100216a>] do_one_initcall+0xfa/0x1b0
[ 2.527124] [<ffffffff810ac225>] ? parse_args+0x225/0x3f0
[ 2.527124] [<ffffffff81d261a3>] kernel_init_freeable+0x1ab/0x247
[ 2.527124] [<ffffffff81d25926>] ? do_early_param+0x88/0x88
[ 2.527124] [<ffffffff816e1690>] ? rest_init+0x80/0x80
[ 2.527124] [<ffffffff816e169e>] kernel_init+0xe/0xf0
[ 2.527124] [<ffffffff8170083c>] ret_from_fork+0x7c/0xb0
[ 2.527124] [<ffffffff816e1690>] ? rest_init+0x80/0x80
[ 2.527124] Code: 00 00 49 ff cc 74 0c bf 58 89 41 00 e8 54 4e c7 ff eb ef 48 83 c3 64 eb b1 83 3d 75 8f 7e 00 00 74 05 e8 6e 7b 9c ff fb 66 66 90 <66> 66 90 45 31 e4 e8 1f 4d a4 ff 4d 39 ec 7c 18 41 83 f6 01 44
[ 2.527124] RIP [<ffffffff816ec356>] panic+0x1a3/0x1e7
[ 2.527124] RSP <ffff880139a9faf8>
[ 2.527124] ---[ end trace c82ee4daf4a04f1c ]---
[ 2.527124] Fixing recursive fault but reboot is needed!
Bisect leads to commit:
commit de7761a39d341ab322f0c2f47ec3ec59a4a6f2a2
Author: Richard Henderson <rth@twiddle.net>
Date: Tue Mar 25 12:22:18 2014 -0700
tcg-ppc64: Relax register restrictions in tcg_out_mem_long
Indeed, I could revert the commit and the crash no longer happens.
Unfortunately, if I pass --enable-debug-tcg to configure, qemu-system-x86_64 always abort , no matter the revert.
$ qemu-system-x86_64 -m 4G -serial mon:stdio -nographic -nodefaults -no-shutdown -snapshot -hda /home/legoater/work/qemu/images/fedora20-x86_64.qcow2
qemu-system-x86_64: /home/greg/Work/qemu/qemu-upstream/tcg/ppc/tcg-target.c:808: tcg_out_mem_long: Assertion `rs != base && (!is_store || rs != rt)' failed.
Aborted
Can a TCG wizard have a look at this ?
Cheers.
--
Greg
> tcg/ppc64/tcg-target.c | 12 +++++++-----
> 1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
> index 951a392..dbe9c5c 100644
> --- a/tcg/ppc64/tcg-target.c
> +++ b/tcg/ppc64/tcg-target.c
> @@ -714,10 +714,9 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
> TCGReg base, tcg_target_long offset)
> {
> tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
> + bool is_store = false;
> TCGReg rs = TCG_REG_R2;
>
> - assert(rt != TCG_REG_R2 && base != TCG_REG_R2);
> -
> switch (opi) {
> case LD: case LWA:
> align = 3;
> @@ -725,19 +724,22 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
> default:
> if (rt != TCG_REG_R0) {
> rs = rt;
> + break;
> }
> break;
> case STD:
> align = 3;
> - break;
> + /* FALLTHRU */
> case STB: case STH: case STW:
> + is_store = true;
> break;
> }
>
> /* For unaligned, or very large offsets, use the indexed form. */
> if (offset & align || offset != (int32_t)offset) {
> - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, orig);
> - tcg_out32(s, opx | TAB(rt, base, TCG_REG_R2));
> + tcg_debug_assert(rs != base && (!is_store || rs != rt));
> + tcg_out_movi(s, TCG_TYPE_PTR, rs, orig);
> + tcg_out32(s, opx | TAB(rt, base, rs));
> return;
> }
>
--
Gregory Kurz kurzgreg@fr.ibm.com
gkurz@linux.vnet.ibm.com
Software Engineer @ IBM/Meiosys http://www.ibm.com
Tel +33 (0)562 165 496
"Anarchy is about taking complete responsibility for yourself."
Alan Moore.
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2014-06-26 13:29 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-20 14:13 [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 01/25] tcg-ppc: Use uintptr_t in ppc_tb_set_jmp_target Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 02/25] tcg-ppc64: Avoid some hard-codings of TCG_TYPE_I64 Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 03/25] tcg-ppc64: Move functions around Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 04/25] tcg-ppc64: Relax register restrictions in tcg_out_mem_long Richard Henderson
2014-06-26 13:29 ` Greg Kurz
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 05/25] tcg-ppc64: Use tcg_out_{ld, st, cmp} internally Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 06/25] tcg-ppc64: Make TCG_AREG0 and TCG_REG_CALL_STACK enum constants Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 07/25] tcg-ppc64: Move call macros out of tcg-target.h Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 08/25] tcg-ppc64: Fix TCG_TARGET_CALL_STACK_OFFSET Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 09/25] tcg-ppc64: Better parameterize the stack frame Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 10/25] tcg-ppc64: Use the correct test in tcg_out_call Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 11/25] tcg-ppc64: Support the ppc64 elfv2 ABI Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 12/25] tcg-ppc64: Adjust tcg_out_call for ELFv2 Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 13/25] tcg-ppc64: Merge 32-bit ABIs into the prologue / frame code Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 14/25] tcg-ppc64: Fix sub2 implementation Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 15/25] tcg-ppc64: Begin merging ppc32 with ppc64 Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 16/25] tcg-ppc64: Merge ppc32 brcond2, setcond2, muluh Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 17/25] tcg-ppc64: Merge ppc32 qemu_ld/st Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 18/25] tcg-ppc64: Merge ppc32 register usage Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 19/25] tcg-ppc64: Support mulsh_i32 Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 20/25] tcg-ppc64: Merge ppc32 shifts Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 21/25] tcg-ppc: Remove the backend Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 22/25] tcg-ppc: Rename the tcg/ppc64 backend Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 23/25] qemu/osdep: Remove the need for qemu_init_auxval Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 24/25] tcg-ppc: Merge cache-utils into the backend Richard Henderson
2014-06-20 14:13 ` [Qemu-devel] [PATCH v3 25/25] tcg-ppc: Use the return address as a base pointer Richard Henderson
2014-06-20 16:51 ` [Qemu-devel] [PATCH v3 00/25] Merge ppc32/ppc64 tcg backends Tom Musta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).