Commit 4f2058de authored by Peter Maydell's avatar Peter Maydell

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: 's avatarPeter Maydell <peter.maydell@linaro.org>
parents 5ee53d15 89b2e37e
......@@ -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
......
......@@ -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
......
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
......@@ -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 */
......@@ -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 */
This diff is collapsed.
......@@ -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" } },
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
static const TCGTargetOpDef s_s = { .args_ct_str = { "s", "s" } };
static const TCGTargetOpDef 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" } };
switch (op) {
case INDEX_op_goto_ptr:
return &r;
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_extract_i32, { "r", "r" } },
{ INDEX_op_sextract_i32, { "r", "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;
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "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;
{ INDEX_op_mb, { } },
{ -1 },
};
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;
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(arm_op_defs);
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;
for (i = 0; i < n; ++i) {
if (arm_op_defs[i].op == op) {
return &arm_op_defs[i];
}
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_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);
tcg_regset_clear(s->reserved_regs);
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);
......
......@@ -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);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -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);
......
This diff is collapsed.
......@@ -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;