131e31b8aSbellard /* 293ac68bcSbellard * qemu user main 331e31b8aSbellard * 431e31b8aSbellard * Copyright (c) 2003 Fabrice Bellard 531e31b8aSbellard * 631e31b8aSbellard * This program is free software; you can redistribute it and/or modify 731e31b8aSbellard * it under the terms of the GNU General Public License as published by 831e31b8aSbellard * the Free Software Foundation; either version 2 of the License, or 931e31b8aSbellard * (at your option) any later version. 1031e31b8aSbellard * 1131e31b8aSbellard * This program is distributed in the hope that it will be useful, 1231e31b8aSbellard * but WITHOUT ANY WARRANTY; without even the implied warranty of 1331e31b8aSbellard * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1431e31b8aSbellard * GNU General Public License for more details. 1531e31b8aSbellard * 1631e31b8aSbellard * You should have received a copy of the GNU General Public License 1731e31b8aSbellard * along with this program; if not, write to the Free Software 1831e31b8aSbellard * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1931e31b8aSbellard */ 2031e31b8aSbellard #include <stdlib.h> 2131e31b8aSbellard #include <stdio.h> 2231e31b8aSbellard #include <stdarg.h> 2304369ff2Sbellard #include <string.h> 2431e31b8aSbellard #include <errno.h> 250ecfa993Sbellard #include <unistd.h> 2631e31b8aSbellard 273ef693a0Sbellard #include "qemu.h" 2831e31b8aSbellard 293ef693a0Sbellard #define DEBUG_LOGFILE "/tmp/qemu.log" 30586314f2Sbellard 3174cd30b8Sbellard static const char *interp_prefix = CONFIG_QEMU_PREFIX; 32c5937220Spbrook const char *qemu_uname_release = CONFIG_UNAME_RELEASE; 33586314f2Sbellard 343a4739d6Sbellard #if defined(__i386__) && !defined(CONFIG_STATIC) 35f801f97eSbellard /* Force usage of an ELF interpreter even if it is an ELF shared 36f801f97eSbellard object ! */ 37f801f97eSbellard const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2"; 384304763bSbellard #endif 3974cd30b8Sbellard 4093ac68bcSbellard /* for recent libc, we add these dummy symbols which are not declared 4174cd30b8Sbellard when generating a linked object (bug in ld ?) */ 42fbf59244Sbellard #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC) 4346027c07Sbellard asm(".globl __preinit_array_start\n" 4446027c07Sbellard ".globl __preinit_array_end\n" 4546027c07Sbellard ".globl __init_array_start\n" 4646027c07Sbellard ".globl __init_array_end\n" 4746027c07Sbellard ".globl __fini_array_start\n" 4846027c07Sbellard ".globl __fini_array_end\n" 4946027c07Sbellard ".section \".rodata\"\n" 5046027c07Sbellard "__preinit_array_start:\n" 5146027c07Sbellard "__preinit_array_end:\n" 5246027c07Sbellard "__init_array_start:\n" 5346027c07Sbellard "__init_array_end:\n" 5446027c07Sbellard "__fini_array_start:\n" 5546027c07Sbellard "__fini_array_end:\n" 5646027c07Sbellard ".long 0\n"); 5774cd30b8Sbellard #endif 5874cd30b8Sbellard 599de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 609de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 619de5e440Sbellard by remapping the process stack directly at the right place */ 629de5e440Sbellard unsigned long x86_stack_size = 512 * 1024; 6331e31b8aSbellard 6431e31b8aSbellard void gemu_log(const char *fmt, ...) 6531e31b8aSbellard { 6631e31b8aSbellard va_list ap; 6731e31b8aSbellard 6831e31b8aSbellard va_start(ap, fmt); 6931e31b8aSbellard vfprintf(stderr, fmt, ap); 7031e31b8aSbellard va_end(ap); 7131e31b8aSbellard } 7231e31b8aSbellard 7361190b14Sbellard void cpu_outb(CPUState *env, int addr, int val) 74367e86e8Sbellard { 75367e86e8Sbellard fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); 76367e86e8Sbellard } 77367e86e8Sbellard 7861190b14Sbellard void cpu_outw(CPUState *env, int addr, int val) 79367e86e8Sbellard { 80367e86e8Sbellard fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); 81367e86e8Sbellard } 82367e86e8Sbellard 8361190b14Sbellard void cpu_outl(CPUState *env, int addr, int val) 84367e86e8Sbellard { 85367e86e8Sbellard fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); 86367e86e8Sbellard } 87367e86e8Sbellard 8861190b14Sbellard int cpu_inb(CPUState *env, int addr) 89367e86e8Sbellard { 90367e86e8Sbellard fprintf(stderr, "inb: port=0x%04x\n", addr); 91367e86e8Sbellard return 0; 92367e86e8Sbellard } 93367e86e8Sbellard 9461190b14Sbellard int cpu_inw(CPUState *env, int addr) 95367e86e8Sbellard { 96367e86e8Sbellard fprintf(stderr, "inw: port=0x%04x\n", addr); 97367e86e8Sbellard return 0; 98367e86e8Sbellard } 99367e86e8Sbellard 10061190b14Sbellard int cpu_inl(CPUState *env, int addr) 101367e86e8Sbellard { 102367e86e8Sbellard fprintf(stderr, "inl: port=0x%04x\n", addr); 103367e86e8Sbellard return 0; 104367e86e8Sbellard } 105367e86e8Sbellard 106a541f297Sbellard int cpu_get_pic_interrupt(CPUState *env) 10792ccca6aSbellard { 10892ccca6aSbellard return -1; 10992ccca6aSbellard } 11092ccca6aSbellard 11128ab0e2eSbellard /* timers for rdtsc */ 11228ab0e2eSbellard 1131dce7c3cSbellard #if 0 11428ab0e2eSbellard 11528ab0e2eSbellard static uint64_t emu_time; 11628ab0e2eSbellard 11728ab0e2eSbellard int64_t cpu_get_real_ticks(void) 11828ab0e2eSbellard { 11928ab0e2eSbellard return emu_time++; 12028ab0e2eSbellard } 12128ab0e2eSbellard 12228ab0e2eSbellard #endif 12328ab0e2eSbellard 124a541f297Sbellard #ifdef TARGET_I386 125a541f297Sbellard /***********************************************************/ 126a541f297Sbellard /* CPUX86 core interface */ 127a541f297Sbellard 12802a1602eSbellard void cpu_smm_update(CPUState *env) 12902a1602eSbellard { 13002a1602eSbellard } 13102a1602eSbellard 13228ab0e2eSbellard uint64_t cpu_get_tsc(CPUX86State *env) 13328ab0e2eSbellard { 13428ab0e2eSbellard return cpu_get_real_ticks(); 13528ab0e2eSbellard } 13628ab0e2eSbellard 137f4beb510Sbellard static void write_dt(void *ptr, unsigned long addr, unsigned long limit, 138f4beb510Sbellard int flags) 1396dbad63eSbellard { 140f4beb510Sbellard unsigned int e1, e2; 14153a5960aSpbrook uint32_t *p; 1426dbad63eSbellard e1 = (addr << 16) | (limit & 0xffff); 1436dbad63eSbellard e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); 144f4beb510Sbellard e2 |= flags; 14553a5960aSpbrook p = ptr; 14653a5960aSpbrook p[0] = tswapl(e1); 14753a5960aSpbrook p[1] = tswapl(e2); 148f4beb510Sbellard } 149f4beb510Sbellard 150f4beb510Sbellard static void set_gate(void *ptr, unsigned int type, unsigned int dpl, 151f4beb510Sbellard unsigned long addr, unsigned int sel) 152f4beb510Sbellard { 153f4beb510Sbellard unsigned int e1, e2; 15453a5960aSpbrook uint32_t *p; 155f4beb510Sbellard e1 = (addr & 0xffff) | (sel << 16); 156f4beb510Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 15753a5960aSpbrook p = ptr; 15853a5960aSpbrook p[0] = tswapl(e1); 15953a5960aSpbrook p[1] = tswapl(e2); 1606dbad63eSbellard } 1616dbad63eSbellard 1626dbad63eSbellard uint64_t gdt_table[6]; 163f4beb510Sbellard uint64_t idt_table[256]; 164f4beb510Sbellard 165f4beb510Sbellard /* only dpl matters as we do only user space emulation */ 166f4beb510Sbellard static void set_idt(int n, unsigned int dpl) 167f4beb510Sbellard { 168f4beb510Sbellard set_gate(idt_table + n, 0, dpl, 0, 0); 169f4beb510Sbellard } 17031e31b8aSbellard 17189e957e7Sbellard void cpu_loop(CPUX86State *env) 172bc8a22ccSbellard { 173bc8a22ccSbellard int trapnr; 174992f48a0Sblueswir1 abi_ulong pc; 175bc8a22ccSbellard target_siginfo_t info; 176bc8a22ccSbellard 177bc8a22ccSbellard for(;;) { 178bc8a22ccSbellard trapnr = cpu_x86_exec(env); 179bc8a22ccSbellard switch(trapnr) { 180f4beb510Sbellard case 0x80: 181f4beb510Sbellard /* linux syscall */ 1821b6b029eSbellard env->regs[R_EAX] = do_syscall(env, 1831b6b029eSbellard env->regs[R_EAX], 1841b6b029eSbellard env->regs[R_EBX], 1851b6b029eSbellard env->regs[R_ECX], 1861b6b029eSbellard env->regs[R_EDX], 1871b6b029eSbellard env->regs[R_ESI], 1881b6b029eSbellard env->regs[R_EDI], 1891b6b029eSbellard env->regs[R_EBP]); 190f4beb510Sbellard break; 191f4beb510Sbellard case EXCP0B_NOSEG: 192f4beb510Sbellard case EXCP0C_STACK: 193f4beb510Sbellard info.si_signo = SIGBUS; 194f4beb510Sbellard info.si_errno = 0; 195f4beb510Sbellard info.si_code = TARGET_SI_KERNEL; 196f4beb510Sbellard info._sifields._sigfault._addr = 0; 197f4beb510Sbellard queue_signal(info.si_signo, &info); 198f4beb510Sbellard break; 199f4beb510Sbellard case EXCP0D_GPF: 20084409ddbSj_mayer #ifndef TARGET_X86_64 201f4beb510Sbellard if (env->eflags & VM_MASK) { 202f4beb510Sbellard handle_vm86_fault(env); 20384409ddbSj_mayer } else 20484409ddbSj_mayer #endif 20584409ddbSj_mayer { 2069de5e440Sbellard info.si_signo = SIGSEGV; 2079de5e440Sbellard info.si_errno = 0; 208b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 2099de5e440Sbellard info._sifields._sigfault._addr = 0; 2109de5e440Sbellard queue_signal(info.si_signo, &info); 2111b6b029eSbellard } 2121b6b029eSbellard break; 213b689bc57Sbellard case EXCP0E_PAGE: 214b689bc57Sbellard info.si_signo = SIGSEGV; 215b689bc57Sbellard info.si_errno = 0; 216b689bc57Sbellard if (!(env->error_code & 1)) 217b689bc57Sbellard info.si_code = TARGET_SEGV_MAPERR; 218b689bc57Sbellard else 219b689bc57Sbellard info.si_code = TARGET_SEGV_ACCERR; 220970a87a6Sbellard info._sifields._sigfault._addr = env->cr[2]; 221b689bc57Sbellard queue_signal(info.si_signo, &info); 222b689bc57Sbellard break; 2239de5e440Sbellard case EXCP00_DIVZ: 22484409ddbSj_mayer #ifndef TARGET_X86_64 225bc8a22ccSbellard if (env->eflags & VM_MASK) { 226447db213Sbellard handle_vm86_trap(env, trapnr); 22784409ddbSj_mayer } else 22884409ddbSj_mayer #endif 22984409ddbSj_mayer { 2309de5e440Sbellard /* division by zero */ 2319de5e440Sbellard info.si_signo = SIGFPE; 2329de5e440Sbellard info.si_errno = 0; 2339de5e440Sbellard info.si_code = TARGET_FPE_INTDIV; 2349de5e440Sbellard info._sifields._sigfault._addr = env->eip; 2359de5e440Sbellard queue_signal(info.si_signo, &info); 236bc8a22ccSbellard } 2379de5e440Sbellard break; 238447db213Sbellard case EXCP01_SSTP: 239447db213Sbellard case EXCP03_INT3: 24084409ddbSj_mayer #ifndef TARGET_X86_64 241447db213Sbellard if (env->eflags & VM_MASK) { 242447db213Sbellard handle_vm86_trap(env, trapnr); 24384409ddbSj_mayer } else 24484409ddbSj_mayer #endif 24584409ddbSj_mayer { 246447db213Sbellard info.si_signo = SIGTRAP; 247447db213Sbellard info.si_errno = 0; 248447db213Sbellard if (trapnr == EXCP01_SSTP) { 249447db213Sbellard info.si_code = TARGET_TRAP_BRKPT; 250447db213Sbellard info._sifields._sigfault._addr = env->eip; 251447db213Sbellard } else { 252447db213Sbellard info.si_code = TARGET_SI_KERNEL; 253447db213Sbellard info._sifields._sigfault._addr = 0; 254447db213Sbellard } 255447db213Sbellard queue_signal(info.si_signo, &info); 256447db213Sbellard } 257447db213Sbellard break; 2589de5e440Sbellard case EXCP04_INTO: 2599de5e440Sbellard case EXCP05_BOUND: 26084409ddbSj_mayer #ifndef TARGET_X86_64 261bc8a22ccSbellard if (env->eflags & VM_MASK) { 262447db213Sbellard handle_vm86_trap(env, trapnr); 26384409ddbSj_mayer } else 26484409ddbSj_mayer #endif 26584409ddbSj_mayer { 2669de5e440Sbellard info.si_signo = SIGSEGV; 2679de5e440Sbellard info.si_errno = 0; 268b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 2699de5e440Sbellard info._sifields._sigfault._addr = 0; 2709de5e440Sbellard queue_signal(info.si_signo, &info); 271bc8a22ccSbellard } 2729de5e440Sbellard break; 2739de5e440Sbellard case EXCP06_ILLOP: 2749de5e440Sbellard info.si_signo = SIGILL; 2759de5e440Sbellard info.si_errno = 0; 2769de5e440Sbellard info.si_code = TARGET_ILL_ILLOPN; 2779de5e440Sbellard info._sifields._sigfault._addr = env->eip; 2789de5e440Sbellard queue_signal(info.si_signo, &info); 2799de5e440Sbellard break; 2809de5e440Sbellard case EXCP_INTERRUPT: 2819de5e440Sbellard /* just indicate that signals should be handled asap */ 2829de5e440Sbellard break; 2831fddef4bSbellard case EXCP_DEBUG: 2841fddef4bSbellard { 2851fddef4bSbellard int sig; 2861fddef4bSbellard 2871fddef4bSbellard sig = gdb_handlesig (env, TARGET_SIGTRAP); 2881fddef4bSbellard if (sig) 2891fddef4bSbellard { 2901fddef4bSbellard info.si_signo = sig; 2911fddef4bSbellard info.si_errno = 0; 2921fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 2931fddef4bSbellard queue_signal(info.si_signo, &info); 2941fddef4bSbellard } 2951fddef4bSbellard } 2961fddef4bSbellard break; 2971b6b029eSbellard default: 298970a87a6Sbellard pc = env->segs[R_CS].base + env->eip; 299bc8a22ccSbellard fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", 300bc8a22ccSbellard (long)pc, trapnr); 3011b6b029eSbellard abort(); 3021b6b029eSbellard } 30366fb9763Sbellard process_pending_signals(env); 3041b6b029eSbellard } 3051b6b029eSbellard } 306b346ff46Sbellard #endif 307b346ff46Sbellard 308b346ff46Sbellard #ifdef TARGET_ARM 309b346ff46Sbellard 3106f1f31c0Sbellard /* XXX: find a better solution */ 311992f48a0Sblueswir1 extern void tb_invalidate_page_range(abi_ulong start, abi_ulong end); 3126f1f31c0Sbellard 313992f48a0Sblueswir1 static void arm_cache_flush(abi_ulong start, abi_ulong last) 3146f1f31c0Sbellard { 315992f48a0Sblueswir1 abi_ulong addr, last1; 3166f1f31c0Sbellard 3176f1f31c0Sbellard if (last < start) 3186f1f31c0Sbellard return; 3196f1f31c0Sbellard addr = start; 3206f1f31c0Sbellard for(;;) { 3216f1f31c0Sbellard last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1; 3226f1f31c0Sbellard if (last1 > last) 3236f1f31c0Sbellard last1 = last; 3246f1f31c0Sbellard tb_invalidate_page_range(addr, last1 + 1); 3256f1f31c0Sbellard if (last1 == last) 3266f1f31c0Sbellard break; 3276f1f31c0Sbellard addr = last1 + 1; 3286f1f31c0Sbellard } 3296f1f31c0Sbellard } 3306f1f31c0Sbellard 331b346ff46Sbellard void cpu_loop(CPUARMState *env) 332b346ff46Sbellard { 333b346ff46Sbellard int trapnr; 334b346ff46Sbellard unsigned int n, insn; 335b346ff46Sbellard target_siginfo_t info; 336b5ff1b31Sbellard uint32_t addr; 337b346ff46Sbellard 338b346ff46Sbellard for(;;) { 339b346ff46Sbellard trapnr = cpu_arm_exec(env); 340b346ff46Sbellard switch(trapnr) { 341b346ff46Sbellard case EXCP_UDEF: 342c6981055Sbellard { 343c6981055Sbellard TaskState *ts = env->opaque; 344c6981055Sbellard uint32_t opcode; 345c6981055Sbellard 346c6981055Sbellard /* we handle the FPU emulation here, as Linux */ 347c6981055Sbellard /* we get the opcode */ 34853a5960aSpbrook opcode = tget32(env->regs[15]); 349c6981055Sbellard 35019b045deSpbrook if (EmulateAll(opcode, &ts->fpa, env) == 0) { 351b346ff46Sbellard info.si_signo = SIGILL; 352b346ff46Sbellard info.si_errno = 0; 353b346ff46Sbellard info.si_code = TARGET_ILL_ILLOPN; 354b346ff46Sbellard info._sifields._sigfault._addr = env->regs[15]; 355b346ff46Sbellard queue_signal(info.si_signo, &info); 356c6981055Sbellard } else { 357c6981055Sbellard /* increment PC */ 358c6981055Sbellard env->regs[15] += 4; 359c6981055Sbellard } 360c6981055Sbellard } 361b346ff46Sbellard break; 362b346ff46Sbellard case EXCP_SWI: 36306c949e6Spbrook case EXCP_BKPT: 364b346ff46Sbellard { 365ce4defa0Spbrook env->eabi = 1; 366b346ff46Sbellard /* system call */ 36706c949e6Spbrook if (trapnr == EXCP_BKPT) { 36806c949e6Spbrook if (env->thumb) { 36953a5960aSpbrook insn = tget16(env->regs[15]); 37006c949e6Spbrook n = insn & 0xff; 37106c949e6Spbrook env->regs[15] += 2; 37206c949e6Spbrook } else { 37353a5960aSpbrook insn = tget32(env->regs[15]); 37406c949e6Spbrook n = (insn & 0xf) | ((insn >> 4) & 0xff0); 37506c949e6Spbrook env->regs[15] += 4; 37606c949e6Spbrook } 37706c949e6Spbrook } else { 378192c7bd9Sbellard if (env->thumb) { 37953a5960aSpbrook insn = tget16(env->regs[15] - 2); 380192c7bd9Sbellard n = insn & 0xff; 381192c7bd9Sbellard } else { 38253a5960aSpbrook insn = tget32(env->regs[15] - 4); 383b346ff46Sbellard n = insn & 0xffffff; 384192c7bd9Sbellard } 38506c949e6Spbrook } 386192c7bd9Sbellard 3876f1f31c0Sbellard if (n == ARM_NR_cacheflush) { 3886f1f31c0Sbellard arm_cache_flush(env->regs[0], env->regs[1]); 389a4f81979Sbellard } else if (n == ARM_NR_semihosting 390a4f81979Sbellard || n == ARM_NR_thumb_semihosting) { 391a4f81979Sbellard env->regs[0] = do_arm_semihosting (env); 392ce4defa0Spbrook } else if (n == 0 || n >= ARM_SYSCALL_BASE 393192c7bd9Sbellard || (env->thumb && n == ARM_THUMB_SYSCALL)) { 394b346ff46Sbellard /* linux syscall */ 395ce4defa0Spbrook if (env->thumb || n == 0) { 396192c7bd9Sbellard n = env->regs[7]; 397192c7bd9Sbellard } else { 398b346ff46Sbellard n -= ARM_SYSCALL_BASE; 399ce4defa0Spbrook env->eabi = 0; 400192c7bd9Sbellard } 401b346ff46Sbellard env->regs[0] = do_syscall(env, 402b346ff46Sbellard n, 403b346ff46Sbellard env->regs[0], 404b346ff46Sbellard env->regs[1], 405b346ff46Sbellard env->regs[2], 406b346ff46Sbellard env->regs[3], 407b346ff46Sbellard env->regs[4], 408e1a2849cSbellard env->regs[5]); 409b346ff46Sbellard } else { 410b346ff46Sbellard goto error; 411b346ff46Sbellard } 412b346ff46Sbellard } 413b346ff46Sbellard break; 41443fff238Sbellard case EXCP_INTERRUPT: 41543fff238Sbellard /* just indicate that signals should be handled asap */ 41643fff238Sbellard break; 41768016c62Sbellard case EXCP_PREFETCH_ABORT: 418b5ff1b31Sbellard addr = env->cp15.c6_data; 419b5ff1b31Sbellard goto do_segv; 42068016c62Sbellard case EXCP_DATA_ABORT: 421b5ff1b31Sbellard addr = env->cp15.c6_insn; 422b5ff1b31Sbellard goto do_segv; 423b5ff1b31Sbellard do_segv: 42468016c62Sbellard { 42568016c62Sbellard info.si_signo = SIGSEGV; 42668016c62Sbellard info.si_errno = 0; 42768016c62Sbellard /* XXX: check env->error_code */ 42868016c62Sbellard info.si_code = TARGET_SEGV_MAPERR; 429b5ff1b31Sbellard info._sifields._sigfault._addr = addr; 43068016c62Sbellard queue_signal(info.si_signo, &info); 43168016c62Sbellard } 43268016c62Sbellard break; 4331fddef4bSbellard case EXCP_DEBUG: 4341fddef4bSbellard { 4351fddef4bSbellard int sig; 4361fddef4bSbellard 4371fddef4bSbellard sig = gdb_handlesig (env, TARGET_SIGTRAP); 4381fddef4bSbellard if (sig) 4391fddef4bSbellard { 4401fddef4bSbellard info.si_signo = sig; 4411fddef4bSbellard info.si_errno = 0; 4421fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 4431fddef4bSbellard queue_signal(info.si_signo, &info); 4441fddef4bSbellard } 4451fddef4bSbellard } 4461fddef4bSbellard break; 447b346ff46Sbellard default: 448b346ff46Sbellard error: 449b346ff46Sbellard fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 450b346ff46Sbellard trapnr); 4517fe48483Sbellard cpu_dump_state(env, stderr, fprintf, 0); 452b346ff46Sbellard abort(); 453b346ff46Sbellard } 454b346ff46Sbellard process_pending_signals(env); 455b346ff46Sbellard } 456b346ff46Sbellard } 457b346ff46Sbellard 458b346ff46Sbellard #endif 4591b6b029eSbellard 46093ac68bcSbellard #ifdef TARGET_SPARC 46193ac68bcSbellard 462060366c5Sbellard //#define DEBUG_WIN 463060366c5Sbellard 4642623cbafSbellard /* WARNING: dealing with register windows _is_ complicated. More info 4652623cbafSbellard can be found at http://www.sics.se/~psm/sparcstack.html */ 466060366c5Sbellard static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 467060366c5Sbellard { 468060366c5Sbellard index = (index + cwp * 16) & (16 * NWINDOWS - 1); 469060366c5Sbellard /* wrap handling : if cwp is on the last window, then we use the 470060366c5Sbellard registers 'after' the end */ 471060366c5Sbellard if (index < 8 && env->cwp == (NWINDOWS - 1)) 472060366c5Sbellard index += (16 * NWINDOWS); 473060366c5Sbellard return index; 474060366c5Sbellard } 475060366c5Sbellard 4762623cbafSbellard /* save the register window 'cwp1' */ 4772623cbafSbellard static inline void save_window_offset(CPUSPARCState *env, int cwp1) 478060366c5Sbellard { 4792623cbafSbellard unsigned int i; 480992f48a0Sblueswir1 abi_ulong sp_ptr; 481060366c5Sbellard 48253a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 483060366c5Sbellard #if defined(DEBUG_WIN) 484060366c5Sbellard printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n", 485060366c5Sbellard (int)sp_ptr, cwp1); 486060366c5Sbellard #endif 4872623cbafSbellard for(i = 0; i < 16; i++) { 48853a5960aSpbrook tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]); 489992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 4902623cbafSbellard } 491060366c5Sbellard } 492060366c5Sbellard 493060366c5Sbellard static void save_window(CPUSPARCState *env) 494060366c5Sbellard { 4955ef54116Sbellard #ifndef TARGET_SPARC64 4962623cbafSbellard unsigned int new_wim; 4972623cbafSbellard new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) & 4982623cbafSbellard ((1LL << NWINDOWS) - 1); 4992623cbafSbellard save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1)); 5002623cbafSbellard env->wim = new_wim; 5015ef54116Sbellard #else 5025ef54116Sbellard save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1)); 5035ef54116Sbellard env->cansave++; 5045ef54116Sbellard env->canrestore--; 5055ef54116Sbellard #endif 506060366c5Sbellard } 507060366c5Sbellard 508060366c5Sbellard static void restore_window(CPUSPARCState *env) 509060366c5Sbellard { 510060366c5Sbellard unsigned int new_wim, i, cwp1; 511992f48a0Sblueswir1 abi_ulong sp_ptr; 512060366c5Sbellard 513060366c5Sbellard new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) & 514060366c5Sbellard ((1LL << NWINDOWS) - 1); 515060366c5Sbellard 516060366c5Sbellard /* restore the invalid window */ 517060366c5Sbellard cwp1 = (env->cwp + 1) & (NWINDOWS - 1); 51853a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 519060366c5Sbellard #if defined(DEBUG_WIN) 520060366c5Sbellard printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n", 521060366c5Sbellard (int)sp_ptr, cwp1); 522060366c5Sbellard #endif 5232623cbafSbellard for(i = 0; i < 16; i++) { 52453a5960aSpbrook env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr); 525992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 5262623cbafSbellard } 527060366c5Sbellard env->wim = new_wim; 5285ef54116Sbellard #ifdef TARGET_SPARC64 5295ef54116Sbellard env->canrestore++; 5305ef54116Sbellard if (env->cleanwin < NWINDOWS - 1) 5315ef54116Sbellard env->cleanwin++; 5325ef54116Sbellard env->cansave--; 5335ef54116Sbellard #endif 534060366c5Sbellard } 535060366c5Sbellard 536060366c5Sbellard static void flush_windows(CPUSPARCState *env) 537060366c5Sbellard { 538060366c5Sbellard int offset, cwp1; 5392623cbafSbellard 5402623cbafSbellard offset = 1; 541060366c5Sbellard for(;;) { 542060366c5Sbellard /* if restore would invoke restore_window(), then we can stop */ 5432623cbafSbellard cwp1 = (env->cwp + offset) & (NWINDOWS - 1); 544060366c5Sbellard if (env->wim & (1 << cwp1)) 545060366c5Sbellard break; 5462623cbafSbellard save_window_offset(env, cwp1); 547060366c5Sbellard offset++; 548060366c5Sbellard } 5492623cbafSbellard /* set wim so that restore will reload the registers */ 5502623cbafSbellard cwp1 = (env->cwp + 1) & (NWINDOWS - 1); 5512623cbafSbellard env->wim = 1 << cwp1; 5522623cbafSbellard #if defined(DEBUG_WIN) 5532623cbafSbellard printf("flush_windows: nb=%d\n", offset - 1); 55480a9d035Sbellard #endif 5552623cbafSbellard } 556060366c5Sbellard 55793ac68bcSbellard void cpu_loop (CPUSPARCState *env) 55893ac68bcSbellard { 559060366c5Sbellard int trapnr, ret; 56061ff6f58Sbellard target_siginfo_t info; 56193ac68bcSbellard 56293ac68bcSbellard while (1) { 56393ac68bcSbellard trapnr = cpu_sparc_exec (env); 56493ac68bcSbellard 56593ac68bcSbellard switch (trapnr) { 5665ef54116Sbellard #ifndef TARGET_SPARC64 567060366c5Sbellard case 0x88: 568060366c5Sbellard case 0x90: 5695ef54116Sbellard #else 570cb33da57Sblueswir1 case 0x110: 5715ef54116Sbellard case 0x16d: 5725ef54116Sbellard #endif 573060366c5Sbellard ret = do_syscall (env, env->gregs[1], 574060366c5Sbellard env->regwptr[0], env->regwptr[1], 575060366c5Sbellard env->regwptr[2], env->regwptr[3], 576060366c5Sbellard env->regwptr[4], env->regwptr[5]); 577060366c5Sbellard if ((unsigned int)ret >= (unsigned int)(-515)) { 578992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 57927908725Sbellard env->xcc |= PSR_CARRY; 58027908725Sbellard #else 58193ac68bcSbellard env->psr |= PSR_CARRY; 58227908725Sbellard #endif 583060366c5Sbellard ret = -ret; 584060366c5Sbellard } else { 585992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 58627908725Sbellard env->xcc &= ~PSR_CARRY; 58727908725Sbellard #else 588060366c5Sbellard env->psr &= ~PSR_CARRY; 58927908725Sbellard #endif 590060366c5Sbellard } 591060366c5Sbellard env->regwptr[0] = ret; 592060366c5Sbellard /* next instruction */ 593060366c5Sbellard env->pc = env->npc; 594060366c5Sbellard env->npc = env->npc + 4; 595060366c5Sbellard break; 596060366c5Sbellard case 0x83: /* flush windows */ 597992f48a0Sblueswir1 #ifdef TARGET_ABI32 598992f48a0Sblueswir1 case 0x103: 599992f48a0Sblueswir1 #endif 6002623cbafSbellard flush_windows(env); 601060366c5Sbellard /* next instruction */ 602060366c5Sbellard env->pc = env->npc; 603060366c5Sbellard env->npc = env->npc + 4; 604060366c5Sbellard break; 6053475187dSbellard #ifndef TARGET_SPARC64 606060366c5Sbellard case TT_WIN_OVF: /* window overflow */ 607060366c5Sbellard save_window(env); 608060366c5Sbellard break; 609060366c5Sbellard case TT_WIN_UNF: /* window underflow */ 610060366c5Sbellard restore_window(env); 61193ac68bcSbellard break; 61261ff6f58Sbellard case TT_TFAULT: 61361ff6f58Sbellard case TT_DFAULT: 61461ff6f58Sbellard { 61561ff6f58Sbellard info.si_signo = SIGSEGV; 61661ff6f58Sbellard info.si_errno = 0; 61761ff6f58Sbellard /* XXX: check env->error_code */ 61861ff6f58Sbellard info.si_code = TARGET_SEGV_MAPERR; 61961ff6f58Sbellard info._sifields._sigfault._addr = env->mmuregs[4]; 62061ff6f58Sbellard queue_signal(info.si_signo, &info); 62161ff6f58Sbellard } 62261ff6f58Sbellard break; 6233475187dSbellard #else 6245ef54116Sbellard case TT_SPILL: /* window overflow */ 6255ef54116Sbellard save_window(env); 6265ef54116Sbellard break; 6275ef54116Sbellard case TT_FILL: /* window underflow */ 6285ef54116Sbellard restore_window(env); 6295ef54116Sbellard break; 6307f84a729Sblueswir1 case TT_TFAULT: 6317f84a729Sblueswir1 case TT_DFAULT: 6327f84a729Sblueswir1 { 6337f84a729Sblueswir1 info.si_signo = SIGSEGV; 6347f84a729Sblueswir1 info.si_errno = 0; 6357f84a729Sblueswir1 /* XXX: check env->error_code */ 6367f84a729Sblueswir1 info.si_code = TARGET_SEGV_MAPERR; 6377f84a729Sblueswir1 if (trapnr == TT_DFAULT) 6387f84a729Sblueswir1 info._sifields._sigfault._addr = env->dmmuregs[4]; 6397f84a729Sblueswir1 else 6407f84a729Sblueswir1 info._sifields._sigfault._addr = env->tpc[env->tl]; 6417f84a729Sblueswir1 queue_signal(info.si_signo, &info); 6427f84a729Sblueswir1 } 6437f84a729Sblueswir1 break; 644*27524dc3Sbellard #ifndef TARGET_ABI32 6455bfb56b2Sblueswir1 case 0x16e: 6465bfb56b2Sblueswir1 flush_windows(env); 6475bfb56b2Sblueswir1 sparc64_get_context(env); 6485bfb56b2Sblueswir1 break; 6495bfb56b2Sblueswir1 case 0x16f: 6505bfb56b2Sblueswir1 flush_windows(env); 6515bfb56b2Sblueswir1 sparc64_set_context(env); 6525bfb56b2Sblueswir1 break; 6533475187dSbellard #endif 654*27524dc3Sbellard #endif 65548dc41ebSbellard case EXCP_INTERRUPT: 65648dc41ebSbellard /* just indicate that signals should be handled asap */ 657e80cfcfcSbellard break; 6581fddef4bSbellard case EXCP_DEBUG: 6591fddef4bSbellard { 6601fddef4bSbellard int sig; 6611fddef4bSbellard 6621fddef4bSbellard sig = gdb_handlesig (env, TARGET_SIGTRAP); 6631fddef4bSbellard if (sig) 6641fddef4bSbellard { 6651fddef4bSbellard info.si_signo = sig; 6661fddef4bSbellard info.si_errno = 0; 6671fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 6681fddef4bSbellard queue_signal(info.si_signo, &info); 6691fddef4bSbellard } 6701fddef4bSbellard } 6711fddef4bSbellard break; 67293ac68bcSbellard default: 673060366c5Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 6747fe48483Sbellard cpu_dump_state(env, stderr, fprintf, 0); 67593ac68bcSbellard exit (1); 67693ac68bcSbellard } 67793ac68bcSbellard process_pending_signals (env); 67893ac68bcSbellard } 67993ac68bcSbellard } 68093ac68bcSbellard 68193ac68bcSbellard #endif 68293ac68bcSbellard 68367867308Sbellard #ifdef TARGET_PPC 6849fddaa0cSbellard static inline uint64_t cpu_ppc_get_tb (CPUState *env) 6859fddaa0cSbellard { 6869fddaa0cSbellard /* TO FIX */ 6879fddaa0cSbellard return 0; 6889fddaa0cSbellard } 6899fddaa0cSbellard 6909fddaa0cSbellard uint32_t cpu_ppc_load_tbl (CPUState *env) 6919fddaa0cSbellard { 6929fddaa0cSbellard return cpu_ppc_get_tb(env) & 0xFFFFFFFF; 6939fddaa0cSbellard } 6949fddaa0cSbellard 6959fddaa0cSbellard uint32_t cpu_ppc_load_tbu (CPUState *env) 6969fddaa0cSbellard { 6979fddaa0cSbellard return cpu_ppc_get_tb(env) >> 32; 6989fddaa0cSbellard } 6999fddaa0cSbellard 700a062e36cSj_mayer uint32_t cpu_ppc_load_atbl (CPUState *env) 7019fddaa0cSbellard { 702a062e36cSj_mayer return cpu_ppc_get_tb(env) & 0xFFFFFFFF; 7039fddaa0cSbellard } 7049fddaa0cSbellard 705a062e36cSj_mayer uint32_t cpu_ppc_load_atbu (CPUState *env) 7069fddaa0cSbellard { 707a062e36cSj_mayer return cpu_ppc_get_tb(env) >> 32; 7089fddaa0cSbellard } 7099fddaa0cSbellard 71076a66253Sj_mayer uint32_t cpu_ppc601_load_rtcu (CPUState *env) 71176a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_load_tbu") )); 71276a66253Sj_mayer 71376a66253Sj_mayer uint32_t cpu_ppc601_load_rtcl (CPUState *env) 7149fddaa0cSbellard { 71576a66253Sj_mayer return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 7169fddaa0cSbellard } 7179fddaa0cSbellard 718a750fc0bSj_mayer /* XXX: to be fixed */ 719a750fc0bSj_mayer int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp) 720a750fc0bSj_mayer { 721a750fc0bSj_mayer return -1; 722a750fc0bSj_mayer } 723a750fc0bSj_mayer 724a750fc0bSj_mayer int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val) 725a750fc0bSj_mayer { 726a750fc0bSj_mayer return -1; 727a750fc0bSj_mayer } 728a750fc0bSj_mayer 729e1833e1fSj_mayer #define EXCP_DUMP(env, fmt, args...) \ 730e1833e1fSj_mayer do { \ 731e1833e1fSj_mayer fprintf(stderr, fmt , ##args); \ 732e1833e1fSj_mayer cpu_dump_state(env, stderr, fprintf, 0); \ 733e1833e1fSj_mayer if (loglevel != 0) { \ 734e1833e1fSj_mayer fprintf(logfile, fmt , ##args); \ 735e1833e1fSj_mayer cpu_dump_state(env, logfile, fprintf, 0); \ 736e1833e1fSj_mayer } \ 737e1833e1fSj_mayer } while (0) 738e1833e1fSj_mayer 73967867308Sbellard void cpu_loop(CPUPPCState *env) 74067867308Sbellard { 74167867308Sbellard target_siginfo_t info; 74261190b14Sbellard int trapnr; 74361190b14Sbellard uint32_t ret; 74467867308Sbellard 74567867308Sbellard for(;;) { 74667867308Sbellard trapnr = cpu_ppc_exec(env); 74767867308Sbellard switch(trapnr) { 748e1833e1fSj_mayer case POWERPC_EXCP_NONE: 749e1833e1fSj_mayer /* Just go on */ 75067867308Sbellard break; 751e1833e1fSj_mayer case POWERPC_EXCP_CRITICAL: /* Critical input */ 752e1833e1fSj_mayer cpu_abort(env, "Critical interrupt while in user mode. " 753e1833e1fSj_mayer "Aborting\n"); 754e1833e1fSj_mayer break; 755e1833e1fSj_mayer case POWERPC_EXCP_MCHECK: /* Machine check exception */ 756e1833e1fSj_mayer cpu_abort(env, "Machine check exception while in user mode. " 757e1833e1fSj_mayer "Aborting\n"); 758e1833e1fSj_mayer break; 759e1833e1fSj_mayer case POWERPC_EXCP_DSI: /* Data storage exception */ 760e1833e1fSj_mayer EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n", 761e1833e1fSj_mayer env->spr[SPR_DAR]); 762e1833e1fSj_mayer /* XXX: check this. Seems bugged */ 763e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 764e1833e1fSj_mayer case 0x40000000: 765e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 766e1833e1fSj_mayer info.si_errno = 0; 767e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 768e1833e1fSj_mayer break; 769e1833e1fSj_mayer case 0x04000000: 770e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 771e1833e1fSj_mayer info.si_errno = 0; 772e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 773e1833e1fSj_mayer break; 774e1833e1fSj_mayer case 0x08000000: 775e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 776e1833e1fSj_mayer info.si_errno = 0; 777e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 778e1833e1fSj_mayer break; 779e1833e1fSj_mayer default: 780e1833e1fSj_mayer /* Let's send a regular segfault... */ 781e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 782e1833e1fSj_mayer env->error_code); 783e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 784e1833e1fSj_mayer info.si_errno = 0; 785e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 786e1833e1fSj_mayer break; 787e1833e1fSj_mayer } 788e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip; 789e1833e1fSj_mayer queue_signal(info.si_signo, &info); 790e1833e1fSj_mayer break; 791e1833e1fSj_mayer case POWERPC_EXCP_ISI: /* Instruction storage exception */ 792e1833e1fSj_mayer EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n", 793f10c315fSj_mayer env->spr[SPR_SRR0]); 794e1833e1fSj_mayer /* XXX: check this */ 795e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 796e1833e1fSj_mayer case 0x40000000: 797e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 798e1833e1fSj_mayer info.si_errno = 0; 799e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 800e1833e1fSj_mayer break; 801e1833e1fSj_mayer case 0x10000000: 802e1833e1fSj_mayer case 0x08000000: 803e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 804e1833e1fSj_mayer info.si_errno = 0; 805e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 806e1833e1fSj_mayer break; 807e1833e1fSj_mayer default: 808e1833e1fSj_mayer /* Let's send a regular segfault... */ 809e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 810e1833e1fSj_mayer env->error_code); 811e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 812e1833e1fSj_mayer info.si_errno = 0; 813e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 814e1833e1fSj_mayer break; 815e1833e1fSj_mayer } 816e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 817e1833e1fSj_mayer queue_signal(info.si_signo, &info); 818e1833e1fSj_mayer break; 819e1833e1fSj_mayer case POWERPC_EXCP_EXTERNAL: /* External input */ 820e1833e1fSj_mayer cpu_abort(env, "External interrupt while in user mode. " 821e1833e1fSj_mayer "Aborting\n"); 822e1833e1fSj_mayer break; 823e1833e1fSj_mayer case POWERPC_EXCP_ALIGN: /* Alignment exception */ 824e1833e1fSj_mayer EXCP_DUMP(env, "Unaligned memory access\n"); 825e1833e1fSj_mayer /* XXX: check this */ 826e1833e1fSj_mayer info.si_signo = TARGET_SIGBUS; 827e1833e1fSj_mayer info.si_errno = 0; 828e1833e1fSj_mayer info.si_code = TARGET_BUS_ADRALN; 829e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 830e1833e1fSj_mayer queue_signal(info.si_signo, &info); 831e1833e1fSj_mayer break; 832e1833e1fSj_mayer case POWERPC_EXCP_PROGRAM: /* Program exception */ 833e1833e1fSj_mayer /* XXX: check this */ 834e1833e1fSj_mayer switch (env->error_code & ~0xF) { 835e1833e1fSj_mayer case POWERPC_EXCP_FP: 836e1833e1fSj_mayer EXCP_DUMP(env, "Floating point program exception\n"); 837e1833e1fSj_mayer info.si_signo = TARGET_SIGFPE; 838e1833e1fSj_mayer info.si_errno = 0; 839e1833e1fSj_mayer switch (env->error_code & 0xF) { 840e1833e1fSj_mayer case POWERPC_EXCP_FP_OX: 841e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTOVF; 842e1833e1fSj_mayer break; 843e1833e1fSj_mayer case POWERPC_EXCP_FP_UX: 844e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTUND; 845e1833e1fSj_mayer break; 846e1833e1fSj_mayer case POWERPC_EXCP_FP_ZX: 847e1833e1fSj_mayer case POWERPC_EXCP_FP_VXZDZ: 848e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTDIV; 849e1833e1fSj_mayer break; 850e1833e1fSj_mayer case POWERPC_EXCP_FP_XX: 851e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTRES; 852e1833e1fSj_mayer break; 853e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSOFT: 854e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTINV; 855e1833e1fSj_mayer break; 8567c58044cSj_mayer case POWERPC_EXCP_FP_VXSNAN: 857e1833e1fSj_mayer case POWERPC_EXCP_FP_VXISI: 858e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIDI: 859e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIMZ: 860e1833e1fSj_mayer case POWERPC_EXCP_FP_VXVC: 861e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSQRT: 862e1833e1fSj_mayer case POWERPC_EXCP_FP_VXCVI: 863e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTSUB; 864e1833e1fSj_mayer break; 865e1833e1fSj_mayer default: 866e1833e1fSj_mayer EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", 867e1833e1fSj_mayer env->error_code); 868e1833e1fSj_mayer break; 869e1833e1fSj_mayer } 870e1833e1fSj_mayer break; 871e1833e1fSj_mayer case POWERPC_EXCP_INVAL: 872e1833e1fSj_mayer EXCP_DUMP(env, "Invalid instruction\n"); 873e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 874e1833e1fSj_mayer info.si_errno = 0; 875e1833e1fSj_mayer switch (env->error_code & 0xF) { 876e1833e1fSj_mayer case POWERPC_EXCP_INVAL_INVAL: 877e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPC; 878e1833e1fSj_mayer break; 879e1833e1fSj_mayer case POWERPC_EXCP_INVAL_LSWX: 880e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPN; 881e1833e1fSj_mayer break; 882e1833e1fSj_mayer case POWERPC_EXCP_INVAL_SPR: 883e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 884e1833e1fSj_mayer break; 885e1833e1fSj_mayer case POWERPC_EXCP_INVAL_FP: 886e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 887e1833e1fSj_mayer break; 888e1833e1fSj_mayer default: 889e1833e1fSj_mayer EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", 890e1833e1fSj_mayer env->error_code & 0xF); 891e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 892e1833e1fSj_mayer break; 893e1833e1fSj_mayer } 894e1833e1fSj_mayer break; 895e1833e1fSj_mayer case POWERPC_EXCP_PRIV: 896e1833e1fSj_mayer EXCP_DUMP(env, "Privilege violation\n"); 897e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 898e1833e1fSj_mayer info.si_errno = 0; 899e1833e1fSj_mayer switch (env->error_code & 0xF) { 900e1833e1fSj_mayer case POWERPC_EXCP_PRIV_OPC: 901e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 902e1833e1fSj_mayer break; 903e1833e1fSj_mayer case POWERPC_EXCP_PRIV_REG: 904e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 905e1833e1fSj_mayer break; 906e1833e1fSj_mayer default: 907e1833e1fSj_mayer EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", 908e1833e1fSj_mayer env->error_code & 0xF); 909e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 910e1833e1fSj_mayer break; 911e1833e1fSj_mayer } 912e1833e1fSj_mayer break; 913e1833e1fSj_mayer case POWERPC_EXCP_TRAP: 914e1833e1fSj_mayer cpu_abort(env, "Tried to call a TRAP\n"); 915e1833e1fSj_mayer break; 916e1833e1fSj_mayer default: 917e1833e1fSj_mayer /* Should not happen ! */ 918e1833e1fSj_mayer cpu_abort(env, "Unknown program exception (%02x)\n", 919e1833e1fSj_mayer env->error_code); 920e1833e1fSj_mayer break; 921e1833e1fSj_mayer } 922e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 923e1833e1fSj_mayer queue_signal(info.si_signo, &info); 924e1833e1fSj_mayer break; 925e1833e1fSj_mayer case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 926e1833e1fSj_mayer EXCP_DUMP(env, "No floating point allowed\n"); 927e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 928e1833e1fSj_mayer info.si_errno = 0; 929e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 930e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 931e1833e1fSj_mayer queue_signal(info.si_signo, &info); 932e1833e1fSj_mayer break; 933e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL: /* System call exception */ 934e1833e1fSj_mayer cpu_abort(env, "Syscall exception while in user mode. " 935e1833e1fSj_mayer "Aborting\n"); 936e1833e1fSj_mayer break; 937e1833e1fSj_mayer case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 938e1833e1fSj_mayer EXCP_DUMP(env, "No APU instruction allowed\n"); 939e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 940e1833e1fSj_mayer info.si_errno = 0; 941e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 942e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 943e1833e1fSj_mayer queue_signal(info.si_signo, &info); 944e1833e1fSj_mayer break; 945e1833e1fSj_mayer case POWERPC_EXCP_DECR: /* Decrementer exception */ 946e1833e1fSj_mayer cpu_abort(env, "Decrementer interrupt while in user mode. " 947e1833e1fSj_mayer "Aborting\n"); 948e1833e1fSj_mayer break; 949e1833e1fSj_mayer case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 950e1833e1fSj_mayer cpu_abort(env, "Fix interval timer interrupt while in user mode. " 951e1833e1fSj_mayer "Aborting\n"); 952e1833e1fSj_mayer break; 953e1833e1fSj_mayer case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 954e1833e1fSj_mayer cpu_abort(env, "Watchdog timer interrupt while in user mode. " 955e1833e1fSj_mayer "Aborting\n"); 956e1833e1fSj_mayer break; 957e1833e1fSj_mayer case POWERPC_EXCP_DTLB: /* Data TLB error */ 958e1833e1fSj_mayer cpu_abort(env, "Data TLB exception while in user mode. " 959e1833e1fSj_mayer "Aborting\n"); 960e1833e1fSj_mayer break; 961e1833e1fSj_mayer case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 962e1833e1fSj_mayer cpu_abort(env, "Instruction TLB exception while in user mode. " 963e1833e1fSj_mayer "Aborting\n"); 964e1833e1fSj_mayer break; 965e1833e1fSj_mayer case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 966e1833e1fSj_mayer /* XXX: check this */ 967e1833e1fSj_mayer { 968e1833e1fSj_mayer int sig; 969e1833e1fSj_mayer 970e1833e1fSj_mayer sig = gdb_handlesig(env, TARGET_SIGTRAP); 971e1833e1fSj_mayer if (sig) { 972e1833e1fSj_mayer info.si_signo = sig; 973e1833e1fSj_mayer info.si_errno = 0; 974e1833e1fSj_mayer info.si_code = TARGET_TRAP_BRKPT; 975e1833e1fSj_mayer queue_signal(info.si_signo, &info); 976e1833e1fSj_mayer } 977e1833e1fSj_mayer } 978e1833e1fSj_mayer break; 979e1833e1fSj_mayer #if defined(TARGET_PPCEMB) 980e1833e1fSj_mayer case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 981e1833e1fSj_mayer EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); 982e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 983e1833e1fSj_mayer info.si_errno = 0; 984e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 985e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 986e1833e1fSj_mayer queue_signal(info.si_signo, &info); 987e1833e1fSj_mayer break; 988e1833e1fSj_mayer case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 989e1833e1fSj_mayer cpu_abort(env, "Embedded floating-point data IRQ not handled\n"); 990e1833e1fSj_mayer break; 991e1833e1fSj_mayer case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 992e1833e1fSj_mayer cpu_abort(env, "Embedded floating-point round IRQ not handled\n"); 993e1833e1fSj_mayer break; 994e1833e1fSj_mayer case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 995e1833e1fSj_mayer cpu_abort(env, "Performance monitor exception not handled\n"); 996e1833e1fSj_mayer break; 997e1833e1fSj_mayer case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 998e1833e1fSj_mayer cpu_abort(env, "Doorbell interrupt while in user mode. " 999e1833e1fSj_mayer "Aborting\n"); 1000e1833e1fSj_mayer break; 1001e1833e1fSj_mayer case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 1002e1833e1fSj_mayer cpu_abort(env, "Doorbell critical interrupt while in user mode. " 1003e1833e1fSj_mayer "Aborting\n"); 1004e1833e1fSj_mayer break; 1005e1833e1fSj_mayer case POWERPC_EXCP_RESET: /* System reset exception */ 1006e1833e1fSj_mayer cpu_abort(env, "Reset interrupt while in user mode. " 1007e1833e1fSj_mayer "Aborting\n"); 1008e1833e1fSj_mayer break; 1009e1833e1fSj_mayer #endif /* defined(TARGET_PPCEMB) */ 1010e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) /* PowerPC 64 */ 1011e1833e1fSj_mayer case POWERPC_EXCP_DSEG: /* Data segment exception */ 1012e1833e1fSj_mayer cpu_abort(env, "Data segment exception while in user mode. " 1013e1833e1fSj_mayer "Aborting\n"); 1014e1833e1fSj_mayer break; 1015e1833e1fSj_mayer case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 1016e1833e1fSj_mayer cpu_abort(env, "Instruction segment exception " 1017e1833e1fSj_mayer "while in user mode. Aborting\n"); 1018e1833e1fSj_mayer break; 1019e85e7c6eSj_mayer #endif /* defined(TARGET_PPC64) && !defined(TARGET_ABI32) */ 1020e85e7c6eSj_mayer #if defined(TARGET_PPC64H) && !defined(TARGET_ABI32) 1021e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1022e1833e1fSj_mayer case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 1023e1833e1fSj_mayer cpu_abort(env, "Hypervisor decrementer interrupt " 1024e1833e1fSj_mayer "while in user mode. Aborting\n"); 1025e1833e1fSj_mayer break; 1026e85e7c6eSj_mayer #endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */ 1027e1833e1fSj_mayer case POWERPC_EXCP_TRACE: /* Trace exception */ 1028e1833e1fSj_mayer /* Nothing to do: 1029e1833e1fSj_mayer * we use this exception to emulate step-by-step execution mode. 1030e1833e1fSj_mayer */ 1031e1833e1fSj_mayer break; 1032e85e7c6eSj_mayer #if defined(TARGET_PPC64H) && !defined(TARGET_ABI32) 1033e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1034e1833e1fSj_mayer case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 1035e1833e1fSj_mayer cpu_abort(env, "Hypervisor data storage exception " 1036e1833e1fSj_mayer "while in user mode. Aborting\n"); 1037e1833e1fSj_mayer break; 1038e1833e1fSj_mayer case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 1039e1833e1fSj_mayer cpu_abort(env, "Hypervisor instruction storage exception " 1040e1833e1fSj_mayer "while in user mode. Aborting\n"); 1041e1833e1fSj_mayer break; 1042e1833e1fSj_mayer case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 1043e1833e1fSj_mayer cpu_abort(env, "Hypervisor data segment exception " 1044e1833e1fSj_mayer "while in user mode. Aborting\n"); 1045e1833e1fSj_mayer break; 1046e1833e1fSj_mayer case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 1047e1833e1fSj_mayer cpu_abort(env, "Hypervisor instruction segment exception " 1048e1833e1fSj_mayer "while in user mode. Aborting\n"); 1049e1833e1fSj_mayer break; 1050e85e7c6eSj_mayer #endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */ 1051e1833e1fSj_mayer case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 1052e1833e1fSj_mayer EXCP_DUMP(env, "No Altivec instructions allowed\n"); 1053e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1054e1833e1fSj_mayer info.si_errno = 0; 1055e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1056e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1057e1833e1fSj_mayer queue_signal(info.si_signo, &info); 1058e1833e1fSj_mayer break; 1059e1833e1fSj_mayer case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 1060e1833e1fSj_mayer cpu_abort(env, "Programable interval timer interrupt " 1061e1833e1fSj_mayer "while in user mode. Aborting\n"); 1062e1833e1fSj_mayer break; 1063e1833e1fSj_mayer case POWERPC_EXCP_IO: /* IO error exception */ 1064e1833e1fSj_mayer cpu_abort(env, "IO error exception while in user mode. " 1065e1833e1fSj_mayer "Aborting\n"); 1066e1833e1fSj_mayer break; 1067e1833e1fSj_mayer case POWERPC_EXCP_RUNM: /* Run mode exception */ 1068e1833e1fSj_mayer cpu_abort(env, "Run mode exception while in user mode. " 1069e1833e1fSj_mayer "Aborting\n"); 1070e1833e1fSj_mayer break; 1071e1833e1fSj_mayer case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 1072e1833e1fSj_mayer cpu_abort(env, "Emulation trap exception not handled\n"); 1073e1833e1fSj_mayer break; 1074e1833e1fSj_mayer case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 1075e1833e1fSj_mayer cpu_abort(env, "Instruction fetch TLB exception " 1076e1833e1fSj_mayer "while in user-mode. Aborting"); 1077e1833e1fSj_mayer break; 1078e1833e1fSj_mayer case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 1079e1833e1fSj_mayer cpu_abort(env, "Data load TLB exception while in user-mode. " 1080e1833e1fSj_mayer "Aborting"); 1081e1833e1fSj_mayer break; 1082e1833e1fSj_mayer case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 1083e1833e1fSj_mayer cpu_abort(env, "Data store TLB exception while in user-mode. " 1084e1833e1fSj_mayer "Aborting"); 1085e1833e1fSj_mayer break; 1086e1833e1fSj_mayer case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 1087e1833e1fSj_mayer cpu_abort(env, "Floating-point assist exception not handled\n"); 1088e1833e1fSj_mayer break; 1089e1833e1fSj_mayer case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 1090e1833e1fSj_mayer cpu_abort(env, "Instruction address breakpoint exception " 1091e1833e1fSj_mayer "not handled\n"); 1092e1833e1fSj_mayer break; 1093e1833e1fSj_mayer case POWERPC_EXCP_SMI: /* System management interrupt */ 1094e1833e1fSj_mayer cpu_abort(env, "System management interrupt while in user mode. " 1095e1833e1fSj_mayer "Aborting\n"); 1096e1833e1fSj_mayer break; 1097e1833e1fSj_mayer case POWERPC_EXCP_THERM: /* Thermal interrupt */ 1098e1833e1fSj_mayer cpu_abort(env, "Thermal interrupt interrupt while in user mode. " 1099e1833e1fSj_mayer "Aborting\n"); 1100e1833e1fSj_mayer break; 1101e1833e1fSj_mayer case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 1102e1833e1fSj_mayer cpu_abort(env, "Performance monitor exception not handled\n"); 1103e1833e1fSj_mayer break; 1104e1833e1fSj_mayer case POWERPC_EXCP_VPUA: /* Vector assist exception */ 1105e1833e1fSj_mayer cpu_abort(env, "Vector assist exception not handled\n"); 1106e1833e1fSj_mayer break; 1107e1833e1fSj_mayer case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 1108e1833e1fSj_mayer cpu_abort(env, "Soft patch exception not handled\n"); 1109e1833e1fSj_mayer break; 1110e1833e1fSj_mayer case POWERPC_EXCP_MAINT: /* Maintenance exception */ 1111e1833e1fSj_mayer cpu_abort(env, "Maintenance exception while in user mode. " 1112e1833e1fSj_mayer "Aborting\n"); 1113e1833e1fSj_mayer break; 1114e1833e1fSj_mayer case POWERPC_EXCP_STOP: /* stop translation */ 1115e1833e1fSj_mayer /* We did invalidate the instruction cache. Go on */ 1116e1833e1fSj_mayer break; 1117e1833e1fSj_mayer case POWERPC_EXCP_BRANCH: /* branch instruction: */ 1118e1833e1fSj_mayer /* We just stopped because of a branch. Go on */ 1119e1833e1fSj_mayer break; 1120e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL_USER: 1121e1833e1fSj_mayer /* system call in user-mode emulation */ 112267867308Sbellard /* WARNING: 112367867308Sbellard * PPC ABI uses overflow flag in cr0 to signal an error 112467867308Sbellard * in syscalls. 112567867308Sbellard */ 112661190b14Sbellard #if 0 112761190b14Sbellard printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0], 112861190b14Sbellard env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]); 112961190b14Sbellard #endif 113067867308Sbellard env->crf[0] &= ~0x1; 113167867308Sbellard ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 113267867308Sbellard env->gpr[5], env->gpr[6], env->gpr[7], 113367867308Sbellard env->gpr[8]); 113467867308Sbellard if (ret > (uint32_t)(-515)) { 113567867308Sbellard env->crf[0] |= 0x1; 113667867308Sbellard ret = -ret; 113767867308Sbellard } 113867867308Sbellard env->gpr[3] = ret; 113961190b14Sbellard #if 0 114061190b14Sbellard printf("syscall returned 0x%08x (%d)\n", ret, ret); 114161190b14Sbellard #endif 114261190b14Sbellard break; 114356ba31ffSj_mayer case EXCP_INTERRUPT: 114456ba31ffSj_mayer /* just indicate that signals should be handled asap */ 114556ba31ffSj_mayer break; 114661190b14Sbellard default: 1147e1833e1fSj_mayer cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr); 114867867308Sbellard break; 114967867308Sbellard } 115067867308Sbellard process_pending_signals(env); 115167867308Sbellard } 115267867308Sbellard } 115367867308Sbellard #endif 115467867308Sbellard 1155048f6b4dSbellard #ifdef TARGET_MIPS 1156048f6b4dSbellard 1157048f6b4dSbellard #define MIPS_SYS(name, args) args, 1158048f6b4dSbellard 1159048f6b4dSbellard static const uint8_t mips_syscall_args[] = { 1160048f6b4dSbellard MIPS_SYS(sys_syscall , 0) /* 4000 */ 1161048f6b4dSbellard MIPS_SYS(sys_exit , 1) 1162048f6b4dSbellard MIPS_SYS(sys_fork , 0) 1163048f6b4dSbellard MIPS_SYS(sys_read , 3) 1164048f6b4dSbellard MIPS_SYS(sys_write , 3) 1165048f6b4dSbellard MIPS_SYS(sys_open , 3) /* 4005 */ 1166048f6b4dSbellard MIPS_SYS(sys_close , 1) 1167048f6b4dSbellard MIPS_SYS(sys_waitpid , 3) 1168048f6b4dSbellard MIPS_SYS(sys_creat , 2) 1169048f6b4dSbellard MIPS_SYS(sys_link , 2) 1170048f6b4dSbellard MIPS_SYS(sys_unlink , 1) /* 4010 */ 1171048f6b4dSbellard MIPS_SYS(sys_execve , 0) 1172048f6b4dSbellard MIPS_SYS(sys_chdir , 1) 1173048f6b4dSbellard MIPS_SYS(sys_time , 1) 1174048f6b4dSbellard MIPS_SYS(sys_mknod , 3) 1175048f6b4dSbellard MIPS_SYS(sys_chmod , 2) /* 4015 */ 1176048f6b4dSbellard MIPS_SYS(sys_lchown , 3) 1177048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1178048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */ 1179048f6b4dSbellard MIPS_SYS(sys_lseek , 3) 1180048f6b4dSbellard MIPS_SYS(sys_getpid , 0) /* 4020 */ 1181048f6b4dSbellard MIPS_SYS(sys_mount , 5) 1182048f6b4dSbellard MIPS_SYS(sys_oldumount , 1) 1183048f6b4dSbellard MIPS_SYS(sys_setuid , 1) 1184048f6b4dSbellard MIPS_SYS(sys_getuid , 0) 1185048f6b4dSbellard MIPS_SYS(sys_stime , 1) /* 4025 */ 1186048f6b4dSbellard MIPS_SYS(sys_ptrace , 4) 1187048f6b4dSbellard MIPS_SYS(sys_alarm , 1) 1188048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */ 1189048f6b4dSbellard MIPS_SYS(sys_pause , 0) 1190048f6b4dSbellard MIPS_SYS(sys_utime , 2) /* 4030 */ 1191048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1192048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1193048f6b4dSbellard MIPS_SYS(sys_access , 2) 1194048f6b4dSbellard MIPS_SYS(sys_nice , 1) 1195048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4035 */ 1196048f6b4dSbellard MIPS_SYS(sys_sync , 0) 1197048f6b4dSbellard MIPS_SYS(sys_kill , 2) 1198048f6b4dSbellard MIPS_SYS(sys_rename , 2) 1199048f6b4dSbellard MIPS_SYS(sys_mkdir , 2) 1200048f6b4dSbellard MIPS_SYS(sys_rmdir , 1) /* 4040 */ 1201048f6b4dSbellard MIPS_SYS(sys_dup , 1) 1202048f6b4dSbellard MIPS_SYS(sys_pipe , 0) 1203048f6b4dSbellard MIPS_SYS(sys_times , 1) 1204048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1205048f6b4dSbellard MIPS_SYS(sys_brk , 1) /* 4045 */ 1206048f6b4dSbellard MIPS_SYS(sys_setgid , 1) 1207048f6b4dSbellard MIPS_SYS(sys_getgid , 0) 1208048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */ 1209048f6b4dSbellard MIPS_SYS(sys_geteuid , 0) 1210048f6b4dSbellard MIPS_SYS(sys_getegid , 0) /* 4050 */ 1211048f6b4dSbellard MIPS_SYS(sys_acct , 0) 1212048f6b4dSbellard MIPS_SYS(sys_umount , 2) 1213048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1214048f6b4dSbellard MIPS_SYS(sys_ioctl , 3) 1215048f6b4dSbellard MIPS_SYS(sys_fcntl , 3) /* 4055 */ 1216048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 2) 1217048f6b4dSbellard MIPS_SYS(sys_setpgid , 2) 1218048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1219048f6b4dSbellard MIPS_SYS(sys_olduname , 1) 1220048f6b4dSbellard MIPS_SYS(sys_umask , 1) /* 4060 */ 1221048f6b4dSbellard MIPS_SYS(sys_chroot , 1) 1222048f6b4dSbellard MIPS_SYS(sys_ustat , 2) 1223048f6b4dSbellard MIPS_SYS(sys_dup2 , 2) 1224048f6b4dSbellard MIPS_SYS(sys_getppid , 0) 1225048f6b4dSbellard MIPS_SYS(sys_getpgrp , 0) /* 4065 */ 1226048f6b4dSbellard MIPS_SYS(sys_setsid , 0) 1227048f6b4dSbellard MIPS_SYS(sys_sigaction , 3) 1228048f6b4dSbellard MIPS_SYS(sys_sgetmask , 0) 1229048f6b4dSbellard MIPS_SYS(sys_ssetmask , 1) 1230048f6b4dSbellard MIPS_SYS(sys_setreuid , 2) /* 4070 */ 1231048f6b4dSbellard MIPS_SYS(sys_setregid , 2) 1232048f6b4dSbellard MIPS_SYS(sys_sigsuspend , 0) 1233048f6b4dSbellard MIPS_SYS(sys_sigpending , 1) 1234048f6b4dSbellard MIPS_SYS(sys_sethostname , 2) 1235048f6b4dSbellard MIPS_SYS(sys_setrlimit , 2) /* 4075 */ 1236048f6b4dSbellard MIPS_SYS(sys_getrlimit , 2) 1237048f6b4dSbellard MIPS_SYS(sys_getrusage , 2) 1238048f6b4dSbellard MIPS_SYS(sys_gettimeofday, 2) 1239048f6b4dSbellard MIPS_SYS(sys_settimeofday, 2) 1240048f6b4dSbellard MIPS_SYS(sys_getgroups , 2) /* 4080 */ 1241048f6b4dSbellard MIPS_SYS(sys_setgroups , 2) 1242048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* old_select */ 1243048f6b4dSbellard MIPS_SYS(sys_symlink , 2) 1244048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */ 1245048f6b4dSbellard MIPS_SYS(sys_readlink , 3) /* 4085 */ 1246048f6b4dSbellard MIPS_SYS(sys_uselib , 1) 1247048f6b4dSbellard MIPS_SYS(sys_swapon , 2) 1248048f6b4dSbellard MIPS_SYS(sys_reboot , 3) 1249048f6b4dSbellard MIPS_SYS(old_readdir , 3) 1250048f6b4dSbellard MIPS_SYS(old_mmap , 6) /* 4090 */ 1251048f6b4dSbellard MIPS_SYS(sys_munmap , 2) 1252048f6b4dSbellard MIPS_SYS(sys_truncate , 2) 1253048f6b4dSbellard MIPS_SYS(sys_ftruncate , 2) 1254048f6b4dSbellard MIPS_SYS(sys_fchmod , 2) 1255048f6b4dSbellard MIPS_SYS(sys_fchown , 3) /* 4095 */ 1256048f6b4dSbellard MIPS_SYS(sys_getpriority , 2) 1257048f6b4dSbellard MIPS_SYS(sys_setpriority , 3) 1258048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1259048f6b4dSbellard MIPS_SYS(sys_statfs , 2) 1260048f6b4dSbellard MIPS_SYS(sys_fstatfs , 2) /* 4100 */ 1261048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */ 1262048f6b4dSbellard MIPS_SYS(sys_socketcall , 2) 1263048f6b4dSbellard MIPS_SYS(sys_syslog , 3) 1264048f6b4dSbellard MIPS_SYS(sys_setitimer , 3) 1265048f6b4dSbellard MIPS_SYS(sys_getitimer , 2) /* 4105 */ 1266048f6b4dSbellard MIPS_SYS(sys_newstat , 2) 1267048f6b4dSbellard MIPS_SYS(sys_newlstat , 2) 1268048f6b4dSbellard MIPS_SYS(sys_newfstat , 2) 1269048f6b4dSbellard MIPS_SYS(sys_uname , 1) 1270048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */ 1271048f6b4dSbellard MIPS_SYS(sys_vhangup , 0) 1272048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */ 1273048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */ 1274048f6b4dSbellard MIPS_SYS(sys_wait4 , 4) 1275048f6b4dSbellard MIPS_SYS(sys_swapoff , 1) /* 4115 */ 1276048f6b4dSbellard MIPS_SYS(sys_sysinfo , 1) 1277048f6b4dSbellard MIPS_SYS(sys_ipc , 6) 1278048f6b4dSbellard MIPS_SYS(sys_fsync , 1) 1279048f6b4dSbellard MIPS_SYS(sys_sigreturn , 0) 1280048f6b4dSbellard MIPS_SYS(sys_clone , 0) /* 4120 */ 1281048f6b4dSbellard MIPS_SYS(sys_setdomainname, 2) 1282048f6b4dSbellard MIPS_SYS(sys_newuname , 1) 1283048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */ 1284048f6b4dSbellard MIPS_SYS(sys_adjtimex , 1) 1285048f6b4dSbellard MIPS_SYS(sys_mprotect , 3) /* 4125 */ 1286048f6b4dSbellard MIPS_SYS(sys_sigprocmask , 3) 1287048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was create_module */ 1288048f6b4dSbellard MIPS_SYS(sys_init_module , 5) 1289048f6b4dSbellard MIPS_SYS(sys_delete_module, 1) 1290048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */ 1291048f6b4dSbellard MIPS_SYS(sys_quotactl , 0) 1292048f6b4dSbellard MIPS_SYS(sys_getpgid , 1) 1293048f6b4dSbellard MIPS_SYS(sys_fchdir , 1) 1294048f6b4dSbellard MIPS_SYS(sys_bdflush , 2) 1295048f6b4dSbellard MIPS_SYS(sys_sysfs , 3) /* 4135 */ 1296048f6b4dSbellard MIPS_SYS(sys_personality , 1) 1297048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */ 1298048f6b4dSbellard MIPS_SYS(sys_setfsuid , 1) 1299048f6b4dSbellard MIPS_SYS(sys_setfsgid , 1) 1300048f6b4dSbellard MIPS_SYS(sys_llseek , 5) /* 4140 */ 1301048f6b4dSbellard MIPS_SYS(sys_getdents , 3) 1302048f6b4dSbellard MIPS_SYS(sys_select , 5) 1303048f6b4dSbellard MIPS_SYS(sys_flock , 2) 1304048f6b4dSbellard MIPS_SYS(sys_msync , 3) 1305048f6b4dSbellard MIPS_SYS(sys_readv , 3) /* 4145 */ 1306048f6b4dSbellard MIPS_SYS(sys_writev , 3) 1307048f6b4dSbellard MIPS_SYS(sys_cacheflush , 3) 1308048f6b4dSbellard MIPS_SYS(sys_cachectl , 3) 1309048f6b4dSbellard MIPS_SYS(sys_sysmips , 4) 1310048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4150 */ 1311048f6b4dSbellard MIPS_SYS(sys_getsid , 1) 1312048f6b4dSbellard MIPS_SYS(sys_fdatasync , 0) 1313048f6b4dSbellard MIPS_SYS(sys_sysctl , 1) 1314048f6b4dSbellard MIPS_SYS(sys_mlock , 2) 1315048f6b4dSbellard MIPS_SYS(sys_munlock , 2) /* 4155 */ 1316048f6b4dSbellard MIPS_SYS(sys_mlockall , 1) 1317048f6b4dSbellard MIPS_SYS(sys_munlockall , 0) 1318048f6b4dSbellard MIPS_SYS(sys_sched_setparam, 2) 1319048f6b4dSbellard MIPS_SYS(sys_sched_getparam, 2) 1320048f6b4dSbellard MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */ 1321048f6b4dSbellard MIPS_SYS(sys_sched_getscheduler, 1) 1322048f6b4dSbellard MIPS_SYS(sys_sched_yield , 0) 1323048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_max, 1) 1324048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_min, 1) 1325048f6b4dSbellard MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */ 1326048f6b4dSbellard MIPS_SYS(sys_nanosleep, 2) 1327048f6b4dSbellard MIPS_SYS(sys_mremap , 4) 1328048f6b4dSbellard MIPS_SYS(sys_accept , 3) 1329048f6b4dSbellard MIPS_SYS(sys_bind , 3) 1330048f6b4dSbellard MIPS_SYS(sys_connect , 3) /* 4170 */ 1331048f6b4dSbellard MIPS_SYS(sys_getpeername , 3) 1332048f6b4dSbellard MIPS_SYS(sys_getsockname , 3) 1333048f6b4dSbellard MIPS_SYS(sys_getsockopt , 5) 1334048f6b4dSbellard MIPS_SYS(sys_listen , 2) 1335048f6b4dSbellard MIPS_SYS(sys_recv , 4) /* 4175 */ 1336048f6b4dSbellard MIPS_SYS(sys_recvfrom , 6) 1337048f6b4dSbellard MIPS_SYS(sys_recvmsg , 3) 1338048f6b4dSbellard MIPS_SYS(sys_send , 4) 1339048f6b4dSbellard MIPS_SYS(sys_sendmsg , 3) 1340048f6b4dSbellard MIPS_SYS(sys_sendto , 6) /* 4180 */ 1341048f6b4dSbellard MIPS_SYS(sys_setsockopt , 5) 1342048f6b4dSbellard MIPS_SYS(sys_shutdown , 2) 1343048f6b4dSbellard MIPS_SYS(sys_socket , 3) 1344048f6b4dSbellard MIPS_SYS(sys_socketpair , 4) 1345048f6b4dSbellard MIPS_SYS(sys_setresuid , 3) /* 4185 */ 1346048f6b4dSbellard MIPS_SYS(sys_getresuid , 3) 1347048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */ 1348048f6b4dSbellard MIPS_SYS(sys_poll , 3) 1349048f6b4dSbellard MIPS_SYS(sys_nfsservctl , 3) 1350048f6b4dSbellard MIPS_SYS(sys_setresgid , 3) /* 4190 */ 1351048f6b4dSbellard MIPS_SYS(sys_getresgid , 3) 1352048f6b4dSbellard MIPS_SYS(sys_prctl , 5) 1353048f6b4dSbellard MIPS_SYS(sys_rt_sigreturn, 0) 1354048f6b4dSbellard MIPS_SYS(sys_rt_sigaction, 4) 1355048f6b4dSbellard MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */ 1356048f6b4dSbellard MIPS_SYS(sys_rt_sigpending, 2) 1357048f6b4dSbellard MIPS_SYS(sys_rt_sigtimedwait, 4) 1358048f6b4dSbellard MIPS_SYS(sys_rt_sigqueueinfo, 3) 1359048f6b4dSbellard MIPS_SYS(sys_rt_sigsuspend, 0) 1360048f6b4dSbellard MIPS_SYS(sys_pread64 , 6) /* 4200 */ 1361048f6b4dSbellard MIPS_SYS(sys_pwrite64 , 6) 1362048f6b4dSbellard MIPS_SYS(sys_chown , 3) 1363048f6b4dSbellard MIPS_SYS(sys_getcwd , 2) 1364048f6b4dSbellard MIPS_SYS(sys_capget , 2) 1365048f6b4dSbellard MIPS_SYS(sys_capset , 2) /* 4205 */ 1366048f6b4dSbellard MIPS_SYS(sys_sigaltstack , 0) 1367048f6b4dSbellard MIPS_SYS(sys_sendfile , 4) 1368048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1369048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1370048f6b4dSbellard MIPS_SYS(sys_mmap2 , 6) /* 4210 */ 1371048f6b4dSbellard MIPS_SYS(sys_truncate64 , 4) 1372048f6b4dSbellard MIPS_SYS(sys_ftruncate64 , 4) 1373048f6b4dSbellard MIPS_SYS(sys_stat64 , 2) 1374048f6b4dSbellard MIPS_SYS(sys_lstat64 , 2) 1375048f6b4dSbellard MIPS_SYS(sys_fstat64 , 2) /* 4215 */ 1376048f6b4dSbellard MIPS_SYS(sys_pivot_root , 2) 1377048f6b4dSbellard MIPS_SYS(sys_mincore , 3) 1378048f6b4dSbellard MIPS_SYS(sys_madvise , 3) 1379048f6b4dSbellard MIPS_SYS(sys_getdents64 , 3) 1380048f6b4dSbellard MIPS_SYS(sys_fcntl64 , 3) /* 4220 */ 1381048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1382048f6b4dSbellard MIPS_SYS(sys_gettid , 0) 1383048f6b4dSbellard MIPS_SYS(sys_readahead , 5) 1384048f6b4dSbellard MIPS_SYS(sys_setxattr , 5) 1385048f6b4dSbellard MIPS_SYS(sys_lsetxattr , 5) /* 4225 */ 1386048f6b4dSbellard MIPS_SYS(sys_fsetxattr , 5) 1387048f6b4dSbellard MIPS_SYS(sys_getxattr , 4) 1388048f6b4dSbellard MIPS_SYS(sys_lgetxattr , 4) 1389048f6b4dSbellard MIPS_SYS(sys_fgetxattr , 4) 1390048f6b4dSbellard MIPS_SYS(sys_listxattr , 3) /* 4230 */ 1391048f6b4dSbellard MIPS_SYS(sys_llistxattr , 3) 1392048f6b4dSbellard MIPS_SYS(sys_flistxattr , 3) 1393048f6b4dSbellard MIPS_SYS(sys_removexattr , 2) 1394048f6b4dSbellard MIPS_SYS(sys_lremovexattr, 2) 1395048f6b4dSbellard MIPS_SYS(sys_fremovexattr, 2) /* 4235 */ 1396048f6b4dSbellard MIPS_SYS(sys_tkill , 2) 1397048f6b4dSbellard MIPS_SYS(sys_sendfile64 , 5) 1398048f6b4dSbellard MIPS_SYS(sys_futex , 2) 1399048f6b4dSbellard MIPS_SYS(sys_sched_setaffinity, 3) 1400048f6b4dSbellard MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */ 1401048f6b4dSbellard MIPS_SYS(sys_io_setup , 2) 1402048f6b4dSbellard MIPS_SYS(sys_io_destroy , 1) 1403048f6b4dSbellard MIPS_SYS(sys_io_getevents, 5) 1404048f6b4dSbellard MIPS_SYS(sys_io_submit , 3) 1405048f6b4dSbellard MIPS_SYS(sys_io_cancel , 3) /* 4245 */ 1406048f6b4dSbellard MIPS_SYS(sys_exit_group , 1) 1407048f6b4dSbellard MIPS_SYS(sys_lookup_dcookie, 3) 1408048f6b4dSbellard MIPS_SYS(sys_epoll_create, 1) 1409048f6b4dSbellard MIPS_SYS(sys_epoll_ctl , 4) 1410048f6b4dSbellard MIPS_SYS(sys_epoll_wait , 3) /* 4250 */ 1411048f6b4dSbellard MIPS_SYS(sys_remap_file_pages, 5) 1412048f6b4dSbellard MIPS_SYS(sys_set_tid_address, 1) 1413048f6b4dSbellard MIPS_SYS(sys_restart_syscall, 0) 1414048f6b4dSbellard MIPS_SYS(sys_fadvise64_64, 7) 1415048f6b4dSbellard MIPS_SYS(sys_statfs64 , 3) /* 4255 */ 1416048f6b4dSbellard MIPS_SYS(sys_fstatfs64 , 2) 1417048f6b4dSbellard MIPS_SYS(sys_timer_create, 3) 1418048f6b4dSbellard MIPS_SYS(sys_timer_settime, 4) 1419048f6b4dSbellard MIPS_SYS(sys_timer_gettime, 2) 1420048f6b4dSbellard MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */ 1421048f6b4dSbellard MIPS_SYS(sys_timer_delete, 1) 1422048f6b4dSbellard MIPS_SYS(sys_clock_settime, 2) 1423048f6b4dSbellard MIPS_SYS(sys_clock_gettime, 2) 1424048f6b4dSbellard MIPS_SYS(sys_clock_getres, 2) 1425048f6b4dSbellard MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */ 1426048f6b4dSbellard MIPS_SYS(sys_tgkill , 3) 1427048f6b4dSbellard MIPS_SYS(sys_utimes , 2) 1428048f6b4dSbellard MIPS_SYS(sys_mbind , 4) 1429048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */ 1430048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */ 1431048f6b4dSbellard MIPS_SYS(sys_mq_open , 4) 1432048f6b4dSbellard MIPS_SYS(sys_mq_unlink , 1) 1433048f6b4dSbellard MIPS_SYS(sys_mq_timedsend, 5) 1434048f6b4dSbellard MIPS_SYS(sys_mq_timedreceive, 5) 1435048f6b4dSbellard MIPS_SYS(sys_mq_notify , 2) /* 4275 */ 1436048f6b4dSbellard MIPS_SYS(sys_mq_getsetattr, 3) 1437048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */ 1438048f6b4dSbellard MIPS_SYS(sys_waitid , 4) 1439048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */ 1440048f6b4dSbellard MIPS_SYS(sys_add_key , 5) 1441048f6b4dSbellard MIPS_SYS(sys_request_key, 4) 1442048f6b4dSbellard MIPS_SYS(sys_keyctl , 5) 14436f5b89a0Sths MIPS_SYS(sys_set_thread_area, 1) 1444388bb21aSths MIPS_SYS(sys_inotify_init, 0) 1445388bb21aSths MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */ 1446388bb21aSths MIPS_SYS(sys_inotify_rm_watch, 2) 1447388bb21aSths MIPS_SYS(sys_migrate_pages, 4) 1448388bb21aSths MIPS_SYS(sys_openat, 4) 1449388bb21aSths MIPS_SYS(sys_mkdirat, 3) 1450388bb21aSths MIPS_SYS(sys_mknodat, 4) /* 4290 */ 1451388bb21aSths MIPS_SYS(sys_fchownat, 5) 1452388bb21aSths MIPS_SYS(sys_futimesat, 3) 1453388bb21aSths MIPS_SYS(sys_fstatat64, 4) 1454388bb21aSths MIPS_SYS(sys_unlinkat, 3) 1455388bb21aSths MIPS_SYS(sys_renameat, 4) /* 4295 */ 1456388bb21aSths MIPS_SYS(sys_linkat, 5) 1457388bb21aSths MIPS_SYS(sys_symlinkat, 3) 1458388bb21aSths MIPS_SYS(sys_readlinkat, 4) 1459388bb21aSths MIPS_SYS(sys_fchmodat, 3) 1460388bb21aSths MIPS_SYS(sys_faccessat, 3) /* 4300 */ 1461388bb21aSths MIPS_SYS(sys_pselect6, 6) 1462388bb21aSths MIPS_SYS(sys_ppoll, 5) 1463388bb21aSths MIPS_SYS(sys_unshare, 1) 1464388bb21aSths MIPS_SYS(sys_splice, 4) 1465388bb21aSths MIPS_SYS(sys_sync_file_range, 7) /* 4305 */ 1466388bb21aSths MIPS_SYS(sys_tee, 4) 1467388bb21aSths MIPS_SYS(sys_vmsplice, 4) 1468388bb21aSths MIPS_SYS(sys_move_pages, 6) 1469388bb21aSths MIPS_SYS(sys_set_robust_list, 2) 1470388bb21aSths MIPS_SYS(sys_get_robust_list, 3) /* 4310 */ 1471388bb21aSths MIPS_SYS(sys_kexec_load, 4) 1472388bb21aSths MIPS_SYS(sys_getcpu, 3) 1473388bb21aSths MIPS_SYS(sys_epoll_pwait, 6) 1474388bb21aSths MIPS_SYS(sys_ioprio_set, 3) 1475388bb21aSths MIPS_SYS(sys_ioprio_get, 2) 1476048f6b4dSbellard }; 1477048f6b4dSbellard 1478048f6b4dSbellard #undef MIPS_SYS 1479048f6b4dSbellard 1480048f6b4dSbellard void cpu_loop(CPUMIPSState *env) 1481048f6b4dSbellard { 1482048f6b4dSbellard target_siginfo_t info; 1483388bb21aSths int trapnr, ret; 1484048f6b4dSbellard unsigned int syscall_num; 1485048f6b4dSbellard 1486048f6b4dSbellard for(;;) { 1487048f6b4dSbellard trapnr = cpu_mips_exec(env); 1488048f6b4dSbellard switch(trapnr) { 1489048f6b4dSbellard case EXCP_SYSCALL: 1490ead9360eSths syscall_num = env->gpr[2][env->current_tc] - 4000; 1491ead9360eSths env->PC[env->current_tc] += 4; 1492048f6b4dSbellard if (syscall_num >= sizeof(mips_syscall_args)) { 1493048f6b4dSbellard ret = -ENOSYS; 1494048f6b4dSbellard } else { 1495388bb21aSths int nb_args; 1496992f48a0Sblueswir1 abi_ulong sp_reg; 1497992f48a0Sblueswir1 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; 1498388bb21aSths 1499048f6b4dSbellard nb_args = mips_syscall_args[syscall_num]; 1500ead9360eSths sp_reg = env->gpr[29][env->current_tc]; 1501388bb21aSths switch (nb_args) { 1502048f6b4dSbellard /* these arguments are taken from the stack */ 1503388bb21aSths case 8: arg8 = tgetl(sp_reg + 28); 1504388bb21aSths case 7: arg7 = tgetl(sp_reg + 24); 1505388bb21aSths case 6: arg6 = tgetl(sp_reg + 20); 1506388bb21aSths case 5: arg5 = tgetl(sp_reg + 16); 1507388bb21aSths default: 1508388bb21aSths break; 1509048f6b4dSbellard } 1510ead9360eSths ret = do_syscall(env, env->gpr[2][env->current_tc], 1511ead9360eSths env->gpr[4][env->current_tc], 1512ead9360eSths env->gpr[5][env->current_tc], 1513ead9360eSths env->gpr[6][env->current_tc], 1514ead9360eSths env->gpr[7][env->current_tc], 1515388bb21aSths arg5, arg6/*, arg7, arg8*/); 1516048f6b4dSbellard } 1517048f6b4dSbellard if ((unsigned int)ret >= (unsigned int)(-1133)) { 1518ead9360eSths env->gpr[7][env->current_tc] = 1; /* error flag */ 1519048f6b4dSbellard ret = -ret; 1520048f6b4dSbellard } else { 1521ead9360eSths env->gpr[7][env->current_tc] = 0; /* error flag */ 1522388bb21aSths } 1523ead9360eSths env->gpr[2][env->current_tc] = ret; 1524048f6b4dSbellard break; 1525ca7c2b1bSths case EXCP_TLBL: 1526ca7c2b1bSths case EXCP_TLBS: 15276900e84bSbellard case EXCP_CpU: 1528048f6b4dSbellard case EXCP_RI: 1529048f6b4dSbellard info.si_signo = TARGET_SIGILL; 1530048f6b4dSbellard info.si_errno = 0; 1531048f6b4dSbellard info.si_code = 0; 1532048f6b4dSbellard queue_signal(info.si_signo, &info); 1533048f6b4dSbellard break; 1534106ec879Sbellard case EXCP_INTERRUPT: 1535106ec879Sbellard /* just indicate that signals should be handled asap */ 1536106ec879Sbellard break; 1537d08b2a28Spbrook case EXCP_DEBUG: 1538d08b2a28Spbrook { 1539d08b2a28Spbrook int sig; 1540d08b2a28Spbrook 1541d08b2a28Spbrook sig = gdb_handlesig (env, TARGET_SIGTRAP); 1542d08b2a28Spbrook if (sig) 1543d08b2a28Spbrook { 1544d08b2a28Spbrook info.si_signo = sig; 1545d08b2a28Spbrook info.si_errno = 0; 1546d08b2a28Spbrook info.si_code = TARGET_TRAP_BRKPT; 1547d08b2a28Spbrook queue_signal(info.si_signo, &info); 1548d08b2a28Spbrook } 1549d08b2a28Spbrook } 1550d08b2a28Spbrook break; 1551048f6b4dSbellard default: 1552048f6b4dSbellard // error: 1553048f6b4dSbellard fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 1554048f6b4dSbellard trapnr); 1555048f6b4dSbellard cpu_dump_state(env, stderr, fprintf, 0); 1556048f6b4dSbellard abort(); 1557048f6b4dSbellard } 1558048f6b4dSbellard process_pending_signals(env); 1559048f6b4dSbellard } 1560048f6b4dSbellard } 1561048f6b4dSbellard #endif 1562048f6b4dSbellard 1563fdf9b3e8Sbellard #ifdef TARGET_SH4 1564fdf9b3e8Sbellard void cpu_loop (CPUState *env) 1565fdf9b3e8Sbellard { 1566fdf9b3e8Sbellard int trapnr, ret; 1567355fb23dSpbrook target_siginfo_t info; 1568fdf9b3e8Sbellard 1569fdf9b3e8Sbellard while (1) { 1570fdf9b3e8Sbellard trapnr = cpu_sh4_exec (env); 1571fdf9b3e8Sbellard 1572fdf9b3e8Sbellard switch (trapnr) { 1573fdf9b3e8Sbellard case 0x160: 1574fdf9b3e8Sbellard ret = do_syscall(env, 15759c2a9ea1Spbrook env->gregs[3], 15769c2a9ea1Spbrook env->gregs[4], 15779c2a9ea1Spbrook env->gregs[5], 15789c2a9ea1Spbrook env->gregs[6], 15799c2a9ea1Spbrook env->gregs[7], 15809c2a9ea1Spbrook env->gregs[0], 1581fdf9b3e8Sbellard 0); 15829c2a9ea1Spbrook env->gregs[0] = ret; 1583fdf9b3e8Sbellard env->pc += 2; 1584fdf9b3e8Sbellard break; 1585355fb23dSpbrook case EXCP_DEBUG: 1586355fb23dSpbrook { 1587355fb23dSpbrook int sig; 1588355fb23dSpbrook 1589355fb23dSpbrook sig = gdb_handlesig (env, TARGET_SIGTRAP); 1590355fb23dSpbrook if (sig) 1591355fb23dSpbrook { 1592355fb23dSpbrook info.si_signo = sig; 1593355fb23dSpbrook info.si_errno = 0; 1594355fb23dSpbrook info.si_code = TARGET_TRAP_BRKPT; 1595355fb23dSpbrook queue_signal(info.si_signo, &info); 1596355fb23dSpbrook } 1597355fb23dSpbrook } 1598355fb23dSpbrook break; 1599fdf9b3e8Sbellard default: 1600fdf9b3e8Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 1601fdf9b3e8Sbellard cpu_dump_state(env, stderr, fprintf, 0); 1602fdf9b3e8Sbellard exit (1); 1603fdf9b3e8Sbellard } 1604fdf9b3e8Sbellard process_pending_signals (env); 1605fdf9b3e8Sbellard } 1606fdf9b3e8Sbellard } 1607fdf9b3e8Sbellard #endif 1608fdf9b3e8Sbellard 160948733d19Sths #ifdef TARGET_CRIS 161048733d19Sths void cpu_loop (CPUState *env) 161148733d19Sths { 161248733d19Sths int trapnr, ret; 161348733d19Sths target_siginfo_t info; 161448733d19Sths 161548733d19Sths while (1) { 161648733d19Sths trapnr = cpu_cris_exec (env); 161748733d19Sths switch (trapnr) { 161848733d19Sths case 0xaa: 161948733d19Sths { 162048733d19Sths info.si_signo = SIGSEGV; 162148733d19Sths info.si_errno = 0; 162248733d19Sths /* XXX: check env->error_code */ 162348733d19Sths info.si_code = TARGET_SEGV_MAPERR; 162448733d19Sths info._sifields._sigfault._addr = env->debug1; 162548733d19Sths queue_signal(info.si_signo, &info); 162648733d19Sths } 162748733d19Sths break; 162848733d19Sths case EXCP_BREAK: 162948733d19Sths ret = do_syscall(env, 163048733d19Sths env->regs[9], 163148733d19Sths env->regs[10], 163248733d19Sths env->regs[11], 163348733d19Sths env->regs[12], 163448733d19Sths env->regs[13], 163548733d19Sths env->pregs[7], 163648733d19Sths env->pregs[11]); 163748733d19Sths env->regs[10] = ret; 163848733d19Sths env->pc += 2; 163948733d19Sths break; 164048733d19Sths case EXCP_DEBUG: 164148733d19Sths { 164248733d19Sths int sig; 164348733d19Sths 164448733d19Sths sig = gdb_handlesig (env, TARGET_SIGTRAP); 164548733d19Sths if (sig) 164648733d19Sths { 164748733d19Sths info.si_signo = sig; 164848733d19Sths info.si_errno = 0; 164948733d19Sths info.si_code = TARGET_TRAP_BRKPT; 165048733d19Sths queue_signal(info.si_signo, &info); 165148733d19Sths } 165248733d19Sths } 165348733d19Sths break; 165448733d19Sths default: 165548733d19Sths printf ("Unhandled trap: 0x%x\n", trapnr); 165648733d19Sths cpu_dump_state(env, stderr, fprintf, 0); 165748733d19Sths exit (1); 165848733d19Sths } 165948733d19Sths process_pending_signals (env); 166048733d19Sths } 166148733d19Sths } 166248733d19Sths #endif 166348733d19Sths 1664e6e5906bSpbrook #ifdef TARGET_M68K 1665e6e5906bSpbrook 1666e6e5906bSpbrook void cpu_loop(CPUM68KState *env) 1667e6e5906bSpbrook { 1668e6e5906bSpbrook int trapnr; 1669e6e5906bSpbrook unsigned int n; 1670e6e5906bSpbrook target_siginfo_t info; 1671e6e5906bSpbrook TaskState *ts = env->opaque; 1672e6e5906bSpbrook 1673e6e5906bSpbrook for(;;) { 1674e6e5906bSpbrook trapnr = cpu_m68k_exec(env); 1675e6e5906bSpbrook switch(trapnr) { 1676e6e5906bSpbrook case EXCP_ILLEGAL: 1677e6e5906bSpbrook { 1678e6e5906bSpbrook if (ts->sim_syscalls) { 1679e6e5906bSpbrook uint16_t nr; 1680e6e5906bSpbrook nr = lduw(env->pc + 2); 1681e6e5906bSpbrook env->pc += 4; 1682e6e5906bSpbrook do_m68k_simcall(env, nr); 1683e6e5906bSpbrook } else { 1684e6e5906bSpbrook goto do_sigill; 1685e6e5906bSpbrook } 1686e6e5906bSpbrook } 1687e6e5906bSpbrook break; 1688a87295e8Spbrook case EXCP_HALT_INSN: 1689e6e5906bSpbrook /* Semihosing syscall. */ 1690a87295e8Spbrook env->pc += 4; 1691e6e5906bSpbrook do_m68k_semihosting(env, env->dregs[0]); 1692e6e5906bSpbrook break; 1693e6e5906bSpbrook case EXCP_LINEA: 1694e6e5906bSpbrook case EXCP_LINEF: 1695e6e5906bSpbrook case EXCP_UNSUPPORTED: 1696e6e5906bSpbrook do_sigill: 1697e6e5906bSpbrook info.si_signo = SIGILL; 1698e6e5906bSpbrook info.si_errno = 0; 1699e6e5906bSpbrook info.si_code = TARGET_ILL_ILLOPN; 1700e6e5906bSpbrook info._sifields._sigfault._addr = env->pc; 1701e6e5906bSpbrook queue_signal(info.si_signo, &info); 1702e6e5906bSpbrook break; 1703e6e5906bSpbrook case EXCP_TRAP0: 1704e6e5906bSpbrook { 1705e6e5906bSpbrook ts->sim_syscalls = 0; 1706e6e5906bSpbrook n = env->dregs[0]; 1707e6e5906bSpbrook env->pc += 2; 1708e6e5906bSpbrook env->dregs[0] = do_syscall(env, 1709e6e5906bSpbrook n, 1710e6e5906bSpbrook env->dregs[1], 1711e6e5906bSpbrook env->dregs[2], 1712e6e5906bSpbrook env->dregs[3], 1713e6e5906bSpbrook env->dregs[4], 1714e6e5906bSpbrook env->dregs[5], 1715e6e5906bSpbrook env->dregs[6]); 1716e6e5906bSpbrook } 1717e6e5906bSpbrook break; 1718e6e5906bSpbrook case EXCP_INTERRUPT: 1719e6e5906bSpbrook /* just indicate that signals should be handled asap */ 1720e6e5906bSpbrook break; 1721e6e5906bSpbrook case EXCP_ACCESS: 1722e6e5906bSpbrook { 1723e6e5906bSpbrook info.si_signo = SIGSEGV; 1724e6e5906bSpbrook info.si_errno = 0; 1725e6e5906bSpbrook /* XXX: check env->error_code */ 1726e6e5906bSpbrook info.si_code = TARGET_SEGV_MAPERR; 1727e6e5906bSpbrook info._sifields._sigfault._addr = env->mmu.ar; 1728e6e5906bSpbrook queue_signal(info.si_signo, &info); 1729e6e5906bSpbrook } 1730e6e5906bSpbrook break; 1731e6e5906bSpbrook case EXCP_DEBUG: 1732e6e5906bSpbrook { 1733e6e5906bSpbrook int sig; 1734e6e5906bSpbrook 1735e6e5906bSpbrook sig = gdb_handlesig (env, TARGET_SIGTRAP); 1736e6e5906bSpbrook if (sig) 1737e6e5906bSpbrook { 1738e6e5906bSpbrook info.si_signo = sig; 1739e6e5906bSpbrook info.si_errno = 0; 1740e6e5906bSpbrook info.si_code = TARGET_TRAP_BRKPT; 1741e6e5906bSpbrook queue_signal(info.si_signo, &info); 1742e6e5906bSpbrook } 1743e6e5906bSpbrook } 1744e6e5906bSpbrook break; 1745e6e5906bSpbrook default: 1746e6e5906bSpbrook fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 1747e6e5906bSpbrook trapnr); 1748e6e5906bSpbrook cpu_dump_state(env, stderr, fprintf, 0); 1749e6e5906bSpbrook abort(); 1750e6e5906bSpbrook } 1751e6e5906bSpbrook process_pending_signals(env); 1752e6e5906bSpbrook } 1753e6e5906bSpbrook } 1754e6e5906bSpbrook #endif /* TARGET_M68K */ 1755e6e5906bSpbrook 17567a3148a9Sj_mayer #ifdef TARGET_ALPHA 17577a3148a9Sj_mayer void cpu_loop (CPUState *env) 17587a3148a9Sj_mayer { 1759e96efcfcSj_mayer int trapnr; 17607a3148a9Sj_mayer target_siginfo_t info; 17617a3148a9Sj_mayer 17627a3148a9Sj_mayer while (1) { 17637a3148a9Sj_mayer trapnr = cpu_alpha_exec (env); 17647a3148a9Sj_mayer 17657a3148a9Sj_mayer switch (trapnr) { 17667a3148a9Sj_mayer case EXCP_RESET: 17677a3148a9Sj_mayer fprintf(stderr, "Reset requested. Exit\n"); 17687a3148a9Sj_mayer exit(1); 17697a3148a9Sj_mayer break; 17707a3148a9Sj_mayer case EXCP_MCHK: 17717a3148a9Sj_mayer fprintf(stderr, "Machine check exception. Exit\n"); 17727a3148a9Sj_mayer exit(1); 17737a3148a9Sj_mayer break; 17747a3148a9Sj_mayer case EXCP_ARITH: 17757a3148a9Sj_mayer fprintf(stderr, "Arithmetic trap.\n"); 17767a3148a9Sj_mayer exit(1); 17777a3148a9Sj_mayer break; 17787a3148a9Sj_mayer case EXCP_HW_INTERRUPT: 17797a3148a9Sj_mayer fprintf(stderr, "External interrupt. Exit\n"); 17807a3148a9Sj_mayer exit(1); 17817a3148a9Sj_mayer break; 17827a3148a9Sj_mayer case EXCP_DFAULT: 17837a3148a9Sj_mayer fprintf(stderr, "MMU data fault\n"); 17847a3148a9Sj_mayer exit(1); 17857a3148a9Sj_mayer break; 17867a3148a9Sj_mayer case EXCP_DTB_MISS_PAL: 17877a3148a9Sj_mayer fprintf(stderr, "MMU data TLB miss in PALcode\n"); 17887a3148a9Sj_mayer exit(1); 17897a3148a9Sj_mayer break; 17907a3148a9Sj_mayer case EXCP_ITB_MISS: 17917a3148a9Sj_mayer fprintf(stderr, "MMU instruction TLB miss\n"); 17927a3148a9Sj_mayer exit(1); 17937a3148a9Sj_mayer break; 17947a3148a9Sj_mayer case EXCP_ITB_ACV: 17957a3148a9Sj_mayer fprintf(stderr, "MMU instruction access violation\n"); 17967a3148a9Sj_mayer exit(1); 17977a3148a9Sj_mayer break; 17987a3148a9Sj_mayer case EXCP_DTB_MISS_NATIVE: 17997a3148a9Sj_mayer fprintf(stderr, "MMU data TLB miss\n"); 18007a3148a9Sj_mayer exit(1); 18017a3148a9Sj_mayer break; 18027a3148a9Sj_mayer case EXCP_UNALIGN: 18037a3148a9Sj_mayer fprintf(stderr, "Unaligned access\n"); 18047a3148a9Sj_mayer exit(1); 18057a3148a9Sj_mayer break; 18067a3148a9Sj_mayer case EXCP_OPCDEC: 18077a3148a9Sj_mayer fprintf(stderr, "Invalid instruction\n"); 18087a3148a9Sj_mayer exit(1); 18097a3148a9Sj_mayer break; 18107a3148a9Sj_mayer case EXCP_FEN: 18117a3148a9Sj_mayer fprintf(stderr, "Floating-point not allowed\n"); 18127a3148a9Sj_mayer exit(1); 18137a3148a9Sj_mayer break; 18147a3148a9Sj_mayer case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1): 18157a3148a9Sj_mayer fprintf(stderr, "Call to PALcode\n"); 18167a3148a9Sj_mayer call_pal(env, (trapnr >> 6) | 0x80); 18177a3148a9Sj_mayer break; 18187a3148a9Sj_mayer case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1): 18197f75ffd3Sblueswir1 fprintf(stderr, "Privileged call to PALcode\n"); 18207a3148a9Sj_mayer exit(1); 18217a3148a9Sj_mayer break; 18227a3148a9Sj_mayer case EXCP_DEBUG: 18237a3148a9Sj_mayer { 18247a3148a9Sj_mayer int sig; 18257a3148a9Sj_mayer 18267a3148a9Sj_mayer sig = gdb_handlesig (env, TARGET_SIGTRAP); 18277a3148a9Sj_mayer if (sig) 18287a3148a9Sj_mayer { 18297a3148a9Sj_mayer info.si_signo = sig; 18307a3148a9Sj_mayer info.si_errno = 0; 18317a3148a9Sj_mayer info.si_code = TARGET_TRAP_BRKPT; 18327a3148a9Sj_mayer queue_signal(info.si_signo, &info); 18337a3148a9Sj_mayer } 18347a3148a9Sj_mayer } 18357a3148a9Sj_mayer break; 18367a3148a9Sj_mayer default: 18377a3148a9Sj_mayer printf ("Unhandled trap: 0x%x\n", trapnr); 18387a3148a9Sj_mayer cpu_dump_state(env, stderr, fprintf, 0); 18397a3148a9Sj_mayer exit (1); 18407a3148a9Sj_mayer } 18417a3148a9Sj_mayer process_pending_signals (env); 18427a3148a9Sj_mayer } 18437a3148a9Sj_mayer } 18447a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 18457a3148a9Sj_mayer 184631e31b8aSbellard void usage(void) 184731e31b8aSbellard { 184884f2e8efSbellard printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n" 1849b1f9be31Sj_mayer "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] [-cpu model] program [arguments...]\n" 1850b346ff46Sbellard "Linux CPU emulator (compiled for %s emulation)\n" 1851d691f669Sbellard "\n" 1852d691f669Sbellard "-h print this help\n" 185374c33bedSbellard "-g port wait gdb connection to port\n" 1854b346ff46Sbellard "-L path set the elf interpreter prefix (default=%s)\n" 1855b346ff46Sbellard "-s size set the stack size in bytes (default=%ld)\n" 1856b1f9be31Sj_mayer "-cpu model select CPU (-cpu ? for list)\n" 1857b12b6a18Sths "-drop-ld-preload drop LD_PRELOAD for target process\n" 185854936004Sbellard "\n" 185954936004Sbellard "debug options:\n" 18606f1f31c0Sbellard "-d options activate log (logfile=%s)\n" 1861b6741956Sbellard "-p pagesize set the host page size to 'pagesize'\n" 1862b6741956Sbellard "-strace log system calls\n", 1863b346ff46Sbellard TARGET_ARCH, 1864d691f669Sbellard interp_prefix, 186554936004Sbellard x86_stack_size, 186654936004Sbellard DEBUG_LOGFILE); 186774cd30b8Sbellard _exit(1); 186831e31b8aSbellard } 186931e31b8aSbellard 18709de5e440Sbellard /* XXX: currently only used for async signals (see signal.c) */ 1871b346ff46Sbellard CPUState *global_env; 187259faf6d6Sbellard 1873851e67a1Sbellard /* used to free thread contexts */ 1874851e67a1Sbellard TaskState *first_task_state; 18759de5e440Sbellard 187631e31b8aSbellard int main(int argc, char **argv) 187731e31b8aSbellard { 187831e31b8aSbellard const char *filename; 1879b1f9be31Sj_mayer const char *cpu_model; 188001ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 188131e31b8aSbellard struct image_info info1, *info = &info1; 1882851e67a1Sbellard TaskState ts1, *ts = &ts1; 1883b346ff46Sbellard CPUState *env; 1884586314f2Sbellard int optind; 1885d691f669Sbellard const char *r; 188674c33bedSbellard int gdbstub_port = 0; 1887b12b6a18Sths int drop_ld_preload = 0, environ_count = 0; 1888b12b6a18Sths char **target_environ, **wrk, **dst; 188931e31b8aSbellard 189031e31b8aSbellard if (argc <= 1) 189131e31b8aSbellard usage(); 1892f801f97eSbellard 1893cc38b844Sbellard /* init debug */ 1894cc38b844Sbellard cpu_set_log_filename(DEBUG_LOGFILE); 1895cc38b844Sbellard 1896b1f9be31Sj_mayer cpu_model = NULL; 1897586314f2Sbellard optind = 1; 1898d691f669Sbellard for(;;) { 1899d691f669Sbellard if (optind >= argc) 1900d691f669Sbellard break; 1901d691f669Sbellard r = argv[optind]; 1902d691f669Sbellard if (r[0] != '-') 1903d691f669Sbellard break; 1904586314f2Sbellard optind++; 1905d691f669Sbellard r++; 1906d691f669Sbellard if (!strcmp(r, "-")) { 1907d691f669Sbellard break; 1908d691f669Sbellard } else if (!strcmp(r, "d")) { 1909e19e89a5Sbellard int mask; 1910e19e89a5Sbellard CPULogItem *item; 1911e19e89a5Sbellard 19126f1f31c0Sbellard if (optind >= argc) 19136f1f31c0Sbellard break; 19146f1f31c0Sbellard 19156f1f31c0Sbellard r = argv[optind++]; 19166f1f31c0Sbellard mask = cpu_str_to_log_mask(r); 1917e19e89a5Sbellard if (!mask) { 1918e19e89a5Sbellard printf("Log items (comma separated):\n"); 1919e19e89a5Sbellard for(item = cpu_log_items; item->mask != 0; item++) { 1920e19e89a5Sbellard printf("%-10s %s\n", item->name, item->help); 1921e19e89a5Sbellard } 1922e19e89a5Sbellard exit(1); 1923e19e89a5Sbellard } 1924e19e89a5Sbellard cpu_set_log(mask); 1925d691f669Sbellard } else if (!strcmp(r, "s")) { 1926d691f669Sbellard r = argv[optind++]; 1927d691f669Sbellard x86_stack_size = strtol(r, (char **)&r, 0); 1928d691f669Sbellard if (x86_stack_size <= 0) 1929d691f669Sbellard usage(); 1930d691f669Sbellard if (*r == 'M') 1931d691f669Sbellard x86_stack_size *= 1024 * 1024; 1932d691f669Sbellard else if (*r == 'k' || *r == 'K') 1933d691f669Sbellard x86_stack_size *= 1024; 1934d691f669Sbellard } else if (!strcmp(r, "L")) { 1935d691f669Sbellard interp_prefix = argv[optind++]; 193654936004Sbellard } else if (!strcmp(r, "p")) { 193783fb7adfSbellard qemu_host_page_size = atoi(argv[optind++]); 193883fb7adfSbellard if (qemu_host_page_size == 0 || 193983fb7adfSbellard (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 194054936004Sbellard fprintf(stderr, "page size must be a power of two\n"); 194154936004Sbellard exit(1); 194254936004Sbellard } 19431fddef4bSbellard } else if (!strcmp(r, "g")) { 194474c33bedSbellard gdbstub_port = atoi(argv[optind++]); 1945c5937220Spbrook } else if (!strcmp(r, "r")) { 1946c5937220Spbrook qemu_uname_release = argv[optind++]; 1947b1f9be31Sj_mayer } else if (!strcmp(r, "cpu")) { 1948b1f9be31Sj_mayer cpu_model = argv[optind++]; 1949b1f9be31Sj_mayer if (strcmp(cpu_model, "?") == 0) { 1950c732abe2Sj_mayer /* XXX: implement xxx_cpu_list for targets that still miss it */ 1951c732abe2Sj_mayer #if defined(cpu_list) 1952c732abe2Sj_mayer cpu_list(stdout, &fprintf); 1953b1f9be31Sj_mayer #endif 1954cff4cbedSths _exit(1); 1955b1f9be31Sj_mayer } 1956b12b6a18Sths } else if (!strcmp(r, "drop-ld-preload")) { 1957b12b6a18Sths drop_ld_preload = 1; 1958b6741956Sbellard } else if (!strcmp(r, "strace")) { 1959b6741956Sbellard do_strace = 1; 1960c6981055Sbellard } else 1961c6981055Sbellard { 1962d691f669Sbellard usage(); 1963586314f2Sbellard } 1964d691f669Sbellard } 1965d691f669Sbellard if (optind >= argc) 1966d691f669Sbellard usage(); 1967586314f2Sbellard filename = argv[optind]; 196831e31b8aSbellard 196931e31b8aSbellard /* Zero out regs */ 197001ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 197131e31b8aSbellard 197231e31b8aSbellard /* Zero out image_info */ 197331e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 197431e31b8aSbellard 197574cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 197674cd30b8Sbellard init_paths(interp_prefix); 197774cd30b8Sbellard 197846027c07Sbellard if (cpu_model == NULL) { 1979aaed909aSbellard #if defined(TARGET_I386) 198046027c07Sbellard #ifdef TARGET_X86_64 198146027c07Sbellard cpu_model = "qemu64"; 198246027c07Sbellard #else 198346027c07Sbellard cpu_model = "qemu32"; 198446027c07Sbellard #endif 1985aaed909aSbellard #elif defined(TARGET_ARM) 1986aaed909aSbellard cpu_model = "arm926"; 1987aaed909aSbellard #elif defined(TARGET_M68K) 1988aaed909aSbellard cpu_model = "any"; 1989aaed909aSbellard #elif defined(TARGET_SPARC) 1990aaed909aSbellard #ifdef TARGET_SPARC64 1991aaed909aSbellard cpu_model = "TI UltraSparc II"; 1992aaed909aSbellard #else 1993aaed909aSbellard cpu_model = "Fujitsu MB86904"; 199446027c07Sbellard #endif 1995aaed909aSbellard #elif defined(TARGET_MIPS) 1996aaed909aSbellard #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) 1997aaed909aSbellard cpu_model = "20Kc"; 1998aaed909aSbellard #else 1999aaed909aSbellard cpu_model = "24Kf"; 2000aaed909aSbellard #endif 2001aaed909aSbellard #elif defined(TARGET_PPC) 2002aaed909aSbellard cpu_model = "750"; 2003aaed909aSbellard #else 2004aaed909aSbellard cpu_model = "any"; 2005aaed909aSbellard #endif 2006aaed909aSbellard } 200783fb7adfSbellard /* NOTE: we need to init the CPU at this stage to get 200883fb7adfSbellard qemu_host_page_size */ 2009aaed909aSbellard env = cpu_init(cpu_model); 2010aaed909aSbellard if (!env) { 2011aaed909aSbellard fprintf(stderr, "Unable to find CPU definition\n"); 2012aaed909aSbellard exit(1); 2013aaed909aSbellard } 201415338fd7Sbellard global_env = env; 201554936004Sbellard 2016b92c47c1Sths if (getenv("QEMU_STRACE")) { 2017b92c47c1Sths do_strace = 1; 2018b92c47c1Sths } 2019b92c47c1Sths 2020b12b6a18Sths wrk = environ; 2021b12b6a18Sths while (*(wrk++)) 2022b12b6a18Sths environ_count++; 2023b12b6a18Sths 2024b12b6a18Sths target_environ = malloc((environ_count + 1) * sizeof(char *)); 2025b12b6a18Sths if (!target_environ) 2026b12b6a18Sths abort(); 2027b12b6a18Sths for (wrk = environ, dst = target_environ; *wrk; wrk++) { 2028b12b6a18Sths if (drop_ld_preload && !strncmp(*wrk, "LD_PRELOAD=", 11)) 2029b12b6a18Sths continue; 2030b12b6a18Sths *(dst++) = strdup(*wrk); 2031b12b6a18Sths } 2032403f14efSths *dst = NULL; /* NULL terminate target_environ */ 2033b12b6a18Sths 2034b12b6a18Sths if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { 203531e31b8aSbellard printf("Error loading %s\n", filename); 203674cd30b8Sbellard _exit(1); 203731e31b8aSbellard } 203831e31b8aSbellard 2039b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 2040b12b6a18Sths free(*wrk); 2041b12b6a18Sths } 2042b12b6a18Sths 2043b12b6a18Sths free(target_environ); 2044b12b6a18Sths 20454b74fe1fSbellard if (loglevel) { 204654936004Sbellard page_dump(logfile); 204754936004Sbellard 20488a4ed7efSbellard fprintf(logfile, "start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 20498a4ed7efSbellard fprintf(logfile, "end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); 20508a4ed7efSbellard fprintf(logfile, "start_code 0x" TARGET_ABI_FMT_lx "\n", 20513d177870Sj_mayer info->start_code); 20528a4ed7efSbellard fprintf(logfile, "start_data 0x" TARGET_ABI_FMT_lx "\n", 20533d177870Sj_mayer info->start_data); 20548a4ed7efSbellard fprintf(logfile, "end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data); 20558a4ed7efSbellard fprintf(logfile, "start_stack 0x" TARGET_ABI_FMT_lx "\n", 20563d177870Sj_mayer info->start_stack); 20578a4ed7efSbellard fprintf(logfile, "brk 0x" TARGET_ABI_FMT_lx "\n", info->brk); 20588a4ed7efSbellard fprintf(logfile, "entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); 20594b74fe1fSbellard } 206031e31b8aSbellard 206153a5960aSpbrook target_set_brk(info->brk); 206231e31b8aSbellard syscall_init(); 206366fb9763Sbellard signal_init(); 206431e31b8aSbellard 2065851e67a1Sbellard /* build Task State */ 2066851e67a1Sbellard memset(ts, 0, sizeof(TaskState)); 2067851e67a1Sbellard env->opaque = ts; 2068851e67a1Sbellard ts->used = 1; 2069978efd6aSpbrook ts->info = info; 207059faf6d6Sbellard env->user_mode_only = 1; 2071851e67a1Sbellard 2072b346ff46Sbellard #if defined(TARGET_I386) 20732e255c6bSbellard cpu_x86_set_cpl(env, 3); 20742e255c6bSbellard 20753802ce26Sbellard env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; 20761bde465eSbellard env->hflags |= HF_PE_MASK; 20771bde465eSbellard if (env->cpuid_features & CPUID_SSE) { 20781bde465eSbellard env->cr[4] |= CR4_OSFXSR_MASK; 20791bde465eSbellard env->hflags |= HF_OSFXSR_MASK; 20801bde465eSbellard } 20813802ce26Sbellard 2082415e561fSbellard /* flags setup : we activate the IRQs by default as in user mode */ 2083415e561fSbellard env->eflags |= IF_MASK; 2084415e561fSbellard 20856dbad63eSbellard /* linux register setup */ 208684409ddbSj_mayer #if defined(TARGET_X86_64) 208784409ddbSj_mayer env->regs[R_EAX] = regs->rax; 208884409ddbSj_mayer env->regs[R_EBX] = regs->rbx; 208984409ddbSj_mayer env->regs[R_ECX] = regs->rcx; 209084409ddbSj_mayer env->regs[R_EDX] = regs->rdx; 209184409ddbSj_mayer env->regs[R_ESI] = regs->rsi; 209284409ddbSj_mayer env->regs[R_EDI] = regs->rdi; 209384409ddbSj_mayer env->regs[R_EBP] = regs->rbp; 209484409ddbSj_mayer env->regs[R_ESP] = regs->rsp; 209584409ddbSj_mayer env->eip = regs->rip; 209684409ddbSj_mayer #else 20970ecfa993Sbellard env->regs[R_EAX] = regs->eax; 20980ecfa993Sbellard env->regs[R_EBX] = regs->ebx; 20990ecfa993Sbellard env->regs[R_ECX] = regs->ecx; 21000ecfa993Sbellard env->regs[R_EDX] = regs->edx; 21010ecfa993Sbellard env->regs[R_ESI] = regs->esi; 21020ecfa993Sbellard env->regs[R_EDI] = regs->edi; 21030ecfa993Sbellard env->regs[R_EBP] = regs->ebp; 21040ecfa993Sbellard env->regs[R_ESP] = regs->esp; 2105dab2ed99Sbellard env->eip = regs->eip; 210684409ddbSj_mayer #endif 210731e31b8aSbellard 2108f4beb510Sbellard /* linux interrupt setup */ 210953a5960aSpbrook env->idt.base = h2g(idt_table); 2110f4beb510Sbellard env->idt.limit = sizeof(idt_table) - 1; 2111f4beb510Sbellard set_idt(0, 0); 2112f4beb510Sbellard set_idt(1, 0); 2113f4beb510Sbellard set_idt(2, 0); 2114f4beb510Sbellard set_idt(3, 3); 2115f4beb510Sbellard set_idt(4, 3); 2116f4beb510Sbellard set_idt(5, 3); 2117f4beb510Sbellard set_idt(6, 0); 2118f4beb510Sbellard set_idt(7, 0); 2119f4beb510Sbellard set_idt(8, 0); 2120f4beb510Sbellard set_idt(9, 0); 2121f4beb510Sbellard set_idt(10, 0); 2122f4beb510Sbellard set_idt(11, 0); 2123f4beb510Sbellard set_idt(12, 0); 2124f4beb510Sbellard set_idt(13, 0); 2125f4beb510Sbellard set_idt(14, 0); 2126f4beb510Sbellard set_idt(15, 0); 2127f4beb510Sbellard set_idt(16, 0); 2128f4beb510Sbellard set_idt(17, 0); 2129f4beb510Sbellard set_idt(18, 0); 2130f4beb510Sbellard set_idt(19, 0); 2131f4beb510Sbellard set_idt(0x80, 3); 2132f4beb510Sbellard 21336dbad63eSbellard /* linux segment setup */ 213453a5960aSpbrook env->gdt.base = h2g(gdt_table); 21356dbad63eSbellard env->gdt.limit = sizeof(gdt_table) - 1; 2136f4beb510Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 2137f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 2138f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 2139f4beb510Sbellard write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, 2140f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 2141f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); 21426dbad63eSbellard cpu_x86_load_seg(env, R_CS, __USER_CS); 21436dbad63eSbellard cpu_x86_load_seg(env, R_DS, __USER_DS); 21446dbad63eSbellard cpu_x86_load_seg(env, R_ES, __USER_DS); 21456dbad63eSbellard cpu_x86_load_seg(env, R_SS, __USER_DS); 21466dbad63eSbellard cpu_x86_load_seg(env, R_FS, __USER_DS); 21476dbad63eSbellard cpu_x86_load_seg(env, R_GS, __USER_DS); 214892ccca6aSbellard 2149d6eb40f6Sths /* This hack makes Wine work... */ 2150d6eb40f6Sths env->segs[R_FS].selector = 0; 2151b346ff46Sbellard #elif defined(TARGET_ARM) 2152b346ff46Sbellard { 2153b346ff46Sbellard int i; 2154b5ff1b31Sbellard cpsr_write(env, regs->uregs[16], 0xffffffff); 2155b346ff46Sbellard for(i = 0; i < 16; i++) { 2156b346ff46Sbellard env->regs[i] = regs->uregs[i]; 2157b346ff46Sbellard } 2158b346ff46Sbellard } 215993ac68bcSbellard #elif defined(TARGET_SPARC) 2160060366c5Sbellard { 2161060366c5Sbellard int i; 2162060366c5Sbellard env->pc = regs->pc; 2163060366c5Sbellard env->npc = regs->npc; 2164060366c5Sbellard env->y = regs->y; 2165060366c5Sbellard for(i = 0; i < 8; i++) 2166060366c5Sbellard env->gregs[i] = regs->u_regs[i]; 2167060366c5Sbellard for(i = 0; i < 8; i++) 2168060366c5Sbellard env->regwptr[i] = regs->u_regs[i + 8]; 2169060366c5Sbellard } 217067867308Sbellard #elif defined(TARGET_PPC) 217167867308Sbellard { 217267867308Sbellard int i; 21733fc6c082Sbellard 21740411a972Sj_mayer #if defined(TARGET_PPC64) 21750411a972Sj_mayer #if defined(TARGET_ABI32) 21760411a972Sj_mayer env->msr &= ~((target_ulong)1 << MSR_SF); 2177e85e7c6eSj_mayer #else 21780411a972Sj_mayer env->msr |= (target_ulong)1 << MSR_SF; 21790411a972Sj_mayer #endif 218084409ddbSj_mayer #endif 218167867308Sbellard env->nip = regs->nip; 218267867308Sbellard for(i = 0; i < 32; i++) { 218367867308Sbellard env->gpr[i] = regs->gpr[i]; 218467867308Sbellard } 218567867308Sbellard } 2186e6e5906bSpbrook #elif defined(TARGET_M68K) 2187e6e5906bSpbrook { 2188e6e5906bSpbrook env->pc = regs->pc; 2189e6e5906bSpbrook env->dregs[0] = regs->d0; 2190e6e5906bSpbrook env->dregs[1] = regs->d1; 2191e6e5906bSpbrook env->dregs[2] = regs->d2; 2192e6e5906bSpbrook env->dregs[3] = regs->d3; 2193e6e5906bSpbrook env->dregs[4] = regs->d4; 2194e6e5906bSpbrook env->dregs[5] = regs->d5; 2195e6e5906bSpbrook env->dregs[6] = regs->d6; 2196e6e5906bSpbrook env->dregs[7] = regs->d7; 2197e6e5906bSpbrook env->aregs[0] = regs->a0; 2198e6e5906bSpbrook env->aregs[1] = regs->a1; 2199e6e5906bSpbrook env->aregs[2] = regs->a2; 2200e6e5906bSpbrook env->aregs[3] = regs->a3; 2201e6e5906bSpbrook env->aregs[4] = regs->a4; 2202e6e5906bSpbrook env->aregs[5] = regs->a5; 2203e6e5906bSpbrook env->aregs[6] = regs->a6; 2204e6e5906bSpbrook env->aregs[7] = regs->usp; 2205e6e5906bSpbrook env->sr = regs->sr; 2206e6e5906bSpbrook ts->sim_syscalls = 1; 2207e6e5906bSpbrook } 2208048f6b4dSbellard #elif defined(TARGET_MIPS) 2209048f6b4dSbellard { 2210048f6b4dSbellard int i; 2211048f6b4dSbellard 2212048f6b4dSbellard for(i = 0; i < 32; i++) { 2213ead9360eSths env->gpr[i][env->current_tc] = regs->regs[i]; 2214048f6b4dSbellard } 2215ead9360eSths env->PC[env->current_tc] = regs->cp0_epc; 2216048f6b4dSbellard } 2217fdf9b3e8Sbellard #elif defined(TARGET_SH4) 2218fdf9b3e8Sbellard { 2219fdf9b3e8Sbellard int i; 2220fdf9b3e8Sbellard 2221fdf9b3e8Sbellard for(i = 0; i < 16; i++) { 2222fdf9b3e8Sbellard env->gregs[i] = regs->regs[i]; 2223fdf9b3e8Sbellard } 2224fdf9b3e8Sbellard env->pc = regs->pc; 2225fdf9b3e8Sbellard } 22267a3148a9Sj_mayer #elif defined(TARGET_ALPHA) 22277a3148a9Sj_mayer { 22287a3148a9Sj_mayer int i; 22297a3148a9Sj_mayer 22307a3148a9Sj_mayer for(i = 0; i < 28; i++) { 2231992f48a0Sblueswir1 env->ir[i] = ((abi_ulong *)regs)[i]; 22327a3148a9Sj_mayer } 22337a3148a9Sj_mayer env->ipr[IPR_USP] = regs->usp; 22347a3148a9Sj_mayer env->ir[30] = regs->usp; 22357a3148a9Sj_mayer env->pc = regs->pc; 22367a3148a9Sj_mayer env->unique = regs->unique; 22377a3148a9Sj_mayer } 223848733d19Sths #elif defined(TARGET_CRIS) 223948733d19Sths { 224048733d19Sths env->regs[0] = regs->r0; 224148733d19Sths env->regs[1] = regs->r1; 224248733d19Sths env->regs[2] = regs->r2; 224348733d19Sths env->regs[3] = regs->r3; 224448733d19Sths env->regs[4] = regs->r4; 224548733d19Sths env->regs[5] = regs->r5; 224648733d19Sths env->regs[6] = regs->r6; 224748733d19Sths env->regs[7] = regs->r7; 224848733d19Sths env->regs[8] = regs->r8; 224948733d19Sths env->regs[9] = regs->r9; 225048733d19Sths env->regs[10] = regs->r10; 225148733d19Sths env->regs[11] = regs->r11; 225248733d19Sths env->regs[12] = regs->r12; 225348733d19Sths env->regs[13] = regs->r13; 225448733d19Sths env->regs[14] = info->start_stack; 225548733d19Sths env->regs[15] = regs->acr; 225648733d19Sths env->pc = regs->erp; 225748733d19Sths } 2258b346ff46Sbellard #else 2259b346ff46Sbellard #error unsupported target CPU 2260b346ff46Sbellard #endif 226131e31b8aSbellard 2262a87295e8Spbrook #if defined(TARGET_ARM) || defined(TARGET_M68K) 2263a87295e8Spbrook ts->stack_base = info->start_stack; 2264a87295e8Spbrook ts->heap_base = info->brk; 2265a87295e8Spbrook /* This will be filled in on the first SYS_HEAPINFO call. */ 2266a87295e8Spbrook ts->heap_limit = 0; 2267a87295e8Spbrook #endif 2268a87295e8Spbrook 226974c33bedSbellard if (gdbstub_port) { 227074c33bedSbellard gdbserver_start (gdbstub_port); 22711fddef4bSbellard gdb_handlesig(env, 0); 22721fddef4bSbellard } 22731b6b029eSbellard cpu_loop(env); 22741b6b029eSbellard /* never exits */ 227531e31b8aSbellard return 0; 227631e31b8aSbellard } 2277