]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR target/37841: Fix SPU abi
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Oct 2008 23:45:02 +0000 (23:45 +0000)
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Oct 2008 23:45:02 +0000 (23:45 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141356 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/spu/spu.h
gcc/doc/tm.texi
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/spu/abi.c [new file with mode: 0644]

index 1beb0d0af5c00d0f9b8cff4c4f7a04e35c21561b..ec04a4d96946f4e88e31229f7dcadf734a10411d 100644 (file)
@@ -1,3 +1,15 @@
+2008-10-24  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/37841
+       * function.c (locate_and_pad_parm): If FUNCTION_ARG_ADJUST_OFFSET
+       is defined, use it to modify the constant offset.
+
+       * doc/tm.texi (FUNCTION_ARG_OFFSET): Document new macro.
+
+       * config/spu/spu.h (FUNCTION_ARG_OFFSET): New macro to move char
+       and short arguments to the correct location as mandated by the
+       ABI.
+
 2008-10-24  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        PR rtl-optimization/37769
index 578c7427cf4e657291ab3665b15c31df6e3f7ec6..4789c10387eb64e7771215d25d17c029a9f5d592 100644 (file)
@@ -354,6 +354,14 @@ targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin;       \
          : (MODE) == VOIDmode ? 1 \
         : HARD_REGNO_NREGS(CUM,MODE))
 
+
+/* The SPU ABI wants 32/64-bit types at offset 0 in the quad-word on the
+   stack.  8/16-bit types should be at offsets 3/2 respectively.  */
+#define FUNCTION_ARG_OFFSET(MODE, TYPE)                                        \
+(((TYPE) && INTEGRAL_TYPE_P (TYPE) && GET_MODE_SIZE (MODE) < 4)                \
+ ? (4 - GET_MODE_SIZE (MODE))                                          \
+ : 0)
+
 #define FUNCTION_ARG_PADDING(MODE,TYPE) upward
 
 #define PAD_VARARGS_DOWN 0
index eae7d4f424b95ad28c579ed47aacbfa1eeb26c6b..880884f5f52f60577e9c42806a0e40516efb80d0 100644 (file)
@@ -4110,6 +4110,15 @@ on the stack.  The compiler knows how to track the amount of stack space
 used for arguments without any special help.
 @end defmac
 
+
+@defmac FUNCTION_ARG_OFFSET (@var{mode}, @var{type})
+If defined, a C expression that is the number of bytes to add to the
+offset of the argument passed in memory.  This is needed for the SPU,
+which passes @code{char} and @code{short} arguments in the preferred
+slot that is in the middle of the quad word instead of starting at the
+top.
+@end defmac
+
 @defmac FUNCTION_ARG_PADDING (@var{mode}, @var{type})
 If defined, a C expression which determines whether, and in which direction,
 to pad out an argument with extra space.  The value should be of type
index 08dc95a697c479b2ab9c09187c9da984d9cf8127..b40b0dbff96673acaabb1a1e6e45fccad213fea2 100644 (file)
@@ -3473,6 +3473,10 @@ locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs,
 
   locate->size.constant -= part_size_in_regs;
 #endif /* ARGS_GROW_DOWNWARD */
