@@ -14,6 +14,7 @@ C_O0_I2(rZ, r)
C_O0_I2(rZ, rJ)
C_O1_I1(r, r)
C_O1_I2(r, r, r)
+C_O1_I2(r, r, rJ)
C_O1_I2(r, rZ, rJ)
C_O1_I4(r, rZ, rJ, rI, 0)
C_O2_I2(r, r, rZ, rJ)
@@ -962,6 +962,14 @@ typedef struct TCGOutOp {
TCGConstraintSetIndex (*dynamic_constraint)(TCGType type, unsigned flags);
} TCGOutOp;
+typedef struct TCGOutOpBinary {
+ TCGOutOp base;
+ void (*out_rrr)(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2);
+ void (*out_rri)(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2);
+} TCGOutOpBinary;
+
#include "tcg-target.c.inc"
#ifndef CONFIG_TCG_INTERPRETER
@@ -975,10 +983,20 @@ static const TCGOutOp outop_notreached = {
.static_constraint = C_NotReached,
};
+/*
+ * Register V as the TCGOutOp for O.
+ * Validate that V has subclass T.
+ */
+#define OUTOP(O, T, V) [O] = _Generic(V, T: &V.base)
+
static const TCGOutOp * const all_outop[NB_OPS] = {
[0 ... NB_OPS - 1] = &outop_notreached,
+ OUTOP(INDEX_op_add_i32, TCGOutOpBinary, outop_add),
+ OUTOP(INDEX_op_add_i64, TCGOutOpBinary, outop_add),
};
+#undef OUTOP
+
/*
* All TCG threads except the parent (i.e. the one that called tcg_context_init
* and registered the target's TCG globals) must register with this function
@@ -5400,6 +5418,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
}
/* emit instruction */
+ TCGType type = TCGOP_TYPE(op);
switch (op->opc) {
case INDEX_op_ext_i32_i64:
tcg_out_exts_i32_i64(s, new_args[0], new_args[1]);
@@ -5410,12 +5429,28 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
case INDEX_op_extrl_i64_i32:
tcg_out_extrl_i64_i32(s, new_args[0], new_args[1]);
break;
+
+ case INDEX_op_add_i32:
+ case INDEX_op_add_i64:
+ {
+ const TCGOutOpBinary *out =
+ container_of(all_outop[op->opc], TCGOutOpBinary, base);
+
+ tcg_debug_assert(!const_args[1]);
+ if (const_args[2]) {
+ out->out_rri(s, type, new_args[0], new_args[1], new_args[2]);
+ } else {
+ out->out_rrr(s, type, new_args[0], new_args[1], new_args[2]);
+ }
+ }
+ break;
+
default:
if (def->flags & TCG_OPF_VECTOR) {
- tcg_out_vec_op(s, op->opc, TCGOP_TYPE(op) - TCG_TYPE_V64,
+ tcg_out_vec_op(s, op->opc, type - TCG_TYPE_V64,
TCGOP_VECE(op), new_args, const_args);
} else {
- tcg_out_op(s, op->opc, TCGOP_TYPE(op), new_args, const_args);
+ tcg_out_op(s, op->opc, type, new_args, const_args);
}
break;
}
@@ -1592,16 +1592,6 @@ static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn)
tcg_out_mov(s, TCG_TYPE_I32, rd, rn);
}
-static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
- TCGReg rn, int64_t aimm)
-{
- if (aimm >= 0) {
- tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
- } else {
- tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
- }
-}
-
static void tcg_out_addsub2(TCGContext *s, TCGType ext, TCGReg rl,
TCGReg rh, TCGReg al, TCGReg ah,
tcg_target_long bl, tcg_target_long bh,
@@ -2115,6 +2105,30 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
flush_idcache_range(jmp_rx, jmp_rw, 4);
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_insn(s, 3502, ADD, type, a0, a1, a2);
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ if (a2 >= 0) {
+ tcg_out_insn(s, 3401, ADDI, type, a0, a1, a2);
+ } else {
+ tcg_out_insn(s, 3401, SUBI, type, a0, a1, -a2);
+ }
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rA),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -2185,23 +2199,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext,
tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2, 3);
break;
- case INDEX_op_add_i32:
- a2 = (int32_t)a2;
- /* FALLTHRU */
- case INDEX_op_add_i64:
- if (c2) {
- tcg_out_addsubi(s, ext, a0, a1, a2);
- } else {
- tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
- }
- break;
-
case INDEX_op_sub_i32:
- a2 = (int32_t)a2;
- /* FALLTHRU */
case INDEX_op_sub_i64:
if (c2) {
- tcg_out_addsubi(s, ext, a0, a1, -a2);
+ tgen_addi(s, ext, a0, a1, -a2);
} else {
tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
}
@@ -2996,8 +2997,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(rZ, r);
- case INDEX_op_add_i32:
- case INDEX_op_add_i64:
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
return C_O1_I2(r, r, rA);
@@ -896,6 +896,17 @@ static void tcg_out_dat_rIK(TCGContext *s, ARMCond cond, ARMInsn opc,
}
}
+static void tcg_out_dat_IN(TCGContext *s, ARMCond cond, ARMInsn opc,
+ ARMInsn opneg, TCGReg dst, TCGReg lhs, TCGArg rhs)
+{
+ int imm12 = encode_imm(rhs);
+ if (imm12 < 0) {
+ imm12 = encode_imm_nofail(-rhs);
+ opc = opneg;
+ }
+ tcg_out_dat_imm(s, cond, opc, dst, lhs, imm12);
+}
+
static void tcg_out_dat_rIN(TCGContext *s, ARMCond cond, ARMInsn opc,
ARMInsn opneg, TCGReg dst, TCGReg lhs, TCGArg rhs,
bool rhs_is_const)
@@ -904,12 +915,7 @@ static void tcg_out_dat_rIN(TCGContext *s, ARMCond cond, ARMInsn opc,
* rhs must satisfy the "rIN" constraint.
*/
if (rhs_is_const) {
- int imm12 = encode_imm(rhs);
- if (imm12 < 0) {
- imm12 = encode_imm_nofail(-rhs);
- opc = opneg;
- }
- tcg_out_dat_imm(s, cond, opc, dst, lhs, imm12);
+ tcg_out_dat_IN(s, cond, opc, opneg, dst, lhs, rhs);
} else {
tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
}
@@ -1847,6 +1853,26 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
flush_idcache_range(jmp_rx, jmp_rw, 4);
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_dat_reg(s, COND_AL, ARITH_ADD, a0, a1, a2, SHIFT_IMM_LSL(0));
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_dat_IN(s, COND_AL, ARITH_ADD, ARITH_SUB, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rIN),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -1895,10 +1921,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[c], ARITH_MOV,
ARITH_MVN, args[0], 0, args[3], const_args[3]);
break;
- case INDEX_op_add_i32:
- tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
- args[0], args[1], args[2], const_args[2]);
- break;
case INDEX_op_sub_i32:
if (const_args[1]) {
if (const_args[2]) {
@@ -2186,7 +2208,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
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:
case INDEX_op_negsetcond_i32:
@@ -2627,6 +2627,40 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
/* no need to flush icache explicitly */
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
+
+ if (a0 == a1) {
+ tgen_arithr(s, ARITH_ADD + rexw, a0, a2);
+ } else if (a0 == a2) {
+ tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
+ } else {
+ tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, 0);
+ }
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
+
+ if (a0 == a1) {
+ tgen_arithi(s, ARITH_ADD + rexw, a0, a2, false);
+ } else {
+ tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, -1, 0, a2);
+ }
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, re),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -2708,24 +2742,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
break;
- OP_32_64(add):
- /* For 3-operand addition, use LEA. */
- if (a0 != a1) {
- TCGArg c3 = 0;
- if (const_a2) {
- c3 = a2, a2 = -1;
- } else if (a0 == a2) {
- /* Watch out for dest = src + dest, since we've removed
- the matching constraint on the add. */
- tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
- break;
- }
-
- tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
- break;
- }
- c = ARITH_ADD;
- goto gen_arith;
OP_32_64(sub):
c = ARITH_SUB;
goto gen_arith;
@@ -3694,10 +3710,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(re, r);
- case INDEX_op_add_i32:
- case INDEX_op_add_i64:
- return C_O1_I2(r, r, re);
-
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
case INDEX_op_mul_i32:
@@ -1278,6 +1278,24 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
flush_idcache_range(jmp_rx, jmp_rw, 4);
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ if (type == TCG_TYPE_I32) {
+ tcg_out_opc_add_w(s, a0, a1, a2);
+ } else {
+ tcg_out_opc_add_d(s, a0, a1, a2);
+ }
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rJ),
+ .out_rrr = tgen_add,
+ .out_rri = tcg_out_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -1536,21 +1554,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
break;
- case INDEX_op_add_i32:
- if (c2) {
- tcg_out_addi(s, TCG_TYPE_I32, a0, a1, a2);
- } else {
- tcg_out_opc_add_w(s, a0, a1, a2);
- }
- break;
- case INDEX_op_add_i64:
- if (c2) {
- tcg_out_addi(s, TCG_TYPE_I64, a0, a1, a2);
- } else {
- tcg_out_opc_add_d(s, a0, a1, a2);
- }
- break;
-
case INDEX_op_sub_i32:
if (c2) {
tcg_out_addi(s, TCG_TYPE_I32, a0, a1, -a2);
@@ -2297,11 +2300,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_rotr_i64:
return C_O1_I2(r, r, ri);
- case INDEX_op_add_i32:
- return C_O1_I2(r, r, ri);
- case INDEX_op_add_i64:
- return C_O1_I2(r, r, rJ);
-
case INDEX_op_and_i32:
case INDEX_op_and_i64:
case INDEX_op_nor_i32:
@@ -1678,6 +1678,28 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
/* Always indirect, nothing to do */
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ADDU : OPC_DADDU;
+ tcg_out_opc_reg(s, insn, a0, a1, a2);
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ADDIU : OPC_DADDIU;
+ tcg_out_opc_imm(s, insn, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rJ),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -1755,12 +1777,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_ldst(s, i1, a0, a1, a2);
break;
- case INDEX_op_add_i32:
- i1 = OPC_ADDU, i2 = OPC_ADDIU;
- goto do_binary;
- case INDEX_op_add_i64:
- i1 = OPC_DADDU, i2 = OPC_DADDIU;
- goto do_binary;
case INDEX_op_or_i32:
case INDEX_op_or_i64:
i1 = OPC_OR, i2 = OPC_ORI;
@@ -2213,9 +2229,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(rZ, r);
- case INDEX_op_add_i32:
- case INDEX_op_add_i64:
- return C_O1_I2(r, r, rJ);
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
return C_O1_I2(r, rZ, rN);
@@ -2940,6 +2940,26 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
flush_idcache_range(jmp_rx, jmp_rw, 4);
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out32(s, ADD | TAB(a0, a1, a2));
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rT),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -3009,15 +3029,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_mem_long(s, STD, STDX, args[0], args[1], args[2]);
break;
- case INDEX_op_add_i32:
- a0 = args[0], a1 = args[1], a2 = args[2];
- if (const_args[2]) {
- do_addi_32:
- tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
- } else {
- tcg_out32(s, ADD | TAB(a0, a1, a2));
- }
- break;
case INDEX_op_sub_i32:
a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[1]) {
@@ -3027,8 +3038,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
}
} else if (const_args[2]) {
- a2 = -a2;
- goto do_addi_32;
+ tgen_addi(s, type, a0, a1, (int32_t)-a2);
} else {
tcg_out32(s, SUBF | TAB(a0, a2, a1));
}
@@ -3223,15 +3233,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out32(s, NOR | SAB(args[1], args[0], args[1]));
break;
- case INDEX_op_add_i64:
- a0 = args[0], a1 = args[1], a2 = args[2];
- if (const_args[2]) {
- do_addi_64:
- tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
- } else {
- tcg_out32(s, ADD | TAB(a0, a1, a2));
- }
- break;
case INDEX_op_sub_i64:
a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[1]) {
@@ -3241,8 +3242,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
}
} else if (const_args[2]) {
- a2 = -a2;
- goto do_addi_64;
+ tgen_addi(s, type, a0, a1, -a2);
} else {
tcg_out32(s, SUBF | TAB(a0, a2, a1));
}
@@ -4203,7 +4203,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(r, r);
- case INDEX_op_add_i32:
case INDEX_op_and_i32:
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
@@ -4250,8 +4249,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_sub_i32:
return C_O1_I2(r, rI, ri);
- case INDEX_op_add_i64:
- return C_O1_I2(r, r, rT);
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
return C_O1_I2(r, r, rU);
@@ -1960,6 +1960,28 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
flush_idcache_range(jmp_rx, jmp_rw, 4);
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ RISCVInsn insn = type == TCG_TYPE_I32 ? OPC_ADDW : OPC_ADD;
+ tcg_out_opc_reg(s, insn, a0, a1, a2);
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ RISCVInsn insn = type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI;
+ tcg_out_opc_imm(s, insn, a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rI),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -2022,21 +2044,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_ldst(s, OPC_SD, a0, a1, a2);
break;
- case INDEX_op_add_i32:
- if (c2) {
- tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
- } else {
- tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
- }
- break;
- case INDEX_op_add_i64:
- if (c2) {
- tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
- } else {
- tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
- }
- break;
-
case INDEX_op_sub_i32:
if (c2) {
tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
@@ -2658,11 +2665,9 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(rZ, r);
- case INDEX_op_add_i32:
case INDEX_op_and_i32:
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
- case INDEX_op_add_i64:
case INDEX_op_and_i64:
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
@@ -2145,6 +2145,58 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
/* no need to flush icache explicitly */
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ if (a0 != a1) {
+ tcg_out_insn(s, RX, LA, a0, a1, a2, 0);
+ } else if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RR, AR, a0, a2);
+ } else {
+ tcg_out_insn(s, RRE, AGR, a0, a2);
+ }
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ if (a0 == a1) {
+ if (type == TCG_TYPE_I32) {
+ if (a2 == (int16_t)a2) {
+ tcg_out_insn(s, RI, AHI, a0, a2);
+ } else {
+ tcg_out_insn(s, RIL, AFI, a0, a2);
+ }
+ return;
+ }
+ if (a2 == (int16_t)a2) {
+ tcg_out_insn(s, RI, AGHI, a0, a2);
+ return;
+ }
+ if (a2 == (int32_t)a2) {
+ tcg_out_insn(s, RIL, AGFI, a0, a2);
+ return;
+ }
+ if (a2 == (uint32_t)a2) {
+ tcg_out_insn(s, RIL, ALGFI, a0, a2);
+ return;
+ }
+ if (-a2 == (uint32_t)-a2) {
+ tcg_out_insn(s, RIL, SLGFI, a0, -a2);
+ return;
+ }
+ }
+ tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, ri),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
# define OP_32_64(x) \
case glue(glue(INDEX_op_,x),_i32): \
case glue(glue(INDEX_op_,x),_i64)
@@ -2201,30 +2253,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
- case INDEX_op_add_i32:
- a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
- if (const_args[2]) {
- do_addi_32:
- if (a0 == a1) {
- if (a2 == (int16_t)a2) {
- tcg_out_insn(s, RI, AHI, a0, a2);
- break;
- }
- tcg_out_insn(s, RIL, AFI, a0, a2);
- break;
- }
- tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
- } else if (a0 == a1) {
- tcg_out_insn(s, RR, AR, a0, a2);
- } else {
- tcg_out_insn(s, RX, LA, a0, a1, a2, 0);
- }
- break;
case INDEX_op_sub_i32:
- a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
+ a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[2]) {
- a2 = -a2;
- goto do_addi_32;
+ tgen_addi(s, type, a0, a1, (int32_t)-a2);
} else if (a0 == a1) {
tcg_out_insn(s, RR, SR, a0, a2);
} else {
@@ -2500,40 +2532,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
break;
- case INDEX_op_add_i64:
- a0 = args[0], a1 = args[1], a2 = args[2];
- if (const_args[2]) {
- do_addi_64:
- if (a0 == a1) {
- if (a2 == (int16_t)a2) {
- tcg_out_insn(s, RI, AGHI, a0, a2);
- break;
- }
- if (a2 == (int32_t)a2) {
- tcg_out_insn(s, RIL, AGFI, a0, a2);
- break;
- }
- if (a2 == (uint32_t)a2) {
- tcg_out_insn(s, RIL, ALGFI, a0, a2);
- break;
- }
- if (-a2 == (uint32_t)-a2) {
- tcg_out_insn(s, RIL, SLGFI, a0, -a2);
- break;
- }
- }
- tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
- } else if (a0 == a1) {
- tcg_out_insn(s, RRE, AGR, a0, a2);
- } else {
- tcg_out_insn(s, RX, LA, a0, a1, a2, 0);
- }
- break;
case INDEX_op_sub_i64:
a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[2]) {
- a2 = -a2;
- goto do_addi_64;
+ tgen_addi(s, type, a0, a1, -a2);
} else {
tcg_out_insn(s, RRFa, SGRK, a0, a1, a2);
}
@@ -3259,8 +3261,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(r, r);
- case INDEX_op_add_i32:
- case INDEX_op_add_i64:
case INDEX_op_shl_i64:
case INDEX_op_shr_i64:
case INDEX_op_sar_i64:
@@ -1288,6 +1288,26 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
{
}
+
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_arith(s, a0, a1, a2, ARITH_ADD);
+}
+
+static void tgen_addi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_arithi(s, a0, a1, a2, ARITH_ADD);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, rJ),
+ .out_rrr = tgen_add,
+ .out_rri = tgen_addi,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -1341,9 +1361,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
case INDEX_op_st32_i64:
tcg_out_ldst(s, a0, a1, a2, STW);
break;
- OP_32_64(add):
- c = ARITH_ADD;
- goto gen_arith;
OP_32_64(sub):
c = ARITH_SUB;
goto gen_arith;
@@ -1575,8 +1592,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_qemu_st_a64_i64:
return C_O0_I2(rZ, r);
- case INDEX_op_add_i32:
- case INDEX_op_add_i64:
case INDEX_op_mul_i32:
case INDEX_op_mul_i64:
case INDEX_op_div_i32:
@@ -91,8 +91,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_rem_i64:
case INDEX_op_remu_i32:
case INDEX_op_remu_i64:
- 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:
@@ -665,6 +663,18 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
/* Always indirect, nothing to do */
}
+static void tgen_add(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_op_rrr(s, glue(INDEX_op_add_i,TCG_TARGET_REG_BITS), a0, a1, a2);
+}
+
+static const TCGOutOpBinary outop_add = {
+ .base.static_constraint = C_O1_I2(r, r, r),
+ .out_rrr = tgen_add,
+};
+
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -706,7 +716,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_ldst(s, opc, args[0], args[1], args[2]);
break;
- CASE_32_64(add)
CASE_32_64(sub)
CASE_32_64(mul)
CASE_32_64(and)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- tcg/sparc64/tcg-target-con-set.h | 1 + tcg/tcg.c | 39 ++++++++++- tcg/aarch64/tcg-target.c.inc | 51 +++++++------- tcg/arm/tcg-target.c.inc | 43 ++++++++---- tcg/i386/tcg-target.c.inc | 56 +++++++++------- tcg/loongarch64/tcg-target.c.inc | 38 +++++------ tcg/mips/tcg-target.c.inc | 31 ++++++--- tcg/ppc/tcg-target.c.inc | 47 +++++++------ tcg/riscv/tcg-target.c.inc | 39 ++++++----- tcg/s390x/tcg-target.c.inc | 110 +++++++++++++++---------------- tcg/sparc64/tcg-target.c.inc | 25 +++++-- tcg/tci/tcg-target.c.inc | 15 ++++- 12 files changed, 300 insertions(+), 195 deletions(-)