1/* Verify that unwinding can find SPE registers in signal frames.  */
2/* Origin: Joseph Myers <joseph@codesourcery.com> */
3/* { dg-do run { target { powerpc*-*-linux* && powerpc_spe } } } */
4/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */
5
6#include <unwind.h>
7#include <stdlib.h>
8#include <signal.h>
9#include <string.h>
10
11int count;
12char *null;
13int found_reg;
14
15typedef int v2si __attribute__((__vector_size__(8)));
16
17v2si v1 = { 123, 234 };
18v2si v2 = { 345, 456 };
19
20static _Unwind_Reason_Code
21force_unwind_stop (int version, _Unwind_Action actions,
22                   _Unwind_Exception_Class exc_class,
23                   struct _Unwind_Exception *exc_obj,
24                   struct _Unwind_Context *context,
25                   void *stop_parameter)
26{
27  unsigned int reg;
28  if (actions & _UA_END_OF_STACK)
29    abort ();
30  if (_Unwind_GetGR (context, 1215) == 123)
31    found_reg = 1;
32  return _URC_NO_REASON;
33}
34
35static void force_unwind ()
36{
37  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
38  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
39  exc->exception_cleanup = 0;
40
41#ifndef __USING_SJLJ_EXCEPTIONS__
42  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
43#else
44  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
45#endif
46
47  abort ();
48}
49
50static void counter (void *p __attribute__((unused)))
51{
52  ++count;
53}
54
55static void handler (void *p __attribute__((unused)))
56{
57  if (count != 2)
58    abort ();
59  if (!found_reg)
60    abort ();
61  exit (0);
62}
63
64static int __attribute__((noinline)) fn5 ()
65{
66  char dummy __attribute__((cleanup (counter)));
67  force_unwind ();
68  return 0;
69}
70
71static void fn4 (int sig)
72{
73  char dummy __attribute__((cleanup (counter)));
74  /* Clobber high part without compiler's knowledge so the only saved
75     copy is from the signal frame.  */
76  asm volatile ("evmergelo 15,15,15");
77  fn5 ();
78  null = NULL;
79}
80
81static void fn3 ()
82{
83  abort ();
84}
85
86static int __attribute__((noinline)) fn2 ()
87{
88  register v2si r15 asm("r15");
89  r15 = v1;
90  asm volatile ("" : "+r" (r15));
91  *null = 0;
92  fn3 ();
93  return 0;
94}
95
96static int __attribute__((noinline)) fn1 ()
97{
98  signal (SIGSEGV, fn4);
99  signal (SIGBUS, fn4);
100  fn2 ();
101  return 0;
102}
103
104static int __attribute__((noinline)) fn0 ()
105{
106  char dummy __attribute__((cleanup (handler)));
107  fn1 ();
108  null = 0;
109  return 0;
110}
111
112int main()
113{
114  fn0 ();
115  abort ();
116}
117