From 7f13ce6fed322f150d1bce91bbc91c306bc8e2b5 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 18 Jan 2004 22:14:31 +0000 Subject: [PATCH] Wrappers around machine state registers within signal handlers. --- SheepShaver/src/Unix/main_unix.cpp | 262 ++++++++++++++++++----------- 1 file changed, 160 insertions(+), 102 deletions(-) diff --git a/SheepShaver/src/Unix/main_unix.cpp b/SheepShaver/src/Unix/main_unix.cpp index 17a9f29e..832d0357 100644 --- a/SheepShaver/src/Unix/main_unix.cpp +++ b/SheepShaver/src/Unix/main_unix.cpp @@ -154,19 +154,70 @@ const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack #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 - struct sigregs { - elf_gregset_t gp_regs; // Identical to pt_regs - double fp_regs[ELF_NFPREG]; // f0..f31 and fpsrc - //more (uninteresting) stuff following here + uint32 nip; + uint32 link; + 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 +#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 +#define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext)) + +#include +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 @@ -238,9 +289,9 @@ extern void emul_ppc(uint32 start); extern void init_emul_ppc(void); extern void exit_emul_ppc(void); #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); +static void sigusr2_handler(int sig, siginfo_t *sip, void *scp); +static void sigsegv_handler(int sig, siginfo_t *sip, void *scp); +static void sigill_handler(int sig, siginfo_t *sip, void *scp); #endif @@ -465,6 +516,7 @@ int main(int argc, char **argv) goto quit; } +#ifndef PAGEZERO_HACK // Create Low Memory area (0x0000..0x3000) if (vm_acquire_fixed((char *)0, 0x3000) < 0) { sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); @@ -472,6 +524,7 @@ int main(int argc, char **argv) goto quit; } lm_area_mapped = true; +#endif // Create areas for Kernel Data kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600); @@ -746,9 +799,11 @@ int main(int argc, char **argv) // Install SIGSEGV and SIGBUS handlers sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling sigaddset(&sigsegv_action.sa_mask, SIGUSR2); - sigsegv_action.sa_handler = (__sighandler_t)sigsegv_handler; - sigsegv_action.sa_flags = SA_ONSTACK; + sigsegv_action.sa_sigaction = sigsegv_handler; + sigsegv_action.sa_flags = SA_ONSTACK | SA_SIGINFO; +#ifdef HAVE_SIGNAL_SA_RESTORER sigsegv_action.sa_restorer = NULL; +#endif if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) { sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno)); ErrorAlert(str); @@ -763,9 +818,11 @@ int main(int argc, char **argv) // Install SIGILL handler sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling sigaddset(&sigill_action.sa_mask, SIGUSR2); - sigill_action.sa_handler = (__sighandler_t)sigill_handler; - sigill_action.sa_flags = SA_ONSTACK; + sigill_action.sa_sigaction = sigill_handler; + sigill_action.sa_flags = SA_ONSTACK | SA_SIGINFO; +#ifdef HAVE_SIGNAL_SA_RESTORER sigill_action.sa_restorer = NULL; +#endif if (sigaction(SIGILL, &sigill_action, NULL) < 0) { sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno)); ErrorAlert(str); @@ -773,19 +830,20 @@ 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_sigaction = sigusr2_handler; + sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; +#ifdef HAVE_SIGNAL_SA_RESTORER sigusr2_action.sa_restorer = NULL; +#endif 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(); @@ -1109,7 +1167,7 @@ static void *tick_func(void *arg) if (emul_thread_fatal) { // Yes, dump registers - pt_regs *r = (pt_regs *)&sigsegv_regs; + sigregs *r = &sigsegv_regs; char str[256]; if (crash_reason == NULL) crash_reason = "SIGSEGV"; @@ -1339,9 +1397,9 @@ static void sigusr2_handler(int sig) #endif } #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 if (*(int32 *)XLM_IRQ_NEST > 0) @@ -1355,13 +1413,13 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc) case MODE_68K: // 68k emulator active, trigger 68k interrupt level 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; #if INTERRUPTS_IN_NATIVE_MODE case MODE_NATIVE: // 68k emulator inactive, in nanokernel? - if (r->gpr[1] != KernelDataAddr) { + if (r->gpr(1) != KernelDataAddr) { // Prepare for 68k interrupt level 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])); @@ -1430,55 +1488,55 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc) */ #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 - uint32 addr = r->dar; + uint32 addr = r->dar(); #if ENABLE_VOSF // Handle screen fault. 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; #endif num_segv++; // 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) { // "VM settings" during MacOS 8 installation - if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) { - r->nip += 4; - r->gpr[8] = 0; + if (r->pc() == ROM_BASE + 0x488160 && r->gpr(20) == 0xf8000000) { + r->pc() += 4; + r->gpr(8) = 0; return; // MacOS 8.5 installation - } else if (r->nip == ROM_BASE + 0x488140 && r->gpr[16] == 0xf8000000) { - r->nip += 4; - r->gpr[8] = 0; + } else if (r->pc() == ROM_BASE + 0x488140 && r->gpr(16) == 0xf8000000) { + r->pc() += 4; + r->gpr(8) = 0; return; // MacOS 8 serial drivers on startup - } else if (r->nip == ROM_BASE + 0x48e080 && (r->gpr[8] == 0xf3012002 || r->gpr[8] == 0xf3012000)) { - r->nip += 4; - r->gpr[8] = 0; + } else if (r->pc() == ROM_BASE + 0x48e080 && (r->gpr(8) == 0xf3012002 || r->gpr(8) == 0xf3012000)) { + r->pc() += 4; + r->gpr(8) = 0; return; // MacOS 8.1 serial drivers on startup - } else if (r->nip == ROM_BASE + 0x48c5e0 && (r->gpr[20] == 0xf3012002 || r->gpr[20] == 0xf3012000)) { - r->nip += 4; + } else if (r->pc() == ROM_BASE + 0x48c5e0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) { + r->pc() += 4; return; - } else if (r->nip == ROM_BASE + 0x4a10a0 && (r->gpr[20] == 0xf3012002 || r->gpr[20] == 0xf3012000)) { - r->nip += 4; + } else if (r->pc() == ROM_BASE + 0x4a10a0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) { + r->pc() += 4; return; } // Get opcode and divide into fields - uint32 opcode = *((uint32 *)r->nip); + uint32 opcode = *((uint32 *)r->pc()); uint32 primop = opcode >> 26; uint32 exop = (opcode >> 1) & 0x3ff; uint32 ra = (opcode >> 16) & 0x1f; @@ -1570,25 +1628,25 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc) #if EMULATE_UNALIGNED_LOADSTORE_MULTIPLE case 46: // lmw if (sig == SIGBUS) { - uint32 ea = (ra == 0 ? 0 : r->gpr[ra]) + imm; - D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->nip)); + uint32 ea = (ra == 0 ? 0 : r->gpr(ra)) + imm; + D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->pc())); for (int i = rd; i <= 31; i++) { - r->gpr[i] = ReadMacInt32(ea); + r->gpr(i) = ReadMacInt32(ea); ea += 4; } - r->nip += 4; + r->pc() += 4; goto rti; } break; case 47: // stmw if (sig == SIGBUS) { - uint32 ea = (ra == 0 ? 0 : r->gpr[ra]) + imm; - D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->nip)); + uint32 ea = (ra == 0 ? 0 : r->gpr(ra)) + imm; + D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->pc())); for (int i = rd; i <= 31; i++) { - WriteMacInt32(ea, r->gpr[i]); + WriteMacInt32(ea, r->gpr(i)); ea += 4; } - r->nip += 4; + r->pc() += 4; goto rti; } break; @@ -1597,20 +1655,20 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc) // Ignore ROM writes 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) - r->gpr[ra] = addr; - r->nip += 4; + r->gpr(ra) = addr; + r->pc() += 4; goto rti; } // Ignore illegal memory accesses? if (PrefsFindBool("ignoresegv")) { if (addr_mode == MODE_U || addr_mode == MODE_UX) - r->gpr[ra] = addr; + r->gpr(ra) = addr; if (transfer_type == TYPE_LOAD) - r->gpr[rd] = 0; - r->nip += 4; + r->gpr(rd) = 0; + r->pc() += 4; goto rti; } @@ -1618,9 +1676,9 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc) if (!PrefsFindBool("nogui")) { char str[256]; 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 - 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); QuitEmulator(); return; @@ -1631,7 +1689,7 @@ static void sigsegv_handler(int sig, sigcontext_struct *sc) crash_reason = (sig == SIGBUS) ? "SIGBUS" : "SIGSEGV"; if (!ready_for_signals) { printf("%s\n"); - printf(" sigcontext %p, pt_regs %p\n", sc, r); + printf(" sigcontext %p, machine_regs %p\n", scp, r); printf( " pc %08lx lr %08lx ctr %08lx msr %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" " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", crash_reason, - r->nip, r->link, r->ctr, r->msr, - r->xer, r->ccr, - 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[8], r->gpr[9], r->gpr[10], r->gpr[11], - 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[20], r->gpr[21], r->gpr[22], r->gpr[23], - 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->pc(), r->lr(), r->ctr(), r->msr(), + r->xer(), r->cr(), + 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(8), r->gpr(9), r->gpr(10), r->gpr(11), + 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(20), r->gpr(21), r->gpr(22), r->gpr(23), + r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27), + r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31)); exit(1); QuitEmulator(); return; } else { // We crashed. Save registers, tell tick thread and loop forever - sigsegv_regs = *(sigregs *)r; + build_sigregs(&sigsegv_regs, r); emul_thread_fatal = true; for (;;) ; } @@ -1671,17 +1729,17 @@ rti:; * 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]; // 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) { // Get opcode and divide into fields - uint32 opcode = *((uint32 *)r->nip); + uint32 opcode = *((uint32 *)r->pc()); uint32 primop = opcode >> 26; uint32 exop = (opcode >> 1) & 0x3ff; uint32 ra = (opcode >> 16) & 0x1f; @@ -1692,7 +1750,7 @@ static void sigill_handler(int sig, sigcontext_struct *sc) switch (primop) { case 9: // POWER instructions 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); QuitEmulator(); return; @@ -1700,14 +1758,14 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1 case 31: switch (exop) { case 83: // mfmsr - r->gpr[rd] = 0xf072; - r->nip += 4; + r->gpr(rd) = 0xf072; + r->pc() += 4; goto rti; case 210: // mtsr case 242: // mtsrin case 306: // tlbie - r->nip += 4; + r->pc() += 4; goto rti; 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 958: // PMC4 case 959: // SDA - r->nip += 4; + r->pc() += 4; goto rti; case 25: // SDR1 - r->gpr[rd] = 0xdead001f; - r->nip += 4; + r->gpr(rd) = 0xdead001f; + r->pc() += 4; goto rti; case 287: // PVR - r->gpr[rd] = PVR; - r->nip += 4; + r->gpr(rd) = PVR; + r->pc() += 4; goto rti; } break; @@ -1767,7 +1825,7 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1 case 957: // PMC3 case 958: // PMC4 case 959: // SDA - r->nip += 4; + r->pc() += 4; goto rti; } 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 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); QuitEmulator(); return; @@ -1797,7 +1855,7 @@ power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1 crash_reason = "SIGILL"; if (!ready_for_signals) { printf("%s\n"); - printf(" sigcontext %p, pt_regs %p\n", sc, r); + printf(" sigcontext %p, machine_regs %p\n", scp, r); printf( " pc %08lx lr %08lx ctr %08lx msr %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" " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", crash_reason, - r->nip, r->link, r->ctr, r->msr, - r->xer, r->ccr, - 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[8], r->gpr[9], r->gpr[10], r->gpr[11], - 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[20], r->gpr[21], r->gpr[22], r->gpr[23], - 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->pc(), r->lr(), r->ctr(), r->msr(), + r->xer(), r->cr(), + 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(8), r->gpr(9), r->gpr(10), r->gpr(11), + 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(20), r->gpr(21), r->gpr(22), r->gpr(23), + r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27), + r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31)); exit(1); QuitEmulator(); return; } else { // We crashed. Save registers, tell tick thread and loop forever - sigsegv_regs = *(sigregs *)r; + build_sigregs(&sigsegv_regs, r); emul_thread_fatal = true; for (;;) ; }