#define DEBUG_LOGFILE "/tmp/qemu.log"
+#ifdef __APPLE__
+#include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#endif
+
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
#if defined(__i386__) && !defined(CONFIG_STATIC)
/* 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];
long __init_array_end[0];
long __fini_array_start[0];
return 0;
}
+int cpu_get_pic_interrupt(CPUState *env)
+{
+ return -1;
+}
+
+/* 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
+
+static uint64_t emu_time;
+
+int64_t cpu_get_real_ticks(void)
+{
+ return emu_time++;
+}
+
+#endif
+
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
-int cpu_x86_get_pic_interrupt(CPUState *env)
+uint64_t cpu_get_tsc(CPUX86State *env)
{
- return -1;
+ return cpu_get_real_ticks();
}
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
#ifdef TARGET_ARM
+/* XXX: find a better solution */
+extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
+
+static void arm_cache_flush(target_ulong start, target_ulong last)
+{
+ target_ulong addr, last1;
+
+ if (last < start)
+ return;
+ addr = start;
+ for(;;) {
+ last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;
+ if (last1 > last)
+ last1 = last;
+ tb_invalidate_page_range(addr, last1 + 1);
+ if (last1 == last)
+ break;
+ addr = last1 + 1;
+ }
+}
+
void cpu_loop(CPUARMState *env)
{
int trapnr;
trapnr = cpu_arm_exec(env);
switch(trapnr) {
case EXCP_UDEF:
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPN;
- info._sifields._sigfault._addr = env->regs[15];
- queue_signal(info.si_signo, &info);
+ {
+ TaskState *ts = env->opaque;
+ uint32_t opcode;
+
+ /* 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) {
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPN;
+ info._sifields._sigfault._addr = env->regs[15];
+ queue_signal(info.si_signo, &info);
+ } else {
+ /* increment PC */
+ env->regs[15] += 4;
+ }
+ }
break;
case EXCP_SWI:
{
/* system call */
insn = ldl((void *)(env->regs[15] - 4));
n = insn & 0xffffff;
- if (n >= ARM_SYSCALL_BASE) {
+ if (n == ARM_NR_cacheflush) {
+ arm_cache_flush(env->regs[0], env->regs[1]);
+ } else if (n >= ARM_SYSCALL_BASE) {
/* linux syscall */
n -= ARM_SYSCALL_BASE;
env->regs[0] = do_syscall(env,
error:
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);
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);
#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);
+}
+
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+ /* TO FIX */
+ return -1;
+}
+
+void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+{
+ /* TO FIX */
+}
+
void cpu_loop(CPUPPCState *env)
{
target_siginfo_t info;
if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
trapnr != EXCP_TRACE) {
if (loglevel > 0) {
- cpu_ppc_dump_state(env, logfile, 0);
+ cpu_dump_state(env, logfile, fprintf, 0);
}
}
switch(trapnr) {
abort();
case EXCP_MTMSR:
/* We reloaded the msr, just go on */
- if (msr_pr) {
+ if (msr_pr == 0) {
fprintf(stderr, "Tried to go into supervisor mode !\n");
if (loglevel)
fprintf(logfile, "Tried to go into supervisor mode !\n");
case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */
break;
+ case EXCP_DEBUG:
+ break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
}
abort();
}
- if (trapnr < EXCP_PPC_MAX)
- env->exceptions &= ~(1 << trapnr);
process_pending_signals(env);
- if (env->exceptions != 0) {
- check_exception_state(env);
- }
}
}
#endif
void usage(void)
{
- printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [-h] [-d] [-L path] [-s size] program [arguments...]\n"
+ 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"
"Linux CPU emulator (compiled for %s emulation)\n"
"\n"
"-h print this help\n"
"-s size set the stack size in bytes (default=%ld)\n"
"\n"
"debug options:\n"
- "-d activate log (logfile=%s)\n"
+#ifdef USE_CODE_COPY
+ "-no-code-copy disable code copy acceleration\n"
+#endif
+ "-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n",
TARGET_ARCH,
interp_prefix,
if (!strcmp(r, "-")) {
break;
} else if (!strcmp(r, "d")) {
- cpu_set_log(CPU_LOG_ALL);
+ int mask;
+ CPULogItem *item;
+
+ if (optind >= argc)
+ break;
+
+ r = argv[optind++];
+ mask = cpu_str_to_log_mask(r);
+ if (!mask) {
+ printf("Log items (comma separated):\n");
+ for(item = cpu_log_items; item->mask != 0; item++) {
+ printf("%-10s %s\n", item->name, item->help);
+ }
+ exit(1);
+ }
+ cpu_set_log(mask);
} else if (!strcmp(r, "s")) {
r = argv[optind++];
x86_stack_size = strtol(r, (char **)&r, 0);
} 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
+#ifdef USE_CODE_COPY
+ if (!strcmp(r, "no-code-copy")) {
+ code_copy_enabled = 0;
+ } 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) {
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
+ /* flags setup : we activate the IRQs by default as in user mode */
+ env->eflags |= IF_MASK;
+
/* linux register setup */
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;