ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/thunks.cpp
Revision: 1.9
Committed: 2004-04-22T22:54:46Z (20 years, 7 months ago) by gbeauche
Branch: MAIN
Changes since 1.8: +6 -6 lines
Log Message:
Extend NativeOp count to 64 (6-bit value), aka fix NATIVE_FILLRECT opcpdes.
Translate NQD_{bitblt,fillrect,invrect} to direct native calls.
Use Mac2HostAddr() for converting Mac base address to native.

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * thunks.cpp - Thunks to share data and code with MacOS
3     *
4     * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22     #include "thunks.h"
23     #include "emul_op.h"
24     #include "cpu_emulation.h"
25 gbeauche 1.6 #include "xlowmem.h"
26 gbeauche 1.1
27     // Native function declarations
28     #include "main.h"
29     #include "video.h"
30     #include "name_registry.h"
31     #include "serial.h"
32     #include "ether.h"
33 gbeauche 1.2 #include "macos_util.h"
34 gbeauche 1.1
35 gbeauche 1.6 // Generate PowerPC thunks for GetResource() replacements?
36     #define POWERPC_GET_RESOURCE_THUNKS 1
37    
38 gbeauche 1.1
39     /* NativeOp instruction format:
40 gbeauche 1.9 +------------+-------------------------+--+-----------+------------+
41     | 6 | |FN| OP | 2 |
42     +------------+-------------------------+--+-----------+------------+
43     0 5 |6 18 19 20 25 26 31
44 gbeauche 1.1 */
45    
46 gbeauche 1.9 #define POWERPC_NATIVE_OP(FN, OP) \
47     (POWERPC_EMUL_OP | ((FN) << 12) | (((uint32)OP) << 6) | 2)
48 gbeauche 1.1
49 gbeauche 1.2 /*
50     * Return the fake PowerPC opcode to handle specified native code
51     */
52    
53 gbeauche 1.1 #if EMULATED_PPC
54     uint32 NativeOpcode(int selector)
55     {
56     uint32 opcode;
57     switch (selector) {
58     case NATIVE_DISABLE_INTERRUPT:
59     case NATIVE_ENABLE_INTERRUPT:
60 gbeauche 1.6 case NATIVE_CHECK_LOAD_INVOC:
61 gbeauche 1.1 opcode = POWERPC_NATIVE_OP(0, selector);
62     break;
63     case NATIVE_PATCH_NAME_REGISTRY:
64     case NATIVE_VIDEO_INSTALL_ACCEL:
65     case NATIVE_VIDEO_VBL:
66     case NATIVE_VIDEO_DO_DRIVER_IO:
67     case NATIVE_ETHER_IRQ:
68     case NATIVE_ETHER_INIT:
69     case NATIVE_ETHER_TERM:
70     case NATIVE_ETHER_OPEN:
71     case NATIVE_ETHER_CLOSE:
72     case NATIVE_ETHER_WPUT:
73     case NATIVE_ETHER_RSRV:
74     case NATIVE_SERIAL_NOTHING:
75     case NATIVE_SERIAL_OPEN:
76     case NATIVE_SERIAL_PRIME_IN:
77     case NATIVE_SERIAL_PRIME_OUT:
78     case NATIVE_SERIAL_CONTROL:
79     case NATIVE_SERIAL_STATUS:
80     case NATIVE_SERIAL_CLOSE:
81     case NATIVE_GET_RESOURCE:
82     case NATIVE_GET_1_RESOURCE:
83     case NATIVE_GET_IND_RESOURCE:
84     case NATIVE_GET_1_IND_RESOURCE:
85     case NATIVE_R_GET_RESOURCE:
86     case NATIVE_MAKE_EXECUTABLE:
87 gbeauche 1.7 case NATIVE_SYNC_HOOK:
88     case NATIVE_BITBLT_HOOK:
89     case NATIVE_FILLRECT_HOOK:
90     case NATIVE_BITBLT:
91     case NATIVE_INVRECT:
92 gbeauche 1.8 case NATIVE_FILLRECT:
93 gbeauche 1.1 opcode = POWERPC_NATIVE_OP(1, selector);
94     break;
95     default:
96     abort();
97     }
98     return opcode;
99     }
100     #endif
101    
102 gbeauche 1.2
103     /*
104 gbeauche 1.6 * Generate PowerPC thunks for GetResource() replacements
105     */
106    
107     #if EMULATED_PPC
108     static uint32 get_resource_func;
109     static uint32 get_1_resource_func;
110     static uint32 get_ind_resource_func;
111     static uint32 get_1_ind_resource_func;
112     static uint32 r_get_resource_func;
113    
114     static void generate_powerpc_thunks(void)
115     {
116     static uint32 get_resource_template[] = {
117     PL(0x7c0802a6), // mflr r0
118     PL(0x90010008), // stw r0,8(r1)
119     PL(0x9421ffbc), // stwu r1,-68(r1)
120     PL(0x90610038), // stw r3,56(r1)
121     PL(0x9081003c), // stw r4,60(r1)
122     PL(0x00000000), // lwz r0,XLM_GET_RESOURCE(r0)
123     PL(0x80402834), // lwz r2,XLM_RES_LIB_TOC(r0)
124     PL(0x7c0903a6), // mtctr r0
125     PL(0x4e800421), // bctrl
126     PL(0x90610040), // stw r3,64(r1)
127     PL(0x80610038), // lwz r3,56(r1)
128     PL(0xa881003e), // lha r4,62(r1)
129     PL(0x80a10040), // lwz r5,64(r1)
130     PL(0x00000001), // <check_load_invoc>
131     PL(0x80610040), // lwz r3,64(r1)
132     PL(0x8001004c), // lwz r0,76(r1)
133     PL(0x7c0803a6), // mtlr r0
134     PL(0x38210044), // addi r1,r1,68
135     PL(0x4e800020) // blr
136     };
137     const uint32 get_resource_template_size = sizeof(get_resource_template);
138    
139     int xlm_index = -1, check_load_invoc_index = -1;
140     for (int i = 0; i < get_resource_template_size/4; i++) {
141     uint32 opcode = ntohl(get_resource_template[i]);
142     switch (opcode) {
143     case 0x00000000:
144     xlm_index = i;
145     break;
146     case 0x00000001:
147     check_load_invoc_index = i;
148     break;
149     }
150     }
151     assert(xlm_index != -1 && check_load_invoc_index != -1);
152    
153     uint32 check_load_invoc_opcode = NativeOpcode(NATIVE_CHECK_LOAD_INVOC);
154     uintptr base;
155    
156     // GetResource()
157     get_resource_func = base = SheepMem::Reserve(get_resource_template_size);
158     Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
159     WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_RESOURCE);
160     WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
161    
162     // Get1Resource()
163     get_1_resource_func = base = SheepMem::Reserve(get_resource_template_size);
164     Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
165     WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_RESOURCE);
166     WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
167    
168     // GetIndResource()
169     get_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size);
170     Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
171     WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_IND_RESOURCE);
172     WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
173    
174     // Get1IndResource()
175     get_1_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size);
176     Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
177     WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_IND_RESOURCE);
178     WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
179    
180     // RGetResource()
181     r_get_resource_func = base = SheepMem::Reserve(get_resource_template_size);
182     Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
183     WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_R_GET_RESOURCE);
184     WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
185     }
186     #endif
187    
188    
189     /*
190 gbeauche 1.2 * Initialize the thunks system
191     */
192    
193 gbeauche 1.1 struct native_op_t {
194     uint32 tvect;
195     uint32 func;
196 gbeauche 1.3 SheepRoutineDescriptor *desc;
197 gbeauche 1.1 };
198     static native_op_t native_op[NATIVE_OP_MAX];
199    
200     bool ThunksInit(void)
201     {
202     #if EMULATED_PPC
203     for (int i = 0; i < NATIVE_OP_MAX; i++) {
204     uintptr base = SheepMem::Reserve(12);
205     WriteMacInt32(base + 0, base + 8);
206     WriteMacInt32(base + 4, 0); // Fake TVECT
207     WriteMacInt32(base + 8, NativeOpcode(i));
208     native_op[i].tvect = base;
209     native_op[i].func = base + 8;
210     }
211 gbeauche 1.6 #if POWERPC_GET_RESOURCE_THUNKS
212     generate_powerpc_thunks();
213     native_op[NATIVE_GET_RESOURCE].func = get_resource_func;
214     native_op[NATIVE_GET_1_RESOURCE].func = get_1_resource_func;
215     native_op[NATIVE_GET_IND_RESOURCE].func = get_ind_resource_func;
216     native_op[NATIVE_GET_1_IND_RESOURCE].func = get_1_ind_resource_func;
217     native_op[NATIVE_R_GET_RESOURCE].func = r_get_resource_func;
218     #endif
219 gbeauche 1.1 #else
220 gbeauche 1.5 #if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
221 gbeauche 1.1 #define DEFINE_NATIVE_OP(ID, FUNC) do { \
222     uintptr base = SheepMem::Reserve(8); \
223     WriteMacInt32(base + 0, (uint32)FUNC); \
224     WriteMacInt32(base + 4, 0); /*Fake TVECT*/ \
225     native_op[ID].tvect = base; \
226     native_op[ID].func = (uint32)FUNC; \
227     } while (0)
228     #elif defined(__BEOS__)
229     #define DEFINE_NATIVE_OP(ID, FUNC) do { \
230     native_op[ID].tvect = FUNC; \
231     native_op[ID].func = ((uint32 *)FUNC)[0]; \
232     } while (0)
233     #else
234     #error "FIXME: define NativeOp for your platform"
235     #endif
236 gbeauche 1.4 // FIXME: add GetResource() and friends for completeness
237 gbeauche 1.2 DEFINE_NATIVE_OP(NATIVE_PATCH_NAME_REGISTRY, DoPatchNameRegistry);
238     DEFINE_NATIVE_OP(NATIVE_VIDEO_INSTALL_ACCEL, VideoInstallAccel);
239     DEFINE_NATIVE_OP(NATIVE_VIDEO_VBL, VideoVBL);
240     DEFINE_NATIVE_OP(NATIVE_VIDEO_DO_DRIVER_IO, VideoDoDriverIO);
241     DEFINE_NATIVE_OP(NATIVE_ETHER_IRQ, EtherIRQ);
242     DEFINE_NATIVE_OP(NATIVE_ETHER_INIT, InitStreamModule);
243     DEFINE_NATIVE_OP(NATIVE_ETHER_TERM, TerminateStreamModule);
244     DEFINE_NATIVE_OP(NATIVE_ETHER_OPEN, ether_open);
245     DEFINE_NATIVE_OP(NATIVE_ETHER_CLOSE, ether_close);
246     DEFINE_NATIVE_OP(NATIVE_ETHER_WPUT, ether_wput);
247     DEFINE_NATIVE_OP(NATIVE_ETHER_RSRV, ether_rsrv);
248 gbeauche 1.1 DEFINE_NATIVE_OP(NATIVE_SERIAL_NOTHING, SerialNothing);
249     DEFINE_NATIVE_OP(NATIVE_SERIAL_OPEN, SerialOpen);
250     DEFINE_NATIVE_OP(NATIVE_SERIAL_PRIME_IN, SerialPrimeIn);
251     DEFINE_NATIVE_OP(NATIVE_SERIAL_PRIME_OUT, SerialPrimeOut);
252     DEFINE_NATIVE_OP(NATIVE_SERIAL_CONTROL, SerialControl);
253     DEFINE_NATIVE_OP(NATIVE_SERIAL_STATUS, SerialStatus);
254     DEFINE_NATIVE_OP(NATIVE_SERIAL_CLOSE, SerialClose);
255     DEFINE_NATIVE_OP(NATIVE_MAKE_EXECUTABLE, MakeExecutable);
256 gbeauche 1.7 DEFINE_NATIVE_OP(NATIVE_SYNC_HOOK, NQD_sync_hook);
257     DEFINE_NATIVE_OP(NATIVE_BITBLT_HOOK, NQD_bitblt_hook);
258 gbeauche 1.8 DEFINE_NATIVE_OP(NATIVE_FILLRECT_HOOK, NQD_fillrect_hook);
259 gbeauche 1.7 DEFINE_NATIVE_OP(NATIVE_BITBLT, NQD_bitblt);
260 gbeauche 1.8 DEFINE_NATIVE_OP(NATIVE_INVRECT, NQD_invrect);
261     DEFINE_NATIVE_OP(NATIVE_FILLRECT, NQD_fillrect);
262 gbeauche 1.1 #undef DEFINE_NATIVE_OP
263     #endif
264 gbeauche 1.3
265 gbeauche 1.4 // Initialize routine descriptors (if TVECT exists)
266     for (int i = 0; i < NATIVE_OP_MAX; i++) {
267     uint32 tvect = native_op[i].tvect;
268     if (tvect)
269     native_op[i].desc = new SheepRoutineDescriptor(0, tvect);
270     }
271 gbeauche 1.3
272 gbeauche 1.1 return true;
273     }
274    
275 gbeauche 1.2
276     /*
277 gbeauche 1.3 * Delete generated thunks
278     */
279    
280     void ThunksExit(void)
281     {
282     for (int i = 0; i < NATIVE_OP_MAX; i++) {
283     SheepRoutineDescriptor *desc = native_op[i].desc;
284     if (desc)
285     delete desc;
286     }
287     }
288    
289    
290     /*
291 gbeauche 1.2 * Return the native function descriptor (TVECT)
292     */
293    
294 gbeauche 1.1 uint32 NativeTVECT(int selector)
295     {
296     assert(selector < NATIVE_OP_MAX);
297     const uint32 tvect = native_op[selector].tvect;
298     assert(tvect != 0);
299 gbeauche 1.2 return tvect;
300 gbeauche 1.1 }
301    
302 gbeauche 1.2
303     /*
304     * Return the native function address
305     */
306    
307 gbeauche 1.1 uint32 NativeFunction(int selector)
308     {
309     assert(selector < NATIVE_OP_MAX);
310     const uint32 func = native_op[selector].func;
311     assert(func != 0);
312 gbeauche 1.2 return func;
313     }
314    
315    
316     /*
317 gbeauche 1.3 * Return the routine descriptor address of the native function
318     */
319    
320     uint32 NativeRoutineDescriptor(int selector)
321     {
322     assert(selector < NATIVE_OP_MAX);
323     SheepRoutineDescriptor * const desc = native_op[selector].desc;
324     assert(desc != 0);
325     return desc->addr();
326     }
327    
328    
329     /*
330 gbeauche 1.2 * Execute native code from EMUL_OP routine (real mode switch)
331     */
332    
333     void ExecuteNative(int selector)
334     {
335     M68kRegisters r;
336 gbeauche 1.3 Execute68k(NativeRoutineDescriptor(selector), &r);
337 gbeauche 1.1 }