mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-23 04:30:10 +00:00
- Share EmulatorData & KernelData struct definitions
- Introduce new SheepShaver data area for alternate stacks, thunks, etc. - Experimental asynchronous interrupts handling. This improves performance by 30% but some (rare) lockups may occur. To be debugged!
This commit is contained in:
parent
ddcfbe2bda
commit
b8b139faf2
@ -117,30 +117,11 @@ const char RAM_AREA_NAME[] = "Macintosh RAM";
|
||||
const char ROM_AREA_NAME[] = "Macintosh ROM";
|
||||
const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache";
|
||||
|
||||
const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area
|
||||
|
||||
const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data
|
||||
const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data
|
||||
const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area
|
||||
|
||||
const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack
|
||||
|
||||
const uint32 MSG_START = 'strt'; // Emulator start message
|
||||
|
||||
|
||||
// Emulator Data
|
||||
struct EmulatorData {
|
||||
uint32 v[0x400];
|
||||
};
|
||||
|
||||
|
||||
// Kernel Data
|
||||
struct KernelData {
|
||||
uint32 v[0x400];
|
||||
EmulatorData ed;
|
||||
};
|
||||
|
||||
|
||||
// Application object
|
||||
class SheepShaver : public BApplication {
|
||||
public:
|
||||
|
@ -145,29 +145,10 @@
|
||||
const char ROM_FILE_NAME[] = "ROM";
|
||||
const char ROM_FILE_NAME2[] = "Mac OS ROM";
|
||||
|
||||
const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area
|
||||
const uint32 ROM_END = ROM_BASE + ROM_SIZE; // End of ROM
|
||||
|
||||
const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data
|
||||
const uint32 KERNEL_DATA2_BASE = 0x5fffe000; // Alternate address of Kernel Data
|
||||
const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area
|
||||
|
||||
const uint32 RAM_BASE = 0x20000000; // Base address of RAM
|
||||
const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
|
||||
|
||||
|
||||
// 68k Emulator Data
|
||||
struct EmulatorData {
|
||||
uint32 v[0x400];
|
||||
};
|
||||
|
||||
|
||||
// Kernel Data
|
||||
struct KernelData {
|
||||
uint32 v[0x400];
|
||||
EmulatorData ed;
|
||||
};
|
||||
|
||||
|
||||
#if !EMULATED_PPC
|
||||
// Structure in which registers are saved in a signal handler;
|
||||
// sigcontext->regs points to it
|
||||
@ -191,6 +172,9 @@ void *TOC; // Small data pointer (r13)
|
||||
#endif
|
||||
uint32 RAMBase; // Base address of Mac RAM
|
||||
uint32 RAMSize; // Size of Mac RAM
|
||||
uint32 SheepStack1Base; // SheepShaver first alternate stack base
|
||||
uint32 SheepStack2Base; // SheepShaver second alternate stack base
|
||||
uint32 SheepThunksBase; // SheepShaver thunks base
|
||||
uint32 KernelDataAddr; // Address of Kernel Data
|
||||
uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
|
||||
uint32 PVR; // Theoretical PVR
|
||||
@ -203,11 +187,11 @@ static char *x_display_name = NULL; // X11 display name
|
||||
Display *x_display = NULL; // X11 display handle
|
||||
|
||||
static int zero_fd = 0; // FD of /dev/zero
|
||||
static bool sheep_area_mapped = false; // Flag: SheepShaver data area mmap()ed
|
||||
static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
|
||||
static int kernel_area = -1; // SHM ID of Kernel Data area
|
||||
static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped
|
||||
static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped
|
||||
static void *mmap_RAMBase = NULL; // Base address of mmap()ed RAM area
|
||||
static KernelData *kernel_data; // Pointer to Kernel Data
|
||||
static EmulatorData *emulator_data;
|
||||
|
||||
@ -238,7 +222,9 @@ static void Quit(void);
|
||||
static void *emul_func(void *arg);
|
||||
static void *nvram_func(void *arg);
|
||||
static void *tick_func(void *arg);
|
||||
#if !EMULATED_PPC
|
||||
#if EMULATED_PPC
|
||||
static void sigusr2_handler(int sig);
|
||||
#else
|
||||
static void sigusr2_handler(int sig, sigcontext_struct *sc);
|
||||
static void sigsegv_handler(int sig, sigcontext_struct *sc);
|
||||
static void sigill_handler(int sig, sigcontext_struct *sc);
|
||||
@ -293,7 +279,6 @@ int main(int argc, char **argv)
|
||||
|
||||
// Initialize variables
|
||||
RAMBase = 0;
|
||||
mmap_RAMBase = NULL;
|
||||
tzset();
|
||||
|
||||
// Print some info
|
||||
@ -451,6 +436,17 @@ int main(int argc, char **argv)
|
||||
KernelDataAddr = (uint32)kernel_data;
|
||||
D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
|
||||
|
||||
// Create area for SheepShaver data
|
||||
if (vm_acquire_fixed((char *)SHEEP_BASE, SHEEP_SIZE) < 0) {
|
||||
sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
SheepStack1Base = SHEEP_BASE + 0x10000;
|
||||
SheepStack2Base = SheepStack1Base + 0x10000;
|
||||
SheepThunksBase = SheepStack2Base + 0x1000;
|
||||
sheep_area_mapped = true;
|
||||
|
||||
// Create area for Mac ROM
|
||||
if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
|
||||
sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
|
||||
@ -474,20 +470,19 @@ int main(int argc, char **argv)
|
||||
RAMSize = 8*1024*1024;
|
||||
}
|
||||
|
||||
mmap_RAMBase = (void *)0x20000000;
|
||||
if (vm_acquire_fixed(mmap_RAMBase, RAMSize) < 0) {
|
||||
if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) {
|
||||
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
#if !EMULATED_PPC
|
||||
if (vm_protect(mmap_RAMBase, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
|
||||
if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
|
||||
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
#endif
|
||||
RAMBase = (uint32)mmap_RAMBase;
|
||||
RAMBase = RAM_BASE;
|
||||
ram_area_mapped = true;
|
||||
D(bug("RAM area at %08x\n", RAMBase));
|
||||
|
||||
@ -717,18 +712,19 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !EMULATED_PPC
|
||||
// Install interrupt signal handler
|
||||
sigemptyset(&sigusr2_action.sa_mask);
|
||||
sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
|
||||
sigusr2_action.sa_flags = 0;
|
||||
#if !EMULATED_PPC
|
||||
sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
|
||||
#endif
|
||||
sigusr2_action.sa_restorer = NULL;
|
||||
if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
|
||||
sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
|
||||
ErrorAlert(str);
|
||||
goto quit;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get my thread ID and execute MacOS thread function
|
||||
emul_thread = pthread_self();
|
||||
@ -805,7 +801,7 @@ static void Quit(void)
|
||||
|
||||
// Delete RAM area
|
||||
if (ram_area_mapped)
|
||||
vm_release(mmap_RAMBase, RAMSize);
|
||||
vm_release((char *)RAM_BASE, RAMSize);
|
||||
|
||||
// Delete ROM area
|
||||
if (rom_area_mapped)
|
||||
@ -1199,7 +1195,7 @@ void B2_delete_mutex(B2_mutex *mutex)
|
||||
* Trigger signal USR2 from another thread
|
||||
*/
|
||||
|
||||
#if !EMULATED_PPC
|
||||
#if !EMULATED_PPC || ASYNC_IRQ
|
||||
void TriggerInterrupt(void)
|
||||
{
|
||||
if (ready_for_signals)
|
||||
@ -1245,11 +1241,19 @@ void EnableInterrupt(void)
|
||||
}
|
||||
|
||||
|
||||
#if !EMULATED_PPC
|
||||
/*
|
||||
* USR2 handler
|
||||
*/
|
||||
|
||||
#if EMULATED_PPC
|
||||
static void sigusr2_handler(int sig)
|
||||
{
|
||||
#if ASYNC_IRQ
|
||||
extern void HandleInterrupt(void);
|
||||
HandleInterrupt();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void sigusr2_handler(int sig, sigcontext_struct *sc)
|
||||
{
|
||||
pt_regs *r = sc->regs;
|
||||
@ -1331,15 +1335,16 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* SIGSEGV handler
|
||||
*/
|
||||
|
||||
#if !EMULATED_PPC
|
||||
static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
||||
{
|
||||
pt_regs *r = sc->regs;
|
||||
|
@ -68,6 +68,8 @@
|
||||
#define POWERPC_ROM 1
|
||||
|
||||
#if EMULATED_PPC
|
||||
// Handle interrupts asynchronously?
|
||||
#define ASYNC_IRQ 0
|
||||
// Mac ROM is write protected when banked memory is used
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
# define ROM_IS_WRITE_PROTECTED 0
|
||||
|
@ -38,6 +38,7 @@ user_string_def platform_strings[] = {
|
||||
{STR_KD2_SHMAT_ERR, "Cannot map second Kernel Data area: %s."},
|
||||
{STR_ROM_MMAP_ERR, "Cannot map ROM: %s."},
|
||||
{STR_RAM_MMAP_ERR, "Cannot map RAM: %s."},
|
||||
{STR_SHEEP_MEM_MMAP_ERR, "Cannot map SheepShaver Data area: %s."},
|
||||
{STR_SIGALTSTACK_ERR, "Cannot install alternate signal stack (%s). It seems that you need a newer kernel."},
|
||||
{STR_SIGSEGV_INSTALL_ERR, "Cannot install SIGSEGV handler: %s."},
|
||||
{STR_SIGILL_INSTALL_ERR, "Cannot install SIGILL handler: %s."},
|
||||
|
@ -29,6 +29,7 @@ enum {
|
||||
STR_KD2_SHMAT_ERR,
|
||||
STR_ROM_MMAP_ERR,
|
||||
STR_RAM_MMAP_ERR,
|
||||
STR_SHEEP_MEM_MMAP_ERR,
|
||||
STR_SIGALTSTACK_ERR,
|
||||
STR_SIGSEGV_INSTALL_ERR,
|
||||
STR_SIGILL_INSTALL_ERR,
|
||||
|
@ -29,12 +29,34 @@
|
||||
// Constants
|
||||
const uint32 ROM_BASE = 0x40800000; // Base address of ROM
|
||||
const uint32 ROM_SIZE = 0x00400000; // Size of ROM file
|
||||
const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area
|
||||
const uint32 ROM_END = ROM_BASE + ROM_SIZE; // End of ROM
|
||||
const uint32 DR_CACHE_BASE = 0x69000000; // Address of DR cache
|
||||
const uint32 DR_CACHE_SIZE = 0x80000; // Size of DR Cache
|
||||
const uint32 SHEEP_BASE = 0x60000000; // Address of SheepShaver data
|
||||
const uint32 SHEEP_SIZE = 0x40000; // Size of SheepShaver data
|
||||
|
||||
const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data
|
||||
const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data
|
||||
const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area
|
||||
|
||||
// MacOS 68k Emulator Data
|
||||
struct EmulatorData {
|
||||
uint32 v[0x400];
|
||||
};
|
||||
|
||||
// MacOS Kernel Data
|
||||
struct KernelData {
|
||||
uint32 v[0x400];
|
||||
EmulatorData ed;
|
||||
};
|
||||
|
||||
// RAM and ROM pointers (allocated and set by main_*.cpp)
|
||||
extern uint32 RAMBase; // Base address of Mac RAM
|
||||
extern uint32 RAMSize; // Size address of Mac RAM
|
||||
extern uint32 SheepStack1Base; // SheepShaver first alternate stack base
|
||||
extern uint32 SheepStack2Base; // SheepShaver second alternate stack base
|
||||
extern uint32 SheepThunksBase; // SheepShaver thunks base
|
||||
|
||||
// Mac memory access functions
|
||||
static inline uint32 ReadMacInt8(uint32 addr) {return *(uint8 *)addr;}
|
||||
|
@ -69,6 +69,9 @@ enum {
|
||||
extern volatile uint32 InterruptFlags; // Currently pending interrupts
|
||||
extern void SetInterruptFlag(uint32);
|
||||
extern void ClearInterruptFlag(uint32);
|
||||
#if EMULATED_PPC
|
||||
extern void HandleInterrupt(void); // Handle SIGUSR1 interrupt in emulator thread
|
||||
#endif
|
||||
extern void TriggerInterrupt(void); // Trigger SIGUSR1 interrupt in emulator thread
|
||||
extern void DisableInterrupt(void); // Disable SIGUSR1 interrupt (can be nested)
|
||||
extern void EnableInterrupt(void); // Enable SIGUSR1 interrupt (can be nested)
|
||||
|
@ -71,19 +71,8 @@ static void enter_mon(void)
|
||||
// Interrupts in native mode?
|
||||
#define INTERRUPTS_IN_NATIVE_MODE 1
|
||||
|
||||
// 68k Emulator Data
|
||||
struct EmulatorData {
|
||||
uint32 v[0x400];
|
||||
};
|
||||
|
||||
// Kernel Data
|
||||
struct KernelData {
|
||||
uint32 v[0x400];
|
||||
EmulatorData ed;
|
||||
};
|
||||
|
||||
// Pointer to Kernel Data
|
||||
static KernelData * const kernel_data = (KernelData *)0x68ffe000;
|
||||
static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE;
|
||||
|
||||
|
||||
/**
|
||||
@ -124,7 +113,7 @@ public:
|
||||
void get_resource(uint32 old_get_resource);
|
||||
|
||||
// Handle MacOS interrupt
|
||||
void interrupt(uint32 entry, sheepshaver_cpu *cpu);
|
||||
void interrupt(uint32 entry);
|
||||
|
||||
// spcflags for interrupts handling
|
||||
static uint32 spcflags;
|
||||
@ -232,10 +221,9 @@ struct execute_nothing {
|
||||
static inline void execute(powerpc_cpu *) { }
|
||||
};
|
||||
|
||||
static void HandleInterrupt(void);
|
||||
|
||||
struct execute_spcflags_check {
|
||||
static inline void execute(powerpc_cpu *cpu) {
|
||||
#if !ASYNC_IRQ
|
||||
if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
|
||||
if (SPCFLAGS_TEST( SPCFLAG_ENTER_MON )) {
|
||||
SPCFLAGS_CLEAR( SPCFLAG_ENTER_MON );
|
||||
@ -250,6 +238,7 @@ struct execute_spcflags_check {
|
||||
SPCFLAGS_SET( SPCFLAG_DOINT );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@ -270,20 +259,18 @@ void sheepshaver_cpu::execute(uint32 entry)
|
||||
}
|
||||
|
||||
// Handle MacOS interrupt
|
||||
void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu)
|
||||
void sheepshaver_cpu::interrupt(uint32 entry)
|
||||
{
|
||||
#if MULTICORE_CPU
|
||||
// Initialize stack pointer from previous CPU running
|
||||
gpr(1) = cpu->gpr(1);
|
||||
#else
|
||||
#if !MULTICORE_CPU
|
||||
// Save program counters and branch registers
|
||||
uint32 saved_pc = pc();
|
||||
uint32 saved_lr = lr();
|
||||
uint32 saved_ctr= ctr();
|
||||
uint32 saved_sp = gpr(1);
|
||||
#endif
|
||||
|
||||
// Create stack frame
|
||||
gpr(1) -= 64;
|
||||
// Initialize stack pointer to SheepShaver alternate stack base
|
||||
gpr(1) = SheepStack1Base - 64;
|
||||
|
||||
// Build trampoline to return from interrupt
|
||||
uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
|
||||
@ -320,14 +307,12 @@ void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu)
|
||||
// Enter nanokernel
|
||||
execute(entry);
|
||||
|
||||
// Cleanup stack
|
||||
gpr(1) += 64;
|
||||
|
||||
#if !MULTICORE_CPU
|
||||
// Restore program counters and branch registers
|
||||
pc() = saved_pc;
|
||||
lr() = saved_lr;
|
||||
ctr()= saved_ctr;
|
||||
gpr(1) = saved_sp;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -585,7 +570,7 @@ void init_emul_ppc(void)
|
||||
|
||||
// Install the handler for SIGSEGV
|
||||
sigsegv_install_handler(sigsegv_handler);
|
||||
|
||||
|
||||
#if ENABLE_MON
|
||||
// Install "regs" command in cxmon
|
||||
mon_add_command("regs", dump_registers, "regs Dump PowerPC registers\n");
|
||||
@ -613,6 +598,7 @@ extern int atomic_add(int *var, int v);
|
||||
extern int atomic_and(int *var, int v);
|
||||
extern int atomic_or(int *var, int v);
|
||||
|
||||
#if !ASYNC_IRQ
|
||||
void TriggerInterrupt(void)
|
||||
{
|
||||
#if 0
|
||||
@ -621,8 +607,9 @@ void TriggerInterrupt(void)
|
||||
SPCFLAGS_SET( SPCFLAG_INT );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void HandleInterrupt(void)
|
||||
void HandleInterrupt(void)
|
||||
{
|
||||
// Do nothing if interrupts are disabled
|
||||
if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
|
||||
@ -659,9 +646,9 @@ static void HandleInterrupt(void)
|
||||
DisableInterrupt();
|
||||
cpu_push(interrupt_cpu);
|
||||
if (ROMType == ROMTYPE_NEWWORLD)
|
||||
current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu);
|
||||
current_cpu->interrupt(ROM_BASE + 0x312b1c);
|
||||
else
|
||||
current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu);
|
||||
current_cpu->interrupt(ROM_BASE + 0x312a3c);
|
||||
cpu_pop();
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user