@@ -22,6 +22,7 @@ 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, r)
C_O1_I2(r, 0, ri)
C_O1_I2(r, 0, rI)
C_O1_I2(r, 0, rJ)
@@ -32,6 +33,7 @@ C_O1_I2(r, r, rI)
C_O1_I2(r, r, rJ)
C_O1_I2(r, r, rK)
C_O1_I2(r, r, rNKR)
+C_O1_I2(r, r, rUV)
C_O1_I2(r, rZ, r)
C_O1_I2(v, v, r)
C_O1_I2(v, v, v)
@@ -173,6 +173,8 @@ typedef enum S390Opcode {
RRE_SLBGR = 0xb989,
RRE_XGR = 0xb982,
+ RRFa_ALRK = 0xb9fa,
+ RRFa_ALGRK = 0xb9ea,
RRFa_MGRK = 0xb9ec,
RRFa_MSRKC = 0xb9fd,
RRFa_MSGRKC = 0xb9ed,
@@ -2259,21 +2261,60 @@ static const TCGOutOpBinary outop_add = {
.out_rri = tgen_addi,
};
+static void tgen_addco_rrr(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ if (type != TCG_TYPE_I32) {
+ tcg_out_insn(s, RRFa, ALGRK, a0, a1, a2);
+ } else if (a0 == a1) {
+ tcg_out_insn(s, RR, ALR, a0, a2);
+ } else {
+ tcg_out_insn(s, RRFa, ALRK, a0, a1, a2);
+ }
+}
+
+static void tgen_addco_rri(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_mov(s, type, a0, a1);
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RIL, ALFI, a0, a2);
+ } else if (a2 >= 0) {
+ tcg_out_insn(s, RIL, ALGFI, a0, a2);
+ } else {
+ tcg_out_insn(s, RIL, SLGFI, a0, -a2);
+ }
+}
+
static const TCGOutOpBinary outop_addco = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_O1_I2(r, r, rUV),
+ .out_rrr = tgen_addco_rrr,
+ .out_rri = tgen_addco_rri,
+};
+
+static void tgen_addcio(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RRE, ALCR, a0, a2);
+ } else {
+ tcg_out_insn(s, RRE, ALCGR, a0, a2);
+ }
+}
+
+static const TCGOutOpBinary outop_addcio = {
+ .base.static_constraint = C_O1_I2(r, 0, r),
+ .out_rrr = tgen_addcio,
};
static const TCGOutOpAddSubCarry outop_addci = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpBinary outop_addcio = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_O1_I2(r, 0, r),
+ .out_rrr = tgen_addcio,
};
static void tcg_out_set_carry(TCGContext *s)
{
- g_assert_not_reached();
+ tcg_out_insn(s, RR, SLR, TCG_REG_R0, TCG_REG_R0); /* cc = 2 */
}
static void tgen_and(TCGContext *s, TCGType type,
@@ -2794,21 +2835,57 @@ static const TCGOutOpSubtract outop_sub = {
.out_rrr = tgen_sub,
};
+static void tgen_subbo_rrr(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ if (type != TCG_TYPE_I32) {
+ tcg_out_insn(s, RRFa, SLGRK, a0, a1, a2);
+ } else if (a0 == a1) {
+ tcg_out_insn(s, RR, SLR, a0, a2);
+ } else {
+ tcg_out_insn(s, RRFa, SLRK, a0, a1, a2);
+ }
+}
+
+static void tgen_subbo_rri(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_mov(s, type, a0, a1);
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RIL, SLFI, a0, a2);
+ } else if (a2 >= 0) {
+ tcg_out_insn(s, RIL, SLGFI, a0, a2);
+ } else {
+ tcg_out_insn(s, RIL, ALGFI, a0, -a2);
+ }
+}
+
static const TCGOutOpAddSubCarry outop_subbo = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_O1_I2(r, r, rUV),
+ .out_rrr = tgen_subbo_rrr,
+ .out_rri = tgen_subbo_rri,
};
-static const TCGOutOpAddSubCarry outop_subbi = {
- .base.static_constraint = C_NotImplemented,
-};
+static void tgen_subbio(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RRE, SLBR, a0, a2);
+ } else {
+ tcg_out_insn(s, RRE, SLBGR, a0, a2);
+ }
+}
static const TCGOutOpAddSubCarry outop_subbio = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_O1_I2(r, 0, r),
+ .out_rrr = tgen_subbio,
};
+#define outop_subbi outop_subbio
+
static void tcg_out_set_borrow(TCGContext *s)
{
- g_assert_not_reached();
+ tcg_out_insn(s, RR, CLR, TCG_REG_R0, TCG_REG_R0); /* cc = 0 */
}
static void tgen_xor(TCGContext *s, TCGType type,
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- tcg/s390x/tcg-target-con-set.h | 2 + tcg/s390x/tcg-target.c.inc | 103 ++++++++++++++++++++++++++++----- 2 files changed, 92 insertions(+), 13 deletions(-)