mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-08-15 11:27:35 +00:00
Wrappers around machine state registers within signal handlers.
This commit is contained in:
@@ -154,19 +154,70 @@ const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
|
|||||||
|
|
||||||
|
|
||||||
#if !EMULATED_PPC
|
#if !EMULATED_PPC
|
||||||
// Structure in which registers are saved in a signal handler;
|
|
||||||
// sigcontext->regs points to it
|
|
||||||
// (see arch/ppc/kernel/signal.c)
|
|
||||||
typedef struct {
|
|
||||||
uint32 u[4];
|
|
||||||
} __attribute((aligned(16))) vector128;
|
|
||||||
#include <linux/elf.h>
|
|
||||||
|
|
||||||
struct sigregs {
|
struct sigregs {
|
||||||
elf_gregset_t gp_regs; // Identical to pt_regs
|
uint32 nip;
|
||||||
double fp_regs[ELF_NFPREG]; // f0..f31 and fpsrc
|
uint32 link;
|
||||||
//more (uninteresting) stuff following here
|
uint32 ctr;
|
||||||
|
uint32 msr;
|
||||||
|
uint32 xer;
|
||||||
|
uint32 ccr;
|
||||||
|
uint32 gpr[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
struct machine_regs : public pt_regs
|
||||||
|
{
|
||||||
|
u_long & cr() { return pt_regs::ccr; }
|
||||||
|
uint32 cr() const { return pt_regs::ccr; }
|
||||||
|
uint32 lr() const { return pt_regs::link; }
|
||||||
|
uint32 ctr() const { return pt_regs::ctr; }
|
||||||
|
uint32 xer() const { return pt_regs::xer; }
|
||||||
|
uint32 msr() const { return pt_regs::msr; }
|
||||||
|
uint32 dar() const { return pt_regs::dar; }
|
||||||
|
u_long & pc() { return pt_regs::nip; }
|
||||||
|
uint32 pc() const { return pt_regs::nip; }
|
||||||
|
u_long & gpr(int i) { return pt_regs::gpr[i]; }
|
||||||
|
uint32 gpr(int i) const { return pt_regs::gpr[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
#define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext.regs))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
|
struct machine_regs : public mcontext
|
||||||
|
{
|
||||||
|
uint32 & cr() { return ss.cr; }
|
||||||
|
uint32 cr() const { return ss.cr; }
|
||||||
|
uint32 lr() const { return ss.lr; }
|
||||||
|
uint32 ctr() const { return ss.ctr; }
|
||||||
|
uint32 xer() const { return ss.xer; }
|
||||||
|
uint32 msr() const { return ss.srr1; }
|
||||||
|
uint32 dar() const { return es.dar; }
|
||||||
|
uint32 & pc() { return ss.srr0; }
|
||||||
|
uint32 pc() const { return ss.srr0; }
|
||||||
|
uint32 & gpr(int i) { return (&ss.r0)[i]; }
|
||||||
|
uint32 gpr(int i) const { return (&ss.r0)[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
#define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext))
|
||||||
|
|
||||||
|
#include <sys/signal.h>
|
||||||
|
extern "C" int sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void build_sigregs(sigregs *srp, machine_regs *mrp)
|
||||||
|
{
|
||||||
|
srp->nip = mrp->pc();
|
||||||
|
srp->link = mrp->lr();
|
||||||
|
srp->ctr = mrp->ctr();
|
||||||
|
srp->msr = mrp->msr();
|
||||||
|
srp->xer = mrp->xer();
|
||||||
|
srp->ccr = mrp->cr();
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
srp->gpr[i] = mrp->gpr(i);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -238,9 +289,9 @@ extern void emul_ppc(uint32 start);
|
|||||||
extern void init_emul_ppc(void);
|
extern void init_emul_ppc(void);
|
||||||
extern void exit_emul_ppc(void);
|
extern void exit_emul_ppc(void);
|
||||||
#else
|
#else
|
||||||
static void sigusr2_handler(int sig, sigcontext_struct *sc);
|
static void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
|
||||||
static void sigsegv_handler(int sig, sigcontext_struct *sc);
|
static void sigsegv_handler(int sig, siginfo_t *sip, void *scp);
|
||||||
static void sigill_handler(int sig, sigcontext_struct *sc);
|
static void sigill_handler(int sig, siginfo_t *sip, void *scp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -465,6 +516,7 @@ int main(int argc, char **argv)
|
|||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef PAGEZERO_HACK
|
||||||
// Create Low Memory area (0x0000..0x3000)
|
// Create Low Memory area (0x0000..0x3000)
|
||||||
if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
|
if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
|
||||||
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
|
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
|
||||||
@@ -472,6 +524,7 @@ int main(int argc, char **argv)
|
|||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
lm_area_mapped = true;
|
lm_area_mapped = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create areas for Kernel Data
|
// Create areas for Kernel Data
|
||||||
kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600);
|
kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600);
|
||||||
@@ -746,9 +799,11 @@ int main(int argc, char **argv)
|
|||||||
// Install SIGSEGV and SIGBUS handlers
|
// Install SIGSEGV and SIGBUS handlers
|
||||||
sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling
|
sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling
|
||||||
sigaddset(&sigsegv_action.sa_mask, SIGUSR2);
|
sigaddset(&sigsegv_action.sa_mask, SIGUSR2);
|
||||||
sigsegv_action.sa_handler = (__sighandler_t)sigsegv_handler;
|
sigsegv_action.sa_sigaction = sigsegv_handler;
|
||||||
sigsegv_action.sa_flags = SA_ONSTACK;
|
sigsegv_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
||||||
|
#ifdef HAVE_SIGNAL_SA_RESTORER
|
||||||
sigsegv_action.sa_restorer = NULL;
|
sigsegv_action.sa_restorer = NULL;
|
||||||
|
#endif
|
||||||
if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
|
if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
|
||||||
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
|
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
|
||||||
ErrorAlert(str);
|
ErrorAlert(str);
|
||||||
@@ -763,9 +818,11 @@ int main(int argc, char **argv)
|
|||||||
// Install SIGILL handler
|
// Install SIGILL handler
|
||||||
sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling
|
sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling
|
||||||
sigaddset(&sigill_action.sa_mask, SIGUSR2);
|
sigaddset(&sigill_action.sa_mask, SIGUSR2);
|
||||||
sigill_action.sa_handler = (__sighandler_t)sigill_handler;
|
sigill_action.sa_sigaction = sigill_handler;
|
||||||
sigill_action.sa_flags = SA_ONSTACK;
|
sigill_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
||||||
|
#ifdef HAVE_SIGNAL_SA_RESTORER
|
||||||
sigill_action.sa_restorer = NULL;
|
sigill_action.sa_restorer = NULL;
|
||||||
|
#endif
|
||||||
if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
|
if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
|
||||||
sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno));
|
sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno));
|
||||||
ErrorAlert(str);
|
ErrorAlert(str);
|
||||||
@@ -773,19 +830,20 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !EMULATED_PPC
|
||||||
// Install interrupt signal handler
|
// Install interrupt signal handler
|
||||||
sigemptyset(&sigusr2_action.sa_mask);
|
sigemptyset(&sigusr2_action.sa_mask);
|
||||||
sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
|
sigusr2_action.sa_sigaction = sigusr2_handler;
|
||||||
sigusr2_action.sa_flags = 0;
|
sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
|
||||||
#if !EMULATED_PPC
|
#ifdef HAVE_SIGNAL_SA_RESTORER
|
||||||
sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
|
|
||||||
#endif
|
|
||||||
sigusr2_action.sa_restorer = NULL;
|
sigusr2_action.sa_restorer = NULL;
|
||||||
|
#endif
|
||||||
if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
|
if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
|
||||||
sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
|
sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
|
||||||
ErrorAlert(str);
|
ErrorAlert(str);
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get my thread ID and execute MacOS thread function
|
// Get my thread ID and execute MacOS thread function
|
||||||
emul_thread = pthread_self();
|
emul_thread = pthread_self();
|
||||||
@@ -1109,7 +1167,7 @@ static void *tick_func(void *arg)
|
|||||||
if (emul_thread_fatal) {
|
if (emul_thread_fatal) {
|
||||||
|
|
||||||
// Yes, dump registers
|
// Yes, dump registers
|
||||||
pt_regs *r = (pt_regs *)&sigsegv_regs;
|
sigregs *r = &sigsegv_regs;
|
||||||
char str[256];
|
char str[256];
|
||||||
if (crash_reason == NULL)
|
if (crash_reason == NULL)
|
||||||
crash_reason = "SIGSEGV";
|
crash_reason = "SIGSEGV";
|
||||||
@@ -1339,9 +1397,9 @@ static void sigusr2_handler(int sig)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void sigusr2_handler(int sig, sigcontext_struct *sc)
|
static void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
|
||||||
{
|
{
|
||||||
pt_regs *r = sc->regs;
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
||||||
|
|
||||||
// Do nothing if interrupts are disabled
|
// Do nothing if interrupts are disabled
|
||||||
if (*(int32 *)XLM_IRQ_NEST > 0)
|
if (*(int32 *)XLM_IRQ_NEST > 0)
|
||||||
@@ -1355,13 +1413,13 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc)
|
|||||||
case MODE_68K:
|
case MODE_68K:
|
||||||
// 68k emulator active, trigger 68k interrupt level 1
|
// 68k emulator active, trigger 68k interrupt level 1
|
||||||
WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
|
WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
|
||||||
r->ccr |= ntohl(kernel_data->v[0x674 >> 2]);
|
r->cr() |= ntohl(kernel_data->v[0x674 >> 2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if INTERRUPTS_IN_NATIVE_MODE
|
#if INTERRUPTS_IN_NATIVE_MODE
|
||||||
case MODE_NATIVE:
|
case MODE_NATIVE:
|
||||||
// 68k emulator inactive, in nanokernel?
|
// 68k emulator inactive, in nanokernel?
|
||||||
if (r->gpr[1] != KernelDataAddr) {
|
if (r->gpr(1) != KernelDataAddr) {
|
||||||
// Prepare for 68k interrupt level 1
|
// Prepare for 68k interrupt level 1
|
||||||
WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
|
WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
|
||||||
WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2]));
|
WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2]));
|
||||||
@@ -1430,55 +1488,55 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if !EMULATED_PPC
|
#if !EMULATED_PPC
|
||||||
static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
static void sigsegv_handler(int sig, siginfo_t *sip, void *scp)
|
||||||
{
|
{
|
||||||
pt_regs *r = sc->regs;
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
||||||
|
|
||||||
// Get effective address
|
// Get effective address
|
||||||
uint32 addr = r->dar;
|
uint32 addr = r->dar();
|
||||||
|
|
||||||
#if ENABLE_VOSF
|
#if ENABLE_VOSF
|
||||||
// Handle screen fault.
|
// Handle screen fault.
|
||||||
extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
|
extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
|
||||||
if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->nip))
|
if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->pc()))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
num_segv++;
|
num_segv++;
|
||||||
|
|
||||||
// Fault in Mac ROM or RAM?
|
// Fault in Mac ROM or RAM?
|
||||||
bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
|
bool mac_fault = (r->pc() >= ROM_BASE) && (r->pc() < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
|
||||||
if (mac_fault) {
|
if (mac_fault) {
|
||||||
|
|
||||||
// "VM settings" during MacOS 8 installation
|
// "VM settings" during MacOS 8 installation
|
||||||
if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) {
|
if (r->pc() == ROM_BASE + 0x488160 && r->gpr(20) == 0xf8000000) {
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
r->gpr[8] = 0;
|
r->gpr(8) = 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// MacOS 8.5 installation
|
// MacOS 8.5 installation
|
||||||
} else if (r->nip == ROM_BASE + 0x488140 && r->gpr[16] == 0xf8000000) {
|
} else if (r->pc() == ROM_BASE + 0x488140 && r->gpr(16) == 0xf8000000) {
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
r->gpr[8] = 0;
|
r->gpr(8) = 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// MacOS 8 serial drivers on startup
|
// MacOS 8 serial drivers on startup
|
||||||
} else if (r->nip == ROM_BASE + 0x48e080 && (r->gpr[8] == 0xf3012002 || r->gpr[8] == 0xf3012000)) {
|
} else if (r->pc() == ROM_BASE + 0x48e080 && (r->gpr(8) == 0xf3012002 || r->gpr(8) == 0xf3012000)) {
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
r->gpr[8] = 0;
|
r->gpr(8) = 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// MacOS 8.1 serial drivers on startup
|
// MacOS 8.1 serial drivers on startup
|
||||||
} else if (r->nip == ROM_BASE + 0x48c5e0 && (r->gpr[20] == 0xf3012002 || r->gpr[20] == 0xf3012000)) {
|
} else if (r->pc() == ROM_BASE + 0x48c5e0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
return;
|
return;
|
||||||
} else if (r->nip == ROM_BASE + 0x4a10a0 && (r->gpr[20] == 0xf3012002 || r->gpr[20] == 0xf3012000)) {
|
} else if (r->pc() == ROM_BASE + 0x4a10a0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) {
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get opcode and divide into fields
|
// Get opcode and divide into fields
|
||||||
uint32 opcode = *((uint32 *)r->nip);
|
uint32 opcode = *((uint32 *)r->pc());
|
||||||
uint32 primop = opcode >> 26;
|
uint32 primop = opcode >> 26;
|
||||||
uint32 exop = (opcode >> 1) & 0x3ff;
|
uint32 exop = (opcode >> 1) & 0x3ff;
|
||||||
uint32 ra = (opcode >> 16) & 0x1f;
|
uint32 ra = (opcode >> 16) & 0x1f;
|
||||||
@@ -1570,25 +1628,25 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
|||||||
#if EMULATE_UNALIGNED_LOADSTORE_MULTIPLE
|
#if EMULATE_UNALIGNED_LOADSTORE_MULTIPLE
|
||||||
case 46: // lmw
|
case 46: // lmw
|
||||||
if (sig == SIGBUS) {
|
if (sig == SIGBUS) {
|
||||||
uint32 ea = (ra == 0 ? 0 : r->gpr[ra]) + imm;
|
uint32 ea = (ra == 0 ? 0 : r->gpr(ra)) + imm;
|
||||||
D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->nip));
|
D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->pc()));
|
||||||
for (int i = rd; i <= 31; i++) {
|
for (int i = rd; i <= 31; i++) {
|
||||||
r->gpr[i] = ReadMacInt32(ea);
|
r->gpr(i) = ReadMacInt32(ea);
|
||||||
ea += 4;
|
ea += 4;
|
||||||
}
|
}
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 47: // stmw
|
case 47: // stmw
|
||||||
if (sig == SIGBUS) {
|
if (sig == SIGBUS) {
|
||||||
uint32 ea = (ra == 0 ? 0 : r->gpr[ra]) + imm;
|
uint32 ea = (ra == 0 ? 0 : r->gpr(ra)) + imm;
|
||||||
D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->nip));
|
D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->pc()));
|
||||||
for (int i = rd; i <= 31; i++) {
|
for (int i = rd; i <= 31; i++) {
|
||||||
WriteMacInt32(ea, r->gpr[i]);
|
WriteMacInt32(ea, r->gpr(i));
|
||||||
ea += 4;
|
ea += 4;
|
||||||
}
|
}
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1597,20 +1655,20 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
|||||||
|
|
||||||
// Ignore ROM writes
|
// Ignore ROM writes
|
||||||
if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
|
if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
|
||||||
// D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->nip));
|
// D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc()));
|
||||||
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
||||||
r->gpr[ra] = addr;
|
r->gpr(ra) = addr;
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore illegal memory accesses?
|
// Ignore illegal memory accesses?
|
||||||
if (PrefsFindBool("ignoresegv")) {
|
if (PrefsFindBool("ignoresegv")) {
|
||||||
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
||||||
r->gpr[ra] = addr;
|
r->gpr(ra) = addr;
|
||||||
if (transfer_type == TYPE_LOAD)
|
if (transfer_type == TYPE_LOAD)
|
||||||
r->gpr[rd] = 0;
|
r->gpr(rd) = 0;
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1618,9 +1676,9 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
|||||||
if (!PrefsFindBool("nogui")) {
|
if (!PrefsFindBool("nogui")) {
|
||||||
char str[256];
|
char str[256];
|
||||||
if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE)
|
if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE)
|
||||||
sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->nip, r->gpr[24], r->gpr[1]);
|
sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->pc(), r->gpr(24), r->gpr(1));
|
||||||
else
|
else
|
||||||
sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->nip, r->gpr[24], r->gpr[1], opcode);
|
sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode);
|
||||||
ErrorAlert(str);
|
ErrorAlert(str);
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
return;
|
return;
|
||||||
@@ -1631,7 +1689,7 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
|||||||
crash_reason = (sig == SIGBUS) ? "SIGBUS" : "SIGSEGV";
|
crash_reason = (sig == SIGBUS) ? "SIGBUS" : "SIGSEGV";
|
||||||
if (!ready_for_signals) {
|
if (!ready_for_signals) {
|
||||||
printf("%s\n");
|
printf("%s\n");
|
||||||
printf(" sigcontext %p, pt_regs %p\n", sc, r);
|
printf(" sigcontext %p, machine_regs %p\n", scp, r);
|
||||||
printf(
|
printf(
|
||||||
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
||||||
" xer %08lx cr %08lx \n"
|
" xer %08lx cr %08lx \n"
|
||||||
@@ -1644,22 +1702,22 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc)
|
|||||||
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
||||||
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
||||||
crash_reason,
|
crash_reason,
|
||||||
r->nip, r->link, r->ctr, r->msr,
|
r->pc(), r->lr(), r->ctr(), r->msr(),
|
||||||
r->xer, r->ccr,
|
r->xer(), r->cr(),
|
||||||
r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
|
r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3),
|
||||||
r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
|
r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7),
|
||||||
r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
|
r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11),
|
||||||
r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
|
r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15),
|
||||||
r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
|
r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19),
|
||||||
r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
|
r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23),
|
||||||
r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
|
r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27),
|
||||||
r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
|
r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31));
|
||||||
exit(1);
|
exit(1);
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// We crashed. Save registers, tell tick thread and loop forever
|
// We crashed. Save registers, tell tick thread and loop forever
|
||||||
sigsegv_regs = *(sigregs *)r;
|
build_sigregs(&sigsegv_regs, r);
|
||||||
emul_thread_fatal = true;
|
emul_thread_fatal = true;
|
||||||
for (;;) ;
|
for (;;) ;
|
||||||
}
|
}
|
||||||
@@ -1671,17 +1729,17 @@ rti:;
|
|||||||
* SIGILL handler
|
* SIGILL handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void sigill_handler(int sig, sigcontext_struct *sc)
|
static void sigill_handler(int sig, siginfo_t *sip, void *scp)
|
||||||
{
|
{
|
||||||
pt_regs *r = sc->regs;
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
||||||
char str[256];
|
char str[256];
|
||||||
|
|
||||||
// Fault in Mac ROM or RAM?
|
// Fault in Mac ROM or RAM?
|
||||||
bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
|
bool mac_fault = (r->pc() >= ROM_BASE) && (r->pc() < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
|
||||||
if (mac_fault) {
|
if (mac_fault) {
|
||||||
|
|
||||||
// Get opcode and divide into fields
|
// Get opcode and divide into fields
|
||||||
uint32 opcode = *((uint32 *)r->nip);
|
uint32 opcode = *((uint32 *)r->pc());
|
||||||
uint32 primop = opcode >> 26;
|
uint32 primop = opcode >> 26;
|
||||||
uint32 exop = (opcode >> 1) & 0x3ff;
|
uint32 exop = (opcode >> 1) & 0x3ff;
|
||||||
uint32 ra = (opcode >> 16) & 0x1f;
|
uint32 ra = (opcode >> 16) & 0x1f;
|
||||||
@@ -1692,7 +1750,7 @@ static void sigill_handler(int sig, sigcontext_struct *sc)
|
|||||||
switch (primop) {
|
switch (primop) {
|
||||||
case 9: // POWER instructions
|
case 9: // POWER instructions
|
||||||
case 22:
|
case 22:
|
||||||
power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1], opcode);
|
power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->pc(), r->gpr(1), opcode);
|
||||||
ErrorAlert(str);
|
ErrorAlert(str);
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
return;
|
return;
|
||||||
@@ -1700,14 +1758,14 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1
|
|||||||
case 31:
|
case 31:
|
||||||
switch (exop) {
|
switch (exop) {
|
||||||
case 83: // mfmsr
|
case 83: // mfmsr
|
||||||
r->gpr[rd] = 0xf072;
|
r->gpr(rd) = 0xf072;
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
|
|
||||||
case 210: // mtsr
|
case 210: // mtsr
|
||||||
case 242: // mtsrin
|
case 242: // mtsrin
|
||||||
case 306: // tlbie
|
case 306: // tlbie
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
|
|
||||||
case 339: { // mfspr
|
case 339: { // mfspr
|
||||||
@@ -1723,15 +1781,15 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1
|
|||||||
case 957: // PMC3
|
case 957: // PMC3
|
||||||
case 958: // PMC4
|
case 958: // PMC4
|
||||||
case 959: // SDA
|
case 959: // SDA
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
case 25: // SDR1
|
case 25: // SDR1
|
||||||
r->gpr[rd] = 0xdead001f;
|
r->gpr(rd) = 0xdead001f;
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
case 287: // PVR
|
case 287: // PVR
|
||||||
r->gpr[rd] = PVR;
|
r->gpr(rd) = PVR;
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1767,7 +1825,7 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1
|
|||||||
case 957: // PMC3
|
case 957: // PMC3
|
||||||
case 958: // PMC4
|
case 958: // PMC4
|
||||||
case 959: // SDA
|
case 959: // SDA
|
||||||
r->nip += 4;
|
r->pc() += 4;
|
||||||
goto rti;
|
goto rti;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1786,7 +1844,7 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1
|
|||||||
|
|
||||||
// In GUI mode, show error alert
|
// In GUI mode, show error alert
|
||||||
if (!PrefsFindBool("nogui")) {
|
if (!PrefsFindBool("nogui")) {
|
||||||
sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->nip, r->gpr[24], r->gpr[1], opcode);
|
sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode);
|
||||||
ErrorAlert(str);
|
ErrorAlert(str);
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
return;
|
return;
|
||||||
@@ -1797,7 +1855,7 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1
|
|||||||
crash_reason = "SIGILL";
|
crash_reason = "SIGILL";
|
||||||
if (!ready_for_signals) {
|
if (!ready_for_signals) {
|
||||||
printf("%s\n");
|
printf("%s\n");
|
||||||
printf(" sigcontext %p, pt_regs %p\n", sc, r);
|
printf(" sigcontext %p, machine_regs %p\n", scp, r);
|
||||||
printf(
|
printf(
|
||||||
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
||||||
" xer %08lx cr %08lx \n"
|
" xer %08lx cr %08lx \n"
|
||||||
@@ -1810,22 +1868,22 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1
|
|||||||
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
||||||
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
||||||
crash_reason,
|
crash_reason,
|
||||||
r->nip, r->link, r->ctr, r->msr,
|
r->pc(), r->lr(), r->ctr(), r->msr(),
|
||||||
r->xer, r->ccr,
|
r->xer(), r->cr(),
|
||||||
r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
|
r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3),
|
||||||
r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
|
r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7),
|
||||||
r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
|
r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11),
|
||||||
r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
|
r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15),
|
||||||
r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
|
r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19),
|
||||||
r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
|
r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23),
|
||||||
r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
|
r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27),
|
||||||
r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
|
r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31));
|
||||||
exit(1);
|
exit(1);
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// We crashed. Save registers, tell tick thread and loop forever
|
// We crashed. Save registers, tell tick thread and loop forever
|
||||||
sigsegv_regs = *(sigregs *)r;
|
build_sigregs(&sigsegv_regs, r);
|
||||||
emul_thread_fatal = true;
|
emul_thread_fatal = true;
|
||||||
for (;;) ;
|
for (;;) ;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user