Test for stack alignment.
[glibc.git] / sysdeps / unix / bsd / sun / sparc / sigtramp.c
blobe11f7e51d35d4277b6564888f6b48178d381b91b
1 /* Copyright (C) 1991,1992,1994,1996,1997,2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
19 #ifndef __GNUC__
20 #error This file uses GNU C extensions; you must compile with GCC.
21 #endif
23 /* Get the definition of `struct sigcontext'. */
24 #define KERNEL
25 #define sigvec sun_sigvec
26 #define sigstack sun_sigstack
27 #define sigcontext sun_sigcontext
28 #include "/usr/include/sys/signal.h"
29 #undef sigvec
30 #undef sigstack
31 #undef sigcontext
32 #undef NSIG
33 #undef SIGABRT
34 #undef SIGCLD
35 #undef SV_ONSTACK
36 #undef SV_RESETHAND
37 #undef SV_INTERRUPT
38 #undef SA_ONSTACK
39 #undef SA_NOCLDSTOP
40 #undef SIG_ERR
41 #undef SIG_DFL
42 #undef SIG_IGN
43 #undef sigmask
44 #undef SIG_BLOCK
45 #undef SIG_UNBLOCK
46 #undef SIG_SETMASK
48 #include <signal.h>
49 #include <stddef.h>
50 #include <errno.h>
52 /* Defined in __sigvec.S. */
53 extern int __raw_sigvec (int sig, CONST struct sigvec *vec,
54 struct sigvec *ovec);
56 /* User-specified signal handlers. */
57 #define mytramp 1
58 #ifdef mytramp
59 static __sighandler_t handlers[NSIG];
60 #else
61 #define handlers _sigfunc
62 extern __sighandler_t _sigfunc[];
63 #endif
65 #if mytramp
67 /* Handler for all signals that are handled by a user-specified function.
68 Saves and restores the general regs %g2-%g7, the %y register, and
69 all the FPU regs (including %fsr), around calling the user's handler. */
70 static void
71 trampoline (sig)
72 int sig;
74 /* We use `double' and `long long int' so `std' (store doubleword) insns,
75 which might be faster than single-word stores, will be generated. */
76 register double f0 asm("%f0");
77 register double f2 asm("%f2");
78 register double f4 asm("%f4");
79 register double f6 asm("%f6");
80 register double f8 asm("%f8");
81 register double f10 asm("%f10");
82 register double f12 asm("%f12");
83 register double f14 asm("%f14");
84 register double f16 asm("%f16");
85 register double f18 asm("%f18");
86 register double f20 asm("%f20");
87 register double f22 asm("%f22");
88 register double f24 asm("%f24");
89 register double f26 asm("%f26");
90 register double f28 asm("%f28");
91 register double f30 asm("%f30");
92 register long long int g2 asm("%g2");
93 register long long int g4 asm("%g4");
94 register long long int g6 asm("%g6");
95 register int *fp asm("%fp");
97 int code;
98 register struct sigcontext *context asm("%i0"); /* See end of fn. */
99 void *addr;
100 int y;
101 double fpsave[16];
102 int fsr;
103 int savefpu;
104 long long int glsave[3];
106 /* SIG isn't really passed as an arg.
107 The args to the signal handler are at fp[16..19]. */
108 sig = fp[16];
109 code = fp[17];
110 context = (struct sigcontext *) fp[18];
111 addr = (PTR) fp[19];
113 /* Save the Y register. */
114 asm("rd %%y, %0" : "=r" (y));
116 /* Save the FPU regs if the FPU enable bit is set in the PSR,
117 and the signal isn't an FP exception. */
118 savefpu = (context->sc_psr & 0x1000) && sig != SIGFPE;
119 if (savefpu)
121 fpsave[0] = f0;
122 fpsave[1] = f2;
123 fpsave[2] = f4;
124 fpsave[3] = f6;
125 fpsave[4] = f8;
126 fpsave[5] = f10;
127 fpsave[6] = f12;
128 fpsave[7] = f14;
129 fpsave[8] = f16;
130 fpsave[9] = f18;
131 fpsave[10] = f20;
132 fpsave[11] = f22;
133 fpsave[12] = f24;
134 fpsave[13] = f26;
135 fpsave[14] = f28;
136 fpsave[15] = f30;
138 /* Force it into a stack slot so the asm won't barf. Sigh. */
139 (void) &fsr;
140 asm("st %%fsr, %0" : "=m" (fsr));
143 /* Save the global registers (except for %g1, which is a scratch reg). */
144 glsave[0] = g2;
145 glsave[1] = g4;
146 glsave[2] = g6;
148 /* Call the user's handler. */
149 (*((void (*) (int sig, int code, struct sigcontext *context,
150 void *addr)) handlers[sig]))
151 (sig, code, context, addr);
153 /* Restore the Y register. */
154 asm("mov %0, %%y" : : "r" (y));
156 if (savefpu)
158 /* Restore the FPU regs. */
159 f0 = fpsave[0];
160 f2 = fpsave[1];
161 f4 = fpsave[2];
162 f6 = fpsave[3];
163 f8 = fpsave[4];
164 f10 = fpsave[5];
165 f12 = fpsave[6];
166 f14 = fpsave[7];
167 f16 = fpsave[8];
168 f18 = fpsave[9];
169 f20 = fpsave[10];
170 f22 = fpsave[11];
171 f24 = fpsave[12];
172 f26 = fpsave[13];
173 f28 = fpsave[14];
174 f30 = fpsave[15];
176 asm("ld %0, %%fsr" : : "m" (fsr));
179 /* Restore the globals. */
180 g2 = glsave[0];
181 g4 = glsave[1];
182 g6 = glsave[2];
184 /* Unwind a frame, and do a "sigcleanup" system call.
185 The system call apparently does a return.
186 I don't know what it's for. Ask Sun. */
187 asm("restore %%g0, 139, %%g1\n"
188 "ta 0\n"
189 "! this should be i0: %0" /* Useless insn that will never be executed, */
190 /* here to make the compiler happy. */
191 : /* No outputs. */ :
192 /* CONTEXT is bound to %i0. We reference it as an input here to make
193 sure the compiler considers it live at this point, and preserves
194 the value in that register. The restore makes %i0 become %o0, the
195 argument to the system call. */
196 "r" (context));
198 #endif
201 __sigvec (sig, vec, ovec)
202 int sig;
203 const struct sigvec *vec;
204 struct sigvec *ovec;
206 #ifndef mytramp
207 extern void _sigtramp (int);
208 #define trampoline _sigtramp
209 #endif
210 struct sigvec myvec;
211 int mask;
212 __sighandler_t ohandler;
214 if (sig <= 0 || sig >= NSIG)
216 __set_errno (EINVAL);
217 return -1;
220 mask = __sigblock (sigmask(sig));
222 ohandler = handlers[sig];
224 if (vec != NULL &&
225 vec->sv_handler != SIG_IGN && vec->sv_handler != SIG_DFL)
227 handlers[sig] = vec->sv_handler;
228 myvec = *vec;
229 myvec.sv_handler = trampoline;
230 vec = &myvec;
233 if (__raw_sigvec(sig, vec, ovec) < 0)
235 int save = errno;
236 (void) __sigsetmask(mask);
237 errno = save;
238 return -1;
241 if (ovec != NULL && ovec->sv_handler == trampoline)
242 ovec->sv_handler = ohandler;
244 (void) __sigsetmask (mask);
246 return 0;