MIPS: Add WSBW instruction to perform bswapsi2
authorDavid Guillen Fandos <david@davidgf.net>
Fri, 19 Sep 2025 16:48:10 +0000 (18:48 +0200)
committerYunQiang Su <yunqiang@isrc.iscas.ac.cn>
Tue, 2 Dec 2025 01:26:25 +0000 (09:26 +0800)
gcc/ChangeLog:

* config/mips/mips.h (ISA_HAS_WSBW): Defined a new macro.
* config/mips/mips.md (bswapsi2): Add new instruction.
(wsbwsi2): Replace with expand to support both wsbw and wsbh.

gcc/testsuite/ChangeLog:

* gcc.target/mips/bswap-7.c: New test.

Signed-off-by: David Guillen Fandos <david@davidgf.net>
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/gcc.target/mips/bswap-7.c [new file with mode: 0644]

index a78f421484899d1c427fdccb9bcc9c5913048f7c..7d1fc6552d6fa244a5a02f0a0a63a891f7b97eec 100644 (file)
@@ -1263,6 +1263,9 @@ struct mips_cpu_info {
 #define ISA_HAS_WSBH           ((mips_isa_rev >= 2 && !TARGET_MIPS16)  \
                                  || TARGET_ALLEGREX)
 
+/* Similar to WSBH but for 32 bit words (byte swap within a word). */
+#define ISA_HAS_WSBW           (TARGET_ALLEGREX)
+
 /* ISA has data prefetch instructions.  This controls use of 'pref'.  */
 #define ISA_HAS_PREFETCH       ((ISA_MIPS4                             \
                                  || TARGET_LOONGSON_2EF                \
index d9aee81895966409410f969a2a34860ffdf773c4..939e51719297befc1beca09909a6c15b6ceff64a 100644 (file)
   "wsbh\t%0,%1"
   [(set_attr "type" "shift")])
 
-(define_insn_and_split "bswapsi2"
+(define_expand "bswapsi2"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+    (bswap:SI (match_operand:SI 1 "register_operand" "d")))]
+  "ISA_HAS_WSBW || (ISA_HAS_WSBH && ISA_HAS_ROR)"
+{
+  if (ISA_HAS_WSBW) {
+    emit_insn (gen_wsbwsi2 (operands[0], operands[1]));
+  }
+  else
+  {
+    rtx tmp = gen_reg_rtx (SImode);
+    emit_insn (gen_wsbh (tmp, operands[1]));
+    emit_insn (gen_rotrsi3 (operands[0], tmp, GEN_INT(16)));
+  }
+  DONE;
+})
+
+(define_insn "wsbwsi2"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (bswap:SI (match_operand:SI 1 "register_operand" "d")))]
-  "ISA_HAS_WSBH && ISA_HAS_ROR"
-  "#"
-  "&& 1"
-  [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_WSBH))
-   (set (match_dup 0) (rotatert:SI (match_dup 0) (const_int 16)))]
-  ""
-  [(set_attr "insn_count" "2")])
+  "ISA_HAS_WSBW"
+  "wsbw\t%0,%1"
+  [(set_attr "type" "shift")])
 
 (define_insn_and_split "bswapdi2"
   [(set (match_operand:DI 0 "register_operand" "=d")
diff --git a/gcc/testsuite/gcc.target/mips/bswap-7.c b/gcc/testsuite/gcc.target/mips/bswap-7.c
new file mode 100644 (file)
index 0000000..c1f923e
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-options "-march=allegrex" } */
+
+NOMIPS16 unsigned int
+foo (unsigned int x)
+{
+  return __builtin_bswap32 (x);
+}
+
+/* { dg-final { scan-assembler "\twsbw\t" } } */
This page took 0.154177 seconds and 5 git commands to generate.