Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / arch / .unmaintained / m68k-emul / sigcore.h
blob49d6e8500bca0ad4c50d7f72906214299e5a9e58
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #ifndef _SIGCORE_H
7 #define _SIGCORE_H
9 #ifdef __linux__
10 /* This is neccessary on Linux to get the sigcontext_struct */
11 # define __KERNEL__
12 #endif
13 #include <signal.h>
14 #ifdef __KERNEL__
15 # undef __KERNEL__
16 #endif
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++)
22 #ifdef __linux__
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
33 "SP_TYPE *". */
34 # define SP_TYPE long
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
44 in the program code.
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) \
65 _PUSH(sp,R0(sc)), \
66 _PUSH(sp,R1(sc)), \
67 _PUSH(sp,R2(sc)), \
68 _PUSH(sp,R3(sc))
70 # define RESTORE_CPU(sp,sc) \
71 (R3(sc) = _POP(sp)), \
72 (R2(sc) = _POP(sp)), \
73 (R1(sc) = _POP(sp)), \
74 (R0(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:
82 | |
83 +--------------------------+
84 | last entry before signal |
85 +--------------------------+
86 | empty space | <--- SP
87 +--------------------------+
88 | signal context |
89 +--------------------------+
90 | |
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*.
97 # define NO_FPU
100 Size of the FPU stackframe in stack units (one stack unit is
101 sizeof(SP_TYPE) bytes).
103 # ifndef NO_FPU
104 # define FPU_FRAMESIZE (sizeof (struct _fpstate) / sizeof (SP_TYPE))
105 # else
106 # define FPU_FRAMESIZE 0
107 # endif
110 This macro return 1 if a FPU is available.
112 # ifndef NO_FPU
113 # define HAS_FPU(sc) (sc->sc_fpstate)
114 # else
115 # define HAS_FPU(sc) 0
116 # endif
119 Save and restore the FPU on/from the stack.
121 # ifndef NO_FPU
122 # define SAVE_FPU(sp,sc) \
123 (sp -= FPU_FRAMESIZE), \
124 HAS_FPU(sc) && \
125 ((*((struct _fpstate *)sp) = *(sc->fpstate)), 1)
127 # define RESTORE_FPU(sp,sc) \
128 HAS_FPU(sc) && \
129 ((*(sc->fpstate) = *((struct _fpstate *)sp)), 1), \
130 (sp += FPU_FRAMESIZE)
131 # else
132 # define SAVE_FPU(sp,sc) (sp -= 0)
133 # define RESTORE_FPU(sp,sc) (sp += 0)
134 # endif
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:
142 high adresses
143 | ... |
144 +------------------------+
145 | arguments |
146 +------------------------+
147 | return address |
148 +------------------------+
149 | old frame pointer |
150 +------------------------+
151 | local variables |
152 +------------------------+
153 | saved registers |
154 +------------------------+
155 | ... |
156 low addresses
157 stack grows from high to
158 low addresses.
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:
165 func (a,b,c);
167 then you must prepare the stack like this:
169 _PUSH(sp,c);
170 _PUSH(sp,b);
171 _PUSH(sp,a);
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
177 and so on).
180 # define PREPARE_INITIAL_FRAME(sp,pc) \
181 (_PUSH(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)), \
195 _PUSH(sp,PC(sc)), \
196 SAVE_FPU(sp,sc), \
197 SAVE_CPU(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)), \
209 (SP(sc) = (long)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__ */
229 #ifdef __FreeBSD__
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) \
249 _PUSH(sp,pc), \
250 _PUSH(sp,0), /* Frame pointer */ \
251 sp -= CPU_NUMREGS
253 # define SAVEREGS(sp,sc) \
254 sp = (long *)SP(sc), \
255 _PUSH(sp,PC(sc)), \
256 _PUSH(sp,FP(sc)), \
257 _PUSH(sp,R0(sc)), \
258 _PUSH(sp,R1(sc)), \
259 _PUSH(sp,R2(sc)), \
260 _PUSH(sp,R3(sc)), \
261 _PUSH(sp,R4(sc)), \
262 _PUSH(sp,R5(sc))
264 # define RESTOREREGS(sp,sc) \
265 R5(sc) = _POP(sp), \
266 R4(sc) = _POP(sp), \
267 R3(sc) = _POP(sp), \
268 R2(sc) = _POP(sp), \
269 R1(sc) = _POP(sp), \
270 R0(sc) = _POP(sp), \
271 FP(sc) = _POP(sp), \
272 PC(sc) = _POP(sp), \
273 SP(sc) = (long)sp
274 #endif /* __FreeBSD__ */
276 #endif /* _SIGCORE_H */