ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/ppc_asm.S
Revision: 1.10
Committed: 2009-08-18T18:26:11Z (15 years, 2 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +6 -4 lines
Log Message:
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.


Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".

SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.

The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.

On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.


Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.

This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.

Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.

A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.


Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.

The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.

This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.


Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.

2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.

3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.

4. Changed and rearranged the allocation of RAM and ROM areas.

Before it worked like this:

  - Allocate ROM area
  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0, allocate at fixed address

We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:

  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0
      if REAL addressing
         allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
      else (direct addressing)
         allocate RAM at fixed address
  - If ROM hasn't been allocated yet, allocate at fixed address

5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.

6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.

7. Change subsequent code from using constant ROM_BASE to variable ROMBase.


Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.

ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.

ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.

main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.

cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.

user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * asm_linux.S - Assembly routines
3     *
4     * SheepShaver (C) 1997-2005 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 <ppc_asm.tmpl>
22     #include <xlowmem.h>
23    
24     #define SAVE_FP_EXEC_68K 1
25    
26    
27     /*
28 gbeauche 1.2 * void *get_sp(void) - Get stack pointer
29 gbeauche 1.1 */
30    
31 gbeauche 1.2 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_sp)
32     C_SYMBOL_NAME(get_sp):
33     mr r3,r1
34 gbeauche 1.1 blr
35    
36    
37     /*
38 gbeauche 1.2 * void *get_r2(void) - Get r2
39 gbeauche 1.1 */
40    
41 gbeauche 1.2 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r2)
42     C_SYMBOL_NAME(get_r2):
43     mr r3,r2
44 gbeauche 1.1 blr
45    
46    
47     /*
48 gbeauche 1.2 * void set_r2(void *val {r3}) - Set r2
49 gbeauche 1.1 */
50    
51     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r2)
52     C_SYMBOL_NAME(set_r2):
53     mr r2,r3
54     blr
55    
56    
57     /*
58 gbeauche 1.2 * void *get_r13(void) - Get r13 (small data pointer under Linux)
59     */
60    
61     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r13)
62     C_SYMBOL_NAME(get_r13):
63     mr r3,r13
64     blr
65    
66     /*
67     * void set_r13(void *val {r3}) - Set r13 (small data pointer under Linux)
68     */
69    
70     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r13)
71     C_SYMBOL_NAME(set_r13):
72     mr r13,r3
73     blr
74    
75    
76     /*
77 gbeauche 1.1 * void flush_icache_range(void *start {r3}, void *end {r3}) - Flush D and I cache
78     */
79    
80     CACHE_LINE_SIZE = 32
81     LG_CACHE_LINE_SIZE = 5
82    
83     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(flush_icache_range)
84     C_SYMBOL_NAME(flush_icache_range):
85     li r5,CACHE_LINE_SIZE-1
86     andc r3,r3,r5
87     subf r4,r3,r4
88     add r4,r4,r5
89     srwi. r4,r4,LG_CACHE_LINE_SIZE
90     beqlr
91     mtctr r4
92     mr r6,r3
93     1: dcbst 0,r3
94     addi r3,r3,CACHE_LINE_SIZE
95     bdnz 1b
96     sync /* wait for dcbst's to get to ram */
97     mtctr r4
98     2: icbi 0,r6
99     addi r6,r6,CACHE_LINE_SIZE
100     bdnz 2b
101     sync
102     isync
103     blr
104    
105    
106     /*
107     * long atomic_add(long *var{r3}, long add{r4}) - Atomic add operation
108     * long atomic_and(long *var{r3}, long and{r4}) - Atomic and operation
109     * long atomic_or(long *var{r3}, long or{r4}) - Atomic or operation
110     * int test_and_set(int *var{r3}, int val{r4}) - Atomic test-and-set
111     */
112    
113     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_add)
114     C_SYMBOL_NAME(atomic_add):
115     0: dcbf 0,r3
116     sync
117     ori r0,r0,1
118     ori r0,r0,1
119     ori r0,r0,1
120     ori r0,r0,1
121     ori r0,r0,1
122     ori r0,r0,1
123     isync
124     lwarx r5,0,r3
125     add r0,r4,r5
126     stwcx. r0,0,r3
127     bne- 0b
128     mr r3,r5
129     isync
130     blr
131    
132     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_and)
133     C_SYMBOL_NAME(atomic_and):
134     0: dcbf 0,r3
135     sync
136     ori r0,r0,1
137     ori r0,r0,1
138     ori r0,r0,1
139     ori r0,r0,1
140     ori r0,r0,1
141     ori r0,r0,1
142     isync
143     lwarx r5,0,r3
144     and r0,r4,r5
145     stwcx. r0,0,r3
146     bne- 0b
147     mr r3,r5
148     isync
149     blr
150    
151     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_or)
152     C_SYMBOL_NAME(atomic_or):
153     0: dcbf 0,r3
154     sync
155     ori r0,r0,1
156     ori r0,r0,1
157     ori r0,r0,1
158     ori r0,r0,1
159     ori r0,r0,1
160     ori r0,r0,1
161     isync
162     lwarx r5,0,r3
163     or r0,r4,r5
164     stwcx. r0,0,r3
165     bne- 0b
166     mr r3,r5
167     isync
168     blr
169    
170     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(test_and_set)
171     C_SYMBOL_NAME(test_and_set):
172     0: dcbf 0,r3
173     sync
174     ori r0,r0,1
175     ori r0,r0,1
176     ori r0,r0,1
177     ori r0,r0,1
178     ori r0,r0,1
179     ori r0,r0,1
180     isync
181     lwarx r5,0,r3
182     cmpi 0,r5,0x0000
183 gbeauche 1.6 bne 1f
184 gbeauche 1.1 stwcx. r4,0,r3
185     bne- 0b
186     1: isync
187     mr r3,r5
188     blr
189    
190    
191     /*
192     * void quit_emulator(void) - Jump to XLM_EMUL_RETURN_PROC
193     */
194    
195     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(quit_emulator)
196     C_SYMBOL_NAME(quit_emulator):
197     lwz r0,XLM_EMUL_RETURN_PROC(0)
198     mtlr r0
199     blr
200    
201    
202     /*
203     * void jump_to_rom(uint32 entry {r3}, uint32 emulator_data {r4}) - Jump to Mac ROM
204     */
205    
206     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(jump_to_rom)
207     C_SYMBOL_NAME(jump_to_rom):
208     // Create stack frame
209     mflr r0
210     stw r0,4(r1)
211     stwu r1,-(20+19*4+18*8)(r1) // maintain 16 byte alignment
212    
213     // Save PowerPC registers
214     stmw r13,20(r1)
215     stfd f14,20+19*4+0*8(r1)
216     stfd f15,20+19*4+1*8(r1)
217     stfd f16,20+19*4+2*8(r1)
218     stfd f17,20+19*4+3*8(r1)
219     stfd f18,20+19*4+4*8(r1)
220     stfd f19,20+19*4+5*8(r1)
221     stfd f20,20+19*4+6*8(r1)
222     stfd f21,20+19*4+7*8(r1)
223     stfd f22,20+19*4+8*8(r1)
224     stfd f23,20+19*4+9*8(r1)
225     stfd f24,20+19*4+10*8(r1)
226     stfd f25,20+19*4+11*8(r1)
227     stfd f26,20+19*4+12*8(r1)
228     stfd f27,20+19*4+13*8(r1)
229     stfd f28,20+19*4+14*8(r1)
230     stfd f29,20+19*4+15*8(r1)
231     stfd f30,20+19*4+16*8(r1)
232     stfd f31,20+19*4+17*8(r1)
233    
234     // Move entry address to ctr
235     mtctr r3
236    
237     // Skip over EMUL_RETURN routine and get its address
238     bl 1f
239    
240    
241     /*
242     * EMUL_RETURN: Returned from emulator
243     */
244    
245     // Restore PowerPC registers
246     lwz r1,XLM_EMUL_RETURN_STACK(0)
247 gbeauche 1.2 RESTORE_SYSTEM_R2
248 gbeauche 1.1 lmw r13,20(r1)
249     lfd f14,20+19*4+0*8(r1)
250     lfd f15,20+19*4+1*8(r1)
251     lfd f16,20+19*4+2*8(r1)
252     lfd f17,20+19*4+3*8(r1)
253     lfd f18,20+19*4+4*8(r1)
254     lfd f19,20+19*4+5*8(r1)
255     lfd f20,20+19*4+6*8(r1)
256     lfd f21,20+19*4+7*8(r1)
257     lfd f22,20+19*4+8*8(r1)
258     lfd f23,20+19*4+9*8(r1)
259     lfd f24,20+19*4+10*8(r1)
260     lfd f25,20+19*4+11*8(r1)
261     lfd f26,20+19*4+12*8(r1)
262     lfd f27,20+19*4+13*8(r1)
263     lfd f28,20+19*4+14*8(r1)
264     lfd f29,20+19*4+15*8(r1)
265     lfd f30,20+19*4+16*8(r1)
266     lfd f31,20+19*4+17*8(r1)
267    
268     // Exiting from 68k emulator
269     li r0,1
270     stw r0,XLM_IRQ_NEST(0)
271     li r0,MODE_NATIVE
272     stw r0,XLM_RUN_MODE(0)
273    
274     // Return to caller of jump_to_rom()
275     lwz r0,20+19*4+18*8+4(r1)
276     mtlr r0
277     addi r1,r1,20+19*4+18*8
278     blr
279    
280    
281     // Save address of EMUL_RETURN routine for 68k emulator patch
282     1: mflr r0
283     stw r0,XLM_EMUL_RETURN_PROC(0)
284    
285     // Skip over EXEC_RETURN routine and get its address
286     bl 2f
287    
288    
289     /*
290     * EXEC_RETURN: Returned from 68k routine executed with Execute68k()
291     */
292    
293     // Save r25 (contains current 68k interrupt level)
294     stw r25,XLM_68K_R25(0)
295    
296     // Reentering EMUL_OP mode
297     li r0,MODE_EMUL_OP
298     stw r0,XLM_RUN_MODE(0)
299    
300     // Save 68k registers
301     lwz r4,48(r1) // Pointer to M68kRegisters
302     stw r8,0*4(r4) // d[0]...d[7]
303     stw r9,1*4(r4)
304     stw r10,2*4(r4)
305     stw r11,3*4(r4)
306     stw r12,4*4(r4)
307     stw r13,5*4(r4)
308     stw r14,6*4(r4)
309     stw r15,7*4(r4)
310     stw r16,8*4(r4) // a[0]..a[6]
311     stw r17,9*4(r4)
312     stw r18,10*4(r4)
313     stw r19,11*4(r4)
314     stw r20,12*4(r4)
315     stw r21,13*4(r4)
316     stw r22,14*4(r4)
317    
318     // Restore PowerPC registers
319     lmw r13,56(r1)
320     #if SAVE_FP_EXEC_68K
321     lfd f14,56+19*4+0*8(r1)
322     lfd f15,56+19*4+1*8(r1)
323     lfd f16,56+19*4+2*8(r1)
324     lfd f17,56+19*4+3*8(r1)
325     lfd f18,56+19*4+4*8(r1)
326     lfd f19,56+19*4+5*8(r1)
327     lfd f20,56+19*4+6*8(r1)
328     lfd f21,56+19*4+7*8(r1)
329     lfd f22,56+19*4+8*8(r1)
330     lfd f23,56+19*4+9*8(r1)
331     lfd f24,56+19*4+10*8(r1)
332     lfd f25,56+19*4+11*8(r1)
333     lfd f26,56+19*4+12*8(r1)
334     lfd f27,56+19*4+13*8(r1)
335     lfd f28,56+19*4+14*8(r1)
336     lfd f29,56+19*4+15*8(r1)
337     lfd f30,56+19*4+16*8(r1)
338     lfd f31,56+19*4+17*8(r1)
339     #endif
340    
341     // Return to caller
342     lwz r0,52(r1)
343     mtcrf 0xff,r0
344     lwz r0,56+19*4+18*8+4(r1)
345     mtlr r0
346     addi r1,r1,56+19*4+18*8
347 gbeauche 1.4 RESTORE_SYSTEM_R2
348     RESTORE_SYSTEM_R13
349 gbeauche 1.1 blr
350    
351    
352     // Save address of EXEC_RETURN routine for 68k emulator patch
353     2: mflr r0
354     stw r0,XLM_EXEC_RETURN_PROC(0)
355    
356     // Skip over EMUL_BREAK/EMUL_OP routine and get its address
357     bl 3f
358    
359    
360     /*
361     * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
362     *
363     * 68k registers are stored in a M68kRegisters struct on the stack
364     * which the native routine may read and modify
365     */
366    
367     // Save r25 (contains current 68k interrupt level)
368     stw r25,XLM_68K_R25(0)
369    
370     // Entering EMUL_OP mode within 68k emulator
371     li r0,MODE_EMUL_OP
372     stw r0,XLM_RUN_MODE(0)
373    
374     // Create PowerPC stack frame, reserve space for M68kRegisters
375     mr r3,r1
376     subi r1,r1,64 // Fake "caller" frame
377     rlwinm r1,r1,0,0,27 // Align stack
378    
379     mfcr r0
380     rlwinm r0,r0,0,11,8
381     stw r0,4(r1)
382     mfxer r0
383     stw r0,16(r1)
384     stw r2,12(r1)
385 gbeauche 1.4 stwu r1,-(56+16*4+15*8)(r1)
386 gbeauche 1.1
387     // Save 68k registers (M68kRegisters)
388 gbeauche 1.4 stw r8,56+0*4(r1) // d[0]..d[7]
389     stw r9,56+1*4(r1)
390     stw r10,56+2*4(r1)
391     stw r11,56+3*4(r1)
392     stw r12,56+4*4(r1)
393     stw r13,56+5*4(r1)
394     stw r14,56+6*4(r1)
395     stw r15,56+7*4(r1)
396     stw r16,56+8*4(r1) // a[0]..a[7]
397     stw r17,56+9*4(r1)
398     stw r18,56+10*4(r1)
399     stw r19,56+11*4(r1)
400     stw r20,56+12*4(r1)
401     stw r21,56+13*4(r1)
402     stw r22,56+14*4(r1)
403     stw r3,56+15*4(r1)
404     stfd f0,56+16*4+0*8(r1)
405     stfd f1,56+16*4+1*8(r1)
406     stfd f2,56+16*4+2*8(r1)
407     stfd f3,56+16*4+3*8(r1)
408     stfd f4,56+16*4+4*8(r1)
409     stfd f5,56+16*4+5*8(r1)
410     stfd f6,56+16*4+6*8(r1)
411     stfd f7,56+16*4+7*8(r1)
412 gbeauche 1.1 mffs f0
413 gbeauche 1.4 stfd f8,56+16*4+8*8(r1)
414     stfd f9,56+16*4+9*8(r1)
415     stfd f10,56+16*4+10*8(r1)
416     stfd f11,56+16*4+11*8(r1)
417     stfd f12,56+16*4+12*8(r1)
418     stfd f13,56+16*4+13*8(r1)
419     stfd f0,56+16*4+14*8(r1)
420 gbeauche 1.1
421     // Execute native routine
422 gbeauche 1.2 RESTORE_SYSTEM_R2
423     RESTORE_SYSTEM_R13
424 gbeauche 1.4 addi r3,r1,56
425 gbeauche 1.1 mr r4,r24
426     bl C_SYMBOL_NAME(EmulOp)
427    
428     // Restore 68k registers (M68kRegisters)
429 gbeauche 1.4 lwz r8,56+0*4(r1) // d[0]..d[7]
430     lwz r9,56+1*4(r1)
431     lwz r10,56+2*4(r1)
432     lwz r11,56+3*4(r1)
433     lwz r12,56+4*4(r1)
434     lwz r13,56+5*4(r1)
435     lwz r14,56+6*4(r1)
436     lwz r15,56+7*4(r1)
437     lwz r16,56+8*4(r1) // a[0]..a[7]
438     lwz r17,56+9*4(r1)
439     lwz r18,56+10*4(r1)
440     lwz r19,56+11*4(r1)
441     lwz r20,56+12*4(r1)
442     lwz r21,56+13*4(r1)
443     lwz r22,56+14*4(r1)
444     lwz r3,56+15*4(r1)
445     lfd f13,56+16*4+14*8(r1)
446     lfd f0,56+16*4+0*8(r1)
447     lfd f1,56+16*4+1*8(r1)
448     lfd f2,56+16*4+2*8(r1)
449     lfd f3,56+16*4+3*8(r1)
450     lfd f4,56+16*4+4*8(r1)
451     lfd f5,56+16*4+5*8(r1)
452     lfd f6,56+16*4+6*8(r1)
453     lfd f7,56+16*4+7*8(r1)
454 gbeauche 1.1 mtfsf 0xff,f13
455 gbeauche 1.4 lfd f8,56+16*4+8*8(r1)
456     lfd f9,56+16*4+9*8(r1)
457     lfd f10,56+16*4+10*8(r1)
458     lfd f11,56+16*4+11*8(r1)
459     lfd f12,56+16*4+12*8(r1)
460     lfd f13,56+16*4+13*8(r1)
461 gbeauche 1.1
462     // Delete PowerPC stack frame
463 gbeauche 1.4 lwz r2,56+16*4+15*8+12(r1)
464     lwz r0,56+16*4+15*8+16(r1)
465 gbeauche 1.1 mtxer r0
466 gbeauche 1.4 lwz r0,56+16*4+15*8+4(r1)
467 gbeauche 1.1 mtcrf 0xff,r0
468     mr r1,r3
469    
470     // Reentering 68k emulator
471     li r0,MODE_68K
472     stw r0,XLM_RUN_MODE(0)
473    
474     // Set r0 to 0 for 68k emulator
475     li r0,0
476    
477     // Execute next 68k opcode
478     rlwimi r29,r27,3,13,28
479     lhau r27,2(r24)
480     mtlr r29
481     blr
482    
483    
484     // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch
485     3: mflr r0
486     stw r0,XLM_EMUL_OP_PROC(0)
487    
488     // Save stack pointer for EMUL_RETURN
489     stw r1,XLM_EMUL_RETURN_STACK(0)
490    
491     // Preset registers for ROM boot routine
492 asvitkine 1.10 lis r3,ASM_HA16(C_SYMBOL_NAME(ROMBase)) // Pointer to ROM boot structure:
493     lwz r3,ASM_LO16(C_SYMBOL_NAME(ROMBase))(r3) // r3 = ROMBase + 0x30d000
494     addis r3,r3,ASM_HA16(0x30d000)
495     addi r3,r3,ASM_LO16(0x30d000)
496 gbeauche 1.1
497     // 68k emulator is now active
498     li r0,MODE_68K
499     stw r0,XLM_RUN_MODE(0)
500    
501     // Jump to ROM
502     bctr
503    
504    
505     /*
506     * void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine
507     */
508    
509     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k)
510     C_SYMBOL_NAME(execute_68k):
511     // Create MacOS stack frame
512     mflr r0
513     stw r0,4(r1)
514     stwu r1,-(56+19*4+18*8)(r1)
515     mfcr r0
516     stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN
517     stw r0,52(r1) // save CR
518    
519     // Save PowerPC registers
520     stmw r13,56(r1)
521     #if SAVE_FP_EXEC_68K
522     stfd f14,56+19*4+0*8(r1)
523     stfd f15,56+19*4+1*8(r1)
524     stfd f16,56+19*4+2*8(r1)
525     stfd f17,56+19*4+3*8(r1)
526     stfd f18,56+19*4+4*8(r1)
527     stfd f19,56+19*4+5*8(r1)
528     stfd f20,56+19*4+6*8(r1)
529     stfd f21,56+19*4+7*8(r1)
530     stfd f22,56+19*4+8*8(r1)
531     stfd f23,56+19*4+9*8(r1)
532     stfd f24,56+19*4+10*8(r1)
533     stfd f25,56+19*4+11*8(r1)
534     stfd f26,56+19*4+12*8(r1)
535     stfd f27,56+19*4+13*8(r1)
536     stfd f28,56+19*4+14*8(r1)
537     stfd f29,56+19*4+15*8(r1)
538     stfd f30,56+19*4+16*8(r1)
539     stfd f31,56+19*4+17*8(r1)
540     #endif
541    
542     // Set up registers for 68k emulator
543     lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data
544     addi r31,r31,0x1000
545     li r0,0
546     mtcrf 0xff,r0
547     creqv 11,11,11 // Supervisor mode
548     lwz r8,0*4(r4) // d[0]..d[7]
549     lwz r9,1*4(r4)
550     lwz r10,2*4(r4)
551     lwz r11,3*4(r4)
552     lwz r12,4*4(r4)
553     lwz r13,5*4(r4)
554     lwz r14,6*4(r4)
555     lwz r15,7*4(r4)
556     lwz r16,8*4(r4) // a[0]..a[6]
557     lwz r17,9*4(r4)
558     lwz r18,10*4(r4)
559     lwz r19,11*4(r4)
560     lwz r20,12*4(r4)
561     lwz r21,13*4(r4)
562     lwz r22,14*4(r4)
563     li r23,0
564     mr r24,r3
565     lwz r25,XLM_68K_R25(0) // MSB of SR
566     li r26,0
567     li r28,0 // VBR
568     lwz r29,0x74(r31) // Pointer to opcode table
569     lwz r30,0x78(r31) // Address of emulator
570    
571     // Push return address (points to EXEC_RETURN opcode) on stack
572     li r0,XLM_EXEC_RETURN_OPCODE
573     stwu r0,-4(r1)
574    
575     // Reentering 68k emulator
576     li r0,MODE_68K
577     stw r0,XLM_RUN_MODE(0)
578    
579     // Set r0 to 0 for 68k emulator
580     li r0,0
581    
582     // Execute 68k opcode
583     lha r27,0(r24)
584     rlwimi r29,r27,3,13,28
585     lhau r27,2(r24)
586     mtlr r29
587     blr
588    
589    
590     /*
591     * uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines
592     */
593    
594     ASM_MACRO_START prolog
595     mflr r0
596     stw r0,4(r1)
597     stwu r1,-64(r1)
598     ASM_MACRO_END
599    
600     ASM_MACRO_START epilog
601     lwz r0,64+4(r1)
602     mtlr r0
603     addi r1,r1,64
604 gbeauche 1.4 RESTORE_SYSTEM_R2
605     RESTORE_SYSTEM_R13
606 gbeauche 1.1 blr
607     ASM_MACRO_END
608    
609     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos)
610     C_SYMBOL_NAME(call_macos):
611     prolog
612     lwz r0,0(r3) // Get routine address
613     lwz r2,4(r3) // Load TOC pointer
614     mtctr r0
615     bctrl
616     epilog
617    
618     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1)
619     C_SYMBOL_NAME(call_macos1):
620     prolog
621     lwz r0,0(r3) // Get routine address
622     lwz r2,4(r3) // Load TOC pointer
623     mtctr r0
624     mr r3,r4
625     bctrl
626     epilog
627    
628     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2)
629     C_SYMBOL_NAME(call_macos2):
630     prolog
631     lwz r0,0(r3) // Get routine address
632     lwz r2,4(r3) // Load TOC pointer
633     mtctr r0
634     mr r3,r4
635     mr r4,r5
636     bctrl
637     epilog
638    
639     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3)
640     C_SYMBOL_NAME(call_macos3):
641     prolog
642     lwz r0,0(r3) // Get routine address
643     lwz r2,4(r3) // Load TOC pointer
644     mtctr r0
645     mr r3,r4
646     mr r4,r5
647     mr r5,r6
648     bctrl
649     epilog
650    
651     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4)
652     C_SYMBOL_NAME(call_macos4):
653     prolog
654     lwz r0,0(r3) // Get routine address
655     lwz r2,4(r3) // Load TOC pointer
656     mtctr r0
657     mr r3,r4
658     mr r4,r5
659     mr r5,r6
660     mr r6,r7
661     bctrl
662     epilog
663    
664     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5)
665     C_SYMBOL_NAME(call_macos5):
666     prolog
667     lwz r0,0(r3) // Get routine address
668     lwz r2,4(r3) // Load TOC pointer
669     mtctr r0
670     mr r3,r4
671     mr r4,r5
672     mr r5,r6
673     mr r6,r7
674     mr r7,r8
675     bctrl
676     epilog
677    
678     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6)
679     C_SYMBOL_NAME(call_macos6):
680     prolog
681     lwz r0,0(r3) // Get routine address
682     lwz r2,4(r3) // Load TOC pointer
683     mtctr r0
684     mr r3,r4
685     mr r4,r5
686     mr r5,r6
687     mr r6,r7
688     mr r7,r8
689     mr r8,r9
690     bctrl
691     epilog
692    
693     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7)
694     C_SYMBOL_NAME(call_macos7):
695     prolog
696     lwz r0,0(r3) // Get routine address
697     lwz r2,4(r3) // Load TOC pointer
698     mtctr r0
699     mr r3,r4
700     mr r4,r5
701     mr r5,r6
702     mr r6,r7
703     mr r7,r8
704     mr r8,r9
705     mr r9,r10
706     bctrl
707     epilog
708    
709    
710     /*
711     * Native resource manager patches
712     */
713    
714 gbeauche 1.5 ASM_MACRO_START do_get_resource ASM_MACRO_ARG0_DEF
715 gbeauche 1.1 // Create stack frame
716     mflr r0
717     stw r0,8(r1)
718     stwu r1,-(56+12)(r1)
719    
720     // Save type/ID
721     stw r3,56(r1)
722     stw r4,56+4(r1)
723    
724     // Call old routine
725 gbeauche 1.5 lwz r0,ASM_MACRO_ARG0(0)
726 gbeauche 1.1 lwz r2,XLM_RES_LIB_TOC(0)
727     mtctr r0
728     bctrl
729     stw r3,56+8(r1) // Save handle
730    
731     // Call CheckLoad
732 gbeauche 1.4 RESTORE_SYSTEM_R2
733     RESTORE_SYSTEM_R13
734 gbeauche 1.1 lwz r3,56(r1)
735     lha r4,56+6(r1)
736     lwz r5,56+8(r1)
737     bl C_SYMBOL_NAME(check_load_invoc)
738     lwz r3,56+8(r1) // Restore handle
739    
740     // Return to caller
741     lwz r0,56+12+8(r1)
742     mtlr r0
743     addi r1,r1,56+12
744     blr
745 gbeauche 1.4 ASM_MACRO_END
746    
747     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource)
748     C_SYMBOL_NAME(get_resource):
749     do_get_resource XLM_GET_RESOURCE
750 gbeauche 1.1
751     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource)
752     C_SYMBOL_NAME(get_1_resource):
753 gbeauche 1.4 do_get_resource XLM_GET_1_RESOURCE
754 gbeauche 1.1
755     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource)
756     C_SYMBOL_NAME(get_ind_resource):
757 gbeauche 1.4 do_get_resource XLM_GET_IND_RESOURCE
758 gbeauche 1.1
759     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource)
760     C_SYMBOL_NAME(get_1_ind_resource):
761 gbeauche 1.4 do_get_resource XLM_GET_1_IND_RESOURCE
762 gbeauche 1.1
763     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource)
764     C_SYMBOL_NAME(r_get_resource):
765 gbeauche 1.4 do_get_resource XLM_R_GET_RESOURCE
766 gbeauche 1.1
767 gbeauche 1.9 ASM_MACRO_START do_get_named_resource ASM_MACRO_ARG0_DEF
768     // Create stack frame
769     mflr r0
770     stw r0,8(r1)
771     stwu r1,-(56+12)(r1)
772    
773     // Save type/ID
774     stw r3,56(r1)
775     stw r4,56+4(r1)
776    
777     // Call old routine
778     lwz r0,ASM_MACRO_ARG0(0)
779     lwz r2,XLM_RES_LIB_TOC(0)
780     mtctr r0
781     bctrl
782     stw r3,56+8(r1) // Save handle
783    
784     // Call CheckLoad
785     RESTORE_SYSTEM_R2
786     RESTORE_SYSTEM_R13
787     lwz r3,56(r1)
788     lwz r4,56+4(r1)
789     lwz r5,56+8(r1)
790     bl C_SYMBOL_NAME(named_check_load_invoc)
791     lwz r3,56+8(r1) // Restore handle
792    
793     // Return to caller
794     lwz r0,56+12+8(r1)
795     mtlr r0
796     addi r1,r1,56+12
797     blr
798     ASM_MACRO_END
799    
800     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_named_resource)
801     C_SYMBOL_NAME(get_named_resource):
802     do_get_named_resource XLM_GET_NAMED_RESOURCE
803    
804     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_named_resource)
805     C_SYMBOL_NAME(get_1_named_resource):
806     do_get_named_resource XLM_GET_1_NAMED_RESOURCE
807    
808 gbeauche 1.1
809     /*
810     * void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt
811     */
812    
813     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt)
814     C_SYMBOL_NAME(ppc_interrupt):
815     mflr r0
816     stw r0,4(r1)
817     stwu r1,-64(r1)
818    
819     // Get address of return routine
820     bl 1f
821    
822     // Return routine
823     lwz r0,64+4(r1)
824     mtlr r0
825     addi r1,r1,64
826     blr
827    
828     // Prepare registers for nanokernel interrupt routine
829     1: mtctr r1
830     mr r1,r4
831     stw r6,0x018(r1)
832     mfctr r6
833     stw r6,0x004(r1)
834     lwz r6,0x65c(r1)
835     stw r7,0x13c(r6)
836     stw r8,0x144(r6)
837     stw r9,0x14c(r6)
838     stw r10,0x154(r6)
839     stw r11,0x15c(r6)
840     stw r12,0x164(r6)
841     stw r13,0x16c(r6)
842    
843     mflr r10
844     mfcr r13
845     lwz r7,0x660(r1)
846     mflr r12
847     rlwimi. r7,r7,8,0,0
848     li r11,0
849     ori r11,r11,0xf072 // MSR (SRR1)
850     mtcrf 0x70,r11
851     li r8,0
852    
853     // Enter nanokernel
854     mtlr r3
855     blr
856 gbeauche 1.7
857    
858     /*
859     * Define signal handlers with alternate stack initialization magic
860     */
861    
862     #define SIG_STACK_SIZE 0x10000
863    
864     ASM_MACRO_START do_define_signal_handler \
865     ASM_MACRO_ARG0_DEF /* name */ \
866     ASM_MACRO_ARG1_DEF /* stack */ \
867     ASM_MACRO_ARG2_DEF /* stack id */ \
868     ASM_MACRO_ARG3_DEF /* signal handler */
869    
870     // Alternate stack lower base for this signal handler
871     .lcomm ASM_MACRO_ARG1,SIG_STACK_SIZE,ASM_ALIGN_2(4)
872     ASM_TYPE(ASM_MACRO_ARG1,@object)
873    
874     // Represents the current nest level for this signal handler
875     // Note that in SheepShaver, SIGUSR2 signals are blocked while
876     // handling other signals so, it's unlikely we ever get a nest
877     // level greater than 1
878     .lcomm ASM_MACRO_ARG2,4,ASM_ALIGN_2(2)
879     ASM_TYPE(ASM_MACRO_ARG2,@object)
880    
881     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ASM_MACRO_ARG0)
882     C_SYMBOL_NAME(ASM_MACRO_ARG0):
883     // Preserve args in scratch registers
884     mflr r14
885     mr r15,r3
886     mr r16,r4
887     mr r17,r5
888     mr r18,r1
889    
890     // Atomically increase stack_id
891     lis r19,ASM_HA16(ASM_MACRO_ARG2)
892 asvitkine 1.10 la r19,ASM_LO16(ASM_MACRO_ARG2)(r19)
893 gbeauche 1.7 li r4,1
894     mr r3,r19
895     bl C_SYMBOL_NAME(atomic_add)
896     cmpwi r3,0
897     bne- 1f
898    
899     // ID was 0, we can use the local stack
900     lis r9,ASM_HA16(ASM_MACRO_ARG1)
901     lis r3,(SIG_STACK_SIZE>>16)
902 asvitkine 1.10 la r9,ASM_LO16(ASM_MACRO_ARG1)(r9)
903 gbeauche 1.7 addi r3,r3,((SIG_STACK_SIZE&0xffff)-64)
904     add r1,r9,r3
905    
906     1: // Invoke signal handler
907     stwu r1,-16(r1)
908     mr r3,r15
909     mr r4,r16
910     mr r5,r17
911     bl C_SYMBOL_NAME(ASM_MACRO_ARG3)
912     addi r1,r1,16
913    
914     // Atomically decrease stack id
915     mr r3,r19
916     li r4,-1
917     bl C_SYMBOL_NAME(atomic_add)
918    
919     // Restore kernel stack and return
920     mtlr r14
921     mr r1,r18
922     blr
923     ASM_MACRO_END
924    
925     #define DEFINE_SIGNAL_HANDLER(NAME) \
926     do_define_signal_handler \
927     NAME##_handler_init ASM_MACRO_ARG_SEP \
928     NAME##_stack ASM_MACRO_ARG_SEP \
929     NAME##_stack_id ASM_MACRO_ARG_SEP \
930     NAME##_handler
931    
932     DEFINE_SIGNAL_HANDLER(sigusr2)