mirror of https://github.com/proxmox/mirror_qemu
tcg: Add flags argument to bswap opcodes
This will eventually simplify front-end usage, and will allow backends to unset TCG_TARGET_HAS_MEMORY_BSWAP without loss of optimization. The argument is added during expansion, not currently exposed to the front end translators. The backends currently only support a flags value of either TCG_BSWAP_IZ, or (TCG_BSWAP_IZ | TCG_BSWAP_OZ), since they all require zero top bytes and leave them that way. At the existing call sites we pass in (TCG_BSWAP_IZ | TCG_BSWAP_OZ), except for the flags-ignored cases of a 32-bit swap of a 32-bit value and or a 64-bit swap of a 64-bit value, where we pass 0. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>master
parent
4f862f79ca
commit
587195bd59
|
@ -96,8 +96,8 @@ DEF(ext8s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8s_i32))
|
||||||
DEF(ext16s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16s_i32))
|
DEF(ext16s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16s_i32))
|
||||||
DEF(ext8u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8u_i32))
|
DEF(ext8u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8u_i32))
|
||||||
DEF(ext16u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16u_i32))
|
DEF(ext16u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16u_i32))
|
||||||
DEF(bswap16_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_bswap16_i32))
|
DEF(bswap16_i32, 1, 1, 1, IMPL(TCG_TARGET_HAS_bswap16_i32))
|
||||||
DEF(bswap32_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_bswap32_i32))
|
DEF(bswap32_i32, 1, 1, 1, IMPL(TCG_TARGET_HAS_bswap32_i32))
|
||||||
DEF(not_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_not_i32))
|
DEF(not_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_not_i32))
|
||||||
DEF(neg_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_neg_i32))
|
DEF(neg_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_neg_i32))
|
||||||
DEF(andc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_andc_i32))
|
DEF(andc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_andc_i32))
|
||||||
|
@ -165,9 +165,9 @@ DEF(ext32s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32s_i64))
|
||||||
DEF(ext8u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8u_i64))
|
DEF(ext8u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8u_i64))
|
||||||
DEF(ext16u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16u_i64))
|
DEF(ext16u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16u_i64))
|
||||||
DEF(ext32u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32u_i64))
|
DEF(ext32u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32u_i64))
|
||||||
DEF(bswap16_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap16_i64))
|
DEF(bswap16_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap16_i64))
|
||||||
DEF(bswap32_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap32_i64))
|
DEF(bswap32_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap32_i64))
|
||||||
DEF(bswap64_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap64_i64))
|
DEF(bswap64_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap64_i64))
|
||||||
DEF(not_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_not_i64))
|
DEF(not_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_not_i64))
|
||||||
DEF(neg_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_neg_i64))
|
DEF(neg_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_neg_i64))
|
||||||
DEF(andc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_andc_i64))
|
DEF(andc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_andc_i64))
|
||||||
|
|
|
@ -408,6 +408,18 @@ typedef TCGv_ptr TCGv_env;
|
||||||
/* Used to align parameters. See the comment before tcgv_i32_temp. */
|
/* Used to align parameters. See the comment before tcgv_i32_temp. */
|
||||||
#define TCG_CALL_DUMMY_ARG ((TCGArg)0)
|
#define TCG_CALL_DUMMY_ARG ((TCGArg)0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags for the bswap opcodes.
|
||||||
|
* If IZ, the input is zero-extended, otherwise unknown.
|
||||||
|
* If OZ or OS, the output is zero- or sign-extended respectively,
|
||||||
|
* otherwise the high bits are undefined.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
TCG_BSWAP_IZ = 1,
|
||||||
|
TCG_BSWAP_OZ = 2,
|
||||||
|
TCG_BSWAP_OS = 4,
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum TCGTempVal {
|
typedef enum TCGTempVal {
|
||||||
TEMP_VAL_DEAD,
|
TEMP_VAL_DEAD,
|
||||||
TEMP_VAL_REG,
|
TEMP_VAL_REG,
|
||||||
|
|
22
tcg/README
22
tcg/README
|
@ -295,19 +295,25 @@ ext32u_i64 t0, t1
|
||||||
|
|
||||||
8, 16 or 32 bit sign/zero extension (both operands must have the same type)
|
8, 16 or 32 bit sign/zero extension (both operands must have the same type)
|
||||||
|
|
||||||
* bswap16_i32/i64 t0, t1
|
* bswap16_i32/i64 t0, t1, flags
|
||||||
|
|
||||||
16 bit byte swap on a 32/64 bit value. It assumes that the two/six high order
|
16 bit byte swap on the low bits of a 32/64 bit input.
|
||||||
bytes are set to zero.
|
If flags & TCG_BSWAP_IZ, then t1 is known to be zero-extended from bit 15.
|
||||||
|
If flags & TCG_BSWAP_OZ, then t0 will be zero-extended from bit 15.
|
||||||
|
If flags & TCG_BSWAP_OS, then t0 will be sign-extended from bit 15.
|
||||||
|
If neither TCG_BSWAP_OZ nor TCG_BSWAP_OS are set, then the bits of
|
||||||
|
t0 above bit 15 may contain any value.
|
||||||
|
|
||||||
* bswap32_i32/i64 t0, t1
|
* bswap32_i64 t0, t1, flags
|
||||||
|
|
||||||
32 bit byte swap on a 32/64 bit value. With a 64 bit value, it assumes that
|
32 bit byte swap on a 64-bit value. The flags are the same as for bswap16,
|
||||||
the four high order bytes are set to zero.
|
except they apply from bit 31 instead of bit 15.
|
||||||
|
|
||||||
* bswap64_i64 t0, t1
|
* bswap32_i32 t0, t1, flags
|
||||||
|
* bswap64_i64 t0, t1, flags
|
||||||
|
|
||||||
64 bit byte swap
|
32/64 bit byte swap. The flags are ignored, but still present
|
||||||
|
for consistency with the other bswap opcodes.
|
||||||
|
|
||||||
* discard_i32/i64 t0
|
* discard_i32/i64 t0
|
||||||
|
|
||||||
|
|
13
tcg/tcg-op.c
13
tcg/tcg-op.c
|
@ -1005,7 +1005,8 @@ void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
|
||||||
void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
|
void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
|
||||||
{
|
{
|
||||||
if (TCG_TARGET_HAS_bswap16_i32) {
|
if (TCG_TARGET_HAS_bswap16_i32) {
|
||||||
tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
|
tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OZ);
|
||||||
} else {
|
} else {
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||||
|
|
||||||
|
@ -1020,7 +1021,7 @@ void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
|
||||||
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
|
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
|
||||||
{
|
{
|
||||||
if (TCG_TARGET_HAS_bswap32_i32) {
|
if (TCG_TARGET_HAS_bswap32_i32) {
|
||||||
tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
|
tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
|
||||||
} else {
|
} else {
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||||
|
@ -1661,7 +1662,8 @@ void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
|
||||||
tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
|
tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
|
||||||
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
|
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
|
||||||
} else if (TCG_TARGET_HAS_bswap16_i64) {
|
} else if (TCG_TARGET_HAS_bswap16_i64) {
|
||||||
tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
|
tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OZ);
|
||||||
} else {
|
} else {
|
||||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
@ -1680,7 +1682,8 @@ void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
|
||||||
tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
|
tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
|
||||||
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
|
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
|
||||||
} else if (TCG_TARGET_HAS_bswap32_i64) {
|
} else if (TCG_TARGET_HAS_bswap32_i64) {
|
||||||
tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
|
tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OZ);
|
||||||
} else {
|
} else {
|
||||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
@ -1717,7 +1720,7 @@ void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
|
||||||
tcg_temp_free_i32(t0);
|
tcg_temp_free_i32(t0);
|
||||||
tcg_temp_free_i32(t1);
|
tcg_temp_free_i32(t1);
|
||||||
} else if (TCG_TARGET_HAS_bswap64_i64) {
|
} else if (TCG_TARGET_HAS_bswap64_i64) {
|
||||||
tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
|
tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
|
||||||
} else {
|
} else {
|
||||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
|
28
tcg/tcg.c
28
tcg/tcg.c
|
@ -1778,6 +1778,14 @@ static const char * const alignment_name[(MO_AMASK >> MO_ASHIFT) + 1] = {
|
||||||
[MO_ALIGN_64 >> MO_ASHIFT] = "al64+",
|
[MO_ALIGN_64 >> MO_ASHIFT] = "al64+",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char bswap_flag_name[][6] = {
|
||||||
|
[TCG_BSWAP_IZ] = "iz",
|
||||||
|
[TCG_BSWAP_OZ] = "oz",
|
||||||
|
[TCG_BSWAP_OS] = "os",
|
||||||
|
[TCG_BSWAP_IZ | TCG_BSWAP_OZ] = "iz,oz",
|
||||||
|
[TCG_BSWAP_IZ | TCG_BSWAP_OS] = "iz,os",
|
||||||
|
};
|
||||||
|
|
||||||
static inline bool tcg_regset_single(TCGRegSet d)
|
static inline bool tcg_regset_single(TCGRegSet d)
|
||||||
{
|
{
|
||||||
return (d & (d - 1)) == 0;
|
return (d & (d - 1)) == 0;
|
||||||
|
@ -1921,6 +1929,26 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case INDEX_op_bswap16_i32:
|
||||||
|
case INDEX_op_bswap16_i64:
|
||||||
|
case INDEX_op_bswap32_i32:
|
||||||
|
case INDEX_op_bswap32_i64:
|
||||||
|
case INDEX_op_bswap64_i64:
|
||||||
|
{
|
||||||
|
TCGArg flags = op->args[k];
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (flags < ARRAY_SIZE(bswap_flag_name)) {
|
||||||
|
name = bswap_flag_name[flags];
|
||||||
|
}
|
||||||
|
if (name) {
|
||||||
|
col += qemu_log(",%s", name);
|
||||||
|
} else {
|
||||||
|
col += qemu_log(",$0x%" TCG_PRIlx, flags);
|
||||||
|
}
|
||||||
|
i = k = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
i = 0;
|
i = 0;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue