ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/thunks.cpp
(Generate patch)

Comparing SheepShaver/src/thunks.cpp (file contents):
Revision 1.1 by gbeauche, 2003-12-04T17:26:35Z vs.
Revision 1.19 by gbeauche, 2008-01-01T09:47:38Z

# Line 1 | Line 1
1   /*
2   *  thunks.cpp - Thunks to share data and code with MacOS
3   *
4 < *  SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
4 > *  SheepShaver (C) 1997-2008 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
# Line 22 | Line 22
22   #include "thunks.h"
23   #include "emul_op.h"
24   #include "cpu_emulation.h"
25 + #include "xlowmem.h"
26  
27   // Native function declarations
28   #include "main.h"
# Line 29 | Line 30
30   #include "name_registry.h"
31   #include "serial.h"
32   #include "ether.h"
33 + #include "macos_util.h"
34 +
35 + // Generate PowerPC thunks for GetResource() replacements?
36 + #define POWERPC_GET_RESOURCE_THUNKS 1
37  
38  
39   /*              NativeOp instruction format:
40 <                +------------+--------------------------+--+----------+------------+
41 <                |      6     |                          |FN|    OP    |      2     |
42 <                +------------+--------------------------+--+----------+------------+
43 <                 0         5 |6                       19 20 21      25 26        31
40 >                +------------+-------------------------+--+-----------+------------+
41 >                |      6     |                         |FN|    OP     |      2     |
42 >                +------------+-------------------------+--+-----------+------------+
43 >                 0         5 |6                      18 19 20      25 26        31
44   */
45  
46 < #define POWERPC_NATIVE_OP(LR, OP) \
47 <                (POWERPC_EMUL_OP | ((LR) << 11) | (((uint32)OP) << 6) | 2)
46 > #define POWERPC_NATIVE_OP(FN, OP) \
47 >                (POWERPC_EMUL_OP | ((FN) << 12) | (((uint32)OP) << 6) | 2)
48 >
49 > /*
50 > *  Return the fake PowerPC opcode to handle specified native code
51 > */
52  
44 // Return the fake PowerPC opcode to handle specified native code
53   #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:
58 >        case NATIVE_CHECK_LOAD_INVOC:
59 >        case NATIVE_NAMED_CHECK_LOAD_INVOC:
60 >        case NATIVE_NQD_SYNC_HOOK:
61 >        case NATIVE_NQD_BITBLT_HOOK:
62 >        case NATIVE_NQD_FILLRECT_HOOK:
63 >        case NATIVE_NQD_UNKNOWN_HOOK:
64 >        case NATIVE_NQD_BITBLT:
65 >        case NATIVE_NQD_INVRECT:
66 >        case NATIVE_NQD_FILLRECT:
67                  opcode = POWERPC_NATIVE_OP(0, selector);
68                  break;
69          case NATIVE_PATCH_NAME_REGISTRY:
70          case NATIVE_VIDEO_INSTALL_ACCEL:
71          case NATIVE_VIDEO_VBL:
72          case NATIVE_VIDEO_DO_DRIVER_IO:
73 +        case NATIVE_ETHER_AO_GET_HWADDR:
74 +        case NATIVE_ETHER_AO_ADD_MULTI:
75 +        case NATIVE_ETHER_AO_DEL_MULTI:
76 +        case NATIVE_ETHER_AO_SEND_PACKET:
77          case NATIVE_ETHER_IRQ:
78          case NATIVE_ETHER_INIT:
79          case NATIVE_ETHER_TERM:
# Line 74 | Line 93 | uint32 NativeOpcode(int selector)
93          case NATIVE_GET_IND_RESOURCE:
94          case NATIVE_GET_1_IND_RESOURCE:
95          case NATIVE_R_GET_RESOURCE:
96 +        case NATIVE_GET_NAMED_RESOURCE:
97 +        case NATIVE_GET_1_NAMED_RESOURCE:
98          case NATIVE_MAKE_EXECUTABLE:
99                  opcode = POWERPC_NATIVE_OP(1, selector);
100                  break;
# Line 84 | Line 105 | uint32 NativeOpcode(int selector)
105   }
106   #endif
107  
108 < // NativeOp -> { TVECT, function base } mappings
108 >
109 > /*
110 > *  Generate PowerPC thunks for GetResource() replacements
111 > */
112 >
113 > #if EMULATED_PPC
114 > static uint32 get_resource_func;
115 > static uint32 get_1_resource_func;
116 > static uint32 get_ind_resource_func;
117 > static uint32 get_1_ind_resource_func;
118 > static uint32 r_get_resource_func;
119 > static uint32 get_named_resource_func;
120 > static uint32 get_1_named_resource_func;
121 >
122 > static void generate_powerpc_thunks(void)
123 > {
124 >        // check_load_invoc() thunk
125 >        uint32 check_load_invoc_opcode = NativeOpcode(NATIVE_CHECK_LOAD_INVOC);
126 >        uint32 base;
127 >
128 >        static uint32 get_resource_template[] = {
129 >                PL(0x7c0802a6),         // mflr    r0
130 >                PL(0x90010008),         // stw     r0,8(r1)
131 >                PL(0x9421ffbc),         // stwu    r1,-68(r1)
132 >                PL(0x90610038),         // stw     r3,56(r1)
133 >                PL(0x9081003c),         // stw     r4,60(r1)
134 >                PL(0x00000000),         // lwz     r0,XLM_GET_RESOURCE(r0)
135 >                PL(0x80402834),         // lwz     r2,XLM_RES_LIB_TOC(r0)
136 >                PL(0x7c0903a6),         // mtctr   r0
137 >                PL(0x4e800421),         // bctrl
138 >                PL(0x90610040),         // stw     r3,64(r1)
139 >                PL(0x80610038),         // lwz     r3,56(r1)
140 >                PL(0xa881003e),         // lha     r4,62(r1)
141 >                PL(0x80a10040),         // lwz     r5,64(r1)
142 >                PL(0x00000001),         // <check_load_invoc>
143 >                PL(0x80610040),         // lwz     r3,64(r1)
144 >                PL(0x8001004c),         // lwz     r0,76(r1)
145 >                PL(0x7c0803a6),         // mtlr    r0
146 >                PL(0x38210044),         // addi    r1,r1,68
147 >                PL(0x4e800020)          // blr
148 >        };
149 >        const uint32 get_resource_template_size = sizeof(get_resource_template);
150 >
151 >        int xlm_index = -1, check_load_invoc_index = -1;
152 >        for (int i = 0; i < get_resource_template_size/4; i++) {
153 >                uint32 opcode = ntohl(get_resource_template[i]);
154 >                switch (opcode) {
155 >                case 0x00000000:
156 >                        xlm_index = i;
157 >                        break;
158 >                case 0x00000001:
159 >                        check_load_invoc_index = i;
160 >                        break;
161 >                }
162 >        }
163 >        assert(xlm_index != -1 && check_load_invoc_index != -1);
164 >
165 >        // GetResource()
166 >        get_resource_func = base = SheepMem::Reserve(get_resource_template_size);
167 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
168 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_RESOURCE);
169 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
170 >
171 >        // Get1Resource()
172 >        get_1_resource_func = base = SheepMem::Reserve(get_resource_template_size);
173 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
174 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_RESOURCE);
175 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
176 >
177 >        // GetIndResource()
178 >        get_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size);
179 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
180 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_IND_RESOURCE);
181 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
182 >
183 >        // Get1IndResource()
184 >        get_1_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size);
185 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
186 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_IND_RESOURCE);
187 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
188 >
189 >        // RGetResource()
190 >        r_get_resource_func = base = SheepMem::Reserve(get_resource_template_size);
191 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
192 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_R_GET_RESOURCE);
193 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
194 >
195 >        // named_check_load_invoc() thunk
196 >        check_load_invoc_opcode = NativeOpcode(NATIVE_NAMED_CHECK_LOAD_INVOC);
197 >
198 >        static uint32 get_named_resource_template[] = {
199 >                PL(0x7c0802a6),         // mflr    r0
200 >                PL(0x90010008),         // stw     r0,8(r1)
201 >                PL(0x9421ffbc),         // stwu    r1,-68(r1)
202 >                PL(0x90610038),         // stw     r3,56(r1)
203 >                PL(0x9081003c),         // stw     r4,60(r1)
204 >                PL(0x00000000),         // lwz     r0,XLM_GET_NAMED_RESOURCE(r0)
205 >                PL(0x80402834),         // lwz     r2,XLM_RES_LIB_TOC(r0)
206 >                PL(0x7c0903a6),         // mtctr   r0
207 >                PL(0x4e800421),         // bctrl
208 >                PL(0x90610040),         // stw     r3,64(r1)
209 >                PL(0x80610038),         // lwz     r3,56(r1)
210 >                PL(0x8081003c),         // lwz     r4,60(r1)
211 >                PL(0x80a10040),         // lwz     r5,64(r1)
212 >                PL(0x00000001),         // <named_check_load_invoc>
213 >                PL(0x80610040),         // lwz     r3,64(r1)
214 >                PL(0x8001004c),         // lwz     r0,76(r1)
215 >                PL(0x7c0803a6),         // mtlr    r0
216 >                PL(0x38210044),         // addi    r1,r1,68
217 >                PL(0x4e800020)          // blr
218 >        };
219 >        const uint32 get_named_resource_template_size = sizeof(get_named_resource_template);
220 >
221 >        xlm_index = -1, check_load_invoc_index = -1;
222 >        for (int i = 0; i < get_resource_template_size/4; i++) {
223 >                uint32 opcode = ntohl(get_resource_template[i]);
224 >                switch (opcode) {
225 >                case 0x00000000:
226 >                        xlm_index = i;
227 >                        break;
228 >                case 0x00000001:
229 >                        check_load_invoc_index = i;
230 >                        break;
231 >                }
232 >        }
233 >        assert(xlm_index != -1 && check_load_invoc_index != -1);
234 >
235 >        // GetNamedResource()
236 >        get_named_resource_func = base = SheepMem::Reserve(get_named_resource_template_size);
237 >        Host2Mac_memcpy(base, get_named_resource_template, get_named_resource_template_size);
238 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_NAMED_RESOURCE);
239 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
240 >
241 >        // Get1NamedResource()
242 >        get_1_named_resource_func = base = SheepMem::Reserve(get_named_resource_template_size);
243 >        Host2Mac_memcpy(base, get_named_resource_template, get_named_resource_template_size);
244 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_NAMED_RESOURCE);
245 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
246 > }
247 > #endif
248 >
249 >
250 > /*
251 > *  Initialize the thunks system
252 > */
253 >
254   struct native_op_t {
255          uint32 tvect;
256          uint32 func;
257 +        SheepRoutineDescriptor *desc;
258   };
259   static native_op_t native_op[NATIVE_OP_MAX];
260  
94 // Initialize the thunks system
261   bool ThunksInit(void)
262   {
263   #if EMULATED_PPC
264          for (int i = 0; i < NATIVE_OP_MAX; i++) {
265 <                uintptr base = SheepMem::Reserve(12);
265 >                uintptr base = SheepMem::Reserve(16);
266                  WriteMacInt32(base + 0, base + 8);
267                  WriteMacInt32(base + 4, 0); // Fake TVECT
268                  WriteMacInt32(base + 8, NativeOpcode(i));
269 +                WriteMacInt32(base + 12, POWERPC_BLR);
270                  native_op[i].tvect = base;
271                  native_op[i].func  = base + 8;
272          }
273 + #if POWERPC_GET_RESOURCE_THUNKS
274 +        generate_powerpc_thunks();
275 +        native_op[NATIVE_GET_RESOURCE].func = get_resource_func;
276 +        native_op[NATIVE_GET_1_RESOURCE].func = get_1_resource_func;
277 +        native_op[NATIVE_GET_IND_RESOURCE].func = get_ind_resource_func;
278 +        native_op[NATIVE_GET_1_IND_RESOURCE].func = get_1_ind_resource_func;
279 +        native_op[NATIVE_R_GET_RESOURCE].func = r_get_resource_func;
280 +        native_op[NATIVE_GET_NAMED_RESOURCE].func = get_named_resource_func;
281 +        native_op[NATIVE_GET_1_NAMED_RESOURCE].func = get_1_named_resource_func;
282 + #endif
283   #else
284 < #if defined(__linux__)
284 > #if defined(__linux__) || defined(__NetBSD__) || (defined(__APPLE__) && defined(__MACH__))
285   #define DEFINE_NATIVE_OP(ID, FUNC) do {                         \
286                  uintptr base = SheepMem::Reserve(8);            \
287                  WriteMacInt32(base + 0, (uint32)FUNC);          \
288 <                WriteMacInt32(base + 4, 0); /*Fake TVECT*/      \
288 >                WriteMacInt32(base + 4, (uint32)TOC);           \
289                  native_op[ID].tvect = base;                                     \
290                  native_op[ID].func  = (uint32)FUNC;                     \
291          } while (0)
# Line 120 | Line 297 | bool ThunksInit(void)
297   #else
298   #error "FIXME: define NativeOp for your platform"
299   #endif
300 +        // FIXME: add GetResource() and friends for completeness
301 +        DEFINE_NATIVE_OP(NATIVE_PATCH_NAME_REGISTRY, DoPatchNameRegistry);
302 +        DEFINE_NATIVE_OP(NATIVE_VIDEO_INSTALL_ACCEL, VideoInstallAccel);
303 +        DEFINE_NATIVE_OP(NATIVE_VIDEO_VBL, VideoVBL);
304 +        DEFINE_NATIVE_OP(NATIVE_VIDEO_DO_DRIVER_IO, VideoDoDriverIO);
305 +        DEFINE_NATIVE_OP(NATIVE_ETHER_AO_GET_HWADDR, AO_get_ethernet_address);
306 +        DEFINE_NATIVE_OP(NATIVE_ETHER_AO_ADD_MULTI, AO_enable_multicast);
307 +        DEFINE_NATIVE_OP(NATIVE_ETHER_AO_DEL_MULTI, AO_disable_multicast);
308 +        DEFINE_NATIVE_OP(NATIVE_ETHER_AO_SEND_PACKET, AO_transmit_packet);
309 +        DEFINE_NATIVE_OP(NATIVE_ETHER_IRQ, EtherIRQ);
310 +        DEFINE_NATIVE_OP(NATIVE_ETHER_INIT, InitStreamModule);
311 +        DEFINE_NATIVE_OP(NATIVE_ETHER_TERM, TerminateStreamModule);
312 +        DEFINE_NATIVE_OP(NATIVE_ETHER_OPEN, ether_open);
313 +        DEFINE_NATIVE_OP(NATIVE_ETHER_CLOSE, ether_close);
314 +        DEFINE_NATIVE_OP(NATIVE_ETHER_WPUT, ether_wput);
315 +        DEFINE_NATIVE_OP(NATIVE_ETHER_RSRV, ether_rsrv);
316          DEFINE_NATIVE_OP(NATIVE_SERIAL_NOTHING, SerialNothing);
317          DEFINE_NATIVE_OP(NATIVE_SERIAL_OPEN, SerialOpen);
318          DEFINE_NATIVE_OP(NATIVE_SERIAL_PRIME_IN, SerialPrimeIn);
# Line 128 | Line 321 | bool ThunksInit(void)
321          DEFINE_NATIVE_OP(NATIVE_SERIAL_STATUS, SerialStatus);
322          DEFINE_NATIVE_OP(NATIVE_SERIAL_CLOSE, SerialClose);
323          DEFINE_NATIVE_OP(NATIVE_MAKE_EXECUTABLE, MakeExecutable);
324 +        DEFINE_NATIVE_OP(NATIVE_NQD_SYNC_HOOK, NQD_sync_hook);
325 +        DEFINE_NATIVE_OP(NATIVE_NQD_BITBLT_HOOK, NQD_bitblt_hook);
326 +        DEFINE_NATIVE_OP(NATIVE_NQD_FILLRECT_HOOK, NQD_fillrect_hook);
327 +        DEFINE_NATIVE_OP(NATIVE_NQD_UNKNOWN_HOOK, NQD_unknown_hook);
328 +        DEFINE_NATIVE_OP(NATIVE_NQD_BITBLT, NQD_bitblt);
329 +        DEFINE_NATIVE_OP(NATIVE_NQD_INVRECT, NQD_invrect);
330 +        DEFINE_NATIVE_OP(NATIVE_NQD_FILLRECT, NQD_fillrect);
331   #undef DEFINE_NATIVE_OP
332   #endif
333 +
334 +        // Initialize routine descriptors (if TVECT exists)
335 +        for (int i = 0; i < NATIVE_OP_MAX; i++) {
336 +                uint32 tvect = native_op[i].tvect;
337 +                if (tvect)
338 +                        native_op[i].desc = new SheepRoutineDescriptor(0, tvect);
339 +        }
340 +
341          return true;
342   }
343  
344 < // Return the native function descriptor (TVECT)
344 >
345 > /*
346 > *  Delete generated thunks
347 > */
348 >
349 > void ThunksExit(void)
350 > {
351 >        for (int i = 0; i < NATIVE_OP_MAX; i++) {
352 >                SheepRoutineDescriptor *desc = native_op[i].desc;
353 >                if (desc)
354 >                        delete desc;
355 >        }
356 > }
357 >
358 >
359 > /*
360 > *  Return the native function descriptor (TVECT)
361 > */
362 >
363   uint32 NativeTVECT(int selector)
364   {
365          assert(selector < NATIVE_OP_MAX);
366          const uint32 tvect = native_op[selector].tvect;
367          assert(tvect != 0);
368 <        return native_op[selector].tvect;
368 >        return tvect;
369   }
370  
371 < // Return the native function address
371 >
372 > /*
373 > *  Return the native function address
374 > */
375 >
376   uint32 NativeFunction(int selector)
377   {
378          assert(selector < NATIVE_OP_MAX);
379          const uint32 func = native_op[selector].func;
380          assert(func != 0);
381 <        return native_op[selector].func;
381 >        return func;
382 > }
383 >
384 >
385 > /*
386 > *  Return the routine descriptor address of the native function
387 > */
388 >
389 > uint32 NativeRoutineDescriptor(int selector)
390 > {
391 >        assert(selector < NATIVE_OP_MAX);
392 >        SheepRoutineDescriptor * const desc = native_op[selector].desc;
393 >        assert(desc != 0);
394 >        return desc->addr();
395 > }
396 >
397 >
398 > /*
399 > *  Execute native code from EMUL_OP routine (real mode switch)
400 > */
401 >
402 > void ExecuteNative(int selector)
403 > {
404 >        M68kRegisters r;
405 >        Execute68k(NativeRoutineDescriptor(selector), &r);
406   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines