tcg: Convert rem to TCGOutOpBinary

For TCI, we're losing type information in the interpreter.
Introduce a tci-specific opcode to handle the difference.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-01-07 18:52:30 -08:00
parent 8109598b68
commit 646f36fead
13 changed files with 115 additions and 57 deletions

View file

@ -2275,6 +2275,18 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static void tgen_rems(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
tcg_out_insn(s, 3508, SDIV, type, TCG_REG_TMP0, a1, a2);
tcg_out_insn(s, 3509, MSUB, type, a0, TCG_REG_TMP0, a2, a1);
}
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_rems,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
@ -2392,11 +2404,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext,
tcg_out_ldst(s, I3312_STRX, a0, a1, a2, 3);
break;
case INDEX_op_rem_i64:
case INDEX_op_rem_i32:
tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP0, a1, a2);
tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP0, a2, a1);
break;
case INDEX_op_remu_i64:
case INDEX_op_remu_i32:
tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP0, a1, a2);
@ -3078,8 +3085,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, r, rC);
case INDEX_op_rem_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i32:
case INDEX_op_remu_i64:
return C_O1_I2(r, r, r);

View file

@ -1955,6 +1955,10 @@ static const TCGOutOpBinary outop_orc = {
.base.static_constraint = C_NotImplemented,
};
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{

View file

@ -2736,6 +2736,10 @@ static const TCGOutOpBinary outop_orc = {
.base.static_constraint = C_NotImplemented,
};
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{

View file

@ -1459,6 +1459,21 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static void tgen_rems(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
if (type == TCG_TYPE_I32) {
tcg_out_opc_mod_w(s, a0, a1, a2);
} else {
tcg_out_opc_mod_d(s, a0, a1, a2);
}
}
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_rems,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
@ -1709,13 +1724,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
break;
case INDEX_op_rem_i32:
tcg_out_opc_mod_w(s, a0, a1, a2);
break;
case INDEX_op_rem_i64:
tcg_out_opc_mod_d(s, a0, a1, a2);
break;
case INDEX_op_remu_i32:
tcg_out_opc_mod_wu(s, a0, a1, a2);
break;
@ -2381,8 +2389,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_setcond_i64:
return C_O1_I2(r, rz, rJ);
case INDEX_op_rem_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i32:
case INDEX_op_remu_i64:
return C_O1_I2(r, rz, rz);

View file

@ -1866,6 +1866,27 @@ static const TCGOutOpBinary outop_orc = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_rems(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
if (use_mips32r6_instructions) {
if (type == TCG_TYPE_I32) {
tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
} else {
tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
}
} else {
MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIV : OPC_DDIV;
tcg_out_opc_reg(s, insn, 0, a1, a2);
tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
}
}
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_rems,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
@ -1989,13 +2010,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_ldst(s, i1, a0, a1, a2);
break;
case INDEX_op_rem_i32:
if (use_mips32r6_instructions) {
tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
break;
}
i1 = OPC_DIV, i2 = OPC_MFHI;
goto do_hilo1;
case INDEX_op_remu_i32:
if (use_mips32r6_instructions) {
tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
@ -2003,13 +2017,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
i1 = OPC_DIVU, i2 = OPC_MFHI;
goto do_hilo1;
case INDEX_op_rem_i64:
if (use_mips32r6_instructions) {
tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
break;
}
i1 = OPC_DDIV, i2 = OPC_MFHI;
goto do_hilo1;
case INDEX_op_remu_i64:
if (use_mips32r6_instructions) {
tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
@ -2275,10 +2282,8 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64:
return C_O0_I2(rz, r);
case INDEX_op_rem_i32:
case INDEX_op_remu_i32:
case INDEX_op_setcond_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
case INDEX_op_setcond_i64:
return C_O1_I2(r, rz, rz);

View file

@ -3091,6 +3091,24 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static TCGConstraintSetIndex cset_mod(TCGType type, unsigned flags)
{
return have_isa_3_00 ? C_O1_I2(r, r, r) : C_NotImplemented;
}
static void tgen_rems(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
uint32_t insn = type == TCG_TYPE_I32 ? MODSW : MODSD;
tcg_out32(s, insn | TAB(a0, a1, a2));
}
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_Dynamic,
.base.dynamic_constraint = cset_mod,
.out_rrr = tgen_rems,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
@ -3241,10 +3259,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out32(s, CNTPOPD | SAB(args[1], args[0], 0));
break;
case INDEX_op_rem_i32:
tcg_out32(s, MODSW | TAB(args[0], args[1], args[2]));
break;
case INDEX_op_remu_i32:
tcg_out32(s, MODUW | TAB(args[0], args[1], args[2]));
break;
@ -3341,9 +3355,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
break;
case INDEX_op_rem_i64:
tcg_out32(s, MODSD | TAB(args[0], args[1], args[2]));
break;
case INDEX_op_remu_i64:
tcg_out32(s, MODUD | TAB(args[0], args[1], args[2]));
break;
@ -4202,9 +4213,7 @@ 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_rem_i32:
case INDEX_op_remu_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
return C_O1_I2(r, r, r);

View file

@ -2120,6 +2120,18 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static void tgen_rems(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
RISCVInsn insn = type == TCG_TYPE_I32 ? OPC_REMW : OPC_REM;
tcg_out_opc_reg(s, insn, a0, a1, a2);
}
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_rems,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
@ -2233,13 +2245,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_rem_i32:
tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
break;
case INDEX_op_rem_i64:
tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
break;
case INDEX_op_remu_i32:
tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
break;
@ -2748,9 +2753,7 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, r, rI);
case INDEX_op_rem_i32:
case INDEX_op_remu_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
return C_O1_I2(r, rz, rz);

View file

@ -2437,6 +2437,10 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{

View file

@ -1476,6 +1476,10 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{

View file

@ -1040,6 +1040,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_not, TCGOutOpUnary, outop_not),
OUTOP(INDEX_op_or, TCGOutOpBinary, outop_or),
OUTOP(INDEX_op_orc, TCGOutOpBinary, outop_orc),
OUTOP(INDEX_op_rem_i32, TCGOutOpBinary, outop_rems),
OUTOP(INDEX_op_rem_i64, TCGOutOpBinary, outop_rems),
OUTOP(INDEX_op_sub, TCGOutOpSubtract, outop_sub),
OUTOP(INDEX_op_xor, TCGOutOpBinary, outop_xor),
};
@ -2270,7 +2272,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_negsetcond_i32:
return TCG_TARGET_HAS_negsetcond_i32;
case INDEX_op_rem_i32:
case INDEX_op_remu_i32:
return TCG_TARGET_HAS_rem_i32;
case INDEX_op_rotl_i32:
@ -2327,7 +2328,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_negsetcond_i64:
return TCG_TARGET_HAS_negsetcond_i64;
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
return TCG_TARGET_HAS_rem_i64;
case INDEX_op_rotl_i64:
@ -5425,6 +5425,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
case INDEX_op_nor:
case INDEX_op_or:
case INDEX_op_orc:
case INDEX_op_rem_i32:
case INDEX_op_rem_i64:
case INDEX_op_xor:
{
const TCGOutOpBinary *out =

View file

@ -586,7 +586,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
tci_args_rrr(insn, &r0, &r1, &r2);
regs[r0] = (uint32_t)regs[r1] / (uint32_t)regs[r2];
break;
case INDEX_op_rem_i32:
case INDEX_op_tci_rems32:
tci_args_rrr(insn, &r0, &r1, &r2);
regs[r0] = (int32_t)regs[r1] % (int32_t)regs[r2];
break;
@ -1081,7 +1081,6 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info)
case INDEX_op_orc:
case INDEX_op_sub:
case INDEX_op_xor:
case INDEX_op_rem_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i32:
case INDEX_op_remu_i64:
@ -1101,6 +1100,7 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info)
case INDEX_op_ctz_i64:
case INDEX_op_tci_divs32:
case INDEX_op_tci_divu32:
case INDEX_op_tci_rems32:
tci_args_rrr(insn, &r0, &r1, &r2);
info->fprintf_func(info->stream, "%-12s %s, %s, %s",
op_name, str_r(r0), str_r(r1), str_r(r2));

View file

@ -4,3 +4,4 @@ DEF(tci_movi, 1, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(tci_movl, 1, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(tci_divs32, 1, 2, 0, TCG_OPF_NOT_PRESENT)
DEF(tci_divu32, 1, 2, 0, TCG_OPF_NOT_PRESENT)
DEF(tci_rems32, 1, 2, 0, TCG_OPF_NOT_PRESENT)

View file

@ -79,8 +79,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_rem_i32:
case INDEX_op_rem_i64:
case INDEX_op_remu_i32:
case INDEX_op_remu_i64:
case INDEX_op_shl_i32:
@ -754,6 +752,20 @@ static const TCGOutOpBinary outop_orc = {
.out_rrr = tgen_orc,
};
static void tgen_rems(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
TCGOpcode opc = (type == TCG_TYPE_I32
? INDEX_op_tci_rems32
: INDEX_op_rem_i64);
tcg_out_op_rrr(s, opc, a0, a1, a2);
}
static const TCGOutOpBinary outop_rems = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_rems,
};
static void tgen_sub(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
@ -843,7 +855,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
CASE_32_64(sar)
CASE_32_64(rotl) /* Optional (TCG_TARGET_HAS_rot_*). */
CASE_32_64(rotr) /* Optional (TCG_TARGET_HAS_rot_*). */
CASE_32_64(rem) /* Optional (TCG_TARGET_HAS_div_*). */
CASE_32_64(remu) /* Optional (TCG_TARGET_HAS_div_*). */
CASE_32_64(clz) /* Optional (TCG_TARGET_HAS_clz_*). */
CASE_32_64(ctz) /* Optional (TCG_TARGET_HAS_ctz_*). */