use USER_CPPFLAGS
[AROS.git] / arch / m68k-all / exec / setfunction.c
blob3a9f5d8a9729971ae17a4bb84cabe581a5e6923a
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Patch a library or device function
6 Lang: english
7 */
8 #include <aros/config.h>
9 #include <exec/execbase.h>
10 #include <proto/intuition.h>
11 #include <aros/libcall.h>
12 #include <proto/exec.h>
13 #include <exec/rawfmt.h>
15 #include "exec_debug.h"
16 #include "exec_intern.h"
18 #ifndef DEBUG_SetFunction
19 # define DEBUG_SetFunction 0
20 #endif
21 #undef DEBUG
22 #if DEBUG_SetFunction
23 # define DEBUG 1
24 #endif
25 #include <aros/debug.h>
26 #undef kprintf
28 /* See rom/kernel/setfunction.c for documentation */
30 /* moveb %d0, %a3@+
31 * rts
33 const ULONG m68k_string = 0x16c04e75;
34 /* addql #1, %a3@
35 * rts
37 const ULONG m68k_count = 0x52934e75;
38 /* jmp %a6@(-86 * 6)
40 const ULONG m68k_serial = 0x4eeefdfc;
42 static AROS_UFH5(APTR, myRawDoFmt,
43 AROS_UFHA(CONST_STRPTR, fmt, A0),
44 AROS_UFHA(APTR, args, A1),
45 AROS_UFHA(VOID_FUNC, putch, A2),
46 AROS_UFHA(APTR, putptr, A3),
47 AROS_UFHA(struct ExecBase *, SysBase, A6))
49 AROS_USERFUNC_INIT
51 switch ((IPTR)putch) {
52 case (IPTR)RAWFMTFUNC_STRING:
53 putch = (VOID_FUNC)&m68k_string;
54 break;
55 case (IPTR)RAWFMTFUNC_COUNT:
56 putch = (VOID_FUNC)&m68k_count;
57 break;
58 case (IPTR)RAWFMTFUNC_SERIAL:
59 putch = (VOID_FUNC)&m68k_serial;
60 break;
61 default:
62 break;
65 return AROS_UFC5(APTR, ((struct IntExecBase *)SysBase)->PlatformData.realRawDoFmt,
66 AROS_UFCA(CONST_STRPTR, fmt, A0),
67 AROS_UFCA(APTR, args, A1),
68 AROS_UFCA(VOID_FUNC, putch, A2),
69 AROS_UFCA(APTR, putptr, A3),
70 AROS_UFCA(struct ExecBase *, SysBase, A6));
72 AROS_USERFUNC_EXIT
75 AROS_LH3(APTR, SetFunction,
76 AROS_LHA(struct Library *, library, A1),
77 AROS_LHA(LONG, funcOffset, A0),
78 AROS_LHA(APTR, newFunction, D0),
79 struct ExecBase *, SysBase, 70, Exec)
81 AROS_LIBFUNC_INIT
82 APTR ret;
83 ULONG *vecaddr;
85 D(bug("SetFunction(%s, -%lx, %lx) = ", (ULONG)library->lib_Node.ln_Name, -funcOffset, (ULONG)newFunction));
88 Fix dos.library/ramlib attempts to SetFunction() CloseDevice/
89 CloseLibrary/RemDevice/RemLibrary/OpenDevice/OpenLibrary.
91 This also effectively limits the max offset to 32k, but this limit was
92 already in the original, though not really documented.
94 What happens is this: the prototype for the funcOffset says it is a
95 long, but the autodoc also says that only a0.w (lower 16 bits) is used.
96 Dos.library/ramlib only sets the lower 16 bits of a0 to the required
97 offset, without sign-extending to the upper 16 bits, in fact without
98 even clearing them. These high 16 bits will therefore contain garbage:
100 SetFunction(exec.library, 7804fe3e, fc6524) = 30303030 CloseDevice
101 SetFunction(exec.library, 3030fe62, fc6528) = 30303030 CloseLibrary
102 SetFunction(exec.library, 3030fe4a, fc651c) = 30303030 RemDevice
103 SetFunction(exec.library, 3030fe6e, fc6520) = 30303030 RemLibrary
104 SetFunction(exec.library, 3030fe44, fc6564) = 30303030 OpenDevice
105 SetFunction(exec.library, 3030fdd8, fc659a) = 30303030 OpenLibrary
107 In my [ldp] opinion, the autodoc should never have said that only A0.W
108 is used for the funcOffset, while specifying a "long" in the prototype.
109 This will stay broken and this fix will stay here until we fix
110 dos.library/ramlib.
112 if (funcOffset & 0x00008000)
114 funcOffset |= 0xffff0000;
116 else
118 funcOffset &= 0x0000ffff;
121 /* AOS 3.1's locale.library wants to trample over Exec/RawDoFmt.
122 * Since the replacement does not understand the 'magic' AROS
123 * RAWFMTFUNC_xxxx vectors, we need to install a wrapper to
124 * translate those to real functions.
126 * This should not effect AROS usage of SetFunction() of
127 * RawDoFmt, as it will only end up adding about 16 m68k
128 * instructions of overhead.
130 if (library == (APTR)SysBase && funcOffset == (-87 * LIB_VECTSIZE)) {
131 ((struct IntExecBase *)SysBase)->PlatformData.realRawDoFmt = newFunction;
132 newFunction = myRawDoFmt;
136 Arbitrate for the jumptable. This isn't enough for interrupt callable
137 functions - but it need not be.
139 Forbid();
141 /* Mark the library as changed. */
142 library->lib_Flags|=LIBF_CHANGED;
144 /* The following section is coded like this (instead of using the macros),
145 because else gcc will output 64-bit muls instructions, that are not
146 present on the 68060 (and will crash it). It's faster this way, too. :) */
147 vecaddr = (APTR)((ULONG)library + funcOffset);
149 /* Get the old vector pointer */
150 ret = (APTR)*(ULONG *)(((ULONG)vecaddr)+2);
152 /* Set new vector and jmp instruction */
153 *(UWORD *)vecaddr = 0x4ef9;
154 *(ULONG *)(((ULONG)vecaddr)+2) = (ULONG)newFunction;
156 #if 1
157 CacheClearU();
158 #else
159 /* Can't use this because there are broken programs that
160 * copy code and then call SetFunction().
162 CacheClearE(vecaddr,LIB_VECTSIZE,CACRF_ClearI|CACRF_ClearD);
163 #endif
165 /* Arbitration is no longer needed */
166 Permit();
168 /* Sum the library up again */
169 SumLibrary(library);
171 D(bug("%lx\n", ret));
173 /* All done. */
174 return ret;
175 AROS_LIBFUNC_EXIT
176 } /* SetFunction */