X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=linux-user%2Fmain.c;h=0c5e6b5b431de2f7151e13ffa88cb77694545eab;hb=c35734b2a6f9b028edacd5813ff271728ce2a9e3;hp=5b4182bd8bc178c00e81b11421829e05dee05dd0;hpb=978efd6aac65bc1e025472859eb738839425318b;p=qemu diff --git a/linux-user/main.c b/linux-user/main.c index 5b4182b..0c5e6b5 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -107,29 +107,7 @@ int cpu_get_pic_interrupt(CPUState *env) /* 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; @@ -144,6 +122,10 @@ int64_t cpu_get_real_ticks(void) /***********************************************************/ /* CPUX86 core interface */ +void cpu_smm_update(CPUState *env) +{ +} + uint64_t cpu_get_tsc(CPUX86State *env) { return cpu_get_real_ticks(); @@ -495,11 +477,17 @@ static inline void save_window_offset(CPUSPARCState *env, int cwp1) 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) @@ -522,6 +510,12 @@ static void restore_window(CPUSPARCState *env) 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) @@ -554,17 +548,29 @@ void cpu_loop (CPUSPARCState *env) trapnr = cpu_sparc_exec (env); switch (trapnr) { +#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[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 */ @@ -596,10 +602,17 @@ void cpu_loop (CPUSPARCState *env) } break; #else + case TT_SPILL: /* window overflow */ + save_window(env); + break; + case TT_FILL: /* window underflow */ + restore_window(env); + break; // XXX #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; @@ -657,18 +670,23 @@ 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; @@ -1284,6 +1302,7 @@ static const uint8_t mips_syscall_args[] = { MIPS_SYS(sys_add_key , 5) MIPS_SYS(sys_request_key , 4) MIPS_SYS(sys_keyctl , 5) + MIPS_SYS(sys_set_thread_area, 1) }; #undef MIPS_SYS @@ -1301,6 +1320,7 @@ void cpu_loop(CPUMIPSState *env) case EXCP_SYSCALL: { syscall_num = env->gpr[2] - 4000; + env->PC += 4; if (syscall_num >= sizeof(mips_syscall_args)) { ret = -ENOSYS; } else { @@ -1327,7 +1347,6 @@ void cpu_loop(CPUMIPSState *env) arg5, arg6); } - env->PC += 4; if ((unsigned int)ret >= (unsigned int)(-1133)) { env->gpr[7] = 1; /* error flag */ ret = -ret; @@ -1339,6 +1358,8 @@ void cpu_loop(CPUMIPSState *env) } } break; + case EXCP_TLBL: + case EXCP_TLBS: case EXCP_CpU: case EXCP_RI: info.si_signo = TARGET_SIGILL; @@ -1346,6 +1367,23 @@ void cpu_loop(CPUMIPSState *env) 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", @@ -1362,7 +1400,7 @@ void cpu_loop(CPUMIPSState *env) void cpu_loop (CPUState *env) { int trapnr, ret; - // target_siginfo_t info; + target_siginfo_t info; while (1) { trapnr = cpu_sh4_exec (env); @@ -1370,16 +1408,30 @@ void cpu_loop (CPUState *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], + 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); @@ -1390,16 +1442,109 @@ void cpu_loop (CPUState *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_HALTED: + /* Semihosing syscall. */ + env->pc += 2; + 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 */ + 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" + "-cpu model select CPU (-cpu ? for list)\n" "\n" "debug options:\n" #ifdef USE_CODE_COPY @@ -1423,6 +1568,7 @@ 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; @@ -1437,6 +1583,7 @@ int main(int argc, char **argv) /* init debug */ cpu_set_log_filename(DEBUG_LOGFILE); + cpu_model = NULL; optind = 1; for(;;) { if (optind >= argc) @@ -1487,6 +1634,18 @@ int main(int argc, char **argv) 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); +#endif + _exit(1); + } } else #ifdef USE_CODE_COPY if (!strcmp(r, "no-code-copy")) { @@ -1612,7 +1771,9 @@ int main(int argc, char **argv) #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]; @@ -1639,15 +1800,9 @@ int main(int argc, char **argv) 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"); @@ -1663,17 +1818,55 @@ int main(int argc, char **argv) env->gpr[i] = regs->gpr[i]; } } +#elif defined(TARGET_M68K) + { + m68k_def_t *def; + def = m68k_find_by_name("cfv4e"); + if (def == NULL) { + cpu_abort(cpu_single_env, + "Unable to find m68k CPU definition\n"); + } + cpu_m68k_register(cpu_single_env, def); + 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->PC = regs->cp0_epc; -#ifdef MIPS_USES_FPU - env->CP0_Status |= (1 << CP0St_CU1); -#endif + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + env->CP0_Status |= (1 << CP0St_CU1); + } } #elif defined(TARGET_SH4) {