2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
10 /* This is neccessary on Linux to get the sigcontext_struct */
18 /* Put a value of type SP_TYPE on the stack or get it off the stack */
19 #define _PUSH(sp,val) (*--sp = (SP_TYPE)(val))
20 #define _POP(sp) (*sp++)
23 /* sigcontext_t is the type of the signals' context. Linux offers no way
24 to get this context in a legal way, so I have to use tricks. */
25 typedef struct sigcontext_struct sigcontext_t
;
27 /* name and type of the signal handler */
28 # define SIGHANDLER linux_sighandler
29 # define SIGHANDLER_T SignalHandler
31 /* Type of the values which can be stored on the stack. A variable
32 which is to be used as a stack pointer must be declared as
36 /* How many general purpose registers are to be saved on the stack
37 when a task switch happens */
38 # define CPU_NUMREGS 4
41 Macros to access the stack pointer, frame pointer and program
42 counter. The FP is the base address for accesses to arguments
43 and local variables of a function and PC is the current address
46 # define SP(sc) (sc->sc_usp)
47 # define PC(sc) (sc->sc_pc)
50 The names of the general purpose registers which are to be saved.
51 Use R and a number as name, no matter what the real name is.
52 General purpose registers (GPRs) are registers which can be
53 modified by the task (ie. data and address registers) and which are
54 not saved by the CPU when an interrupt happens.
56 # define R0(sc) (sc->sc_d0)
57 # define R1(sc) (sc->sc_d1)
58 # define R2(sc) (sc->sc_a0)
59 # define R3(sc) (sc->sc_a1)
62 Save and restore the CPU GPRs on/from the stack.
64 # define SAVE_CPU(sp,sc) \
70 # define RESTORE_CPU(sp,sc) \
71 (R3(sc) = _POP(sp)), \
72 (R2(sc) = _POP(sp)), \
73 (R1(sc) = _POP(sp)), \
77 It's not possible to do save the FPU under linux because linux
78 uses the tasks stack to save the signal context. The signal
79 context conatins the SP *before* the sigcontext was pushed on
80 this stack, so it looks like this:
83 +--------------------------+
84 | last entry before signal |
85 +--------------------------+
86 | empty space | <--- SP
87 +--------------------------+
89 +--------------------------+
93 As you can see, SP points to the empty space. Now this empty space
94 is not very big. It's big enough that one can save the CPU
95 registers but not big enough for the FPU. *sigh*.
100 Size of the FPU stackframe in stack units (one stack unit is
101 sizeof(SP_TYPE) bytes).
104 # define FPU_FRAMESIZE (sizeof (struct _fpstate) / sizeof (SP_TYPE))
106 # define FPU_FRAMESIZE 0
110 This macro return 1 if a FPU is available.
113 # define HAS_FPU(sc) (sc->sc_fpstate)
115 # define HAS_FPU(sc) 0
119 Save and restore the FPU on/from the stack.
122 # define SAVE_FPU(sp,sc) \
123 (sp -= FPU_FRAMESIZE), \
125 ((*((struct _fpstate *)sp) = *(sc->fpstate)), 1)
127 # define RESTORE_FPU(sp,sc) \
129 ((*(sc->fpstate) = *((struct _fpstate *)sp)), 1), \
130 (sp += FPU_FRAMESIZE)
132 # define SAVE_FPU(sp,sc) (sp -= 0)
133 # define RESTORE_FPU(sp,sc) (sp += 0)
137 Prepare the stack. This macro is used on the stack before a new
138 task is run for the first time. To create such a macro, you must
139 know how the system uses the stack. On Linux/i386, every stack
140 frame looks like this:
144 +------------------------+
146 +------------------------+
148 +------------------------+
149 | old frame pointer |
150 +------------------------+
152 +------------------------+
154 +------------------------+
157 stack grows from high to
160 The first routine gets no arguments, but if you want to pass
161 some to it, then you must push them on the stack before you
162 call this macro. Note that the arguments must be pushed in
163 reverse order, ie. if you want to call a function like this:
167 then you must prepare the stack like this:
172 PREPARE_INITIAL_FRAME(sp,func);
174 This is because the arguments are fetched relative to the FP
175 (ie. FP[0] is the old frame pointer, FP[1] is the return
176 address, FP[2] is the first argument, FP[3] is the second
180 # define PREPARE_INITIAL_FRAME(sp,pc) \
182 (sp -= (FPU_FRAMESIZE+CPU_NUMREGS)))
185 This macro is similar to PREPARE_INITIAL_FRAME() but also saves
186 all general purpose registers. Use this macro when you want to
187 leave the current tasks' context to save the registers. Note that
188 the argument "sp" of the macro is just the name of the stack
189 pointer. The macro will load it from the sigcontext "sc". You
190 must store the value of "sp" after the macro and hand it to
191 RESTOREREGS() below to restore this context.
193 # define SAVEREGS(sp,sc) \
194 ((sp = (long *)SP(sc)), \
200 This macro does the opposite to SAVEREGS(). It restores all
201 general purpose registers. After that, you can enter the new
202 tasks' context. Both "sp" and "sc" must be initialized.
203 The macro will save the new SP into the sigcontext "sc".
205 # define RESTOREREGS(sp,sc) \
206 (RESTORE_CPU(sp,sc), \
207 RESTORE_FPU(sp,sc), \
208 (PC(sc) = _POP(sp)), \
211 # define PRINT_SC(sc) \
212 printf (" SP=%08lx FP=%08lx PC=%08lx FPU=%s\n" \
213 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
214 , SP(sc), 0, PC(sc) \
215 , HAS_FPU(sc) ? "yes" : "no" \
216 , R0(sc), R1(sc), R2(sc), R3(sc) \
219 # define PRINT_STACK(sp) \
220 printf (" SP=%08lx PC=%08lx\n" \
221 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
222 , (ULONG)(sp+(FPU_FRAMESIZE+CPU_NUMREGS+1)) \
223 , sp[FPU_FRAMESIZE+CPU_NUMREGS] \
224 , sp[3], sp[2], sp[1], sp[0] \
227 #endif /* __linux__ */
230 typedef struct sigcontext sigcontext_t
;
231 # define SIGHANDLER bsd_sighandler
232 # define SIGHANDLER_T __sighandler_t *
234 # define SP_TYPE long
235 # define CPU_NUMREGS 6
237 # define SP(sc) (sc->sc_esp)
238 # define FP(sc) (sc->sc_ebp)
239 # define PC(sc) (sc->sc_eip)
241 # define R0(sc) (sc->sc_eax)
242 # define R1(sc) (sc->sc_ebx)
243 # define R2(sc) (sc->sc_ecx)
244 # define R3(sc) (sc->sc_edx)
245 # define R4(sc) (sc->sc_edi)
246 # define R5(sc) (sc->sc_esi)
248 # define PREPARE_INITIAL_FRAME(sp,pc) \
250 _PUSH(sp,0), /* Frame pointer */ \
253 # define SAVEREGS(sp,sc) \
254 sp = (long *)SP(sc), \
264 # define RESTOREREGS(sp,sc) \
274 #endif /* __FreeBSD__ */
276 #endif /* _SIGCORE_H */