tcg: Convert extract2 to TCGOutOpExtract2

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 21:30:10 -08:00
parent 4d137ff819
commit c8f9f70047
23 changed files with 97 additions and 77 deletions

View file

@ -13,13 +13,11 @@
#define have_lse2 (cpuinfo & CPUINFO_LSE2) #define have_lse2 (cpuinfo & CPUINFO_LSE2)
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_extract2_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1

View file

@ -2634,6 +2634,17 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static void tgen_extract2(TCGContext *s, TCGType type, TCGReg a0,
TCGReg a1, TCGReg a2, unsigned shr)
{
tcg_out_extr(s, type, a0, a2, a1, shr);
}
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_O1_I2(r, rz, rz),
.out_rrr = tgen_extract2,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext, static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext,
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])
@ -2714,11 +2725,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_extract2_i64:
case INDEX_op_extract2_i32:
tcg_out_extr(s, ext, a0, a2, a1, args[3]);
break;
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, a2, args[3], tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, a2, args[3],
(int32_t)args[4], args[5], const_args[4], (int32_t)args[4], args[5], const_args[4],
@ -3231,10 +3237,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_extract2_i32:
case INDEX_op_extract2_i64:
return C_O1_I2(r, rz, rz);
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

@ -24,7 +24,6 @@ extern bool use_neon_instructions;
#endif #endif
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 1
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_qemu_ldst_i128 0 #define TCG_TARGET_HAS_qemu_ldst_i128 0

View file

@ -2317,6 +2317,20 @@ static const TCGOutOpSetcond2 outop_setcond2 = {
.out = tgen_setcond2, .out = tgen_setcond2,
}; };
static void tgen_extract2(TCGContext *s, TCGType type, TCGReg a0,
TCGReg a1, TCGReg a2, unsigned shr)
{
/* We can do extract2 in 2 insns, vs the 3 required otherwise. */
tgen_shli(s, TCG_TYPE_I32, TCG_REG_TMP, a2, 32 - shr);
tcg_out_dat_reg(s, COND_AL, ARITH_ORR, a0, TCG_REG_TMP,
a1, SHIFT_IMM_LSR(shr));
}
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_O1_I2(r, r, r),
.out_rrr = tgen_extract2,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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])
@ -2411,28 +2425,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_extract2_i32:
/* ??? These optimization vs zero should be generic. */
/* ??? But we can't substitute 2 for 1 in the opcode stream yet. */
if (const_args[1]) {
if (const_args[2]) {
tcg_out_movi(s, TCG_TYPE_REG, args[0], 0);
} else {
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0,
args[2], SHIFT_IMM_LSL(32 - args[3]));
}
} else if (const_args[2]) {
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0,
args[1], SHIFT_IMM_LSR(args[3]));
} else {
/* We can do extract2 in 2 insns, vs the 3 required otherwise. */
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP, 0,
args[2], SHIFT_IMM_LSL(32 - args[3]));
tcg_out_dat_reg(s, COND_AL, ARITH_ORR, args[0], TCG_REG_TMP,
args[1], SHIFT_IMM_LSR(args[3]));
}
break;
case INDEX_op_mb: case INDEX_op_mb:
tcg_out_mb(s, args[0]); tcg_out_mb(s, args[0]);
break; break;
@ -2464,8 +2456,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_extract2_i32:
return C_O1_I2(r, rZ, rZ);
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
return C_O2_I4(r, r, r, r, rIN, rIK); return C_O2_I4(r, r, r, r, rIN, rIK);
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:

View file

@ -26,14 +26,12 @@
#define have_avx512vbmi2 ((cpuinfo & CPUINFO_AVX512VBMI2) && have_avx512vl) #define have_avx512vbmi2 ((cpuinfo & CPUINFO_AVX512VBMI2) && have_avx512vl)
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
/* Keep 32-bit values zero-extended in a register. */ /* Keep 32-bit values zero-extended in a register. */
#define TCG_TARGET_HAS_extr_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_extract2_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0

View file

