diff options
Diffstat (limited to 'tcg')
-rw-r--r-- | tcg/README | 22 | ||||
-rw-r--r-- | tcg/tcg-op.c | 13 | ||||
-rw-r--r-- | tcg/tcg.c | 28 |
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(); @@ -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; |