aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-02-03 19:35:57 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-02-03 19:35:57 +0000
commitdb754f8ccaf2f073c9aed46a4389e9c0c2080399 (patch)
tree8a802661a24877e2252058e92048cdbeaa7d4380
parent1ed9228f63ea4bcc0ae240365305ee264e9189ce (diff)
parent0c823e596877a30fd6c17a1ae9f98218a53055ea (diff)
downloadqemu-db754f8ccaf2f073c9aed46a4389e9c0c2080399.zip
qemu-db754f8ccaf2f073c9aed46a4389e9c0c2080399.tar.gz
qemu-db754f8ccaf2f073c9aed46a4389e9c0c2080399.tar.bz2
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210202' into staging
TCG backend constraints cleanup # gpg: Signature made Tue 02 Feb 2021 22:59:19 GMT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth-gitlab/tags/pull-tcg-20210202: (24 commits) tcg: Remove TCG_TARGET_CON_SET_H tcg/tci: Split out constraint sets to tcg-target-con-set.h tcg/sparc: Split out constraint sets to tcg-target-con-set.h tcg/s390: Split out constraint sets to tcg-target-con-set.h tcg/riscv: Split out constraint sets to tcg-target-con-set.h tcg/ppc: Split out constraint sets to tcg-target-con-set.h tcg/mips: Split out constraint sets to tcg-target-con-set.h tcg/arm: Split out constraint sets to tcg-target-con-set.h tcg/aarch64: Split out constraint sets to tcg-target-con-set.h tcg/i386: Split out constraint sets to tcg-target-con-set.h tcg: Remove TCG_TARGET_CON_STR_H tcg/sparc: Split out target constraints to tcg-target-con-str.h tcg/s390: Split out target constraints to tcg-target-con-str.h tcg/riscv: Split out target constraints to tcg-target-con-str.h tcg/mips: Split out target constraints to tcg-target-con-str.h tcg/tci: Split out target constraints to tcg-target-con-str.h tcg/ppc: Split out target constraints to tcg-target-con-str.h tcg/aarch64: Split out target constraints to tcg-target-con-str.h tcg/arm: Split out target constraints to tcg-target-con-str.h tcg/i386: Split out target constraints to tcg-target-con-str.h ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--tcg/aarch64/tcg-target-con-set.h36
-rw-r--r--tcg/aarch64/tcg-target-con-str.h24
-rw-r--r--tcg/aarch64/tcg-target.c.inc139
-rw-r--r--tcg/arm/tcg-target-con-set.h35
-rw-r--r--tcg/arm/tcg-target-con-str.h22
-rw-r--r--tcg/arm/tcg-target.c.inc170
-rw-r--r--tcg/i386/tcg-target-con-set.h55
-rw-r--r--tcg/i386/tcg-target-con-str.h33
-rw-r--r--tcg/i386/tcg-target.c.inc319
-rw-r--r--tcg/mips/tcg-target-con-set.h36
-rw-r--r--tcg/mips/tcg-target-con-str.h24
-rw-r--r--tcg/mips/tcg-target.c.inc175
-rw-r--r--tcg/ppc/tcg-target-con-set.h42
-rw-r--r--tcg/ppc/tcg-target-con-str.h30
-rw-r--r--tcg/ppc/tcg-target.c.inc211
-rw-r--r--tcg/riscv/tcg-target-con-set.h30
-rw-r--r--tcg/riscv/tcg-target-con-str.h21
-rw-r--r--tcg/riscv/tcg-target.c.inc135
-rw-r--r--tcg/s390/tcg-target-con-set.h29
-rw-r--r--tcg/s390/tcg-target-con-str.h28
-rw-r--r--tcg/s390/tcg-target.c.inc174
-rw-r--r--tcg/sparc/tcg-target-con-set.h32
-rw-r--r--tcg/sparc/tcg-target-con-str.h23
-rw-r--r--tcg/sparc/tcg-target.c.inc154
-rw-r--r--tcg/sparc/tcg-target.h4
-rw-r--r--tcg/tcg.c136
-rw-r--r--tcg/tci/tcg-target-con-set.h25
-rw-r--r--tcg/tci/tcg-target-con-str.h11
-rw-r--r--tcg/tci/tcg-target.c.inc363
29 files changed, 1250 insertions, 1266 deletions
diff --git a/tcg/aarch64/tcg-target-con-set.h b/tcg/aarch64/tcg-target-con-set.h
new file mode 100644
index 0000000..d6c6866
--- /dev/null
+++ b/tcg/aarch64/tcg-target-con-set.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Define AArch64 target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(lZ, l)
+C_O0_I2(r, rA)
+C_O0_I2(rZ, r)
+C_O0_I2(w, r)
+C_O1_I1(r, l)
+C_O1_I1(r, r)
+C_O1_I1(w, r)
+C_O1_I1(w, w)
+C_O1_I1(w, wr)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, rA)
+C_O1_I2(r, r, rAL)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rL)
+C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, 0, w)
+C_O1_I2(w, w, w)
+C_O1_I2(w, w, wN)
+C_O1_I2(w, w, wO)
+C_O1_I2(w, w, wZ)
+C_O1_I3(w, w, w, w)
+C_O1_I4(r, r, rA, rZ, rZ)
+C_O2_I4(r, r, rZ, rZ, rA, rMZ)
diff --git a/tcg/aarch64/tcg-target-con-str.h b/tcg/aarch64/tcg-target-con-str.h
new file mode 100644
index 0000000..00adb64
--- /dev/null
+++ b/tcg/aarch64/tcg-target-con-str.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Define AArch64 target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('l', ALL_QLDST_REGS)
+REGS('w', ALL_VECTOR_REGS)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('A', TCG_CT_CONST_AIMM)
+CONST('L', TCG_CT_CONST_LIMM)
+CONST('M', TCG_CT_CONST_MONE)
+CONST('O', TCG_CT_CONST_ORRI)
+CONST('N', TCG_CT_CONST_ANDI)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 23954ec..3c1ee39 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -126,51 +126,16 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
#define TCG_CT_CONST_ORRI 0x1000
#define TCG_CT_CONST_ANDI 0x2000
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'r': /* general registers */
- ct->regs |= 0xffffffffu;
- break;
- case 'w': /* advsimd registers */
- ct->regs |= 0xffffffff00000000ull;
- break;
- case 'l': /* qemu_ld / qemu_st address, data_reg */
- ct->regs = 0xffffffffu;
+#define ALL_GENERAL_REGS 0xffffffffu
+#define ALL_VECTOR_REGS 0xffffffff00000000ull
+
#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. */
- tcg_regset_reset_reg(ct->regs, TCG_REG_X0);
- tcg_regset_reset_reg(ct->regs, TCG_REG_X1);
- tcg_regset_reset_reg(ct->regs, TCG_REG_X2);
- tcg_regset_reset_reg(ct->regs, TCG_REG_X3);
+#define ALL_QLDST_REGS \
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_X0) | (1 << TCG_REG_X1) | \
+ (1 << TCG_REG_X2) | (1 << TCG_REG_X3)))
+#else
+#define ALL_QLDST_REGS ALL_GENERAL_REGS
#endif
- break;
- case 'A': /* Valid for arithmetic immediate (positive or negative). */
- ct->ct |= TCG_CT_CONST_AIMM;
- break;
- case 'L': /* Valid for logical immediate. */
- ct->ct |= TCG_CT_CONST_LIMM;
- break;
- case 'M': /* minus one */
- ct->ct |= TCG_CT_CONST_MONE;
- break;
- case 'O': /* vector orr/bic immediate */
- ct->ct |= TCG_CT_CONST_ORRI;
- break;
- case 'N': /* vector orr/bic immediate, inverted */
- ct->ct |= TCG_CT_CONST_ANDI;
- break;
- case 'Z': /* zero */
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
/* Match a constant valid for addition (12-bit, optionally shifted). */
static inline bool is_aimm(uint64_t val)
@@ -2582,42 +2547,11 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
va_end(va);
}
-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 w_w = { .args_ct_str = { "w", "w" } };
- static const TCGTargetOpDef w_r = { .args_ct_str = { "w", "r" } };
- static const TCGTargetOpDef w_wr = { .args_ct_str = { "w", "wr" } };
- 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 w_w_w = { .args_ct_str = { "w", "w", "w" } };
- static const TCGTargetOpDef w_0_w = { .args_ct_str = { "w", "0", "w" } };
- static const TCGTargetOpDef w_w_wO = { .args_ct_str = { "w", "w", "wO" } };
- static const TCGTargetOpDef w_w_wN = { .args_ct_str = { "w", "w", "wN" } };
- static const TCGTargetOpDef w_w_wZ = { .args_ct_str = { "w", "w", "wZ" } };
- 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 ext2
- = { .args_ct_str = { "r", "rZ", "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" } };
- static const TCGTargetOpDef w_w_w_w
- = { .args_ct_str = { "w", "w", "w", "w" } };
-
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(r);
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
@@ -2656,7 +2590,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_extract_i64:
case INDEX_op_sextract_i32:
case INDEX_op_sextract_i64:
- return &r_r;
+ return C_O1_I1(r, r);
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
@@ -2665,7 +2599,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
- return &rZ_r;
+ return C_O0_I2(rZ, r);
case INDEX_op_add_i32:
case INDEX_op_add_i64:
@@ -2673,7 +2607,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_sub_i64:
case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64:
- return &r_r_rA;
+ return C_O1_I2(r, r, rA);
case INDEX_op_mul_i32:
case INDEX_op_mul_i64:
@@ -2687,7 +2621,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_remu_i64:
case INDEX_op_muluh_i64:
case INDEX_op_mulsh_i64:
- return &r_r_r;
+ return C_O1_I2(r, r, r);
case INDEX_op_and_i32:
case INDEX_op_and_i64:
@@ -2701,7 +2635,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_orc_i64:
case INDEX_op_eqv_i32:
case INDEX_op_eqv_i64:
- return &r_r_rL;
+ return C_O1_I2(r, r, rL);
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
@@ -2713,42 +2647,42 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_sar_i64:
case INDEX_op_rotl_i64:
case INDEX_op_rotr_i64:
- return &r_r_ri;
+ return C_O1_I2(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;
+ return C_O1_I2(r, r, rAL);
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return &r_rA;
+ return C_O0_I2(r, rA);
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
- return &movc;
+ return C_O1_I4(r, r, rA, rZ, rZ);
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_ld_i64:
- return &r_l;
+ return C_O1_I1(r, l);
case INDEX_op_qemu_st_i32:
case INDEX_op_qemu_st_i64:
- return &lZ_l;
+ return C_O0_I2(lZ, l);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
- return &dep;
+ return C_O1_I2(r, 0, rZ);
case INDEX_op_extract2_i32:
case INDEX_op_extract2_i64:
- return &ext2;
+ return C_O1_I2(r, rZ, rZ);
case INDEX_op_add2_i32:
case INDEX_op_add2_i64:
case INDEX_op_sub2_i32:
case INDEX_op_sub2_i64:
- return &add2;
+ return C_O2_I4(r, r, rZ, rZ, rA, rMZ);
case INDEX_op_add_vec:
case INDEX_op_sub_vec:
@@ -2766,35 +2700,36 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_shrv_vec:
case INDEX_op_sarv_vec:
case INDEX_op_aa64_sshl_vec:
- return &w_w_w;
+ return C_O1_I2(w, w, w);
case INDEX_op_not_vec:
case INDEX_op_neg_vec:
case INDEX_op_abs_vec:
case INDEX_op_shli_vec:
case INDEX_op_shri_vec:
case INDEX_op_sari_vec:
- return &w_w;
+ return C_O1_I1(w, w);
case INDEX_op_ld_vec:
- case INDEX_op_st_vec:
case INDEX_op_dupm_vec:
- return &w_r;
+ return C_O1_I1(w, r);
+ case INDEX_op_st_vec:
+ return C_O0_I2(w, r);
case INDEX_op_dup_vec:
- return &w_wr;
+ return C_O1_I1(w, wr);
case INDEX_op_or_vec:
case INDEX_op_andc_vec:
- return &w_w_wO;
+ return C_O1_I2(w, w, wO);
case INDEX_op_and_vec:
case INDEX_op_orc_vec:
- return &w_w_wN;
+ return C_O1_I2(w, w, wN);
case INDEX_op_cmp_vec:
- return &w_w_wZ;
+ return C_O1_I2(w, w, wZ);
case INDEX_op_bitsel_vec:
- return &w_w_w_w;
+ return C_O1_I3(w, w, w, w);
case INDEX_op_aa64_sli_vec:
- return &w_0_w;
+ return C_O1_I2(w, 0, w);
default:
- return NULL;
+ g_assert_not_reached();
}
}
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
new file mode 100644
index 0000000..ab63e08
--- /dev/null
+++ b/tcg/arm/tcg-target-con-set.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define Arm target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(r, r)
+C_O0_I2(r, rIN)
+C_O0_I2(s, s)
+C_O0_I3(s, s, s)
+C_O0_I4(r, r, rI, rI)
+C_O0_I4(s, s, s, s)
+C_O1_I1(r, l)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, l, l)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rIK)
+C_O1_I2(r, r, rIN)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, r, r, rI, rI)
+C_O1_I4(r, r, rIN, rIK, 0)
+C_O2_I1(r, r, l)
+C_O2_I2(r, r, l, l)
+C_O2_I2(r, r, r, r)
+C_O2_I4(r, r, r, r, rIN, rIK)
+C_O2_I4(r, r, rI, rI, rIN, rIK)
diff --git a/tcg/arm/tcg-target-con-str.h b/tcg/arm/tcg-target-con-str.h
new file mode 100644
index 0000000..a0ab774
--- /dev/null
+++ b/tcg/arm/tcg-target-con-str.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define Arm target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('l', ALL_QLOAD_REGS)
+REGS('s', ALL_QSTORE_REGS)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('I', TCG_CT_CONST_ARM)
+CONST('K', TCG_CT_CONST_INV)
+CONST('N', TCG_CT_CONST_NEG)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index c2b26b3..8457108 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -237,65 +237,27 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
#define TCG_CT_CONST_NEG 0x400
#define TCG_CT_CONST_ZERO 0x800
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'I':
- ct->ct |= TCG_CT_CONST_ARM;
- break;
- case 'K':
- ct->ct |= TCG_CT_CONST_INV;
- break;
- case 'N': /* The gcc constraint letter is L, already used here. */
- ct->ct |= TCG_CT_CONST_NEG;
- break;
- case 'Z':
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
+#define ALL_GENERAL_REGS 0xffffu
- case 'r':
- ct->regs = 0xffff;
- break;
-
- /* qemu_ld address */
- case 'l':
- ct->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.
+ * r3 is removed for softmmu to avoid clashes with helper arguments.
+ */
#ifdef CONFIG_SOFTMMU
- /* r0-r2,lr will be overwritten when reading the tlb entry,
- so don't use these. */
- tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
-#endif
- break;
-
- /* qemu_st address & data */
- case 's':
- ct->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->regs, TCG_REG_R0);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
-#if defined(CONFIG_SOFTMMU)
- /* Avoid clashes with registers being used for helper args */
- tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
-#if TARGET_LONG_BITS == 64
- /* Avoid clashes with registers being used for helper args */
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
-#endif
- tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
+#define ALL_QLOAD_REGS \
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1) | \
+ (1 << TCG_REG_R2) | (1 << TCG_REG_R3) | \
+ (1 << TCG_REG_R14)))
+#define ALL_QSTORE_REGS \
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1) | \
+ (1 << TCG_REG_R2) | (1 << TCG_REG_R14) | \
+ ((TARGET_LONG_BITS == 64) << TCG_REG_R3)))
+#else
+#define ALL_QLOAD_REGS ALL_GENERAL_REGS
+#define ALL_QSTORE_REGS \
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1)))
#endif
- break;
-
- default:
- return NULL;
- }
- return ct_str;
-}
static inline uint32_t rotl(uint32_t val, int n)
{
@@ -2074,57 +2036,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
-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 ext2
- = { .args_ct_str = { "r", "rZ", "rZ" } };
- 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", "rI", "rI" } };
- static const TCGTargetOpDef setc2
- = { .args_ct_str = { "r", "r", "r", "rI", "rI" } };
-
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(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:
@@ -2134,62 +2056,72 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_ext16u_i32:
case INDEX_op_extract_i32:
case INDEX_op_sextract_i32:
- return &r_r;
+ return C_O1_I1(r, r);
+
+ case INDEX_op_st8_i32:
+ case INDEX_op_st16_i32:
+ case INDEX_op_st_i32:
+ return C_O0_I2(r, r);
case INDEX_op_add_i32:
case INDEX_op_sub_i32:
case INDEX_op_setcond_i32:
- return &r_r_rIN;
+ return C_O1_I2(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;
+ return C_O1_I2(r, r, rIK);
+
case INDEX_op_mul_i32:
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
- return &r_r_r;
+ return C_O1_I2(r, r, r);
+
case INDEX_op_mulu2_i32:
case INDEX_op_muls2_i32:
- return &r_r_r_r;
+ return C_O2_I2(r, r, r, r);
+
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
- return &r_r_rI;
+ return C_O1_I2(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;
+ return C_O1_I2(r, r, ri);
case INDEX_op_brcond_i32:
- return &br;
+ return C_O0_I2(r, rIN);
case INDEX_op_deposit_i32:
- return &dep;
+ return C_O1_I2(r, 0, rZ);
case INDEX_op_extract2_i32:
- return &ext2;
+ return C_O1_I2(r, rZ, rZ);
case INDEX_op_movcond_i32:
- return &movc;
+ return C_O1_I4(r, r, rIN, rIK, 0);
case INDEX_op_add2_i32:
- return &add2;
+ return C_O2_I4(r, r, r, r, rIN, rIK);
case INDEX_op_sub2_i32:
- return &sub2;
+ return C_O2_I4(r, r, rI, rI, rIN, rIK);
case INDEX_op_brcond2_i32:
- return &br2;
+ return C_O0_I4(r, r, rI, rI);
case INDEX_op_setcond2_i32:
- return &setc2;
+ return C_O1_I4(r, r, r, rI, rI);
case INDEX_op_qemu_ld_i32:
- return TARGET_LONG_BITS == 32 ? &r_l : &r_l_l;
+ return TARGET_LONG_BITS == 32 ? C_O1_I1(r, l) : C_O1_I2(r, l, l);
case INDEX_op_qemu_ld_i64:
- return TARGET_LONG_BITS == 32 ? &r_r_l : &r_r_l_l;
+ return TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, l) : C_O2_I2(r, r, l, l);
case INDEX_op_qemu_st_i32:
- return TARGET_LONG_BITS == 32 ? &s_s : &s_s_s;
+ return TARGET_LONG_BITS == 32 ? C_O0_I2(s, s) : C_O0_I3(s, s, s);
case INDEX_op_qemu_st_i64:
- return TARGET_LONG_BITS == 32 ? &s_s_s : &s_s_s_s;
+ return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s);
default:
- return NULL;
+ g_assert_not_reached();
}
}
diff --git a/tcg/i386/tcg-target-con-set.h b/tcg/i386/tcg-target-con-set.h
new file mode 100644
index 0000000..78774d1
--- /dev/null
+++ b/tcg/i386/tcg-target-con-set.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define i386 target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ *
+ * C_N1_Im(...) defines a constraint set with 1 output and <m> inputs,
+ * except that the output must use a new register.
+ */
+C_O0_I1(r)
+C_O0_I2(L, L)
+C_O0_I2(qi, r)
+C_O0_I2(re, r)
+C_O0_I2(ri, r)
+C_O0_I2(r, re)
+C_O0_I2(s, L)
+C_O0_I2(x, r)
+C_O0_I3(L, L, L)
+C_O0_I3(s, L, L)
+C_O0_I4(L, L, L, L)
+C_O0_I4(r, r, ri, ri)
+C_O1_I1(r, 0)
+C_O1_I1(r, L)
+C_O1_I1(r, q)
+C_O1_I1(r, r)
+C_O1_I1(x, r)
+C_O1_I1(x, x)
+C_O1_I2(Q, 0, Q)
+C_O1_I2(q, r, re)
+C_O1_I2(r, 0, ci)
+C_O1_I2(r, 0, r)
+C_O1_I2(r, 0, re)
+C_O1_I2(r, 0, reZ)
+C_O1_I2(r, 0, ri)
+C_O1_I2(r, 0, rI)
+C_O1_I2(r, L, L)
+C_O1_I2(r, r, re)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(x, x, x)
+C_N1_I2(r, r, r)
+C_N1_I2(r, r, rW)
+C_O1_I3(x, x, x, x)
+C_O1_I4(r, r, re, r, 0)
+C_O1_I4(r, r, r, ri, ri)
+C_O2_I1(r, r, L)
+C_O2_I2(a, d, a, r)
+C_O2_I2(r, r, L, L)
+C_O2_I3(a, d, 0, 1, r)
+C_O2_I4(r, r, 0, 1, re, re)
diff --git a/tcg/i386/tcg-target-con-str.h b/tcg/i386/tcg-target-con-str.h
new file mode 100644
index 0000000..24e6bcb
--- /dev/null
+++ b/tcg/i386/tcg-target-con-str.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define i386 target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ *
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('a', 1u << TCG_REG_EAX)
+REGS('b', 1u << TCG_REG_EBX)
+REGS('c', 1u << TCG_REG_ECX)
+REGS('d', 1u << TCG_REG_EDX)
+REGS('S', 1u << TCG_REG_ESI)
+REGS('D', 1u << TCG_REG_EDI)
+
+REGS('r', ALL_GENERAL_REGS)
+REGS('x', ALL_VECTOR_REGS)
+REGS('q', ALL_BYTEL_REGS) /* regs that can be used as a byte operand */
+REGS('Q', ALL_BYTEH_REGS) /* regs with a second byte (e.g. %ah) */
+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_ld/st */
+REGS('s', ALL_BYTEL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_st8_i32 data */
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('e', TCG_CT_CONST_S32)
+CONST('I', TCG_CT_CONST_I32)
+CONST('W', TCG_CT_CONST_WSZ)
+CONST('Z', TCG_CT_CONST_U32)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 050f3cb..40326c2 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -132,6 +132,22 @@ static const int tcg_target_call_oarg_regs[] = {
# define TCG_REG_L1 TCG_REG_EDX
#endif
+#define ALL_BYTEH_REGS 0x0000000fu
+#if TCG_TARGET_REG_BITS == 64
+# define ALL_GENERAL_REGS 0x0000ffffu
+# define ALL_VECTOR_REGS 0xffff0000u
+# define ALL_BYTEL_REGS ALL_GENERAL_REGS
+#else
+# define ALL_GENERAL_REGS 0x000000ffu
+# define ALL_VECTOR_REGS 0x00ff0000u
+# define ALL_BYTEL_REGS ALL_BYTEH_REGS
+#endif
+#ifdef CONFIG_SOFTMMU
+# define SOFTMMU_RESERVE_REGS ((1 << TCG_REG_L0) | (1 << TCG_REG_L1))
+#else
+# define SOFTMMU_RESERVE_REGS 0
+#endif
+
/* The host compiler should supply <cpuid.h> to enable runtime features
detection, as we're not going to go so far as our own inline assembly.
If not available, default values will be assumed. */
@@ -193,91 +209,6 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
return true;
}
-#if TCG_TARGET_REG_BITS == 64
-#define ALL_GENERAL_REGS 0x0000ffffu
-#define ALL_VECTOR_REGS 0xffff0000u
-#else
-#define ALL_GENERAL_REGS 0x000000ffu
-#define ALL_VECTOR_REGS 0x00ff0000u
-#endif
-
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch(*ct_str++) {
- case 'a':
- tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
- break;
- case 'b':
- tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
- break;
- case 'c':
- tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
- break;
- case 'd':
- tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
- break;
- case 'S':
- tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
- break;
- case 'D':
- tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
- break;
- case 'q':
- /* A register that can be used as a byte operand. */
- ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
- break;
- case 'Q':
- /* A register with an addressable second byte (e.g. %ah). */
- ct->regs = 0xf;
- break;
- case 'r':
- /* A general register. */
- ct->regs |= ALL_GENERAL_REGS;
- break;
- case 'W':
- /* With TZCNT/LZCNT, we can have operand-size as an input. */
- ct->ct |= TCG_CT_CONST_WSZ;
- break;
- case 'x':
- /* A vector register. */
- ct->regs |= ALL_VECTOR_REGS;
- break;
-
- case 'L':
- /* qemu_ld/st data+address constraint */
- ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
-#ifdef CONFIG_SOFTMMU
- tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
- tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
-#endif
- break;
- case 's':
- /* qemu_st8_i32 data constraint */
- ct->regs = 0xf;
-#ifdef CONFIG_SOFTMMU
- tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
- tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
-#endif
- break;
-
- case 'e':
- ct->ct |= (type == TCG_TYPE_I32 ? TCG_CT_CONST : TCG_CT_CONST_S32);
- break;
- case 'Z':
- ct->ct |= (type == TCG_TYPE_I32 ? TCG_CT_CONST : TCG_CT_CONST_U32);
- break;
- case 'I':
- ct->ct |= (type == TCG_TYPE_I32 ? TCG_CT_CONST : TCG_CT_CONST_I32);
- break;
-
- default:
- return NULL;
- }
- return ct_str;
-}
-
/* test if a constant matches the constraint */
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
@@ -286,14 +217,20 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
if (ct & TCG_CT_CONST) {
return 1;
}
- if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_I32) && ~val == (int32_t)~val) {
- return 1;
+ if (type == TCG_TYPE_I32) {
+ if (ct & (TCG_CT_CONST_S32 | TCG_CT_CONST_U32 | TCG_CT_CONST_I32)) {
+ return 1;
+ }
+ } else {
+ if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_I32) && ~val == (int32_t)~val) {
+ return 1;
+ }
}
if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
return 1;
@@ -2957,41 +2894,11 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
}
}
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
-{
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
- static const TCGTargetOpDef ri_r = { .args_ct_str = { "ri", "r" } };
- static const TCGTargetOpDef re_r = { .args_ct_str = { "re", "r" } };
- static const TCGTargetOpDef qi_r = { .args_ct_str = { "qi", "r" } };
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
- static const TCGTargetOpDef r_q = { .args_ct_str = { "r", "q" } };
- static const TCGTargetOpDef r_re = { .args_ct_str = { "r", "re" } };
- static const TCGTargetOpDef r_0 = { .args_ct_str = { "r", "0" } };
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
- static const TCGTargetOpDef r_r_re = { .args_ct_str = { "r", "r", "re" } };
- static const TCGTargetOpDef r_0_r = { .args_ct_str = { "r", "0", "r" } };
- static const TCGTargetOpDef r_0_re = { .args_ct_str = { "r", "0", "re" } };
- static const TCGTargetOpDef r_0_ci = { .args_ct_str = { "r", "0", "ci" } };
- static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
- static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
- static const TCGTargetOpDef s_L = { .args_ct_str = { "s", "L" } };
- static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
- static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
- static const TCGTargetOpDef L_L_L = { .args_ct_str = { "L", "L", "L" } };
- static const TCGTargetOpDef s_L_L = { .args_ct_str = { "s", "L", "L" } };
- static const TCGTargetOpDef r_r_L_L
- = { .args_ct_str = { "r", "r", "L", "L" } };
- static const TCGTargetOpDef L_L_L_L
- = { .args_ct_str = { "L", "L", "L", "L" } };
- static const TCGTargetOpDef x_x = { .args_ct_str = { "x", "x" } };
- static const TCGTargetOpDef x_x_x = { .args_ct_str = { "x", "x", "x" } };
- static const TCGTargetOpDef x_x_x_x
- = { .args_ct_str = { "x", "x", "x", "x" } };
- static const TCGTargetOpDef x_r = { .args_ct_str = { "x", "r" } };
-
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(r);
case INDEX_op_ld8u_i32:
case INDEX_op_ld8u_i64:
@@ -3005,22 +2912,25 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_ld32u_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld_i64:
- return &r_r;
+ return C_O1_I1(r, r);
case INDEX_op_st8_i32:
case INDEX_op_st8_i64:
- return &qi_r;
+ return C_O0_I2(qi, r);
+
case INDEX_op_st16_i32:
case INDEX_op_st16_i64:
case INDEX_op_st_i32:
case INDEX_op_st32_i64:
- return &ri_r;
+ return C_O0_I2(ri, r);
+
case INDEX_op_st_i64:
- return &re_r;
+ return C_O0_I2(re, r);
case INDEX_op_add_i32:
case INDEX_op_add_i64:
- return &r_r_re;
+ return C_O1_I2(r, r, re);
+
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
case INDEX_op_mul_i32:
@@ -3029,24 +2939,15 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_or_i64:
case INDEX_op_xor_i32:
case INDEX_op_xor_i64:
- return &r_0_re;
+ return C_O1_I2(r, 0, re);
case INDEX_op_and_i32:
case INDEX_op_and_i64:
- {
- static const TCGTargetOpDef and
- = { .args_ct_str = { "r", "0", "reZ" } };
- return &and;
- }
- break;
+ return C_O1_I2(r, 0, reZ);
+
case INDEX_op_andc_i32:
case INDEX_op_andc_i64:
- {
- static const TCGTargetOpDef andc
- = { .args_ct_str = { "r", "r", "rI" } };
- return &andc;
- }
- break;
+ return C_O1_I2(r, r, rI);
case INDEX_op_shl_i32:
case INDEX_op_shl_i64:
@@ -3054,16 +2955,17 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_shr_i64:
case INDEX_op_sar_i32:
case INDEX_op_sar_i64:
- return have_bmi2 ? &r_r_ri : &r_0_ci;
+ return have_bmi2 ? C_O1_I2(r, r, ri) : C_O1_I2(r, 0, ci);
+
case INDEX_op_rotl_i32:
case INDEX_op_rotl_i64:
case INDEX_op_rotr_i32:
case INDEX_op_rotr_i64:
- return &r_0_ci;
+ return C_O1_I2(r, 0, ci);
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return &r_re;
+ return C_O0_I2(r, re);
case INDEX_op_bswap16_i32:
case INDEX_op_bswap16_i64:
@@ -3075,13 +2977,14 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_not_i32:
case INDEX_op_not_i64:
case INDEX_op_extrh_i64_i32:
- return &r_0;
+ return C_O1_I1(r, 0);
case INDEX_op_ext8s_i32:
case INDEX_op_ext8s_i64:
case INDEX_op_ext8u_i32:
case INDEX_op_ext8u_i64:
- return &r_q;
+ return C_O1_I1(r, q);
+
case INDEX_op_ext16s_i32:
case INDEX_op_ext16s_i64:
case INDEX_op_ext16u_i32:
@@ -3096,110 +2999,83 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_sextract_i32:
case INDEX_op_ctpop_i32:
case INDEX_op_ctpop_i64:
- return &r_r;
+ return C_O1_I1(r, r);
+
case INDEX_op_extract2_i32:
case INDEX_op_extract2_i64:
- return &r_0_r;
+ return C_O1_I2(r, 0, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
- {
- static const TCGTargetOpDef dep
- = { .args_ct_str = { "Q", "0", "Q" } };
- return &dep;
- }
+ return C_O1_I2(Q, 0, Q);
+
case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64:
- {
- static const TCGTargetOpDef setc
- = { .args_ct_str = { "q", "r", "re" } };
- return &setc;
- }
+ return C_O1_I2(q, r, re);
+
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
- {
- static const TCGTargetOpDef movc
- = { .args_ct_str = { "r", "r", "re", "r", "0" } };
- return &movc;
- }
+ return C_O1_I4(r, r, re, r, 0);
+
case INDEX_op_div2_i32:
case INDEX_op_div2_i64:
case INDEX_op_divu2_i32:
case INDEX_op_divu2_i64:
- {
- static const TCGTargetOpDef div2
- = { .args_ct_str = { "a", "d", "0", "1", "r" } };
- return &div2;
- }
+ return C_O2_I3(a, d, 0, 1, r);
+
case INDEX_op_mulu2_i32:
case INDEX_op_mulu2_i64:
case INDEX_op_muls2_i32:
case INDEX_op_muls2_i64:
- {
- static const TCGTargetOpDef mul2
- = { .args_ct_str = { "a", "d", "a", "r" } };
- return &mul2;
- }
+ return C_O2_I2(a, d, a, r);
+
case INDEX_op_add2_i32:
case INDEX_op_add2_i64:
case INDEX_op_sub2_i32:
case INDEX_op_sub2_i64:
- {
- static const TCGTargetOpDef arith2
- = { .args_ct_str = { "r", "r", "0", "1", "re", "re" } };
- return &arith2;
- }
+ return C_O2_I4(r, r, 0, 1, re, re);
+
case INDEX_op_ctz_i32:
case INDEX_op_ctz_i64:
- {
- static const TCGTargetOpDef ctz[2] = {
- { .args_ct_str = { "&r", "r", "r" } },
- { .args_ct_str = { "&r", "r", "rW" } },
- };
- return &ctz[have_bmi1];
- }
+ return have_bmi1 ? C_N1_I2(r, r, rW) : C_N1_I2(r, r, r);
+
case INDEX_op_clz_i32:
case INDEX_op_clz_i64:
- {
- static const TCGTargetOpDef clz[2] = {
- { .args_ct_str = { "&r", "r", "r" } },
- { .args_ct_str = { "&r", "r", "rW" } },
- };
- return &clz[have_lzcnt];
- }
+ return have_lzcnt ? C_N1_I2(r, r, rW) : C_N1_I2(r, r, r);
case INDEX_op_qemu_ld_i32:
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_L : &r_L_L;
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
+
case INDEX_op_qemu_st_i32:
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &L_L : &L_L_L;
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O0_I2(L, L) : C_O0_I3(L, L, L));
case INDEX_op_qemu_st8_i32:
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &s_L : &s_L_L;
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O0_I2(s, L) : C_O0_I3(s, L, L));
+
case INDEX_op_qemu_ld_i64:
- return (TCG_TARGET_REG_BITS == 64 ? &r_L
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_r_L
- : &r_r_L_L);
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, L)
+ : C_O2_I2(r, r, L, L));
+
case INDEX_op_qemu_st_i64:
- return (TCG_TARGET_REG_BITS == 64 ? &L_L
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &L_L_L
- : &L_L_L_L);
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(L, L)
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(L, L, L)
+ : C_O0_I4(L, L, L, L));
case INDEX_op_brcond2_i32:
- {
- static const TCGTargetOpDef b2
- = { .args_ct_str = { "r", "r", "ri", "ri" } };
- return &b2;
- }
+ return C_O0_I4(r, r, ri, ri);
+
case INDEX_op_setcond2_i32:
- {
- static const TCGTargetOpDef s2
- = { .args_ct_str = { "r", "r", "r", "ri", "ri" } };
- return &s2;
- }
+ return C_O1_I4(r, r, r, ri, ri);
case INDEX_op_ld_vec:
- case INDEX_op_st_vec:
case INDEX_op_dupm_vec:
- return &x_r;
+ return C_O1_I1(x, r);
+
+ case INDEX_op_st_vec:
+ return C_O0_I2(x, r);
case INDEX_op_add_vec:
case INDEX_op_sub_vec:
@@ -3234,21 +3110,22 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
#if TCG_TARGET_REG_BITS == 32
case INDEX_op_dup2_vec:
#endif
- return &x_x_x;
+ return C_O1_I2(x, x, x);
+
case INDEX_op_abs_vec:
case INDEX_op_dup_vec:
case INDEX_op_shli_vec:
case INDEX_op_shri_vec:
case INDEX_op_sari_vec:
case INDEX_op_x86_psrldq_vec:
- return &x_x;
+ return C_O1_I1(x, x);
+
case INDEX_op_x86_vpblendvb_vec:
- return &x_x_x_x;
+ return C_O1_I3(x, x, x, x);
default:
- break;
+ g_assert_not_reached();
}
- return NULL;
}
int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
diff --git a/tcg/mips/tcg-target-con-set.h b/tcg/mips/tcg-target-con-set.h
new file mode 100644
index 0000000..fe3e868
--- /dev/null
+++ b/tcg/mips/tcg-target-con-set.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define MIPS target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(rZ, r)
+C_O0_I2(rZ, rZ)
+C_O0_I2(SZ, S)
+C_O0_I3(SZ, S, S)
+C_O0_I3(SZ, SZ, S)
+C_O0_I4(rZ, rZ, rZ, rZ)
+C_O0_I4(SZ, SZ, S, S)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, L, L)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rIK)
+C_O1_I2(r, r, rJ)
+C_O1_I2(r, r, rWZ)
+C_O1_I2(r, rZ, rN)
+C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, rZ, rZ, rZ, 0)
+C_O1_I4(r, rZ, rZ, rZ, rZ)
+C_O2_I1(r, r, L)
+C_O2_I2(r, r, L, L)
+C_O2_I2(r, r, r, r)
+C_O2_I4(r, r, rZ, rZ, rN, rN)
diff --git a/tcg/mips/tcg-target-con-str.h b/tcg/mips/tcg-target-con-str.h
new file mode 100644
index 0000000..e4b2965
--- /dev/null
+++ b/tcg/mips/tcg-target-con-str.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define MIPS target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('L', ALL_QLOAD_REGS)
+REGS('S', ALL_QSTORE_REGS)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('I', TCG_CT_CONST_U16)
+CONST('J', TCG_CT_CONST_S16)
+CONST('K', TCG_CT_CONST_P2M1)
+CONST('N', TCG_CT_CONST_N16)
+CONST('W', TCG_CT_CONST_WSZ)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 7293169..ab55f31 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -171,67 +171,27 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
#define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
#define TCG_CT_CONST_WSZ 0x2000 /* word size */
+#define ALL_GENERAL_REGS 0xffffffffu
+#define NOA0_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_A0))
+
+#ifdef CONFIG_SOFTMMU
+#define ALL_QLOAD_REGS \
+ (NOA0_REGS & ~((TCG_TARGET_REG_BITS < TARGET_LONG_BITS) << TCG_REG_A2))
+#define ALL_QSTORE_REGS \
+ (NOA0_REGS & ~(TCG_TARGET_REG_BITS < TARGET_LONG_BITS \
+ ? (1 << TCG_REG_A2) | (1 << TCG_REG_A3) \
+ : (1 << TCG_REG_A1)))
+#else
+#define ALL_QLOAD_REGS NOA0_REGS
+#define ALL_QSTORE_REGS NOA0_REGS
+#endif
+
+
static inline bool is_p2m1(tcg_target_long val)
{
return val && ((val + 1) & val) == 0;
}
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch(*ct_str++) {
- case 'r':
- ct->regs = 0xffffffff;
- break;
- case 'L': /* qemu_ld input arg constraint */
- ct->regs = 0xffffffff;
- tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
-#if defined(CONFIG_SOFTMMU)
- if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
- tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
- }
-#endif
- break;
- case 'S': /* qemu_st constraint */
- ct->regs = 0xffffffff;
- tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
-#if defined(CONFIG_SOFTMMU)
- if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
- tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
- tcg_regset_reset_reg(ct->regs, TCG_REG_A3);
- } else {
- tcg_regset_reset_reg(ct->regs, TCG_REG_A1);
- }
-#endif
- break;
- case 'I':
- ct->ct |= TCG_CT_CONST_U16;
- break;
- case 'J':
- ct->ct |= TCG_CT_CONST_S16;
- break;
- case 'K':
- ct->ct |= TCG_CT_CONST_P2M1;
- break;
- case 'N':
- ct->ct |= TCG_CT_CONST_N16;
- break;
- case 'W':
- ct->ct |= TCG_CT_CONST_WSZ;
- break;
- case 'Z':
- /* We are cheating a bit here, using the fact that the register
- ZERO is also the register number 0. Hence there is no need
- to check for const_args in each instruction. */
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
-
/* test if a constant matches the constraint */
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
@@ -1697,6 +1657,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
TCGArg a0, a1, a2;
int c2;
+ /*
+ * Note that many operands use the constraint set "rZ".
+ * We make use of the fact that 0 is the ZERO register,
+ * and hence such cases need not check for const_args.
+ */
a0 = args[0];
a1 = args[1];
a2 = args[2];
@@ -2147,52 +2112,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
-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 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" } };
-
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(r);
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
@@ -2225,7 +2149,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_extrl_i64_i32:
case INDEX_op_extrh_i64_i32:
case INDEX_op_extract_i64:
- return &r_r;
+ return C_O1_I1(r, r);
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
@@ -2234,14 +2158,14 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
- return &rZ_r;
+ return C_O0_I2(rZ, r);
case INDEX_op_add_i32:
case INDEX_op_add_i64:
- return &r_r_rJ;
+ return C_O1_I2(r, r, rJ);
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
- return &r_rZ_rN;
+ return C_O1_I2(r, rZ, rN);
case INDEX_op_mul_i32:
case INDEX_op_mulsh_i32:
case INDEX_op_muluh_i32:
@@ -2260,20 +2184,20 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_remu_i64:
case INDEX_op_nor_i64:
case INDEX_op_setcond_i64:
- return &r_rZ_rZ;
+ return C_O1_I2(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;
+ return C_O2_I2(r, r, r, r);
case INDEX_op_and_i32:
case INDEX_op_and_i64:
- return &r_r_rIK;
+ return C_O1_I2(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;
+ return C_O1_I2(r, r, rI);
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
@@ -2284,44 +2208,47 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_sar_i64:
case INDEX_op_rotr_i64:
case INDEX_op_rotl_i64:
- return &r_r_ri;
+ return C_O1_I2(r, r, ri);
case INDEX_op_clz_i32:
case INDEX_op_clz_i64:
- return &r_r_rWZ;
+ return C_O1_I2(r, r, rWZ);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
- return &dep;
+ return C_O1_I2(r, 0, rZ);
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return &rZ_rZ;
+ return C_O0_I2(rZ, rZ);
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
- return use_mips32r6_instructions ? &movc_r6 : &movc;
-
+ return (use_mips32r6_instructions
+ ? C_O1_I4(r, rZ, rZ, rZ, rZ)
+ : C_O1_I4(r, rZ, rZ, rZ, 0));
case INDEX_op_add2_i32:
case INDEX_op_sub2_i32:
- return &add2;
+ return C_O2_I4(r, r, rZ, rZ, rN, rN);
case INDEX_op_setcond2_i32:
- return &setc2;
+ return C_O1_I4(r, rZ, rZ, rZ, rZ);
case INDEX_op_brcond2_i32:
- return &br2;
+ return C_O0_I4(rZ, rZ, rZ, rZ);
case INDEX_op_qemu_ld_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
- ? &r_L : &r_L_L);
+ ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
case INDEX_op_qemu_st_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
- ? &SZ_S : &SZ_S_S);
+ ? C_O0_I2(SZ, S) : C_O0_I3(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);
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
+ : TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, L)
+ : C_O2_I2(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);
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(SZ, S)
+ : TARGET_LONG_BITS == 32 ? C_O0_I3(SZ, SZ, S)
+ : C_O0_I4(SZ, SZ, S, S));
default:
- return NULL;
+ g_assert_not_reached();
}
}
diff --git a/tcg/ppc/tcg-target-con-set.h b/tcg/ppc/tcg-target-con-set.h
new file mode 100644
index 0000000..a1a3458
--- /dev/null
+++ b/tcg/ppc/tcg-target-con-set.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define PowerPC target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(r, r)
+C_O0_I2(r, ri)
+C_O0_I2(S, S)
+C_O0_I2(v, r)
+C_O0_I3(S, S, S)
+C_O0_I4(r, r, ri, ri)
+C_O0_I4(S, S, S, S)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I1(v, r)
+C_O1_I1(v, v)
+C_O1_I1(v, vr)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, L, L)
+C_O1_I2(r, rI, ri)
+C_O1_I2(r, rI, rT)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rT)
+C_O1_I2(r, r, rU)
+C_O1_I2(r, r, rZW)
+C_O1_I2(v, v, v)
+C_O1_I3(v, v, v, v)
+C_O1_I4(r, r, ri, rZ, rZ)
+C_O1_I4(r, r, r, ri, ri)
+C_O2_I1(L, L, L)
+C_O2_I2(L, L, L, L)
+C_O2_I4(r, r, rI, rZM, r, r)
+C_O2_I4(r, r, r, r, rI, rZM)
diff --git a/tcg/ppc/tcg-target-con-str.h b/tcg/ppc/tcg-target-con-str.h
new file mode 100644
index 0000000..298ca20
--- /dev/null
+++ b/tcg/ppc/tcg-target-con-str.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define PowerPC target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('v', ALL_VECTOR_REGS)
+REGS('A', 1u << TCG_REG_R3)
+REGS('B', 1u << TCG_REG_R4)
+REGS('C', 1u << TCG_REG_R5)
+REGS('D', 1u << TCG_REG_R6)
+REGS('L', ALL_QLOAD_REGS)
+REGS('S', ALL_QSTORE_REGS)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('I', TCG_CT_CONST_S16)
+CONST('J', TCG_CT_CONST_U16)
+CONST('M', TCG_CT_CONST_MONE)
+CONST('T', TCG_CT_CONST_S32)
+CONST('U', TCG_CT_CONST_U32)
+CONST('W', TCG_CT_CONST_WSZ)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index cf64892..4377d15 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -62,6 +62,21 @@
#define TCG_CT_CONST_MONE 0x2000
#define TCG_CT_CONST_WSZ 0x4000
+#define ALL_GENERAL_REGS 0xffffffffu
+#define ALL_VECTOR_REGS 0xffffffff00000000ull
+
+#ifdef CONFIG_SOFTMMU
+#define ALL_QLOAD_REGS \
+ (ALL_GENERAL_REGS & \
+ ~((1 << TCG_REG_R3) | (1 << TCG_REG_R4) | (1 << TCG_REG_R5)))
+#define ALL_QSTORE_REGS \
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R3) | (1 << TCG_REG_R4) | \
+ (1 << TCG_REG_R5) | (1 << TCG_REG_R6)))
+#else
+#define ALL_QLOAD_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_R3))
+#define ALL_QSTORE_REGS ALL_QLOAD_REGS
+#endif
+
TCGPowerISA have_isa;
static bool have_isel;
bool have_altivec;
@@ -222,64 +237,6 @@ static bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
return false;
}
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'A': case 'B': case 'C': case 'D':
- tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
- break;
- case 'r':
- ct->regs = 0xffffffff;
- break;
- case 'v':
- ct->regs = 0xffffffff00000000ull;
- break;
- case 'L': /* qemu_ld constraint */
- ct->regs = 0xffffffff;
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
-#ifdef CONFIG_SOFTMMU
- tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
-#endif
- break;
- case 'S': /* qemu_st constraint */
- ct->regs = 0xffffffff;
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
-#ifdef CONFIG_SOFTMMU
- tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R6);
-#endif
- break;
- case 'I':
- ct->ct |= TCG_CT_CONST_S16;
- break;
- case 'J':
- ct->ct |= TCG_CT_CONST_U16;
- break;
- case 'M':
- ct->ct |= TCG_CT_CONST_MONE;
- break;
- case 'T':
- ct->ct |= TCG_CT_CONST_S32;
- break;
- case 'U':
- ct->ct |= TCG_CT_CONST_U32;
- break;
- case 'W':
- ct->ct |= TCG_CT_CONST_WSZ;
- break;
- case 'Z':
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
-
/* test if a constant matches the constraint */
static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
@@ -3499,62 +3456,17 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
va_end(va);
}
-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 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" } };
- static const TCGTargetOpDef v_r = { .args_ct_str = { "v", "r" } };
- static const TCGTargetOpDef v_vr = { .args_ct_str = { "v", "vr" } };
- static const TCGTargetOpDef v_v = { .args_ct_str = { "v", "v" } };
- static const TCGTargetOpDef v_v_v = { .args_ct_str = { "v", "v", "v" } };
- static const TCGTargetOpDef v_v_v_v
- = { .args_ct_str = { "v", "v", "v", "v" } };
-
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(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:
@@ -3570,10 +3482,6 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
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:
@@ -3586,7 +3494,16 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_bswap32_i64:
case INDEX_op_bswap64_i64:
case INDEX_op_extract_i64:
- return &r_r;
+ return C_O1_I1(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 C_O0_I2(r, r);
case INDEX_op_add_i32:
case INDEX_op_and_i32:
@@ -3609,10 +3526,12 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_rotl_i64:
case INDEX_op_rotr_i64:
case INDEX_op_setcond_i64:
- return &r_r_ri;
+ return C_O1_I2(r, r, ri);
+
case INDEX_op_mul_i32:
case INDEX_op_mul_i64:
- return &r_r_rI;
+ return C_O1_I2(r, r, rI);
+
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
case INDEX_op_nand_i32:
@@ -3627,55 +3546,63 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_divu_i64:
case INDEX_op_mulsh_i64:
case INDEX_op_muluh_i64:
- return &r_r_r;
+ return C_O1_I2(r, r, r);
+
case INDEX_op_sub_i32:
- return &r_rI_ri;
+ return C_O1_I2(r, rI, ri);
case INDEX_op_add_i64:
- return &r_r_rT;
+ return C_O1_I2(r, r, rT);
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
- return &r_r_rU;
+ return C_O1_I2(r, r, rU);
case INDEX_op_sub_i64:
- return &r_rI_rT;
+ return C_O1_I2(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;
+ return C_O1_I2(r, r, rZW);
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return &r_ri;
+ return C_O0_I2(r, ri);
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
- return &movc;
+ return C_O1_I4(r, r, ri, rZ, rZ);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
- return &dep;
+ return C_O1_I2(r, 0, rZ);
case INDEX_op_brcond2_i32:
- return &br2;
+ return C_O0_I4(r, r, ri, ri);
case INDEX_op_setcond2_i32:
- return &setc2;
+ return C_O1_I4(r, r, r, ri, ri);
case INDEX_op_add2_i64:
case INDEX_op_add2_i32:
- return &add2;
+ return C_O2_I4(r, r, r, r, rI, rZM);
case INDEX_op_sub2_i64:
case INDEX_op_sub2_i32:
- return &sub2;
+ return C_O2_I4(r, r, rI, rZM, r, r);
case INDEX_op_qemu_ld_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
- ? &r_L : &r_L_L);
+ ? C_O1_I1(r, L)
+ : C_O1_I2(r, L, L));
+
case INDEX_op_qemu_st_i32:
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
- ? &S_S : &S_S_S);
+ ? C_O0_I2(S, S)
+ : C_O0_I3(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);
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
+ : TARGET_LONG_BITS == 32 ? C_O2_I1(L, L, L)
+ : C_O2_I2(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);
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(S, S)
+ : TARGET_LONG_BITS == 32 ? C_O0_I3(S, S, S)
+ : C_O0_I4(S, S, S, S));
case INDEX_op_add_vec:
case INDEX_op_sub_vec:
@@ -3705,22 +3632,28 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_ppc_mulou_vec:
case INDEX_op_ppc_pkum_vec:
case INDEX_op_dup2_vec:
- return &v_v_v;
+ return C_O1_I2(v, v, v);
+
case INDEX_op_not_vec:
case INDEX_op_neg_vec:
- return &v_v;
+ return C_O1_I1(v, v);
+
case INDEX_op_dup_vec:
- return have_isa_3_00 ? &v_vr : &v_v;
+ return have_isa_3_00 ? C_O1_I1(v, vr) : C_O1_I1(v, v);
+
case INDEX_op_ld_vec:
- case INDEX_op_st_vec:
case INDEX_op_dupm_vec:
- return &v_r;
+ return C_O1_I1(v, r);
+
+ case INDEX_op_st_vec:
+ return C_O0_I2(v, r);
+
case INDEX_op_bitsel_vec:
case INDEX_op_ppc_msum_vec:
- return &v_v_v_v;
+ return C_O1_I3(v, v, v, v);
default:
- return NULL;
+ g_assert_not_reached();
}
}
diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
new file mode 100644
index 0000000..cf0ac4d
--- /dev/null
+++ b/tcg/riscv/tcg-target-con-set.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define RISC-V target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(LZ, L)
+C_O0_I2(rZ, r)
+C_O0_I2(rZ, rZ)
+C_O0_I3(LZ, L, L)
+C_O0_I3(LZ, LZ, L)
+C_O0_I4(LZ, LZ, L, L)
+C_O0_I4(rZ, rZ, rZ, rZ)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, L, L)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, rZ, rN)
+C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, rZ, rZ, rZ, rZ)
+C_O2_I1(r, r, L)
+C_O2_I2(r, r, L, L)
+C_O2_I4(r, r, rZ, rZ, rM, rM)
diff --git a/tcg/riscv/tcg-target-con-str.h b/tcg/riscv/tcg-target-con-str.h
new file mode 100644
index 0000000..8d8afae
--- /dev/null
+++ b/tcg/riscv/tcg-target-con-str.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define RISC-V target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('I', TCG_CT_CONST_S12)
+CONST('N', TCG_CT_CONST_N12)
+CONST('M', TCG_CT_CONST_M12)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 71c0bad..e700c52 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -122,6 +122,19 @@ static const int tcg_target_call_oarg_regs[] = {
#define TCG_CT_CONST_N12 0x400
#define TCG_CT_CONST_M12 0x800
+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
+/*
+ * For softmmu, we need to avoid conflicts with the first 5
+ * argument registers to call the helper. Some of these are
+ * also used for the tlb lookup.
+ */
+#ifdef CONFIG_SOFTMMU
+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5)
+#else
+#define SOFTMMU_RESERVE_REGS 0
+#endif
+
+
static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
{
if (TCG_TARGET_REG_BITS == 32) {
@@ -131,45 +144,6 @@ static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
}
}
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'r':
- ct->regs = 0xffffffff;
- break;
- case 'L':
- /* qemu_ld/qemu_st constraint */
- ct->regs = 0xffffffff;
- /* qemu_ld/qemu_st uses TCG_REG_TMP0 */
-#if defined(CONFIG_SOFTMMU)
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[0]);
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[1]);
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[2]);
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[3]);
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[4]);
-#endif
- break;
- case 'I':
- ct->ct |= TCG_CT_CONST_S12;
- break;
- case 'N':
- ct->ct |= TCG_CT_CONST_N12;
- break;
- case 'M':
- ct->ct |= TCG_CT_CONST_M12;
- break;
- case 'Z':
- /* we can use a zero immediate as a zero register argument. */
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
-
/* test if a constant matches the constraint */
static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
@@ -1569,50 +1543,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
+static TCGConstraintSetIndex 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 rZ_r
- = { .args_ct_str = { "rZ", "r" } };
- static const TCGTargetOpDef rZ_rZ
- = { .args_ct_str = { "rZ", "rZ" } };
- static const TCGTargetOpDef rZ_rZ_rZ_rZ
- = { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
- 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_rZ_rN
- = { .args_ct_str = { "r", "rZ", "rN" } };
- static const TCGTargetOpDef r_rZ_rZ
- = { .args_ct_str = { "r", "rZ", "rZ" } };
- static const TCGTargetOpDef r_rZ_rZ_rZ_rZ
- = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
- static const TCGTargetOpDef r_L
- = { .args_ct_str = { "r", "L" } };
- 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_L_L
- = { .args_ct_str = { "r", "r", "L", "L" } };
- static const TCGTargetOpDef LZ_L
- = { .args_ct_str = { "LZ", "L" } };
- static const TCGTargetOpDef LZ_L_L
- = { .args_ct_str = { "LZ", "L", "L" } };
- static const TCGTargetOpDef LZ_LZ_L
- = { .args_ct_str = { "LZ", "LZ", "L" } };
- static const TCGTargetOpDef LZ_LZ_L_L
- = { .args_ct_str = { "LZ", "LZ", "L", "L" } };
- static const TCGTargetOpDef r_r_rZ_rZ_rM_rM
- = { .args_ct_str = { "r", "r", "rZ", "rZ", "rM", "rM" } };
-
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(r);
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
@@ -1644,7 +1579,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_extrl_i64_i32:
case INDEX_op_extrh_i64_i32:
case INDEX_op_ext_i32_i64:
- return &r_r;
+ return C_O1_I1(r, r);
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
@@ -1653,7 +1588,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_st16_i64:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
- return &rZ_r;
+ return C_O0_I2(rZ, r);
case INDEX_op_add_i32:
case INDEX_op_and_i32:
@@ -1663,11 +1598,11 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_and_i64:
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
- return &r_r_rI;
+ return C_O1_I2(r, r, rI);
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
- return &r_rZ_rN;
+ return C_O1_I2(r, rZ, rN);
case INDEX_op_mul_i32:
case INDEX_op_mulsh_i32:
@@ -1685,7 +1620,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
case INDEX_op_setcond_i64:
- return &r_rZ_rZ;
+ return C_O1_I2(r, rZ, rZ);
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
@@ -1693,39 +1628,41 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
- return &r_r_ri;
+ return C_O1_I2(r, r, ri);
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return &rZ_rZ;
+ return C_O0_I2(rZ, rZ);
case INDEX_op_add2_i32:
case INDEX_op_add2_i64:
case INDEX_op_sub2_i32:
case INDEX_op_sub2_i64:
- return &r_r_rZ_rZ_rM_rM;
+ return C_O2_I4(r, r, rZ, rZ, rM, rM);
case INDEX_op_brcond2_i32:
- return &rZ_rZ_rZ_rZ;
+ return C_O0_I4(rZ, rZ, rZ, rZ);
case INDEX_op_setcond2_i32:
- return &r_rZ_rZ_rZ_rZ;
+ return C_O1_I4(r, rZ, rZ, rZ, rZ);
case INDEX_op_qemu_ld_i32:
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_L : &r_L_L;
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
case INDEX_op_qemu_st_i32:
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &LZ_L : &LZ_L_L;
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O0_I2(LZ, L) : C_O0_I3(LZ, L, L));
case INDEX_op_qemu_ld_i64:
- return TCG_TARGET_REG_BITS == 64 ? &r_L
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_r_L
- : &r_r_L_L;
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, L)
+ : C_O2_I2(r, r, L, L));
case INDEX_op_qemu_st_i64:
- return TCG_TARGET_REG_BITS == 64 ? &LZ_L
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &LZ_LZ_L
- : &LZ_LZ_L_L;
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(LZ, L)
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(LZ, LZ, L)
+ : C_O0_I4(LZ, LZ, L, L));
default:
- return NULL;
+ g_assert_not_reached();
}
}
diff --git a/tcg/s390/tcg-target-con-set.h b/tcg/s390/tcg-target-con-set.h
new file mode 100644
index 0000000..31985e4
--- /dev/null
+++ b/tcg/s390/tcg-target-con-set.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define S390 target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(L, L)
+C_O0_I2(r, r)
+C_O0_I2(r, ri)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, ri)
+C_O1_I2(r, 0, rI)
+C_O1_I2(r, 0, rJ)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, rZ, r)
+C_O1_I4(r, r, ri, r, 0)
+C_O1_I4(r, r, ri, rI, 0)
+C_O2_I2(b, a, 0, r)
+C_O2_I3(b, a, 0, 1, r)
+C_O2_I4(r, r, 0, 1, rA, r)
+C_O2_I4(r, r, 0, 1, ri, r)
+C_O2_I4(r, r, 0, 1, r, r)
diff --git a/tcg/s390/tcg-target-con-str.h b/tcg/s390/tcg-target-con-str.h
new file mode 100644
index 0000000..892d8f8
--- /dev/null
+++ b/tcg/s390/tcg-target-con-str.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define S390 target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
+/*
+ * A (single) even/odd pair for division.
+ * TODO: Add something to the register allocator to allow
+ * this kind of regno+1 pairing to be done more generally.
+ */
+REGS('a', 1u << TCG_REG_R2)
+REGS('b', 1u << TCG_REG_R3)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('A', TCG_CT_CONST_S33)
+CONST('I', TCG_CT_CONST_S16)
+CONST('J', TCG_CT_CONST_S32)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
index 8517e55..b674701 100644
--- a/tcg/s390/tcg-target.c.inc
+++ b/tcg/s390/tcg-target.c.inc
@@ -42,6 +42,19 @@
#define TCG_CT_CONST_S33 0x400
#define TCG_CT_CONST_ZERO 0x800
+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 16)
+/*
+ * For softmmu, we need to avoid conflicts with the first 3
+ * argument registers to perform the tlb lookup, and to call
+ * the helper function.
+ */
+#ifdef CONFIG_SOFTMMU
+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_R2, 3)
+#else
+#define SOFTMMU_RESERVE_REGS 0
+#endif
+
+
/* Several places within the instruction set 0 means "no register"
rather than TCG_REG_R0. */
#define TCG_REG_NONE 0
@@ -403,46 +416,6 @@ static bool patch_reloc(tcg_insn_unit *src_rw, int type,
return false;
}
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'r': /* all registers */
- ct->regs = 0xffff;
- break;
- case 'L': /* qemu_ld/st constraint */
- ct->regs = 0xffff;
- tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
- break;
- case 'a': /* force R2 for division */
- ct->regs = 0;
- tcg_regset_set_reg(ct->regs, TCG_REG_R2);
- break;
- case 'b': /* force R3 for division */
- ct->regs = 0;
- tcg_regset_set_reg(ct->regs, TCG_REG_R3);
- break;
- case 'A':
- ct->ct |= TCG_CT_CONST_S33;
- break;
- case 'I':
- ct->ct |= TCG_CT_CONST_S16;
- break;
- case 'J':
- ct->ct |= TCG_CT_CONST_S32;
- break;
- case 'Z':
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
-
/* Test if a constant matches the constraint. */
static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
@@ -2301,27 +2274,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
+static TCGConstraintSetIndex 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 r_L = { .args_ct_str = { "r", "L" } };
- static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
- static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
- static const TCGTargetOpDef r_0_ri = { .args_ct_str = { "r", "0", "ri" } };
- static const TCGTargetOpDef r_0_rI = { .args_ct_str = { "r", "0", "rI" } };
- static const TCGTargetOpDef r_0_rJ = { .args_ct_str = { "r", "0", "rJ" } };
- static const TCGTargetOpDef a2_r
- = { .args_ct_str = { "r", "r", "0", "1", "r", "r" } };
- static const TCGTargetOpDef a2_ri
- = { .args_ct_str = { "r", "r", "0", "1", "ri", "r" } };
- static const TCGTargetOpDef a2_rA
- = { .args_ct_str = { "r", "r", "0", "1", "rA", "r" } };
-
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(r);
case INDEX_op_ld8u_i32:
case INDEX_op_ld8u_i64:
@@ -2335,6 +2292,8 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_ld32u_i64:
case INDEX_op_ld32s_i64:
case INDEX_op_ld_i64:
+ return C_O1_I1(r, r);
+
case INDEX_op_st8_i32:
case INDEX_op_st8_i64:
case INDEX_op_st16_i32:
@@ -2342,11 +2301,22 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_st_i32:
case INDEX_op_st32_i64:
case INDEX_op_st_i64:
- return &r_r;
+ return C_O0_I2(r, r);
case INDEX_op_add_i32:
case INDEX_op_add_i64:
- return &r_r_ri;
+ case INDEX_op_shl_i64:
+ case INDEX_op_shr_i64:
+ case INDEX_op_sar_i64:
+ case INDEX_op_rotl_i32:
+ case INDEX_op_rotl_i64:
+ case INDEX_op_rotr_i32:
+ case INDEX_op_rotr_i64:
+ case INDEX_op_clz_i64:
+ case INDEX_op_setcond_i32:
+ case INDEX_op_setcond_i64:
+ return C_O1_I2(r, r, ri);
+
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
case INDEX_op_and_i32:
@@ -2355,35 +2325,33 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_or_i64:
case INDEX_op_xor_i32:
case INDEX_op_xor_i64:
- return (s390_facilities & FACILITY_DISTINCT_OPS ? &r_r_ri : &r_0_ri);
+ return (s390_facilities & FACILITY_DISTINCT_OPS
+ ? C_O1_I2(r, r, ri)
+ : C_O1_I2(r, 0, ri));
case INDEX_op_mul_i32:
/* If we have the general-instruction-extensions, then we have
MULTIPLY SINGLE IMMEDIATE with a signed 32-bit, otherwise we
have only MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit. */
- return (s390_facilities & FACILITY_GEN_INST_EXT ? &r_0_ri : &r_0_rI);
+ return (s390_facilities & FACILITY_GEN_INST_EXT
+ ? C_O1_I2(r, 0, ri)
+ : C_O1_I2(r, 0, rI));
+
case INDEX_op_mul_i64:
- return (s390_facilities & FACILITY_GEN_INST_EXT ? &r_0_rJ : &r_0_rI);
+ return (s390_facilities & FACILITY_GEN_INST_EXT
+ ? C_O1_I2(r, 0, rJ)
+ : C_O1_I2(r, 0, rI));
case INDEX_op_shl_i32:
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
- return (s390_facilities & FACILITY_DISTINCT_OPS ? &r_r_ri : &r_0_ri);
-
- case INDEX_op_shl_i64:
- case INDEX_op_shr_i64:
- case INDEX_op_sar_i64:
- return &r_r_ri;
-
- case INDEX_op_rotl_i32:
- case INDEX_op_rotl_i64:
- case INDEX_op_rotr_i32:
- case INDEX_op_rotr_i64:
- return &r_r_ri;
+ return (s390_facilities & FACILITY_DISTINCT_OPS
+ ? C_O1_I2(r, r, ri)
+ : C_O1_I2(r, 0, ri));
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return &r_ri;
+ return C_O0_I2(r, ri);
case INDEX_op_bswap16_i32:
case INDEX_op_bswap16_i64:
@@ -2406,63 +2374,49 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_extu_i32_i64:
case INDEX_op_extract_i32:
case INDEX_op_extract_i64:
- return &r_r;
-
- case INDEX_op_clz_i64:
- case INDEX_op_setcond_i32:
- case INDEX_op_setcond_i64:
- return &r_r_ri;
+ return C_O1_I1(r, r);
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_ld_i64:
- return &r_L;
+ return C_O1_I1(r, L);
case INDEX_op_qemu_st_i64:
case INDEX_op_qemu_st_i32:
- return &L_L;
+ return C_O0_I2(L, L);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
- {
- static const TCGTargetOpDef dep
- = { .args_ct_str = { "r", "rZ", "r" } };
- return &dep;
- }
+ return C_O1_I2(r, rZ, r);
+
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
- {
- static const TCGTargetOpDef movc
- = { .args_ct_str = { "r", "r", "ri", "r", "0" } };
- static const TCGTargetOpDef movc_l
- = { .args_ct_str = { "r", "r", "ri", "rI", "0" } };
- return (s390_facilities & FACILITY_LOAD_ON_COND2 ? &movc_l : &movc);
- }
+ return (s390_facilities & FACILITY_LOAD_ON_COND2
+ ? C_O1_I4(r, r, ri, rI, 0)
+ : C_O1_I4(r, r, ri, r, 0));
+
case INDEX_op_div2_i32:
case INDEX_op_div2_i64:
case INDEX_op_divu2_i32:
case INDEX_op_divu2_i64:
- {
- static const TCGTargetOpDef div2
- = { .args_ct_str = { "b", "a", "0", "1", "r" } };
- return &div2;
- }
+ return C_O2_I3(b, a, 0, 1, r);
+
case INDEX_op_mulu2_i64:
- {
- static const TCGTargetOpDef mul2
- = { .args_ct_str = { "b", "a", "0", "r" } };
- return &mul2;
- }
+ return C_O2_I2(b, a, 0, r);
case INDEX_op_add2_i32:
case INDEX_op_sub2_i32:
- return (s390_facilities & FACILITY_EXT_IMM ? &a2_ri : &a2_r);
+ return (s390_facilities & FACILITY_EXT_IMM
+ ? C_O2_I4(r, r, 0, 1, ri, r)
+ : C_O2_I4(r, r, 0, 1, r, r));
+
case INDEX_op_add2_i64:
case INDEX_op_sub2_i64:
- return (s390_facilities & FACILITY_EXT_IMM ? &a2_rA : &a2_r);
+ return (s390_facilities & FACILITY_EXT_IMM
+ ? C_O2_I4(r, r, 0, 1, rA, r)
+ : C_O2_I4(r, r, 0, 1, r, r));
default:
- break;
+ g_assert_not_reached();
}
- return NULL;
}
static void query_s390_facilities(void)
diff --git a/tcg/sparc/tcg-target-con-set.h b/tcg/sparc/tcg-target-con-set.h
new file mode 100644
index 0000000..3b751dc
--- /dev/null
+++ b/tcg/sparc/tcg-target-con-set.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define Sparc target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
+C_O0_I2(rZ, r)
+C_O0_I2(RZ, r)
+C_O0_I2(rZ, rJ)
+C_O0_I2(RZ, RJ)
+C_O0_I2(sZ, A)
+C_O0_I2(SZ, A)
+C_O1_I1(r, A)
+C_O1_I1(R, A)
+C_O1_I1(r, r)
+C_O1_I1(r, R)
+C_O1_I1(R, r)
+C_O1_I1(R, R)
+C_O1_I2(R, R, R)
+C_O1_I2(r, rZ, rJ)
+C_O1_I2(R, RZ, RJ)
+C_O1_I4(r, rZ, rJ, rI, 0)
+C_O1_I4(R, RZ, RJ, RI, 0)
+C_O2_I2(r, r, rZ, rJ)
+C_O2_I4(R, R, RZ, RZ, RJ, RI)
+C_O2_I4(r, r, rZ, rZ, rJ, rJ)
diff --git a/tcg/sparc/tcg-target-con-str.h b/tcg/sparc/tcg-target-con-str.h
new file mode 100644
index 0000000..fdb25d9
--- /dev/null
+++ b/tcg/sparc/tcg-target-con-str.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define Sparc target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', ALL_GENERAL_REGS)
+REGS('R', ALL_GENERAL_REGS64)
+REGS('s', ALL_QLDST_REGS)
+REGS('S', ALL_QLDST_REGS64)
+REGS('A', TARGET_LONG_BITS == 64 ? ALL_QLDST_REGS64 : ALL_QLDST_REGS)
+
+/*
+ * Define constraint letters for constants:
+ * CONST(letter, TCG_CT_CONST_* bit set)
+ */
+CONST('I', TCG_CT_CONST_S11)
+CONST('J', TCG_CT_CONST_S13)
+CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
index 28b5b65..3d50f98 100644
--- a/tcg/sparc/tcg-target.c.inc
+++ b/tcg/sparc/tcg-target.c.inc
@@ -67,17 +67,37 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
# define SPARC64 0
#endif
-/* Note that sparcv8plus can only hold 64 bit quantities in %g and %o
- registers. These are saved manually by the kernel in full 64-bit
- slots. The %i and %l registers are saved by the register window
- mechanism, which only allocates space for 32 bits. Given that this
- window spill/fill can happen on any signal, we must consider the
- high bits of the %i and %l registers garbage at all times. */
+#define TCG_CT_CONST_S11 0x100
+#define TCG_CT_CONST_S13 0x200
+#define TCG_CT_CONST_ZERO 0x400
+
+/*
+ * For softmmu, we need to avoid conflicts with the first 3
+ * argument registers to perform the tlb lookup, and to call
+ * the helper function.
+ */
+#ifdef CONFIG_SOFTMMU
+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_O0, 3)
+#else
+#define SOFTMMU_RESERVE_REGS 0
+#endif
+
+/*
+ * Note that sparcv8plus can only hold 64 bit quantities in %g and %o
+ * registers. These are saved manually by the kernel in full 64-bit
+ * slots. The %i and %l registers are saved by the register window
+ * mechanism, which only allocates space for 32 bits. Given that this
+ * window spill/fill can happen on any signal, we must consider the
+ * high bits of the %i and %l registers garbage at all times.
+ */
+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
#if SPARC64
-# define ALL_64 0xffffffffu
+# define ALL_GENERAL_REGS64 ALL_GENERAL_REGS
#else
-# define ALL_64 0xffffu
+# define ALL_GENERAL_REGS64 MAKE_64BIT_MASK(0, 16)
#endif
+#define ALL_QLDST_REGS (ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
+#define ALL_QLDST_REGS64 (ALL_GENERAL_REGS64 & ~SOFTMMU_RESERVE_REGS)
/* Define some temporary registers. T2 is used for constant generation. */
#define TCG_REG_T1 TCG_REG_G1
@@ -320,45 +340,6 @@ static bool patch_reloc(tcg_insn_unit *src_rw, int type,
return true;
}
-/* parse target specific constraints */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'r':
- ct->regs = 0xffffffff;
- break;
- case 'R':
- ct->regs = ALL_64;
- break;
- case 'A': /* qemu_ld/st address constraint */
- ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
- reserve_helpers:
- tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
- tcg_regset_reset_reg(ct->regs, TCG_REG_O1);
- tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
- break;
- case 's': /* qemu_st data 32-bit constraint */
- ct->regs = 0xffffffff;
- goto reserve_helpers;
- case 'S': /* qemu_st data 64-bit constraint */
- ct->regs = ALL_64;
- goto reserve_helpers;
- case 'I':
- ct->ct |= TCG_CT_CONST_S11;
- break;
- case 'J':
- ct->ct |= TCG_CT_CONST_S13;
- break;
- case 'Z':
- ct->ct |= TCG_CT_CONST_ZERO;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
-
/* test if a constant matches the constraint */
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
@@ -1592,40 +1573,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
}
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
+static TCGConstraintSetIndex 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 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" } };
-
switch (op) {
case INDEX_op_goto_ptr:
- return &r;
+ return C_O0_I1(r);
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
@@ -1634,12 +1586,12 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_ld_i32:
case INDEX_op_neg_i32:
case INDEX_op_not_i32:
- return &r_r;
+ return C_O1_I1(r, r);
case INDEX_op_st8_i32:
case INDEX_op_st16_i32:
case INDEX_op_st_i32:
- return &rZ_r;
+ return C_O0_I2(rZ, r);
case INDEX_op_add_i32:
case INDEX_op_mul_i32:
@@ -1655,18 +1607,18 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_shr_i32:
case INDEX_op_sar_i32:
case INDEX_op_setcond_i32:
- return &r_rZ_rJ;
+ return C_O1_I2(r, rZ, rJ);
case INDEX_op_brcond_i32:
- return &rZ_rJ;
+ return C_O0_I2(rZ, rJ);
case INDEX_op_movcond_i32:
- return &movc_32;
+ return C_O1_I4(r, rZ, rJ, rI, 0);
case INDEX_op_add2_i32:
case INDEX_op_sub2_i32:
- return &add2_32;
+ return C_O2_I4(r, r, rZ, rZ, rJ, rJ);
case INDEX_op_mulu2_i32:
case INDEX_op_muls2_i32:
- return &r_r_rZ_rJ;
+ return C_O2_I2(r, r, rZ, rJ);
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
@@ -1677,13 +1629,13 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_ld_i64:
case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64:
- return &R_r;
+ return C_O1_I1(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;
+ return C_O0_I2(RZ, r);
case INDEX_op_add_i64:
case INDEX_op_mul_i64:
@@ -1699,39 +1651,39 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
case INDEX_op_setcond_i64:
- return &R_RZ_RJ;
+ return C_O1_I2(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;
+ return C_O1_I1(R, R);
case INDEX_op_extrl_i64_i32:
case INDEX_op_extrh_i64_i32:
- return &r_R;
+ return C_O1_I1(r, R);
case INDEX_op_brcond_i64:
- return &RZ_RJ;
+ return C_O0_I2(RZ, RJ);
case INDEX_op_movcond_i64:
- return &movc_64;
+ return C_O1_I4(R, RZ, RJ, RI, 0);
case INDEX_op_add2_i64:
case INDEX_op_sub2_i64:
- return &add2_64;
+ return C_O2_I4(R, R, RZ, RZ, RJ, RI);
case INDEX_op_muluh_i64:
- return &R_R_R;
+ return C_O1_I2(R, R, R);
case INDEX_op_qemu_ld_i32:
- return &r_A;
+ return C_O1_I1(r, A);
case INDEX_op_qemu_ld_i64:
- return &R_A;
+ return C_O1_I1(R, A);
case INDEX_op_qemu_st_i32:
- return &sZ_A;
+ return C_O0_I2(sZ, A);
case INDEX_op_qemu_st_i64:
- return &SZ_A;
+ return C_O0_I2(SZ, A);
default:
- return NULL;
+ g_assert_not_reached();
}
}
@@ -1746,8 +1698,8 @@ static void tcg_target_init(TCGContext *s)
}
#endif
- tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
- tcg_target_available_regs[TCG_TYPE_I64] = ALL_64;
+ tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
+ tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS64;
tcg_target_call_clobber_regs = 0;
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G1);
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 95ab9af..f66f5d0 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -66,10 +66,6 @@ typedef enum {
TCG_REG_I7,
} TCGReg;
-#define TCG_CT_CONST_S11 0x100
-#define TCG_CT_CONST_S13 0x200
-#define TCG_CT_CONST_ZERO 0x400
-
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_O6
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 9e1b0d7..63a12b1 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,7 +69,6 @@
/* Forward declarations for functions declared in tcg-target.c.inc and
used here. */
static void tcg_target_init(TCGContext *s);
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode);
static void tcg_target_qemu_prologue(TCGContext *s);
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend);
@@ -103,8 +102,6 @@ static void tcg_register_jit_int(const void *buf, size_t size,
__attribute__((unused));
/* Forward declarations for functions declared and used in tcg-target.c.inc. */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type);
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
intptr_t arg2);
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
@@ -349,6 +346,109 @@ static void set_jmp_reset_offset(TCGContext *s, int which)
s->tb_jmp_reset_offset[which] = tcg_current_code_size(s);
}
+#define C_PFX1(P, A) P##A
+#define C_PFX2(P, A, B) P##A##_##B
+#define C_PFX3(P, A, B, C) P##A##_##B##_##C
+#define C_PFX4(P, A, B, C, D) P##A##_##B##_##C##_##D
+#define C_PFX5(P, A, B, C, D, E) P##A##_##B##_##C##_##D##_##E
+#define C_PFX6(P, A, B, C, D, E, F) P##A##_##B##_##C##_##D##_##E##_##F
+
+/* Define an enumeration for the various combinations. */
+
+#define C_O0_I1(I1) C_PFX1(c_o0_i1_, I1),
+#define C_O0_I2(I1, I2) C_PFX2(c_o0_i2_, I1, I2),
+#define C_O0_I3(I1, I2, I3) C_PFX3(c_o0_i3_, I1, I2, I3),
+#define C_O0_I4(I1, I2, I3, I4) C_PFX4(c_o0_i4_, I1, I2, I3, I4),
+
+#define C_O1_I1(O1, I1) C_PFX2(c_o1_i1_, O1, I1),
+#define C_O1_I2(O1, I1, I2) C_PFX3(c_o1_i2_, O1, I1, I2),
+#define C_O1_I3(O1, I1, I2, I3) C_PFX4(c_o1_i3_, O1, I1, I2, I3),
+#define C_O1_I4(O1, I1, I2, I3, I4) C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4),
+
+#define C_N1_I2(O1, I1, I2) C_PFX3(c_n1_i2_, O1, I1, I2),
+
+#define C_O2_I1(O1, O2, I1) C_PFX3(c_o2_i1_, O1, O2, I1),
+#define C_O2_I2(O1, O2, I1, I2) C_PFX4(c_o2_i2_, O1, O2, I1, I2),
+#define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3),
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4),
+
+typedef enum {
+#include "tcg-target-con-set.h"
+} TCGConstraintSetIndex;
+
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode);
+
+#undef C_O0_I1
+#undef C_O0_I2
+#undef C_O0_I3
+#undef C_O0_I4
+#undef C_O1_I1
+#undef C_O1_I2
+#undef C_O1_I3
+#undef C_O1_I4
+#undef C_N1_I2
+#undef C_O2_I1
+#undef C_O2_I2
+#undef C_O2_I3
+#undef C_O2_I4
+
+/* Put all of the constraint sets into an array, indexed by the enum. */
+
+#define C_O0_I1(I1) { .args_ct_str = { #I1 } },
+#define C_O0_I2(I1, I2) { .args_ct_str = { #I1, #I2 } },
+#define C_O0_I3(I1, I2, I3) { .args_ct_str = { #I1, #I2, #I3 } },
+#define C_O0_I4(I1, I2, I3, I4) { .args_ct_str = { #I1, #I2, #I3, #I4 } },
+
+#define C_O1_I1(O1, I1) { .args_ct_str = { #O1, #I1 } },
+#define C_O1_I2(O1, I1, I2) { .args_ct_str = { #O1, #I1, #I2 } },
+#define C_O1_I3(O1, I1, I2, I3) { .args_ct_str = { #O1, #I1, #I2, #I3 } },
+#define C_O1_I4(O1, I1, I2, I3, I4) { .args_ct_str = { #O1, #I1, #I2, #I3, #I4 } },
+
+#define C_N1_I2(O1, I1, I2) { .args_ct_str = { "&" #O1, #I1, #I2 } },
+
+#define C_O2_I1(O1, O2, I1) { .args_ct_str = { #O1, #O2, #I1 } },
+#define C_O2_I2(O1, O2, I1, I2) { .args_ct_str = { #O1, #O2, #I1, #I2 } },
+#define C_O2_I3(O1, O2, I1, I2, I3) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3 } },
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3, #I4 } },
+
+static const TCGTargetOpDef constraint_sets[] = {
+#include "tcg-target-con-set.h"
+};
+
+
+#undef C_O0_I1
+#undef C_O0_I2
+#undef C_O0_I3
+#undef C_O0_I4
+#undef C_O1_I1
+#undef C_O1_I2
+#undef C_O1_I3
+#undef C_O1_I4
+#undef C_N1_I2
+#undef C_O2_I1
+#undef C_O2_I2
+#undef C_O2_I3
+#undef C_O2_I4
+
+/* Expand the enumerator to be returned from tcg_target_op_def(). */
+
+#define C_O0_I1(I1) C_PFX1(c_o0_i1_, I1)
+#define C_O0_I2(I1, I2) C_PFX2(c_o0_i2_, I1, I2)
+#define C_O0_I3(I1, I2, I3) C_PFX3(c_o0_i3_, I1, I2, I3)
+#define C_O0_I4(I1, I2, I3, I4) C_PFX4(c_o0_i4_, I1, I2, I3, I4)
+
+#define C_O1_I1(O1, I1) C_PFX2(c_o1_i1_, O1, I1)
+#define C_O1_I2(O1, I1, I2) C_PFX3(c_o1_i2_, O1, I1, I2)
+#define C_O1_I3(O1, I1, I2, I3) C_PFX4(c_o1_i3_, O1, I1, I2, I3)
+#define C_O1_I4(O1, I1, I2, I3, I4) C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4)
+
+#define C_N1_I2(O1, I1, I2) C_PFX3(c_n1_i2_, O1, I1, I2)
+
+#define C_O2_I1(O1, O2, I1) C_PFX3(c_o2_i1_, O1, O2, I1)
+#define C_O2_I2(O1, O2, I1, I2) C_PFX4(c_o2_i2_, O1, O2, I1, I2)
+#define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3)
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4)
+
#include "tcg-target.c.inc"
/* compare a pointer @ptr and a tb_tc @s */
@@ -2415,7 +2515,6 @@ static void process_op_defs(TCGContext *s)
for (op = 0; op < NB_OPS; op++) {
TCGOpDef *def = &tcg_op_defs[op];
const TCGTargetOpDef *tdefs;
- TCGType type;
int i, nb_args;
if (def->flags & TCG_OPF_NOT_PRESENT) {
@@ -2427,11 +2526,15 @@ static void process_op_defs(TCGContext *s)
continue;
}
- tdefs = tcg_target_op_def(op);
- /* Missing TCGTargetOpDef entry. */
- tcg_debug_assert(tdefs != NULL);
+ /*
+ * Macro magic should make it impossible, but double-check that
+ * the array index is in range. Since the signness of an enum
+ * is implementation defined, force the result to unsigned.
+ */
+ unsigned con_set = tcg_target_op_def(op);
+ tcg_debug_assert(con_set < ARRAY_SIZE(constraint_sets));
+ tdefs = &constraint_sets[con_set];
- type = (def->flags & TCG_OPF_64BIT ? TCG_TYPE_I64 : TCG_TYPE_I32);
for (i = 0; i < nb_args; i++) {
const char *ct_str = tdefs->args_ct_str[i];
/* Incomplete TCGTargetOpDef entry. */
@@ -2463,11 +2566,22 @@ static void process_op_defs(TCGContext *s)
def->args_ct[i].ct |= TCG_CT_CONST;
ct_str++;
break;
+
+ /* Include all of the target-specific constraints. */
+
+#undef CONST
+#define CONST(CASE, MASK) \
+ case CASE: def->args_ct[i].ct |= MASK; ct_str++; break;
+#define REGS(CASE, MASK) \
+ case CASE: def->args_ct[i].regs |= MASK; ct_str++; break;
+
+#include "tcg-target-con-str.h"
+
+#undef REGS
+#undef CONST
default:
- ct_str = target_parse_constraint(&def->args_ct[i],
- ct_str, type);
/* Typo in TCGTargetOpDef constraint. */
- tcg_debug_assert(ct_str != NULL);
+ g_assert_not_reached();
}
}
}
diff --git a/tcg/tci/tcg-target-con-set.h b/tcg/tci/tcg-target-con-set.h
new file mode 100644
index 0000000..38e82f7
--- /dev/null
+++ b/tcg/tci/tcg-target-con-set.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * TCI target-specific constraint sets.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I2(r, r)
+C_O0_I2(r, ri)
+C_O0_I3(r, r, r)
+C_O0_I4(r, r, ri, ri)
+C_O0_I4(r, r, r, r)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, r)
+C_O1_I2(r, ri, ri)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, ri)
+C_O1_I4(r, r, r, ri, ri)
+C_O2_I1(r, r, r)
+C_O2_I2(r, r, r, r)
+C_O2_I4(r, r, r, r, r, r)
diff --git a/tcg/tci/tcg-target-con-str.h b/tcg/tci/tcg-target-con-str.h
new file mode 100644
index 0000000..87c0f19
--- /dev/null
+++ b/tcg/tci/tcg-target-con-str.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define TCI target-specific operand constraints.
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * Define constraint letters for register sets:
+ * REGS(letter, register_mask)
+ */
+REGS('r', MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS))
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 1598126..f0f6b13 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -37,236 +37,143 @@
/* Bitfield n...m (in 32 bit value). */
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
-/* Macros used in tcg_target_op_defs. */
-#define R "r"
-#define RI "ri"
-#if TCG_TARGET_REG_BITS == 32
-# define R64 "r", "r"
-#else
-# define R64 "r"
-#endif
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-# define L "L", "L"
-# define S "S", "S"
-#else
-# define L "L"
-# define S "S"
-#endif
-
-/* TODO: documentation. */
-static const TCGTargetOpDef tcg_target_op_defs[] = {
- { INDEX_op_exit_tb, { NULL } },
- { INDEX_op_goto_tb, { NULL } },
- { INDEX_op_br, { NULL } },
-
- { 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, RI, RI } },
- { INDEX_op_sub_i32, { R, RI, RI } },
- { INDEX_op_mul_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_div_i32
- { INDEX_op_div_i32, { R, R, R } },
- { INDEX_op_divu_i32, { R, R, R } },
- { INDEX_op_rem_i32, { R, R, R } },
- { INDEX_op_remu_i32, { R, R, R } },
-#elif TCG_TARGET_HAS_div2_i32
- { INDEX_op_div2_i32, { R, R, "0", "1", R } },
- { INDEX_op_divu2_i32, { R, R, "0", "1", R } },
-#endif
- /* TODO: Does R, RI, RI result in faster code than R, R, RI?
- If both operands are constants, we can optimize. */
- { INDEX_op_and_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_andc_i32
- { INDEX_op_andc_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_eqv_i32
- { INDEX_op_eqv_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_nand_i32
- { INDEX_op_nand_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_nor_i32
- { INDEX_op_nor_i32, { R, RI, RI } },
-#endif
- { INDEX_op_or_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_orc_i32
- { INDEX_op_orc_i32, { R, RI, RI } },
-#endif
- { INDEX_op_xor_i32, { R, RI, RI } },
- { INDEX_op_shl_i32, { R, RI, RI } },
- { INDEX_op_shr_i32, { R, RI, RI } },
- { INDEX_op_sar_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_rot_i32
- { INDEX_op_rotl_i32, { R, RI, RI } },
- { INDEX_op_rotr_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_deposit_i32
- { INDEX_op_deposit_i32, { R, "0", R } },
-#endif
-
- { INDEX_op_brcond_i32, { R, RI } },
-
- { INDEX_op_setcond_i32, { R, R, RI } },
-#if TCG_TARGET_REG_BITS == 64
- { INDEX_op_setcond_i64, { R, R, RI } },
-#endif /* TCG_TARGET_REG_BITS == 64 */
-
-#if TCG_TARGET_REG_BITS == 32
- /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
- { INDEX_op_add2_i32, { R, R, R, R, R, R } },
- { INDEX_op_sub2_i32, { R, R, R, R, R, R } },
- { INDEX_op_brcond2_i32, { R, R, RI, RI } },
- { INDEX_op_mulu2_i32, { R, R, R, R } },
- { INDEX_op_setcond2_i32, { R, R, R, RI, RI } },
-#endif
-
-#if TCG_TARGET_HAS_not_i32
- { INDEX_op_not_i32, { R, R } },
-#endif
-#if TCG_TARGET_HAS_neg_i32
- { INDEX_op_neg_i32, { R, R } },
-#endif
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
+ switch (op) {
+ 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_not_i32:
+ case INDEX_op_not_i64:
+ case INDEX_op_neg_i32:
+ case INDEX_op_neg_i64:
+ case INDEX_op_ext8s_i32:
+ case INDEX_op_ext8s_i64:
+ case INDEX_op_ext16s_i32:
+ case INDEX_op_ext16s_i64:
+ case INDEX_op_ext8u_i32:
+ case INDEX_op_ext8u_i64:
+ case INDEX_op_ext16u_i32:
+ case INDEX_op_ext16u_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_bswap16_i32:
+ case INDEX_op_bswap16_i64:
+ case INDEX_op_bswap32_i32:
+ case INDEX_op_bswap32_i64:
+ case INDEX_op_bswap64_i64:
+ return C_O1_I1(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, RI, RI } },
- { INDEX_op_sub_i64, { R, RI, RI } },
- { INDEX_op_mul_i64, { R, RI, RI } },
-#if TCG_TARGET_HAS_div_i64
- { INDEX_op_div_i64, { R, R, R } },
- { INDEX_op_divu_i64, { R, R, R } },
- { INDEX_op_rem_i64, { R, R, R } },
- { INDEX_op_remu_i64, { R, R, R } },
-#elif TCG_TARGET_HAS_div2_i64
- { INDEX_op_div2_i64, { R, R, "0", "1", R } },
- { INDEX_op_divu2_i64, { R, R, "0", "1", R } },
-#endif
- { INDEX_op_and_i64, { R, RI, RI } },
-#if TCG_TARGET_HAS_andc_i64
- { INDEX_op_andc_i64, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_eqv_i64
- { INDEX_op_eqv_i64, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_nand_i64
- { INDEX_op_nand_i64, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_nor_i64
- { INDEX_op_nor_i64, { R, RI, RI } },
-#endif
- { INDEX_op_or_i64, { R, RI, RI } },
-#if TCG_TARGET_HAS_orc_i64
- { INDEX_op_orc_i64, { R, RI, RI } },
-#endif
- { INDEX_op_xor_i64, { R, RI, RI } },
- { INDEX_op_shl_i64, { R, RI, RI } },
- { INDEX_op_shr_i64, { R, RI, RI } },
- { INDEX_op_sar_i64, { R, RI, RI } },
-#if TCG_TARGET_HAS_rot_i64
- { INDEX_op_rotl_i64, { R, RI, RI } },
- { INDEX_op_rotr_i64, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_deposit_i64
- { INDEX_op_deposit_i64, { R, "0", R } },
-#endif
- { INDEX_op_brcond_i64, { R, RI } },
+ 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 C_O0_I2(r, r);
+
+ 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:
+ return C_O1_I2(r, r, r);
-#if TCG_TARGET_HAS_ext8s_i64
- { INDEX_op_ext8s_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext16s_i64
- { INDEX_op_ext16s_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext32s_i64
- { INDEX_op_ext32s_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext8u_i64
- { INDEX_op_ext8u_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext16u_i64
- { INDEX_op_ext16u_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext32u_i64
- { INDEX_op_ext32u_i64, { R, R } },
-#endif
- { INDEX_op_ext_i32_i64, { R, R } },
- { INDEX_op_extu_i32_i64, { R, R } },
-#if TCG_TARGET_HAS_bswap16_i64
- { INDEX_op_bswap16_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_bswap32_i64
- { INDEX_op_bswap32_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_bswap64_i64
- { INDEX_op_bswap64_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_not_i64
- { INDEX_op_not_i64, { R, R } },
-#endif
-#if TCG_TARGET_HAS_neg_i64
- { INDEX_op_neg_i64, { R, R } },
-#endif
-#endif /* TCG_TARGET_REG_BITS == 64 */
+ case INDEX_op_add_i32:
+ case INDEX_op_add_i64:
+ case INDEX_op_sub_i32:
+ case INDEX_op_sub_i64:
+ case INDEX_op_mul_i32:
+ case INDEX_op_mul_i64:
+ case INDEX_op_and_i32:
+ case INDEX_op_and_i64:
+ case INDEX_op_andc_i32:
+ case INDEX_op_andc_i64:
+ case INDEX_op_eqv_i32:
+ case INDEX_op_eqv_i64:
+ case INDEX_op_nand_i32:
+ case INDEX_op_nand_i64:
+ case INDEX_op_nor_i32:
+ case INDEX_op_nor_i64:
+ case INDEX_op_or_i32:
+ case INDEX_op_or_i64:
+ case INDEX_op_orc_i32:
+ case INDEX_op_orc_i64:
+ case INDEX_op_xor_i32:
+ case INDEX_op_xor_i64:
+ case INDEX_op_shl_i32:
+ case INDEX_op_shl_i64:
+ case INDEX_op_shr_i32:
+ case INDEX_op_shr_i64:
+ case INDEX_op_sar_i32:
+ case INDEX_op_sar_i64:
+ case INDEX_op_rotl_i32:
+ case INDEX_op_rotl_i64:
+ case INDEX_op_rotr_i32:
+ case INDEX_op_rotr_i64:
+ /* TODO: Does R, RI, RI result in faster code than R, R, RI? */
+ return C_O1_I2(r, ri, ri);
- { INDEX_op_qemu_ld_i32, { R, L } },
- { INDEX_op_qemu_ld_i64, { R64, L } },
+ case INDEX_op_deposit_i32:
+ case INDEX_op_deposit_i64:
+ return C_O1_I2(r, 0, r);
- { INDEX_op_qemu_st_i32, { R, S } },
- { INDEX_op_qemu_st_i64, { R64, S } },
+ case INDEX_op_brcond_i32:
+ case INDEX_op_brcond_i64:
+ return C_O0_I2(r, ri);
-#if TCG_TARGET_HAS_ext8s_i32
- { INDEX_op_ext8s_i32, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext16s_i32
- { INDEX_op_ext16s_i32, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext8u_i32
- { INDEX_op_ext8u_i32, { R, R } },
-#endif
-#if TCG_TARGET_HAS_ext16u_i32
- { INDEX_op_ext16u_i32, { R, R } },
-#endif
+ case INDEX_op_setcond_i32:
+ case INDEX_op_setcond_i64:
+ return C_O1_I2(r, r, ri);
-#if TCG_TARGET_HAS_bswap16_i32
- { INDEX_op_bswap16_i32, { R, R } },
-#endif
-#if TCG_TARGET_HAS_bswap32_i32
- { INDEX_op_bswap32_i32, { R, R } },
+#if TCG_TARGET_REG_BITS == 32
+ /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
+ case INDEX_op_add2_i32:
+ case INDEX_op_sub2_i32:
+ return C_O2_I4(r, r, r, r, r, r);
+ case INDEX_op_brcond2_i32:
+ return C_O0_I4(r, r, ri, ri);
+ case INDEX_op_mulu2_i32:
+ return C_O2_I2(r, r, r, r);
+ case INDEX_op_setcond2_i32:
+ return C_O1_I4(r, r, r, ri, ri);
#endif
- { INDEX_op_mb, { } },
- { -1 },
-};
-
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
-{
- int i, n = ARRAY_SIZE(tcg_target_op_defs);
+ case INDEX_op_qemu_ld_i32:
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O1_I1(r, r)
+ : C_O1_I2(r, r, r));
+ case INDEX_op_qemu_ld_i64:
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, r)
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, r)
+ : C_O2_I2(r, r, r, r));
+ case INDEX_op_qemu_st_i32:
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ ? C_O0_I2(r, r)
+ : C_O0_I3(r, r, r));
+ case INDEX_op_qemu_st_i64:
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(r, r)
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(r, r, r)
+ : C_O0_I4(r, r, r, r));
- for (i = 0; i < n; ++i) {
- if (tcg_target_op_defs[i].op == op) {
- return &tcg_target_op_defs[i];
- }
+ default:
+ g_assert_not_reached();
}
- return NULL;
}
static const int tcg_target_reg_alloc_order[] = {
@@ -384,22 +291,6 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
return true;
}
-/* Parse target specific constraints. */
-static const char *target_parse_constraint(TCGArgConstraint *ct,
- const char *ct_str, TCGType type)
-{
- switch (*ct_str++) {
- case 'r':
- case 'L': /* qemu_ld constraint */
- case 'S': /* qemu_st constraint */
- ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
- break;
- default:
- return NULL;
- }
- return ct_str;
-}
-
#if defined(CONFIG_DEBUG_TCG_INTERPRETER)
/* Show current bytecode. Used by tcg interpreter. */
void tci_disas(uint8_t opc)