diff mbox series

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

Message ID 20210614083800.1166166-14-richard.henderson@linaro.org
State Superseded
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(-)

-- 
2.25.1

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;