tcg queued patches

-----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJZvo7AAAoJEGTfOOivfiFf7FgIAKEVBYVENbDD98AIOCwg4qld
 uSQDGFoLwPZvyPK6STTDY5BKyiCTsjSEIjs1wJ6r7BCLqvs8sdKKr2r7CXdG4bVG
 KKYpZXPyrpW3wDUletHm8fDBq36swYAkFl4e2z8IgFDMryqnOktJ8qHIanl3C8qN
 B5tIeNWeOGqsoc2TYjBdgG6kjDjSV2CRi0KbEA0SYr8lgpX1mFLRlRQ/WJcK90tj
 CfTKUhFFUWbv7WN00onz/NPiFnX+AuqaeQlaPvHH3AijMN2G34nCHu1zLiBqI2x7
 6kCupqA3w6p3VzKSOPtB0JNREt5IP4jj5jPGfl69NZl3EYUxi4wEktWGWt9b4Eo=
 =o5Mz
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20170917' into staging

tcg queued patches

# gpg: Signature made Sun 17 Sep 2017 16:03:28 BST
# gpg:                using RSA key 0x64DF38E8AF7E215F
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* remotes/rth/tags/pull-tcg-20170917:
  tcg/mips: Fully convert tcg_target_op_def
  tcg/sparc: Fully convert tcg_target_op_def
  tcg/ppc: Fully convert tcg_target_op_def
  tcg/arm: Fully convert tcg_target_op_def
  tcg/aarch64: Fully convert tcg_target_op_def
  tcg: Fix types in tcg_regset_{set,reset}_reg
  tcg: Remove tcg_regset_set32
  tcg: Remove tcg_regset_{or,and,andnot,not}
  tcg: Remove tcg_regset_set
  tcg: Remove tcg_regset_clear
  tcg: Add tcg_op_supported
  accel/tcg: move USER code to user-exec.c
  accel/tcg: move atomic_template.h to accel/tcg/
  accel/tcg: move tcg-runtime to accel/tcg/
  accel/tcg: move user-exec to accel/tcg/
  accel/tcg: move softmmu_template.h to accel/tcg/
  tcg/ppc: disable atomic write check on ppc32

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-09-17 16:24:48 +01:00
commit 4f2058ded4
19 changed files with 1162 additions and 842 deletions

View File

@ -86,7 +86,6 @@ M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: cpus.c
F: exec.c
F: softmmu_template.h
F: accel/tcg/
F: include/exec/cpu*.h
F: include/exec/exec-all.h
@ -1604,8 +1603,7 @@ Overall
M: Riku Voipio <riku.voipio@iki.fi>
S: Maintained
F: thunk.c
F: user-exec.c
F: user-exec-stub.c
F: accel/tcg/user-exec*.c
BSD user
S: Orphan

View File

@ -94,7 +94,7 @@ all: $(PROGS) stap
obj-y += exec.o
obj-y += accel/
obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/tcg-runtime.o
obj-$(CONFIG_TCG) += tcg/tcg-common.o
obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
obj-y += fpu/softfloat.o
@ -119,7 +119,7 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \
-I$(SRC_PATH)/linux-user
obj-y += linux-user/
obj-y += gdbstub.o thunk.o user-exec.o user-exec-stub.o
obj-y += gdbstub.o thunk.o
endif #CONFIG_LINUX_USER
@ -132,7 +132,7 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \
-I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR)
obj-y += bsd-user/
obj-y += gdbstub.o user-exec.o user-exec-stub.o
obj-y += gdbstub.o
endif #CONFIG_BSD_USER

View File

@ -1,4 +1,8 @@
obj-$(CONFIG_SOFTMMU) += tcg-all.o
obj-$(CONFIG_SOFTMMU) += cputlb.o
obj-y += tcg-runtime.o
obj-y += cpu-exec.o cpu-exec-common.o translate-all.o
obj-y += translator.o
obj-$(CONFIG_USER_ONLY) += user-exec.o
obj-$(call lnot,$(CONFIG_SOFTMMU)) += user-exec-stub.o

View File

@ -178,57 +178,3 @@ void HELPER(exit_atomic)(CPUArchState *env)
{
cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC());
}
#ifndef CONFIG_SOFTMMU
/* The softmmu versions of these helpers are in cputlb.c. */
/* Do not allow unaligned operations to proceed. Return the host address. */
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
int size, uintptr_t retaddr)
{
/* Enforce qemu required alignment. */
if (unlikely(addr & (size - 1))) {
cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
}
return g2h(addr);
}
/* Macro to call the above, with local variables from the use context. */
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
#define EXTRA_ARGS
#define DATA_SIZE 1
#include "atomic_template.h"
#define DATA_SIZE 2
#include "atomic_template.h"
#define DATA_SIZE 4
#include "atomic_template.h"
#ifdef CONFIG_ATOMIC64
#define DATA_SIZE 8
#include "atomic_template.h"
#endif
/* The following is only callable from other helpers, and matches up
with the softmmu version. */
#ifdef CONFIG_ATOMIC128
#undef EXTRA_ARGS
#undef ATOMIC_NAME
#undef ATOMIC_MMU_LOOKUP
#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
#define ATOMIC_NAME(X) \
HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, retaddr)
#define DATA_SIZE 16
#include "atomic_template.h"
#endif /* CONFIG_ATOMIC128 */
#endif /* !CONFIG_SOFTMMU */

View File

@ -24,6 +24,7 @@
#include "qemu/bitops.h"
#include "exec/cpu_ldst.h"
#include "translate-all.h"
#include "exec/helper-proto.h"
#undef EAX
#undef ECX
@ -573,3 +574,54 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#error host CPU specific signal handler needed
#endif
/* The softmmu versions of these helpers are in cputlb.c. */
/* Do not allow unaligned operations to proceed. Return the host address. */
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
int size, uintptr_t retaddr)
{
/* Enforce qemu required alignment. */
if (unlikely(addr & (size - 1))) {
cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
}
return g2h(addr);
}
/* Macro to call the above, with local variables from the use context. */
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
#define EXTRA_ARGS
#define DATA_SIZE 1
#include "atomic_template.h"
#define DATA_SIZE 2
#include "atomic_template.h"
#define DATA_SIZE 4
#include "atomic_template.h"
#ifdef CONFIG_ATOMIC64
#define DATA_SIZE 8
#include "atomic_template.h"
#endif
/* The following is only callable from other helpers, and matches up
with the softmmu version. */
#ifdef CONFIG_ATOMIC128
#undef EXTRA_ARGS
#undef ATOMIC_NAME
#undef ATOMIC_MMU_LOOKUP
#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
#define ATOMIC_NAME(X) \
HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, retaddr)
#define DATA_SIZE 16
#include "atomic_template.h"
#endif /* CONFIG_ATOMIC128 */

View File

@ -121,11 +121,11 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
switch (*ct_str++) {
case 'r':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
ct->u.regs = 0xffffffffu;
break;
case 'l': /* qemu_ld / qemu_st address, data_reg */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
ct->u.regs = 0xffffffffu;
#ifdef CONFIG_SOFTMMU
/* x0 and x1 will be overwritten when reading the tlb entry,
and x2, and x3 for helper args, better to avoid using them. */
@ -1786,161 +1786,182 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
#undef REG0
}
static const TCGTargetOpDef aarch64_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_br, { } },
{ INDEX_op_goto_ptr, { "r" } },
{ 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_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_i32, { "rZ", "r" } },
{ INDEX_op_st16_i32, { "rZ", "r" } },
{ INDEX_op_st_i32, { "rZ", "r" } },
{ INDEX_op_st8_i64, { "rZ", "r" } },
{ INDEX_op_st16_i64, { "rZ", "r" } },
{ INDEX_op_st32_i64, { "rZ", "r" } },
{ INDEX_op_st_i64, { "rZ", "r" } },
{ INDEX_op_add_i32, { "r", "r", "rA" } },
{ INDEX_op_add_i64, { "r", "r", "rA" } },
{ INDEX_op_sub_i32, { "r", "r", "rA" } },
{ INDEX_op_sub_i64, { "r", "r", "rA" } },
{ INDEX_op_mul_i32, { "r", "r", "r" } },
{ INDEX_op_mul_i64, { "r", "r", "r" } },
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_div_i64, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i64, { "r", "r", "r" } },
{ INDEX_op_rem_i32, { "r", "r", "r" } },
{ INDEX_op_rem_i64, { "r", "r", "r" } },
{ INDEX_op_remu_i32, { "r", "r", "r" } },
{ INDEX_op_remu_i64, { "r", "r", "r" } },
{ INDEX_op_and_i32, { "r", "r", "rL" } },
{ INDEX_op_and_i64, { "r", "r", "rL" } },
{ INDEX_op_or_i32, { "r", "r", "rL" } },
{ INDEX_op_or_i64, { "r", "r", "rL" } },
{ INDEX_op_xor_i32, { "r", "r", "rL" } },
{ INDEX_op_xor_i64, { "r", "r", "rL" } },
{ INDEX_op_andc_i32, { "r", "r", "rL" } },
{ INDEX_op_andc_i64, { "r", "r", "rL" } },
{ INDEX_op_orc_i32, { "r", "r", "rL" } },
{ INDEX_op_orc_i64, { "r", "r", "rL" } },
{ INDEX_op_eqv_i32, { "r", "r", "rL" } },
{ INDEX_op_eqv_i64, { "r", "r", "rL" } },
{ INDEX_op_neg_i32, { "r", "r" } },
{ INDEX_op_neg_i64, { "r", "r" } },
{ INDEX_op_not_i32, { "r", "r" } },
{ INDEX_op_not_i64, { "r", "r" } },
{ 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_clz_i32, { "r", "r", "rAL" } },
{ INDEX_op_ctz_i32, { "r", "r", "rAL" } },
{ INDEX_op_shl_i64, { "r", "r", "ri" } },
{ INDEX_op_shr_i64, { "r", "r", "ri" } },
{ INDEX_op_sar_i64, { "r", "r", "ri" } },
{ INDEX_op_rotl_i64, { "r", "r", "ri" } },
{ INDEX_op_rotr_i64, { "r", "r", "ri" } },
{ INDEX_op_clz_i64, { "r", "r", "rAL" } },
{ INDEX_op_ctz_i64, { "r", "r", "rAL" } },
{ INDEX_op_brcond_i32, { "r", "rA" } },
{ INDEX_op_brcond_i64, { "r", "rA" } },
{ INDEX_op_setcond_i32, { "r", "r", "rA" } },
{ INDEX_op_setcond_i64, { "r", "r", "rA" } },
{ INDEX_op_movcond_i32, { "r", "r", "rA", "rZ", "rZ" } },
{ INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
{ INDEX_op_qemu_ld_i32, { "r", "l" } },
{ INDEX_op_qemu_ld_i64, { "r", "l" } },
{ INDEX_op_qemu_st_i32, { "lZ", "l" } },
{ INDEX_op_qemu_st_i64, { "lZ", "l" } },
{ INDEX_op_bswap16_i32, { "r", "r" } },
{ INDEX_op_bswap32_i32, { "r", "r" } },
{ INDEX_op_bswap16_i64, { "r", "r" } },
{ INDEX_op_bswap32_i64, { "r", "r" } },
{ INDEX_op_bswap64_i64, { "r", "r" } },
{ INDEX_op_ext8s_i32, { "r", "r" } },
{ INDEX_op_ext16s_i32, { "r", "r" } },
{ INDEX_op_ext8u_i32, { "r", "r" } },
{ INDEX_op_ext16u_i32, { "r", "r" } },
{ INDEX_op_ext8s_i64, { "r", "r" } },
{ INDEX_op_ext16s_i64, { "r", "r" } },
{ INDEX_op_ext32s_i64, { "r", "r" } },
{ INDEX_op_ext8u_i64, { "r", "r" } },
{ INDEX_op_ext16u_i64, { "r", "r" } },
{ INDEX_op_ext32u_i64, { "r", "r" } },
{ INDEX_op_ext_i32_i64, { "r", "r" } },
{ INDEX_op_extu_i32_i64, { "r", "r" } },
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_deposit_i64, { "r", "0", "rZ" } },
{ INDEX_op_extract_i32, { "r", "r" } },
{ INDEX_op_extract_i64, { "r", "r" } },
{ INDEX_op_sextract_i32, { "r", "r" } },
{ INDEX_op_sextract_i64, { "r", "r" } },
{ INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_muluh_i64, { "r", "r", "r" } },
{ INDEX_op_mulsh_i64, { "r", "r", "r" } },
{ INDEX_op_mb, { } },
{ -1 },
};
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(aarch64_op_defs);
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
static const TCGTargetOpDef r_rA = { .args_ct_str = { "r", "rA" } };
static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
static const TCGTargetOpDef lZ_l = { .args_ct_str = { "lZ", "l" } };
static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
static const TCGTargetOpDef r_r_rA = { .args_ct_str = { "r", "r", "rA" } };
static const TCGTargetOpDef r_r_rL = { .args_ct_str = { "r", "r", "rL" } };
static const TCGTargetOpDef r_r_rAL
= { .args_ct_str = { "r", "r", "rAL" } };
static const TCGTargetOpDef dep
= { .args_ct_str = { "r", "0", "rZ" } };
static const TCGTargetOpDef movc
= { .args_ct_str = { "r", "r", "rA", "rZ", "rZ" } };
static const TCGTargetOpDef add2
= { .args_ct_str = { "r", "r", "rZ", "rZ", "rA", "rMZ" } };
for (i = 0; i < n; ++i) {
if (aarch64_op_defs[i].op == op) {
return &aarch64_op_defs[i];
}
switch (op) {
case INDEX_op_goto_ptr:
return &r;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
case INDEX_op_ld16u_i64:
case INDEX_op_ld16s_i64:
case INDEX_op_ld32u_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld_i64:
case INDEX_op_neg_i32:
case INDEX_op_neg_i64:
case INDEX_op_not_i32:
case INDEX_op_not_i64:
case INDEX_op_bswap16_i32:
case INDEX_op_bswap32_i32:
case INDEX_op_bswap16_i64:
case INDEX_op_bswap32_i64:
case INDEX_op_bswap64_i64:
case INDEX_op_ext8s_i32:
case INDEX_op_ext16s_i32:
case INDEX_op_ext8u_i32:
case INDEX_op_ext16u_i32:
case INDEX_op_ext8s_i64:
case INDEX_op_ext16s_i64:
case INDEX_op_ext32s_i64:
case INDEX_op_ext8u_i64:
case INDEX_op_ext16u_i64:
case INDEX_op_ext32u_i64:
case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64:
case INDEX_op_extract_i32:
case INDEX_op_extract_i64:
case INDEX_op_sextract_i32:
case INDEX_op_sextract_i64:
return &r_r;
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
case INDEX_op_st8_i64:
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
return &rZ_r;
case INDEX_op_add_i32:
case INDEX_op_add_i64:
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64:
return &r_r_rA;
case INDEX_op_mul_i32:
case INDEX_op_mul_i64:
case INDEX_op_div_i32:
case INDEX_op_div_i64:
case INDEX_op_divu_i32:
case INDEX_op_divu_i64:
case INDEX_op_rem_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i32:
case INDEX_op_remu_i64:
case INDEX_op_muluh_i64:
case INDEX_op_mulsh_i64:
return &r_r_r;
case INDEX_op_and_i32:
case INDEX_op_and_i64:
case INDEX_op_or_i32:
case INDEX_op_or_i64:
case INDEX_op_xor_i32:
case INDEX_op_xor_i64:
case INDEX_op_andc_i32:
case INDEX_op_andc_i64:
case INDEX_op_orc_i32:
case INDEX_op_orc_i64:
case INDEX_op_eqv_i32:
case INDEX_op_eqv_i64:
return &r_r_rL;
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
case INDEX_op_rotl_i32:
case INDEX_op_rotr_i32:
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
case INDEX_op_rotl_i64:
case INDEX_op_rotr_i64:
return &r_r_ri;
case INDEX_op_clz_i32:
case INDEX_op_ctz_i32:
case INDEX_op_clz_i64:
case INDEX_op_ctz_i64:
return &r_r_rAL;
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
return &r_rA;
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
return &movc;
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_ld_i64:
return &r_l;
case INDEX_op_qemu_st_i32:
case INDEX_op_qemu_st_i64:
return &lZ_l;
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return &dep;
case INDEX_op_add2_i32:
case INDEX_op_add2_i64:
case INDEX_op_sub2_i32:
case INDEX_op_sub2_i64:
return &add2;
default:
return NULL;
}
return NULL;
}
static void tcg_target_init(TCGContext *s)
{
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
(1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
(1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
(1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
(1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
(1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
(1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
(1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
(1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
(1 << TCG_REG_X18) | (1 << TCG_REG_X30));
tcg_target_call_clobber_regs = 0xfffffffu;
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X19);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X20);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X21);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X22);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X23);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X24);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X25);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X26);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X27);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X28);
tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X29);
tcg_regset_clear(s->reserved_regs);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);

View File

@ -264,13 +264,13 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
case 'r':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
ct->u.regs = 0xffff;
break;
/* qemu_ld address */
case 'l':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
ct->u.regs = 0xffff;
#ifdef CONFIG_SOFTMMU
/* r0-r2,lr will be overwritten when reading the tlb entry,
so don't use these. */
@ -284,7 +284,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
/* qemu_st address & data */
case 's':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
ct->u.regs = 0xffff;
/* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
and r0-r1 doing the byte swapping, so don't use these. */
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
@ -2060,91 +2060,119 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
static const TCGTargetOpDef arm_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_br, { } },
{ INDEX_op_goto_ptr, { "r" } },
{ 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" } },
/* TODO: "r", "r", "ri" */
{ INDEX_op_add_i32, { "r", "r", "rIN" } },
{ INDEX_op_sub_i32, { "r", "rI", "rIN" } },
{ INDEX_op_mul_i32, { "r", "r", "r" } },
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
{ INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
{ INDEX_op_and_i32, { "r", "r", "rIK" } },
{ INDEX_op_andc_i32, { "r", "r", "rIK" } },
{ INDEX_op_or_i32, { "r", "r", "rI" } },
{ INDEX_op_xor_i32, { "r", "r", "rI" } },
{ INDEX_op_neg_i32, { "r", "r" } },
{ INDEX_op_not_i32, { "r", "r" } },
{ 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_clz_i32, { "r", "r", "rIK" } },
{ INDEX_op_ctz_i32, { "r", "r", "rIK" } },
{ INDEX_op_brcond_i32, { "r", "rIN" } },
{ INDEX_op_setcond_i32, { "r", "r", "rIN" } },
{ INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
{ INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
{ INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
{ INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
{ INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
#if TARGET_LONG_BITS == 32
{ INDEX_op_qemu_ld_i32, { "r", "l" } },
{ INDEX_op_qemu_ld_i64, { "r", "r", "l" } },
{ INDEX_op_qemu_st_i32, { "s", "s" } },
{ INDEX_op_qemu_st_i64, { "s", "s", "s" } },
#else
{ INDEX_op_qemu_ld_i32, { "r", "l", "l" } },
{ INDEX_op_qemu_ld_i64, { "r", "r", "l", "l" } },
{ INDEX_op_qemu_st_i32, { "s", "s", "s" } },
{ INDEX_op_qemu_st_i64, { "s", "s", "s", "s" } },
#endif
{ INDEX_op_bswap16_i32, { "r", "r" } },
{ INDEX_op_bswap32_i32, { "r", "r" } },
{ INDEX_op_ext8s_i32, { "r", "r" } },
{ INDEX_op_ext16s_i32, { "r", "r" } },
{ INDEX_op_ext16u_i32, { "r", "r" } },
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_extract_i32, { "r", "r" } },
{ INDEX_op_sextract_i32, { "r", "r" } },
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
{ INDEX_op_mb, { } },
{ -1 },
};
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(arm_op_defs);
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef s_s = { .args_ct_str = { "s", "s" } };
static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
static const TCGTargetOpDef r_r_l = { .args_ct_str = { "r", "r", "l" } };
static const TCGTargetOpDef r_l_l = { .args_ct_str = { "r", "l", "l" } };
static const TCGTargetOpDef s_s_s = { .args_ct_str = { "s", "s", "s" } };
static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
static const TCGTargetOpDef r_r_rIN
= { .args_ct_str = { "r", "r", "rIN" } };
static const TCGTargetOpDef r_r_rIK
= { .args_ct_str = { "r", "r", "rIK" } };
static const TCGTargetOpDef r_r_r_r
= { .args_ct_str = { "r", "r", "r", "r" } };
static const TCGTargetOpDef r_r_l_l
= { .args_ct_str = { "r", "r", "l", "l" } };
static const TCGTargetOpDef s_s_s_s
= { .args_ct_str = { "s", "s", "s", "s" } };
static const TCGTargetOpDef br
= { .args_ct_str = { "r", "rIN" } };
static const TCGTargetOpDef dep
= { .args_ct_str = { "r", "0", "rZ" } };
static const TCGTargetOpDef movc
= { .args_ct_str = { "r", "r", "rIN", "rIK", "0" } };
static const TCGTargetOpDef add2
= { .args_ct_str = { "r", "r", "r", "r", "rIN", "rIK" } };
static const TCGTargetOpDef sub2
= { .args_ct_str = { "r", "r", "rI", "rI", "rIN", "rIK" } };
static const TCGTargetOpDef br2
= { .args_ct_str = { "r", "r", "rIN", "rIN" } };
static const TCGTargetOpDef setc2
= { .args_ct_str = { "r", "r", "r", "rIN", "rIN" } };
for (i = 0; i < n; ++i) {
if (arm_op_defs[i].op == op) {
return &arm_op_defs[i];
}
switch (op) {
case INDEX_op_goto_ptr:
return &r;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
case INDEX_op_neg_i32:
case INDEX_op_not_i32:
case INDEX_op_bswap16_i32:
case INDEX_op_bswap32_i32:
case INDEX_op_ext8s_i32:
case INDEX_op_ext16s_i32:
case INDEX_op_ext16u_i32:
case INDEX_op_extract_i32:
case INDEX_op_sextract_i32:
return &r_r;
case INDEX_op_add_i32:
case INDEX_op_sub_i32:
case INDEX_op_setcond_i32:
return &r_r_rIN;
case INDEX_op_and_i32:
case INDEX_op_andc_i32:
case INDEX_op_clz_i32:
case INDEX_op_ctz_i32:
return &r_r_rIK;
case INDEX_op_mul_i32:
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
return &r_r_r;
case INDEX_op_mulu2_i32:
case INDEX_op_muls2_i32:
return &r_r_r_r;
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
return &r_r_rI;
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
case INDEX_op_rotl_i32:
case INDEX_op_rotr_i32:
return &r_r_ri;
case INDEX_op_brcond_i32:
return &br;
case INDEX_op_deposit_i32:
return &dep;
case INDEX_op_movcond_i32:
return &movc;
case INDEX_op_add2_i32:
return &add2;
case INDEX_op_sub2_i32:
return &sub2;
case INDEX_op_brcond2_i32:
return &br2;
case INDEX_op_setcond2_i32:
return &setc2;
case INDEX_op_qemu_ld_i32:
return TARGET_LONG_BITS == 32 ? &r_l : &r_l_l;
case INDEX_op_qemu_ld_i64:
return TARGET_LONG_BITS == 32 ? &r_r_l : &r_r_l_l;
case INDEX_op_qemu_st_i32:
return TARGET_LONG_BITS == 32 ? &s_s : &s_s_s;
case INDEX_op_qemu_st_i64:
return TARGET_LONG_BITS == 32 ? &s_s_s : &s_s_s_s;
default:
return NULL;
}
return NULL;
}
static void tcg_target_init(TCGContext *s)
@ -2164,16 +2192,17 @@ static void tcg_target_init(TCGContext *s)
}
}
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_R0) |
(1 << TCG_REG_R1) |
(1 << TCG_REG_R2) |
(1 << TCG_REG_R3) |
(1 << TCG_REG_R12) |
(1 << TCG_REG_R14));
tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;
tcg_regset_clear(s->reserved_regs);
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R2);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R3);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R12);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);

View File

@ -193,23 +193,15 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 'q':
ct->ct |= TCG_CT_REG;
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(ct->u.regs, 0, 0xffff);
} else {
tcg_regset_set32(ct->u.regs, 0, 0xf);
}
ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
break;
case 'Q':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xf);
ct->u.regs = 0xf;
break;
case 'r':
ct->ct |= TCG_CT_REG;
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(ct->u.regs, 0, 0xffff);
} else {
tcg_regset_set32(ct->u.regs, 0, 0xff);
}
ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
break;
case 'W':
/* With TZCNT/LZCNT, we can have operand-size as an input. */
@ -219,11 +211,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
/* qemu_ld/st address constraint */
case 'L':
ct->ct |= TCG_CT_REG;
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(ct->u.regs, 0, 0xffff);
} else {
tcg_regset_set32(ct->u.regs, 0, 0xff);
}
ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
break;
@ -2643,13 +2631,13 @@ static void tcg_target_init(TCGContext *s)
#endif /* CONFIG_CPUID_H */
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;
tcg_target_available_regs[TCG_TYPE_I64] = 0xffff;
} else {
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
tcg_target_available_regs[TCG_TYPE_I32] = 0xff;
}
tcg_regset_clear(tcg_target_call_clobber_regs);
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
@ -2664,7 +2652,7 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
}
tcg_regset_clear(s->reserved_regs);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
}

View File

@ -195,11 +195,11 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
switch(*ct_str++) {
case 'r':
ct->ct |= TCG_CT_REG;
tcg_regset_set(ct->u.regs, 0xffffffff);
ct->u.regs = 0xffffffff;
break;
case 'L': /* qemu_ld input arg constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set(ct->u.regs, 0xffffffff);
ct->u.regs = 0xffffffff;
tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
#if defined(CONFIG_SOFTMMU)
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
@ -209,7 +209,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 'S': /* qemu_st constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set(ct->u.regs, 0xffffffff);
ct->u.regs = 0xffffffff;
tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
#if defined(CONFIG_SOFTMMU)
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
@ -2163,166 +2163,182 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_br, { } },
{ INDEX_op_goto_ptr, { "r" } },
{ 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, { "rZ", "r" } },
{ INDEX_op_st16_i32, { "rZ", "r" } },
{ INDEX_op_st_i32, { "rZ", "r" } },
{ INDEX_op_add_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
#if !use_mips32r6_instructions
{ INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
{ INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
#endif
{ INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_div_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_sub_i32, { "r", "rZ", "rN" } },
{ INDEX_op_and_i32, { "r", "rZ", "rIK" } },
{ INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_not_i32, { "r", "rZ" } },
{ INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
{ INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
{ INDEX_op_shl_i32, { "r", "rZ", "ri" } },
{ INDEX_op_shr_i32, { "r", "rZ", "ri" } },
{ INDEX_op_sar_i32, { "r", "rZ", "ri" } },
{ INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
{ INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
{ INDEX_op_clz_i32, { "r", "r", "rWZ" } },
{ INDEX_op_bswap16_i32, { "r", "r" } },
{ INDEX_op_bswap32_i32, { "r", "r" } },
{ INDEX_op_ext8s_i32, { "r", "rZ" } },
{ INDEX_op_ext16s_i32, { "r", "rZ" } },
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_extract_i32, { "r", "r" } },
{ INDEX_op_brcond_i32, { "rZ", "rZ" } },
#if use_mips32r6_instructions
{ INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
#else
{ INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
#endif
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
#if TCG_TARGET_REG_BITS == 32
{ INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
{ INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
{ INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
{ INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
#endif
#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_ld32s_i64, { "r", "r" } },
{ INDEX_op_ld32u_i64, { "r", "r" } },
{ INDEX_op_ld_i64, { "r", "r" } },
{ INDEX_op_st8_i64, { "rZ", "r" } },
{ INDEX_op_st16_i64, { "rZ", "r" } },
{ INDEX_op_st32_i64, { "rZ", "r" } },
{ INDEX_op_st_i64, { "rZ", "r" } },
{ INDEX_op_add_i64, { "r", "rZ", "rJ" } },
{ INDEX_op_mul_i64, { "r", "rZ", "rZ" } },
#if !use_mips32r6_instructions
{ INDEX_op_muls2_i64, { "r", "r", "rZ", "rZ" } },
{ INDEX_op_mulu2_i64, { "r", "r", "rZ", "rZ" } },
#endif
{ INDEX_op_mulsh_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_muluh_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_div_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_divu_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_rem_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_remu_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_sub_i64, { "r", "rZ", "rN" } },
{ INDEX_op_and_i64, { "r", "rZ", "rIK" } },
{ INDEX_op_nor_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_not_i64, { "r", "rZ" } },
{ INDEX_op_or_i64, { "r", "rZ", "rI" } },
{ INDEX_op_xor_i64, { "r", "rZ", "rI" } },
{ INDEX_op_shl_i64, { "r", "rZ", "ri" } },
{ INDEX_op_shr_i64, { "r", "rZ", "ri" } },
{ INDEX_op_sar_i64, { "r", "rZ", "ri" } },
{ INDEX_op_rotr_i64, { "r", "rZ", "ri" } },
{ INDEX_op_rotl_i64, { "r", "rZ", "ri" } },
{ INDEX_op_clz_i64, { "r", "r", "rWZ" } },
{ INDEX_op_bswap16_i64, { "r", "r" } },
{ INDEX_op_bswap32_i64, { "r", "r" } },
{ INDEX_op_bswap64_i64, { "r", "r" } },
{ INDEX_op_ext8s_i64, { "r", "rZ" } },
{ INDEX_op_ext16s_i64, { "r", "rZ" } },
{ INDEX_op_ext32s_i64, { "r", "rZ" } },
{ INDEX_op_ext32u_i64, { "r", "rZ" } },
{ INDEX_op_ext_i32_i64, { "r", "rZ" } },
{ INDEX_op_extu_i32_i64, { "r", "rZ" } },
{ INDEX_op_extrl_i64_i32, { "r", "rZ" } },
{ INDEX_op_extrh_i64_i32, { "r", "rZ" } },
{ INDEX_op_deposit_i64, { "r", "0", "rZ" } },
{ INDEX_op_extract_i64, { "r", "r" } },
{ INDEX_op_brcond_i64, { "rZ", "rZ" } },
#if use_mips32r6_instructions
{ INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rZ", "rZ" } },
#else
{ INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rZ", "0" } },
#endif
{ INDEX_op_setcond_i64, { "r", "rZ", "rZ" } },
{ INDEX_op_qemu_ld_i32, { "r", "LZ" } },
{ INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
{ INDEX_op_qemu_ld_i64, { "r", "LZ" } },
{ INDEX_op_qemu_st_i64, { "SZ", "SZ" } },
#elif TARGET_LONG_BITS == 32
{ INDEX_op_qemu_ld_i32, { "r", "LZ" } },
{ INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
{ INDEX_op_qemu_ld_i64, { "r", "r", "LZ" } },
{ INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ" } },
#else
{ INDEX_op_qemu_ld_i32, { "r", "LZ", "LZ" } },
{ INDEX_op_qemu_st_i32, { "SZ", "SZ", "SZ" } },
{ INDEX_op_qemu_ld_i64, { "r", "r", "LZ", "LZ" } },
{ INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ", "SZ" } },
#endif
{ INDEX_op_mb, { } },
{ -1 },
};
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(mips_op_defs);
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
static const TCGTargetOpDef SZ_S = { .args_ct_str = { "SZ", "S" } };
static const TCGTargetOpDef rZ_rZ = { .args_ct_str = { "rZ", "rZ" } };
static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
static const TCGTargetOpDef r_r_rJ = { .args_ct_str = { "r", "r", "rJ" } };
static const TCGTargetOpDef SZ_S_S = { .args_ct_str = { "SZ", "S", "S" } };
static const TCGTargetOpDef SZ_SZ_S
= { .args_ct_str = { "SZ", "SZ", "S" } };
static const TCGTargetOpDef SZ_SZ_S_S
= { .args_ct_str = { "SZ", "SZ", "S", "S" } };
static const TCGTargetOpDef r_rZ_rN
= { .args_ct_str = { "r", "rZ", "rN" } };
static const TCGTargetOpDef r_rZ_rZ
= { .args_ct_str = { "r", "rZ", "rZ" } };
static const TCGTargetOpDef r_r_rIK
= { .args_ct_str = { "r", "r", "rIK" } };
static const TCGTargetOpDef r_r_rWZ
= { .args_ct_str = { "r", "r", "rWZ" } };
static const TCGTargetOpDef r_r_r_r
= { .args_ct_str = { "r", "r", "r", "r" } };
static const TCGTargetOpDef r_r_L_L
= { .args_ct_str = { "r", "r", "L", "L" } };
static const TCGTargetOpDef dep
= { .args_ct_str = { "r", "0", "rZ" } };
static const TCGTargetOpDef movc
= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "0" } };
static const TCGTargetOpDef movc_r6
= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
static const TCGTargetOpDef add2
= { .args_ct_str = { "r", "r", "rZ", "rZ", "rN", "rN" } };
static const TCGTargetOpDef br2
= { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
static const TCGTargetOpDef setc2
= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
for (i = 0; i < n; ++i) {
if (mips_op_defs[i].op == op) {
return &mips_op_defs[i];
}
switch (op) {
case INDEX_op_goto_ptr:
return &r;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
case INDEX_op_not_i32:
case INDEX_op_bswap16_i32:
case INDEX_op_bswap32_i32:
case INDEX_op_ext8s_i32:
case INDEX_op_ext16s_i32:
case INDEX_op_extract_i32:
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
case INDEX_op_ld16u_i64:
case INDEX_op_ld16s_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld32u_i64:
case INDEX_op_ld_i64:
case INDEX_op_not_i64:
case INDEX_op_bswap16_i64:
case INDEX_op_bswap32_i64:
case INDEX_op_bswap64_i64:
case INDEX_op_ext8s_i64:
case INDEX_op_ext16s_i64:
case INDEX_op_ext32s_i64:
case INDEX_op_ext32u_i64:
case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64:
case INDEX_op_extrl_i64_i32:
case INDEX_op_extrh_i64_i32:
case INDEX_op_extract_i64:
return &r_r;
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
case INDEX_op_st8_i64:
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
return &rZ_r;
case INDEX_op_add_i32:
case INDEX_op_add_i64:
return &r_r_rJ;
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
return &r_rZ_rN;
case INDEX_op_mul_i32:
case INDEX_op_mulsh_i32:
case INDEX_op_muluh_i32:
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
case INDEX_op_rem_i32:
case INDEX_op_remu_i32:
case INDEX_op_nor_i32:
case INDEX_op_setcond_i32:
case INDEX_op_mul_i64:
case INDEX_op_mulsh_i64:
case INDEX_op_muluh_i64:
case INDEX_op_div_i64:
case INDEX_op_divu_i64:
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
case INDEX_op_nor_i64:
case INDEX_op_setcond_i64:
return &r_rZ_rZ;
case INDEX_op_muls2_i32:
case INDEX_op_mulu2_i32:
case INDEX_op_muls2_i64:
case INDEX_op_mulu2_i64:
return &r_r_r_r;
case INDEX_op_and_i32:
case INDEX_op_and_i64:
return &r_r_rIK;
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
return &r_r_rI;
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
case INDEX_op_rotr_i32:
case INDEX_op_rotl_i32:
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
case INDEX_op_rotr_i64:
case INDEX_op_rotl_i64:
return &r_r_ri;
case INDEX_op_clz_i32:
case INDEX_op_clz_i64:
return &r_r_rWZ;
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return &dep;
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
return &rZ_rZ;
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
return use_mips32r6_instructions ? &movc_r6 : &movc;
case INDEX_op_add2_i32:
case INDEX_op_sub2_i32:
return &add2;
case INDEX_op_setcond2_i32:
return &setc2;
case INDEX_op_brcond2_i32:
return &br2;
case INDEX_op_qemu_ld_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
? &r_L : &r_L_L);
case INDEX_op_qemu_st_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
? &SZ_S : &SZ_S_S);
case INDEX_op_qemu_ld_i64:
return (TCG_TARGET_REG_BITS == 64 ? &r_L
: TARGET_LONG_BITS == 32 ? &r_r_L : &r_r_L_L);
case INDEX_op_qemu_st_i64:
return (TCG_TARGET_REG_BITS == 64 ? &SZ_S
: TARGET_LONG_BITS == 32 ? &SZ_SZ_S : &SZ_SZ_S_S);
default:
return NULL;
}
return NULL;
}
static int tcg_target_callee_save_regs[] = {
@ -2607,29 +2623,30 @@ static void tcg_target_qemu_prologue(TCGContext *s)
static void tcg_target_init(TCGContext *s)
{
tcg_target_detect_isa();
tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I64], 0xffffffff);
tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
}
tcg_regset_set(tcg_target_call_clobber_regs,
(1 << TCG_REG_V0) |
(1 << TCG_REG_V1) |
(1 << TCG_REG_A0) |
(1 << TCG_REG_A1) |
(1 << TCG_REG_A2) |
(1 << TCG_REG_A3) |
(1 << TCG_REG_T0) |
(1 << TCG_REG_T1) |
(1 << TCG_REG_T2) |
(1 << TCG_REG_T3) |
(1 << TCG_REG_T4) |
(1 << TCG_REG_T5) |
(1 << TCG_REG_T6) |
(1 << TCG_REG_T7) |
(1 << TCG_REG_T8) |
(1 << TCG_REG_T9));
tcg_regset_clear(s->reserved_regs);
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */

View File

@ -260,11 +260,11 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 'r':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
ct->u.regs = 0xffffffff;
break;
case 'L': /* qemu_ld constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
ct->u.regs = 0xffffffff;
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
#ifdef CONFIG_SOFTMMU
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
@ -273,7 +273,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 'S': /* qemu_st constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
ct->u.regs = 0xffffffff;
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
#ifdef CONFIG_SOFTMMU
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
@ -1374,7 +1374,9 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
pair = (uint64_t)i2 << 32 | i1;
#endif
atomic_set((uint64_t *)jmp_addr, pair);
/* As per the enclosing if, this is ppc64. Avoid the _Static_assert
within atomic_set that would fail to build a ppc32 host. */
atomic_set__nocheck((uint64_t *)jmp_addr, pair);
flush_icache_range(jmp_addr, jmp_addr + 8);
} else {
intptr_t diff = addr - jmp_addr;
@ -2594,166 +2596,181 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
}
}
static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_br, { } },
{ INDEX_op_goto_ptr, { "r" } },
{ 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_sub_i32, { "r", "rI", "ri" } },
{ INDEX_op_and_i32, { "r", "r", "ri" } },
{ INDEX_op_or_i32, { "r", "r", "ri" } },
{ INDEX_op_xor_i32, { "r", "r", "ri" } },
{ INDEX_op_andc_i32, { "r", "r", "ri" } },
{ INDEX_op_orc_i32, { "r", "r", "ri" } },
{ INDEX_op_eqv_i32, { "r", "r", "ri" } },
{ INDEX_op_nand_i32, { "r", "r", "r" } },
{ INDEX_op_nor_i32, { "r", "r", "r" } },
{ INDEX_op_clz_i32, { "r", "r", "rZW" } },
{ INDEX_op_ctz_i32, { "r", "r", "rZW" } },
{ INDEX_op_ctpop_i32, { "r", "r" } },
{ 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_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" } },
{ INDEX_op_extract_i32, { "r", "r" } },
{ 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" } },
{ 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" } },
{ INDEX_op_and_i64, { "r", "r", "ri" } },
{ INDEX_op_or_i64, { "r", "r", "rU" } },
{ INDEX_op_xor_i64, { "r", "r", "rU" } },
{ INDEX_op_andc_i64, { "r", "r", "ri" } },
{ INDEX_op_orc_i64, { "r", "r", "r" } },
{ INDEX_op_eqv_i64, { "r", "r", "r" } },
{ INDEX_op_nand_i64, { "r", "r", "r" } },
{ INDEX_op_nor_i64, { "r", "r", "r" } },
{ INDEX_op_clz_i64, { "r", "r", "rZW" } },
{ INDEX_op_ctz_i64, { "r", "r", "rZW" } },
{ INDEX_op_ctpop_i64, { "r", "r" } },
{ INDEX_op_shl_i64, { "r", "r", "ri" } },
{ INDEX_op_shr_i64, { "r", "r", "ri" } },
{ INDEX_op_sar_i64, { "r", "r", "ri" } },
{ INDEX_op_rotl_i64, { "r", "r", "ri" } },
{ INDEX_op_rotr_i64, { "r", "r", "ri" } },
{ INDEX_op_mul_i64, { "r", "r", "rI" } },
{ INDEX_op_div_i64, { "r", "r", "r" } },
{ INDEX_op_divu_i64, { "r", "r", "r" } },
{ INDEX_op_neg_i64, { "r", "r" } },
{ INDEX_op_not_i64, { "r", "r" } },
{ INDEX_op_ext8s_i64, { "r", "r" } },
{ INDEX_op_ext16s_i64, { "r", "r" } },
{ INDEX_op_ext32s_i64, { "r", "r" } },
{ INDEX_op_ext_i32_i64, { "r", "r" } },
{ INDEX_op_extu_i32_i64, { "r", "r" } },
{ INDEX_op_bswap16_i64, { "r", "r" } },
{ INDEX_op_bswap32_i64, { "r", "r" } },
{ INDEX_op_bswap64_i64, { "r", "r" } },
{ 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_extract_i64, { "r", "r" } },
{ INDEX_op_mulsh_i64, { "r", "r", "r" } },
{ 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" } },
#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, { "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, { "L", "L", "L", "L" } },
{ INDEX_op_qemu_st_i64, { "S", "S", "S", "S" } },
#endif
{ INDEX_op_mb, { } },
{ -1 },
};
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(ppc_op_defs);
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
static const TCGTargetOpDef S_S = { .args_ct_str = { "S", "S" } };
static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
static const TCGTargetOpDef L_L_L = { .args_ct_str = { "L", "L", "L" } };
static const TCGTargetOpDef S_S_S = { .args_ct_str = { "S", "S", "S" } };
static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
static const TCGTargetOpDef r_r_rT = { .args_ct_str = { "r", "r", "rT" } };
static const TCGTargetOpDef r_r_rU = { .args_ct_str = { "r", "r", "rU" } };
static const TCGTargetOpDef r_rI_ri
= { .args_ct_str = { "r", "rI", "ri" } };
static const TCGTargetOpDef r_rI_rT
= { .args_ct_str = { "r", "rI", "rT" } };
static const TCGTargetOpDef r_r_rZW
= { .args_ct_str = { "r", "r", "rZW" } };
static const TCGTargetOpDef L_L_L_L
= { .args_ct_str = { "L", "L", "L", "L" } };
static const TCGTargetOpDef S_S_S_S
= { .args_ct_str = { "S", "S", "S", "S" } };
static const TCGTargetOpDef movc
= { .args_ct_str = { "r", "r", "ri", "rZ", "rZ" } };
static const TCGTargetOpDef dep
= { .args_ct_str = { "r", "0", "rZ" } };
static const TCGTargetOpDef br2
= { .args_ct_str = { "r", "r", "ri", "ri" } };
static const TCGTargetOpDef setc2
= { .args_ct_str = { "r", "r", "r", "ri", "ri" } };
static const TCGTargetOpDef add2
= { .args_ct_str = { "r", "r", "r", "r", "rI", "rZM" } };
static const TCGTargetOpDef sub2
= { .args_ct_str = { "r", "r", "rI", "rZM", "r", "r" } };
for (i = 0; i < n; ++i) {
if (ppc_op_defs[i].op == op) {
return &ppc_op_defs[i];
}
switch (op) {
case INDEX_op_goto_ptr:
return &r;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
case INDEX_op_ctpop_i32:
case INDEX_op_neg_i32:
case INDEX_op_not_i32:
case INDEX_op_ext8s_i32:
case INDEX_op_ext16s_i32:
case INDEX_op_bswap16_i32:
case INDEX_op_bswap32_i32:
case INDEX_op_extract_i32:
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
case INDEX_op_ld16u_i64:
case INDEX_op_ld16s_i64:
case INDEX_op_ld32u_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld_i64:
case INDEX_op_st8_i64:
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
case INDEX_op_ctpop_i64:
case INDEX_op_neg_i64:
case INDEX_op_not_i64:
case INDEX_op_ext8s_i64:
case INDEX_op_ext16s_i64:
case INDEX_op_ext32s_i64:
case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64:
case INDEX_op_bswap16_i64:
case INDEX_op_bswap32_i64:
case INDEX_op_bswap64_i64:
case INDEX_op_extract_i64:
return &r_r;
case INDEX_op_add_i32:
case INDEX_op_and_i32:
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
case INDEX_op_andc_i32:
case INDEX_op_orc_i32:
case INDEX_op_eqv_i32:
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
case INDEX_op_rotl_i32:
case INDEX_op_rotr_i32:
case INDEX_op_setcond_i32:
case INDEX_op_and_i64:
case INDEX_op_andc_i64:
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
case INDEX_op_rotl_i64:
case INDEX_op_rotr_i64:
case INDEX_op_setcond_i64:
return &r_r_ri;
case INDEX_op_mul_i32:
case INDEX_op_mul_i64:
return &r_r_rI;
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
case INDEX_op_nand_i32:
case INDEX_op_nor_i32:
case INDEX_op_muluh_i32:
case INDEX_op_mulsh_i32:
case INDEX_op_orc_i64:
case INDEX_op_eqv_i64:
case INDEX_op_nand_i64:
case INDEX_op_nor_i64:
case INDEX_op_div_i64:
case INDEX_op_divu_i64:
case INDEX_op_mulsh_i64:
case INDEX_op_muluh_i64:
return &r_r_r;
case INDEX_op_sub_i32:
return &r_rI_ri;
case INDEX_op_add_i64:
return &r_r_rT;
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
return &r_r_rU;
case INDEX_op_sub_i64:
return &r_rI_rT;
case INDEX_op_clz_i32:
case INDEX_op_ctz_i32:
case INDEX_op_clz_i64:
case INDEX_op_ctz_i64:
return &r_r_rZW;
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
return &r_ri;
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
return &movc;
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return &dep;
case INDEX_op_brcond2_i32:
return &br2;
case INDEX_op_setcond2_i32:
return &setc2;
case INDEX_op_add2_i64:
case INDEX_op_add2_i32:
return &add2;
case INDEX_op_sub2_i64:
case INDEX_op_sub2_i32:
return &sub2;
case INDEX_op_qemu_ld_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
? &r_L : &r_L_L);
case INDEX_op_qemu_st_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
? &S_S : &S_S_S);
case INDEX_op_qemu_ld_i64:
return (TCG_TARGET_REG_BITS == 64 ? &r_L
: TARGET_LONG_BITS == 32 ? &L_L_L : &L_L_L_L);
case INDEX_op_qemu_st_i64:
return (TCG_TARGET_REG_BITS == 64 ? &S_S
: TARGET_LONG_BITS == 32 ? &S_S_S : &S_S_S_S);
default:
return NULL;
}
return NULL;
}
static void tcg_target_init(TCGContext *s)
@ -2770,23 +2787,24 @@ static void tcg_target_init(TCGContext *s)
}
#endif
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_R0) |
(1 << TCG_REG_R2) |
(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_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
tcg_regset_clear(s->reserved_regs);
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R2);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R3);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R4);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R5);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R6);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R7);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R12);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
#if defined(_CALL_SYSV)

View File

@ -402,23 +402,23 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
switch (*ct_str++) {
case 'r': /* all registers */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffff);
ct->u.regs = 0xffff;
break;
case 'L': /* qemu_ld/st constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffff);
tcg_regset_reset_reg (ct->u.regs, TCG_REG_R2);
tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
ct->u.regs = 0xffff;
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
break;
case 'a': /* force R2 for division */
ct->ct |= TCG_CT_REG;
tcg_regset_clear(ct->u.regs);
ct->u.regs = 0;
tcg_regset_set_reg(ct->u.regs, TCG_REG_R2);
break;
case 'b': /* force R3 for division */
ct->ct |= TCG_CT_REG;
tcg_regset_clear(ct->u.regs);
ct->u.regs = 0;
tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
break;
case 'A':
@ -2519,10 +2519,10 @@ static void tcg_target_init(TCGContext *s)
{
query_s390_facilities();
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;
tcg_target_available_regs[TCG_TYPE_I64] = 0xffff;
tcg_regset_clear(tcg_target_call_clobber_regs);
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R2);
@ -2535,7 +2535,7 @@ static void tcg_target_init(TCGContext *s)
/* The return register can be considered call-clobbered. */
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
tcg_regset_clear(s->reserved_regs);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);
/* XXX many insns can't be used with R0, so we better avoid it for now */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);

View File

@ -343,16 +343,15 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
switch (*ct_str++) {
case 'r':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
ct->u.regs = 0xffffffff;
break;
case 'R':
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, ALL_64);
ct->u.regs = ALL_64;
break;
case 'A': /* qemu_ld/st address constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0,
TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff);
ct->u.regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
reserve_helpers:
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
@ -360,11 +359,11 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 's': /* qemu_st data 32-bit constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
ct->u.regs = 0xffffffff;
goto reserve_helpers;
case 'S': /* qemu_st data 64-bit constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, ALL_64);
ct->u.regs = ALL_64;
goto reserve_helpers;
case 'I':
ct->ct |= TCG_CT_CONST_S11;
@ -1633,112 +1632,147 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_br, { } },
{ INDEX_op_goto_ptr, { "r" } },
{ 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, { "rZ", "r" } },
{ INDEX_op_st16_i32, { "rZ", "r" } },
{ INDEX_op_st_i32, { "rZ", "r" } },
{ INDEX_op_add_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_div_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_divu_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_and_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_andc_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_or_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_orc_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_xor_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_shl_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_shr_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_sar_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_neg_i32, { "r", "rJ" } },
{ INDEX_op_not_i32, { "r", "rJ" } },
{ INDEX_op_brcond_i32, { "rZ", "rJ" } },
{ INDEX_op_setcond_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_movcond_i32, { "r", "rZ", "rJ", "rI", "0" } },
{ INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
{ INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
{ INDEX_op_mulu2_i32, { "r", "r", "rZ", "rJ" } },
{ INDEX_op_muls2_i32, { "r", "r", "rZ", "rJ" } },
{ 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, { "RZ", "r" } },
{ INDEX_op_st16_i64, { "RZ", "r" } },
{ INDEX_op_st32_i64, { "RZ", "r" } },
{ INDEX_op_st_i64, { "RZ", "r" } },
{ INDEX_op_add_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_mul_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_div_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_divu_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_sub_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_and_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_andc_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_or_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_orc_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_xor_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_shl_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_shr_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_sar_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_neg_i64, { "R", "RJ" } },
{ INDEX_op_not_i64, { "R", "RJ" } },
{ INDEX_op_ext32s_i64, { "R", "R" } },
{ INDEX_op_ext32u_i64, { "R", "R" } },
{ INDEX_op_ext_i32_i64, { "R", "r" } },
{ INDEX_op_extu_i32_i64, { "R", "r" } },
{ INDEX_op_extrl_i64_i32, { "r", "R" } },
{ INDEX_op_extrh_i64_i32, { "r", "R" } },
{ INDEX_op_brcond_i64, { "RZ", "RJ" } },
{ INDEX_op_setcond_i64, { "R", "RZ", "RJ" } },
{ INDEX_op_movcond_i64, { "R", "RZ", "RJ", "RI", "0" } },
{ INDEX_op_add2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
{ INDEX_op_sub2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
{ INDEX_op_muluh_i64, { "R", "RZ", "RZ" } },
{ INDEX_op_qemu_ld_i32, { "r", "A" } },
{ INDEX_op_qemu_ld_i64, { "R", "A" } },
{ INDEX_op_qemu_st_i32, { "sZ", "A" } },
{ INDEX_op_qemu_st_i64, { "SZ", "A" } },
{ INDEX_op_mb, { } },
{ -1 },
};
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(sparc_op_defs);
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef R_r = { .args_ct_str = { "R", "r" } };
static const TCGTargetOpDef r_R = { .args_ct_str = { "r", "R" } };
static const TCGTargetOpDef R_R = { .args_ct_str = { "R", "R" } };
static const TCGTargetOpDef r_A = { .args_ct_str = { "r", "A" } };
static const TCGTargetOpDef R_A = { .args_ct_str = { "R", "A" } };
static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
static const TCGTargetOpDef RZ_r = { .args_ct_str = { "RZ", "r" } };
static const TCGTargetOpDef sZ_A = { .args_ct_str = { "sZ", "A" } };
static const TCGTargetOpDef SZ_A = { .args_ct_str = { "SZ", "A" } };
static const TCGTargetOpDef rZ_rJ = { .args_ct_str = { "rZ", "rJ" } };
static const TCGTargetOpDef RZ_RJ = { .args_ct_str = { "RZ", "RJ" } };
static const TCGTargetOpDef R_R_R = { .args_ct_str = { "R", "R", "R" } };
static const TCGTargetOpDef r_rZ_rJ
= { .args_ct_str = { "r", "rZ", "rJ" } };
static const TCGTargetOpDef R_RZ_RJ
= { .args_ct_str = { "R", "RZ", "RJ" } };
static const TCGTargetOpDef r_r_rZ_rJ
= { .args_ct_str = { "r", "r", "rZ", "rJ" } };
static const TCGTargetOpDef movc_32
= { .args_ct_str = { "r", "rZ", "rJ", "rI", "0" } };
static const TCGTargetOpDef movc_64
= { .args_ct_str = { "R", "RZ", "RJ", "RI", "0" } };
static const TCGTargetOpDef add2_32
= { .args_ct_str = { "r", "r", "rZ", "rZ", "rJ", "rJ" } };
static const TCGTargetOpDef add2_64
= { .args_ct_str = { "R", "R", "RZ", "RZ", "RJ", "RI" } };
for (i = 0; i < n; ++i) {
if (sparc_op_defs[i].op == op) {
return &sparc_op_defs[i];
}
switch (op) {
case INDEX_op_goto_ptr:
return &r;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
case INDEX_op_neg_i32:
case INDEX_op_not_i32:
return &r_r;
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
return &rZ_r;
case INDEX_op_add_i32:
case INDEX_op_mul_i32:
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
case INDEX_op_sub_i32:
case INDEX_op_and_i32:
case INDEX_op_andc_i32:
case INDEX_op_or_i32:
case INDEX_op_orc_i32:
case INDEX_op_xor_i32:
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
case INDEX_op_setcond_i32:
return &r_rZ_rJ;
case INDEX_op_brcond_i32:
return &rZ_rJ;
case INDEX_op_movcond_i32:
return &movc_32;
case INDEX_op_add2_i32:
case INDEX_op_sub2_i32:
return &add2_32;
case INDEX_op_mulu2_i32:
case INDEX_op_muls2_i32:
return &r_r_rZ_rJ;
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
case INDEX_op_ld16u_i64:
case INDEX_op_ld16s_i64:
case INDEX_op_ld32u_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld_i64:
case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64:
return &R_r;
case INDEX_op_st8_i64:
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
return &RZ_r;
case INDEX_op_add_i64:
case INDEX_op_mul_i64:
case INDEX_op_div_i64:
case INDEX_op_divu_i64:
case INDEX_op_sub_i64:
case INDEX_op_and_i64:
case INDEX_op_andc_i64:
case INDEX_op_or_i64:
case INDEX_op_orc_i64:
case INDEX_op_xor_i64:
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
case INDEX_op_setcond_i64:
return &R_RZ_RJ;
case INDEX_op_neg_i64:
case INDEX_op_not_i64:
case INDEX_op_ext32s_i64:
case INDEX_op_ext32u_i64:
return &R_R;
case INDEX_op_extrl_i64_i32:
case INDEX_op_extrh_i64_i32:
return &r_R;
case INDEX_op_brcond_i64:
return &RZ_RJ;
case INDEX_op_movcond_i64:
return &movc_64;
case INDEX_op_add2_i64:
case INDEX_op_sub2_i64:
return &add2_64;
case INDEX_op_muluh_i64:
return &R_R_R;
case INDEX_op_qemu_ld_i32:
return &r_A;
case INDEX_op_qemu_ld_i64:
return &R_A;
case INDEX_op_qemu_st_i32:
return &sZ_A;
case INDEX_op_qemu_st_i64:
return &SZ_A;
default:
return NULL;
}
return NULL;
}
static void tcg_target_init(TCGContext *s)
@ -1752,26 +1786,27 @@ static void tcg_target_init(TCGContext *s)
}
#endif
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, ALL_64);
tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
tcg_target_available_regs[TCG_TYPE_I64] = ALL_64;
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_G1) |
(1 << TCG_REG_G2) |
(1 << TCG_REG_G3) |
(1 << TCG_REG_G4) |
(1 << TCG_REG_G5) |
(1 << TCG_REG_G6) |
(1 << TCG_REG_G7) |
(1 << TCG_REG_O0) |
(1 << TCG_REG_O1) |
(1 << TCG_REG_O2) |
(1 << TCG_REG_O3) |
(1 << TCG_REG_O4) |
(1 << TCG_REG_O5) |
(1 << TCG_REG_O7));
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G2);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G3);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G4);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G5);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G6);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G7);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O0);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O1);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O2);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O3);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O4);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O5);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O6);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O7);
tcg_regset_clear(s->reserved_regs);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */

