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.11 by gbeauche, 2004-11-13T14:09:15Z

# 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:
51 <        case NATIVE_ENABLE_INTERRUPT:
58 >        case NATIVE_CHECK_LOAD_INVOC:
59                  opcode = POWERPC_NATIVE_OP(0, selector);
60                  break;
61          case NATIVE_PATCH_NAME_REGISTRY:
# Line 75 | Line 82 | uint32 NativeOpcode(int selector)
82          case NATIVE_GET_1_IND_RESOURCE:
83          case NATIVE_R_GET_RESOURCE:
84          case NATIVE_MAKE_EXECUTABLE:
85 +        case NATIVE_SYNC_HOOK:
86 +        case NATIVE_BITBLT_HOOK:
87 +        case NATIVE_FILLRECT_HOOK:
88 +        case NATIVE_BITBLT:
89 +        case NATIVE_INVRECT:
90 +        case NATIVE_FILLRECT:
91                  opcode = POWERPC_NATIVE_OP(1, selector);
92                  break;
93          default:
# Line 84 | Line 97 | uint32 NativeOpcode(int selector)
97   }
98   #endif
99  
100 < // NativeOp -> { TVECT, function base } mappings
100 >
101 > /*
102 > *  Generate PowerPC thunks for GetResource() replacements
103 > */
104 >
105 > #if EMULATED_PPC
106 > static uint32 get_resource_func;
107 > static uint32 get_1_resource_func;
108 > static uint32 get_ind_resource_func;
109 > static uint32 get_1_ind_resource_func;
110 > static uint32 r_get_resource_func;
111 >
112 > static void generate_powerpc_thunks(void)
113 > {
114 >        static uint32 get_resource_template[] = {
115 >                PL(0x7c0802a6),         // mflr    r0
116 >                PL(0x90010008),         // stw     r0,8(r1)
117 >                PL(0x9421ffbc),         // stwu    r1,-68(r1)
118 >                PL(0x90610038),         // stw     r3,56(r1)
119 >                PL(0x9081003c),         // stw     r4,60(r1)
120 >                PL(0x00000000),         // lwz     r0,XLM_GET_RESOURCE(r0)
121 >                PL(0x80402834),         // lwz     r2,XLM_RES_LIB_TOC(r0)
122 >                PL(0x7c0903a6),         // mtctr   r0
123 >                PL(0x4e800421),         // bctrl
124 >                PL(0x90610040),         // stw     r3,64(r1)
125 >                PL(0x80610038),         // lwz     r3,56(r1)
126 >                PL(0xa881003e),         // lha     r4,62(r1)
127 >                PL(0x80a10040),         // lwz     r5,64(r1)
128 >                PL(0x00000001),         // <check_load_invoc>
129 >                PL(0x80610040),         // lwz     r3,64(r1)
130 >                PL(0x8001004c),         // lwz     r0,76(r1)
131 >                PL(0x7c0803a6),         // mtlr    r0
132 >                PL(0x38210044),         // addi    r1,r1,68
133 >                PL(0x4e800020)          // blr
134 >        };
135 >        const uint32 get_resource_template_size = sizeof(get_resource_template);
136 >
137 >        int xlm_index = -1, check_load_invoc_index = -1;
138 >        for (int i = 0; i < get_resource_template_size/4; i++) {
139 >                uint32 opcode = ntohl(get_resource_template[i]);
140 >                switch (opcode) {
141 >                case 0x00000000:
142 >                        xlm_index = i;
143 >                        break;
144 >                case 0x00000001:
145 >                        check_load_invoc_index = i;
146 >                        break;
147 >                }
148 >        }
149 >        assert(xlm_index != -1 && check_load_invoc_index != -1);
150 >
151 >        uint32 check_load_invoc_opcode = NativeOpcode(NATIVE_CHECK_LOAD_INVOC);
152 >        uint32 base;
153 >
154 >        // GetResource()
155 >        get_resource_func = base = SheepMem::Reserve(get_resource_template_size);
156 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
157 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_RESOURCE);
158 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
159 >
160 >        // Get1Resource()
161 >        get_1_resource_func = base = SheepMem::Reserve(get_resource_template_size);
162 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
163 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_RESOURCE);
164 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
165 >
166 >        // GetIndResource()
167 >        get_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size);
168 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
169 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_IND_RESOURCE);
170 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
171 >
172 >        // Get1IndResource()
173 >        get_1_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size);
174 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
175 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_IND_RESOURCE);
176 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
177 >
178 >        // RGetResource()
179 >        r_get_resource_func = base = SheepMem::Reserve(get_resource_template_size);
180 >        Host2Mac_memcpy(base, get_resource_template, get_resource_template_size);
181 >        WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_R_GET_RESOURCE);
182 >        WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode);
183 > }
184 > #endif
185 >
186 >
187 > /*
188 > *  Initialize the thunks system
189 > */
190 >
191   struct native_op_t {
192          uint32 tvect;
193          uint32 func;
194 +        SheepRoutineDescriptor *desc;
195   };
196   static native_op_t native_op[NATIVE_OP_MAX];
197  
94 // Initialize the thunks system
198   bool ThunksInit(void)
199   {
200   #if EMULATED_PPC
# Line 103 | Line 206 | bool ThunksInit(void)
206                  native_op[i].tvect = base;
207                  native_op[i].func  = base + 8;
208          }
209 + #if POWERPC_GET_RESOURCE_THUNKS
210 +        generate_powerpc_thunks();
211 +        native_op[NATIVE_GET_RESOURCE].func = get_resource_func;
212 +        native_op[NATIVE_GET_1_RESOURCE].func = get_1_resource_func;
213 +        native_op[NATIVE_GET_IND_RESOURCE].func = get_ind_resource_func;
214 +        native_op[NATIVE_GET_1_IND_RESOURCE].func = get_1_ind_resource_func;
215 +        native_op[NATIVE_R_GET_RESOURCE].func = r_get_resource_func;
216 + #endif
217   #else
218 < #if defined(__linux__)
218 > #if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
219   #define DEFINE_NATIVE_OP(ID, FUNC) do {                         \
220                  uintptr base = SheepMem::Reserve(8);            \
221                  WriteMacInt32(base + 0, (uint32)FUNC);          \
# Line 120 | Line 231 | bool ThunksInit(void)
231   #else
232   #error "FIXME: define NativeOp for your platform"
233   #endif
234 +        // FIXME: add GetResource() and friends for completeness
235 +        DEFINE_NATIVE_OP(NATIVE_PATCH_NAME_REGISTRY, DoPatchNameRegistry);
236 +        DEFINE_NATIVE_OP(NATIVE_VIDEO_INSTALL_ACCEL, VideoInstallAccel);
237 +        DEFINE_NATIVE_OP(NATIVE_VIDEO_VBL, VideoVBL);
238 +        DEFINE_NATIVE_OP(NATIVE_VIDEO_DO_DRIVER_IO, VideoDoDriverIO);
239 +        DEFINE_NATIVE_OP(NATIVE_ETHER_IRQ, EtherIRQ);
240 +        DEFINE_NATIVE_OP(NATIVE_ETHER_INIT, InitStreamModule);
241 +        DEFINE_NATIVE_OP(NATIVE_ETHER_TERM, TerminateStreamModule);
242 +        DEFINE_NATIVE_OP(NATIVE_ETHER_OPEN, ether_open);
243 +        DEFINE_NATIVE_OP(NATIVE_ETHER_CLOSE, ether_close);
244 +        DEFINE_NATIVE_OP(NATIVE_ETHER_WPUT, ether_wput);
245 +        DEFINE_NATIVE_OP(NATIVE_ETHER_RSRV, ether_rsrv);
246          DEFINE_NATIVE_OP(NATIVE_SERIAL_NOTHING, SerialNothing);
247          DEFINE_NATIVE_OP(NATIVE_SERIAL_OPEN, SerialOpen);
248          DEFINE_NATIVE_OP(NATIVE_SERIAL_PRIME_IN, SerialPrimeIn);
# Line 128 | Line 251 | bool ThunksInit(void)
251          DEFINE_NATIVE_OP(NATIVE_SERIAL_STATUS, SerialStatus);
252          DEFINE_NATIVE_OP(NATIVE_SERIAL_CLOSE, SerialClose);
253          DEFINE_NATIVE_OP(NATIVE_MAKE_EXECUTABLE, MakeExecutable);
254 +        DEFINE_NATIVE_OP(NATIVE_SYNC_HOOK, NQD_sync_hook);
255 +        DEFINE_NATIVE_OP(NATIVE_BITBLT_HOOK, NQD_bitblt_hook);
256 +        DEFINE_NATIVE_OP(NATIVE_FILLRECT_HOOK, NQD_fillrect_hook);
257 +        DEFINE_NATIVE_OP(NATIVE_BITBLT, NQD_bitblt);
258 +        DEFINE_NATIVE_OP(NATIVE_INVRECT, NQD_invrect);
259 +        DEFINE_NATIVE_OP(NATIVE_FILLRECT, NQD_fillrect);
260   #undef DEFINE_NATIVE_OP
261   #endif
262 +
263 +        // Initialize routine descriptors (if TVECT exists)
264 +        for (int i = 0; i < NATIVE_OP_MAX; i++) {
265 +                uint32 tvect = native_op[i].tvect;
266 +                if (tvect)
267 +                        native_op[i].desc = new SheepRoutineDescriptor(0, tvect);
268 +        }
269 +
270          return true;
271   }
272  
273 < // Return the native function descriptor (TVECT)
273 >
274 > /*
275 > *  Delete generated thunks
276 > */
277 >
278 > void ThunksExit(void)
279 > {
280 >        for (int i = 0; i < NATIVE_OP_MAX; i++) {
281 >                SheepRoutineDescriptor *desc = native_op[i].desc;
282 >                if (desc)
283 >                        delete desc;
284 >        }
285 > }
286 >
287 >
288 > /*
289 > *  Return the native function descriptor (TVECT)
290 > */
291 >
292   uint32 NativeTVECT(int selector)
293   {
294          assert(selector < NATIVE_OP_MAX);
295          const uint32 tvect = native_op[selector].tvect;
296          assert(tvect != 0);
297 <        return native_op[selector].tvect;
297 >        return tvect;
298   }
299  
300 < // Return the native function address
300 >
301 > /*
302 > *  Return the native function address
303 > */
304 >
305   uint32 NativeFunction(int selector)
306   {
307          assert(selector < NATIVE_OP_MAX);
308          const uint32 func = native_op[selector].func;
309          assert(func != 0);
310 <        return native_op[selector].func;
310 >        return func;
311 > }
312 >
313 >
314 > /*
315 > *  Return the routine descriptor address of the native function
316 > */
317 >
318 > uint32 NativeRoutineDescriptor(int selector)
319 > {
320 >        assert(selector < NATIVE_OP_MAX);
321 >        SheepRoutineDescriptor * const desc = native_op[selector].desc;
322 >        assert(desc != 0);
323 >        return desc->addr();
324 > }
325 >
326 >
327 > /*
328 > *  Execute native code from EMUL_OP routine (real mode switch)
329 > */
330 >
331 > void ExecuteNative(int selector)
332 > {
333 >        M68kRegisters r;
334 >        Execute68k(NativeRoutineDescriptor(selector), &r);
335   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines