/*
* qemu user main
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
/* timers for rdtsc */
-#if defined(__i386__)
-
-int64_t cpu_get_real_ticks(void)
-{
- int64_t val;
- asm volatile ("rdtsc" : "=A" (val));
- return val;
-}
-
-#elif defined(__x86_64__)
-
-int64_t cpu_get_real_ticks(void)
-{
- uint32_t low,high;
- int64_t val;
- asm volatile("rdtsc" : "=a" (low), "=d" (high));
- val = high;
- val <<= 32;
- val |= low;
- return val;
-}
-
-#else
+#if 0
static uint64_t emu_time;
/***********************************************************/
/* CPUX86 core interface */
+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,
+static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
unsigned int e1, e2;
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;
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;
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();
}
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 = tget32(env->regs[15]);
-
+
if (EmulateAll(opcode, &ts->fpa, env) == 0) {
info.si_signo = SIGILL;
info.si_errno = 0;
n -= ARM_SYSCALL_BASE;
env->eabi = 0;
}
- env->regs[0] = do_syscall(env,
- n,
+ env->regs[0] = do_syscall(env,
+ n,
env->regs[0],
env->regs[1],
env->regs[2],
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_dump_state(env, stderr, fprintf, 0);
abort();
{
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++) {
static void save_window(CPUSPARCState *env)
{
+#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;
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 = 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++) {
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 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 */
}
break;
#else
- // XXX
+ 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 0x100: // XXX, why do we get these?
- break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
case EXCP_DEBUG:
{
int sig;
/* 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 */
{
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);
}
-
-uint32_t cpu_ppc_load_decr (CPUState *env)
+
+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)
{
- /* TO FIX */
- return -1;
+ cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
}
-
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
{
- /* TO FIX */
+ return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
}
-
+
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 &&
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",
+ fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n",
env->spr[SPR_DAR]);
if (loglevel) {
- fprintf(logfile, "Invalid data memory access: 0x%08x\n",
+ fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n",
env->spr[SPR_DAR]);
}
switch (env->error_code & 0xFF000000) {
}
break;
default:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
if (loglevel) {
fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
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_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, nb_args;
+ int trapnr, ret;
unsigned int syscall_num;
- target_ulong arg5, arg6, sp_reg;
for(;;) {
trapnr = cpu_mips_exec(env);
switch(trapnr) {
case EXCP_SYSCALL:
- {
- syscall_num = env->gpr[2] - 4000;
- if (syscall_num >= sizeof(mips_syscall_args)) {
- ret = -ENOSYS;
- } else {
- nb_args = mips_syscall_args[syscall_num];
- if (nb_args >= 5) {
- sp_reg = env->gpr[29];
- /* these arguments are taken from the stack */
- arg5 = tgetl(sp_reg + 16);
- if (nb_args >= 6) {
- arg6 = tgetl(sp_reg + 20);
- } else {
- arg6 = 0;
- }
- } else {
- arg5 = 0;
- arg6 = 0;
- }
- ret = do_syscall(env,
- env->gpr[2],
- env->gpr[4],
- env->gpr[5],
- env->gpr[6],
- env->gpr[7],
- arg5,
- arg6);
- }
- env->PC += 4;
- if ((unsigned int)ret >= (unsigned int)(-1133)) {
- env->gpr[7] = 1; /* error flag */
- ret = -ret;
- env->gpr[0] = ret;
- env->gpr[2] = ret;
- } else {
- env->gpr[7] = 0; /* error flag */
- env->gpr[2] = ret;
+ 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_TLBL:
+ case EXCP_TLBS:
case EXCP_CpU:
case EXCP_RI:
info.si_signo = TARGET_SIGILL;
info.si_code = 0;
queue_signal(info.si_signo, &info);
break;
+ 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:
// error:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
abort();
void cpu_loop (CPUState *env)
{
int trapnr, ret;
- // target_siginfo_t info;
-
+ target_siginfo_t info;
+
while (1) {
trapnr = cpu_sh4_exec (env);
-
+
switch (trapnr) {
case 0x160:
- ret = do_syscall(env,
- env->gregs[0x13],
- env->gregs[0x14],
- env->gregs[0x15],
- env->gregs[0x16],
- env->gregs[0x17],
- env->gregs[0x10],
+ 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[0x10] = ret;
+ 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);
}
#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-2005 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [-h] [-g] [-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"
- "-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"
+ "-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);
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;
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) {
gdbstub_port = atoi(argv[optind++]);
} else if (!strcmp(r, "r")) {
qemu_uname_release = argv[optind++];
- } else
+ } 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();
qemu_host_page_size */
env = cpu_init();
global_env = env;
-
- if (loader_exec(filename, argv+optind, environ, regs, info) != 0) {
- printf("Error loading %s\n", filename);
- _exit(1);
+
+ 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);
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);
/* 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 = h2g(idt_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;
- cpu_arm_set_model(env, ARM_CPUID_ARM1026);
+ 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];
}
- 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;
}
#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;
int i;
/* Choose and initialise CPU */
- /* XXX: CPU model (or PVR) should be provided on command line */
- // ppc_find_by_name("750gx", &def);
- // ppc_find_by_name("750fx", &def);
- // ppc_find_by_name("750p", &def);
- ppc_find_by_name("750", &def);
- // ppc_find_by_name("G3", &def);
- // ppc_find_by_name("604r", &def);
- // ppc_find_by_name("604e", &def);
- // ppc_find_by_name("604", &def);
+ 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");
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] = regs->regs[i];
+ env->gpr[i][env->current_tc] = regs->regs[i];
}
- env->PC = regs->cp0_epc;
-#ifdef MIPS_USES_FPU
- env->CP0_Status |= (1 << CP0St_CU1);
-#endif
+ env->PC[env->current_tc] = regs->cp0_epc;
}
#elif defined(TARGET_SH4)
{
}
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);