diff mbox series

[13/28] tcg/mips: Support bswap flags in tcg_out_bswap16

Message ID 20210614083800.1166166-14-richard.henderson@linaro.org (mailing list archive)
State New, archived
Headers show
Series tcg: bswap improvements | expand

Commit Message

Richard Henderson June 14, 2021, 8:37 a.m. UTC
Merge tcg_out_bswap16 and tcg_out_bswap16s.  Use the flags
in the internal uses for loads and stores.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/mips/tcg-target.c.inc | 60 ++++++++++++++++++---------------------
 1 file changed, 28 insertions(+), 32 deletions(-)

Comments

Philippe Mathieu-Daudé June 22, 2021, 6:36 a.m. UTC | #1
Hi Richard,

On 6/14/21 10:37 AM, Richard Henderson wrote:
> Merge tcg_out_bswap16 and tcg_out_bswap16s.  Use the flags
> in the internal uses for loads and stores.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  tcg/mips/tcg-target.c.inc | 60 ++++++++++++++++++---------------------
>  1 file changed, 28 insertions(+), 32 deletions(-)
> 
> diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
> index 5944448b2a..7a5634419c 100644
> --- a/tcg/mips/tcg-target.c.inc
> +++ b/tcg/mips/tcg-target.c.inc
> @@ -540,39 +540,36 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
>      }
>  }
>  
> -static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
> +static void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
>  {
> +    /* ret and arg can't be register tmp0 */
> +    tcg_debug_assert(ret != TCG_TMP0);
> +    tcg_debug_assert(arg != TCG_TMP0);
> +
>      if (use_mips32r2_instructions) {
>          tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
> -    } else {
> -        /* ret and arg can't be register at */
> -        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
> -            tcg_abort();
> +        if (flags & TCG_BSWAP_OS) {
> +            tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
> +        } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
> +            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff);
>          }
> -
> -        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
> -        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
> -        tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
> -        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
> +        return;
>      }
> -}
>  
> -static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
> -{
> -    if (use_mips32r2_instructions) {
> -        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
> -        tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
> -    } else {
> -        /* ret and arg can't be register at */
> -        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
> -            tcg_abort();
> -        }
> -
> -        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
> +    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
> +    if (!(flags & TCG_BSWAP_IZ)) {
> +        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff);
> +    }
> +    if (flags & TCG_BSWAP_OS) {
>          tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
>          tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
> -        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
> +    } else {
> +        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
> +        if (flags & TCG_BSWAP_OZ) {
> +            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
> +        }
>      }
> +    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
>  }

Do you mind including the comments (after reviewing them ;) )?

static void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg, int
flags)
{
    /* ret and arg can't be register tmp0 */
    tcg_debug_assert(ret != TCG_TMP0);
    tcg_debug_assert(arg != TCG_TMP0);

                                                        /* src = abcd
efgh */
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);      /* ret = cdab
ghef */
        if (flags & TCG_BSWAP_OS) {
            tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);   /* ret = ssss
ghef */
        } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) ==
TCG_BSWAP_OZ) {
            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff);
                                                        /* ret = 0000
ghef */
        }
        return;
    }

    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);       /* t0  = ssab
cdef */
    if (!(flags & TCG_BSWAP_IZ)) {                      /* t0  = 0000
00ef */
        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff);
    }
    if (flags & TCG_BSWAP_OS) {
        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);       /* ret = gh..
.... */
        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);       /* ret = ssss
gh.. */
    } else {
        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);        /* ret = cdef
gh.. */
        if (flags & TCG_BSWAP_OZ) {                     /* ret = 0000
gh.. */
            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
        }
    }
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); /* OZ: ret = 0000
ghef */
                                                    /* OS: ret = ssss
ghef */
}

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Richard Henderson June 22, 2021, 1:54 p.m. UTC | #2
On 6/21/21 11:36 PM, Philippe Mathieu-Daudé wrote:
>                                                          /* src = abcd
> efgh */
>      if (use_mips32r2_instructions) {
>          tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);      /* ret = cdab
> ghef */

badc -- bytes swapped in halfwords.  Also, this is a 32-bit insn, so 4 bytes is sufficient.

>          if (flags & TCG_BSWAP_OS) {
>              tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);   /* ret = ssss
> ghef */

(ssss)ssdc

Again, 32-bit insn, but implicitly sign-extending to 64-bits as per standard mips convention.

>          } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) ==
> TCG_BSWAP_OZ) {
>              tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff);
>                                                          /* ret = 0000
> ghef */

(0000)00dc.

>      tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);       /* t0  = ssab
> cdef */
>      if (!(flags & TCG_BSWAP_IZ)) {                      /* t0  = 0000
> 00ef */
>          tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff);
>      }
>      if (flags & TCG_BSWAP_OS) {
>          tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);       /* ret = gh..
> .... */
>          tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);       /* ret = ssss
> gh.. */
>      } else {
>          tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);        /* ret = cdef
> gh.. */
>          if (flags & TCG_BSWAP_OZ) {                     /* ret = 0000
> gh.. */
>              tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
>          }
>      }
>      tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); /* OZ: ret = 0000
> ghef */
>                                                      /* OS: ret = ssss
> ghef */

Something like that, yes.  I'll fix it up.


r~
diff mbox series

Patch

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 5944448b2a..7a5634419c 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -540,39 +540,36 @@  static void tcg_out_movi(TCGContext *s, TCGType type,
     }
 }
 
-static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
+static void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
 {
+    /* ret and arg can't be register tmp0 */
+    tcg_debug_assert(ret != TCG_TMP0);
+    tcg_debug_assert(arg != TCG_TMP0);
+
     if (use_mips32r2_instructions) {
         tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
-    } else {
-        /* ret and arg can't be register at */
-        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
-            tcg_abort();
+        if (flags & TCG_BSWAP_OS) {
+            tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
+        } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
+            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff);
         }
-
-        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
-        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
-        tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
-        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
+        return;
     }
-}
 
-static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
-{
-    if (use_mips32r2_instructions) {
-        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
-        tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
-    } else {
-        /* ret and arg can't be register at */
-        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
-            tcg_abort();
-        }
-
-        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
+    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
+    if (!(flags & TCG_BSWAP_IZ)) {
+        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff);
+    }
+    if (flags & TCG_BSWAP_OS) {
         tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
         tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
-        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
+    } else {
+        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
+        if (flags & TCG_BSWAP_OZ) {
+            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
+        }
     }
+    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 }
 
 static void tcg_out_bswap_subr(TCGContext *s, const tcg_insn_unit *sub)
@@ -1367,14 +1364,14 @@  static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
         break;
     case MO_UW | MO_BSWAP:
         tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
-        tcg_out_bswap16(s, lo, TCG_TMP1);
+        tcg_out_bswap16(s, lo, TCG_TMP1, TCG_BSWAP_IZ | TCG_BSWAP_OZ);
         break;
     case MO_UW:
         tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
         break;
     case MO_SW | MO_BSWAP:
         tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
-        tcg_out_bswap16s(s, lo, TCG_TMP1);
+        tcg_out_bswap16(s, lo, TCG_TMP1, TCG_BSWAP_IZ | TCG_BSWAP_OS);
         break;
     case MO_SW:
         tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
@@ -1514,8 +1511,7 @@  static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
         break;
 
     case MO_16 | MO_BSWAP:
-        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, lo, 0xffff);
-        tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
+        tcg_out_bswap16(s, TCG_TMP1, lo, 0);
         lo = TCG_TMP1;
         /* FALLTHRU */
     case MO_16:
@@ -1933,10 +1929,6 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_not_i64:
         i1 = OPC_NOR;
         goto do_unary;
-    case INDEX_op_bswap16_i32:
-    case INDEX_op_bswap16_i64:
-        i1 = OPC_WSBH;
-        goto do_unary;
     case INDEX_op_ext8s_i32:
     case INDEX_op_ext8s_i64:
         i1 = OPC_SEB;
@@ -1948,6 +1940,10 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
         break;
 
+    case INDEX_op_bswap16_i32:
+    case INDEX_op_bswap16_i64:
+        tcg_out_bswap16(s, a0, a1, a2);
+        break;
     case INDEX_op_bswap32_i32:
         tcg_out_bswap32(s, a0, a1);
         break;