mirror of
https://github.com/Motorhead1991/qemu.git
synced 2026-02-06 16:20:43 -07:00
tcg/s390x: Implement add/sub carry opcodes
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
19b9fc2a39
commit
cda7f93fa2
3 changed files with 96 additions and 69 deletions
|
|
@ -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)
|
||||
|
|
@ -43,5 +45,3 @@ C_O2_I1(o, m, r)
|
|||
C_O2_I2(o, m, 0, r)
|
||||
C_O2_I2(o, m, r, r)
|
||||
C_O2_I3(o, m, 0, 1, r)
|
||||
C_N1_O1_I4(r, r, 0, 1, ri, r)
|
||||
C_N1_O1_I4(r, r, 0, 1, rUV, r)
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ extern uint64_t s390_facilities[3];
|
|||
((s390_facilities[FACILITY_##X / 64] >> (63 - FACILITY_##X % 64)) & 1)
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 0
|
||||
#define TCG_TARGET_HAS_sub2_i32 0
|
||||
#define TCG_TARGET_HAS_extr_i64_i32 0
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 0
|
||||
#define TCG_TARGET_HAS_sub2_i64 0
|
||||
|
||||
#define TCG_TARGET_HAS_qemu_ldst_i128 1
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -2967,23 +3044,6 @@ 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_add2_i32:
|
||||
if (const_args[4]) {
|
||||
tcg_out_insn(s, RIL, ALFI, args[0], args[4]);
|
||||
} else {
|
||||
tcg_out_insn(s, RR, ALR, args[0], args[4]);
|
||||
}
|
||||
tcg_out_insn(s, RRE, ALCR, args[1], args[5]);
|
||||
break;
|
||||
case INDEX_op_sub2_i32:
|
||||
if (const_args[4]) {
|
||||
tcg_out_insn(s, RIL, SLFI, args[0], args[4]);
|
||||
} else {
|
||||
tcg_out_insn(s, RR, SLR, args[0], args[4]);
|
||||
}
|
||||
tcg_out_insn(s, RRE, SLBR, args[1], args[5]);
|
||||
break;
|
||||
|
||||
case INDEX_op_br:
|
||||
tgen_branch(s, S390_CC_ALWAYS, arg_label(args[0]));
|
||||
break;
|
||||
|
|
@ -3027,31 +3087,6 @@ 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_add2_i64:
|
||||
if (const_args[4]) {
|
||||
if ((int64_t)args[4] >= 0) {
|
||||
tcg_out_insn(s, RIL, ALGFI, args[0], args[4]);
|
||||
} else {
|
||||
tcg_out_insn(s, RIL, SLGFI, args[0], -args[4]);
|
||||
}
|
||||
} else {
|
||||
tcg_out_insn(s, RRE, ALGR, args[0], args[4]);
|
||||
}
|
||||
tcg_out_insn(s, RRE, ALCGR, args[1], args[5]);
|
||||
break;
|
||||
case INDEX_op_sub2_i64:
|
||||
if (const_args[4]) {
|
||||
if ((int64_t)args[4] >= 0) {
|
||||
tcg_out_insn(s, RIL, SLGFI, args[0], args[4]);
|
||||
} else {
|
||||
tcg_out_insn(s, RIL, ALGFI, args[0], -args[4]);
|
||||
}
|
||||
} else {
|
||||
tcg_out_insn(s, RRE, SLGR, args[0], args[4]);
|
||||
}
|
||||
tcg_out_insn(s, RRE, SLBGR, args[1], args[5]);
|
||||
break;
|
||||
|
||||
case INDEX_op_mb:
|
||||
/* The host memory model is quite strong, we simply need to
|
||||
serialize the instruction stream. */
|
||||
|
|
@ -3546,14 +3581,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
|
|||
case INDEX_op_qemu_st_i128:
|
||||
return C_O0_I3(o, m, r);
|
||||
|
||||
case INDEX_op_add2_i32:
|
||||
case INDEX_op_sub2_i32:
|
||||
return C_N1_O1_I4(r, r, 0, 1, ri, r);
|
||||
|
||||
case INDEX_op_add2_i64:
|
||||
case INDEX_op_sub2_i64:
|
||||
return C_N1_O1_I4(r, r, 0, 1, rUV, r);
|
||||
|
||||
case INDEX_op_st_vec:
|
||||
return C_O0_I2(v, r);
|
||||
case INDEX_op_ld_vec:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue