This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [power7-meissner] Add __builtin_bswap{16,64} support to powerpc


Well it would be helpful to attach the patch.

[gcc]
2009-06-11  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* doc/extend.texi (PowerPC AltiVec/VSX Built-in Functions):
	Document the non-Altivec/VSX builtins.

	* config/rs6000/rs6000.c (rs6000_expand_builtin): Add
	support for __builtin_bswap16.
	(rs6000_init_builtins): Ditto.
	* config/rs6000/rs6000.h (enum rs6000_builtins): Ditto.

	* config/rs6000/rs6000.md (bswap*): Add support for 16 and 64-bit
	bswaps, including using the ldbrx/stbrx instructions on power7.

[gcc/testsuite]
2009-06-11  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/bswap16.c: New function to test swap
	functions.
	* gcc.target/powerpc/bswap32.c: Ditto.
	* gcc.target/powerpc/bswap64-1.c: Ditto.
	* gcc.target/powerpc/bswap64-2.c: Ditto.
	* gcc.target/powerpc/bswap-run.c: Ditto.

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 148152)
+++ gcc/doc/extend.texi	(working copy)
@@ -11482,6 +11482,15 @@ int vec_any_numeric (vector float);
 int vec_any_out (vector float, vector float);
 @end smallexample
 
+GCC provides a few other builtins on Powerpc to access certain instructions:
+@smallexample
+float __builtin_recipdivf (float, float);
+float __builtin_rsqrtf (float);
+double __builtin_recipdiv (double, double);
+long __builtin_bpermd (long, long);
+int __builtin_bswap16 (int);
+@end smallexample
+
 @node SPARC VIS Built-in Functions
 @subsection SPARC VIS Built-in Functions
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 148180)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -10529,6 +10529,9 @@ rs6000_expand_builtin (tree exp, rtx tar
   if (fcode == RS6000_BUILTIN_RSQRTF)
       return rs6000_expand_unop_builtin (CODE_FOR_rsqrtsf2, exp, target);
 
+  if (fcode == RS6000_BUILTIN_BSWAP_HI)
+    return rs6000_expand_unop_builtin (CODE_FOR_bswaphi2, exp, target);
+
   if (fcode == POWER7_BUILTIN_BPERMD)
     return rs6000_expand_binop_builtin (((TARGET_64BIT)
 					 ? CODE_FOR_bpermd_di
@@ -10845,6 +10848,14 @@ rs6000_init_builtins (void)
       def_builtin (MASK_POPCNTD, "__builtin_bpermd", ftype,
 		   POWER7_BUILTIN_BPERMD);
     }
+  if (TARGET_POWERPC)
+    {
+      tree ftype = builtin_function_type (SImode, SImode, VOIDmode, VOIDmode,
+					  RS6000_BUILTIN_BSWAP_HI,
+					  "__builtin_bswap16");
+      def_builtin (MASK_POWERPC, "__builtin_bswap16", ftype,
+		   RS6000_BUILTIN_BSWAP_HI);
+    }
 
 #if TARGET_XCOFF
   /* AIX libm provides clog as __clog.  */
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 148180)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -3370,6 +3370,7 @@ enum rs6000_builtins
 
   /* Power7 builtins, that aren't VSX instructions.  */
   POWER7_BUILTIN_BPERMD,
+  RS6000_BUILTIN_BSWAP_HI,
 
   RS6000_BUILTIN_COUNT
 };
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 148152)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -2266,15 +2266,108 @@ (define_expand "parity<mode>2"
     DONE;
   })
 
-(define_insn "bswapsi2"
+;; For the generation phase, restrict ourselves to registers, and let the
+;; optimization passes remove the extra moves.  Take SI input and provide SI
+;; output, and internally convert to HI.
+(define_expand "bswaphi2"
+  [(use (match_operand:SI 0 "gpc_reg_operand" ""))
+   (use (match_operand:SI 1 "gpc_reg_operand" ""))]
+  "TARGET_POWERPC"
+  {
+    rtx inp = gen_reg_rtx (HImode);
+    rtx out = gen_reg_rtx (HImode);
+
+    emit_move_insn (inp, simplify_gen_subreg (HImode, operands[1], SImode, 2));
+    emit_insn (gen_bswaphi2_internal (out, inp));
+    emit_insn (gen_zero_extendhisi2 (operands[0], out));
+    DONE;
+  })
+
+;; Since the hardware zeros the upper part of the register, save generating the
+;; AND immediate if converting to unsigned
+(define_insn "*bswaphi2_extendsi"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(zero_extend:SI
+	 (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
+  "TARGET_POWERPC"
+  "lhbrx %0,%y1"
+  [(set_attr "length" "4")
+   (set_attr "type" "load")])
+
+(define_insn "*bswaphi2_extenddi"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+	(zero_extend:DI
+	 (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
+  "TARGET_POWERPC64"
+  "lhbrx %0,%y1"
+  [(set_attr "length" "4")
+   (set_attr "type" "load")])
+
+(define_insn "bswaphi2_internal"
+  [(set (match_operand:HI 0 "reg_or_mem_operand" "=r,Z,&r")
+	(bswap:HI
+	 (match_operand:HI 1 "reg_or_mem_operand" "Z,r,r")))
+   (clobber (match_scratch:SI 2 "=X,X,&r"))]
+  "TARGET_POWERPC"
+  "@
+   lhbrx %0,%y1
+   sthbrx %1,%y0
+   #"
+  [(set_attr "length" "4,4,12")
+   (set_attr "type" "load,store,*")])
+
+(define_split
+  [(set (match_operand:HI 0 "gpc_reg_operand" "")
+	(bswap:HI (match_operand:HI 1 "gpc_reg_operand" "")))
+   (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+  "TARGET_POWERPC && reload_completed"
+  [(set (match_dup 3)
+	(zero_extract:SI (match_dup 4)
+			 (const_int 8)
+			 (const_int 16)))
+   (set (match_dup 2)
+	(and:SI (ashift:SI (match_dup 4)
+			   (const_int 8))
+		(const_int 65280)))		;; 0xff00
+   (set (match_dup 3)
+	(ior:SI (match_dup 3)
+		(match_dup 2)))]
+  "
+{
+  operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
+  operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
+}")
+
+(define_insn "*bswapsi2_extenddi"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+	(zero_extend:DI
+	 (bswap:SI (match_operand:SI 1 "memory_operand" "Z"))))]
+  "TARGET_POWERPC64"
+  "lwbrx %0,%y1"
+  [(set_attr "length" "4")
+   (set_attr "type" "load")])
+
+(define_expand "bswapsi2"
+  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
+	(bswap:SI
+	 (match_operand:SI 1 "reg_or_mem_operand" "")))]
+  ""
+{
+  if (!REG_P (operands[0]) && !REG_P (operands[1]))
+    operands[1] = force_reg (SImode, operands[1]);
+})
+
+(define_insn "*bswapsi2_internal"
   [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Z,&r")
-	(bswap:SI (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
+	(bswap:SI
+	 (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
   ""
   "@
    {lbrx|lwbrx} %0,%y1
    {stbrx|stwbrx} %1,%y0
    #"
-  [(set_attr "length" "4,4,12")])
+  [(set_attr "length" "4,4,12")
+   (set_attr "type" "load,store,*")])
 
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
@@ -2293,6 +2386,292 @@ (define_split
 		   (const_int 16)))]
   "")
 
+(define_expand "bswapdi2"
+  [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "")
+		   (bswap:DI
+		    (match_operand:DI 1 "reg_or_mem_operand" "")))
+	      (clobber (match_scratch:DI 2 ""))
+	      (clobber (match_scratch:DI 3 ""))
+	      (clobber (match_scratch:DI 4 ""))])]
+  ""
+{
+  if (!REG_P (operands[0]) && !REG_P (operands[1]))
+    operands[1] = force_reg (DImode, operands[1]);
+
+  if (TARGET_32BIT)
+    {
+      /* 32-bit needs fewer scratch registers.  */
+      emit_insn (gen_bswapdi2_32bit (operands[0], operands[1]));
+      DONE;
+    }
+})
+
+;; Power7 has ldbrx/stdbrx, so use it directly
+(define_insn "*bswapdi2_power7"
+  [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+	(bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+   (clobber (match_scratch:DI 2 "=X,X,&r"))
+   (clobber (match_scratch:DI 3 "=X,X,&r"))
+   (clobber (match_scratch:DI 4 "=X,X,&r"))]
+  "TARGET_POWERPC64 && TARGET_POPCNTD && (REG_P (operands[0]) || REG_P (operands[1]))"
+  "@
+   ldbrx %0,%y1
+   stdbrx %1,%y0
+   #"
+  [(set_attr "length" "4,4,36")
+   (set_attr "type" "load,store,*")])
+
+;; Non-power7, fall back to use lwbrx/stwbrx
+(define_insn "*bswapdi2_64bit"
+  [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+	(bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+   (clobber (match_scratch:DI 2 "=&b,&b,&r"))
+   (clobber (match_scratch:DI 3 "=&b,&r,&r"))
+   (clobber (match_scratch:DI 4 "=&b,X,&r"))]
+  "TARGET_POWERPC64 && !TARGET_POPCNTD && (REG_P (operands[0]) || REG_P (operands[1]))"
+  "#"
+  [(set_attr "length" "16,12,36")])
+
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+	(bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+   (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+   (clobber (match_operand:DI 4 "gpc_reg_operand" ""))]
+  "TARGET_POWERPC64 && !TARGET_POPCNTD && reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx dest   = operands[0];
+  rtx src    = operands[1];
+  rtx op2    = operands[2];
+  rtx op3    = operands[3];
+  rtx op4    = operands[4];
+  rtx op3_32 = simplify_gen_subreg (SImode, op3, DImode, 4);
+  rtx op4_32 = simplify_gen_subreg (SImode, op4, DImode, 4);
+  rtx addr1;
+  rtx addr2;
+  rtx word_high;
+  rtx word_low;
+
+  addr1 = XEXP (src, 0);
+  if (GET_CODE (addr1) == PLUS)
+    {
+      emit_insn (gen_adddi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+      addr1 = XEXP (addr1, 1);
+    }
+  else
+    emit_move_insn (op2, GEN_INT (4));
+
+  addr2 = gen_rtx_PLUS (DImode, op2, addr1);
+
+  if (BYTES_BIG_ENDIAN)
+    {
+      word_high = change_address (src, SImode, addr1);
+      word_low  = change_address (src, SImode, addr2);
+    }
+  else
+    {
+      word_high = change_address (src, SImode, addr2);
+      word_low  = change_address (src, SImode, addr1);
+    }
+
+  emit_insn (gen_bswapsi2 (op3_32, word_low));
+  emit_insn (gen_bswapsi2 (op4_32, word_high));
+  emit_insn (gen_ashldi3 (dest, op3, GEN_INT (32)));
+  emit_insn (gen_iordi3 (dest, dest, op4));
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
+	(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+   (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+   (clobber (match_operand:DI 4 "" ""))]
+  "TARGET_POWERPC64 && !TARGET_POPCNTD && reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx dest   = operands[0];
+  rtx src    = operands[1];
+  rtx op2    = operands[2];
+  rtx op3    = operands[3];
+  rtx src_si = simplify_gen_subreg (SImode, src, DImode, 4);
+  rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, 4);
+  rtx addr1;
+  rtx addr2;
+  rtx word_high;
+  rtx word_low;
+
+  addr1 = XEXP (dest, 0);
+  if (GET_CODE (addr1) == PLUS)
+    {
+      emit_insn (gen_adddi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+      addr1 = XEXP (addr1, 1);
+    }
+  else
+    emit_move_insn (op2, GEN_INT (4));
+
+  addr2 = gen_rtx_PLUS (DImode, op2, addr1);
+
+  emit_insn (gen_lshrdi3 (op3, src, GEN_INT (32)));
+  if (BYTES_BIG_ENDIAN)
+    {
+      word_high = change_address (dest, SImode, addr1);
+      word_low  = change_address (dest, SImode, addr2);
+      emit_insn (gen_bswapsi2 (word_high, src_si));
+      emit_insn (gen_bswapsi2 (word_low, op3_si));
+    }
+  else
+    {
+      word_high = change_address (dest, SImode, addr2);
+      word_low  = change_address (dest, SImode, addr1);
+      emit_insn (gen_bswapsi2 (word_low, src_si));
+      emit_insn (gen_bswapsi2 (word_high, op3_si));
+    }
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+	(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+   (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+   (clobber (match_operand:DI 4 "" ""))]
+  "TARGET_POWERPC64 && reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx dest    = operands[0];
+  rtx src     = operands[1];
+  rtx op2     = operands[2];
+  rtx op3     = operands[3];
+  rtx dest_si = simplify_gen_subreg (SImode, dest, DImode, 4);
+  rtx src_si  = simplify_gen_subreg (SImode, src, DImode, 4);
+  rtx op2_si  = simplify_gen_subreg (SImode, op2, DImode, 4);
+  rtx op3_si  = simplify_gen_subreg (SImode, op3, DImode, 4);
+
+  emit_insn (gen_lshrdi3 (op2, src, GEN_INT (32)));
+  emit_insn (gen_bswapsi2 (dest_si, src_si));
+  emit_insn (gen_bswapsi2 (op3_si, op2_si));
+  emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32)));
+  emit_insn (gen_iordi3 (dest, dest, op3));
+}")
+
+(define_insn "bswapdi2_32bit"
+  [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+	(bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+   (clobber (match_scratch:SI 2 "=&b,&b,X"))]
+  "TARGET_32BIT && (REG_P (operands[0]) || REG_P (operands[1]))"
+  "#"
+  [(set_attr "length" "16,12,36")])
+
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+	(bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
+   (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+  "TARGET_32BIT && reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx dest   = operands[0];
+  rtx src    = operands[1];
+  rtx op2    = operands[2];
+  rtx dest_hi = simplify_gen_subreg (SImode, dest, DImode, 0);
+  rtx dest_lo = simplify_gen_subreg (SImode, dest, DImode, 4);
+  rtx addr1;
+  rtx addr2;
+  rtx word_high;
+  rtx word_low;
+
+  addr1 = XEXP (src, 0);
+  if (GET_CODE (addr1) == PLUS)
+    {
+      emit_insn (gen_adddi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+      addr1 = XEXP (addr1, 1);
+    }
+  else
+    emit_move_insn (op2, GEN_INT (4));
+
+  addr2 = gen_rtx_PLUS (DImode, op2, addr1);
+
+  if (BYTES_BIG_ENDIAN)
+    {
+      word_high = change_address (src, SImode, addr1);
+      word_low  = change_address (src, SImode, addr2);
+    }
+  else
+    {
+      word_high = change_address (src, SImode, addr2);
+      word_low  = change_address (src, SImode, addr1);
+    }
+
+  emit_insn (gen_bswapsi2 (dest_hi, word_low));
+  emit_insn (gen_bswapsi2 (dest_lo, word_high));
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
+	(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+   (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+  "TARGET_32BIT && reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx dest     = operands[0];
+  rtx src      = operands[1];
+  rtx op2      = operands[2];
+  rtx src_high = simplify_gen_subreg (SImode, src, DImode, 0);
+  rtx src_low  = simplify_gen_subreg (SImode, src, DImode, 4);
+  rtx addr1;
+  rtx addr2;
+  rtx word_high;
+  rtx word_low;
+
+  addr1 = XEXP (dest, 0);
+  if (GET_CODE (addr1) == PLUS)
+    {
+      emit_insn (gen_addsi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+      addr1 = XEXP (addr1, 1);
+    }
+  else
+    emit_move_insn (op2, GEN_INT (4));
+
+  addr2 = gen_rtx_PLUS (SImode, op2, addr1);
+
+  if (BYTES_BIG_ENDIAN)
+    {
+      word_high = change_address (dest, SImode, addr1);
+      word_low  = change_address (dest, SImode, addr2);
+    }
+  else
+    {
+      word_high = change_address (dest, SImode, addr2);
+      word_low  = change_address (dest, SImode, addr1);
+    }
+
+  emit_insn (gen_bswapsi2 (word_high, src_low));
+  emit_insn (gen_bswapsi2 (word_low, src_high));
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+	(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+   (clobber (match_operand:SI 2 "" ""))]
+  "TARGET_32BIT && reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx dest      = operands[0];
+  rtx src       = operands[1];
+  rtx src_high  = simplify_gen_subreg (SImode, src, DImode, 0);
+  rtx src_low   = simplify_gen_subreg (SImode, src, DImode, 4);
+  rtx dest_high = simplify_gen_subreg (SImode, dest, DImode, 0);
+  rtx dest_low  = simplify_gen_subreg (SImode, dest, DImode, 4);
+
+  emit_insn (gen_bswapsi2 (dest_high, src_low));
+  emit_insn (gen_bswapsi2 (dest_low, src_high));
+}")
+
 (define_expand "mulsi3"
   [(use (match_operand:SI 0 "gpc_reg_operand" ""))
    (use (match_operand:SI 1 "gpc_reg_operand" ""))
Index: gcc/testsuite/gcc.target/powerpc/bswap64-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/bswap64-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/bswap64-2.c	(revision 0)
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -mpopcntd" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-final { scan-assembler "ldbrx" } } */
+/* { dg-final { scan-assembler "stdbrx" } } */
+
+unsigned long ul;
+unsigned long load_bswap64 (unsigned long *p) { return __builtin_bswap64 (*p); }
+void store_bswap64 (unsigned long a) { ul = __builtin_bswap64 (a); }
Index: gcc/testsuite/gcc.target/powerpc/bswap-run.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/bswap-run.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/bswap-run.c	(revision 0)
@@ -0,0 +1,102 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-options "-O2 -std=gnu99" } */
+
+extern void abort (void);
+
+static unsigned char bytes[] = { 0, 1, 2, 0x80, 0xff };
+
+unsigned short b16a (unsigned short *p) { return __builtin_bswap16 (*p); }
+void b16b (unsigned short *p, unsigned short a) { *p = __builtin_bswap16 (a); }
+int b16c (unsigned short a) { return __builtin_bswap16 (a); }
+
+unsigned int b32a (unsigned int *p) { return __builtin_bswap32 (*p); }
+void b32b (unsigned int *p, unsigned int a) { *p = __builtin_bswap32 (a); }
+static unsigned int b32c (unsigned int a) { return __builtin_bswap32 (a); }
+
+unsigned long long b64a (unsigned long long *p) { return __builtin_bswap64 (*p); }
+void b64b (unsigned long long *p, unsigned long long a) { *p = __builtin_bswap64 (a); }
+unsigned long long b64c (unsigned long long a) { return __builtin_bswap64 (a); }
+
+int
+main (void)
+{
+  unsigned i1, i2, i3, i4, i5;
+  unsigned b1, b2, b3, b4, b5;
+  unsigned short b16_inp, b16_exp, b16_var;
+  unsigned int b32_inp, b32_exp, b32_var;
+  unsigned long long b64_inp, b64_exp, b64_var;
+
+  for (i1 = 0; i1 < sizeof (bytes); i1++)
+    {
+      b1 = bytes[i1];
+      for (i2 = 0; i2 < sizeof (bytes); i2++)
+	{
+	  b2 = bytes[i2];
+	  b16_inp = (b1 << 8) | b2;
+	  b16_exp = (b2 << 8) | b1;
+
+	  if (b16a (&b16_inp) != b16_exp)
+	    abort ();
+
+	  b16b (&b16_var, b16_inp);
+	  if (b16_var != b16_exp)
+	    abort ();
+
+	  if (b16c (b16_inp) != b16_exp)
+	    abort ();
+
+	  for (i3 = 0; i3 < sizeof (bytes); i3++)
+	    {
+	      b3 = bytes[i3];
+	      for (i4 = 0; i4 < sizeof (bytes); i4++)
+		{
+		  b4 = bytes[i4];
+		  b32_inp = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+		  b32_exp = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
+
+		  if (b32a (&b32_inp) != b32_exp)
+		    abort ();
+
+		  b32b (&b32_var, b32_inp);
+		  if (b32_var != b32_exp)
+		    abort ();
+
+		  if (b32c (b32_inp) != b32_exp)
+		    abort ();
+
+		  for (i5 = 0; i5 < sizeof (bytes); i5++)
+		    {
+		      b5 = bytes[i5];
+		      b64_inp = (((unsigned long long)b32_inp) << 32) | b5;
+		      b64_exp = (((unsigned long long)b5) << 56) | b32_exp;
+
+		      if (b64a (&b64_inp) != b64_exp)
+			abort ();
+
+		      b64b (&b64_var, b64_inp);
+		      if (b64_var != b64_exp)
+			abort ();
+
+		      if (b64c (b64_inp) != b64_exp)
+			abort ();
+
+		      b64_inp = (((unsigned long long)b5) << 56) | b32_inp;
+		      b64_exp = (((unsigned long long)b32_exp) << 32) | b5;
+
+		      if (b64a (&b64_inp) != b64_exp)
+			abort ();
+
+		      b64b (&b64_var, b64_inp);
+		      if (b64_var != b64_exp)
+			abort ();
+
+		      if (b64c (b64_inp) != b64_exp)
+			abort ();
+		    }
+		}
+	    }
+	}
+    }
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/bswap16.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/bswap16.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/bswap16.c	(revision 0)
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "lhbrx" } } */
+/* { dg-final { scan-assembler "sthbrx" } } */
+
+unsigned short us;
+unsigned int load_bswap16 (unsigned short *p) { return __builtin_bswap16 (*p); }
+void store_bswap16 (unsigned int a) { us = __builtin_bswap16 (a); }
Index: gcc/testsuite/gcc.target/powerpc/bswap64-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/bswap64-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/bswap64-1.c	(revision 0)
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -mno-popcntd" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-final { scan-assembler "lwbrx" } } */
+/* { dg-final { scan-assembler "stwbrx" } } */
+
+unsigned long ul;
+unsigned long load_bswap64 (unsigned long *p) { return __builtin_bswap64 (*p); }
+void store_bswap64 (unsigned long a) { ul = __builtin_bswap64 (a); }
Index: gcc/testsuite/gcc.target/powerpc/bswap32.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/bswap32.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/bswap32.c	(revision 0)
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "lwbrx" } } */
+/* { dg-final { scan-assembler "stwbrx" } } */
+
+unsigned int ui;
+unsigned int load_bswap32 (unsigned int *p) { return __builtin_bswap32 (*p); }
+void store_bswap32 (unsigned int a) { ui = __builtin_bswap32 (a); }
Index: gcc/testsuite/ChangeLog.power7
===================================================================
--- gcc/testsuite/ChangeLog.power7	(revision 148152)
+++ gcc/testsuite/ChangeLog.power7	(working copy)
@@ -1,3 +1,12 @@
+2009-06-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+	* gcc.target/powerpc/bswap16.c: New function to test swap
+	functions.
+	* gcc.target/powerpc/bswap32.c: Ditto.
+	* gcc.target/powerpc/bswap64-1.c: Ditto.
+	* gcc.target/powerpc/bswap64-2.c: Ditto.
+	* gcc.target/powerpc/bswap-run.c: Ditto.
+	
 2009-05-12  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
 	* gcc.target/powerpc/altivec-6.c: Make sure the result of vec_add

-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]