mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-05-28 12:41:32 +00:00
b3b5db5456
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.
933 lines
18 KiB
ArmAsm
933 lines
18 KiB
ArmAsm
/*
|
|
* asm_linux.S - Assembly routines
|
|
*
|
|
* SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <ppc_asm.tmpl>
|
|
#include <xlowmem.h>
|
|
|
|
#define SAVE_FP_EXEC_68K 1
|
|
|
|
|
|
/*
|
|
* void *get_sp(void) - Get stack pointer
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_sp)
|
|
C_SYMBOL_NAME(get_sp):
|
|
mr r3,r1
|
|
blr
|
|
|
|
|
|
/*
|
|
* void *get_r2(void) - Get r2
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r2)
|
|
C_SYMBOL_NAME(get_r2):
|
|
mr r3,r2
|
|
blr
|
|
|
|
|
|
/*
|
|
* void set_r2(void *val {r3}) - Set r2
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r2)
|
|
C_SYMBOL_NAME(set_r2):
|
|
mr r2,r3
|
|
blr
|
|
|
|
|
|
/*
|
|
* void *get_r13(void) - Get r13 (small data pointer under Linux)
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r13)
|
|
C_SYMBOL_NAME(get_r13):
|
|
mr r3,r13
|
|
blr
|
|
|
|
/*
|
|
* void set_r13(void *val {r3}) - Set r13 (small data pointer under Linux)
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r13)
|
|
C_SYMBOL_NAME(set_r13):
|
|
mr r13,r3
|
|
blr
|
|
|
|
|
|
/*
|
|
* void flush_icache_range(void *start {r3}, void *end {r3}) - Flush D and I cache
|
|
*/
|
|
|
|
CACHE_LINE_SIZE = 32
|
|
LG_CACHE_LINE_SIZE = 5
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(flush_icache_range)
|
|
C_SYMBOL_NAME(flush_icache_range):
|
|
li r5,CACHE_LINE_SIZE-1
|
|
andc r3,r3,r5
|
|
subf r4,r3,r4
|
|
add r4,r4,r5
|
|
srwi. r4,r4,LG_CACHE_LINE_SIZE
|
|
beqlr
|
|
mtctr r4
|
|
mr r6,r3
|
|
1: dcbst 0,r3
|
|
addi r3,r3,CACHE_LINE_SIZE
|
|
bdnz 1b
|
|
sync /* wait for dcbst's to get to ram */
|
|
mtctr r4
|
|
2: icbi 0,r6
|
|
addi r6,r6,CACHE_LINE_SIZE
|
|
bdnz 2b
|
|
sync
|
|
isync
|
|
blr
|
|
|
|
|
|
/*
|
|
* long atomic_add(long *var{r3}, long add{r4}) - Atomic add operation
|
|
* long atomic_and(long *var{r3}, long and{r4}) - Atomic and operation
|
|
* long atomic_or(long *var{r3}, long or{r4}) - Atomic or operation
|
|
* int test_and_set(int *var{r3}, int val{r4}) - Atomic test-and-set
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_add)
|
|
C_SYMBOL_NAME(atomic_add):
|
|
0: dcbf 0,r3
|
|
sync
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
isync
|
|
lwarx r5,0,r3
|
|
add r0,r4,r5
|
|
stwcx. r0,0,r3
|
|
bne- 0b
|
|
mr r3,r5
|
|
isync
|
|
blr
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_and)
|
|
C_SYMBOL_NAME(atomic_and):
|
|
0: dcbf 0,r3
|
|
sync
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
isync
|
|
lwarx r5,0,r3
|
|
and r0,r4,r5
|
|
stwcx. r0,0,r3
|
|
bne- 0b
|
|
mr r3,r5
|
|
isync
|
|
blr
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_or)
|
|
C_SYMBOL_NAME(atomic_or):
|
|
0: dcbf 0,r3
|
|
sync
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
isync
|
|
lwarx r5,0,r3
|
|
or r0,r4,r5
|
|
stwcx. r0,0,r3
|
|
bne- 0b
|
|
mr r3,r5
|
|
isync
|
|
blr
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(test_and_set)
|
|
C_SYMBOL_NAME(test_and_set):
|
|
0: dcbf 0,r3
|
|
sync
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
ori r0,r0,1
|
|
isync
|
|
lwarx r5,0,r3
|
|
cmpi 0,r5,0x0000
|
|
bne 1f
|
|
stwcx. r4,0,r3
|
|
bne- 0b
|
|
1: isync
|
|
mr r3,r5
|
|
blr
|
|
|
|
|
|
/*
|
|
* void quit_emulator(void) - Jump to XLM_EMUL_RETURN_PROC
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(quit_emulator)
|
|
C_SYMBOL_NAME(quit_emulator):
|
|
lwz r0,XLM_EMUL_RETURN_PROC(0)
|
|
mtlr r0
|
|
blr
|
|
|
|
|
|
/*
|
|
* void jump_to_rom(uint32 entry {r3}, uint32 emulator_data {r4}) - Jump to Mac ROM
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(jump_to_rom)
|
|
C_SYMBOL_NAME(jump_to_rom):
|
|
// Create stack frame
|
|
mflr r0
|
|
stw r0,4(r1)
|
|
stwu r1,-(20+19*4+18*8)(r1) // maintain 16 byte alignment
|
|
|
|
// Save PowerPC registers
|
|
stmw r13,20(r1)
|
|
stfd f14,20+19*4+0*8(r1)
|
|
stfd f15,20+19*4+1*8(r1)
|
|
stfd f16,20+19*4+2*8(r1)
|
|
stfd f17,20+19*4+3*8(r1)
|
|
stfd f18,20+19*4+4*8(r1)
|
|
stfd f19,20+19*4+5*8(r1)
|
|
stfd f20,20+19*4+6*8(r1)
|
|
stfd f21,20+19*4+7*8(r1)
|
|
stfd f22,20+19*4+8*8(r1)
|
|
stfd f23,20+19*4+9*8(r1)
|
|
stfd f24,20+19*4+10*8(r1)
|
|
stfd f25,20+19*4+11*8(r1)
|
|
stfd f26,20+19*4+12*8(r1)
|
|
stfd f27,20+19*4+13*8(r1)
|
|
stfd f28,20+19*4+14*8(r1)
|
|
stfd f29,20+19*4+15*8(r1)
|
|
stfd f30,20+19*4+16*8(r1)
|
|
stfd f31,20+19*4+17*8(r1)
|
|
|
|
// Move entry address to ctr
|
|
mtctr r3
|
|
|
|
// Skip over EMUL_RETURN routine and get its address
|
|
bl 1f
|
|
|
|
|
|
/*
|
|
* EMUL_RETURN: Returned from emulator
|
|
*/
|
|
|
|
// Restore PowerPC registers
|
|
lwz r1,XLM_EMUL_RETURN_STACK(0)
|
|
RESTORE_SYSTEM_R2
|
|
lmw r13,20(r1)
|
|
lfd f14,20+19*4+0*8(r1)
|
|
lfd f15,20+19*4+1*8(r1)
|
|
lfd f16,20+19*4+2*8(r1)
|
|
lfd f17,20+19*4+3*8(r1)
|
|
lfd f18,20+19*4+4*8(r1)
|
|
lfd f19,20+19*4+5*8(r1)
|
|
lfd f20,20+19*4+6*8(r1)
|
|
lfd f21,20+19*4+7*8(r1)
|
|
lfd f22,20+19*4+8*8(r1)
|
|
lfd f23,20+19*4+9*8(r1)
|
|
lfd f24,20+19*4+10*8(r1)
|
|
lfd f25,20+19*4+11*8(r1)
|
|
lfd f26,20+19*4+12*8(r1)
|
|
lfd f27,20+19*4+13*8(r1)
|
|
lfd f28,20+19*4+14*8(r1)
|
|
lfd f29,20+19*4+15*8(r1)
|
|
lfd f30,20+19*4+16*8(r1)
|
|
lfd f31,20+19*4+17*8(r1)
|
|
|
|
// Exiting from 68k emulator
|
|
li r0,1
|
|
stw r0,XLM_IRQ_NEST(0)
|
|
li r0,MODE_NATIVE
|
|
stw r0,XLM_RUN_MODE(0)
|
|
|
|
// Return to caller of jump_to_rom()
|
|
lwz r0,20+19*4+18*8+4(r1)
|
|
mtlr r0
|
|
addi r1,r1,20+19*4+18*8
|
|
blr
|
|
|
|
|
|
// Save address of EMUL_RETURN routine for 68k emulator patch
|
|
1: mflr r0
|
|
stw r0,XLM_EMUL_RETURN_PROC(0)
|
|
|
|
// Skip over EXEC_RETURN routine and get its address
|
|
bl 2f
|
|
|
|
|
|
/*
|
|
* EXEC_RETURN: Returned from 68k routine executed with Execute68k()
|
|
*/
|
|
|
|
// Save r25 (contains current 68k interrupt level)
|
|
stw r25,XLM_68K_R25(0)
|
|
|
|
// Reentering EMUL_OP mode
|
|
li r0,MODE_EMUL_OP
|
|
stw r0,XLM_RUN_MODE(0)
|
|
|
|
// Save 68k registers
|
|
lwz r4,48(r1) // Pointer to M68kRegisters
|
|
stw r8,0*4(r4) // d[0]...d[7]
|
|
stw r9,1*4(r4)
|
|
stw r10,2*4(r4)
|
|
stw r11,3*4(r4)
|
|
stw r12,4*4(r4)
|
|
stw r13,5*4(r4)
|
|
stw r14,6*4(r4)
|
|
stw r15,7*4(r4)
|
|
stw r16,8*4(r4) // a[0]..a[6]
|
|
stw r17,9*4(r4)
|
|
stw r18,10*4(r4)
|
|
stw r19,11*4(r4)
|
|
stw r20,12*4(r4)
|
|
stw r21,13*4(r4)
|
|
stw r22,14*4(r4)
|
|
|
|
// Restore PowerPC registers
|
|
lmw r13,56(r1)
|
|
#if SAVE_FP_EXEC_68K
|
|
lfd f14,56+19*4+0*8(r1)
|
|
lfd f15,56+19*4+1*8(r1)
|
|
lfd f16,56+19*4+2*8(r1)
|
|
lfd f17,56+19*4+3*8(r1)
|
|
lfd f18,56+19*4+4*8(r1)
|
|
lfd f19,56+19*4+5*8(r1)
|
|
lfd f20,56+19*4+6*8(r1)
|
|
lfd f21,56+19*4+7*8(r1)
|
|
lfd f22,56+19*4+8*8(r1)
|
|
lfd f23,56+19*4+9*8(r1)
|
|
lfd f24,56+19*4+10*8(r1)
|
|
lfd f25,56+19*4+11*8(r1)
|
|
lfd f26,56+19*4+12*8(r1)
|
|
lfd f27,56+19*4+13*8(r1)
|
|
lfd f28,56+19*4+14*8(r1)
|
|
lfd f29,56+19*4+15*8(r1)
|
|
lfd f30,56+19*4+16*8(r1)
|
|
lfd f31,56+19*4+17*8(r1)
|
|
#endif
|
|
|
|
// Return to caller
|
|
lwz r0,52(r1)
|
|
mtcrf 0xff,r0
|
|
lwz r0,56+19*4+18*8+4(r1)
|
|
mtlr r0
|
|
addi r1,r1,56+19*4+18*8
|
|
RESTORE_SYSTEM_R2
|
|
RESTORE_SYSTEM_R13
|
|
blr
|
|
|
|
|
|
// Save address of EXEC_RETURN routine for 68k emulator patch
|
|
2: mflr r0
|
|
stw r0,XLM_EXEC_RETURN_PROC(0)
|
|
|
|
// Skip over EMUL_BREAK/EMUL_OP routine and get its address
|
|
bl 3f
|
|
|
|
|
|
/*
|
|
* EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
|
|
*
|
|
* 68k registers are stored in a M68kRegisters struct on the stack
|
|
* which the native routine may read and modify
|
|
*/
|
|
|
|
// Save r25 (contains current 68k interrupt level)
|
|
stw r25,XLM_68K_R25(0)
|
|
|
|
// Entering EMUL_OP mode within 68k emulator
|
|
li r0,MODE_EMUL_OP
|
|
stw r0,XLM_RUN_MODE(0)
|
|
|
|
// Create PowerPC stack frame, reserve space for M68kRegisters
|
|
mr r3,r1
|
|
subi r1,r1,64 // Fake "caller" frame
|
|
rlwinm r1,r1,0,0,27 // Align stack
|
|
|
|
mfcr r0
|
|
rlwinm r0,r0,0,11,8
|
|
stw r0,4(r1)
|
|
mfxer r0
|
|
stw r0,16(r1)
|
|
stw r2,12(r1)
|
|
stwu r1,-(56+16*4+15*8)(r1)
|
|
|
|
// Save 68k registers (M68kRegisters)
|
|
stw r8,56+0*4(r1) // d[0]..d[7]
|
|
stw r9,56+1*4(r1)
|
|
stw r10,56+2*4(r1)
|
|
stw r11,56+3*4(r1)
|
|
stw r12,56+4*4(r1)
|
|
stw r13,56+5*4(r1)
|
|
stw r14,56+6*4(r1)
|
|
stw r15,56+7*4(r1)
|
|
stw r16,56+8*4(r1) // a[0]..a[7]
|
|
stw r17,56+9*4(r1)
|
|
stw r18,56+10*4(r1)
|
|
stw r19,56+11*4(r1)
|
|
stw r20,56+12*4(r1)
|
|
stw r21,56+13*4(r1)
|
|
stw r22,56+14*4(r1)
|
|
stw r3,56+15*4(r1)
|
|
stfd f0,56+16*4+0*8(r1)
|
|
stfd f1,56+16*4+1*8(r1)
|
|
stfd f2,56+16*4+2*8(r1)
|
|
stfd f3,56+16*4+3*8(r1)
|
|
stfd f4,56+16*4+4*8(r1)
|
|
stfd f5,56+16*4+5*8(r1)
|
|
stfd f6,56+16*4+6*8(r1)
|
|
stfd f7,56+16*4+7*8(r1)
|
|
mffs f0
|
|
stfd f8,56+16*4+8*8(r1)
|
|
stfd f9,56+16*4+9*8(r1)
|
|
stfd f10,56+16*4+10*8(r1)
|
|
stfd f11,56+16*4+11*8(r1)
|
|
stfd f12,56+16*4+12*8(r1)
|
|
stfd f13,56+16*4+13*8(r1)
|
|
stfd f0,56+16*4+14*8(r1)
|
|
|
|
// Execute native routine
|
|
RESTORE_SYSTEM_R2
|
|
RESTORE_SYSTEM_R13
|
|
addi r3,r1,56
|
|
mr r4,r24
|
|
bl C_SYMBOL_NAME(EmulOp)
|
|
|
|
// Restore 68k registers (M68kRegisters)
|
|
lwz r8,56+0*4(r1) // d[0]..d[7]
|
|
lwz r9,56+1*4(r1)
|
|
lwz r10,56+2*4(r1)
|
|
lwz r11,56+3*4(r1)
|
|
lwz r12,56+4*4(r1)
|
|
lwz r13,56+5*4(r1)
|
|
lwz r14,56+6*4(r1)
|
|
lwz r15,56+7*4(r1)
|
|
lwz r16,56+8*4(r1) // a[0]..a[7]
|
|
lwz r17,56+9*4(r1)
|
|
lwz r18,56+10*4(r1)
|
|
lwz r19,56+11*4(r1)
|
|
lwz r20,56+12*4(r1)
|
|
lwz r21,56+13*4(r1)
|
|
lwz r22,56+14*4(r1)
|
|
lwz r3,56+15*4(r1)
|
|
lfd f13,56+16*4+14*8(r1)
|
|
lfd f0,56+16*4+0*8(r1)
|
|
lfd f1,56+16*4+1*8(r1)
|
|
lfd f2,56+16*4+2*8(r1)
|
|
lfd f3,56+16*4+3*8(r1)
|
|
lfd f4,56+16*4+4*8(r1)
|
|
lfd f5,56+16*4+5*8(r1)
|
|
lfd f6,56+16*4+6*8(r1)
|
|
lfd f7,56+16*4+7*8(r1)
|
|
mtfsf 0xff,f13
|
|
lfd f8,56+16*4+8*8(r1)
|
|
lfd f9,56+16*4+9*8(r1)
|
|
lfd f10,56+16*4+10*8(r1)
|
|
lfd f11,56+16*4+11*8(r1)
|
|
lfd f12,56+16*4+12*8(r1)
|
|
lfd f13,56+16*4+13*8(r1)
|
|
|
|
// Delete PowerPC stack frame
|
|
lwz r2,56+16*4+15*8+12(r1)
|
|
lwz r0,56+16*4+15*8+16(r1)
|
|
mtxer r0
|
|
lwz r0,56+16*4+15*8+4(r1)
|
|
mtcrf 0xff,r0
|
|
mr r1,r3
|
|
|
|
// Reentering 68k emulator
|
|
li r0,MODE_68K
|
|
stw r0,XLM_RUN_MODE(0)
|
|
|
|
// Set r0 to 0 for 68k emulator
|
|
li r0,0
|
|
|
|
// Execute next 68k opcode
|
|
rlwimi r29,r27,3,13,28
|
|
lhau r27,2(r24)
|
|
mtlr r29
|
|
blr
|
|
|
|
|
|
// Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch
|
|
3: mflr r0
|
|
stw r0,XLM_EMUL_OP_PROC(0)
|
|
|
|
// Save stack pointer for EMUL_RETURN
|
|
stw r1,XLM_EMUL_RETURN_STACK(0)
|
|
|
|
// Preset registers for ROM boot routine
|
|
lis r3,ASM_HA16(C_SYMBOL_NAME(ROMBase)) // Pointer to ROM boot structure:
|
|
lwz r3,ASM_LO16(C_SYMBOL_NAME(ROMBase))(r3) // r3 = ROMBase + 0x30d000
|
|
addis r3,r3,ASM_HA16(0x30d000)
|
|
addi r3,r3,ASM_LO16(0x30d000)
|
|
|
|
// 68k emulator is now active
|
|
li r0,MODE_68K
|
|
stw r0,XLM_RUN_MODE(0)
|
|
|
|
// Jump to ROM
|
|
bctr
|
|
|
|
|
|
/*
|
|
* void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k)
|
|
C_SYMBOL_NAME(execute_68k):
|
|
// Create MacOS stack frame
|
|
mflr r0
|
|
stw r0,4(r1)
|
|
stwu r1,-(56+19*4+18*8)(r1)
|
|
mfcr r0
|
|
stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN
|
|
stw r0,52(r1) // save CR
|
|
|
|
// Save PowerPC registers
|
|
stmw r13,56(r1)
|
|
#if SAVE_FP_EXEC_68K
|
|
stfd f14,56+19*4+0*8(r1)
|
|
stfd f15,56+19*4+1*8(r1)
|
|
stfd f16,56+19*4+2*8(r1)
|
|
stfd f17,56+19*4+3*8(r1)
|
|
stfd f18,56+19*4+4*8(r1)
|
|
stfd f19,56+19*4+5*8(r1)
|
|
stfd f20,56+19*4+6*8(r1)
|
|
stfd f21,56+19*4+7*8(r1)
|
|
stfd f22,56+19*4+8*8(r1)
|
|
stfd f23,56+19*4+9*8(r1)
|
|
stfd f24,56+19*4+10*8(r1)
|
|
stfd f25,56+19*4+11*8(r1)
|
|
stfd f26,56+19*4+12*8(r1)
|
|
stfd f27,56+19*4+13*8(r1)
|
|
stfd f28,56+19*4+14*8(r1)
|
|
stfd f29,56+19*4+15*8(r1)
|
|
stfd f30,56+19*4+16*8(r1)
|
|
stfd f31,56+19*4+17*8(r1)
|
|
#endif
|
|
|
|
// Set up registers for 68k emulator
|
|
lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data
|
|
addi r31,r31,0x1000
|
|
li r0,0
|
|
mtcrf 0xff,r0
|
|
creqv 11,11,11 // Supervisor mode
|
|
lwz r8,0*4(r4) // d[0]..d[7]
|
|
lwz r9,1*4(r4)
|
|
lwz r10,2*4(r4)
|
|
lwz r11,3*4(r4)
|
|
lwz r12,4*4(r4)
|
|
lwz r13,5*4(r4)
|
|
lwz r14,6*4(r4)
|
|
lwz r15,7*4(r4)
|
|
lwz r16,8*4(r4) // a[0]..a[6]
|
|
lwz r17,9*4(r4)
|
|
lwz r18,10*4(r4)
|
|
lwz r19,11*4(r4)
|
|
lwz r20,12*4(r4)
|
|
lwz r21,13*4(r4)
|
|
lwz r22,14*4(r4)
|
|
li r23,0
|
|
mr r24,r3
|
|
lwz r25,XLM_68K_R25(0) // MSB of SR
|
|
li r26,0
|
|
li r28,0 // VBR
|
|
lwz r29,0x74(r31) // Pointer to opcode table
|
|
lwz r30,0x78(r31) // Address of emulator
|
|
|
|
// Push return address (points to EXEC_RETURN opcode) on stack
|
|
li r0,XLM_EXEC_RETURN_OPCODE
|
|
stwu r0,-4(r1)
|
|
|
|
// Reentering 68k emulator
|
|
li r0,MODE_68K
|
|
stw r0,XLM_RUN_MODE(0)
|
|
|
|
// Set r0 to 0 for 68k emulator
|
|
li r0,0
|
|
|
|
// Execute 68k opcode
|
|
lha r27,0(r24)
|
|
rlwimi r29,r27,3,13,28
|
|
lhau r27,2(r24)
|
|
mtlr r29
|
|
blr
|
|
|
|
|
|
/*
|
|
* uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines
|
|
*/
|
|
|
|
ASM_MACRO_START prolog
|
|
mflr r0
|
|
stw r0,4(r1)
|
|
stwu r1,-64(r1)
|
|
ASM_MACRO_END
|
|
|
|
ASM_MACRO_START epilog
|
|
lwz r0,64+4(r1)
|
|
mtlr r0
|
|
addi r1,r1,64
|
|
RESTORE_SYSTEM_R2
|
|
RESTORE_SYSTEM_R13
|
|
blr
|
|
ASM_MACRO_END
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos)
|
|
C_SYMBOL_NAME(call_macos):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1)
|
|
C_SYMBOL_NAME(call_macos1):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2)
|
|
C_SYMBOL_NAME(call_macos2):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
mr r4,r5
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3)
|
|
C_SYMBOL_NAME(call_macos3):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
mr r4,r5
|
|
mr r5,r6
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4)
|
|
C_SYMBOL_NAME(call_macos4):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
mr r4,r5
|
|
mr r5,r6
|
|
mr r6,r7
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5)
|
|
C_SYMBOL_NAME(call_macos5):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
mr r4,r5
|
|
mr r5,r6
|
|
mr r6,r7
|
|
mr r7,r8
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6)
|
|
C_SYMBOL_NAME(call_macos6):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
mr r4,r5
|
|
mr r5,r6
|
|
mr r6,r7
|
|
mr r7,r8
|
|
mr r8,r9
|
|
bctrl
|
|
epilog
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7)
|
|
C_SYMBOL_NAME(call_macos7):
|
|
prolog
|
|
lwz r0,0(r3) // Get routine address
|
|
lwz r2,4(r3) // Load TOC pointer
|
|
mtctr r0
|
|
mr r3,r4
|
|
mr r4,r5
|
|
mr r5,r6
|
|
mr r6,r7
|
|
mr r7,r8
|
|
mr r8,r9
|
|
mr r9,r10
|
|
bctrl
|
|
epilog
|
|
|
|
|
|
/*
|
|
* Native resource manager patches
|
|
*/
|
|
|
|
ASM_MACRO_START do_get_resource ASM_MACRO_ARG0_DEF
|
|
// Create stack frame
|
|
mflr r0
|
|
stw r0,8(r1)
|
|
stwu r1,-(56+12)(r1)
|
|
|
|
// Save type/ID
|
|
stw r3,56(r1)
|
|
stw r4,56+4(r1)
|
|
|
|
// Call old routine
|
|
lwz r0,ASM_MACRO_ARG0(0)
|
|
lwz r2,XLM_RES_LIB_TOC(0)
|
|
mtctr r0
|
|
bctrl
|
|
stw r3,56+8(r1) // Save handle
|
|
|
|
// Call CheckLoad
|
|
RESTORE_SYSTEM_R2
|
|
RESTORE_SYSTEM_R13
|
|
lwz r3,56(r1)
|
|
lha r4,56+6(r1)
|
|
lwz r5,56+8(r1)
|
|
bl C_SYMBOL_NAME(check_load_invoc)
|
|
lwz r3,56+8(r1) // Restore handle
|
|
|
|
// Return to caller
|
|
lwz r0,56+12+8(r1)
|
|
mtlr r0
|
|
addi r1,r1,56+12
|
|
blr
|
|
ASM_MACRO_END
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource)
|
|
C_SYMBOL_NAME(get_resource):
|
|
do_get_resource XLM_GET_RESOURCE
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource)
|
|
C_SYMBOL_NAME(get_1_resource):
|
|
do_get_resource XLM_GET_1_RESOURCE
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource)
|
|
C_SYMBOL_NAME(get_ind_resource):
|
|
do_get_resource XLM_GET_IND_RESOURCE
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource)
|
|
C_SYMBOL_NAME(get_1_ind_resource):
|
|
do_get_resource XLM_GET_1_IND_RESOURCE
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource)
|
|
C_SYMBOL_NAME(r_get_resource):
|
|
do_get_resource XLM_R_GET_RESOURCE
|
|
|
|
ASM_MACRO_START do_get_named_resource ASM_MACRO_ARG0_DEF
|
|
// Create stack frame
|
|
mflr r0
|
|
stw r0,8(r1)
|
|
stwu r1,-(56+12)(r1)
|
|
|
|
// Save type/ID
|
|
stw r3,56(r1)
|
|
stw r4,56+4(r1)
|
|
|
|
// Call old routine
|
|
lwz r0,ASM_MACRO_ARG0(0)
|
|
lwz r2,XLM_RES_LIB_TOC(0)
|
|
mtctr r0
|
|
bctrl
|
|
stw r3,56+8(r1) // Save handle
|
|
|
|
// Call CheckLoad
|
|
RESTORE_SYSTEM_R2
|
|
RESTORE_SYSTEM_R13
|
|
lwz r3,56(r1)
|
|
lwz r4,56+4(r1)
|
|
lwz r5,56+8(r1)
|
|
bl C_SYMBOL_NAME(named_check_load_invoc)
|
|
lwz r3,56+8(r1) // Restore handle
|
|
|
|
// Return to caller
|
|
lwz r0,56+12+8(r1)
|
|
mtlr r0
|
|
addi r1,r1,56+12
|
|
blr
|
|
ASM_MACRO_END
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_named_resource)
|
|
C_SYMBOL_NAME(get_named_resource):
|
|
do_get_named_resource XLM_GET_NAMED_RESOURCE
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_named_resource)
|
|
C_SYMBOL_NAME(get_1_named_resource):
|
|
do_get_named_resource XLM_GET_1_NAMED_RESOURCE
|
|
|
|
|
|
/*
|
|
* void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt
|
|
*/
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt)
|
|
C_SYMBOL_NAME(ppc_interrupt):
|
|
mflr r0
|
|
stw r0,4(r1)
|
|
stwu r1,-64(r1)
|
|
|
|
// Get address of return routine
|
|
bl 1f
|
|
|
|
// Return routine
|
|
lwz r0,64+4(r1)
|
|
mtlr r0
|
|
addi r1,r1,64
|
|
blr
|
|
|
|
// Prepare registers for nanokernel interrupt routine
|
|
1: mtctr r1
|
|
mr r1,r4
|
|
stw r6,0x018(r1)
|
|
mfctr r6
|
|
stw r6,0x004(r1)
|
|
lwz r6,0x65c(r1)
|
|
stw r7,0x13c(r6)
|
|
stw r8,0x144(r6)
|
|
stw r9,0x14c(r6)
|
|
stw r10,0x154(r6)
|
|
stw r11,0x15c(r6)
|
|
stw r12,0x164(r6)
|
|
stw r13,0x16c(r6)
|
|
|
|
mflr r10
|
|
mfcr r13
|
|
lwz r7,0x660(r1)
|
|
mflr r12
|
|
rlwimi. r7,r7,8,0,0
|
|
li r11,0
|
|
ori r11,r11,0xf072 // MSR (SRR1)
|
|
mtcrf 0x70,r11
|
|
li r8,0
|
|
|
|
// Enter nanokernel
|
|
mtlr r3
|
|
blr
|
|
|
|
|
|
/*
|
|
* Define signal handlers with alternate stack initialization magic
|
|
*/
|
|
|
|
#define SIG_STACK_SIZE 0x10000
|
|
|
|
ASM_MACRO_START do_define_signal_handler \
|
|
ASM_MACRO_ARG0_DEF /* name */ \
|
|
ASM_MACRO_ARG1_DEF /* stack */ \
|
|
ASM_MACRO_ARG2_DEF /* stack id */ \
|
|
ASM_MACRO_ARG3_DEF /* signal handler */
|
|
|
|
// Alternate stack lower base for this signal handler
|
|
.lcomm ASM_MACRO_ARG1,SIG_STACK_SIZE,ASM_ALIGN_2(4)
|
|
ASM_TYPE(ASM_MACRO_ARG1,@object)
|
|
|
|
// Represents the current nest level for this signal handler
|
|
// Note that in SheepShaver, SIGUSR2 signals are blocked while
|
|
// handling other signals so, it's unlikely we ever get a nest
|
|
// level greater than 1
|
|
.lcomm ASM_MACRO_ARG2,4,ASM_ALIGN_2(2)
|
|
ASM_TYPE(ASM_MACRO_ARG2,@object)
|
|
|
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ASM_MACRO_ARG0)
|
|
C_SYMBOL_NAME(ASM_MACRO_ARG0):
|
|
// Preserve args in scratch registers
|
|
mflr r14
|
|
mr r15,r3
|
|
mr r16,r4
|
|
mr r17,r5
|
|
mr r18,r1
|
|
|
|
// Atomically increase stack_id
|
|
lis r19,ASM_HA16(ASM_MACRO_ARG2)
|
|
la r19,ASM_LO16(ASM_MACRO_ARG2)(r19)
|
|
li r4,1
|
|
mr r3,r19
|
|
bl C_SYMBOL_NAME(atomic_add)
|
|
cmpwi r3,0
|
|
bne- 1f
|
|
|
|
// ID was 0, we can use the local stack
|
|
lis r9,ASM_HA16(ASM_MACRO_ARG1)
|
|
lis r3,(SIG_STACK_SIZE>>16)
|
|
la r9,ASM_LO16(ASM_MACRO_ARG1)(r9)
|
|
addi r3,r3,((SIG_STACK_SIZE&0xffff)-64)
|
|
add r1,r9,r3
|
|
|
|
1: // Invoke signal handler
|
|
stwu r1,-16(r1)
|
|
mr r3,r15
|
|
mr r4,r16
|
|
mr r5,r17
|
|
bl C_SYMBOL_NAME(ASM_MACRO_ARG3)
|
|
addi r1,r1,16
|
|
|
|
// Atomically decrease stack id
|
|
mr r3,r19
|
|
li r4,-1
|
|
bl C_SYMBOL_NAME(atomic_add)
|
|
|
|
// Restore kernel stack and return
|
|
mtlr r14
|
|
mr r1,r18
|
|
blr
|
|
ASM_MACRO_END
|
|
|
|
#define DEFINE_SIGNAL_HANDLER(NAME) \
|
|
do_define_signal_handler \
|
|
NAME##_handler_init ASM_MACRO_ARG_SEP \
|
|
NAME##_stack ASM_MACRO_ARG_SEP \
|
|
NAME##_stack_id ASM_MACRO_ARG_SEP \
|
|
NAME##_handler
|
|
|
|
DEFINE_SIGNAL_HANDLER(sigusr2)
|