aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
Diffstat (limited to 'tcg')
-rw-r--r--tcg/README22
-rw-r--r--tcg/tcg-op.c13
-rw-r--r--tcg/tcg.c28
3 files changed, 50 insertions, 13 deletions
diff --git a/tcg/README b/tcg/README
index 8510d823e3..c2e7762a37 100644
--- a/tcg/README
+++ b/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)
-* 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
-bytes are set to zero.
+16 bit byte swap on the low bits of a 32/64 bit input.
+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
-the four high order bytes are set to zero.
+32 bit byte swap on a 64-bit value. The flags are the same as for bswap16,
+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
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index dcc2ed0bbc..dc65577e2f 100644
--- a/tcg/tcg-op.c
+++ b/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)
{
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 {
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)
{
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 {
TCGv_i32 t0 = 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_movi_i32(TCGV_HIGH(ret), 0);
} 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 {
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_movi_i32(TCGV_HIGH(ret), 0);
} 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 {
TCGv_i64 t0 = 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(t1);
} 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 {
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 5e53c3348f..5150ed700e 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1778,6 +1778,14 @@ static const char * const alignment_name[(MO_AMASK >> MO_ASHIFT) + 1] = {
[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)
{
return (d & (d - 1)) == 0;
@@ -1921,6 +1929,26 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
i = 1;
}
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:
i = 0;
break;