mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 08:13:54 -06:00
tcg: Convert div2 to TCGOutOpDivRem
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
961b80aecd
commit
d6cad9c927
11 changed files with 88 additions and 29 deletions
|
@ -2168,6 +2168,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1880,6 +1880,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2637,6 +2637,18 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.base.static_constraint = C_NotImplemented,
|
.base.static_constraint = C_NotImplemented,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void tgen_divs2(TCGContext *s, TCGType type,
|
||||||
|
TCGReg a0, TCGReg a1, TCGReg a4)
|
||||||
|
{
|
||||||
|
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
|
||||||
|
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, a4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_O2_I3(a, d, 0, 1, r),
|
||||||
|
.out_rr01r = tgen_divs2,
|
||||||
|
};
|
||||||
|
|
||||||
static const TCGOutOpBinary outop_divu = {
|
static const TCGOutOpBinary outop_divu = {
|
||||||
.base.static_constraint = C_NotImplemented,
|
.base.static_constraint = C_NotImplemented,
|
||||||
};
|
};
|
||||||
|
@ -2847,9 +2859,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
OP_32_64(div2):
|
|
||||||
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
|
|
||||||
break;
|
|
||||||
OP_32_64(divu2):
|
OP_32_64(divu2):
|
||||||
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
|
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
|
||||||
break;
|
break;
|
||||||
|
@ -3789,8 +3798,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
|
||||||
case INDEX_op_movcond_i64:
|
case INDEX_op_movcond_i64:
|
||||||
return C_O1_I4(r, r, reT, r, 0);
|
return C_O1_I4(r, r, reT, r, 0);
|
||||||
|
|
||||||
case INDEX_op_div2_i32:
|
|
||||||
case INDEX_op_div2_i64:
|
|
||||||
case INDEX_op_divu2_i32:
|
case INDEX_op_divu2_i32:
|
||||||
case INDEX_op_divu2_i64:
|
case INDEX_op_divu2_i64:
|
||||||
return C_O2_I3(a, d, 0, 1, r);
|
return C_O2_I3(a, d, 0, 1, r);
|
||||||
|
|
|
@ -1343,6 +1343,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1733,6 +1733,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2972,6 +2972,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2009,6 +2009,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2246,6 +2246,28 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.base.static_constraint = C_NotImplemented,
|
.base.static_constraint = C_NotImplemented,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void tgen_divs2(TCGContext *s, TCGType type,
|
||||||
|
TCGReg a0, TCGReg a1, TCGReg a4)
|
||||||
|
{
|
||||||
|
tcg_debug_assert((a1 & 1) == 0);
|
||||||
|
tcg_debug_assert(a0 == a1 + 1);
|
||||||
|
if (type == TCG_TYPE_I32) {
|
||||||
|
tcg_out_insn(s, RR, DR, a1, a4);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* TODO: Move the sign-extend of the numerator from a2 into a3
|
||||||
|
* into the tcg backend, instead of in early expansion. It is
|
||||||
|
* required for 32-bit DR, but not 64-bit DSGR.
|
||||||
|
*/
|
||||||
|
tcg_out_insn(s, RRE, DSGR, a1, a4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_O2_I3(o, m, 0, 1, r),
|
||||||
|
.out_rr01r = tgen_divs2,
|
||||||
|
};
|
||||||
|
|
||||||
static const TCGOutOpBinary outop_divu = {
|
static const TCGOutOpBinary outop_divu = {
|
||||||
.base.static_constraint = C_NotImplemented,
|
.base.static_constraint = C_NotImplemented,
|
||||||
};
|
};
|
||||||
|
@ -2527,13 +2549,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]);
|
tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_div2_i32:
|
|
||||||
tcg_debug_assert(args[0] == args[2]);
|
|
||||||
tcg_debug_assert(args[1] == args[3]);
|
|
||||||
tcg_debug_assert((args[1] & 1) == 0);
|
|
||||||
tcg_debug_assert(args[0] == args[1] + 1);
|
|
||||||
tcg_out_insn(s, RR, DR, args[1], args[4]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_divu2_i32:
|
case INDEX_op_divu2_i32:
|
||||||
tcg_debug_assert(args[0] == args[2]);
|
tcg_debug_assert(args[0] == args[2]);
|
||||||
tcg_debug_assert(args[1] == args[3]);
|
tcg_debug_assert(args[1] == args[3]);
|
||||||
|
@ -2702,19 +2717,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
|
||||||
tcg_out_insn(s, RRE, LRVGR, args[0], args[1]);
|
tcg_out_insn(s, RRE, LRVGR, args[0], args[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_div2_i64:
|
|
||||||
/*
|
|
||||||
* ??? We get an unnecessary sign-extension of the dividend
|
|
||||||
* into op0 with this definition, but as we do in fact always
|
|
||||||
* produce both quotient and remainder using INDEX_op_div_i64
|
|
||||||
* instead requires jumping through even more hoops.
|
|
||||||
*/
|
|
||||||
tcg_debug_assert(args[0] == args[2]);
|
|
||||||
tcg_debug_assert(args[1] == args[3]);
|
|
||||||
tcg_debug_assert((args[1] & 1) == 0);
|
|
||||||
tcg_debug_assert(args[0] == args[1] + 1);
|
|
||||||
tcg_out_insn(s, RRE, DSGR, args[1], args[4]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_divu2_i64:
|
case INDEX_op_divu2_i64:
|
||||||
tcg_debug_assert(args[0] == args[2]);
|
tcg_debug_assert(args[0] == args[2]);
|
||||||
tcg_debug_assert(args[1] == args[3]);
|
tcg_debug_assert(args[1] == args[3]);
|
||||||
|
@ -3396,8 +3398,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
|
||||||
case INDEX_op_movcond_i64:
|
case INDEX_op_movcond_i64:
|
||||||
return C_O1_I4(r, r, rC, rI, r);
|
return C_O1_I4(r, r, rC, rI, r);
|
||||||
|
|
||||||
case INDEX_op_div2_i32:
|
|
||||||
case INDEX_op_div2_i64:
|
|
||||||
case INDEX_op_divu2_i32:
|
case INDEX_op_divu2_i32:
|
||||||
case INDEX_op_divu2_i64:
|
case INDEX_op_divu2_i64:
|
||||||
return C_O2_I3(o, m, 0, 1, r);
|
return C_O2_I3(o, m, 0, 1, r);
|
||||||
|
|
|
@ -1352,6 +1352,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rri = tgen_divsi,
|
.out_rri = tgen_divsi,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu_rJ(TCGContext *s, TCGType type,
|
static void tgen_divu_rJ(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGArg a2, bool c2)
|
TCGReg a0, TCGReg a1, TCGArg a2, bool c2)
|
||||||
{
|
{
|
||||||
|
|
24
tcg/tcg.c
24
tcg/tcg.c
|
@ -986,6 +986,12 @@ typedef struct TCGOutOpBinary {
|
||||||
TCGReg a0, TCGReg a1, tcg_target_long a2);
|
TCGReg a0, TCGReg a1, tcg_target_long a2);
|
||||||
} TCGOutOpBinary;
|
} TCGOutOpBinary;
|
||||||
|
|
||||||
|
typedef struct TCGOutOpDivRem {
|
||||||
|
TCGOutOp base;
|
||||||
|
void (*out_rr01r)(TCGContext *s, TCGType type,
|
||||||
|
TCGReg a0, TCGReg a1, TCGReg a4);
|
||||||
|
} TCGOutOpDivRem;
|
||||||
|
|
||||||
typedef struct TCGOutOpUnary {
|
typedef struct TCGOutOpUnary {
|
||||||
TCGOutOp base;
|
TCGOutOp base;
|
||||||
void (*out_rr)(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1);
|
void (*out_rr)(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1);
|
||||||
|
@ -1022,6 +1028,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
|
||||||
OUTOP(INDEX_op_andc, TCGOutOpBinary, outop_andc),
|
OUTOP(INDEX_op_andc, TCGOutOpBinary, outop_andc),
|
||||||
OUTOP(INDEX_op_divs, TCGOutOpBinary, outop_divs),
|
OUTOP(INDEX_op_divs, TCGOutOpBinary, outop_divs),
|
||||||
OUTOP(INDEX_op_divu, TCGOutOpBinary, outop_divu),
|
OUTOP(INDEX_op_divu, TCGOutOpBinary, outop_divu),
|
||||||
|
OUTOP(INDEX_op_div2_i32, TCGOutOpDivRem, outop_divs2),
|
||||||
|
OUTOP(INDEX_op_div2_i64, TCGOutOpDivRem, outop_divs2),
|
||||||
OUTOP(INDEX_op_eqv, TCGOutOpBinary, outop_eqv),
|
OUTOP(INDEX_op_eqv, TCGOutOpBinary, outop_eqv),
|
||||||
OUTOP(INDEX_op_mul, TCGOutOpBinary, outop_mul),
|
OUTOP(INDEX_op_mul, TCGOutOpBinary, outop_mul),
|
||||||
OUTOP(INDEX_op_mulsh, TCGOutOpBinary, outop_mulsh),
|
OUTOP(INDEX_op_mulsh, TCGOutOpBinary, outop_mulsh),
|
||||||
|
@ -2265,7 +2273,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
|
||||||
case INDEX_op_rem_i32:
|
case INDEX_op_rem_i32:
|
||||||
case INDEX_op_remu_i32:
|
case INDEX_op_remu_i32:
|
||||||
return TCG_TARGET_HAS_rem_i32;
|
return TCG_TARGET_HAS_rem_i32;
|
||||||
case INDEX_op_div2_i32:
|
|
||||||
case INDEX_op_divu2_i32:
|
case INDEX_op_divu2_i32:
|
||||||
return TCG_TARGET_HAS_div2_i32;
|
return TCG_TARGET_HAS_div2_i32;
|
||||||
case INDEX_op_rotl_i32:
|
case INDEX_op_rotl_i32:
|
||||||
|
@ -2325,7 +2332,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
|
||||||
case INDEX_op_rem_i64:
|
case INDEX_op_rem_i64:
|
||||||
case INDEX_op_remu_i64:
|
case INDEX_op_remu_i64:
|
||||||
return TCG_TARGET_HAS_rem_i64;
|
return TCG_TARGET_HAS_rem_i64;
|
||||||
case INDEX_op_div2_i64:
|
|
||||||
case INDEX_op_divu2_i64:
|
case INDEX_op_divu2_i64:
|
||||||
return TCG_TARGET_HAS_div2_i64;
|
return TCG_TARGET_HAS_div2_i64;
|
||||||
case INDEX_op_rotl_i64:
|
case INDEX_op_rotl_i64:
|
||||||
|
@ -5467,6 +5473,20 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case INDEX_op_div2_i32:
|
||||||
|
case INDEX_op_div2_i64:
|
||||||
|
{
|
||||||
|
const TCGOutOpDivRem *out =
|
||||||
|
container_of(all_outop[op->opc], TCGOutOpDivRem, base);
|
||||||
|
|
||||||
|
/* Only used by x86 and s390x, which use matching constraints. */
|
||||||
|
tcg_debug_assert(new_args[0] == new_args[2]);
|
||||||
|
tcg_debug_assert(new_args[1] == new_args[3]);
|
||||||
|
tcg_debug_assert(!const_args[4]);
|
||||||
|
out->out_rr01r(s, type, new_args[0], new_args[1], new_args[4]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (def->flags & TCG_OPF_VECTOR) {
|
if (def->flags & TCG_OPF_VECTOR) {
|
||||||
tcg_out_vec_op(s, op->opc, type - TCG_TYPE_V64,
|
tcg_out_vec_op(s, op->opc, type - TCG_TYPE_V64,
|
||||||
|
|
|
@ -658,6 +658,10 @@ static const TCGOutOpBinary outop_divs = {
|
||||||
.out_rrr = tgen_divs,
|
.out_rrr = tgen_divs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TCGOutOpDivRem outop_divs2 = {
|
||||||
|
.base.static_constraint = C_NotImplemented,
|
||||||
|
};
|
||||||
|
|
||||||
static void tgen_divu(TCGContext *s, TCGType type,
|
static void tgen_divu(TCGContext *s, TCGType type,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2)
|
TCGReg a0, TCGReg a1, TCGReg a2)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue