[PATCH] PPC64 ABI conformance

Hartmut Penner HPENNER@de.ibm.com
Fri Jan 16 13:34:00 GMT 2004


Hello,
      current ppc64 compiler does not conform to the new 64bit ABI:
Out of ABI document version 1.7:

  * If there is no known function prototype for a callee, or if the
    function prototype for a callee contains an ellipsis and the
    argument value is not part of the fixed arguments described by the
    prototype, then floating point and vector values are passed according
    to the following rules for non-floating, non-vector types.  In the
    case of no known prototype this may result in two copies of floating
    and vector argument values being passed.

Change below will generate PARALLEL to force paramater in vector register
and GPR / memory in the absence of a prototype.

OK to commit, if bootstraped / regtested ?

ChangeLog

2004-01-16  Hartmut Penner  <hpenner@de.ibm.com>

      * gcc/config/rs6000/rs6000.c (function_arg) Handle
      vector register special in function without prototype.
      (function_arg_advance): Likewise.

Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.576
diff -u -p -r1.576 rs6000.c
--- config/rs6000/rs6000.c    16 Jan 2004 07:07:27 -0000    1.576
+++ config/rs6000/rs6000.c    16 Jan 2004 13:26:27 -0000
@@ -3923,8 +3923,9 @@ function_arg_advance (CUMULATIVE_ARGS *c

       /* In variable-argument functions, vector arguments get GPRs allocated
       even if they are going to be passed in a vector register.  */
-      if (cum->stdarg && DEFAULT_ABI != ABI_V4)
-     {
+      if (DEFAULT_ABI != ABI_V4
+          && (cum->stdarg || (TARGET_64BIT && !cum->prototype)))
+        {
        int align;

        /* Vector parameters must be 16-byte aligned.  This places
@@ -4228,7 +4229,29 @@ function_arg (CUMULATIVE_ARGS *cum, enum
     }

   if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
-    return gen_rtx_REG (mode, cum->vregno);
+    if (TARGET_64BIT && ! cum->prototype)
+      {
+       /* Vector parameters get passed in vector register
+          and also in GPRs or memory, in absence of prototype.  */
+       int align_words;
+       rtx slot;
+       align_words = (cum->words + 1) & ~1;
+
+       if (align_words >= GP_ARG_NUM_REG)
+         slot = NULL_RTX;
+       else
+         slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+
+       return gen_rtx_PARALLEL (mode,
+                gen_rtvec (2,
+                           gen_rtx_EXPR_LIST (VOIDmode,
+                                              slot, const0_rtx),
+                           gen_rtx_EXPR_LIST (VOIDmode,
+                                              gen_rtx_REG (mode, cum->vregno),
+                                              const0_rtx)));
+      }
+    else
+      return gen_rtx_REG (mode, cum->vregno);
   else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
     {
       if (named || abi == ABI_V4)




Testcase ppc64-abi-2.c:

/* { dg-do run { target powerpc64-*-* } } */
/* { dg-options "-O2 -maltivec -mabi=altivec" } */
#include <stdarg.h>
#include <signal.h>
#include <altivec.h>

/* Testcase to check for ABI compliance of parameter passing
   for the PowerPC64 ABI.  */

void
sig_ill_handler (int sig)
{
  exit (0);
}

extern void abort (void);

typedef struct
{
  unsigned long gprs[8];
  double fprs[13];
  long pad;
  vector int vrs[12];
}
reg_parms_t;

reg_parms_t gparms;


/* Testcase could break on future gcc's, if parameter regs
   are changed before this asm.  */

#ifndef __MACH__
#define save_parms(lparms)                      \
    asm volatile ("ld 11,gparms@got(2)\n\t"             \
                  "std 3,0(11)\n\t"               \
                "std 4,8(11)\n\t"               \
                "std 5,16(11)\n\t"              \
                "std 6,24(11)\n\t"              \
                "std 7,32(11)\n\t"              \
                "std 8,40(11)\n\t"              \
                "std 9,48(11)\n\t"              \
                "std 10,56(11)\n\t"                   \
                  "stfd 1,64(11)\n\t"                   \
                "stfd 2,72(11)\n\t"             \
                "stfd 3,80(11)\n\t"             \
                "stfd 4,88(11)\n\t"             \
                "stfd 5,96(11)\n\t"             \
                "stfd 6,104(11)\n\t"                  \
                "stfd 7,112(11)\n\t"                  \
                "stfd 8,120(11)\n\t"                  \
                "stfd 9,128(11)\n\t"                  \
                "stfd 10,136(11)\n\t"                 \
                "stfd 11,144(11)\n\t"                 \
                "stfd 12,152(11)\n\t"                 \
                "stfd 13,160(11)\n\t"                 \
                  "li 3,176\n\t"                        \
                  "stvx 2,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 3,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 4,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 5,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 6,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 7,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 8,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 9,3,11\n\t"               \
                  "addi 3,3,16\n\t"                     \
                  "stvx 10,3,11\n\t"                    \
                  "addi 3,3,16\n\t"                     \
                  "stvx 11,3,11\n\t"                    \
                  "addi 3,3,16\n\t"                     \
                  "stvx 12,3,11\n\t"                    \
                  "addi 3,3,16\n\t"                     \
                  "stvx 13,3,11\n\t"                    \
                  "ld 3,0(11)":::"3", "4", "5", "6",    \
              "7", "8", "9", "10", "11", "memory"); \
                  lparms=gparms;
#else
#define save_parms(lparms)                      \
    asm volatile ("ld r11,gparms@got(r2)\n\t"           \
                  "std r3,0(r11)\n\t"                   \
                "std r4,8(r11)\n\t"             \
                "std r5,16(r11)\n\t"                  \
                "std r6,24(r11)\n\t"                  \
                "std r7,32(r11)\n\t"                  \
                "std r8,40(r11)\n\t"                  \
                "std r9,48(r11)\n\t"                  \
                "std r10,56(r11)\n\t"                 \
                  "stfd f1,64(r11)\n\t"                 \
                "stfd f2,72(r11)\n\t"                 \
                "stfd f3,80(r11)\n\t"                 \
                "stfd f4,88(r11)\n\t"                 \
                "stfd f5,96(r11)\n\t"                 \
                "stfd f6,104(r11)\n\t"          \
                "stfd f7,112(r11)\n\t"          \
                "stfd f8,120(r11)\n\t"          \
                "stfd f9,128(r11)\n\t"          \
                "stfd f10,136(r11)\n\t"         \
                "stfd f11,144(r11)\n\t"         \
                "stfd f12,152(r11)\n\t"               \
                "stfd f13,160(r11)\n\t"               \
                  "li r3,176\n\t"                       \
                  "stvx v2,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v3,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v4,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v5,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v6,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v7,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v8,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v9,r3,r11\n\t"                  \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v10,r3,r11\n\t"                 \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v11,r3,r11\n\t"                 \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v12,r3,r11\n\t"                 \
                  "addi r3,r3,16\n\t"                   \
                  "stvx v13,r3,r11\n\t"                 \
                  "ld r3,0(r11)":::"11", "memory");     \
                  lparms=gparms;

#endif


/* Stackframe structure relevant for parameter passing.  */
typedef union
{
  double d;
  unsigned long l;
  unsigned int i[2];
}
parm_t;

typedef struct sf
{
  struct sf *backchain;
  long a1;
  long a2;
  long a3;
  long a4;
  long a5;
  parm_t slot[100];
}
stack_frame_t;

typedef union
{
  unsigned int i[4];
  unsigned long l[2];
  vector int v;
}
vector_int_t;

/* Paramter passing.
   s : gpr 3
   v : vpr 2
   w : vpr 3
*/
void __attribute__ ((noinline))
fcvv (char *s, vector int v, vector int w)
{
  vector int a, c = { 6, 8, 10, 12 };
  reg_parms_t lparms;
  save_parms (lparms);

  if (s != (char *) lparms.gprs[0])
    abort ();

  if (!vec_all_eq (v, lparms.vrs[0]))
    abort ();

  if (!vec_all_eq (w, lparms.vrs[1]))
    abort ();

  a = vec_add (v, w);

  if (!vec_all_eq (a, c))
    abort ();
}

/* Paramter passing.
   s : gpr 3
   i : gpr 4
   v : vpr 2
   w : vpr 3
*/
void __attribute__ ((noinline))
fcivv (char *s, int i, vector int v, vector int w)
{
  vector int a, c = { 6, 8, 10, 12 };
  reg_parms_t lparms;
  save_parms (lparms);

  if (s != (char *) lparms.gprs[0])
    abort ();

  if (i != (int) lparms.gprs[1])
    abort ();

  if (!vec_all_eq (v, lparms.vrs[0]))
    abort ();

  if (!vec_all_eq (w, lparms.vrs[1]))
    abort ();

  a = vec_add (v, w);

  if (!vec_all_eq (a, c))
    abort ();
}

/* Paramter passing.
   s : gpr 3
   v : slot 2-3
   w : slot 4-5
*/

void __attribute__ ((noinline))
fce (char *s, ...)
{
  vector int a, c = { 6, 8, 10, 12 };
  vector int v, w;
  stack_frame_t *sp;
  reg_parms_t lparms;
  va_list arg;

  save_parms (lparms);
  va_start (arg, s);

  if (s != (char *) lparms.gprs[0])
    abort ();

  v = va_arg (arg, vector int);
  w = va_arg (arg, vector int);
  a = vec_add (v, w);

  if (!vec_all_eq (a, c))
    abort ();

  /* Go back one frame.  */
  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (sp->slot[2].l != 0x100000002ULL || sp->slot[4].l != 0x500000006ULL)
    abort ();
}

/* Paramter passing.
   s : gpr 3
   i : gpr 4
   j : gpr 5
   v : slot 4-5
   w : slot 6-7
*/
void __attribute__ ((noinline))
fciie (char *s, int i, int j, ...)
{
  vector int a, c = { 6, 8, 10, 12 };
  vector int v, w;
  stack_frame_t *sp;
  reg_parms_t lparms;
  va_list arg;

  save_parms (lparms);
  va_start (arg, j);

  if (s != (char *) lparms.gprs[0])
    abort ();

  if (i != (int) lparms.gprs[1])
    abort ();

  if (j != (int) lparms.gprs[2])
    abort ();

  v = va_arg (arg, vector int);
  w = va_arg (arg, vector int);
  a = vec_add (v, w);

  if (!vec_all_eq (a, c))
    abort ();

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (sp->slot[4].l != 0x100000002ULL || sp->slot[6].l != 0x500000006ULL)
    abort ();
}

void __attribute__ ((noinline))
fcve (char *s, vector int x, ...)
{
  vector int a, c = { 7, 10, 13, 16 };
  vector int v, w;
  stack_frame_t *sp;
  reg_parms_t lparms;
  va_list arg;

  save_parms (lparms);
  va_start (arg, x);

  v = va_arg (arg, vector int);
  w = va_arg (arg, vector int);

  a = vec_add (v, w);
  a = vec_add (a, x);

  if (!vec_all_eq (a, c))
    abort ();

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (sp->slot[4].l != 0x100000002ULL || sp->slot[6].l != 0x500000006ULL)
    abort ();
}

void fnp_cvvvv ();

int __attribute__ ((noinline))
main1 ()
{
  char *s = "vv";
  vector int v = { 1, 2, 3, 4 };
  vector int w = { 5, 6, 7, 8 };

  fcvv (s, v, w);
  fnp_cvvvv (s, v, w, v, w);
  fcivv (s, 1, v, w);
  fce (s, v, w);
  fciie (s, 1, 2, v, w);
  fcve (s, v, v, w);
  return 0;
}

int
main ()
{
  /* Exit on systems without altivec.  */
  signal (SIGILL, sig_ill_handler);
  /* Altivec instruction, 'vor %v0,%v0,%v0'.  */
  asm volatile (".long 0x10000484");
  signal (SIGILL, SIG_DFL);

  return main1 ();
}

/* Paramter passing.
   Function called with no prototype.
   s : gpr 3
   v : vpr 2 gpr 5-6
   w : vpr 3 gpr 7-8
*/

void __attribute__ ((noinline))
fnp_cvvvv (char *s, vector int v, vector int w)
{
  vector int a, c = { 6, 8, 10, 12 };
  reg_parms_t lparms;
  stack_frame_t *sp;
  vector_int_t v0, v1;
  save_parms (lparms);

  if (s != (char *) lparms.gprs[0])
    abort ();

  if (!vec_all_eq (v, lparms.vrs[0]))
    abort ();

  if (!vec_all_eq (w, lparms.vrs[1]))
    abort ();

  a = vec_add (v, w);

  if (!vec_all_eq (a, c))
    abort ();

  v0.v = lparms.vrs[0];
  v1.v = lparms.vrs[1];

  if (v0.l[0] != lparms.gprs[2])
    abort ();

  if (v0.l[1] != lparms.gprs[3])
    abort ();

  if (v1.l[0] != lparms.gprs[4])
    abort ();

  if (v1.l[1] != lparms.gprs[5])
    abort ();
}



More information about the Gcc-patches mailing list