242
tcg/tcg.c
View File

@ -749,6 +749,229 @@ int tcg_check_temp_count(void)
}
#endif
/* Return true if OP may appear in the opcode stream.
Test the runtime variable that controls each opcode. */
bool tcg_op_supported(TCGOpcode op)
{
switch (op) {
case INDEX_op_discard:
case INDEX_op_set_label:
case INDEX_op_call:
case INDEX_op_br:
case INDEX_op_mb:
case INDEX_op_insn_start:
case INDEX_op_exit_tb:
case INDEX_op_goto_tb:
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_st_i32:
case INDEX_op_qemu_ld_i64:
case INDEX_op_qemu_st_i64:
return true;
case INDEX_op_goto_ptr:
return TCG_TARGET_HAS_goto_ptr;
case INDEX_op_mov_i32:
case INDEX_op_movi_i32:
case INDEX_op_setcond_i32:
case INDEX_op_brcond_i32:
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
case INDEX_op_add_i32:
case INDEX_op_sub_i32:
case INDEX_op_mul_i32:
case INDEX_op_and_i32:
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
return true;
case INDEX_op_movcond_i32:
return TCG_TARGET_HAS_movcond_i32;
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
return TCG_TARGET_HAS_div_i32;
case INDEX_op_rem_i32:
case INDEX_op_remu_i32:
return TCG_TARGET_HAS_rem_i32;
case INDEX_op_div2_i32:
case INDEX_op_divu2_i32:
return TCG_TARGET_HAS_div2_i32;
case INDEX_op_rotl_i32:
case INDEX_op_rotr_i32:
return TCG_TARGET_HAS_rot_i32;
case INDEX_op_deposit_i32:
return TCG_TARGET_HAS_deposit_i32;
case INDEX_op_extract_i32:
return TCG_TARGET_HAS_extract_i32;
case INDEX_op_sextract_i32:
return TCG_TARGET_HAS_sextract_i32;
case INDEX_op_add2_i32:
return TCG_TARGET_HAS_add2_i32;
case INDEX_op_sub2_i32:
return TCG_TARGET_HAS_sub2_i32;
case INDEX_op_mulu2_i32:
return TCG_TARGET_HAS_mulu2_i32;
case INDEX_op_muls2_i32:
return TCG_TARGET_HAS_muls2_i32;
case INDEX_op_muluh_i32:
return TCG_TARGET_HAS_muluh_i32;
case INDEX_op_mulsh_i32:
return TCG_TARGET_HAS_mulsh_i32;
case INDEX_op_ext8s_i32:
return TCG_TARGET_HAS_ext8s_i32;
case INDEX_op_ext16s_i32:
return TCG_TARGET_HAS_ext16s_i32;
case INDEX_op_ext8u_i32:
return TCG_TARGET_HAS_ext8u_i32;
case INDEX_op_ext16u_i32:
return TCG_TARGET_HAS_ext16u_i32;
case INDEX_op_bswap16_i32:
return TCG_TARGET_HAS_bswap16_i32;
case INDEX_op_bswap32_i32:
return TCG_TARGET_HAS_bswap32_i32;
case INDEX_op_not_i32:
return TCG_TARGET_HAS_not_i32;
case INDEX_op_neg_i32:
return TCG_TARGET_HAS_neg_i32;
case INDEX_op_andc_i32:
return TCG_TARGET_HAS_andc_i32;
case INDEX_op_orc_i32:
return TCG_TARGET_HAS_orc_i32;
case INDEX_op_eqv_i32:
return TCG_TARGET_HAS_eqv_i32;
case INDEX_op_nand_i32:
return TCG_TARGET_HAS_nand_i32;
case INDEX_op_nor_i32:
return TCG_TARGET_HAS_nor_i32;
case INDEX_op_clz_i32:
return TCG_TARGET_HAS_clz_i32;
case INDEX_op_ctz_i32:
return TCG_TARGET_HAS_ctz_i32;
case INDEX_op_ctpop_i32:
return TCG_TARGET_HAS_ctpop_i32;
case INDEX_op_brcond2_i32:
case INDEX_op_setcond2_i32:
return TCG_TARGET_REG_BITS == 32;
case INDEX_op_mov_i64:
case INDEX_op_movi_i64:
case INDEX_op_setcond_i64:
case INDEX_op_brcond_i64:
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
case INDEX_op_ld16u_i64:
case INDEX_op_ld16s_i64:
case INDEX_op_ld32u_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld_i64:
case INDEX_op_st8_i64:
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
case INDEX_op_add_i64:
case INDEX_op_sub_i64:
case INDEX_op_mul_i64:
case INDEX_op_and_i64:
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64:
return TCG_TARGET_REG_BITS == 64;
case INDEX_op_movcond_i64:
return TCG_TARGET_HAS_movcond_i64;
case INDEX_op_div_i64:
case INDEX_op_divu_i64:
return TCG_TARGET_HAS_div_i64;
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
return TCG_TARGET_HAS_rem_i64;
case INDEX_op_div2_i64:
case INDEX_op_divu2_i64:
return TCG_TARGET_HAS_div2_i64;
case INDEX_op_rotl_i64:
case INDEX_op_rotr_i64:
return TCG_TARGET_HAS_rot_i64;
case INDEX_op_deposit_i64:
return TCG_TARGET_HAS_deposit_i64;
case INDEX_op_extract_i64:
return TCG_TARGET_HAS_extract_i64;
case INDEX_op_sextract_i64:
return TCG_TARGET_HAS_sextract_i64;
case INDEX_op_extrl_i64_i32:
return TCG_TARGET_HAS_extrl_i64_i32;
case INDEX_op_extrh_i64_i32:
return TCG_TARGET_HAS_extrh_i64_i32;
case INDEX_op_ext8s_i64:
return TCG_TARGET_HAS_ext8s_i64;
case INDEX_op_ext16s_i64:
return TCG_TARGET_HAS_ext16s_i64;
case INDEX_op_ext32s_i64:
return TCG_TARGET_HAS_ext32s_i64;
case INDEX_op_ext8u_i64:
return TCG_TARGET_HAS_ext8u_i64;
case INDEX_op_ext16u_i64:
return TCG_TARGET_HAS_ext16u_i64;
case INDEX_op_ext32u_i64:
return TCG_TARGET_HAS_ext32u_i64;
case INDEX_op_bswap16_i64:
return TCG_TARGET_HAS_bswap16_i64;
case INDEX_op_bswap32_i64:
return TCG_TARGET_HAS_bswap32_i64;
case INDEX_op_bswap64_i64:
return TCG_TARGET_HAS_bswap64_i64;
case INDEX_op_not_i64:
return TCG_TARGET_HAS_not_i64;
case INDEX_op_neg_i64:
return TCG_TARGET_HAS_neg_i64;
case INDEX_op_andc_i64:
return TCG_TARGET_HAS_andc_i64;
case INDEX_op_orc_i64:
return TCG_TARGET_HAS_orc_i64;
case INDEX_op_eqv_i64:
return TCG_TARGET_HAS_eqv_i64;
case INDEX_op_nand_i64:
return TCG_TARGET_HAS_nand_i64;
case INDEX_op_nor_i64:
return TCG_TARGET_HAS_nor_i64;
case INDEX_op_clz_i64:
return TCG_TARGET_HAS_clz_i64;
case INDEX_op_ctz_i64:
return TCG_TARGET_HAS_ctz_i64;
case INDEX_op_ctpop_i64:
return TCG_TARGET_HAS_ctpop_i64;
case INDEX_op_add2_i64:
return TCG_TARGET_HAS_add2_i64;
case INDEX_op_sub2_i64:
return TCG_TARGET_HAS_sub2_i64;
case INDEX_op_mulu2_i64:
return TCG_TARGET_HAS_mulu2_i64;
case INDEX_op_muls2_i64:
return TCG_TARGET_HAS_muls2_i64;
case INDEX_op_muluh_i64:
return TCG_TARGET_HAS_muluh_i64;
case INDEX_op_mulsh_i64:
return TCG_TARGET_HAS_mulsh_i64;
case NB_OPS:
break;
}
g_assert_not_reached();
}
/* Note: we convert the 64 bit args to 32 bit and do some alignment
and endian swap. Maybe it would be better to do the alignment
and endian swap in tcg_reg_alloc_call(). */
@ -1277,7 +1500,7 @@ static void process_op_defs(TCGContext *s)
/* Incomplete TCGTargetOpDef entry. */
tcg_debug_assert(ct_str != NULL);
tcg_regset_clear(def->args_ct[i].u.regs);
def->args_ct[i].u.regs = 0;
def->args_ct[i].ct = 0;
while (*ct_str != '\0') {
switch(*ct_str) {
@ -1993,7 +2216,7 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
TCGReg reg;
TCGRegSet reg_ct;
tcg_regset_andnot(reg_ct, desired_regs, allocated_regs);
reg_ct = desired_regs & ~allocated_regs;
order = rev ? indirect_reg_alloc_order : tcg_target_reg_alloc_order;
/* first try free registers */
@ -2139,7 +2362,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
TCGTemp *ts, *ots;
TCGType otype, itype;
tcg_regset_set(allocated_regs, s->reserved_regs);
allocated_regs = s->reserved_regs;
ots = &s->temps[args[0]];
ts = &s->temps[args[1]];
@ -2227,8 +2450,8 @@ static void tcg_reg_alloc_op(TCGContext *s,
args + nb_oargs + nb_iargs,
sizeof(TCGArg) * def->nb_cargs);
tcg_regset_set(i_allocated_regs, s->reserved_regs);
tcg_regset_set(o_allocated_regs, s->reserved_regs);
i_allocated_regs = s->reserved_regs;
o_allocated_regs = s->reserved_regs;
/* satisfy input constraints */
for(k = 0; k < nb_iargs; k++) {
@ -2428,7 +2651,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
}
/* assign input registers */
tcg_regset_set(allocated_regs, s->reserved_regs);
allocated_regs = s->reserved_regs;
for(i = 0; i < nb_regs; i++) {
arg = args[nb_oargs + i];
if (arg != TCG_CALL_DUMMY_ARG) {
@ -2441,9 +2664,8 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
tcg_out_mov(s, ts->type, reg, ts->reg);
}
} else {
TCGRegSet arg_set;
TCGRegSet arg_set = 0;
tcg_regset_clear(arg_set);
tcg_regset_set_reg(arg_set, reg);
temp_load(s, ts, arg_set, allocated_regs);
}
@ -2673,9 +2895,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
break;
default:
/* Sanity check that we've not introduced any unhandled opcodes. */
if (def->flags & TCG_OPF_NOT_PRESENT) {
tcg_abort();
}
tcg_debug_assert(tcg_op_supported(opc));
/* Note: in order to speed up the code, it would be much
faster to have specialized register allocator functions for
some common argument patterns */

View File

@ -186,16 +186,9 @@ typedef enum TCGOpcode {
NB_OPS,
} TCGOpcode;
#define tcg_regset_clear(d) (d) = 0
#define tcg_regset_set(d, s) (d) = (s)
#define tcg_regset_set32(d, reg, val32) (d) |= (val32) << (reg)
#define tcg_regset_set_reg(d, r) (d) |= 1L << (r)
#define tcg_regset_reset_reg(d, r) (d) &= ~(1L << (r))
#define tcg_regset_test_reg(d, r) (((d) >> (r)) & 1)
#define tcg_regset_or(d, a, b) (d) = (a) | (b)
#define tcg_regset_and(d, a, b) (d) = (a) & (b)
#define tcg_regset_andnot(d, a, b) (d) = (a) & ~(b)
#define tcg_regset_not(d, a) (d) = ~(a)
#define tcg_regset_set_reg(d, r) ((d) |= (TCGRegSet)1 << (r))
#define tcg_regset_reset_reg(d, r) ((d) &= ~((TCGRegSet)1 << (r)))
#define tcg_regset_test_reg(d, r) (((d) >> (r)) & 1)
#ifndef TCG_TARGET_INSN_UNIT_SIZE
# error "Missing TCG_TARGET_INSN_UNIT_SIZE"
@ -932,6 +925,8 @@ do {\
#define tcg_temp_free_ptr(T) tcg_temp_free_i64(TCGV_PTR_TO_NAT(T))
#endif
bool tcg_op_supported(TCGOpcode op);
void tcg_gen_callN(TCGContext *s, void *func,
TCGArg ret, int nargs, TCGArg *args);

View File

@ -390,7 +390,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
case 'L': /* qemu_ld constraint */
case 'S': /* qemu_st constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set32(ct->u.regs, 0, BIT(TCG_TARGET_NB_REGS) - 1);
ct->u.regs = BIT(TCG_TARGET_NB_REGS) - 1;
break;
default:
return NULL;
@ -870,16 +870,13 @@ static void tcg_target_init(TCGContext *s)
tcg_debug_assert(tcg_op_defs_max <= UINT8_MAX);
/* Registers available for 32 bit operations. */
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
BIT(TCG_TARGET_NB_REGS) - 1);
tcg_target_available_regs[TCG_TYPE_I32] = BIT(TCG_TARGET_NB_REGS) - 1;
/* Registers available for 64 bit operations. */
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0,
BIT(TCG_TARGET_NB_REGS) - 1);
tcg_target_available_regs[TCG_TYPE_I64] = BIT(TCG_TARGET_NB_REGS) - 1;
/* TODO: Which registers should be set here? */
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
BIT(TCG_TARGET_NB_REGS) - 1);
tcg_target_call_clobber_regs = BIT(TCG_TARGET_NB_REGS) - 1;
tcg_regset_clear(s->reserved_regs);
s->reserved_regs = 0;
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
/* We use negative offsets from "sp" so that we can distinguish