- 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:
gbeauche 2003-09-29 15:46:09 +00:00
parent ddcfbe2bda
commit b8b139faf2
8 changed files with 83 additions and 81 deletions

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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."},

View File

@ -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,

View File

@ -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;}

View File

@ -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)

View File

@ -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;