mirror of https://gitee.com/openkylin/qemu.git
tcg-sparc: Support addsub2_i64
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
b60a7726cc
commit
609ac1e164
|
@ -719,9 +719,9 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh,
|
static void tcg_out_addsub2_i32(TCGContext *s, TCGReg rl, TCGReg rh,
|
||||||
TCGReg al, TCGReg ah, int32_t bl, int blconst,
|
TCGReg al, TCGReg ah, int32_t bl, int blconst,
|
||||||
int32_t bh, int bhconst, int opl, int oph)
|
int32_t bh, int bhconst, int opl, int oph)
|
||||||
{
|
{
|
||||||
TCGReg tmp = TCG_REG_T1;
|
TCGReg tmp = TCG_REG_T1;
|
||||||
|
|
||||||
|
@ -735,6 +735,51 @@ static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh,
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
|
tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_addsub2_i64(TCGContext *s, TCGReg rl, TCGReg rh,
|
||||||
|
TCGReg al, TCGReg ah, int32_t bl, int blconst,
|
||||||
|
int32_t bh, int bhconst, bool is_sub)
|
||||||
|
{
|
||||||
|
TCGReg tmp = TCG_REG_T1;
|
||||||
|
|
||||||
|
/* Note that the low parts are fully consumed before tmp is set. */
|
||||||
|
if (rl != ah && (bhconst || rl != bh)) {
|
||||||
|
tmp = rl;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_out_arithc(s, tmp, al, bl, blconst, is_sub ? ARITH_SUBCC : ARITH_ADDCC);
|
||||||
|
|
||||||
|
/* Note that ADDX/SUBX take the carry-in from %icc, the 32-bit carry,
|
||||||
|
while we want %xcc, the 64-bit carry. */
|
||||||
|
/* ??? There is a 2011 VIS3 ADDXC insn that does take a 64-bit carry. */
|
||||||
|
|
||||||
|
if (bh == TCG_REG_G0) {
|
||||||
|
/* If we have a zero, we can perform the operation in two insns,
|
||||||
|
with the arithmetic first, and a conditional move into place. */
|
||||||
|
if (rh == ah) {
|
||||||
|
tcg_out_arithi(s, TCG_REG_T2, ah, 1,
|
||||||
|
is_sub ? ARITH_SUB : ARITH_ADD);
|
||||||
|
tcg_out_movcc(s, TCG_COND_LTU, MOVCC_XCC, rh, TCG_REG_T2, 0);
|
||||||
|
} else {
|
||||||
|
tcg_out_arithi(s, rh, ah, 1, is_sub ? ARITH_SUB : ARITH_ADD);
|
||||||
|
tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, rh, ah, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Otherwise adjust BH as if there is carry into T2 ... */
|
||||||
|
if (bhconst) {
|
||||||
|
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_T2, bh + (is_sub ? -1 : 1));
|
||||||
|
} else {
|
||||||
|
tcg_out_arithi(s, TCG_REG_T2, bh, 1,
|
||||||
|
is_sub ? ARITH_SUB : ARITH_ADD);
|
||||||
|
}
|
||||||
|
/* ... smoosh T2 back to original BH if carry is clear ... */
|
||||||
|
tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, TCG_REG_T2, bh, bhconst);
|
||||||
|
/* ... and finally perform the arithmetic with the new operand. */
|
||||||
|
tcg_out_arith(s, rh, ah, TCG_REG_T2, is_sub ? ARITH_SUB : ARITH_ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I64, rl, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_call_nodelay(TCGContext *s, tcg_insn_unit *dest)
|
static void tcg_out_call_nodelay(TCGContext *s, tcg_insn_unit *dest)
|
||||||
{
|
{
|
||||||
ptrdiff_t disp = tcg_pcrel_diff(s, dest);
|
ptrdiff_t disp = tcg_pcrel_diff(s, dest);
|
||||||
|
@ -1264,12 +1309,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_add2_i32:
|
case INDEX_op_add2_i32:
|
||||||
tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], const_args[4],
|
tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3],
|
||||||
args[5], const_args[5], ARITH_ADDCC, ARITH_ADDX);
|
args[4], const_args[4], args[5], const_args[5],
|
||||||
|
ARITH_ADDCC, ARITH_ADDX);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_sub2_i32:
|
case INDEX_op_sub2_i32:
|
||||||
tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], const_args[4],
|
tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3],
|
||||||
args[5], const_args[5], ARITH_SUBCC, ARITH_SUBX);
|
args[4], const_args[4], args[5], const_args[5],
|
||||||
|
ARITH_SUBCC, ARITH_SUBX);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_mulu2_i32:
|
case INDEX_op_mulu2_i32:
|
||||||
c = ARITH_UMUL;
|
c = ARITH_UMUL;
|
||||||
|
@ -1351,6 +1398,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||||
case INDEX_op_movcond_i64:
|
case INDEX_op_movcond_i64:
|
||||||
tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
|
tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
|
||||||
break;
|
break;
|
||||||
|
case INDEX_op_add2_i64:
|
||||||
|
tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4],
|
||||||
|
const_args[4], args[5], const_args[5], false);
|
||||||
|
break;
|
||||||
|
case INDEX_op_sub2_i64:
|
||||||
|
tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4],
|
||||||
|
const_args[4], args[5], const_args[5], true);
|
||||||
|
break;
|
||||||
|
|
||||||
gen_arith:
|
gen_arith:
|
||||||
tcg_out_arithc(s, a0, a1, a2, c2, c);
|
tcg_out_arithc(s, a0, a1, a2, c2, c);
|
||||||
|
@ -1449,6 +1504,9 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
||||||
{ INDEX_op_setcond_i64, { "R", "RZ", "RJ" } },
|
{ INDEX_op_setcond_i64, { "R", "RZ", "RJ" } },
|
||||||
{ INDEX_op_movcond_i64, { "R", "RZ", "RJ", "RI", "0" } },
|
{ INDEX_op_movcond_i64, { "R", "RZ", "RJ", "RI", "0" } },
|
||||||
|
|
||||||
|
{ INDEX_op_add2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
|
||||||
|
{ INDEX_op_sub2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
|
||||||
|
|
||||||
{ INDEX_op_qemu_ld_i32, { "r", "A" } },
|
{ INDEX_op_qemu_ld_i32, { "r", "A" } },
|
||||||
{ INDEX_op_qemu_ld_i64, { "R", "A" } },
|
{ INDEX_op_qemu_ld_i64, { "R", "A" } },
|
||||||
{ INDEX_op_qemu_st_i32, { "sZ", "A" } },
|
{ INDEX_op_qemu_st_i32, { "sZ", "A" } },
|
||||||
|
|
|
@ -133,8 +133,8 @@ typedef enum {
|
||||||
#define TCG_TARGET_HAS_nor_i64 0
|
#define TCG_TARGET_HAS_nor_i64 0
|
||||||
#define TCG_TARGET_HAS_deposit_i64 0
|
#define TCG_TARGET_HAS_deposit_i64 0
|
||||||
#define TCG_TARGET_HAS_movcond_i64 1
|
#define TCG_TARGET_HAS_movcond_i64 1
|
||||||
#define TCG_TARGET_HAS_add2_i64 0
|
#define TCG_TARGET_HAS_add2_i64 1
|
||||||
#define TCG_TARGET_HAS_sub2_i64 0
|
#define TCG_TARGET_HAS_sub2_i64 1
|
||||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||||
#define TCG_TARGET_HAS_muls2_i64 0
|
#define TCG_TARGET_HAS_muls2_i64 0
|
||||||
#define TCG_TARGET_HAS_muluh_i64 0
|
#define TCG_TARGET_HAS_muluh_i64 0
|
||||||
|
|
Loading…
Reference in New Issue