revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / codesets / include / SDI_hook.h
blobf780bc0412833e159309161b8d3f9ff0023db227
1 #ifndef SDI_HOOK_H
2 #define SDI_HOOK_H
4 /* Includeheader
6 Name: SDI_hook.h
7 Versionstring: $VER: SDI_hook.h 1.26 (17.10.2012)
8 Authors: Dirk Stoecker, Jens Maus
9 Distribution: PD
10 Project page: http://sf.net/p/adtools/code/HEAD/tree/trunk/sdi/
11 Description: defines to hide compiler specific hook stuff
12 Id: $Id$
13 URL: $URL: https://svn.code.sf.net/p/adtools/code/trunk/sdi/SDI_hook.h $
15 1.0 21.06.02 : based on the work made for freeciv and YAM with
16 additional texts partly taken from YAM_hook.h changes made
17 by Jens Langner, largely reworked the mechanism
18 1.1 07.10.02 : added HOOKPROTONP and HOOKPROTONONP requested by Jens
19 1.2 18.10.02 : reverted to old MorphOS-method for GCC
20 1.3 08.02.04 : modified to get it compatible to AmigaOS4
21 1.4 17.02.04 : modified to get compatible to latest SDI_compiler.h changes
22 1.5 02.03.04 : added UNUSED define to OS4 hook specification so that the
23 compiler can ignore some warnings.
24 1.6 02.03.04 : added (APTR) casts to MorphOS prototype definition to
25 reduce compiler warnings.
26 1.7 04.07.04 : removed static from all DISPATCHERPROTO definitions as there
27 may be dispatchers that are of course non static.
28 1.8 07.04.05 : added MakeHookWithData (Sebastian Bauer)
29 1.9 08.04.05 : changed MorphOS hooks to use HookEntry (Ilkka Lehtoranta)
30 1.10 16.05.05 : simplified and fixed for vbcc/MorphOS (Frank Wille)
31 1.11 17.05.05 : changed cast in DISPATCHERPROTO from (void(*)()) to APTR
32 cause SDI version of the EmulLibEntry uses APTR for easy
33 usage.
34 Added #ifndef SDI_TRAP_LIB to avoid double defines when
35 combining with SDI_interrupt.h or SDI_misc.h (Guido
36 Mersmann)
37 1.12 18.05.05 : DISPATCHERPROTO wasn't working, because of the missing REG_Ax
38 definitions. Added include <emul/emulregs.h> (Guido Mersmann)
39 1.13 11.12.05 : fixed a minor typo in the PPC HOOKPROTONP macro.
40 (Jens Langner)
41 1.14 20.04.06 : unified static of MorphOs with non-MorphOS vesion
42 1.15 30.04.06 : modified to get it compatible to AROS. (Guido Mersmann)
43 1.16 06.10.06 : added new DISPATCHER() macro and separated it from the
44 DISPATCHERPROTO() definition. Now the DISPATCHERPROTO() should
45 only be used to get the correct prototype and the plain
46 DISPATCHER() for defining the dispatcher itself.
47 1.17 14.07.08 : added "_" to all UNUSED variable specifications to make sure
48 a user does not use those definition on accident.
49 1.18 20.03.09 : modified macros to be somewhat more compatible for an AROS
50 usage (Pavel Fedin)
51 1.19 25.03.09 : fixed the DISPATCHERPROTO() macros for x86_64 AROS.
52 1.20 26.03.09 : fixed m68k define checks.
53 1.21 19.05.09 : added SDISPATCHER() to generate a static dispatcher.
54 1.22 24.06.10 : fixed AROS macros (Matthias Rustler).
55 1.23 12.08.10 : added missing proto/alib.h include for AROS
56 1.24 03.03.11 : fixed AROS macros for m68k (Jason McMullan)
57 1.25 18.07.12 : added crosscall macros for functions with 1 and 2 parameters.
58 These macros are to be used in case i.e. PPC code is to be called
59 from m68k code. The function pointer must be passed with ENTRY().
60 1.26 17.10.12 : added crosscall macros for functions with 1 and 2 parameters but
61 no return value.
65 ** This is PD (Public Domain). This means you can do with it whatever you want
66 ** without any restrictions. I only ask you to tell me improvements, so I may
67 ** fix the main line of this files as well.
69 ** To keep confusion level low: When changing this file, please note it in
70 ** above history list and indicate that the change was not made by myself
71 ** (e.g. add your name or nick name).
73 ** Find the latest version of this file at:
74 ** http://sf.net/p/adtools/code/HEAD/tree/trunk/sdi/
76 ** Jens Maus <mail@jens-maus.de>
77 ** Dirk Stoecker <soft@dstoecker.de>
80 #include "SDI_compiler.h"
83 ** Hook macros to handle the creation of Hooks/Dispatchers for different
84 ** Operating System versions.
85 ** Currently AmigaOS, AROS, and MorphOS are supported.
87 ** For more information about hooks see include file <utility/hooks.h> or
88 ** the relevant descriptions in utility.library autodocs.
90 ** Example:
92 ** Creates a hook with the name "TestHook" that calls a corresponding
93 ** function "TestFunc" that will be called with a pointer "text"
94 ** (in register A1) and returns a long.
96 ** HOOKPROTONHNO(TestFunc, LONG, STRPTR text)
97 ** {
98 ** Printf(text);
99 ** return 0;
100 ** }
101 ** MakeHook(TestHook, TestFunc);
103 ** Every function that is created with HOOKPROTO* must have a MakeHook() or
104 ** MakeStaticHook() to create the corresponding hook. Best is to call this
105 ** directly after the hook function. This is required by the GCC macros.
107 ** The naming convention for the Hook Prototype macros is as followed:
109 ** HOOKPROTO[NH][NO][NP]
110 ** ^^ ^^ ^^
111 ** NoHook | NoParameter
112 ** NoObject
114 ** So a plain HOOKPROTO() creates you a Hook function that requires
115 ** 4 parameters, the "name" of the hookfunction, the "obj" in REG_A2,
116 ** the "param" in REG_A1 and a "hook" in REG_A0. Usually you will always
117 ** use NH, as the hook structure itself is nearly never required.
119 ** The DISPATCHERPROTO macro is for MUI dispatcher functions. It gets the
120 ** functionname as argument. To supply this function for use by MUI, use
121 ** The ENTRY macro, which also gets the function name as argument.
124 #if !defined(__AROS__) && (defined(_M68000) || defined(__M68000) || defined(__mc68000))
125 #define HOOKPROTO(name, ret, obj, param) static SAVEDS ASM ret \
126 name(REG(a0, struct Hook *hook), REG(a2, obj), REG(a1, param))
127 #define HOOKPROTONO(name, ret, param) static SAVEDS ASM ret \
128 name(REG(a0, struct Hook *hook), REG(a1, param))
129 #define HOOKPROTONP(name, ret, obj) static SAVEDS ASM ret \
130 name(REG(a0, struct Hook *hook), REG(a2, obj))
131 #define HOOKPROTONONP(name, ret) static SAVEDS ASM ret \
132 name(REG(a0, struct Hook *hook))
133 #define HOOKPROTONH(name, ret, obj, param) static SAVEDS ASM ret \
134 name(REG(a2, obj), REG(a1, param))
135 #define HOOKPROTONHNO(name, ret, param) static SAVEDS ASM ret \
136 name(REG(a1, param))
137 #define HOOKPROTONHNP(name, ret, obj) static SAVEDS ASM ret \
138 name(REG(a2, obj))
139 #define HOOKPROTONHNONP(name, ret) static SAVEDS ret name(void)
140 #else
141 /* NOTE: This is fine for AROS, since HookEntry will handle stack params
143 #define HOOKPROTO(name, ret, obj, param) static SAVEDS ret \
144 name(struct Hook *hook, obj, param)
145 #define HOOKPROTONO(name, ret, param) static SAVEDS ret \
146 name(struct Hook *hook, UNUSED APTR _obj, param)
147 #define HOOKPROTONP(name, ret, obj) static SAVEDS ret \
148 name(struct Hook *hook, obj, UNUSED APTR _param)
149 #define HOOKPROTONONP(name, ret) static SAVEDS ret \
150 name(struct Hook *hook, UNUSED APTR _obj, UNUSED APTR _param)
151 #define HOOKPROTONH(name, ret, obj, param) static SAVEDS ret \
152 name(UNUSED struct Hook *_hook, obj, param)
153 #define HOOKPROTONHNO(name, ret, param) static SAVEDS ret \
154 name(UNUSED struct Hook *_hook, UNUSED APTR _obj, param)
155 #define HOOKPROTONHNP(name, ret, obj) static SAVEDS ret \
156 name(UNUSED struct Hook *_hook, obj, UNUSED APTR _param)
157 #define HOOKPROTONHNONP(name, ret) static SAVEDS ret name(void)
158 #endif
160 #ifdef __MORPHOS__
162 #ifndef SDI_TRAP_LIB /* avoid defining this twice */
163 #include <proto/alib.h>
164 #include <emul/emulregs.h>
166 #define SDI_TRAP_LIB 0xFF00 /* SDI prefix to reduce conflicts */
168 struct SDI_EmulLibEntry
170 UWORD Trap;
171 UWORD pad;
172 APTR Func;
174 #endif
176 #define MakeHook(hookname, funcname) struct Hook hookname = {{NULL, NULL}, \
177 (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, NULL}
178 #define MakeHookWithData(hookname, funcname, data) struct Hook hookname = \
179 {{NULL, NULL}, (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, (APTR)data}
180 #define MakeStaticHook(hookname, funcname) static struct Hook hookname = \
181 {{NULL, NULL}, (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, NULL}
182 #define DISPATCHERPROTO(name) ULONG name(struct IClass * cl, Object * obj, \
183 Msg msg); \
184 extern const struct SDI_EmulLibEntry Gate_##name
185 #define DISPATCHER(name) \
186 struct IClass; \
187 ULONG name(struct IClass * cl, Object * obj, Msg msg); \
188 static ULONG Trampoline_##name(void) {return name((struct IClass *) \
189 REG_A0, (Object *) REG_A2, (Msg) REG_A1);} \
190 const struct SDI_EmulLibEntry Gate_##name = {SDI_TRAP_LIB, 0, \
191 (APTR) Trampoline_##name}; \
192 ULONG name(struct IClass * cl, Object * obj, Msg msg)
193 #define SDISPATCHER(name) \
194 struct IClass; \
195 static ULONG name(struct IClass * cl, Object * obj, Msg msg); \
196 static ULONG Trampoline_##name(void) {return name((struct IClass *) \
197 REG_A0, (Object *) REG_A2, (Msg) REG_A1);} \
198 static const struct SDI_EmulLibEntry Gate_##name = {SDI_TRAP_LIB, 0, \
199 (APTR) Trampoline_##name}; \
200 static ULONG name(struct IClass * cl, Object * obj, Msg msg)
201 #define CROSSCALL1(name, ret, type1, param1) \
202 static STDARGS SAVEDS ret name(type1 param1); \
203 static ret Trampoline_##name(void) \
205 ULONG *stk = (ULONG *)REG_A7; \
206 type1 param1 = (type1)stk[1]; \
207 return name(param1); \
209 static const struct SDI_EmulLibEntry Gate_##name = {SDI_TRAP_LIB, 0, \
210 (APTR) Trampoline_##name}; \
211 static STDARGS SAVEDS ret name(type1 param1, type2 param2)
212 #define CROSSCALL1NR(name, type1, param1) \
213 static STDARGS SAVEDS void name(type1 param1); \
214 static void Trampoline_##name(void) \
216 ULONG *stk = (ULONG *)REG_A7; \
217 type1 param1 = (type1)stk[1]; \
218 name(param1); \
220 static const struct SDI_EmulLibEntry Gate_##name = {SDI_TRAP_LIB, 0, \
221 (APTR) Trampoline_##name}; \
222 static STDARGS SAVEDS void name(type1 param1)
223 #define CROSSCALL2(name, ret, type1, param1, type2, param2) \
224 static STDARGS SAVEDS ret name(type1 param1, type2 param2); \
225 static ret Trampoline_##name(void) \
227 ULONG *stk = (ULONG *)REG_A7; \
228 type1 param1 = (type1)stk[1]; \
229 type2 param2 = (type2)stk[2]; \
230 return name(param1, param2); \
232 static const struct SDI_EmulLibEntry Gate_##name = {SDI_TRAP_LIB, 0, \
233 (APTR) Trampoline_##name}; \
234 static STDARGS SAVEDS ret name(type1 param1, type2 param2)
235 #define CROSSCALL2NR(name, type1, param1, type2, param2) \
236 static STDARGS SAVEDS void name(type1 param1, type2 param2); \
237 static void Trampoline_##name(void) \
239 ULONG *stk = (ULONG *)REG_A7; \
240 type1 param1 = (type1)stk[1]; \
241 type2 param2 = (type2)stk[2]; \
242 name(param1, param2); \
244 static const struct SDI_EmulLibEntry Gate_##name = {SDI_TRAP_LIB, 0, \
245 (APTR) Trampoline_##name}; \
246 static STDARGS SAVEDS void name(type1 param1, type2 param2)
247 #define ENTRY(func) (APTR)&Gate_##func
249 #elif defined(__AROS__)
250 #include <proto/alib.h>
252 #define MakeHook(hookname, funcname) struct Hook hookname = {{NULL, NULL}, \
253 (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, NULL}
254 #define MakeHookWithData(hookname, funcname, data) struct Hook hookname = \
255 {{NULL, NULL}, (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, (APTR)data}
256 #define MakeStaticHook(hookname, funcname) static struct Hook hookname = \
257 {{NULL, NULL}, (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, NULL}
258 #define DISPATCHERPROTO(name) \
259 IPTR name(struct IClass * cl, Object * obj, Msg msg); \
260 AROS_UFP3(IPTR, Gate_##name, \
261 AROS_UFPA(struct IClass *, cl, A0), \
262 AROS_UFPA(Object *, obj, A2), \
263 AROS_UFPA(Msg, msg, A1))
264 #define DISPATCHERx(x,name) \
265 x IPTR name(struct IClass * cl, Object * obj, Msg msg); \
266 x AROS_UFH3(IPTR, Gate_##name, \
267 AROS_UFHA(struct IClass *, cl, A0), \
268 AROS_UFHA(Object *, obj, A2), \
269 AROS_UFHA(Msg, msg, A1)) \
270 { AROS_USERFUNC_INIT \
271 return name(cl, obj, msg); \
272 AROS_USERFUNC_EXIT \
274 x IPTR name(struct IClass * cl, Object * obj, Msg msg)
275 #define DISPATCHER(name) DISPATCHERx(,name)
276 #define SDISPATCHER(name) DISPATCHERx(static,name)
277 #define CROSSCALL1(name, ret, type1, param1) \
278 static STDARGS SAVEDS ret Gate_##name(type1 param1)
279 #define CROSSCALL1NR(name, type1, param1) \
280 static STDARGS SAVEDS void Gate_##name(type1 param1)
281 #define CROSSCALL2(name, ret, type1, param1, type2, param2) \
282 static STDARGS SAVEDS ret Gate_##name(type1 param1, type2 param2)
283 #define CROSSCALL2NR(name, type1, param1, type2, param2) \
284 static STDARGS SAVEDS void Gate_##name(type1 param1, type2 param2)
285 #define ENTRY(func) (APTR)Gate_##func
287 #else /* !__MORPHOS__ && !__AROS__*/
289 #define MakeHook(hookname, funcname) struct Hook hookname = {{NULL, NULL}, \
290 (HOOKFUNC)funcname, NULL, NULL}
291 #define MakeHookWithData(hookname, funcname, data) struct Hook hookname = \
292 {{NULL, NULL}, (HOOKFUNC)funcname, NULL, (APTR)data}
293 #define MakeStaticHook(hookname, funcname) static struct Hook hookname = \
294 {{NULL, NULL}, (HOOKFUNC)funcname, NULL, NULL}
295 #define DISPATCHERPROTO(name) SAVEDS ASM IPTR name(REG(a0, \
296 struct IClass * cl), REG(a2, Object * obj), REG(a1, Msg msg))
297 #define DISPATCHER(name) DISPATCHERPROTO(name)
298 #define SDISPATCHER(name) static DISPATCHERPROTO(name)
299 #define CROSSCALL1(name, ret, type1, param1) \
300 static STDARGS SAVEDS ret name(type1 param1)
301 #define CROSSCALL1NR(name, type1, param1) \
302 static STDARGS SAVEDS void name(type1 param1)
303 #define CROSSCALL2(name, ret, type1, param1, type2, param2) \
304 static STDARGS SAVEDS ret name(type1 param1, type2 param2)
305 #define CROSSCALL2NR(name, type1, param1, type2, param2) \
306 static STDARGS SAVEDS void name(type1 param1, type2 param2)
307 #define ENTRY(func) (APTR)func
309 #endif
311 #define InitHook(hook, orighook, data) ((hook)->h_Entry = (orighook).h_Entry,\
312 (hook)->h_SubEntry = (orighook).h_SubEntry,(hook)->h_Data = (APTR)(data))
314 #endif /* SDI_HOOK_H */