@ -3261,6 +3261,21 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static void tgen_extract2(TCGContext *s, TCGType type, TCGReg a0,
TCGReg a1, TCGReg a2, unsigned shr)
{
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
/* Note that SHRD outputs to the r/m operand. */
tcg_out_modrm(s, OPC_SHRD_Ib + rexw, a2, a0);
tcg_out8(s, shr);
}
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_O1_I2(r, 0, r),
.out_rrr = tgen_extract2,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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],
@ -3414,12 +3429,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
break; break;
#endif #endif
OP_32_64(extract2):
/* Note that SHRD outputs to the r/m operand. */
tcg_out_modrm(s, OPC_SHRD_Ib + rexw, a2, a0);
tcg_out8(s, args[3]);
break;
case INDEX_op_mb: case INDEX_op_mb:
tcg_out_mb(s, a0); tcg_out_mb(s, a0);
break; break;
@ -4008,10 +4017,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(re, r); return C_O0_I2(re, r);
case INDEX_op_extract2_i32:
case INDEX_op_extract2_i64:
return C_O1_I2(r, 0, 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:

View file

@ -10,13 +10,11 @@
#include "host/cpuinfo.h" #include "host/cpuinfo.h"
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_add2_i32 0
#define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_sub2_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
/* 64-bit operations */ /* 64-bit operations */
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_extr_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_add2_i64 0
#define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_sub2_i64 0

View file

@ -1868,6 +1868,11 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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])

View file

@ -51,13 +51,7 @@ extern bool use_mips32r2_instructions;
#endif #endif
/* optional instructions detected at runtime */ /* optional instructions detected at runtime */
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_extract2_i64 0
#endif
#define TCG_TARGET_HAS_qemu_ldst_i128 0 #define TCG_TARGET_HAS_qemu_ldst_i128 0
#define TCG_TARGET_HAS_tst 0 #define TCG_TARGET_HAS_tst 0

View file

@ -2273,6 +2273,11 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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])

View file

@ -17,14 +17,12 @@
#define have_vsx (cpuinfo & CPUINFO_VSX) #define have_vsx (cpuinfo & CPUINFO_VSX)
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_add2_i32 0
#define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_sub2_i32 0
#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#endif #endif

View file

@ -3495,6 +3495,10 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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],

View file

@ -10,12 +10,10 @@
#include "host/cpuinfo.h" #include "host/cpuinfo.h"
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_extr_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1

View file

@ -2542,6 +2542,11 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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])

View file

