tcg: Convert deposit to TCGOutOpDeposit

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-12 20:29:41 -08:00
parent b3b1397664
commit cf4905c031
12 changed files with 206 additions and 155 deletions

View file

@ -1347,15 +1347,6 @@ static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a); tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
} }
static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
TCGReg rn, unsigned lsb, unsigned width)
{
unsigned size = ext ? 64 : 32;
unsigned a = (size - lsb) & (size - 1);
unsigned b = width - 1;
tcg_out_bfm(s, ext, rd, rn, a, b);
}
static void tgen_cmp(TCGContext *s, TCGType ext, TCGCond cond, static void tgen_cmp(TCGContext *s, TCGType ext, TCGCond cond,
TCGReg a, TCGReg b) TCGReg a, TCGReg b)
{ {
@ -2577,6 +2568,18 @@ static const TCGOutOpMovcond outop_movcond = {
.out = tgen_movcond, .out = tgen_movcond,
}; };
static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len)
{
unsigned mask = type == TCG_TYPE_I32 ? 31 : 63;
tcg_out_bfm(s, type, a0, a2, -ofs & mask, len - 1);
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, 0, rz),
.out_rrr = tgen_deposit,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {
@ -2684,11 +2687,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext,
tcg_out_qemu_ldst_i128(s, a0, a1, a2, args[3], false); tcg_out_qemu_ldst_i128(s, a0, a1, a2, args[3], false);
break; break;
case INDEX_op_deposit_i64:
case INDEX_op_deposit_i32:
tcg_out_dep(s, ext, a0, a2, args[3], args[4]);
break;
case INDEX_op_extract2_i64: case INDEX_op_extract2_i64:
case INDEX_op_extract2_i32: case INDEX_op_extract2_i32:
tcg_out_extr(s, ext, a0, a2, a1, args[3]); tcg_out_extr(s, ext, a0, a2, a1, args[3]);
@ -3206,10 +3204,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_qemu_st_i128: case INDEX_op_qemu_st_i128:
return C_O0_I3(rz, rz, r); return C_O0_I3(rz, rz, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(r, 0, rz);
case INDEX_op_extract2_i32: case INDEX_op_extract2_i32:
case INDEX_op_extract2_i64: case INDEX_op_extract2_i64:
return C_O1_I2(r, rz, rz); return C_O1_I2(r, rz, rz);

View file

@ -969,18 +969,27 @@ static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn)
g_assert_not_reached(); g_assert_not_reached();
} }
static void tcg_out_deposit(TCGContext *s, ARMCond cond, TCGReg rd, static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGArg a1, int ofs, int len, bool const_a1) TCGReg a2, unsigned ofs, unsigned len)
{ {
if (const_a1) {
/* bfi becomes bfc with rn == 15. */
a1 = 15;
}
/* bfi/bfc */ /* bfi/bfc */
tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1 tcg_out32(s, 0x07c00010 | (COND_AL << 28) | (a0 << 12) | a1
| (ofs << 7) | ((ofs + len - 1) << 16)); | (ofs << 7) | ((ofs + len - 1) << 16));
} }
static void tgen_depositi(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
tcg_target_long a2, unsigned ofs, unsigned len)
{
/* bfi becomes bfc with rn == 15. */
tgen_deposit(s, type, a0, a1, 15, ofs, len);
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, 0, rZ),
.out_rrr = tgen_deposit,
.out_rri = tgen_depositi,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn, static void tgen_extract(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {
@ -2402,10 +2411,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_qemu_st(s, args[0], args[1], args[2], args[3], TCG_TYPE_I64); tcg_out_qemu_st(s, args[0], args[1], args[2], args[3], TCG_TYPE_I64);
break; break;
case INDEX_op_deposit_i32:
tcg_out_deposit(s, COND_AL, args[0], args[2],
args[3], args[4], const_args[2]);
break;
case INDEX_op_extract2_i32: case INDEX_op_extract2_i32:
/* ??? These optimization vs zero should be generic. */ /* ??? These optimization vs zero should be generic. */
/* ??? But we can't substitute 2 for 1 in the opcode stream yet. */ /* ??? But we can't substitute 2 for 1 in the opcode stream yet. */
@ -2459,8 +2464,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i32: case INDEX_op_st_i32:
return C_O0_I2(r, r); return C_O0_I2(r, r);
case INDEX_op_deposit_i32:
return C_O1_I2(r, 0, rZ);
case INDEX_op_extract2_i32: case INDEX_op_extract2_i32:
return C_O1_I2(r, rZ, rZ); return C_O1_I2(r, rZ, rZ);
case INDEX_op_add2_i32: case INDEX_op_add2_i32:

View file

@ -3150,6 +3150,43 @@ static const TCGOutOpUnary outop_not = {
.out_rr = tgen_not, .out_rr = tgen_not,
}; };
static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len)
{
if (ofs == 0 && len == 8) {
tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM, a2, a0);
} else if (ofs == 0 && len == 16) {
tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, a2, a0);
} else if (TCG_TARGET_REG_BITS == 32 && ofs == 8 && len == 8) {
tcg_out_modrm(s, OPC_MOVB_EvGv, a2, a0 + 4);
} else {
g_assert_not_reached();
}
}
static void tgen_depositi(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
tcg_target_long a2, unsigned ofs, unsigned len)
{
if (ofs == 0 && len == 8) {
tcg_out_opc(s, OPC_MOVB_Ib | P_REXB_RM | LOWREGMASK(a0), 0, a0, 0);
tcg_out8(s, a2);
} else if (ofs == 0 && len == 16) {
tcg_out_opc(s, OPC_MOVL_Iv | P_DATA16 | LOWREGMASK(a0), 0, a0, 0);
tcg_out16(s, a2);
} else if (TCG_TARGET_REG_BITS == 32 && ofs == 8 && len == 8) {
tcg_out8(s, OPC_MOVB_Ib + a0 + 4);
tcg_out8(s, a2);
} else {
g_assert_not_reached();
}
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(q, 0, qi),
.out_rrr = tgen_deposit,
.out_rri = tgen_depositi,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {
@ -3230,7 +3267,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const int const_args[TCG_MAX_OP_ARGS]) const int const_args[TCG_MAX_OP_ARGS])
{ {
TCGArg a0, a1, a2; TCGArg a0, a1, a2;
int const_a2, rexw; int rexw;
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
# define OP_32_64(x) \ # define OP_32_64(x) \
@ -3245,7 +3282,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
a0 = args[0]; a0 = args[0];
a1 = args[1]; a1 = args[1];
a2 = args[2]; a2 = args[2];
const_a2 = const_args[2];
rexw = type == TCG_TYPE_I32 ? 0 : P_REXW; rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
switch (opc) { switch (opc) {
@ -3378,38 +3414,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
break; break;
#endif #endif
OP_32_64(deposit):
if (args[3] == 0 && args[4] == 8) {
/* load bits 0..7 */
if (const_a2) {
tcg_out_opc(s, OPC_MOVB_Ib | P_REXB_RM | LOWREGMASK(a0),
0, a0, 0);
tcg_out8(s, a2);
} else {
tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM, a2, a0);
}
} else if (TCG_TARGET_REG_BITS == 32 && args[3] == 8 && args[4] == 8) {
/* load bits 8..15 */
if (const_a2) {
tcg_out8(s, OPC_MOVB_Ib + a0 + 4);
tcg_out8(s, a2);
} else {
tcg_out_modrm(s, OPC_MOVB_EvGv, a2, a0 + 4);
}
} else if (args[3] == 0 && args[4] == 16) {
/* load bits 0..15 */
if (const_a2) {
tcg_out_opc(s, OPC_MOVL_Iv | P_DATA16 | LOWREGMASK(a0),
0, a0, 0);
tcg_out16(s, a2);
} else {
tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, a2, a0);
}
} else {
g_assert_not_reached();
}
break;
OP_32_64(extract2): OP_32_64(extract2):
/* Note that SHRD outputs to the r/m operand. */ /* Note that SHRD outputs to the r/m operand. */
tcg_out_modrm(s, OPC_SHRD_Ib + rexw, a2, a0); tcg_out_modrm(s, OPC_SHRD_Ib + rexw, a2, a0);
@ -4008,10 +4012,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_extract2_i64: case INDEX_op_extract2_i64:
return C_O1_I2(r, 0, r); return C_O1_I2(r, 0, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(q, 0, qi);
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
case INDEX_op_add2_i64: case INDEX_op_add2_i64:
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:

View file

@ -1809,6 +1809,21 @@ static const TCGOutOpUnary outop_not = {
.out_rr = tgen_not, .out_rr = tgen_not,
}; };
static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len)
{
if (type == TCG_TYPE_I32) {
tcg_out_opc_bstrins_w(s, a0, a2, ofs, ofs + len - 1);
} else {
tcg_out_opc_bstrins_d(s, a0, a2, ofs, ofs + len - 1);
}
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, 0, rz),
.out_rrr = tgen_deposit,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {
@ -1877,13 +1892,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_opc_b(s, 0); tcg_out_opc_b(s, 0);
break; break;
case INDEX_op_deposit_i32:
tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1);
break;
case INDEX_op_deposit_i64:
tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1);
break;
case INDEX_op_ld8s_i32: case INDEX_op_ld8s_i32:
case INDEX_op_ld8s_i64: case INDEX_op_ld8s_i64:
tcg_out_ldst(s, OPC_LD_B, a0, a1, a2); tcg_out_ldst(s, OPC_LD_B, a0, a1, a2);
@ -2484,11 +2492,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_qemu_ld_i64: case INDEX_op_qemu_ld_i64:
return C_O1_I1(r, r); return C_O1_I1(r, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
/* Must deposit into the same register as input */
return C_O1_I2(r, 0, rz);
case INDEX_op_ld_vec: case INDEX_op_ld_vec:
case INDEX_op_dupm_vec: case INDEX_op_dupm_vec:
case INDEX_op_dup_vec: case INDEX_op_dup_vec:

View file

@ -2215,6 +2215,22 @@ static const TCGOutOpUnary outop_not = {
.out_rr = tgen_not, .out_rr = tgen_not,
}; };
static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len)
{
if (type == TCG_TYPE_I32) {
tcg_out_opc_bf(s, OPC_INS, a0, a2, ofs + len - 1, ofs);
} else {
tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
ofs + len - 1, ofs);
}
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, 0, rz),
.out_rrr = tgen_deposit,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {
@ -2327,14 +2343,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_ldst(s, i1, a0, a1, a2); tcg_out_ldst(s, i1, a0, a1, a2);
break; break;
case INDEX_op_deposit_i32:
tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
break;
case INDEX_op_deposit_i64:
tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
args[3] + args[4] - 1, args[3]);
break;
case INDEX_op_qemu_ld_i32: case INDEX_op_qemu_ld_i32:
tcg_out_qemu_ld(s, a0, 0, a1, a2, TCG_TYPE_I32); tcg_out_qemu_ld(s, a0, 0, a1, a2, TCG_TYPE_I32);
break; break;
@ -2407,9 +2415,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64: case INDEX_op_st_i64:
return C_O0_I2(rz, r); return C_O0_I2(rz, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(r, 0, rz);
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:
return C_O2_I4(r, r, rz, rz, rN, rN); return C_O2_I4(r, r, rz, rz, rN, rN);

View file

@ -3429,6 +3429,28 @@ static const TCGOutOpUnary outop_not = {
.out_rr = tgen_not, .out_rr = tgen_not,
}; };
static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len)
{
if (type == TCG_TYPE_I32) {
tcg_out_rlw(s, RLWIMI, a0, a2, ofs, 32 - ofs - len, 31 - ofs);
} else {
tcg_out_rld(s, RLDIMI, a0, a2, ofs, 64 - ofs - len);
}
}
static void tgen_depositi(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
tcg_target_long a2, unsigned ofs, unsigned len)
{
tgen_andi(s, type, a0, a1, ~MAKE_64BIT_MASK(ofs, len));
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, 0, rZ),
.out_rrr = tgen_deposit,
.out_rri = tgen_depositi,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {
@ -3575,25 +3597,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_qemu_ldst_i128(s, args[0], args[1], args[2], args[3], false); tcg_out_qemu_ldst_i128(s, args[0], args[1], args[2], args[3], false);
break; break;
case INDEX_op_deposit_i32:
if (const_args[2]) {
uint32_t mask = ((2u << (args[4] - 1)) - 1) << args[3];
tcg_out_andi32(s, args[0], args[0], ~mask);
} else {
tcg_out_rlw(s, RLWIMI, args[0], args[2], args[3],
32 - args[3] - args[4], 31 - args[3]);
}
break;
case INDEX_op_deposit_i64:
if (const_args[2]) {
uint64_t mask = ((2ull << (args[4] - 1)) - 1) << args[3];
tcg_out_andi64(s, args[0], args[0], ~mask);
} else {
tcg_out_rld(s, RLDIMI, args[0], args[2], args[3],
64 - args[3] - args[4]);
}
break;
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
case INDEX_op_add2_i64: case INDEX_op_add2_i64:
#else #else
@ -4290,9 +4293,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64: case INDEX_op_st_i64:
return C_O0_I2(r, r); return C_O0_I2(r, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(r, 0, rZ);
case INDEX_op_add2_i64: case INDEX_op_add2_i64:
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
return C_O2_I4(r, r, r, r, rI, rZM); return C_O2_I4(r, r, r, r, rI, rZM);

View file

@ -2482,6 +2482,10 @@ static const TCGOutOpUnary outop_not = {
.out_rr = tgen_not, .out_rr = tgen_not,
}; };
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {

View file

@ -1555,14 +1555,40 @@ static const TCGOutOpMovcond outop_movcond = {
.out = tgen_movcond, .out = tgen_movcond,
}; };
static void tgen_deposit(TCGContext *s, TCGReg dest, TCGReg src, static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
int ofs, int len, int z) TCGReg a2, unsigned ofs, unsigned len)
{ {
int lsb = (63 - ofs); unsigned lsb = (63 - ofs);
int msb = lsb - (len - 1); unsigned msb = lsb - (len - 1);
tcg_out_risbg(s, dest, src, msb, lsb, ofs, z);
/*
* Since we can't support "0Z" as a constraint, we allow a1 in
* any register. Fix things up as if a matching constraint.
*/
if (a0 != a1) {
if (a0 == a2) {
tcg_out_mov(s, type, TCG_TMP0, a2);
a2 = TCG_TMP0;
}
tcg_out_mov(s, type, a0, a1);
}
tcg_out_risbg(s, a0, a2, msb, lsb, ofs, false);
} }
static void tgen_depositz(TCGContext *s, TCGType type, TCGReg a0, TCGReg a2,
unsigned ofs, unsigned len)
{
unsigned lsb = (63 - ofs);
unsigned msb = lsb - (len - 1);
tcg_out_risbg(s, a0, a2, msb, lsb, ofs, true);
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, rZ, r),
.out_rrr = tgen_deposit,
.out_rzr = tgen_depositz,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg dest, static void tgen_extract(TCGContext *s, TCGType type, TCGReg dest,
TCGReg src, unsigned ofs, unsigned len) TCGReg src, unsigned ofs, unsigned len)
{ {
@ -2845,7 +2871,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS], const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS]) const int const_args[TCG_MAX_OP_ARGS])
{ {
TCGArg a0, a1, a2; TCGArg a0;
switch (opc) { switch (opc) {
case INDEX_op_goto_ptr: case INDEX_op_goto_ptr:
@ -2977,24 +3003,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_insn(s, RRE, SLBGR, args[1], args[5]); tcg_out_insn(s, RRE, SLBGR, args[1], args[5]);
break; break;
OP_32_64(deposit):
a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[1]) {
tgen_deposit(s, a0, a2, args[3], args[4], 1);
} else {
/* Since we can't support "0Z" as a constraint, we allow a1 in
any register. Fix things up as if a matching constraint. */
if (a0 != a1) {
if (a0 == a2) {
tcg_out_mov(s, type, TCG_TMP0, a2);
a2 = TCG_TMP0;
}
tcg_out_mov(s, type, a0, a1);
}
tgen_deposit(s, a0, a2, args[3], args[4], 0);
}
break;
case INDEX_op_mb: case INDEX_op_mb:
/* The host memory model is quite strong, we simply need to /* The host memory model is quite strong, we simply need to
serialize the instruction stream. */ serialize the instruction stream. */
@ -3489,10 +3497,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_qemu_st_i128: case INDEX_op_qemu_st_i128:
return C_O0_I3(o, m, r); return C_O0_I3(o, m, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(r, rZ, r);
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:
return C_N1_O1_I4(r, r, 0, 1, ri, r); return C_N1_O1_I4(r, r, 0, 1, ri, r);

View file

@ -1767,6 +1767,10 @@ static const TCGOutOpUnary outop_not = {
.out_rr = tgen_not, .out_rr = tgen_not,
}; };
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
unsigned ofs, unsigned len) unsigned ofs, unsigned len)
{ {

View file

@ -1007,6 +1007,16 @@ typedef struct TCGOutOpBswap {
TCGReg a0, TCGReg a1, unsigned flags); TCGReg a0, TCGReg a1, unsigned flags);
} TCGOutOpBswap; } TCGOutOpBswap;
typedef struct TCGOutOpDeposit {
TCGOutOp base;
void (*out_rrr)(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len);
void (*out_rri)(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
tcg_target_long a2, unsigned ofs, unsigned len);
void (*out_rzr)(TCGContext *s, TCGType type, TCGReg a0,
TCGReg a2, unsigned ofs, unsigned len);
} TCGOutOpDeposit;
typedef struct TCGOutOpDivRem { typedef struct TCGOutOpDivRem {
TCGOutOp base; TCGOutOp base;
void (*out_rr01r)(TCGContext *s, TCGType type, void (*out_rr01r)(TCGContext *s, TCGType type,
@ -1123,6 +1133,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_clz, TCGOutOpBinary, outop_clz), OUTOP(INDEX_op_clz, TCGOutOpBinary, outop_clz),
OUTOP(INDEX_op_ctpop, TCGOutOpUnary, outop_ctpop), OUTOP(INDEX_op_ctpop, TCGOutOpUnary, outop_ctpop),
OUTOP(INDEX_op_ctz, TCGOutOpBinary, outop_ctz), OUTOP(INDEX_op_ctz, TCGOutOpBinary, outop_ctz),
OUTOP(INDEX_op_deposit_i32, TCGOutOpDeposit, outop_deposit),
OUTOP(INDEX_op_deposit_i64, TCGOutOpDeposit, outop_deposit),
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_divs2, TCGOutOpDivRem, outop_divs2), OUTOP(INDEX_op_divs2, TCGOutOpDivRem, outop_divs2),
@ -5537,6 +5549,27 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
} }
break; break;
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
{
const TCGOutOpDeposit *out = &outop_deposit;
if (const_args[2]) {
tcg_debug_assert(!const_args[1]);
out->out_rri(s, type, new_args[0], new_args[1],
new_args[2], new_args[3], new_args[4]);
} else if (const_args[1]) {
tcg_debug_assert(new_args[1] == 0);
tcg_debug_assert(!const_args[2]);
out->out_rzr(s, type, new_args[0], new_args[2],
new_args[3], new_args[4]);
} else {
out->out_rrr(s, type, new_args[0], new_args[1],
new_args[2], new_args[3], new_args[4]);
}
}
break;
case INDEX_op_divs2: case INDEX_op_divs2:
case INDEX_op_divu2: case INDEX_op_divu2:
{ {

View file

@ -27,6 +27,7 @@
#define ctpop_tr glue(ctpop, TCG_TARGET_REG_BITS) #define ctpop_tr glue(ctpop, TCG_TARGET_REG_BITS)
#define deposit_tr glue(deposit, TCG_TARGET_REG_BITS)
#define extract_tr glue(extract, TCG_TARGET_REG_BITS) #define extract_tr glue(extract, TCG_TARGET_REG_BITS)
#define sextract_tr glue(sextract, TCG_TARGET_REG_BITS) #define sextract_tr glue(sextract, TCG_TARGET_REG_BITS)
@ -655,8 +656,9 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
regs[r0] = ror32(regs[r1], regs[r2] & 31); regs[r0] = ror32(regs[r1], regs[r2] & 31);
break; break;
case INDEX_op_deposit_i32: case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len); tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
regs[r0] = deposit32(regs[r1], pos, len, regs[r2]); regs[r0] = deposit_tr(regs[r1], pos, len, regs[r2]);
break; break;
case INDEX_op_extract: case INDEX_op_extract:
tci_args_rrbb(insn, &r0, &r1, &pos, &len); tci_args_rrbb(insn, &r0, &r1, &pos, &len);
@ -770,10 +772,6 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
tci_args_rrr(insn, &r0, &r1, &r2); tci_args_rrr(insn, &r0, &r1, &r2);
regs[r0] = ror64(regs[r1], regs[r2] & 63); regs[r0] = ror64(regs[r1], regs[r2] & 63);
break; break;
case INDEX_op_deposit_i64:
tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
regs[r0] = deposit64(regs[r1], pos, len, regs[r2]);
break;
case INDEX_op_ext_i32_i64: case INDEX_op_ext_i32_i64:
tci_args_rr(insn, &r0, &r1); tci_args_rr(insn, &r0, &r1);
regs[r0] = (int32_t)regs[r1]; regs[r0] = (int32_t)regs[r1];

View file

@ -66,10 +66,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64: case INDEX_op_st_i64:
return C_O0_I2(r, r); return C_O0_I2(r, r);
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(r, r, r);
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
case INDEX_op_add2_i64: case INDEX_op_add2_i64:
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:
@ -623,6 +619,17 @@ static const TCGOutOpBinary outop_ctz = {
.out_rrr = tgen_ctz, .out_rrr = tgen_ctz,
}; };
static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned ofs, unsigned len)
{
tcg_out_op_rrrbb(s, INDEX_op_deposit_i64, a0, a1, a2, ofs, len);
}
static const TCGOutOpDeposit outop_deposit = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_deposit,
};
static void tgen_divs(TCGContext *s, TCGType type, static void tgen_divs(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2) TCGReg a0, TCGReg a1, TCGReg a2)
{ {
@ -1084,10 +1091,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_ldst(s, opc, args[0], args[1], args[2]); tcg_out_ldst(s, opc, args[0], args[1], args[2]);
break; break;
CASE_32_64(deposit)
tcg_out_op_rrrbb(s, opc, args[0], args[1], args[2], args[3], args[4]);
break;
CASE_32_64(add2) CASE_32_64(add2)
CASE_32_64(sub2) CASE_32_64(sub2)
tcg_out_op_rrrrrr(s, opc, args[0], args[1], args[2], tcg_out_op_rrrrrr(s, opc, args[0], args[1], args[2],