+
+#ifdef FUNCTION_ARG_OFFSET
+  locate->offset.constant += FUNCTION_ARG_OFFSET (passed_mode, type);
+#endif
 }
 
 /* Round the stack offset in *OFFSET_PTR up to a multiple of BOUNDARY.
index ea653ce4b52b99a9cf6894a55601a51e70fe8476..886e542fca25f887be5a7a6d81349235f74d2b9f 100644 (file)
@@ -1,3 +1,8 @@
+2008-10-24  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/37841
+       * gcc.target/spu/abi.c: New file.
+
 2008-10-24  DJ Delorie  <dj@redhat.com>
 
        * lib/scanasm.exp (scan-assembler, scan-assembler-not,
diff --git a/gcc/testsuite/gcc.target/spu/abi.c b/gcc/testsuite/gcc.target/spu/abi.c
new file mode 100644 (file)
index 0000000..b435f1e
--- /dev/null
@@ -0,0 +1,474 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* Test that arguments are passed in the correct location according to the ABI.  */
+
+#include <stdlib.h>
+
+/* Hack to allow calling func_asm which takes 84 arguments that are scalars.
+   The function func_call takes 84 union quadword arguments, so we can check to
+   see if each scalar is passed in the correct location.  This asm glues the
+   two functions together, so that the compiler is not aware of the
+   aliasing.  */
+__asm__ ("func_asm = func_call");
+
+typedef unsigned int uqword __attribute__((mode(TI)));
+typedef int qword __attribute__((mode(TI)));
+
+union u
+{
+  uqword               uq;
+  qword                        sq;
+  double               d[2];
+  float                        f[4];
+  unsigned long long   ull[2];
+  long long            sll[2];
+  unsigned long                ul[4];
+  long                 sl[4];
+  unsigned int         ui[4];
+  int                  si[4];
+  unsigned short       us[8];
+  short                        ss[8];
+  unsigned char                uc[16];
+  signed char          sc[16];
+};
+
+
+extern void func_asm(signed char a1,
+                    unsigned char a2,
+                    short a3,
+                    unsigned short a4,
+                    int a5,
+                    unsigned int a6,
+                    long a7,
+                    unsigned long a8,
+                    long long a9,
+                    unsigned long long a10,
+                    float a11,
+                    double a12,
+                    int a13,
+                    int a14,
+                    int a15,
+                    int a16,
+                    int a17,
+                    int a18,
+                    int a19,
+                    int a20,
+                    int a21,
+                    int a22,
+                    int a23,
+                    int a24,
+                    int a25,
+                    int a26,
+                    int a27,
+                    int a28,
+                    int a29,
+                    int a30,
+                    int a31,
+                    int a32,
+                    int a33,
+                    int a34,
+                    int a35,
+                    int a36,
+                    int a37,
+                    int a38,
+                    int a39,
+                    int a40,
+                    int a41,
+                    int a42,
+                    int a43,
+                    int a44,
+                    int a45,
+                    int a46,
+                    int a47,
+                    int a48,
+                    int a49,
+                    int a50,
+                    int a51,
+                    int a52,
+                    int a53,
+                    int a54,
+                    int a55,
+                    int a56,
+                    int a57,
+                    int a58,
+                    int a59,
+                    int a60,
+                    int a61,
+                    int a62,
+                    int a63,
+                    int a64,
+                    int a65,
+                    int a66,
+                    int a67,
+                    int a68,
+                    int a69,
+                    int a70,
+                    int a71,
+                    int a72,
+                    signed char a73,
+                    unsigned char a74,
+                    short a75,
+                    unsigned short a76,
+                    int a77,
+                    unsigned int a78,
+                    long a79,
+                    unsigned long a80,
+                    long long a81,
+                    unsigned long long a82,
+                    float a83,
+                    double a84);
+
+void func_call(union u a1,
+              union u a2,
+              union u a3,
+              union u a4,
+              union u a5,
+              union u a6,
+              union u a7,
+              union u a8,
+              union u a9,
+              union u a10,
+              union u a11,
+              union u a12,
+              union u a13,
+              union u a14,
+              union u a15,
+              union u a16,
+              union u a17,
+              union u a18,
+              union u a19,
+              union u a20,
+              union u a21,
+              union u a22,
+              union u a23,
+              union u a24,
+              union u a25,
+              union u a26,
+              union u a27,
+              union u a28,
+              union u a29,
+              union u a30,
+              union u a31,
+              union u a32,
+              union u a33,
+              union u a34,
+              union u a35,
+              union u a36,
+              union u a37,
+              union u a38,
+              union u a39,
+              union u a40,
+              union u a41,
+              union u a42,
+              union u a43,
+              union u a44,
+              union u a45,
+              union u a46,
+              union u a47,
+              union u a48,
+              union u a49,
+              union u a50,
+              union u a51,
+              union u a52,
+              union u a53,
+              union u a54,
+              union u a55,
+              union u a56,
+              union u a57,
+              union u a58,
+              union u a59,
+              union u a60,
+              union u a61,
+              union u a62,
+              union u a63,
+              union u a64,
+              union u a65,
+              union u a66,
+              union u a67,
+              union u a68,
+              union u a69,
+              union u a70,
+              union u a71,
+              union u a72,
+              union u a73,
+              union u a74,
+              union u a75,
+              union u a76,
+              union u a77,
+              union u a78,
+              union u a79,
+              union u a80,
+              union u a81,
+              union u a82,
+              union u a83,
+              union u a84)
+{
+  /* arguments passed in registers */
+  if (a1.sc[3] != -1)                  /* signed char */
+    abort ();
+
+  if (a2.uc[3] != +2)                  /* unsigned char */
+    abort ();
+
+  if (a3.ss[1] != -3)                  /* short */
+    abort ();
+
+  if (a4.us[1] != +4)                  /* unsigned short */
+    abort ();
+
+  if (a5.si[0] != -5)                  /* int */
+    abort ();
+
+  if (a6.ui[0] != +6)                  /* unsigned int */
+    abort ();
+
+  if (a7.sl[0] != -7)                  /* long */
+    abort ();
+
+  if (a8.ul[0] != +8)                  /* unsigned long */
+    abort ();
+
+  if (a9.sll[0] != -9)                 /* long long */
+    abort ();
+
+  if (a10.ull[0] != +10)               /* unsigned long long */
+    abort ();
+
+  if (a11.f[0] != -11.0f)              /* float */
+    abort ();
+
+  if (a12.d[0] != +12.0)               /* double */
+    abort ();
+
+  if (a13.si[0] != -13)                        /* int */
+    abort ();
+
+  if (a14.si[0] != +14)                        /* int */
+    abort ();
+
+  if (a15.si[0] != -15)                        /* int */
+    abort ();
+
+  if (a16.si[0] != +16)                        /* int */
+    abort ();
+
+  if (a17.si[0] != -17)                        /* int */
+    abort ();
+
+  if (a18.si[0] != +18)                        /* int */
+    abort ();
+
+  if (a19.si[0] != -19)                        /* int */
+    abort ();
+
+  if (a20.si[0] != +20)                        /* int */
+    abort ();
+
+  if (a21.si[0] != -21)                        /* int */
+    abort ();
+
+  if (a22.si[0] != +22)                        /* int */
+    abort ();
+
+  if (a23.si[0] != -23)                        /* int */
+    abort ();
+
+  if (a24.si[0] != +24)                        /* int */
+    abort ();
+
+  if (a25.si[0] != -25)                        /* int */
+    abort ();
+
+  if (a26.si[0] != +26)                        /* int */
+    abort ();
+
+  if (a27.si[0] != -27)                        /* int */
+    abort ();
+
+  if (a28.si[0] != +28)                        /* int */
+    abort ();
+
+  if (a29.si[0] != -29)                        /* int */
+    abort ();
+
+  if (a30.si[0] != +30)                        /* int */
+    abort ();
+
+  if (a31.si[0] != -31)                        /* int */
+    abort ();
+
+  if (a32.si[0] != +32)                        /* int */
+    abort ();
+
+  if (a33.si[0] != -33)                        /* int */
+    abort ();
+
+  if (a34.si[0] != +34)                        /* int */
+    abort ();
+
+  if (a35.si[0] != -35)                        /* int */
+    abort ();
+
+  if (a36.si[0] != +36)                        /* int */
+    abort ();
+
+  if (a37.si[0] != -37)                        /* int */
+    abort ();
+
+  if (a38.si[0] != +38)                        /* int */
+    abort ();
+
+  if (a39.si[0] != -39)                        /* int */
+    abort ();
+
+  if (a40.si[0] != +40)                        /* int */
+    abort ();
+
+  if (a41.si[0] != -41)                        /* int */
+    abort ();
+
+  if (a42.si[0] != +42)                        /* int */
+    abort ();
+
+  if (a43.si[0] != -43)                        /* int */
+    abort ();
+
+  if (a44.si[0] != +44)                        /* int */
+    abort ();
+
+  if (a45.si[0] != -45)                        /* int */
+    abort ();
+
+  if (a46.si[0] != +46)                        /* int */
+    abort ();
+
+  if (a47.si[0] != -47)                        /* int */
+    abort ();
+
+  if (a48.si[0] != +48)                        /* int */
+    abort ();
+
+  if (a49.si[0] != -49)                        /* int */
+    abort ();
+
+  if (a50.si[0] != +50)                        /* int */
+    abort ();
+
+  if (a51.si[0] != -51)                        /* int */
+    abort ();
+
+  if (a52.si[0] != +52)                        /* int */
+    abort ();
+
+  if (a53.si[0] != -53)                        /* int */
+    abort ();
+
+  if (a54.si[0] != +54)                        /* int */
+    abort ();
+
+  if (a55.si[0] != -55)                        /* int */
+    abort ();
+
+  if (a56.si[0] != +56)                        /* int */
+    abort ();
+
+  if (a57.si[0] != -57)                        /* int */
+    abort ();
+
+  if (a58.si[0] != +58)                        /* int */
+    abort ();
+
+  if (a59.si[0] != -59)                        /* int */
+    abort ();
+
+  if (a60.si[0] != +60)                        /* int */
+    abort ();
+
+  if (a61.si[0] != -61)                        /* int */
+    abort ();
+
+  if (a62.si[0] != +62)                        /* int */
+    abort ();
+
+  if (a63.si[0] != -63)                        /* int */
+    abort ();
+
+  if (a64.si[0] != +64)                        /* int */
+    abort ();
+
+  if (a65.si[0] != -65)                        /* int */
+    abort ();
+
+  if (a66.si[0] != +66)                        /* int */
+    abort ();
+
+  if (a67.si[0] != -67)                        /* int */
+    abort ();
+
+  if (a68.si[0] != +68)                        /* int */
+    abort ();
+
+  if (a69.si[0] != -69)                        /* int */
+    abort ();
+
+  if (a70.si[0] != +70)                        /* int */
+    abort ();
+
+  if (a71.si[0] != -71)                        /* int */
+    abort ();
+
+  if (a72.si[0] != +72)                        /* int */
+    abort ();
+
+  /* arguments passed on the stack */
+  if (a73.sc[3] != -73)                        /* signed char */
+    abort ();
+
+  if (a74.uc[3] != 74)                 /* unsigned char */
+    abort ();
+
+  if (a75.ss[1] != -75)                        /* short */
+    abort ();
+
+  if (a76.us[1] != +76)                        /* unsigned short */
+    abort ();
+
+  if (a77.si[0] != -77)                        /* int */
+    abort ();
+
+  if (a78.ui[0] != +78)                        /* unsigned int */
+    abort ();
+
+  if (a79.sl[0] != -79)                        /* long */
+    abort ();
+
+  if (a80.ul[0] != +80)                        /* unsigned long */
+    abort ();
+
+  if (a81.sll[0] != -81)               /* long long */
+    abort ();
+
+  if (a82.ull[0] != +82)               /* unsigned long long */
+    abort ();
+
+  if (a83.f[0] != -83.0f)              /* float */
+    abort ();
+
+  if (a84.d[0] != +84.0)               /* double */
+    abort ();
+}
+
+int main(void)
+{
+  func_asm(-1,   +2,  -3,  +4,  -5,  +6,  -7,  +8,  -9, +10,
+          -11, +12, -13, +14, -15, +16, -17, +18, -19, +20,
+          -21, +22, -23, +24, -25, +26, -27, +28, -29, +30,
+          -31, +32, -33, +34, -35, +36, -37, +38, -39, +40,
+          -41, +42, -43, +44, -45, +46, -47, +48, -49, +50,
+          -51, +52, -53, +54, -55, +56, -57, +58, -59, +60,
+          -61, +62, -63, +64, -65, +66, -67, +68, -69, +70,
+          -71, +72, -73, +74, -75, +76, -77, +78, -79, +80,
+          -81, +82, -83, +84);
+
+  return 0;
+}