Re-enabled use of AROS.Boot file due to lack of general enthusiasm for
[tangerine.git] / arch / all-linux / ppc / sigcore.h.src
blob1c6e47785960e1820a499844a369435148495e50
1 /*
2     Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3     $Id$
5     Desc: Macros to handle unix signals
6     Lang: english
7 */
9 #ifndef _SIGCORE_H
10 #define _SIGCORE_H
12 #define USE_SA_SIGINFO 1
14 #if USE_SA_SIGINFO
15 #define SIGCORE_NEED_SA_SIGINFO 1
16 #endif
17 #include <ucontext.h>
19 #include <signal.h>
20 #include "etask.h"
22 /* Put a value of type SP_TYPE on the stack or get it off the stack. */
24 #define _PUSH(sp,val)              \
25     do                             \
26     {                              \
27        SP_TYPE **stackp = (sp);    \
28        --*stackp;                  \
29        **stackp = (SP_TYPE) (val); \
30     } while (0)
31 #define _POP(sp)        (*sp++)
33 #ifndef _SIGNAL_H
34 #define _SIGNAL_H
35 #endif
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
47 #if USE_SA_SIGINFO
48 #define GLOBAL_SIGNAL_INIT \
49         static void sighandler (int sig, sigcontext_t * sc);                    \
50                                                                                 \
51         static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u)   \
52         {                                                                       \
53             sighandler(sig, (sigcontext_t *)&u->uc_pad);                        \
54         }
56 #else
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);    \
62                                                                 \
63         static void SIGHANDLER (int sig)                        \
64         {                                                       \
65             sigcontext_t *sc =                                  \
66                 (sigcontext_t *) ((BYTE *) &sig + 24 + 64);     \
67             sighandler(sig, sc);                                \
68         }
69 #endif
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
73    "SP_TYPE *". */
75 #define SP_TYPE long
77 /* How many general purpose registers are to be saved on the stack
78    when a task switch happens. */
80 #define CPU_NUMREGS     0
82 /* This structure is used to save/restore registers, because the stack is too
83    small. */
85 struct AROS_cpu_context
87     struct pt_regs            regs;
88     double                    fpregs[32];
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
112    handler instead. */
114 #define SAVE_CPU(task,sc)\
115 {                                                               \
116     long i;                                                     \
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)\
134     long i;\
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)\
140 {                                                               \
141     long i;                                                     \
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)\
159     long i;\
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)                    \
165     do                                                        \
166     {                                                         \
167         GetCpuContext(task)->regs.link = (unsigned long) addr;\
168     } while (0)
170 #define PREPARE_INITIAL_ARGS(task, args, numargs)\
172     long i;\
173     for (i = 0; i < numargs; i++)\
174         GetCpuContext(task)->regs.gpr[3+i] = args[i];\
177 #define PREPARE_INITIAL_FRAME(sp,pc)                           \
178     do                                                         \
179     {                                                          \
180         GetCpuContext(task)->regs.gpr[1] = (unsigned long) sp; \
181         GetCpuContext(task)->regs.nip    = (unsigned long) pc; \
182     } while (0)
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)          \
198 {                                                 \
199     __asm__ __volatile__ (                        \
200     "stw 2,%0 \n\t"                               \
201     : "=m"(GetCpuContext(task)->regs.gpr[2])      \
202     :                                             \
203     : "memory");                                  \
204     {                                             \
205         long i;                                   \
206         for (i = 0; i < 32; i++)                  \
207             GetCpuContext(task)->fpregs[i] = 0.0; \
208     }                                             \
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)           \
220     do                              \
221     {                               \
222         SP_TYPE **sp = GetSP(task); \
223         *sp = (SP_TYPE *)SP(sc);    \
224         SAVE_CPU(task,sc);          \
225         SAVE_FPU(task,sc);          \
226     } while(0)
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)           \
234     do                                 \
235     {                                  \
236         RESTORE_FPU(task,sc);          \
237         RESTORE_CPU(task,sc);          \
238         SP_TYPE** sp = GetSP(task);    \
239         SP(sc) = (typeof(SP(sc))) *sp; \
240     } while(0)
242 /* This macro prints the current signals' context */
244 #define PRINT_SC(sc) \
245         printf ("SC: SP=%08lx  PC=%08lx\n" \
246             , SP(sc), PC(sc) \
247         )
249 /* This macro prints the current stack (after SAVEREGS()) */
251 #define PRINT_STACK(sp) /**/
253 #endif /* _SIGCORE_H */