/*
* qemu user main
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
#define DEBUG_LOGFILE "/tmp/qemu.log"
+#ifdef __APPLE__
+#include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#endif
+
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
+const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
#if defined(__i386__) && !defined(CONFIG_STATIC)
/* Force usage of an ELF interpreter even if it is an ELF shared
/* for recent libc, we add these dummy symbols which are not declared
when generating a linked object (bug in ld ?) */
-#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
+#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
long __preinit_array_start[0];
long __preinit_array_end[0];
long __init_array_start[0];
return -1;
}
+/* timers for rdtsc */
+
+#if 0
+
+static uint64_t emu_time;
+
+int64_t cpu_get_real_ticks(void)
+{
+ return emu_time++;
+}
+
+#endif
+
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
-static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
+void cpu_smm_update(CPUState *env)
+{
+}
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+ return cpu_get_real_ticks();
+}
+
+static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
unsigned int e1, e2;
+ uint32_t *p;
e1 = (addr << 16) | (limit & 0xffff);
e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
e2 |= flags;
- stl((uint8_t *)ptr, e1);
- stl((uint8_t *)ptr + 4, e2);
+ p = ptr;
+ p[0] = tswapl(e1);
+ p[1] = tswapl(e2);
}
-static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
+static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
unsigned long addr, unsigned int sel)
{
unsigned int e1, e2;
+ uint32_t *p;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
- stl((uint8_t *)ptr, e1);
- stl((uint8_t *)ptr + 4, e2);
+ p = ptr;
+ p[0] = tswapl(e1);
+ p[1] = tswapl(e2);
}
uint64_t gdt_table[6];
void cpu_loop(CPUX86State *env)
{
int trapnr;
- uint8_t *pc;
+ target_ulong pc;
target_siginfo_t info;
for(;;) {
switch(trapnr) {
case 0x80:
/* linux syscall */
- env->regs[R_EAX] = do_syscall(env,
- env->regs[R_EAX],
+ env->regs[R_EAX] = do_syscall(env,
+ env->regs[R_EAX],
env->regs[R_EBX],
env->regs[R_ECX],
env->regs[R_EDX],
queue_signal(info.si_signo, &info);
break;
case EXCP0D_GPF:
+#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_fault(env);
- } else {
+ } else
+#endif
+ {
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL;
queue_signal(info.si_signo, &info);
break;
case EXCP00_DIVZ:
+#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
- } else {
+ } else
+#endif
+ {
/* division by zero */
info.si_signo = SIGFPE;
info.si_errno = 0;
break;
case EXCP01_SSTP:
case EXCP03_INT3:
+#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
- } else {
+ } else
+#endif
+ {
info.si_signo = SIGTRAP;
info.si_errno = 0;
if (trapnr == EXCP01_SSTP) {
break;
case EXCP04_INTO:
case EXCP05_BOUND:
+#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
- } else {
+ } else
+#endif
+ {
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
pc = env->segs[R_CS].base + env->eip;
- fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
+ fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
(long)pc, trapnr);
abort();
}
int trapnr;
unsigned int n, insn;
target_siginfo_t info;
-
+ uint32_t addr;
+
for(;;) {
trapnr = cpu_arm_exec(env);
switch(trapnr) {
/* we handle the FPU emulation here, as Linux */
/* we get the opcode */
- opcode = ldl_raw((uint8_t *)env->regs[15]);
-
- if (EmulateAll(opcode, &ts->fpa, env->regs) == 0) {
+ opcode = tget32(env->regs[15]);
+
+ if (EmulateAll(opcode, &ts->fpa, env) == 0) {
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
}
break;
case EXCP_SWI:
+ case EXCP_BKPT:
{
+ env->eabi = 1;
/* system call */
- insn = ldl((void *)(env->regs[15] - 4));
- n = insn & 0xffffff;
+ if (trapnr == EXCP_BKPT) {
+ if (env->thumb) {
+ insn = tget16(env->regs[15]);
+ n = insn & 0xff;
+ env->regs[15] += 2;
+ } else {
+ insn = tget32(env->regs[15]);
+ n = (insn & 0xf) | ((insn >> 4) & 0xff0);
+ env->regs[15] += 4;
+ }
+ } else {
+ if (env->thumb) {
+ insn = tget16(env->regs[15] - 2);
+ n = insn & 0xff;
+ } else {
+ insn = tget32(env->regs[15] - 4);
+ n = insn & 0xffffff;
+ }
+ }
+
if (n == ARM_NR_cacheflush) {
arm_cache_flush(env->regs[0], env->regs[1]);
- } else if (n >= ARM_SYSCALL_BASE) {
+ } else if (n == ARM_NR_semihosting
+ || n == ARM_NR_thumb_semihosting) {
+ env->regs[0] = do_arm_semihosting (env);
+ } else if (n == 0 || n >= ARM_SYSCALL_BASE
+ || (env->thumb && n == ARM_THUMB_SYSCALL)) {
/* linux syscall */
- n -= ARM_SYSCALL_BASE;
- env->regs[0] = do_syscall(env,
- n,
+ if (env->thumb || n == 0) {
+ n = env->regs[7];
+ } else {
+ n -= ARM_SYSCALL_BASE;
+ env->eabi = 0;
+ }
+ env->regs[0] = do_syscall(env,
+ n,
env->regs[0],
env->regs[1],
env->regs[2],
env->regs[3],
env->regs[4],
- 0);
+ env->regs[5]);
} else {
goto error;
}
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
+ case EXCP_PREFETCH_ABORT:
+ addr = env->cp15.c6_data;
+ goto do_segv;
+ case EXCP_DATA_ABORT:
+ addr = env->cp15.c6_insn;
+ goto do_segv;
+ do_segv:
+ {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = addr;
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
error:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
- cpu_arm_dump_state(env, stderr, 0);
+ cpu_dump_state(env, stderr, fprintf, 0);
abort();
}
process_pending_signals(env);
//#define DEBUG_WIN
-/* WARNING: dealing with register windows _is_ complicated */
+/* WARNING: dealing with register windows _is_ complicated. More info
+ can be found at http://www.sics.se/~psm/sparcstack.html */
static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
{
index = (index + cwp * 16) & (16 * NWINDOWS - 1);
return index;
}
-static inline void save_window_offset(CPUSPARCState *env, int offset)
+/* save the register window 'cwp1' */
+static inline void save_window_offset(CPUSPARCState *env, int cwp1)
{
- unsigned int new_wim, i, cwp1;
- uint32_t *sp_ptr;
-
- new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
- ((1LL << NWINDOWS) - 1);
- /* save the window */
- cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
- sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
+ unsigned int i;
+ target_ulong sp_ptr;
+
+ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
#if defined(DEBUG_WIN)
- printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
+ printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
(int)sp_ptr, cwp1);
#endif
- for(i = 0; i < 16; i++)
- stl_raw(sp_ptr + i, env->regbase[get_reg_index(env, cwp1, 8 + i)]);
- env->wim = new_wim;
+ for(i = 0; i < 16; i++) {
+ tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]);
+ sp_ptr += sizeof(target_ulong);
+ }
}
static void save_window(CPUSPARCState *env)
{
- save_window_offset(env, 2);
+#ifndef TARGET_SPARC64
+ unsigned int new_wim;
+ new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
+ ((1LL << NWINDOWS) - 1);
+ save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
+ env->wim = new_wim;
+#else
+ save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
+ env->cansave++;
+ env->canrestore--;
+#endif
}
static void restore_window(CPUSPARCState *env)
{
unsigned int new_wim, i, cwp1;
- uint32_t *sp_ptr;
-
+ target_ulong sp_ptr;
+
new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
((1LL << NWINDOWS) - 1);
-
+
/* restore the invalid window */
cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
- sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
+ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
#if defined(DEBUG_WIN)
- printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
+ printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
(int)sp_ptr, cwp1);
#endif
- for(i = 0; i < 16; i++)
- env->regbase[get_reg_index(env, cwp1, 8 + i)] = ldl_raw(sp_ptr + i);
+ for(i = 0; i < 16; i++) {
+ env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr);
+ sp_ptr += sizeof(target_ulong);
+ }
env->wim = new_wim;
+#ifdef TARGET_SPARC64
+ env->canrestore++;
+ if (env->cleanwin < NWINDOWS - 1)
+ env->cleanwin++;
+ env->cansave--;
+#endif
}
static void flush_windows(CPUSPARCState *env)
{
int offset, cwp1;
-#if defined(DEBUG_WIN)
- printf("flush_windows:\n");
-#endif
- offset = 2;
+
+ offset = 1;
for(;;) {
/* if restore would invoke restore_window(), then we can stop */
- cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
+ cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
if (env->wim & (1 << cwp1))
break;
-#if defined(DEBUG_WIN)
- printf("offset=%d: ", offset);
-#endif
- save_window_offset(env, offset);
+ save_window_offset(env, cwp1);
offset++;
}
+ /* set wim so that restore will reload the registers */
+ cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
+ env->wim = 1 << cwp1;
+#if defined(DEBUG_WIN)
+ printf("flush_windows: nb=%d\n", offset - 1);
+#endif
}
void cpu_loop (CPUSPARCState *env)
{
int trapnr, ret;
-
+ target_siginfo_t info;
+
while (1) {
trapnr = cpu_sparc_exec (env);
-
+
switch (trapnr) {
- case 0x88:
+#ifndef TARGET_SPARC64
+ case 0x88:
case 0x90:
+#else
+ case 0x16d:
+#endif
ret = do_syscall (env, env->gregs[1],
- env->regwptr[0], env->regwptr[1],
- env->regwptr[2], env->regwptr[3],
+ env->regwptr[0], env->regwptr[1],
+ env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5]);
if ((unsigned int)ret >= (unsigned int)(-515)) {
+#ifdef TARGET_SPARC64
+ env->xcc |= PSR_CARRY;
+#else
env->psr |= PSR_CARRY;
+#endif
ret = -ret;
} else {
+#ifdef TARGET_SPARC64
+ env->xcc &= ~PSR_CARRY;
+#else
env->psr &= ~PSR_CARRY;
+#endif
}
env->regwptr[0] = ret;
/* next instruction */
env->npc = env->npc + 4;
break;
case 0x83: /* flush windows */
- // flush_windows(env);
+ flush_windows(env);
/* next instruction */
env->pc = env->npc;
env->npc = env->npc + 4;
break;
+#ifndef TARGET_SPARC64
case TT_WIN_OVF: /* window overflow */
save_window(env);
break;
case TT_WIN_UNF: /* window underflow */
restore_window(env);
break;
+ case TT_TFAULT:
+ case TT_DFAULT:
+ {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = env->mmuregs[4];
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+#else
+ case TT_SPILL: /* window overflow */
+ save_window(env);
+ break;
+ case TT_FILL: /* window underflow */
+ restore_window(env);
+ break;
+ case TT_TFAULT:
+ case TT_DFAULT:
+ {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ if (trapnr == TT_DFAULT)
+ info._sifields._sigfault._addr = env->dmmuregs[4];
+ else
+ info._sifields._sigfault._addr = env->tpc[env->tl];
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+#endif
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
- cpu_sparc_dump_state(env, stderr, 0);
+ cpu_dump_state(env, stderr, fprintf, 0);
exit (1);
}
process_pending_signals (env);
#endif
#ifdef TARGET_PPC
+
+static inline uint64_t cpu_ppc_get_tb (CPUState *env)
+{
+ /* TO FIX */
+ return 0;
+}
+
+uint32_t cpu_ppc_load_tbl (CPUState *env)
+{
+ return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUState *env)
+{
+ return cpu_ppc_get_tb(env) >> 32;
+}
+
+static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+{
+ /* TO FIX */
+}
+
+void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+ cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+}
+
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+ cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+}
+
+void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+__attribute__ (( alias ("cpu_ppc_store_tbu") ));
+
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+
+void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
+{
+ cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+}
+
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+{
+ return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
+{
+ return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+ return -1;
+}
+
+#define EXCP_DUMP(env, fmt, args...) \
+do { \
+ fprintf(stderr, fmt , ##args); \
+ cpu_dump_state(env, stderr, fprintf, 0); \
+ if (loglevel != 0) { \
+ fprintf(logfile, fmt , ##args); \
+ cpu_dump_state(env, logfile, fprintf, 0); \
+ } \
+} while (0)
+
void cpu_loop(CPUPPCState *env)
{
target_siginfo_t info;
int trapnr;
uint32_t ret;
-
+
for(;;) {
trapnr = cpu_ppc_exec(env);
- if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
- trapnr != EXCP_TRACE) {
- if (loglevel > 0) {
- cpu_ppc_dump_state(env, logfile, 0);
- }
- }
switch(trapnr) {
- case EXCP_NONE:
+ case POWERPC_EXCP_NONE:
+ /* Just go on */
break;
- case EXCP_SYSCALL_USER:
- /* system call */
- /* WARNING:
- * PPC ABI uses overflow flag in cr0 to signal an error
- * in syscalls.
- */
-#if 0
- printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
- env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
-#endif
- env->crf[0] &= ~0x1;
- ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8]);
- if (ret > (uint32_t)(-515)) {
- env->crf[0] |= 0x1;
- ret = -ret;
- }
- env->gpr[3] = ret;
-#if 0
- printf("syscall returned 0x%08x (%d)\n", ret, ret);
-#endif
+ case POWERPC_EXCP_CRITICAL: /* Critical input */
+ cpu_abort(env, "Critical interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_RESET:
- /* Should not happen ! */
- fprintf(stderr, "RESET asked... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- abort();
- case EXCP_MACHINE_CHECK:
- fprintf(stderr, "Machine check exeption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- info.si_signo = TARGET_SIGBUS;
- info.si_errno = 0;
- info.si_code = TARGET_BUS_OBJERR;
- info._sifields._sigfault._addr = env->nip - 4;
- queue_signal(info.si_signo, &info);
- case EXCP_DSI:
- fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
- if (loglevel) {
- fprintf(logfile, "Invalid data memory access: 0x%08x\n",
- env->spr[DAR]);
- }
- switch (env->error_code & 0xF) {
- case EXCP_DSI_TRANSLATE:
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ cpu_abort(env, "Machine check exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+ env->spr[SPR_DAR]);
+ /* XXX: check this. Seems bugged */
+ switch (env->error_code & 0xFF000000) {
+ case 0x40000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
- case EXCP_DSI_NOTSUP:
- case EXCP_DSI_EXTERNAL:
+ case 0x04000000:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLADR;
break;
- case EXCP_DSI_PROT:
+ case 0x08000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR;
break;
- case EXCP_DSI_DABR:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- break;
default:
/* Let's send a regular segfault... */
- fprintf(stderr, "Invalid segfault errno (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Invalid segfault errno (%02x)\n",
- env->error_code);
- }
+ EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+ env->error_code);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->nip;
queue_signal(info.si_signo, &info);
break;
- case EXCP_ISI:
- fprintf(stderr, "Invalid instruction fetch\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction fetch\n");
- switch (env->error_code) {
- case EXCP_ISI_TRANSLATE:
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+ env->spr[SPR_DAR]);
+ /* XXX: check this */
+ switch (env->error_code & 0xFF000000) {
+ case 0x40000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
- case EXCP_ISI_GUARD:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLADR;
- break;
- case EXCP_ISI_NOEXEC:
- case EXCP_ISI_PROT:
+ case 0x10000000:
+ case 0x08000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR;
break;
default:
/* Let's send a regular segfault... */
- fprintf(stderr, "Invalid segfault errno (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Invalid segfault errno (%02x)\n",
- env->error_code);
- }
+ EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+ env->error_code);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_EXTERNAL:
- /* Should not happen ! */
- fprintf(stderr, "External interruption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "External interruption... Stop emulation\n");
- abort();
- case EXCP_ALIGN:
- fprintf(stderr, "Invalid unaligned memory access\n");
- if (loglevel)
- fprintf(logfile, "Invalid unaligned memory access\n");
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ cpu_abort(env, "External interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ EXCP_DUMP(env, "Unaligned memory access\n");
+ /* XXX: check this */
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_PROGRAM:
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ /* XXX: check this */
switch (env->error_code & ~0xF) {
- case EXCP_FP:
- fprintf(stderr, "Program exception\n");
- if (loglevel)
- fprintf(logfile, "Program exception\n");
+ case POWERPC_EXCP_FP:
+ EXCP_DUMP(env, "Floating point program exception\n");
/* Set FX */
env->fpscr[7] |= 0x8;
/* Finally, update FEX */
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
switch (env->error_code & 0xF) {
- case EXCP_FP_OX:
+ case POWERPC_EXCP_FP_OX:
info.si_code = TARGET_FPE_FLTOVF;
break;
- case EXCP_FP_UX:
+ case POWERPC_EXCP_FP_UX:
info.si_code = TARGET_FPE_FLTUND;
break;
- case EXCP_FP_ZX:
- case EXCP_FP_VXZDZ:
+ case POWERPC_EXCP_FP_ZX:
+ case POWERPC_EXCP_FP_VXZDZ:
info.si_code = TARGET_FPE_FLTDIV;
break;
- case EXCP_FP_XX:
+ case POWERPC_EXCP_FP_XX:
info.si_code = TARGET_FPE_FLTRES;
break;
- case EXCP_FP_VXSOFT:
+ case POWERPC_EXCP_FP_VXSOFT:
info.si_code = TARGET_FPE_FLTINV;
break;
- case EXCP_FP_VXNAN:
- case EXCP_FP_VXISI:
- case EXCP_FP_VXIDI:
- case EXCP_FP_VXIMZ:
- case EXCP_FP_VXVC:
- case EXCP_FP_VXSQRT:
- case EXCP_FP_VXCVI:
+ case POWERPC_EXCP_FP_VXNAN:
+ case POWERPC_EXCP_FP_VXISI:
+ case POWERPC_EXCP_FP_VXIDI:
+ case POWERPC_EXCP_FP_VXIMZ:
+ case POWERPC_EXCP_FP_VXVC:
+ case POWERPC_EXCP_FP_VXSQRT:
+ case POWERPC_EXCP_FP_VXCVI:
info.si_code = TARGET_FPE_FLTSUB;
break;
default:
- fprintf(stderr, "Unknown floating point exception "
- "(%02x)\n", env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknown floating point exception "
- "(%02x)\n", env->error_code & 0xF);
- }
+ EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+ env->error_code);
+ break;
}
- break;
- case EXCP_INVAL:
- fprintf(stderr, "Invalid instruction\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction\n");
+ break;
+ case POWERPC_EXCP_INVAL:
+ EXCP_DUMP(env, "Invalid instruction\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
- case EXCP_INVAL_INVAL:
+ case POWERPC_EXCP_INVAL_INVAL:
info.si_code = TARGET_ILL_ILLOPC;
break;
- case EXCP_INVAL_LSWX:
- info.si_code = TARGET_ILL_ILLOPN;
+ case POWERPC_EXCP_INVAL_LSWX:
+ info.si_code = TARGET_ILL_ILLOPN;
break;
- case EXCP_INVAL_SPR:
+ case POWERPC_EXCP_INVAL_SPR:
info.si_code = TARGET_ILL_PRVREG;
break;
- case EXCP_INVAL_FP:
+ case POWERPC_EXCP_INVAL_FP:
info.si_code = TARGET_ILL_COPROC;
break;
default:
- fprintf(stderr, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- if (loglevel) {
- fprintf(logfile, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- }
+ EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+ env->error_code & 0xF);
info.si_code = TARGET_ILL_ILLADR;
break;
}
break;
- case EXCP_PRIV:
- fprintf(stderr, "Privilege violation\n");
- if (loglevel)
- fprintf(logfile, "Privilege violation\n");
+ case POWERPC_EXCP_PRIV:
+ EXCP_DUMP(env, "Privilege violation\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
- case EXCP_PRIV_OPC:
+ case POWERPC_EXCP_PRIV_OPC:
info.si_code = TARGET_ILL_PRVOPC;
break;
- case EXCP_PRIV_REG:
+ case POWERPC_EXCP_PRIV_REG:
info.si_code = TARGET_ILL_PRVREG;
- break;
+ break;
default:
- fprintf(stderr, "Unknown privilege violation (%02x)\n",
- env->error_code & 0xF);
+ EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+ env->error_code & 0xF);
info.si_code = TARGET_ILL_PRVOPC;
break;
}
break;
- case EXCP_TRAP:
- fprintf(stderr, "Tried to call a TRAP\n");
- if (loglevel)
- fprintf(logfile, "Tried to call a TRAP\n");
- abort();
+ case POWERPC_EXCP_TRAP:
+ cpu_abort(env, "Tried to call a TRAP\n");
+ break;
default:
/* Should not happen ! */
- fprintf(stderr, "Unknown program exception (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknwon program exception (%02x)\n",
- env->error_code);
- }
- abort();
+ cpu_abort(env, "Unknown program exception (%02x)\n",
+ env->error_code);
+ break;
}
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_NO_FP:
- fprintf(stderr, "No floating point allowed\n");
- if (loglevel)
- fprintf(logfile, "No floating point allowed\n");
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ EXCP_DUMP(env, "No floating point allowed\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_DECR:
- /* Should not happen ! */
- fprintf(stderr, "Decrementer exception\n");
- if (loglevel)
- fprintf(logfile, "Decrementer exception\n");
- abort();
- case EXCP_RESA: /* Implementation specific */
- /* Should not happen ! */
- fprintf(stderr, "RESA exception should never happen !\n");
- if (loglevel)
- fprintf(logfile, "RESA exception should never happen !\n");
- abort();
- case EXCP_RESB: /* Implementation specific */
- /* Should not happen ! */
- fprintf(stderr, "RESB exception should never happen !\n");
- if (loglevel)
- fprintf(logfile, "RESB exception should never happen !\n");
- abort();
- case EXCP_TRACE:
- /* Do nothing: we use this to trace execution */
- break;
- case EXCP_FP_ASSIST:
- /* Should not happen ! */
- fprintf(stderr, "Floating point assist exception\n");
- if (loglevel)
- fprintf(logfile, "Floating point assist exception\n");
- abort();
- case EXCP_MTMSR:
- /* We reloaded the msr, just go on */
- if (msr_pr) {
- fprintf(stderr, "Tried to go into supervisor mode !\n");
- if (loglevel)
- fprintf(logfile, "Tried to go into supervisor mode !\n");
- abort();
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ cpu_abort(env, "Syscall exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ EXCP_DUMP(env, "No APU instruction allowed\n");
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ cpu_abort(env, "Decrementer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ cpu_abort(env, "Data TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ cpu_abort(env, "Instruction TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DEBUG: /* Debug interrupt */
+ /* XXX: check this */
+ {
+ int sig;
+
+ sig = gdb_handlesig(env, TARGET_SIGTRAP);
+ if (sig) {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
+#if defined(TARGET_PPCEMB)
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
+ cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
+ cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
+ cpu_abort(env, "Doorbell interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
+ cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ cpu_abort(env, "Reset interrupt while in user mode. "
+ "Aborting\n");
+ break;
+#endif /* defined(TARGET_PPCEMB) */
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+ case POWERPC_EXCP_DSEG: /* Data segment exception */
+ cpu_abort(env, "Data segment exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ISEG: /* Instruction segment exception */
+ cpu_abort(env, "Instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
+ cpu_abort(env, "Hypervisor decrementer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) */
+ case POWERPC_EXCP_TRACE: /* Trace exception */
+ /* Nothing to do:
+ * we use this exception to emulate step-by-step execution mode.
+ */
+ break;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
+ cpu_abort(env, "Hypervisor data storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
+ cpu_abort(env, "Hypervisor instruction storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
+ cpu_abort(env, "Hypervisor data segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
+ cpu_abort(env, "Hypervisor instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ EXCP_DUMP(env, "No Altivec instructions allowed\n");
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
+ cpu_abort(env, "Programable interval timer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_IO: /* IO error exception */
+ cpu_abort(env, "IO error exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ cpu_abort(env, "Run mode exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
+ cpu_abort(env, "Emulation trap exception not handled\n");
+ break;
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ cpu_abort(env, "Instruction fetch TLB exception "
+ "while in user-mode. Aborting");
+ break;
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ cpu_abort(env, "Data load TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ cpu_abort(env, "Data store TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_FPA: /* Floating-point assist exception */
+ cpu_abort(env, "Floating-point assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ cpu_abort(env, "Instruction address breakpoint exception "
+ "not handled\n");
+ break;
+ case POWERPC_EXCP_SMI: /* System management interrupt */
+ cpu_abort(env, "System management interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_THERM: /* Thermal interrupt */
+ cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_VPUA: /* Vector assist exception */
+ cpu_abort(env, "Vector assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_SOFTP: /* Soft patch exception */
+ cpu_abort(env, "Soft patch exception not handled\n");
+ break;
+ case POWERPC_EXCP_MAINT: /* Maintenance exception */
+ cpu_abort(env, "Maintenance exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_STOP: /* stop translation */
+ /* We did invalidate the instruction cache. Go on */
+ break;
+ case POWERPC_EXCP_BRANCH: /* branch instruction: */
+ /* We just stopped because of a branch. Go on */
+ break;
+ case POWERPC_EXCP_SYSCALL_USER:
+ /* system call in user-mode emulation */
+ /* WARNING:
+ * PPC ABI uses overflow flag in cr0 to signal an error
+ * in syscalls.
+ */
+#if 0
+ printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
+ env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
+#endif
+ env->crf[0] &= ~0x1;
+ ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8]);
+ if (ret > (uint32_t)(-515)) {
+ env->crf[0] |= 0x1;
+ ret = -ret;
+ }
+ env->gpr[3] = ret;
+#if 0
+ printf("syscall returned 0x%08x (%d)\n", ret, ret);
+#endif
+ break;
+ default:
+ cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
+ break;
}
+ process_pending_signals(env);
+ }
+}
+#endif
+
+#ifdef TARGET_MIPS
+
+#define MIPS_SYS(name, args) args,
+
+static const uint8_t mips_syscall_args[] = {
+ MIPS_SYS(sys_syscall , 0) /* 4000 */
+ MIPS_SYS(sys_exit , 1)
+ MIPS_SYS(sys_fork , 0)
+ MIPS_SYS(sys_read , 3)
+ MIPS_SYS(sys_write , 3)
+ MIPS_SYS(sys_open , 3) /* 4005 */
+ MIPS_SYS(sys_close , 1)
+ MIPS_SYS(sys_waitpid , 3)
+ MIPS_SYS(sys_creat , 2)
+ MIPS_SYS(sys_link , 2)
+ MIPS_SYS(sys_unlink , 1) /* 4010 */
+ MIPS_SYS(sys_execve , 0)
+ MIPS_SYS(sys_chdir , 1)
+ MIPS_SYS(sys_time , 1)
+ MIPS_SYS(sys_mknod , 3)
+ MIPS_SYS(sys_chmod , 2) /* 4015 */
+ MIPS_SYS(sys_lchown , 3)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
+ MIPS_SYS(sys_lseek , 3)
+ MIPS_SYS(sys_getpid , 0) /* 4020 */
+ MIPS_SYS(sys_mount , 5)
+ MIPS_SYS(sys_oldumount , 1)
+ MIPS_SYS(sys_setuid , 1)
+ MIPS_SYS(sys_getuid , 0)
+ MIPS_SYS(sys_stime , 1) /* 4025 */
+ MIPS_SYS(sys_ptrace , 4)
+ MIPS_SYS(sys_alarm , 1)
+ MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
+ MIPS_SYS(sys_pause , 0)
+ MIPS_SYS(sys_utime , 2) /* 4030 */
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_access , 2)
+ MIPS_SYS(sys_nice , 1)
+ MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
+ MIPS_SYS(sys_sync , 0)
+ MIPS_SYS(sys_kill , 2)
+ MIPS_SYS(sys_rename , 2)
+ MIPS_SYS(sys_mkdir , 2)
+ MIPS_SYS(sys_rmdir , 1) /* 4040 */
+ MIPS_SYS(sys_dup , 1)
+ MIPS_SYS(sys_pipe , 0)
+ MIPS_SYS(sys_times , 1)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_brk , 1) /* 4045 */
+ MIPS_SYS(sys_setgid , 1)
+ MIPS_SYS(sys_getgid , 0)
+ MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
+ MIPS_SYS(sys_geteuid , 0)
+ MIPS_SYS(sys_getegid , 0) /* 4050 */
+ MIPS_SYS(sys_acct , 0)
+ MIPS_SYS(sys_umount , 2)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_ioctl , 3)
+ MIPS_SYS(sys_fcntl , 3) /* 4055 */
+ MIPS_SYS(sys_ni_syscall , 2)
+ MIPS_SYS(sys_setpgid , 2)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_olduname , 1)
+ MIPS_SYS(sys_umask , 1) /* 4060 */
+ MIPS_SYS(sys_chroot , 1)
+ MIPS_SYS(sys_ustat , 2)
+ MIPS_SYS(sys_dup2 , 2)
+ MIPS_SYS(sys_getppid , 0)
+ MIPS_SYS(sys_getpgrp , 0) /* 4065 */
+ MIPS_SYS(sys_setsid , 0)
+ MIPS_SYS(sys_sigaction , 3)
+ MIPS_SYS(sys_sgetmask , 0)
+ MIPS_SYS(sys_ssetmask , 1)
+ MIPS_SYS(sys_setreuid , 2) /* 4070 */
+ MIPS_SYS(sys_setregid , 2)
+ MIPS_SYS(sys_sigsuspend , 0)
+ MIPS_SYS(sys_sigpending , 1)
+ MIPS_SYS(sys_sethostname , 2)
+ MIPS_SYS(sys_setrlimit , 2) /* 4075 */
+ MIPS_SYS(sys_getrlimit , 2)
+ MIPS_SYS(sys_getrusage , 2)
+ MIPS_SYS(sys_gettimeofday, 2)
+ MIPS_SYS(sys_settimeofday, 2)
+ MIPS_SYS(sys_getgroups , 2) /* 4080 */
+ MIPS_SYS(sys_setgroups , 2)
+ MIPS_SYS(sys_ni_syscall , 0) /* old_select */
+ MIPS_SYS(sys_symlink , 2)
+ MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
+ MIPS_SYS(sys_readlink , 3) /* 4085 */
+ MIPS_SYS(sys_uselib , 1)
+ MIPS_SYS(sys_swapon , 2)
+ MIPS_SYS(sys_reboot , 3)
+ MIPS_SYS(old_readdir , 3)
+ MIPS_SYS(old_mmap , 6) /* 4090 */
+ MIPS_SYS(sys_munmap , 2)
+ MIPS_SYS(sys_truncate , 2)
+ MIPS_SYS(sys_ftruncate , 2)
+ MIPS_SYS(sys_fchmod , 2)
+ MIPS_SYS(sys_fchown , 3) /* 4095 */
+ MIPS_SYS(sys_getpriority , 2)
+ MIPS_SYS(sys_setpriority , 3)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_statfs , 2)
+ MIPS_SYS(sys_fstatfs , 2) /* 4100 */
+ MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
+ MIPS_SYS(sys_socketcall , 2)
+ MIPS_SYS(sys_syslog , 3)
+ MIPS_SYS(sys_setitimer , 3)
+ MIPS_SYS(sys_getitimer , 2) /* 4105 */
+ MIPS_SYS(sys_newstat , 2)
+ MIPS_SYS(sys_newlstat , 2)
+ MIPS_SYS(sys_newfstat , 2)
+ MIPS_SYS(sys_uname , 1)
+ MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
+ MIPS_SYS(sys_vhangup , 0)
+ MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
+ MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
+ MIPS_SYS(sys_wait4 , 4)
+ MIPS_SYS(sys_swapoff , 1) /* 4115 */
+ MIPS_SYS(sys_sysinfo , 1)
+ MIPS_SYS(sys_ipc , 6)
+ MIPS_SYS(sys_fsync , 1)
+ MIPS_SYS(sys_sigreturn , 0)
+ MIPS_SYS(sys_clone , 0) /* 4120 */
+ MIPS_SYS(sys_setdomainname, 2)
+ MIPS_SYS(sys_newuname , 1)
+ MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
+ MIPS_SYS(sys_adjtimex , 1)
+ MIPS_SYS(sys_mprotect , 3) /* 4125 */
+ MIPS_SYS(sys_sigprocmask , 3)
+ MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
+ MIPS_SYS(sys_init_module , 5)
+ MIPS_SYS(sys_delete_module, 1)
+ MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
+ MIPS_SYS(sys_quotactl , 0)
+ MIPS_SYS(sys_getpgid , 1)
+ MIPS_SYS(sys_fchdir , 1)
+ MIPS_SYS(sys_bdflush , 2)
+ MIPS_SYS(sys_sysfs , 3) /* 4135 */
+ MIPS_SYS(sys_personality , 1)
+ MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
+ MIPS_SYS(sys_setfsuid , 1)
+ MIPS_SYS(sys_setfsgid , 1)
+ MIPS_SYS(sys_llseek , 5) /* 4140 */
+ MIPS_SYS(sys_getdents , 3)
+ MIPS_SYS(sys_select , 5)
+ MIPS_SYS(sys_flock , 2)
+ MIPS_SYS(sys_msync , 3)
+ MIPS_SYS(sys_readv , 3) /* 4145 */
+ MIPS_SYS(sys_writev , 3)
+ MIPS_SYS(sys_cacheflush , 3)
+ MIPS_SYS(sys_cachectl , 3)
+ MIPS_SYS(sys_sysmips , 4)
+ MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
+ MIPS_SYS(sys_getsid , 1)
+ MIPS_SYS(sys_fdatasync , 0)
+ MIPS_SYS(sys_sysctl , 1)
+ MIPS_SYS(sys_mlock , 2)
+ MIPS_SYS(sys_munlock , 2) /* 4155 */
+ MIPS_SYS(sys_mlockall , 1)
+ MIPS_SYS(sys_munlockall , 0)
+ MIPS_SYS(sys_sched_setparam, 2)
+ MIPS_SYS(sys_sched_getparam, 2)
+ MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
+ MIPS_SYS(sys_sched_getscheduler, 1)
+ MIPS_SYS(sys_sched_yield , 0)
+ MIPS_SYS(sys_sched_get_priority_max, 1)
+ MIPS_SYS(sys_sched_get_priority_min, 1)
+ MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
+ MIPS_SYS(sys_nanosleep, 2)
+ MIPS_SYS(sys_mremap , 4)
+ MIPS_SYS(sys_accept , 3)
+ MIPS_SYS(sys_bind , 3)
+ MIPS_SYS(sys_connect , 3) /* 4170 */
+ MIPS_SYS(sys_getpeername , 3)
+ MIPS_SYS(sys_getsockname , 3)
+ MIPS_SYS(sys_getsockopt , 5)
+ MIPS_SYS(sys_listen , 2)
+ MIPS_SYS(sys_recv , 4) /* 4175 */
+ MIPS_SYS(sys_recvfrom , 6)
+ MIPS_SYS(sys_recvmsg , 3)
+ MIPS_SYS(sys_send , 4)
+ MIPS_SYS(sys_sendmsg , 3)
+ MIPS_SYS(sys_sendto , 6) /* 4180 */
+ MIPS_SYS(sys_setsockopt , 5)
+ MIPS_SYS(sys_shutdown , 2)
+ MIPS_SYS(sys_socket , 3)
+ MIPS_SYS(sys_socketpair , 4)
+ MIPS_SYS(sys_setresuid , 3) /* 4185 */
+ MIPS_SYS(sys_getresuid , 3)
+ MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
+ MIPS_SYS(sys_poll , 3)
+ MIPS_SYS(sys_nfsservctl , 3)
+ MIPS_SYS(sys_setresgid , 3) /* 4190 */
+ MIPS_SYS(sys_getresgid , 3)
+ MIPS_SYS(sys_prctl , 5)
+ MIPS_SYS(sys_rt_sigreturn, 0)
+ MIPS_SYS(sys_rt_sigaction, 4)
+ MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
+ MIPS_SYS(sys_rt_sigpending, 2)
+ MIPS_SYS(sys_rt_sigtimedwait, 4)
+ MIPS_SYS(sys_rt_sigqueueinfo, 3)
+ MIPS_SYS(sys_rt_sigsuspend, 0)
+ MIPS_SYS(sys_pread64 , 6) /* 4200 */
+ MIPS_SYS(sys_pwrite64 , 6)
+ MIPS_SYS(sys_chown , 3)
+ MIPS_SYS(sys_getcwd , 2)
+ MIPS_SYS(sys_capget , 2)
+ MIPS_SYS(sys_capset , 2) /* 4205 */
+ MIPS_SYS(sys_sigaltstack , 0)
+ MIPS_SYS(sys_sendfile , 4)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_mmap2 , 6) /* 4210 */
+ MIPS_SYS(sys_truncate64 , 4)
+ MIPS_SYS(sys_ftruncate64 , 4)
+ MIPS_SYS(sys_stat64 , 2)
+ MIPS_SYS(sys_lstat64 , 2)
+ MIPS_SYS(sys_fstat64 , 2) /* 4215 */
+ MIPS_SYS(sys_pivot_root , 2)
+ MIPS_SYS(sys_mincore , 3)
+ MIPS_SYS(sys_madvise , 3)
+ MIPS_SYS(sys_getdents64 , 3)
+ MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
+ MIPS_SYS(sys_ni_syscall , 0)
+ MIPS_SYS(sys_gettid , 0)
+ MIPS_SYS(sys_readahead , 5)
+ MIPS_SYS(sys_setxattr , 5)
+ MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
+ MIPS_SYS(sys_fsetxattr , 5)
+ MIPS_SYS(sys_getxattr , 4)
+ MIPS_SYS(sys_lgetxattr , 4)
+ MIPS_SYS(sys_fgetxattr , 4)
+ MIPS_SYS(sys_listxattr , 3) /* 4230 */
+ MIPS_SYS(sys_llistxattr , 3)
+ MIPS_SYS(sys_flistxattr , 3)
+ MIPS_SYS(sys_removexattr , 2)
+ MIPS_SYS(sys_lremovexattr, 2)
+ MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
+ MIPS_SYS(sys_tkill , 2)
+ MIPS_SYS(sys_sendfile64 , 5)
+ MIPS_SYS(sys_futex , 2)
+ MIPS_SYS(sys_sched_setaffinity, 3)
+ MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
+ MIPS_SYS(sys_io_setup , 2)
+ MIPS_SYS(sys_io_destroy , 1)
+ MIPS_SYS(sys_io_getevents, 5)
+ MIPS_SYS(sys_io_submit , 3)
+ MIPS_SYS(sys_io_cancel , 3) /* 4245 */
+ MIPS_SYS(sys_exit_group , 1)
+ MIPS_SYS(sys_lookup_dcookie, 3)
+ MIPS_SYS(sys_epoll_create, 1)
+ MIPS_SYS(sys_epoll_ctl , 4)
+ MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
+ MIPS_SYS(sys_remap_file_pages, 5)
+ MIPS_SYS(sys_set_tid_address, 1)
+ MIPS_SYS(sys_restart_syscall, 0)
+ MIPS_SYS(sys_fadvise64_64, 7)
+ MIPS_SYS(sys_statfs64 , 3) /* 4255 */
+ MIPS_SYS(sys_fstatfs64 , 2)
+ MIPS_SYS(sys_timer_create, 3)
+ MIPS_SYS(sys_timer_settime, 4)
+ MIPS_SYS(sys_timer_gettime, 2)
+ MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
+ MIPS_SYS(sys_timer_delete, 1)
+ MIPS_SYS(sys_clock_settime, 2)
+ MIPS_SYS(sys_clock_gettime, 2)
+ MIPS_SYS(sys_clock_getres, 2)
+ MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
+ MIPS_SYS(sys_tgkill , 3)
+ MIPS_SYS(sys_utimes , 2)
+ MIPS_SYS(sys_mbind , 4)
+ MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
+ MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
+ MIPS_SYS(sys_mq_open , 4)
+ MIPS_SYS(sys_mq_unlink , 1)
+ MIPS_SYS(sys_mq_timedsend, 5)
+ MIPS_SYS(sys_mq_timedreceive, 5)
+ MIPS_SYS(sys_mq_notify , 2) /* 4275 */
+ MIPS_SYS(sys_mq_getsetattr, 3)
+ MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
+ MIPS_SYS(sys_waitid , 4)
+ MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
+ MIPS_SYS(sys_add_key , 5)
+ MIPS_SYS(sys_request_key, 4)
+ MIPS_SYS(sys_keyctl , 5)
+ MIPS_SYS(sys_set_thread_area, 1)
+ MIPS_SYS(sys_inotify_init, 0)
+ MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
+ MIPS_SYS(sys_inotify_rm_watch, 2)
+ MIPS_SYS(sys_migrate_pages, 4)
+ MIPS_SYS(sys_openat, 4)
+ MIPS_SYS(sys_mkdirat, 3)
+ MIPS_SYS(sys_mknodat, 4) /* 4290 */
+ MIPS_SYS(sys_fchownat, 5)
+ MIPS_SYS(sys_futimesat, 3)
+ MIPS_SYS(sys_fstatat64, 4)
+ MIPS_SYS(sys_unlinkat, 3)
+ MIPS_SYS(sys_renameat, 4) /* 4295 */
+ MIPS_SYS(sys_linkat, 5)
+ MIPS_SYS(sys_symlinkat, 3)
+ MIPS_SYS(sys_readlinkat, 4)
+ MIPS_SYS(sys_fchmodat, 3)
+ MIPS_SYS(sys_faccessat, 3) /* 4300 */
+ MIPS_SYS(sys_pselect6, 6)
+ MIPS_SYS(sys_ppoll, 5)
+ MIPS_SYS(sys_unshare, 1)
+ MIPS_SYS(sys_splice, 4)
+ MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
+ MIPS_SYS(sys_tee, 4)
+ MIPS_SYS(sys_vmsplice, 4)
+ MIPS_SYS(sys_move_pages, 6)
+ MIPS_SYS(sys_set_robust_list, 2)
+ MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
+ MIPS_SYS(sys_kexec_load, 4)
+ MIPS_SYS(sys_getcpu, 3)
+ MIPS_SYS(sys_epoll_pwait, 6)
+ MIPS_SYS(sys_ioprio_set, 3)
+ MIPS_SYS(sys_ioprio_get, 2)
+};
+
+#undef MIPS_SYS
+
+void cpu_loop(CPUMIPSState *env)
+{
+ target_siginfo_t info;
+ int trapnr, ret;
+ unsigned int syscall_num;
+
+ for(;;) {
+ trapnr = cpu_mips_exec(env);
+ switch(trapnr) {
+ case EXCP_SYSCALL:
+ syscall_num = env->gpr[2][env->current_tc] - 4000;
+ env->PC[env->current_tc] += 4;
+ if (syscall_num >= sizeof(mips_syscall_args)) {
+ ret = -ENOSYS;
+ } else {
+ int nb_args;
+ target_ulong sp_reg;
+ target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
+
+ nb_args = mips_syscall_args[syscall_num];
+ sp_reg = env->gpr[29][env->current_tc];
+ switch (nb_args) {
+ /* these arguments are taken from the stack */
+ case 8: arg8 = tgetl(sp_reg + 28);
+ case 7: arg7 = tgetl(sp_reg + 24);
+ case 6: arg6 = tgetl(sp_reg + 20);
+ case 5: arg5 = tgetl(sp_reg + 16);
+ default:
+ break;
+ }
+ ret = do_syscall(env, env->gpr[2][env->current_tc],
+ env->gpr[4][env->current_tc],
+ env->gpr[5][env->current_tc],
+ env->gpr[6][env->current_tc],
+ env->gpr[7][env->current_tc],
+ arg5, arg6/*, arg7, arg8*/);
+ }
+ if ((unsigned int)ret >= (unsigned int)(-1133)) {
+ env->gpr[7][env->current_tc] = 1; /* error flag */
+ ret = -ret;
+ } else {
+ env->gpr[7][env->current_tc] = 0; /* error flag */
+ }
+ env->gpr[2][env->current_tc] = ret;
break;
- case EXCP_BRANCH:
- /* We stopped because of a jump... */
+ case EXCP_TLBL:
+ case EXCP_TLBS:
+ case EXCP_CpU:
+ case EXCP_RI:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = 0;
+ queue_signal(info.si_signo, &info);
break;
- case EXCP_RFI:
- /* Should not occur: we always are in user mode */
- fprintf(stderr, "Return from interrupt ?\n");
- if (loglevel)
- fprintf(logfile, "Return from interrupt ?\n");
- abort();
case EXCP_INTERRUPT:
- /* Don't know why this should ever happen... */
+ /* just indicate that signals should be handled asap */
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
break;
- case EXCP_DEBUG:
- break;
default:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ // error:
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
- if (loglevel) {
- fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
- "0x%02x - aborting\n", trapnr, env->error_code);
- }
+ cpu_dump_state(env, stderr, fprintf, 0);
abort();
}
- if (trapnr < EXCP_PPC_MAX)
- env->exceptions &= ~(1 << trapnr);
process_pending_signals(env);
- if (env->exceptions != 0) {
- check_exception_state(env);
+ }
+}
+#endif
+
+#ifdef TARGET_SH4
+void cpu_loop (CPUState *env)
+{
+ int trapnr, ret;
+ target_siginfo_t info;
+
+ while (1) {
+ trapnr = cpu_sh4_exec (env);
+
+ switch (trapnr) {
+ case 0x160:
+ ret = do_syscall(env,
+ env->gregs[3],
+ env->gregs[4],
+ env->gregs[5],
+ env->gregs[6],
+ env->gregs[7],
+ env->gregs[0],
+ 0);
+ env->gregs[0] = ret;
+ env->pc += 2;
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
+ default:
+ printf ("Unhandled trap: 0x%x\n", trapnr);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ exit (1);
}
+ process_pending_signals (env);
}
}
#endif
+#ifdef TARGET_M68K
+
+void cpu_loop(CPUM68KState *env)
+{
+ int trapnr;
+ unsigned int n;
+ target_siginfo_t info;
+ TaskState *ts = env->opaque;
+
+ for(;;) {
+ trapnr = cpu_m68k_exec(env);
+ switch(trapnr) {
+ case EXCP_ILLEGAL:
+ {
+ if (ts->sim_syscalls) {
+ uint16_t nr;
+ nr = lduw(env->pc + 2);
+ env->pc += 4;
+ do_m68k_simcall(env, nr);
+ } else {
+ goto do_sigill;
+ }
+ }
+ break;
+ case EXCP_HALT_INSN:
+ /* Semihosing syscall. */
+ env->pc += 4;
+ do_m68k_semihosting(env, env->dregs[0]);
+ break;
+ case EXCP_LINEA:
+ case EXCP_LINEF:
+ case EXCP_UNSUPPORTED:
+ do_sigill:
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPN;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP_TRAP0:
+ {
+ ts->sim_syscalls = 0;
+ n = env->dregs[0];
+ env->pc += 2;
+ env->dregs[0] = do_syscall(env,
+ n,
+ env->dregs[1],
+ env->dregs[2],
+ env->dregs[3],
+ env->dregs[4],
+ env->dregs[5],
+ env->dregs[6]);
+ }
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ case EXCP_ACCESS:
+ {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = env->mmu.ar;
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ trapnr);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ abort();
+ }
+ process_pending_signals(env);
+ }
+}
+#endif /* TARGET_M68K */
+
+#ifdef TARGET_ALPHA
+void cpu_loop (CPUState *env)
+{
+ int trapnr;
+ target_siginfo_t info;
+
+ while (1) {
+ trapnr = cpu_alpha_exec (env);
+
+ switch (trapnr) {
+ case EXCP_RESET:
+ fprintf(stderr, "Reset requested. Exit\n");
+ exit(1);
+ break;
+ case EXCP_MCHK:
+ fprintf(stderr, "Machine check exception. Exit\n");
+ exit(1);
+ break;
+ case EXCP_ARITH:
+ fprintf(stderr, "Arithmetic trap.\n");
+ exit(1);
+ break;
+ case EXCP_HW_INTERRUPT:
+ fprintf(stderr, "External interrupt. Exit\n");
+ exit(1);
+ break;
+ case EXCP_DFAULT:
+ fprintf(stderr, "MMU data fault\n");
+ exit(1);
+ break;
+ case EXCP_DTB_MISS_PAL:
+ fprintf(stderr, "MMU data TLB miss in PALcode\n");
+ exit(1);
+ break;
+ case EXCP_ITB_MISS:
+ fprintf(stderr, "MMU instruction TLB miss\n");
+ exit(1);
+ break;
+ case EXCP_ITB_ACV:
+ fprintf(stderr, "MMU instruction access violation\n");
+ exit(1);
+ break;
+ case EXCP_DTB_MISS_NATIVE:
+ fprintf(stderr, "MMU data TLB miss\n");
+ exit(1);
+ break;
+ case EXCP_UNALIGN:
+ fprintf(stderr, "Unaligned access\n");
+ exit(1);
+ break;
+ case EXCP_OPCDEC:
+ fprintf(stderr, "Invalid instruction\n");
+ exit(1);
+ break;
+ case EXCP_FEN:
+ fprintf(stderr, "Floating-point not allowed\n");
+ exit(1);
+ break;
+ case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
+ fprintf(stderr, "Call to PALcode\n");
+ call_pal(env, (trapnr >> 6) | 0x80);
+ break;
+ case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
+ fprintf(stderr, "Privileged call to PALcode\n");
+ exit(1);
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
+ default:
+ printf ("Unhandled trap: 0x%x\n", trapnr);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ exit (1);
+ }
+ process_pending_signals (env);
+ }
+}
+#endif /* TARGET_ALPHA */
+
void usage(void)
{
- printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
+ printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
+ "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] [-cpu model] program [arguments...]\n"
"Linux CPU emulator (compiled for %s emulation)\n"
"\n"
- "-h print this help\n"
- "-L path set the elf interpreter prefix (default=%s)\n"
- "-s size set the stack size in bytes (default=%ld)\n"
+ "-h print this help\n"
+ "-g port wait gdb connection to port\n"
+ "-L path set the elf interpreter prefix (default=%s)\n"
+ "-s size set the stack size in bytes (default=%ld)\n"
+ "-cpu model select CPU (-cpu ? for list)\n"
+ "-drop-ld-preload drop LD_PRELOAD for target process\n"
"\n"
"debug options:\n"
#ifdef USE_CODE_COPY
"-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n",
TARGET_ARCH,
- interp_prefix,
+ interp_prefix,
x86_stack_size,
DEBUG_LOGFILE);
_exit(1);
/* XXX: currently only used for async signals (see signal.c) */
CPUState *global_env;
-/* used only if single thread */
-CPUState *cpu_single_env = NULL;
/* used to free thread contexts */
TaskState *first_task_state;
int main(int argc, char **argv)
{
const char *filename;
+ const char *cpu_model;
struct target_pt_regs regs1, *regs = ®s1;
struct image_info info1, *info = &info1;
TaskState ts1, *ts = &ts1;
CPUState *env;
int optind;
const char *r;
-
+ int gdbstub_port = 0;
+ int drop_ld_preload = 0, environ_count = 0;
+ char **target_environ, **wrk, **dst;
+
if (argc <= 1)
usage();
/* init debug */
cpu_set_log_filename(DEBUG_LOGFILE);
+ cpu_model = NULL;
optind = 1;
for(;;) {
if (optind >= argc)
if (optind >= argc)
break;
-
+
r = argv[optind++];
mask = cpu_str_to_log_mask(r);
if (!mask) {
} else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++];
} else if (!strcmp(r, "p")) {
- host_page_size = atoi(argv[optind++]);
- if (host_page_size == 0 ||
- (host_page_size & (host_page_size - 1)) != 0) {
+ qemu_host_page_size = atoi(argv[optind++]);
+ if (qemu_host_page_size == 0 ||
+ (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
fprintf(stderr, "page size must be a power of two\n");
exit(1);
}
- } else
+ } else if (!strcmp(r, "g")) {
+ gdbstub_port = atoi(argv[optind++]);
+ } else if (!strcmp(r, "r")) {
+ qemu_uname_release = argv[optind++];
+ } else if (!strcmp(r, "cpu")) {
+ cpu_model = argv[optind++];
+ if (strcmp(cpu_model, "?") == 0) {
+#if defined(TARGET_PPC)
+ ppc_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_ARM)
+ arm_cpu_list();
+#elif defined(TARGET_MIPS)
+ mips_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_SPARC)
+ sparc_cpu_list(stdout, &fprintf);
+#endif
+ _exit(1);
+ }
+ } else if (!strcmp(r, "drop-ld-preload")) {
+ drop_ld_preload = 1;
+ } else
#ifdef USE_CODE_COPY
if (!strcmp(r, "no-code-copy")) {
code_copy_enabled = 0;
- } else
+ } else
#endif
{
usage();
/* Scan interp_prefix dir for replacement files. */
init_paths(interp_prefix);
- /* NOTE: we need to init the CPU at this stage to get the
- host_page_size */
+ /* NOTE: we need to init the CPU at this stage to get
+ qemu_host_page_size */
env = cpu_init();
-
- if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
- printf("Error loading %s\n", filename);
- _exit(1);
+ global_env = env;
+
+ wrk = environ;
+ while (*(wrk++))
+ environ_count++;
+
+ target_environ = malloc((environ_count + 1) * sizeof(char *));
+ if (!target_environ)
+ abort();
+ for (wrk = environ, dst = target_environ; *wrk; wrk++) {
+ if (drop_ld_preload && !strncmp(*wrk, "LD_PRELOAD=", 11))
+ continue;
+ *(dst++) = strdup(*wrk);
+ }
+ *dst = NULL; /* NULL terminate target_environ */
+
+ if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
+ printf("Error loading %s\n", filename);
+ _exit(1);
+ }
+
+ for (wrk = target_environ; *wrk; wrk++) {
+ free(*wrk);
}
-
+
+ free(target_environ);
+
if (loglevel) {
page_dump(logfile);
-
+
fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
+ fprintf(logfile, "start_data 0x%08lx\n" , info->start_data);
fprintf(logfile, "end_data 0x%08lx\n" , info->end_data);
fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
fprintf(logfile, "brk 0x%08lx\n" , info->brk);
fprintf(logfile, "entry 0x%08lx\n" , info->entry);
}
- target_set_brk((char *)info->brk);
+ target_set_brk(info->brk);
syscall_init();
signal_init();
- global_env = env;
-
/* build Task State */
memset(ts, 0, sizeof(TaskState));
env->opaque = ts;
ts->used = 1;
+ ts->info = info;
env->user_mode_only = 1;
-
+
#if defined(TARGET_I386)
cpu_x86_set_cpl(env, 3);
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
+ if (env->cpuid_features & CPUID_SSE) {
+ env->cr[4] |= CR4_OSFXSR_MASK;
+ env->hflags |= HF_OSFXSR_MASK;
+ }
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
-
+
/* linux register setup */
+#if defined(TARGET_X86_64)
+ env->regs[R_EAX] = regs->rax;
+ env->regs[R_EBX] = regs->rbx;
+ env->regs[R_ECX] = regs->rcx;
+ env->regs[R_EDX] = regs->rdx;
+ env->regs[R_ESI] = regs->rsi;
+ env->regs[R_EDI] = regs->rdi;
+ env->regs[R_EBP] = regs->rbp;
+ env->regs[R_ESP] = regs->rsp;
+ env->eip = regs->rip;
+#else
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->eip = regs->eip;
+#endif
/* linux interrupt setup */
- env->idt.base = (void *)idt_table;
+ env->idt.base = h2g(idt_table);
env->idt.limit = sizeof(idt_table) - 1;
set_idt(0, 0);
set_idt(1, 0);
set_idt(0x80, 3);
/* linux segment setup */
- env->gdt.base = (void *)gdt_table;
+ env->gdt.base = h2g(gdt_table);
env->gdt.limit = sizeof(gdt_table) - 1;
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_DS, __USER_DS);
cpu_x86_load_seg(env, R_FS, __USER_DS);
cpu_x86_load_seg(env, R_GS, __USER_DS);
+ /* This hack makes Wine work... */
+ env->segs[R_FS].selector = 0;
#elif defined(TARGET_ARM)
{
int i;
+ if (cpu_model == NULL)
+ cpu_model = "arm926";
+ cpu_arm_set_model(env, cpu_model);
+ cpsr_write(env, regs->uregs[16], 0xffffffff);
for(i = 0; i < 16; i++) {
env->regs[i] = regs->uregs[i];
}
- env->cpsr = regs->uregs[16];
}
#elif defined(TARGET_SPARC)
{
int i;
+ const sparc_def_t *def;
+#ifdef TARGET_SPARC64
+ if (cpu_model == NULL)
+ cpu_model = "TI UltraSparc II";
+#else
+ if (cpu_model == NULL)
+ cpu_model = "Fujitsu MB86904";
+#endif
+ sparc_find_by_name(cpu_model, &def);
+ if (def == NULL) {
+ fprintf(stderr, "Unable to find Sparc CPU definition\n");
+ exit(1);
+ }
+ cpu_sparc_register(env, def);
env->pc = regs->pc;
env->npc = regs->npc;
env->y = regs->y;
}
#elif defined(TARGET_PPC)
{
+ ppc_def_t *def;
int i;
+
+ /* Choose and initialise CPU */
+ if (cpu_model == NULL)
+ cpu_model = "750";
+ ppc_find_by_name(cpu_model, &def);
+ if (def == NULL) {
+ cpu_abort(env,
+ "Unable to find PowerPC CPU definition\n");
+ }
+ cpu_ppc_register(env, def);
+
for (i = 0; i < 32; i++) {
- if (i != 12 && i != 6)
+ if (i != 12 && i != 6 && i != 13)
env->msr[i] = (regs->msr >> i) & 1;
}
+#if defined(TARGET_PPC64)
+ msr_sf = 1;
+#endif
env->nip = regs->nip;
for(i = 0; i < 32; i++) {
env->gpr[i] = regs->gpr[i];
}
}
+#elif defined(TARGET_M68K)
+ {
+ if (cpu_model == NULL)
+ cpu_model = "any";
+ if (cpu_m68k_set_model(env, cpu_model)) {
+ cpu_abort(cpu_single_env,
+ "Unable to find m68k CPU definition\n");
+ }
+ env->pc = regs->pc;
+ env->dregs[0] = regs->d0;
+ env->dregs[1] = regs->d1;
+ env->dregs[2] = regs->d2;
+ env->dregs[3] = regs->d3;
+ env->dregs[4] = regs->d4;
+ env->dregs[5] = regs->d5;
+ env->dregs[6] = regs->d6;
+ env->dregs[7] = regs->d7;
+ env->aregs[0] = regs->a0;
+ env->aregs[1] = regs->a1;
+ env->aregs[2] = regs->a2;
+ env->aregs[3] = regs->a3;
+ env->aregs[4] = regs->a4;
+ env->aregs[5] = regs->a5;
+ env->aregs[6] = regs->a6;
+ env->aregs[7] = regs->usp;
+ env->sr = regs->sr;
+ ts->sim_syscalls = 1;
+ }
+#elif defined(TARGET_MIPS)
+ {
+ mips_def_t *def;
+ int i;
+
+ /* Choose and initialise CPU */
+ if (cpu_model == NULL)
+ cpu_model = "24Kf";
+ mips_find_by_name(cpu_model, &def);
+ if (def == NULL)
+ cpu_abort(env, "Unable to find MIPS CPU definition\n");
+ cpu_mips_register(env, def);
+
+ for(i = 0; i < 32; i++) {
+ env->gpr[i][env->current_tc] = regs->regs[i];
+ }
+ env->PC[env->current_tc] = regs->cp0_epc;
+ }
+#elif defined(TARGET_SH4)
+ {
+ int i;
+
+ for(i = 0; i < 16; i++) {
+ env->gregs[i] = regs->regs[i];
+ }
+ env->pc = regs->pc;
+ }
+#elif defined(TARGET_ALPHA)
+ {
+ int i;
+
+ for(i = 0; i < 28; i++) {
+ env->ir[i] = ((target_ulong *)regs)[i];
+ }
+ env->ipr[IPR_USP] = regs->usp;
+ env->ir[30] = regs->usp;
+ env->pc = regs->pc;
+ env->unique = regs->unique;
+ }
#else
#error unsupported target CPU
#endif
+#if defined(TARGET_ARM) || defined(TARGET_M68K)
+ ts->stack_base = info->start_stack;
+ ts->heap_base = info->brk;
+ /* This will be filled in on the first SYS_HEAPINFO call. */
+ ts->heap_limit = 0;
+#endif
+
+ if (gdbstub_port) {
+ gdbserver_start (gdbstub_port);
+ gdb_handlesig(env, 0);
+ }
cpu_loop(env);
/* never exits */
return 0;