2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
5 Desc: Macros to handle unix signals
12 #define USE_SA_SIGINFO 1
15 #define SIGCORE_NEED_SA_SIGINFO 1
22 /* Put a value of type SP_TYPE on the stack or get it off the stack. */
24 #define _PUSH(sp,val) \
27 SP_TYPE **stackp = (sp); \
29 **stackp = (SP_TYPE) (val); \
31 #define _POP(sp) (*sp++)
36 #include <bits/sigcontext.h>
38 /* sigcontext_t is the type of the signals' context. Linux offers no way
39 to get this context in a legal way, so I have to use tricks. */
40 typedef @sigcontext@ sigcontext_t;
41 typedef @sighandler@ SignalHandler;
43 /* name and type of the signal handler */
44 #define SIGHANDLER linux_sighandler
45 #define SIGHANDLER_T SignalHandler
48 #define GLOBAL_SIGNAL_INIT \
49 static void sighandler (int sig, sigcontext_t * sc); \
51 static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u) \
53 sighandler(sig, (sigcontext_t *)&u->uc_pad); \
58 // Browsing the memory sc pattern was found at offset 24 + 64.
59 // This did only work for -O0.
60 #define GLOBAL_SIGNAL_INIT \
61 static void sighandler (int sig, sigcontext_t * sc); \
63 static void SIGHANDLER (int sig) \
66 (sigcontext_t *) ((BYTE *) &sig + 24 + 64); \
67 sighandler(sig, sc); \
71 /* Type of the values which can be stored on the stack. A variable
72 which is to be used as a stack pointer must be declared as
77 /* How many general purpose registers are to be saved on the stack
78 when a task switch happens. */
82 /* This structure is used to save/restore registers, because the stack is too
85 struct AROS_cpu_context
89 struct AROS_cpu_context * sc;
92 #define SIZEOF_ALL_REGISTERS (sizeof (struct AROS_cpu_context))
93 #define GetCpuContext(task) ((struct AROS_cpu_context *)\
94 (GetIntETask(task)->iet_Context))
95 #define GetSP(task) ((SP_TYPE **)&task->tc_SPReg)
98 /* Macros to access the stack pointer and program counter,
99 PC is the current address in the program code. */
101 #define SP(sc) (sc->regs->gpr[1])
102 #define PC(sc) (sc->regs->nip)
104 /* Macros to enable or disable all signals after the signal handler
105 has returned and the normal execution commences. */
107 #define SC_DISABLE(sc) (sc->oldmask = ~0L)
108 #define SC_ENABLE(sc) (sc->oldmask = 0L)
110 /* This stuff is not used on Linux/m68k, because the signal handler context
111 doesn't contain enough registers. Some assembler is needed for the signal
114 #define SAVE_CPU(task,sc)\
117 for (i = 0; i < 32; i++) \
118 GetCpuContext(task)->regs.gpr[i] = sc->regs->gpr[i]; \
119 GetCpuContext(task)->regs.nip = sc->regs->nip; \
120 GetCpuContext(task)->regs.msr = sc->regs->msr; \
121 GetCpuContext(task)->regs.orig_gpr3 = sc->regs->orig_gpr3; \
122 GetCpuContext(task)->regs.ctr = sc->regs->ctr; \
123 GetCpuContext(task)->regs.link = sc->regs->link; \
124 GetCpuContext(task)->regs.xer = sc->regs->xer; \
125 GetCpuContext(task)->regs.ccr = sc->regs->ccr; \
126 GetCpuContext(task)->regs.trap = sc->regs->trap; \
127 GetCpuContext(task)->regs.dar = sc->regs->dar; \
128 GetCpuContext(task)->regs.dsisr = sc->regs->dsisr; \
129 GetCpuContext(task)->regs.result = sc->regs->result; \
132 #define SAVE_FPU(task,sc)\
135 for (i = 0; i < 32; i++)\
136 GetCpuContext(task)->fpregs[i] = *(double*)&(sc->regs->gpr[PT_FPR0 + 2 * i]);\
139 #define RESTORE_CPU(task,sc)\
142 for (i = 0; i < 32; i++) \
143 sc->regs->gpr[i] = GetCpuContext(task)->regs.gpr[i]; \
144 sc->regs->nip = GetCpuContext(task)->regs.nip; \
145 sc->regs->msr = GetCpuContext(task)->regs.msr; \
146 sc->regs->orig_gpr3 = GetCpuContext(task)->regs.orig_gpr3; \
147 sc->regs->ctr = GetCpuContext(task)->regs.ctr; \
148 sc->regs->link = GetCpuContext(task)->regs.link; \
149 sc->regs->xer = GetCpuContext(task)->regs.xer; \
150 sc->regs->ccr = GetCpuContext(task)->regs.ccr; \
151 sc->regs->trap = GetCpuContext(task)->regs.trap; \
152 sc->regs->dar = GetCpuContext(task)->regs.dar; \
153 sc->regs->dsisr = GetCpuContext(task)->regs.dsisr; \
154 sc->regs->result = GetCpuContext(task)->regs.result; \
157 #define RESTORE_FPU(task,sc)\
160 for (i = 0; i < 32; i++)\
161 *(double*)&(sc->regs->gpr[PT_FPR0 + 2 * i]) = GetCpuContext(task)->fpregs[i];\
164 #define PREPARE_RETURN_ADDRESS(task, addr) \
167 GetCpuContext(task)->regs.link = (unsigned long) addr;\
170 #define PREPARE_INITIAL_ARGS(task, args, numargs)\
173 for (i = 0; i < numargs; i++)\
174 GetCpuContext(task)->regs.gpr[3+i] = args[i];\
177 #define PREPARE_INITIAL_FRAME(sp,pc) \
180 GetCpuContext(task)->regs.gpr[1] = (unsigned long) sp; \
181 GetCpuContext(task)->regs.nip = (unsigned long) pc; \
184 /* For PowerPc setting up a task exception
185 is just passing the SysBase as argument
186 to the Exec_Exception, which in turn will
187 call the users exception handler. */
188 #define SETUP_EXCEPTION(sc,arg)\
190 sc->regs->gpr[3] = (unsigned long) arg;\
193 /* Prepare the cpu context
194 Sys V PPC ABI says r2 is reserved
195 so we copy the current one and it
196 will never be changed again */
197 #define PREPARE_INITIAL_CONTEXT(task,pc) \
199 __asm__ __volatile__ ( \
201 : "=m"(GetCpuContext(task)->regs.gpr[2]) \
206 for (i = 0; i < 32; i++) \
207 GetCpuContext(task)->fpregs[i] = 0.0; \
211 /* This macro is similar to PREPARE_INITIAL_FRAME() but also saves
212 all general purpose registers. Use this macro when you want to
213 leave the current tasks' context to save the registers. Note that
214 the argument "sp" of the macro is just the name of the stack
215 pointer. The macro will load it from the sigcontext "sc". You
216 must store the value of "sp" after the macro and hand it to
217 RESTOREREGS() below to restore this context. */
219 #define SAVEREGS(task,sc) \
222 SP_TYPE **sp = GetSP(task); \
223 *sp = (SP_TYPE *)SP(sc); \
228 /* This macro does the opposite to SAVEREGS(). It restores all
229 general purpose registers. After that, you can enter the new
230 tasks' context. Both "sp" and "sc" must be initialized.
231 The macro will save the new SP into the sigcontext "sc". */
233 #define RESTOREREGS(task,sc) \
236 RESTORE_FPU(task,sc); \
237 RESTORE_CPU(task,sc); \
238 SP_TYPE** sp = GetSP(task); \
239 SP(sc) = (typeof(SP(sc))) *sp; \
242 /* This macro prints the current signals' context */
244 #define PRINT_SC(sc) \
245 printf ("SC: SP=%08lx PC=%08lx\n" \
249 /* This macro prints the current stack (after SAVEREGS()) */
251 #define PRINT_STACK(sp) /**/
253 #endif /* _SIGCORE_H */