1  /* { dg-do run { target { { powerpc*-*-linux* && lp64 } && powerpc_altivec_ok } } } */
       2  /* { dg-options "-O2 -fprofile -mprofile-kernel -maltivec -mabi=altivec -mno-pcrel" } */
       3  #include <stdarg.h>
       4  #include <signal.h>
       5  #include <altivec.h>
       6  #include <stdlib.h>
       7  
       8  /* Testcase to check for ABI compliance of parameter passing
       9     for the PowerPC64 ABI.  */
      10  
      11  void __attribute__((no_instrument_function))
      12  sig_ill_handler (int sig)
      13  {
      14      exit(0);
      15  }
      16  
      17  extern void abort (void);
      18  
      19  typedef struct
      20  {
      21    unsigned long gprs[8];
      22    double fprs[13];
      23    long pad;
      24    vector int vrs[12];
      25  } reg_parms_t;
      26  
      27  volatile reg_parms_t gparms;
      28  
      29  /* _mcount call is done on Linux ppc64 early in the prologue.
      30     my_mcount will provide a entry point _mcount,
      31     which will save all parameter registers to gparms.
      32     Note that _mcount needs to restore lr to original value,
      33     therefore use ctr to return.
      34  */
      35  
      36  extern void my_mcount (void) asm ("_mcount");
      37  void __attribute__((no_instrument_function, no_split_stack))
      38  my_mcount (void)
      39  {
      40    asm volatile ("mflr 12\n\t"
      41  		"mtctr 12\n\t"
      42  		"mtlr 0\n\t"
      43  		"addis 12,2,gparms@got@ha\n\t"
      44  		"ld 12,gparms@got@l(12)\n\t"
      45  		"std 3,0(12)\n\t"
      46  		"std 4,8(12)\n\t"
      47  		"std 5,16(12)\n\t"
      48  		"std 6,24(12)\n\t"
      49  		"std 7,32(12)\n\t"
      50  		"std 8,40(12)\n\t"
      51  		"std 9,48(12)\n\t"
      52  		"std 10,56(12)\n\t"
      53  		"stfd 1,64(12)\n\t"
      54  		"stfd 2,72(12)\n\t"
      55  		"stfd 3,80(12)\n\t"
      56  		"stfd 4,88(12)\n\t"
      57  		"stfd 5,96(12)\n\t"
      58  		"stfd 6,104(12)\n\t"
      59  		"stfd 7,112(12)\n\t"
      60  		"stfd 8,120(12)\n\t"
      61  		"stfd 9,128(12)\n\t"
      62  		"stfd 10,136(12)\n\t"
      63  		"stfd 11,144(12)\n\t"
      64  		"stfd 12,152(12)\n\t"
      65  		"stfd 13,160(12)\n\t"
      66  		"li 0,176\n\t"
      67  		"stvx 2,12,0\n\t"
      68  		"li 0,192\n\t"
      69  		"stvx 3,12,0\n\t"
      70  		"li 0,208\n\t"
      71  		"stvx 4,12,0\n\t"
      72  		"li 0,224\n\t"
      73  		"stvx 5,12,0\n\t"
      74  		"li 0,240\n\t"
      75  		"stvx 6,12,0\n\t"
      76  		"li 0,256\n\t"
      77  		"stvx 7,12,0\n\t"
      78  		"li 0,272\n\t"
      79  		"stvx 8,12,0\n\t"
      80  		"li 0,288\n\t"
      81  		"stvx 9,12,0\n\t"
      82  		"li 0,304\n\t"
      83  		"stvx 10,12,0\n\t"
      84  		"li 0,320\n\t"
      85  		"stvx 11,12,0\n\t"
      86  		"li 0,336\n\t"
      87  		"stvx 12,12,0\n\t"
      88  		"li 0,352\n\t"
      89  		"stvx 13,12,0\n\t"
      90  		"bctr");
      91  }
      92  
      93  /* Stackframe structure relevant for parameter passing.  */
      94  typedef union
      95  {
      96    double d;
      97    unsigned long l;
      98    unsigned int i[2];
      99  } parm_t;
     100  
     101  typedef struct sf
     102  {
     103    struct sf *backchain;
     104    long a1;
     105    long a2;
     106    long a3;
     107  #if _CALL_ELF != 2
     108    long a4;
     109    long a5;
     110  #endif
     111    parm_t slot[100];
     112  } stack_frame_t;
     113  
     114  typedef union
     115  {
     116    unsigned int i[4];
     117    unsigned long l[2];
     118    vector int v;
     119  } vector_int_t;
     120  
     121  #ifdef __LITTLE_ENDIAN__
     122  #define MAKE_SLOT(x, y) ((long)x | ((long)y << 32))
     123  #else
     124  #define MAKE_SLOT(x, y) ((long)y | ((long)x << 32))
     125  #endif
     126  
     127  /* Paramter passing.
     128     s : gpr 3
     129     v : vpr 2
     130     i : gpr 7
     131  */
     132  void __attribute__ ((noinline))
     133  fcvi (char *s, vector int v, int i)
     134  {
     135    reg_parms_t lparms = gparms;
     136  
     137    if (s != (char *) lparms.gprs[0])
     138      abort();
     139  
     140    if (!vec_all_eq (v, lparms.vrs[0]))
     141      abort ();
     142  
     143    if ((long) i != lparms.gprs[4])
     144      abort();
     145  }
     146  /* Paramter passing.
     147     s : gpr 3
     148     v : vpr 2
     149     w : vpr 3
     150  */
     151  
     152  void __attribute__ ((noinline))
     153  fcvv (char *s, vector int v, vector int w)
     154  {
     155    vector int a, c = {6, 8, 10, 12};
     156    reg_parms_t lparms = gparms;
     157  
     158    if (s != (char *) lparms.gprs[0])
     159      abort();
     160  
     161    if (!vec_all_eq (v, lparms.vrs[0]))
     162      abort ();
     163  
     164    if (!vec_all_eq (w, lparms.vrs[1]))
     165      abort ();
     166  
     167    a = vec_add (v,w);
     168  
     169    if (!vec_all_eq (a, c))
     170      abort ();
     171  }
     172  
     173  /* Paramter passing.
     174     s : gpr 3
     175     i : gpr 4
     176     v : vpr 2
     177     w : vpr 3
     178  */
     179  void __attribute__ ((noinline))
     180  fcivv (char *s, int i, vector int v, vector int w)
     181  {
     182    vector int a, c = {6, 8, 10, 12};
     183    reg_parms_t lparms = gparms;
     184  
     185    if (s != (char *) lparms.gprs[0])
     186      abort();
     187  
     188    if ((long) i != lparms.gprs[1])
     189      abort();
     190  
     191    if (!vec_all_eq (v, lparms.vrs[0]))
     192      abort ();
     193  
     194    if (!vec_all_eq (w, lparms.vrs[1]))
     195      abort ();
     196  
     197    a = vec_add (v,w);
     198  
     199    if (!vec_all_eq (a, c))
     200      abort ();
     201  }
     202  
     203  /* Paramter passing.
     204     s : gpr 3
     205     v : slot 2-3
     206     w : slot 4-5
     207  */
     208  
     209  void __attribute__ ((noinline))
     210  fcevv (char *s, ...)
     211  {
     212    vector int a, c = {6, 8, 10, 12};
     213    vector int v,w;
     214    stack_frame_t *sp;
     215    reg_parms_t lparms = gparms;
     216    va_list arg;
     217  
     218    va_start (arg, s);
     219  
     220    if (s != (char *) lparms.gprs[0])
     221      abort();
     222  
     223    v = va_arg(arg, vector int);
     224    w = va_arg(arg, vector int);
     225    a = vec_add (v,w);
     226  
     227    if (!vec_all_eq (a, c))
     228      abort ();
     229  
     230    /* Go back one frame.  */
     231    sp = __builtin_frame_address(0);
     232    sp = sp->backchain;
     233  
     234    if (sp->slot[2].l != MAKE_SLOT (1, 2)
     235        || sp->slot[4].l !=  MAKE_SLOT (5, 6))
     236      abort();
     237  }
     238  
     239  /* Paramter passing.
     240     s : gpr 3
     241     i : gpr 4
     242     j : gpr 5
     243     v : slot 4-5
     244     w : slot 6-7
     245  */
     246  void __attribute__ ((noinline))
     247  fciievv (char *s, int i, int j, ...)
     248  {
     249    vector int a, c = {6, 8, 10, 12};
     250    vector int v,w;
     251    stack_frame_t *sp;
     252    reg_parms_t lparms = gparms;
     253    va_list arg;
     254  
     255    va_start (arg, j);
     256  
     257    if (s != (char *) lparms.gprs[0])
     258      abort();
     259  
     260    if ((long) i != lparms.gprs[1])
     261      abort();
     262  
     263    if ((long) j != lparms.gprs[2])
     264      abort();
     265  
     266    v = va_arg(arg, vector int);
     267    w = va_arg(arg, vector int);
     268    a = vec_add (v,w);
     269  
     270    if (!vec_all_eq (a, c))
     271      abort ();
     272  
     273    sp = __builtin_frame_address(0);
     274    sp = sp->backchain;
     275  
     276    if (sp->slot[4].l != MAKE_SLOT (1, 2)
     277        || sp->slot[6].l !=  MAKE_SLOT (5, 6))
     278      abort();
     279  }
     280  
     281  void __attribute__ ((noinline))
     282  fcvevv (char *s, vector int x, ...)
     283  {
     284    vector int a, c = {7, 10, 13, 16};
     285    vector int v,w;
     286    stack_frame_t *sp;
     287    reg_parms_t lparms = gparms;
     288    va_list arg;
     289  
     290    va_start (arg, x);
     291  
     292    v = va_arg(arg, vector int);
     293    w = va_arg(arg, vector int);
     294  
     295    a = vec_add (v,w);
     296    a = vec_add (a, x);
     297  
     298    if (!vec_all_eq (a, c))
     299      abort ();
     300  
     301    sp = __builtin_frame_address(0);
     302    sp = sp->backchain;
     303  
     304    if (sp->slot[4].l != MAKE_SLOT (1, 2)
     305        || sp->slot[6].l !=  MAKE_SLOT (5, 6))
     306      abort();
     307  }
     308  
     309  int __attribute__((no_instrument_function, noinline))
     310  main1()
     311  {
     312    char *s = "vv";
     313    vector int v = {1, 2, 3, 4};
     314    vector int w = {5, 6, 7, 8};
     315  
     316    fcvi (s, v, 2);
     317    fcvv (s, v, w);
     318    fcivv (s, 1, v, w);
     319    fcevv (s, v, w);
     320    fciievv (s, 1, 2, v, w);
     321    fcvevv (s, v, v, w);
     322    return 0;
     323  }
     324  
     325  int __attribute__((no_instrument_function))
     326  main()
     327  {
     328    /* Exit on systems without altivec.  */
     329    signal (SIGILL, sig_ill_handler);
     330    /* Altivec instruction, 'vor %v0,%v0,%v0'.  */
     331    asm volatile (".long 0x10000484");
     332    signal (SIGILL, SIG_DFL);
     333  
     334    return main1 ();
     335  }
     336  
     337  /* Paramter passing.
     338     Function called with no prototype.
     339     s : gpr 3
     340     v : vpr 2 gpr 5-6
     341     w : vpr 3 gpr 7-8
     342     x : vpr 4 gpr 9-10
     343     y : vpr 5 slot 8-9
     344  */
     345  void
     346  fnp_cvvvv (char *s, vector int v, vector int w,
     347  	   vector int x, vector int y)
     348  {
     349    vector int a, c = {12, 16, 20, 24};
     350    reg_parms_t lparms = gparms;
     351    stack_frame_t *sp;
     352    vector_int_t v0, v1, v2, v3;
     353  
     354    if (s != (char *) lparms.gprs[0])
     355      abort();
     356  
     357    if (!vec_all_eq (v, lparms.vrs[0]))
     358      abort ();
     359  
     360    if (!vec_all_eq (w, lparms.vrs[1]))
     361      abort ();
     362  
     363    if (!vec_all_eq (x, lparms.vrs[2]))
     364      abort ();
     365  
     366    if (!vec_all_eq (y, lparms.vrs[3]))
     367      abort ();
     368  
     369    a = vec_add (v,w);
     370    a = vec_add (a,x);
     371    a = vec_add (a,y);
     372  
     373    if (!vec_all_eq (a, c))
     374      abort ();
     375  
     376    v0.v = lparms.vrs[0];
     377    v1.v = lparms.vrs[1];
     378    v2.v = lparms.vrs[2];
     379    v3.v = lparms.vrs[3];
     380  
     381    if (v0.l[0] != lparms.gprs[2])
     382      abort ();
     383  
     384    if (v0.l[1] != lparms.gprs[3])
     385      abort ();
     386  
     387    if (v1.l[0] != lparms.gprs[4])
     388      abort ();
     389  
     390    if (v1.l[1] != lparms.gprs[5])
     391      abort ();
     392  
     393    if (v2.l[0] != lparms.gprs[6])
     394      abort ();
     395  
     396    if (v2.l[1] != lparms.gprs[7])
     397      abort ();
     398  
     399    sp = __builtin_frame_address(0);
     400    sp = sp->backchain;
     401  
     402    if (sp->slot[8].l != v3.l[0])
     403      abort ();
     404  
     405    if (sp->slot[9].l != v3.l[1])
     406      abort ();
     407  }