@ -29,13 +29,11 @@ extern uint64_t s390_facilities[3];
((s390_facilities[FACILITY_##X / 64] >> (63 - FACILITY_##X % 64)) & 1) ((s390_facilities[FACILITY_##X / 64] >> (63 - FACILITY_##X % 64)) & 1)
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1

View file

@ -1637,6 +1637,10 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tgen_gotoi(TCGContext *s, int cc, const tcg_insn_unit *dest) static void tgen_gotoi(TCGContext *s, int cc, const tcg_insn_unit *dest)
{ {
ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1; ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1;

View file

@ -14,13 +14,11 @@ extern bool use_vis3_instructions;
#endif #endif
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1

View file

@ -1795,6 +1795,10 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tgen_sextract, .out_rr = tgen_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, 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])

View file

@ -12,7 +12,6 @@
#if TCG_TARGET_REG_BITS == 32 #if TCG_TARGET_REG_BITS == 32
/* Turn some undef macros into false macros. */ /* Turn some undef macros into false macros. */
#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_add2_i64 0
#define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_sub2_i64 0
/* Turn some undef macros into true macros. */ /* Turn some undef macros into true macros. */

View file

@ -921,7 +921,7 @@ void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2,
t1 = tcg_temp_ebb_new_i32(); t1 = tcg_temp_ebb_new_i32();
if (TCG_TARGET_HAS_extract2_i32) { if (tcg_op_supported(INDEX_op_extract2_i32, TCG_TYPE_I32, 0)) {
if (ofs + len == 32) { if (ofs + len == 32) {
tcg_gen_shli_i32(t1, arg1, len); tcg_gen_shli_i32(t1, arg1, len);
tcg_gen_extract2_i32(ret, t1, arg2, len); tcg_gen_extract2_i32(ret, t1, arg2, len);
@ -1077,7 +1077,7 @@ void tcg_gen_extract2_i32(TCGv_i32 ret, TCGv_i32 al, TCGv_i32 ah,
tcg_gen_mov_i32(ret, ah); tcg_gen_mov_i32(ret, ah);
} else if (al == ah) { } else if (al == ah) {
tcg_gen_rotri_i32(ret, al, ofs); tcg_gen_rotri_i32(ret, al, ofs);
} else if (TCG_TARGET_HAS_extract2_i32) { } else if (tcg_op_supported(INDEX_op_extract2_i32, TCG_TYPE_I32, 0)) {
tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs); tcg_gen_op4i_i32(INDEX_op_extract2_i32, ret, al, ah, ofs);
} else { } else {
TCGv_i32 t0 = tcg_temp_ebb_new_i32(); TCGv_i32 t0 = tcg_temp_ebb_new_i32();
@ -1799,7 +1799,7 @@ static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
tcg_gen_movi_i32(TCGV_LOW(ret), 0); tcg_gen_movi_i32(TCGV_LOW(ret), 0);
} }
} else if (right) { } else if (right) {
if (TCG_TARGET_HAS_extract2_i32) { if (tcg_op_supported(INDEX_op_extract2_i32, TCG_TYPE_I32, 0)) {
tcg_gen_extract2_i32(TCGV_LOW(ret), tcg_gen_extract2_i32(TCGV_LOW(ret),
TCGV_LOW(arg1), TCGV_HIGH(arg1), c); TCGV_LOW(arg1), TCGV_HIGH(arg1), c);
} else { } else {
@ -1813,7 +1813,7 @@ static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); tcg_gen_shri_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
} }
} else { } else {
if (TCG_TARGET_HAS_extract2_i32) { if (tcg_op_supported(INDEX_op_extract2_i32, TCG_TYPE_I32, 0)) {
tcg_gen_extract2_i32(TCGV_HIGH(ret), tcg_gen_extract2_i32(TCGV_HIGH(ret),
TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c); TCGV_LOW(arg1), TCGV_HIGH(arg1), 32 - c);
} else { } else {
@ -2553,7 +2553,7 @@ void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2,
t1 = tcg_temp_ebb_new_i64(); t1 = tcg_temp_ebb_new_i64();
if (TCG_TARGET_HAS_extract2_i64) { if (tcg_op_supported(INDEX_op_extract2_i64, TCG_TYPE_I64, 0)) {
if (ofs + len == 64) { if (ofs + len == 64) {
tcg_gen_shli_i64(t1, arg1, len); tcg_gen_shli_i64(t1, arg1, len);
tcg_gen_extract2_i64(ret, t1, arg2, len); tcg_gen_extract2_i64(ret, t1, arg2, len);
@ -2781,7 +2781,7 @@ void tcg_gen_extract2_i64(TCGv_i64 ret, TCGv_i64 al, TCGv_i64 ah,
tcg_gen_mov_i64(ret, ah); tcg_gen_mov_i64(ret, ah);
} else if (al == ah) { } else if (al == ah) {
tcg_gen_rotri_i64(ret, al, ofs); tcg_gen_rotri_i64(ret, al, ofs);
} else if (TCG_TARGET_HAS_extract2_i64) { } else if (tcg_op_supported(INDEX_op_extract2_i64, TCG_TYPE_I64, 0)) {
tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs); tcg_gen_op4i_i64(INDEX_op_extract2_i64, ret, al, ah, ofs);
} else { } else {
TCGv_i64 t0 = tcg_temp_ebb_new_i64(); TCGv_i64 t0 = tcg_temp_ebb_new_i64();

View file

@ -1029,6 +1029,12 @@ typedef struct TCGOutOpExtract {
unsigned ofs, unsigned len); unsigned ofs, unsigned len);
} TCGOutOpExtract; } TCGOutOpExtract;
typedef struct TCGOutOpExtract2 {
TCGOutOp base;
void (*out_rrr)(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
TCGReg a2, unsigned shr);
} TCGOutOpExtract2;
typedef struct TCGOutOpMovcond { typedef struct TCGOutOpMovcond {
TCGOutOp base; TCGOutOp base;
void (*out)(TCGContext *s, TCGType type, TCGCond cond, void (*out)(TCGContext *s, TCGType type, TCGCond cond,
@ -1140,6 +1146,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_divu2, TCGOutOpDivRem, outop_divu2), OUTOP(INDEX_op_divu2, TCGOutOpDivRem, outop_divu2),
OUTOP(INDEX_op_eqv, TCGOutOpBinary, outop_eqv), OUTOP(INDEX_op_eqv, TCGOutOpBinary, outop_eqv),
OUTOP(INDEX_op_extract, TCGOutOpExtract, outop_extract), OUTOP(INDEX_op_extract, TCGOutOpExtract, outop_extract),
OUTOP(INDEX_op_extract2_i32, TCGOutOpExtract2, outop_extract2),
OUTOP(INDEX_op_extract2_i64, TCGOutOpExtract2, outop_extract2),
OUTOP(INDEX_op_movcond, TCGOutOpMovcond, outop_movcond), OUTOP(INDEX_op_movcond, TCGOutOpMovcond, outop_movcond),
OUTOP(INDEX_op_mul, TCGOutOpBinary, outop_mul), OUTOP(INDEX_op_mul, TCGOutOpBinary, outop_mul),
OUTOP(INDEX_op_muls2, TCGOutOpMul2, outop_muls2), OUTOP(INDEX_op_muls2, TCGOutOpMul2, outop_muls2),
@ -2399,8 +2407,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i32: case INDEX_op_st_i32:
return true; return true;
case INDEX_op_extract2_i32:
return TCG_TARGET_HAS_extract2_i32;
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
return TCG_TARGET_HAS_add2_i32; return TCG_TARGET_HAS_add2_i32;
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:
@ -2427,8 +2433,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_extrh_i64_i32: case INDEX_op_extrh_i64_i32:
return TCG_TARGET_REG_BITS == 64; return TCG_TARGET_REG_BITS == 64;
case INDEX_op_extract2_i64:
return TCG_TARGET_HAS_extract2_i64;
case INDEX_op_add2_i64: case INDEX_op_add2_i64:
return TCG_TARGET_HAS_add2_i64; return TCG_TARGET_HAS_add2_i64;
case INDEX_op_sub2_i64: case INDEX_op_sub2_i64:
@ -5593,6 +5597,18 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
} }
break; break;
case INDEX_op_extract2_i32:
case INDEX_op_extract2_i64:
{
const TCGOutOpExtract2 *out = &outop_extract2;
tcg_debug_assert(!const_args[1]);
tcg_debug_assert(!const_args[2]);
out->out_rrr(s, type, new_args[0], new_args[1],
new_args[2], new_args[3]);
}
break;
case INDEX_op_muls2: case INDEX_op_muls2:
case INDEX_op_mulu2: case INDEX_op_mulu2:
{ {

View file

@ -7,12 +7,10 @@
#ifndef TCG_TARGET_HAS_H #ifndef TCG_TARGET_HAS_H
#define TCG_TARGET_HAS_H #define TCG_TARGET_HAS_H
#define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_extr_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1

View file

@ -447,6 +447,10 @@ static const TCGOutOpExtract outop_sextract = {
.out_rr = tcg_out_sextract, .out_rr = tcg_out_sextract,
}; };
static const TCGOutOpExtract2 outop_extract2 = {
.base.static_constraint = C_NotImplemented,
};
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
{ {
tcg_out_sextract(s, type, rd, rs, 0, 8); tcg_out_sextract(s, type, rd, rs, 0, 8);