Retain the current rorw bswap16 expansion for the zero-in/zero-out case.
Otherwise, perform a wider bswap plus a right-shift or extend.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
tcg/i386/tcg-target.c.inc | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 34113388ef..98d924b91a 100644
@@ -2421,10 +2421,28 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
OP_32_64(bswap16):
- tcg_out_rolw_8(s, a0);
+ if (a2 & TCG_BSWAP_OS) {
+ /* Output must be sign-extended. */
+ if (rexw) {
+ tcg_out_bswap64(s, a0);
+ tcg_out_shifti(s, SHIFT_SAR + rexw, a0, 48);
+ } else {
+ tcg_out_bswap32(s, a0);
+ tcg_out_shifti(s, SHIFT_SAR, a0, 16);
+ }
+ } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
+ /* Output must be zero-extended, but input isn't. */
+ tcg_out_bswap32(s, a0);
+ tcg_out_shifti(s, SHIFT_SHR, a0, 16);
+ } else {
+ tcg_out_rolw_8(s, a0);
+ }
break;
OP_32_64(bswap32):
tcg_out_bswap32(s, a0);
+ if (rexw && (a2 & TCG_BSWAP_OS)) {
+ tcg_out_ext32s(s, a0, a0);
+ }
break;
OP_32_64(neg):
--
2.25.1