xref: /qemu/linux-user/main.c (revision a87295e8)
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 
3183fb7adfSbellard #ifdef __APPLE__
3283fb7adfSbellard #include <crt_externs.h>
3383fb7adfSbellard # define environ  (*_NSGetEnviron())
3483fb7adfSbellard #endif
3583fb7adfSbellard 
3674cd30b8Sbellard static const char *interp_prefix = CONFIG_QEMU_PREFIX;
37c5937220Spbrook const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
38586314f2Sbellard 
393a4739d6Sbellard #if defined(__i386__) && !defined(CONFIG_STATIC)
40f801f97eSbellard /* Force usage of an ELF interpreter even if it is an ELF shared
41f801f97eSbellard    object ! */
42f801f97eSbellard const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
434304763bSbellard #endif
4474cd30b8Sbellard 
4593ac68bcSbellard /* for recent libc, we add these dummy symbols which are not declared
4674cd30b8Sbellard    when generating a linked object (bug in ld ?) */
47fbf59244Sbellard #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
48c6981055Sbellard long __preinit_array_start[0];
49c6981055Sbellard long __preinit_array_end[0];
5074cd30b8Sbellard long __init_array_start[0];
5174cd30b8Sbellard long __init_array_end[0];
5274cd30b8Sbellard long __fini_array_start[0];
5374cd30b8Sbellard long __fini_array_end[0];
5474cd30b8Sbellard #endif
5574cd30b8Sbellard 
569de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
579de5e440Sbellard    we allocate a bigger stack. Need a better solution, for example
589de5e440Sbellard    by remapping the process stack directly at the right place */
599de5e440Sbellard unsigned long x86_stack_size = 512 * 1024;
6031e31b8aSbellard 
6131e31b8aSbellard void gemu_log(const char *fmt, ...)
6231e31b8aSbellard {
6331e31b8aSbellard     va_list ap;
6431e31b8aSbellard 
6531e31b8aSbellard     va_start(ap, fmt);
6631e31b8aSbellard     vfprintf(stderr, fmt, ap);
6731e31b8aSbellard     va_end(ap);
6831e31b8aSbellard }
6931e31b8aSbellard 
7061190b14Sbellard void cpu_outb(CPUState *env, int addr, int val)
71367e86e8Sbellard {
72367e86e8Sbellard     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
73367e86e8Sbellard }
74367e86e8Sbellard 
7561190b14Sbellard void cpu_outw(CPUState *env, int addr, int val)
76367e86e8Sbellard {
77367e86e8Sbellard     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
78367e86e8Sbellard }
79367e86e8Sbellard 
8061190b14Sbellard void cpu_outl(CPUState *env, int addr, int val)
81367e86e8Sbellard {
82367e86e8Sbellard     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
83367e86e8Sbellard }
84367e86e8Sbellard 
8561190b14Sbellard int cpu_inb(CPUState *env, int addr)
86367e86e8Sbellard {
87367e86e8Sbellard     fprintf(stderr, "inb: port=0x%04x\n", addr);
88367e86e8Sbellard     return 0;
89367e86e8Sbellard }
90367e86e8Sbellard 
9161190b14Sbellard int cpu_inw(CPUState *env, int addr)
92367e86e8Sbellard {
93367e86e8Sbellard     fprintf(stderr, "inw: port=0x%04x\n", addr);
94367e86e8Sbellard     return 0;
95367e86e8Sbellard }
96367e86e8Sbellard 
9761190b14Sbellard int cpu_inl(CPUState *env, int addr)
98367e86e8Sbellard {
99367e86e8Sbellard     fprintf(stderr, "inl: port=0x%04x\n", addr);
100367e86e8Sbellard     return 0;
101367e86e8Sbellard }
102367e86e8Sbellard 
103a541f297Sbellard int cpu_get_pic_interrupt(CPUState *env)
10492ccca6aSbellard {
10592ccca6aSbellard     return -1;
10692ccca6aSbellard }
10792ccca6aSbellard 
10828ab0e2eSbellard /* timers for rdtsc */
10928ab0e2eSbellard 
1101dce7c3cSbellard #if 0
11128ab0e2eSbellard 
11228ab0e2eSbellard static uint64_t emu_time;
11328ab0e2eSbellard 
11428ab0e2eSbellard int64_t cpu_get_real_ticks(void)
11528ab0e2eSbellard {
11628ab0e2eSbellard     return emu_time++;
11728ab0e2eSbellard }
11828ab0e2eSbellard 
11928ab0e2eSbellard #endif
12028ab0e2eSbellard 
121a541f297Sbellard #ifdef TARGET_I386
122a541f297Sbellard /***********************************************************/
123a541f297Sbellard /* CPUX86 core interface */
124a541f297Sbellard 
12502a1602eSbellard void cpu_smm_update(CPUState *env)
12602a1602eSbellard {
12702a1602eSbellard }
12802a1602eSbellard 
12928ab0e2eSbellard uint64_t cpu_get_tsc(CPUX86State *env)
13028ab0e2eSbellard {
13128ab0e2eSbellard     return cpu_get_real_ticks();
13228ab0e2eSbellard }
13328ab0e2eSbellard 
134f4beb510Sbellard static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
135f4beb510Sbellard                      int flags)
1366dbad63eSbellard {
137f4beb510Sbellard     unsigned int e1, e2;
13853a5960aSpbrook     uint32_t *p;
1396dbad63eSbellard     e1 = (addr << 16) | (limit & 0xffff);
1406dbad63eSbellard     e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
141f4beb510Sbellard     e2 |= flags;
14253a5960aSpbrook     p = ptr;
14353a5960aSpbrook     p[0] = tswapl(e1);
14453a5960aSpbrook     p[1] = tswapl(e2);
145f4beb510Sbellard }
146f4beb510Sbellard 
147f4beb510Sbellard static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
148f4beb510Sbellard                      unsigned long addr, unsigned int sel)
149f4beb510Sbellard {
150f4beb510Sbellard     unsigned int e1, e2;
15153a5960aSpbrook     uint32_t *p;
152f4beb510Sbellard     e1 = (addr & 0xffff) | (sel << 16);
153f4beb510Sbellard     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
15453a5960aSpbrook     p = ptr;
15553a5960aSpbrook     p[0] = tswapl(e1);
15653a5960aSpbrook     p[1] = tswapl(e2);
1576dbad63eSbellard }
1586dbad63eSbellard 
1596dbad63eSbellard uint64_t gdt_table[6];
160f4beb510Sbellard uint64_t idt_table[256];
161f4beb510Sbellard 
162f4beb510Sbellard /* only dpl matters as we do only user space emulation */
163f4beb510Sbellard static void set_idt(int n, unsigned int dpl)
164f4beb510Sbellard {
165f4beb510Sbellard     set_gate(idt_table + n, 0, dpl, 0, 0);
166f4beb510Sbellard }
16731e31b8aSbellard 
16889e957e7Sbellard void cpu_loop(CPUX86State *env)
169bc8a22ccSbellard {
170bc8a22ccSbellard     int trapnr;
17180a9d035Sbellard     target_ulong pc;
172bc8a22ccSbellard     target_siginfo_t info;
173bc8a22ccSbellard 
174bc8a22ccSbellard     for(;;) {
175bc8a22ccSbellard         trapnr = cpu_x86_exec(env);
176bc8a22ccSbellard         switch(trapnr) {
177f4beb510Sbellard         case 0x80:
178f4beb510Sbellard             /* linux syscall */
1791b6b029eSbellard             env->regs[R_EAX] = do_syscall(env,
1801b6b029eSbellard                                           env->regs[R_EAX],
1811b6b029eSbellard                                           env->regs[R_EBX],
1821b6b029eSbellard                                           env->regs[R_ECX],
1831b6b029eSbellard                                           env->regs[R_EDX],
1841b6b029eSbellard                                           env->regs[R_ESI],
1851b6b029eSbellard                                           env->regs[R_EDI],
1861b6b029eSbellard                                           env->regs[R_EBP]);
187f4beb510Sbellard             break;
188f4beb510Sbellard         case EXCP0B_NOSEG:
189f4beb510Sbellard         case EXCP0C_STACK:
190f4beb510Sbellard             info.si_signo = SIGBUS;
191f4beb510Sbellard             info.si_errno = 0;
192f4beb510Sbellard             info.si_code = TARGET_SI_KERNEL;
193f4beb510Sbellard             info._sifields._sigfault._addr = 0;
194f4beb510Sbellard             queue_signal(info.si_signo, &info);
195f4beb510Sbellard             break;
196f4beb510Sbellard         case EXCP0D_GPF:
19784409ddbSj_mayer #ifndef TARGET_X86_64
198f4beb510Sbellard             if (env->eflags & VM_MASK) {
199f4beb510Sbellard                 handle_vm86_fault(env);
20084409ddbSj_mayer             } else
20184409ddbSj_mayer #endif
20284409ddbSj_mayer             {
2039de5e440Sbellard                 info.si_signo = SIGSEGV;
2049de5e440Sbellard                 info.si_errno = 0;
205b689bc57Sbellard                 info.si_code = TARGET_SI_KERNEL;
2069de5e440Sbellard                 info._sifields._sigfault._addr = 0;
2079de5e440Sbellard                 queue_signal(info.si_signo, &info);
2081b6b029eSbellard             }
2091b6b029eSbellard             break;
210b689bc57Sbellard         case EXCP0E_PAGE:
211b689bc57Sbellard             info.si_signo = SIGSEGV;
212b689bc57Sbellard             info.si_errno = 0;
213b689bc57Sbellard             if (!(env->error_code & 1))
214b689bc57Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
215b689bc57Sbellard             else
216b689bc57Sbellard                 info.si_code = TARGET_SEGV_ACCERR;
217970a87a6Sbellard             info._sifields._sigfault._addr = env->cr[2];
218b689bc57Sbellard             queue_signal(info.si_signo, &info);
219b689bc57Sbellard             break;
2209de5e440Sbellard         case EXCP00_DIVZ:
22184409ddbSj_mayer #ifndef TARGET_X86_64
222bc8a22ccSbellard             if (env->eflags & VM_MASK) {
223447db213Sbellard                 handle_vm86_trap(env, trapnr);
22484409ddbSj_mayer             } else
22584409ddbSj_mayer #endif
22684409ddbSj_mayer             {
2279de5e440Sbellard                 /* division by zero */
2289de5e440Sbellard                 info.si_signo = SIGFPE;
2299de5e440Sbellard                 info.si_errno = 0;
2309de5e440Sbellard                 info.si_code = TARGET_FPE_INTDIV;
2319de5e440Sbellard                 info._sifields._sigfault._addr = env->eip;
2329de5e440Sbellard                 queue_signal(info.si_signo, &info);
233bc8a22ccSbellard             }
2349de5e440Sbellard             break;
235447db213Sbellard         case EXCP01_SSTP:
236447db213Sbellard         case EXCP03_INT3:
23784409ddbSj_mayer #ifndef TARGET_X86_64
238447db213Sbellard             if (env->eflags & VM_MASK) {
239447db213Sbellard                 handle_vm86_trap(env, trapnr);
24084409ddbSj_mayer             } else
24184409ddbSj_mayer #endif
24284409ddbSj_mayer             {
243447db213Sbellard                 info.si_signo = SIGTRAP;
244447db213Sbellard                 info.si_errno = 0;
245447db213Sbellard                 if (trapnr == EXCP01_SSTP) {
246447db213Sbellard                     info.si_code = TARGET_TRAP_BRKPT;
247447db213Sbellard                     info._sifields._sigfault._addr = env->eip;
248447db213Sbellard                 } else {
249447db213Sbellard                     info.si_code = TARGET_SI_KERNEL;
250447db213Sbellard                     info._sifields._sigfault._addr = 0;
251447db213Sbellard                 }
252447db213Sbellard                 queue_signal(info.si_signo, &info);
253447db213Sbellard             }
254447db213Sbellard             break;
2559de5e440Sbellard         case EXCP04_INTO:
2569de5e440Sbellard         case EXCP05_BOUND:
25784409ddbSj_mayer #ifndef TARGET_X86_64
258bc8a22ccSbellard             if (env->eflags & VM_MASK) {
259447db213Sbellard                 handle_vm86_trap(env, trapnr);
26084409ddbSj_mayer             } else
26184409ddbSj_mayer #endif
26284409ddbSj_mayer             {
2639de5e440Sbellard                 info.si_signo = SIGSEGV;
2649de5e440Sbellard                 info.si_errno = 0;
265b689bc57Sbellard                 info.si_code = TARGET_SI_KERNEL;
2669de5e440Sbellard                 info._sifields._sigfault._addr = 0;
2679de5e440Sbellard                 queue_signal(info.si_signo, &info);
268bc8a22ccSbellard             }
2699de5e440Sbellard             break;
2709de5e440Sbellard         case EXCP06_ILLOP:
2719de5e440Sbellard             info.si_signo = SIGILL;
2729de5e440Sbellard             info.si_errno = 0;
2739de5e440Sbellard             info.si_code = TARGET_ILL_ILLOPN;
2749de5e440Sbellard             info._sifields._sigfault._addr = env->eip;
2759de5e440Sbellard             queue_signal(info.si_signo, &info);
2769de5e440Sbellard             break;
2779de5e440Sbellard         case EXCP_INTERRUPT:
2789de5e440Sbellard             /* just indicate that signals should be handled asap */
2799de5e440Sbellard             break;
2801fddef4bSbellard         case EXCP_DEBUG:
2811fddef4bSbellard             {
2821fddef4bSbellard                 int sig;
2831fddef4bSbellard 
2841fddef4bSbellard                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2851fddef4bSbellard                 if (sig)
2861fddef4bSbellard                   {
2871fddef4bSbellard                     info.si_signo = sig;
2881fddef4bSbellard                     info.si_errno = 0;
2891fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
2901fddef4bSbellard                     queue_signal(info.si_signo, &info);
2911fddef4bSbellard                   }
2921fddef4bSbellard             }
2931fddef4bSbellard             break;
2941b6b029eSbellard         default:
295970a87a6Sbellard             pc = env->segs[R_CS].base + env->eip;
296bc8a22ccSbellard             fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
297bc8a22ccSbellard                     (long)pc, trapnr);
2981b6b029eSbellard             abort();
2991b6b029eSbellard         }
30066fb9763Sbellard         process_pending_signals(env);
3011b6b029eSbellard     }
3021b6b029eSbellard }
303b346ff46Sbellard #endif
304b346ff46Sbellard 
305b346ff46Sbellard #ifdef TARGET_ARM
306b346ff46Sbellard 
3076f1f31c0Sbellard /* XXX: find a better solution */
3086f1f31c0Sbellard extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
3096f1f31c0Sbellard 
3106f1f31c0Sbellard static void arm_cache_flush(target_ulong start, target_ulong last)
3116f1f31c0Sbellard {
3126f1f31c0Sbellard     target_ulong addr, last1;
3136f1f31c0Sbellard 
3146f1f31c0Sbellard     if (last < start)
3156f1f31c0Sbellard         return;
3166f1f31c0Sbellard     addr = start;
3176f1f31c0Sbellard     for(;;) {
3186f1f31c0Sbellard         last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;
3196f1f31c0Sbellard         if (last1 > last)
3206f1f31c0Sbellard             last1 = last;
3216f1f31c0Sbellard         tb_invalidate_page_range(addr, last1 + 1);
3226f1f31c0Sbellard         if (last1 == last)
3236f1f31c0Sbellard             break;
3246f1f31c0Sbellard         addr = last1 + 1;
3256f1f31c0Sbellard     }
3266f1f31c0Sbellard }
3276f1f31c0Sbellard 
328b346ff46Sbellard void cpu_loop(CPUARMState *env)
329b346ff46Sbellard {
330b346ff46Sbellard     int trapnr;
331b346ff46Sbellard     unsigned int n, insn;
332b346ff46Sbellard     target_siginfo_t info;
333b5ff1b31Sbellard     uint32_t addr;
334b346ff46Sbellard 
335b346ff46Sbellard     for(;;) {
336b346ff46Sbellard         trapnr = cpu_arm_exec(env);
337b346ff46Sbellard         switch(trapnr) {
338b346ff46Sbellard         case EXCP_UDEF:
339c6981055Sbellard             {
340c6981055Sbellard                 TaskState *ts = env->opaque;
341c6981055Sbellard                 uint32_t opcode;
342c6981055Sbellard 
343c6981055Sbellard                 /* we handle the FPU emulation here, as Linux */
344c6981055Sbellard                 /* we get the opcode */
34553a5960aSpbrook                 opcode = tget32(env->regs[15]);
346c6981055Sbellard 
34719b045deSpbrook                 if (EmulateAll(opcode, &ts->fpa, env) == 0) {
348b346ff46Sbellard                     info.si_signo = SIGILL;
349b346ff46Sbellard                     info.si_errno = 0;
350b346ff46Sbellard                     info.si_code = TARGET_ILL_ILLOPN;
351b346ff46Sbellard                     info._sifields._sigfault._addr = env->regs[15];
352b346ff46Sbellard                     queue_signal(info.si_signo, &info);
353c6981055Sbellard                 } else {
354c6981055Sbellard                     /* increment PC */
355c6981055Sbellard                     env->regs[15] += 4;
356c6981055Sbellard                 }
357c6981055Sbellard             }
358b346ff46Sbellard             break;
359b346ff46Sbellard         case EXCP_SWI:
36006c949e6Spbrook         case EXCP_BKPT:
361b346ff46Sbellard             {
362ce4defa0Spbrook                 env->eabi = 1;
363b346ff46Sbellard                 /* system call */
36406c949e6Spbrook                 if (trapnr == EXCP_BKPT) {
36506c949e6Spbrook                     if (env->thumb) {
36653a5960aSpbrook                         insn = tget16(env->regs[15]);
36706c949e6Spbrook                         n = insn & 0xff;
36806c949e6Spbrook                         env->regs[15] += 2;
36906c949e6Spbrook                     } else {
37053a5960aSpbrook                         insn = tget32(env->regs[15]);
37106c949e6Spbrook                         n = (insn & 0xf) | ((insn >> 4) & 0xff0);
37206c949e6Spbrook                         env->regs[15] += 4;
37306c949e6Spbrook                     }
37406c949e6Spbrook                 } else {
375192c7bd9Sbellard                     if (env->thumb) {
37653a5960aSpbrook                         insn = tget16(env->regs[15] - 2);
377192c7bd9Sbellard                         n = insn & 0xff;
378192c7bd9Sbellard                     } else {
37953a5960aSpbrook                         insn = tget32(env->regs[15] - 4);
380b346ff46Sbellard                         n = insn & 0xffffff;
381192c7bd9Sbellard                     }
38206c949e6Spbrook                 }
383192c7bd9Sbellard 
3846f1f31c0Sbellard                 if (n == ARM_NR_cacheflush) {
3856f1f31c0Sbellard                     arm_cache_flush(env->regs[0], env->regs[1]);
386a4f81979Sbellard                 } else if (n == ARM_NR_semihosting
387a4f81979Sbellard                            || n == ARM_NR_thumb_semihosting) {
388a4f81979Sbellard                     env->regs[0] = do_arm_semihosting (env);
389ce4defa0Spbrook                 } else if (n == 0 || n >= ARM_SYSCALL_BASE
390192c7bd9Sbellard                            || (env->thumb && n == ARM_THUMB_SYSCALL)) {
391b346ff46Sbellard                     /* linux syscall */
392ce4defa0Spbrook                     if (env->thumb || n == 0) {
393192c7bd9Sbellard                         n = env->regs[7];
394192c7bd9Sbellard                     } else {
395b346ff46Sbellard                         n -= ARM_SYSCALL_BASE;
396ce4defa0Spbrook                         env->eabi = 0;
397192c7bd9Sbellard                     }
398b346ff46Sbellard                     env->regs[0] = do_syscall(env,
399b346ff46Sbellard                                               n,
400b346ff46Sbellard                                               env->regs[0],
401b346ff46Sbellard                                               env->regs[1],
402b346ff46Sbellard                                               env->regs[2],
403b346ff46Sbellard                                               env->regs[3],
404b346ff46Sbellard                                               env->regs[4],
405e1a2849cSbellard                                               env->regs[5]);
406b346ff46Sbellard                 } else {
407b346ff46Sbellard                     goto error;
408b346ff46Sbellard                 }
409b346ff46Sbellard             }
410b346ff46Sbellard             break;
41143fff238Sbellard         case EXCP_INTERRUPT:
41243fff238Sbellard             /* just indicate that signals should be handled asap */
41343fff238Sbellard             break;
41468016c62Sbellard         case EXCP_PREFETCH_ABORT:
415b5ff1b31Sbellard             addr = env->cp15.c6_data;
416b5ff1b31Sbellard             goto do_segv;
41768016c62Sbellard         case EXCP_DATA_ABORT:
418b5ff1b31Sbellard             addr = env->cp15.c6_insn;
419b5ff1b31Sbellard             goto do_segv;
420b5ff1b31Sbellard         do_segv:
42168016c62Sbellard             {
42268016c62Sbellard                 info.si_signo = SIGSEGV;
42368016c62Sbellard                 info.si_errno = 0;
42468016c62Sbellard                 /* XXX: check env->error_code */
42568016c62Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
426b5ff1b31Sbellard                 info._sifields._sigfault._addr = addr;
42768016c62Sbellard                 queue_signal(info.si_signo, &info);
42868016c62Sbellard             }
42968016c62Sbellard             break;
4301fddef4bSbellard         case EXCP_DEBUG:
4311fddef4bSbellard             {
4321fddef4bSbellard                 int sig;
4331fddef4bSbellard 
4341fddef4bSbellard                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
4351fddef4bSbellard                 if (sig)
4361fddef4bSbellard                   {
4371fddef4bSbellard                     info.si_signo = sig;
4381fddef4bSbellard                     info.si_errno = 0;
4391fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
4401fddef4bSbellard                     queue_signal(info.si_signo, &info);
4411fddef4bSbellard                   }
4421fddef4bSbellard             }
4431fddef4bSbellard             break;
444b346ff46Sbellard         default:
445b346ff46Sbellard         error:
446b346ff46Sbellard             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
447b346ff46Sbellard                     trapnr);
4487fe48483Sbellard             cpu_dump_state(env, stderr, fprintf, 0);
449b346ff46Sbellard             abort();
450b346ff46Sbellard         }
451b346ff46Sbellard         process_pending_signals(env);
452b346ff46Sbellard     }
453b346ff46Sbellard }
454b346ff46Sbellard 
455b346ff46Sbellard #endif
4561b6b029eSbellard 
45793ac68bcSbellard #ifdef TARGET_SPARC
45893ac68bcSbellard 
459060366c5Sbellard //#define DEBUG_WIN
460060366c5Sbellard 
4612623cbafSbellard /* WARNING: dealing with register windows _is_ complicated. More info
4622623cbafSbellard    can be found at http://www.sics.se/~psm/sparcstack.html */
463060366c5Sbellard static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
464060366c5Sbellard {
465060366c5Sbellard     index = (index + cwp * 16) & (16 * NWINDOWS - 1);
466060366c5Sbellard     /* wrap handling : if cwp is on the last window, then we use the
467060366c5Sbellard        registers 'after' the end */
468060366c5Sbellard     if (index < 8 && env->cwp == (NWINDOWS - 1))
469060366c5Sbellard         index += (16 * NWINDOWS);
470060366c5Sbellard     return index;
471060366c5Sbellard }
472060366c5Sbellard 
4732623cbafSbellard /* save the register window 'cwp1' */
4742623cbafSbellard static inline void save_window_offset(CPUSPARCState *env, int cwp1)
475060366c5Sbellard {
4762623cbafSbellard     unsigned int i;
47753a5960aSpbrook     target_ulong sp_ptr;
478060366c5Sbellard 
47953a5960aSpbrook     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
480060366c5Sbellard #if defined(DEBUG_WIN)
481060366c5Sbellard     printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
482060366c5Sbellard            (int)sp_ptr, cwp1);
483060366c5Sbellard #endif
4842623cbafSbellard     for(i = 0; i < 16; i++) {
48553a5960aSpbrook         tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]);
48653a5960aSpbrook         sp_ptr += sizeof(target_ulong);
4872623cbafSbellard     }
488060366c5Sbellard }
489060366c5Sbellard 
490060366c5Sbellard static void save_window(CPUSPARCState *env)
491060366c5Sbellard {
4925ef54116Sbellard #ifndef TARGET_SPARC64
4932623cbafSbellard     unsigned int new_wim;
4942623cbafSbellard     new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
4952623cbafSbellard         ((1LL << NWINDOWS) - 1);
4962623cbafSbellard     save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
4972623cbafSbellard     env->wim = new_wim;
4985ef54116Sbellard #else
4995ef54116Sbellard     save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
5005ef54116Sbellard     env->cansave++;
5015ef54116Sbellard     env->canrestore--;
5025ef54116Sbellard #endif
503060366c5Sbellard }
504060366c5Sbellard 
505060366c5Sbellard static void restore_window(CPUSPARCState *env)
506060366c5Sbellard {
507060366c5Sbellard     unsigned int new_wim, i, cwp1;
50853a5960aSpbrook     target_ulong sp_ptr;
509060366c5Sbellard 
510060366c5Sbellard     new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
511060366c5Sbellard         ((1LL << NWINDOWS) - 1);
512060366c5Sbellard 
513060366c5Sbellard     /* restore the invalid window */
514060366c5Sbellard     cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
51553a5960aSpbrook     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
516060366c5Sbellard #if defined(DEBUG_WIN)
517060366c5Sbellard     printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
518060366c5Sbellard            (int)sp_ptr, cwp1);
519060366c5Sbellard #endif
5202623cbafSbellard     for(i = 0; i < 16; i++) {
52153a5960aSpbrook         env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr);
52253a5960aSpbrook         sp_ptr += sizeof(target_ulong);
5232623cbafSbellard     }
524060366c5Sbellard     env->wim = new_wim;
5255ef54116Sbellard #ifdef TARGET_SPARC64
5265ef54116Sbellard     env->canrestore++;
5275ef54116Sbellard     if (env->cleanwin < NWINDOWS - 1)
5285ef54116Sbellard 	env->cleanwin++;
5295ef54116Sbellard     env->cansave--;
5305ef54116Sbellard #endif
531060366c5Sbellard }
532060366c5Sbellard 
533060366c5Sbellard static void flush_windows(CPUSPARCState *env)
534060366c5Sbellard {
535060366c5Sbellard     int offset, cwp1;
5362623cbafSbellard 
5372623cbafSbellard     offset = 1;
538060366c5Sbellard     for(;;) {
539060366c5Sbellard         /* if restore would invoke restore_window(), then we can stop */
5402623cbafSbellard         cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
541060366c5Sbellard         if (env->wim & (1 << cwp1))
542060366c5Sbellard             break;
5432623cbafSbellard         save_window_offset(env, cwp1);
544060366c5Sbellard         offset++;
545060366c5Sbellard     }
5462623cbafSbellard     /* set wim so that restore will reload the registers */
5472623cbafSbellard     cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
5482623cbafSbellard     env->wim = 1 << cwp1;
5492623cbafSbellard #if defined(DEBUG_WIN)
5502623cbafSbellard     printf("flush_windows: nb=%d\n", offset - 1);
55180a9d035Sbellard #endif
5522623cbafSbellard }
553060366c5Sbellard 
55493ac68bcSbellard void cpu_loop (CPUSPARCState *env)
55593ac68bcSbellard {
556060366c5Sbellard     int trapnr, ret;
55761ff6f58Sbellard     target_siginfo_t info;
55893ac68bcSbellard 
55993ac68bcSbellard     while (1) {
56093ac68bcSbellard         trapnr = cpu_sparc_exec (env);
56193ac68bcSbellard 
56293ac68bcSbellard         switch (trapnr) {
5635ef54116Sbellard #ifndef TARGET_SPARC64
564060366c5Sbellard         case 0x88:
565060366c5Sbellard         case 0x90:
5665ef54116Sbellard #else
5675ef54116Sbellard         case 0x16d:
5685ef54116Sbellard #endif
569060366c5Sbellard             ret = do_syscall (env, env->gregs[1],
570060366c5Sbellard                               env->regwptr[0], env->regwptr[1],
571060366c5Sbellard                               env->regwptr[2], env->regwptr[3],
572060366c5Sbellard                               env->regwptr[4], env->regwptr[5]);
573060366c5Sbellard             if ((unsigned int)ret >= (unsigned int)(-515)) {
57427908725Sbellard #ifdef TARGET_SPARC64
57527908725Sbellard                 env->xcc |= PSR_CARRY;
57627908725Sbellard #else
57793ac68bcSbellard                 env->psr |= PSR_CARRY;
57827908725Sbellard #endif
579060366c5Sbellard                 ret = -ret;
580060366c5Sbellard             } else {
58127908725Sbellard #ifdef TARGET_SPARC64
58227908725Sbellard                 env->xcc &= ~PSR_CARRY;
58327908725Sbellard #else
584060366c5Sbellard                 env->psr &= ~PSR_CARRY;
58527908725Sbellard #endif
586060366c5Sbellard             }
587060366c5Sbellard             env->regwptr[0] = ret;
588060366c5Sbellard             /* next instruction */
589060366c5Sbellard             env->pc = env->npc;
590060366c5Sbellard             env->npc = env->npc + 4;
591060366c5Sbellard             break;
592060366c5Sbellard         case 0x83: /* flush windows */
5932623cbafSbellard             flush_windows(env);
594060366c5Sbellard             /* next instruction */
595060366c5Sbellard             env->pc = env->npc;
596060366c5Sbellard             env->npc = env->npc + 4;
597060366c5Sbellard             break;
5983475187dSbellard #ifndef TARGET_SPARC64
599060366c5Sbellard         case TT_WIN_OVF: /* window overflow */
600060366c5Sbellard             save_window(env);
601060366c5Sbellard             break;
602060366c5Sbellard         case TT_WIN_UNF: /* window underflow */
603060366c5Sbellard             restore_window(env);
60493ac68bcSbellard             break;
60561ff6f58Sbellard         case TT_TFAULT:
60661ff6f58Sbellard         case TT_DFAULT:
60761ff6f58Sbellard             {
60861ff6f58Sbellard                 info.si_signo = SIGSEGV;
60961ff6f58Sbellard                 info.si_errno = 0;
61061ff6f58Sbellard                 /* XXX: check env->error_code */
61161ff6f58Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
61261ff6f58Sbellard                 info._sifields._sigfault._addr = env->mmuregs[4];
61361ff6f58Sbellard                 queue_signal(info.si_signo, &info);
61461ff6f58Sbellard             }
61561ff6f58Sbellard             break;
6163475187dSbellard #else
6175ef54116Sbellard         case TT_SPILL: /* window overflow */
6185ef54116Sbellard             save_window(env);
6195ef54116Sbellard             break;
6205ef54116Sbellard         case TT_FILL: /* window underflow */
6215ef54116Sbellard             restore_window(env);
6225ef54116Sbellard             break;
6233475187dSbellard 	    // XXX
6243475187dSbellard #endif
62548dc41ebSbellard         case EXCP_INTERRUPT:
62648dc41ebSbellard             /* just indicate that signals should be handled asap */
627e80cfcfcSbellard             break;
6281fddef4bSbellard         case EXCP_DEBUG:
6291fddef4bSbellard             {
6301fddef4bSbellard                 int sig;
6311fddef4bSbellard 
6321fddef4bSbellard                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
6331fddef4bSbellard                 if (sig)
6341fddef4bSbellard                   {
6351fddef4bSbellard                     info.si_signo = sig;
6361fddef4bSbellard                     info.si_errno = 0;
6371fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
6381fddef4bSbellard                     queue_signal(info.si_signo, &info);
6391fddef4bSbellard                   }
6401fddef4bSbellard             }
6411fddef4bSbellard             break;
64293ac68bcSbellard         default:
643060366c5Sbellard             printf ("Unhandled trap: 0x%x\n", trapnr);
6447fe48483Sbellard             cpu_dump_state(env, stderr, fprintf, 0);
64593ac68bcSbellard             exit (1);
64693ac68bcSbellard         }
64793ac68bcSbellard         process_pending_signals (env);
64893ac68bcSbellard     }
64993ac68bcSbellard }
65093ac68bcSbellard 
65193ac68bcSbellard #endif
65293ac68bcSbellard 
65367867308Sbellard #ifdef TARGET_PPC
6549fddaa0cSbellard 
6559fddaa0cSbellard static inline uint64_t cpu_ppc_get_tb (CPUState *env)
6569fddaa0cSbellard {
6579fddaa0cSbellard     /* TO FIX */
6589fddaa0cSbellard     return 0;
6599fddaa0cSbellard }
6609fddaa0cSbellard 
6619fddaa0cSbellard uint32_t cpu_ppc_load_tbl (CPUState *env)
6629fddaa0cSbellard {
6639fddaa0cSbellard     return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
6649fddaa0cSbellard }
6659fddaa0cSbellard 
6669fddaa0cSbellard uint32_t cpu_ppc_load_tbu (CPUState *env)
6679fddaa0cSbellard {
6689fddaa0cSbellard     return cpu_ppc_get_tb(env) >> 32;
6699fddaa0cSbellard }
6709fddaa0cSbellard 
6719fddaa0cSbellard static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
6729fddaa0cSbellard {
6739fddaa0cSbellard     /* TO FIX */
6749fddaa0cSbellard }
6759fddaa0cSbellard 
6769fddaa0cSbellard void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
6779fddaa0cSbellard {
6789fddaa0cSbellard     cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
6799fddaa0cSbellard }
6809fddaa0cSbellard 
6819fddaa0cSbellard void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
6829fddaa0cSbellard {
6839fddaa0cSbellard     cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
6849fddaa0cSbellard }
6859fddaa0cSbellard 
68676a66253Sj_mayer void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
68776a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_store_tbu") ));
68876a66253Sj_mayer 
68976a66253Sj_mayer uint32_t cpu_ppc601_load_rtcu (CPUState *env)
69076a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_load_tbu") ));
69176a66253Sj_mayer 
69276a66253Sj_mayer void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
6939fddaa0cSbellard {
69476a66253Sj_mayer     cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
6959fddaa0cSbellard }
6969fddaa0cSbellard 
69776a66253Sj_mayer uint32_t cpu_ppc601_load_rtcl (CPUState *env)
6989fddaa0cSbellard {
69976a66253Sj_mayer     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
7009fddaa0cSbellard }
7019fddaa0cSbellard 
70267867308Sbellard void cpu_loop(CPUPPCState *env)
70367867308Sbellard {
70467867308Sbellard     target_siginfo_t info;
70561190b14Sbellard     int trapnr;
70661190b14Sbellard     uint32_t ret;
70767867308Sbellard 
70867867308Sbellard     for(;;) {
70967867308Sbellard         trapnr = cpu_ppc_exec(env);
71061190b14Sbellard         if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
71161190b14Sbellard             trapnr != EXCP_TRACE) {
71261190b14Sbellard             if (loglevel > 0) {
7137fe48483Sbellard                 cpu_dump_state(env, logfile, fprintf, 0);
71461190b14Sbellard             }
71561190b14Sbellard         }
71667867308Sbellard         switch(trapnr) {
71767867308Sbellard         case EXCP_NONE:
71867867308Sbellard             break;
71961190b14Sbellard         case EXCP_SYSCALL_USER:
72067867308Sbellard             /* system call */
72167867308Sbellard             /* WARNING:
72267867308Sbellard              * PPC ABI uses overflow flag in cr0 to signal an error
72367867308Sbellard              * in syscalls.
72467867308Sbellard              */
72561190b14Sbellard #if 0
72661190b14Sbellard             printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
72761190b14Sbellard                    env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
72861190b14Sbellard #endif
72967867308Sbellard             env->crf[0] &= ~0x1;
73067867308Sbellard             ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
73167867308Sbellard                              env->gpr[5], env->gpr[6], env->gpr[7],
73267867308Sbellard                              env->gpr[8]);
73367867308Sbellard             if (ret > (uint32_t)(-515)) {
73467867308Sbellard                 env->crf[0] |= 0x1;
73567867308Sbellard                 ret = -ret;
73667867308Sbellard             }
73767867308Sbellard             env->gpr[3] = ret;
73861190b14Sbellard #if 0
73961190b14Sbellard             printf("syscall returned 0x%08x (%d)\n", ret, ret);
74061190b14Sbellard #endif
74161190b14Sbellard             break;
74261190b14Sbellard         case EXCP_RESET:
74361190b14Sbellard             /* Should not happen ! */
74461190b14Sbellard             fprintf(stderr, "RESET asked... Stop emulation\n");
74561190b14Sbellard             if (loglevel)
74661190b14Sbellard                 fprintf(logfile, "RESET asked... Stop emulation\n");
74761190b14Sbellard             abort();
74861190b14Sbellard         case EXCP_MACHINE_CHECK:
74961190b14Sbellard             fprintf(stderr, "Machine check exeption...  Stop emulation\n");
75061190b14Sbellard             if (loglevel)
75161190b14Sbellard                 fprintf(logfile, "RESET asked... Stop emulation\n");
75261190b14Sbellard             info.si_signo = TARGET_SIGBUS;
75361190b14Sbellard             info.si_errno = 0;
75461190b14Sbellard             info.si_code = TARGET_BUS_OBJERR;
75561190b14Sbellard             info._sifields._sigfault._addr = env->nip - 4;
75661190b14Sbellard             queue_signal(info.si_signo, &info);
75761190b14Sbellard         case EXCP_DSI:
758e96efcfcSj_mayer             fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n",
7593fc6c082Sbellard                     env->spr[SPR_DAR]);
76061190b14Sbellard             if (loglevel) {
761e96efcfcSj_mayer                 fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n",
7623fc6c082Sbellard                         env->spr[SPR_DAR]);
76361190b14Sbellard             }
7642be0071fSbellard             switch (env->error_code & 0xFF000000) {
7652be0071fSbellard             case 0x40000000:
76661190b14Sbellard                 info.si_signo = TARGET_SIGSEGV;
76761190b14Sbellard                 info.si_errno = 0;
76861190b14Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
76961190b14Sbellard                 break;
7702be0071fSbellard             case 0x04000000:
77161190b14Sbellard                 info.si_signo = TARGET_SIGILL;
77261190b14Sbellard                 info.si_errno = 0;
77361190b14Sbellard                 info.si_code = TARGET_ILL_ILLADR;
77461190b14Sbellard                 break;
7752be0071fSbellard             case 0x08000000:
77661190b14Sbellard                 info.si_signo = TARGET_SIGSEGV;
77761190b14Sbellard                 info.si_errno = 0;
77861190b14Sbellard                 info.si_code = TARGET_SEGV_ACCERR;
77961190b14Sbellard                 break;
78061190b14Sbellard             default:
78161190b14Sbellard                 /* Let's send a regular segfault... */
78261190b14Sbellard                 fprintf(stderr, "Invalid segfault errno (%02x)\n",
78361190b14Sbellard                         env->error_code);
78461190b14Sbellard                 if (loglevel) {
78561190b14Sbellard                     fprintf(logfile, "Invalid segfault errno (%02x)\n",
78661190b14Sbellard                             env->error_code);
78761190b14Sbellard                 }
78861190b14Sbellard                 info.si_signo = TARGET_SIGSEGV;
78961190b14Sbellard                 info.si_errno = 0;
79061190b14Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
79167867308Sbellard                 break;
79267867308Sbellard             }
79361190b14Sbellard             info._sifields._sigfault._addr = env->nip;
79461190b14Sbellard             queue_signal(info.si_signo, &info);
79561190b14Sbellard             break;
79661190b14Sbellard         case EXCP_ISI:
79761190b14Sbellard             fprintf(stderr, "Invalid instruction fetch\n");
79861190b14Sbellard             if (loglevel)
79961190b14Sbellard                 fprintf(logfile, "Invalid instruction fetch\n");
8002be0071fSbellard             switch (env->error_code & 0xFF000000) {
8012be0071fSbellard             case 0x40000000:
80261190b14Sbellard                 info.si_signo = TARGET_SIGSEGV;
80361190b14Sbellard             info.si_errno = 0;
80461190b14Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
80561190b14Sbellard                 break;
8062be0071fSbellard             case 0x10000000:
8072be0071fSbellard             case 0x08000000:
80861190b14Sbellard                 info.si_signo = TARGET_SIGSEGV;
80961190b14Sbellard                 info.si_errno = 0;
81061190b14Sbellard                 info.si_code = TARGET_SEGV_ACCERR;
81161190b14Sbellard                 break;
81267867308Sbellard             default:
81361190b14Sbellard                 /* Let's send a regular segfault... */
81461190b14Sbellard                 fprintf(stderr, "Invalid segfault errno (%02x)\n",
81561190b14Sbellard                         env->error_code);
81661190b14Sbellard                 if (loglevel) {
81761190b14Sbellard                     fprintf(logfile, "Invalid segfault errno (%02x)\n",
81861190b14Sbellard                             env->error_code);
81961190b14Sbellard                 }
82061190b14Sbellard                 info.si_signo = TARGET_SIGSEGV;
82161190b14Sbellard                 info.si_errno = 0;
82261190b14Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
82361190b14Sbellard                 break;
82461190b14Sbellard             }
82561190b14Sbellard             info._sifields._sigfault._addr = env->nip - 4;
82661190b14Sbellard             queue_signal(info.si_signo, &info);
82761190b14Sbellard             break;
82861190b14Sbellard         case EXCP_EXTERNAL:
82961190b14Sbellard             /* Should not happen ! */
83061190b14Sbellard             fprintf(stderr, "External interruption... Stop emulation\n");
83161190b14Sbellard             if (loglevel)
83261190b14Sbellard                 fprintf(logfile, "External interruption... Stop emulation\n");
83361190b14Sbellard             abort();
83461190b14Sbellard         case EXCP_ALIGN:
83561190b14Sbellard             fprintf(stderr, "Invalid unaligned memory access\n");
83661190b14Sbellard             if (loglevel)
83761190b14Sbellard                 fprintf(logfile, "Invalid unaligned memory access\n");
83861190b14Sbellard             info.si_signo = TARGET_SIGBUS;
83961190b14Sbellard             info.si_errno = 0;
84061190b14Sbellard             info.si_code = TARGET_BUS_ADRALN;
84161190b14Sbellard             info._sifields._sigfault._addr = env->nip - 4;
84261190b14Sbellard             queue_signal(info.si_signo, &info);
84361190b14Sbellard             break;
84461190b14Sbellard         case EXCP_PROGRAM:
84561190b14Sbellard             switch (env->error_code & ~0xF) {
84661190b14Sbellard             case EXCP_FP:
84761190b14Sbellard             fprintf(stderr, "Program exception\n");
84861190b14Sbellard                 if (loglevel)
84961190b14Sbellard                     fprintf(logfile, "Program exception\n");
85061190b14Sbellard                 /* Set FX */
85161190b14Sbellard                 env->fpscr[7] |= 0x8;
85261190b14Sbellard                 /* Finally, update FEX */
85361190b14Sbellard                 if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
85461190b14Sbellard                     ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
85561190b14Sbellard                     env->fpscr[7] |= 0x4;
85661190b14Sbellard                 info.si_signo = TARGET_SIGFPE;
85761190b14Sbellard                 info.si_errno = 0;
85861190b14Sbellard                 switch (env->error_code & 0xF) {
85961190b14Sbellard                 case EXCP_FP_OX:
86061190b14Sbellard                     info.si_code = TARGET_FPE_FLTOVF;
86161190b14Sbellard                     break;
86261190b14Sbellard                 case EXCP_FP_UX:
86361190b14Sbellard                     info.si_code = TARGET_FPE_FLTUND;
86461190b14Sbellard                     break;
86561190b14Sbellard                 case EXCP_FP_ZX:
86661190b14Sbellard                 case EXCP_FP_VXZDZ:
86761190b14Sbellard                     info.si_code = TARGET_FPE_FLTDIV;
86861190b14Sbellard                     break;
86961190b14Sbellard                 case EXCP_FP_XX:
87061190b14Sbellard                     info.si_code = TARGET_FPE_FLTRES;
87161190b14Sbellard                     break;
87261190b14Sbellard                 case EXCP_FP_VXSOFT:
87361190b14Sbellard                     info.si_code = TARGET_FPE_FLTINV;
87461190b14Sbellard                     break;
87561190b14Sbellard                 case EXCP_FP_VXNAN:
87661190b14Sbellard                 case EXCP_FP_VXISI:
87761190b14Sbellard                 case EXCP_FP_VXIDI:
87861190b14Sbellard                 case EXCP_FP_VXIMZ:
87961190b14Sbellard                 case EXCP_FP_VXVC:
88061190b14Sbellard                 case EXCP_FP_VXSQRT:
88161190b14Sbellard                 case EXCP_FP_VXCVI:
88261190b14Sbellard                     info.si_code = TARGET_FPE_FLTSUB;
88361190b14Sbellard                     break;
88461190b14Sbellard                 default:
88561190b14Sbellard                     fprintf(stderr, "Unknown floating point exception "
88661190b14Sbellard                             "(%02x)\n", env->error_code);
88761190b14Sbellard                     if (loglevel) {
88861190b14Sbellard                         fprintf(logfile, "Unknown floating point exception "
88961190b14Sbellard                                 "(%02x)\n", env->error_code & 0xF);
89061190b14Sbellard                     }
89161190b14Sbellard                 }
89261190b14Sbellard             break;
89361190b14Sbellard         case EXCP_INVAL:
89461190b14Sbellard                 fprintf(stderr, "Invalid instruction\n");
89561190b14Sbellard                 if (loglevel)
89661190b14Sbellard                     fprintf(logfile, "Invalid instruction\n");
89761190b14Sbellard                 info.si_signo = TARGET_SIGILL;
89861190b14Sbellard                 info.si_errno = 0;
89961190b14Sbellard                 switch (env->error_code & 0xF) {
90061190b14Sbellard                 case EXCP_INVAL_INVAL:
90161190b14Sbellard                     info.si_code = TARGET_ILL_ILLOPC;
90261190b14Sbellard                     break;
90361190b14Sbellard                 case EXCP_INVAL_LSWX:
90461190b14Sbellard             info.si_code = TARGET_ILL_ILLOPN;
90561190b14Sbellard                     break;
90661190b14Sbellard                 case EXCP_INVAL_SPR:
90761190b14Sbellard                     info.si_code = TARGET_ILL_PRVREG;
90861190b14Sbellard                     break;
90961190b14Sbellard                 case EXCP_INVAL_FP:
91061190b14Sbellard                     info.si_code = TARGET_ILL_COPROC;
91161190b14Sbellard                     break;
91261190b14Sbellard                 default:
91361190b14Sbellard                     fprintf(stderr, "Unknown invalid operation (%02x)\n",
91461190b14Sbellard                             env->error_code & 0xF);
91561190b14Sbellard                     if (loglevel) {
91661190b14Sbellard                         fprintf(logfile, "Unknown invalid operation (%02x)\n",
91761190b14Sbellard                                 env->error_code & 0xF);
91861190b14Sbellard                     }
91961190b14Sbellard                     info.si_code = TARGET_ILL_ILLADR;
92061190b14Sbellard                     break;
92161190b14Sbellard                 }
92261190b14Sbellard                 break;
92361190b14Sbellard             case EXCP_PRIV:
92461190b14Sbellard                 fprintf(stderr, "Privilege violation\n");
92561190b14Sbellard                 if (loglevel)
92661190b14Sbellard                     fprintf(logfile, "Privilege violation\n");
92761190b14Sbellard                 info.si_signo = TARGET_SIGILL;
92861190b14Sbellard                 info.si_errno = 0;
92961190b14Sbellard                 switch (env->error_code & 0xF) {
93061190b14Sbellard                 case EXCP_PRIV_OPC:
93161190b14Sbellard                     info.si_code = TARGET_ILL_PRVOPC;
93261190b14Sbellard                     break;
93361190b14Sbellard                 case EXCP_PRIV_REG:
93461190b14Sbellard                     info.si_code = TARGET_ILL_PRVREG;
93561190b14Sbellard                 break;
93661190b14Sbellard                 default:
93761190b14Sbellard                     fprintf(stderr, "Unknown privilege violation (%02x)\n",
93861190b14Sbellard                             env->error_code & 0xF);
93961190b14Sbellard                     info.si_code = TARGET_ILL_PRVOPC;
94061190b14Sbellard                     break;
94161190b14Sbellard                 }
94261190b14Sbellard                 break;
94361190b14Sbellard             case EXCP_TRAP:
94461190b14Sbellard                 fprintf(stderr, "Tried to call a TRAP\n");
94561190b14Sbellard                 if (loglevel)
94661190b14Sbellard                     fprintf(logfile, "Tried to call a TRAP\n");
94761190b14Sbellard                 abort();
94861190b14Sbellard             default:
94961190b14Sbellard                 /* Should not happen ! */
95061190b14Sbellard                 fprintf(stderr, "Unknown program exception (%02x)\n",
95161190b14Sbellard                         env->error_code);
95261190b14Sbellard                 if (loglevel) {
95361190b14Sbellard                     fprintf(logfile, "Unknwon program exception (%02x)\n",
95461190b14Sbellard                             env->error_code);
95561190b14Sbellard                 }
95667867308Sbellard                 abort();
95767867308Sbellard             }
95861190b14Sbellard             info._sifields._sigfault._addr = env->nip - 4;
95961190b14Sbellard             queue_signal(info.si_signo, &info);
96061190b14Sbellard             break;
96161190b14Sbellard         case EXCP_NO_FP:
96261190b14Sbellard             fprintf(stderr, "No floating point allowed\n");
96361190b14Sbellard             if (loglevel)
96461190b14Sbellard                 fprintf(logfile, "No floating point allowed\n");
96561190b14Sbellard             info.si_signo = TARGET_SIGILL;
96661190b14Sbellard             info.si_errno = 0;
96761190b14Sbellard             info.si_code = TARGET_ILL_COPROC;
96861190b14Sbellard             info._sifields._sigfault._addr = env->nip - 4;
96961190b14Sbellard             queue_signal(info.si_signo, &info);
97061190b14Sbellard             break;
97161190b14Sbellard         case EXCP_DECR:
97261190b14Sbellard             /* Should not happen ! */
97361190b14Sbellard             fprintf(stderr, "Decrementer exception\n");
97461190b14Sbellard             if (loglevel)
97561190b14Sbellard                 fprintf(logfile, "Decrementer exception\n");
97661190b14Sbellard             abort();
97761190b14Sbellard         case EXCP_TRACE:
97861190b14Sbellard             /* Do nothing: we use this to trace execution */
97961190b14Sbellard             break;
98061190b14Sbellard         case EXCP_FP_ASSIST:
98161190b14Sbellard             /* Should not happen ! */
98261190b14Sbellard             fprintf(stderr, "Floating point assist exception\n");
98361190b14Sbellard             if (loglevel)
98461190b14Sbellard                 fprintf(logfile, "Floating point assist exception\n");
98561190b14Sbellard             abort();
98661190b14Sbellard         case EXCP_MTMSR:
98761190b14Sbellard             /* We reloaded the msr, just go on */
9889fddaa0cSbellard             if (msr_pr == 0) {
98961190b14Sbellard                 fprintf(stderr, "Tried to go into supervisor mode !\n");
99061190b14Sbellard                 if (loglevel)
99161190b14Sbellard                     fprintf(logfile, "Tried to go into supervisor mode !\n");
99261190b14Sbellard                 abort();
99361190b14Sbellard         }
99461190b14Sbellard             break;
99561190b14Sbellard         case EXCP_BRANCH:
99661190b14Sbellard             /* We stopped because of a jump... */
99761190b14Sbellard             break;
99861190b14Sbellard         case EXCP_INTERRUPT:
99961190b14Sbellard             /* Don't know why this should ever happen... */
100061190b14Sbellard             break;
1001a541f297Sbellard         case EXCP_DEBUG:
10021fddef4bSbellard             {
10031fddef4bSbellard                 int sig;
10041fddef4bSbellard 
10051fddef4bSbellard                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
10061fddef4bSbellard                 if (sig)
10071fddef4bSbellard                   {
10081fddef4bSbellard                     info.si_signo = sig;
10091fddef4bSbellard                     info.si_errno = 0;
10101fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
10111fddef4bSbellard                     queue_signal(info.si_signo, &info);
10121fddef4bSbellard                   }
10131fddef4bSbellard             }
1014a541f297Sbellard             break;
101561190b14Sbellard         default:
101661190b14Sbellard             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
101761190b14Sbellard                     trapnr);
101861190b14Sbellard             if (loglevel) {
101961190b14Sbellard                 fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
102061190b14Sbellard                         "0x%02x - aborting\n", trapnr, env->error_code);
102161190b14Sbellard             }
102261190b14Sbellard             abort();
102361190b14Sbellard         }
102467867308Sbellard         process_pending_signals(env);
102567867308Sbellard     }
102667867308Sbellard }
102767867308Sbellard #endif
102867867308Sbellard 
1029048f6b4dSbellard #ifdef TARGET_MIPS
1030048f6b4dSbellard 
1031048f6b4dSbellard #define MIPS_SYS(name, args) args,
1032048f6b4dSbellard 
1033048f6b4dSbellard static const uint8_t mips_syscall_args[] = {
1034048f6b4dSbellard 	MIPS_SYS(sys_syscall	, 0)	/* 4000 */
1035048f6b4dSbellard 	MIPS_SYS(sys_exit	, 1)
1036048f6b4dSbellard 	MIPS_SYS(sys_fork	, 0)
1037048f6b4dSbellard 	MIPS_SYS(sys_read	, 3)
1038048f6b4dSbellard 	MIPS_SYS(sys_write	, 3)
1039048f6b4dSbellard 	MIPS_SYS(sys_open	, 3)	/* 4005 */
1040048f6b4dSbellard 	MIPS_SYS(sys_close	, 1)
1041048f6b4dSbellard 	MIPS_SYS(sys_waitpid	, 3)
1042048f6b4dSbellard 	MIPS_SYS(sys_creat	, 2)
1043048f6b4dSbellard 	MIPS_SYS(sys_link	, 2)
1044048f6b4dSbellard 	MIPS_SYS(sys_unlink	, 1)	/* 4010 */
1045048f6b4dSbellard 	MIPS_SYS(sys_execve	, 0)
1046048f6b4dSbellard 	MIPS_SYS(sys_chdir	, 1)
1047048f6b4dSbellard 	MIPS_SYS(sys_time	, 1)
1048048f6b4dSbellard 	MIPS_SYS(sys_mknod	, 3)
1049048f6b4dSbellard 	MIPS_SYS(sys_chmod	, 2)	/* 4015 */
1050048f6b4dSbellard 	MIPS_SYS(sys_lchown	, 3)
1051048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1052048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_stat */
1053048f6b4dSbellard 	MIPS_SYS(sys_lseek	, 3)
1054048f6b4dSbellard 	MIPS_SYS(sys_getpid	, 0)	/* 4020 */
1055048f6b4dSbellard 	MIPS_SYS(sys_mount	, 5)
1056048f6b4dSbellard 	MIPS_SYS(sys_oldumount	, 1)
1057048f6b4dSbellard 	MIPS_SYS(sys_setuid	, 1)
1058048f6b4dSbellard 	MIPS_SYS(sys_getuid	, 0)
1059048f6b4dSbellard 	MIPS_SYS(sys_stime	, 1)	/* 4025 */
1060048f6b4dSbellard 	MIPS_SYS(sys_ptrace	, 4)
1061048f6b4dSbellard 	MIPS_SYS(sys_alarm	, 1)
1062048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_fstat */
1063048f6b4dSbellard 	MIPS_SYS(sys_pause	, 0)
1064048f6b4dSbellard 	MIPS_SYS(sys_utime	, 2)	/* 4030 */
1065048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1066048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1067048f6b4dSbellard 	MIPS_SYS(sys_access	, 2)
1068048f6b4dSbellard 	MIPS_SYS(sys_nice	, 1)
1069048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4035 */
1070048f6b4dSbellard 	MIPS_SYS(sys_sync	, 0)
1071048f6b4dSbellard 	MIPS_SYS(sys_kill	, 2)
1072048f6b4dSbellard 	MIPS_SYS(sys_rename	, 2)
1073048f6b4dSbellard 	MIPS_SYS(sys_mkdir	, 2)
1074048f6b4dSbellard 	MIPS_SYS(sys_rmdir	, 1)	/* 4040 */
1075048f6b4dSbellard 	MIPS_SYS(sys_dup		, 1)
1076048f6b4dSbellard 	MIPS_SYS(sys_pipe	, 0)
1077048f6b4dSbellard 	MIPS_SYS(sys_times	, 1)
1078048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1079048f6b4dSbellard 	MIPS_SYS(sys_brk		, 1)	/* 4045 */
1080048f6b4dSbellard 	MIPS_SYS(sys_setgid	, 1)
1081048f6b4dSbellard 	MIPS_SYS(sys_getgid	, 0)
1082048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was signal(2) */
1083048f6b4dSbellard 	MIPS_SYS(sys_geteuid	, 0)
1084048f6b4dSbellard 	MIPS_SYS(sys_getegid	, 0)	/* 4050 */
1085048f6b4dSbellard 	MIPS_SYS(sys_acct	, 0)
1086048f6b4dSbellard 	MIPS_SYS(sys_umount	, 2)
1087048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1088048f6b4dSbellard 	MIPS_SYS(sys_ioctl	, 3)
1089048f6b4dSbellard 	MIPS_SYS(sys_fcntl	, 3)	/* 4055 */
1090048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 2)
1091048f6b4dSbellard 	MIPS_SYS(sys_setpgid	, 2)
1092048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1093048f6b4dSbellard 	MIPS_SYS(sys_olduname	, 1)
1094048f6b4dSbellard 	MIPS_SYS(sys_umask	, 1)	/* 4060 */
1095048f6b4dSbellard 	MIPS_SYS(sys_chroot	, 1)
1096048f6b4dSbellard 	MIPS_SYS(sys_ustat	, 2)
1097048f6b4dSbellard 	MIPS_SYS(sys_dup2	, 2)
1098048f6b4dSbellard 	MIPS_SYS(sys_getppid	, 0)
1099048f6b4dSbellard 	MIPS_SYS(sys_getpgrp	, 0)	/* 4065 */
1100048f6b4dSbellard 	MIPS_SYS(sys_setsid	, 0)
1101048f6b4dSbellard 	MIPS_SYS(sys_sigaction	, 3)
1102048f6b4dSbellard 	MIPS_SYS(sys_sgetmask	, 0)
1103048f6b4dSbellard 	MIPS_SYS(sys_ssetmask	, 1)
1104048f6b4dSbellard 	MIPS_SYS(sys_setreuid	, 2)	/* 4070 */
1105048f6b4dSbellard 	MIPS_SYS(sys_setregid	, 2)
1106048f6b4dSbellard 	MIPS_SYS(sys_sigsuspend	, 0)
1107048f6b4dSbellard 	MIPS_SYS(sys_sigpending	, 1)
1108048f6b4dSbellard 	MIPS_SYS(sys_sethostname	, 2)
1109048f6b4dSbellard 	MIPS_SYS(sys_setrlimit	, 2)	/* 4075 */
1110048f6b4dSbellard 	MIPS_SYS(sys_getrlimit	, 2)
1111048f6b4dSbellard 	MIPS_SYS(sys_getrusage	, 2)
1112048f6b4dSbellard 	MIPS_SYS(sys_gettimeofday, 2)
1113048f6b4dSbellard 	MIPS_SYS(sys_settimeofday, 2)
1114048f6b4dSbellard 	MIPS_SYS(sys_getgroups	, 2)	/* 4080 */
1115048f6b4dSbellard 	MIPS_SYS(sys_setgroups	, 2)
1116048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* old_select */
1117048f6b4dSbellard 	MIPS_SYS(sys_symlink	, 2)
1118048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_lstat */
1119048f6b4dSbellard 	MIPS_SYS(sys_readlink	, 3)	/* 4085 */
1120048f6b4dSbellard 	MIPS_SYS(sys_uselib	, 1)
1121048f6b4dSbellard 	MIPS_SYS(sys_swapon	, 2)
1122048f6b4dSbellard 	MIPS_SYS(sys_reboot	, 3)
1123048f6b4dSbellard 	MIPS_SYS(old_readdir	, 3)
1124048f6b4dSbellard 	MIPS_SYS(old_mmap	, 6)	/* 4090 */
1125048f6b4dSbellard 	MIPS_SYS(sys_munmap	, 2)
1126048f6b4dSbellard 	MIPS_SYS(sys_truncate	, 2)
1127048f6b4dSbellard 	MIPS_SYS(sys_ftruncate	, 2)
1128048f6b4dSbellard 	MIPS_SYS(sys_fchmod	, 2)
1129048f6b4dSbellard 	MIPS_SYS(sys_fchown	, 3)	/* 4095 */
1130048f6b4dSbellard 	MIPS_SYS(sys_getpriority	, 2)
1131048f6b4dSbellard 	MIPS_SYS(sys_setpriority	, 3)
1132048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1133048f6b4dSbellard 	MIPS_SYS(sys_statfs	, 2)
1134048f6b4dSbellard 	MIPS_SYS(sys_fstatfs	, 2)	/* 4100 */
1135048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was ioperm(2) */
1136048f6b4dSbellard 	MIPS_SYS(sys_socketcall	, 2)
1137048f6b4dSbellard 	MIPS_SYS(sys_syslog	, 3)
1138048f6b4dSbellard 	MIPS_SYS(sys_setitimer	, 3)
1139048f6b4dSbellard 	MIPS_SYS(sys_getitimer	, 2)	/* 4105 */
1140048f6b4dSbellard 	MIPS_SYS(sys_newstat	, 2)
1141048f6b4dSbellard 	MIPS_SYS(sys_newlstat	, 2)
1142048f6b4dSbellard 	MIPS_SYS(sys_newfstat	, 2)
1143048f6b4dSbellard 	MIPS_SYS(sys_uname	, 1)
1144048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4110 was iopl(2) */
1145048f6b4dSbellard 	MIPS_SYS(sys_vhangup	, 0)
1146048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_idle() */
1147048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_vm86 */
1148048f6b4dSbellard 	MIPS_SYS(sys_wait4	, 4)
1149048f6b4dSbellard 	MIPS_SYS(sys_swapoff	, 1)	/* 4115 */
1150048f6b4dSbellard 	MIPS_SYS(sys_sysinfo	, 1)
1151048f6b4dSbellard 	MIPS_SYS(sys_ipc		, 6)
1152048f6b4dSbellard 	MIPS_SYS(sys_fsync	, 1)
1153048f6b4dSbellard 	MIPS_SYS(sys_sigreturn	, 0)
1154048f6b4dSbellard 	MIPS_SYS(sys_clone	, 0)	/* 4120 */
1155048f6b4dSbellard 	MIPS_SYS(sys_setdomainname, 2)
1156048f6b4dSbellard 	MIPS_SYS(sys_newuname	, 1)
1157048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_modify_ldt */
1158048f6b4dSbellard 	MIPS_SYS(sys_adjtimex	, 1)
1159048f6b4dSbellard 	MIPS_SYS(sys_mprotect	, 3)	/* 4125 */
1160048f6b4dSbellard 	MIPS_SYS(sys_sigprocmask	, 3)
1161048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was create_module */
1162048f6b4dSbellard 	MIPS_SYS(sys_init_module	, 5)
1163048f6b4dSbellard 	MIPS_SYS(sys_delete_module, 1)
1164048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4130	was get_kernel_syms */
1165048f6b4dSbellard 	MIPS_SYS(sys_quotactl	, 0)
1166048f6b4dSbellard 	MIPS_SYS(sys_getpgid	, 1)
1167048f6b4dSbellard 	MIPS_SYS(sys_fchdir	, 1)
1168048f6b4dSbellard 	MIPS_SYS(sys_bdflush	, 2)
1169048f6b4dSbellard 	MIPS_SYS(sys_sysfs	, 3)	/* 4135 */
1170048f6b4dSbellard 	MIPS_SYS(sys_personality	, 1)
1171048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* for afs_syscall */
1172048f6b4dSbellard 	MIPS_SYS(sys_setfsuid	, 1)
1173048f6b4dSbellard 	MIPS_SYS(sys_setfsgid	, 1)
1174048f6b4dSbellard 	MIPS_SYS(sys_llseek	, 5)	/* 4140 */
1175048f6b4dSbellard 	MIPS_SYS(sys_getdents	, 3)
1176048f6b4dSbellard 	MIPS_SYS(sys_select	, 5)
1177048f6b4dSbellard 	MIPS_SYS(sys_flock	, 2)
1178048f6b4dSbellard 	MIPS_SYS(sys_msync	, 3)
1179048f6b4dSbellard 	MIPS_SYS(sys_readv	, 3)	/* 4145 */
1180048f6b4dSbellard 	MIPS_SYS(sys_writev	, 3)
1181048f6b4dSbellard 	MIPS_SYS(sys_cacheflush	, 3)
1182048f6b4dSbellard 	MIPS_SYS(sys_cachectl	, 3)
1183048f6b4dSbellard 	MIPS_SYS(sys_sysmips	, 4)
1184048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4150 */
1185048f6b4dSbellard 	MIPS_SYS(sys_getsid	, 1)
1186048f6b4dSbellard 	MIPS_SYS(sys_fdatasync	, 0)
1187048f6b4dSbellard 	MIPS_SYS(sys_sysctl	, 1)
1188048f6b4dSbellard 	MIPS_SYS(sys_mlock	, 2)
1189048f6b4dSbellard 	MIPS_SYS(sys_munlock	, 2)	/* 4155 */
1190048f6b4dSbellard 	MIPS_SYS(sys_mlockall	, 1)
1191048f6b4dSbellard 	MIPS_SYS(sys_munlockall	, 0)
1192048f6b4dSbellard 	MIPS_SYS(sys_sched_setparam, 2)
1193048f6b4dSbellard 	MIPS_SYS(sys_sched_getparam, 2)
1194048f6b4dSbellard 	MIPS_SYS(sys_sched_setscheduler, 3)	/* 4160 */
1195048f6b4dSbellard 	MIPS_SYS(sys_sched_getscheduler, 1)
1196048f6b4dSbellard 	MIPS_SYS(sys_sched_yield	, 0)
1197048f6b4dSbellard 	MIPS_SYS(sys_sched_get_priority_max, 1)
1198048f6b4dSbellard 	MIPS_SYS(sys_sched_get_priority_min, 1)
1199048f6b4dSbellard 	MIPS_SYS(sys_sched_rr_get_interval, 2)	/* 4165 */
1200048f6b4dSbellard 	MIPS_SYS(sys_nanosleep,	2)
1201048f6b4dSbellard 	MIPS_SYS(sys_mremap	, 4)
1202048f6b4dSbellard 	MIPS_SYS(sys_accept	, 3)
1203048f6b4dSbellard 	MIPS_SYS(sys_bind	, 3)
1204048f6b4dSbellard 	MIPS_SYS(sys_connect	, 3)	/* 4170 */
1205048f6b4dSbellard 	MIPS_SYS(sys_getpeername	, 3)
1206048f6b4dSbellard 	MIPS_SYS(sys_getsockname	, 3)
1207048f6b4dSbellard 	MIPS_SYS(sys_getsockopt	, 5)
1208048f6b4dSbellard 	MIPS_SYS(sys_listen	, 2)
1209048f6b4dSbellard 	MIPS_SYS(sys_recv	, 4)	/* 4175 */
1210048f6b4dSbellard 	MIPS_SYS(sys_recvfrom	, 6)
1211048f6b4dSbellard 	MIPS_SYS(sys_recvmsg	, 3)
1212048f6b4dSbellard 	MIPS_SYS(sys_send	, 4)
1213048f6b4dSbellard 	MIPS_SYS(sys_sendmsg	, 3)
1214048f6b4dSbellard 	MIPS_SYS(sys_sendto	, 6)	/* 4180 */
1215048f6b4dSbellard 	MIPS_SYS(sys_setsockopt	, 5)
1216048f6b4dSbellard 	MIPS_SYS(sys_shutdown	, 2)
1217048f6b4dSbellard 	MIPS_SYS(sys_socket	, 3)
1218048f6b4dSbellard 	MIPS_SYS(sys_socketpair	, 4)
1219048f6b4dSbellard 	MIPS_SYS(sys_setresuid	, 3)	/* 4185 */
1220048f6b4dSbellard 	MIPS_SYS(sys_getresuid	, 3)
1221048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_query_module */
1222048f6b4dSbellard 	MIPS_SYS(sys_poll	, 3)
1223048f6b4dSbellard 	MIPS_SYS(sys_nfsservctl	, 3)
1224048f6b4dSbellard 	MIPS_SYS(sys_setresgid	, 3)	/* 4190 */
1225048f6b4dSbellard 	MIPS_SYS(sys_getresgid	, 3)
1226048f6b4dSbellard 	MIPS_SYS(sys_prctl	, 5)
1227048f6b4dSbellard 	MIPS_SYS(sys_rt_sigreturn, 0)
1228048f6b4dSbellard 	MIPS_SYS(sys_rt_sigaction, 4)
1229048f6b4dSbellard 	MIPS_SYS(sys_rt_sigprocmask, 4)	/* 4195 */
1230048f6b4dSbellard 	MIPS_SYS(sys_rt_sigpending, 2)
1231048f6b4dSbellard 	MIPS_SYS(sys_rt_sigtimedwait, 4)
1232048f6b4dSbellard 	MIPS_SYS(sys_rt_sigqueueinfo, 3)
1233048f6b4dSbellard 	MIPS_SYS(sys_rt_sigsuspend, 0)
1234048f6b4dSbellard 	MIPS_SYS(sys_pread64	, 6)	/* 4200 */
1235048f6b4dSbellard 	MIPS_SYS(sys_pwrite64	, 6)
1236048f6b4dSbellard 	MIPS_SYS(sys_chown	, 3)
1237048f6b4dSbellard 	MIPS_SYS(sys_getcwd	, 2)
1238048f6b4dSbellard 	MIPS_SYS(sys_capget	, 2)
1239048f6b4dSbellard 	MIPS_SYS(sys_capset	, 2)	/* 4205 */
1240048f6b4dSbellard 	MIPS_SYS(sys_sigaltstack	, 0)
1241048f6b4dSbellard 	MIPS_SYS(sys_sendfile	, 4)
1242048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1243048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1244048f6b4dSbellard 	MIPS_SYS(sys_mmap2	, 6)	/* 4210 */
1245048f6b4dSbellard 	MIPS_SYS(sys_truncate64	, 4)
1246048f6b4dSbellard 	MIPS_SYS(sys_ftruncate64	, 4)
1247048f6b4dSbellard 	MIPS_SYS(sys_stat64	, 2)
1248048f6b4dSbellard 	MIPS_SYS(sys_lstat64	, 2)
1249048f6b4dSbellard 	MIPS_SYS(sys_fstat64	, 2)	/* 4215 */
1250048f6b4dSbellard 	MIPS_SYS(sys_pivot_root	, 2)
1251048f6b4dSbellard 	MIPS_SYS(sys_mincore	, 3)
1252048f6b4dSbellard 	MIPS_SYS(sys_madvise	, 3)
1253048f6b4dSbellard 	MIPS_SYS(sys_getdents64	, 3)
1254048f6b4dSbellard 	MIPS_SYS(sys_fcntl64	, 3)	/* 4220 */
1255048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1256048f6b4dSbellard 	MIPS_SYS(sys_gettid	, 0)
1257048f6b4dSbellard 	MIPS_SYS(sys_readahead	, 5)
1258048f6b4dSbellard 	MIPS_SYS(sys_setxattr	, 5)
1259048f6b4dSbellard 	MIPS_SYS(sys_lsetxattr	, 5)	/* 4225 */
1260048f6b4dSbellard 	MIPS_SYS(sys_fsetxattr	, 5)
1261048f6b4dSbellard 	MIPS_SYS(sys_getxattr	, 4)
1262048f6b4dSbellard 	MIPS_SYS(sys_lgetxattr	, 4)
1263048f6b4dSbellard 	MIPS_SYS(sys_fgetxattr	, 4)
1264048f6b4dSbellard 	MIPS_SYS(sys_listxattr	, 3)	/* 4230 */
1265048f6b4dSbellard 	MIPS_SYS(sys_llistxattr	, 3)
1266048f6b4dSbellard 	MIPS_SYS(sys_flistxattr	, 3)
1267048f6b4dSbellard 	MIPS_SYS(sys_removexattr	, 2)
1268048f6b4dSbellard 	MIPS_SYS(sys_lremovexattr, 2)
1269048f6b4dSbellard 	MIPS_SYS(sys_fremovexattr, 2)	/* 4235 */
1270048f6b4dSbellard 	MIPS_SYS(sys_tkill	, 2)
1271048f6b4dSbellard 	MIPS_SYS(sys_sendfile64	, 5)
1272048f6b4dSbellard 	MIPS_SYS(sys_futex	, 2)
1273048f6b4dSbellard 	MIPS_SYS(sys_sched_setaffinity, 3)
1274048f6b4dSbellard 	MIPS_SYS(sys_sched_getaffinity, 3)	/* 4240 */
1275048f6b4dSbellard 	MIPS_SYS(sys_io_setup	, 2)
1276048f6b4dSbellard 	MIPS_SYS(sys_io_destroy	, 1)
1277048f6b4dSbellard 	MIPS_SYS(sys_io_getevents, 5)
1278048f6b4dSbellard 	MIPS_SYS(sys_io_submit	, 3)
1279048f6b4dSbellard 	MIPS_SYS(sys_io_cancel	, 3)	/* 4245 */
1280048f6b4dSbellard 	MIPS_SYS(sys_exit_group	, 1)
1281048f6b4dSbellard 	MIPS_SYS(sys_lookup_dcookie, 3)
1282048f6b4dSbellard 	MIPS_SYS(sys_epoll_create, 1)
1283048f6b4dSbellard 	MIPS_SYS(sys_epoll_ctl	, 4)
1284048f6b4dSbellard 	MIPS_SYS(sys_epoll_wait	, 3)	/* 4250 */
1285048f6b4dSbellard 	MIPS_SYS(sys_remap_file_pages, 5)
1286048f6b4dSbellard 	MIPS_SYS(sys_set_tid_address, 1)
1287048f6b4dSbellard 	MIPS_SYS(sys_restart_syscall, 0)
1288048f6b4dSbellard 	MIPS_SYS(sys_fadvise64_64, 7)
1289048f6b4dSbellard 	MIPS_SYS(sys_statfs64	, 3)	/* 4255 */
1290048f6b4dSbellard 	MIPS_SYS(sys_fstatfs64	, 2)
1291048f6b4dSbellard 	MIPS_SYS(sys_timer_create, 3)
1292048f6b4dSbellard 	MIPS_SYS(sys_timer_settime, 4)
1293048f6b4dSbellard 	MIPS_SYS(sys_timer_gettime, 2)
1294048f6b4dSbellard 	MIPS_SYS(sys_timer_getoverrun, 1)	/* 4260 */
1295048f6b4dSbellard 	MIPS_SYS(sys_timer_delete, 1)
1296048f6b4dSbellard 	MIPS_SYS(sys_clock_settime, 2)
1297048f6b4dSbellard 	MIPS_SYS(sys_clock_gettime, 2)
1298048f6b4dSbellard 	MIPS_SYS(sys_clock_getres, 2)
1299048f6b4dSbellard 	MIPS_SYS(sys_clock_nanosleep, 4)	/* 4265 */
1300048f6b4dSbellard 	MIPS_SYS(sys_tgkill	, 3)
1301048f6b4dSbellard 	MIPS_SYS(sys_utimes	, 2)
1302048f6b4dSbellard 	MIPS_SYS(sys_mbind	, 4)
1303048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_get_mempolicy */
1304048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4270 sys_set_mempolicy */
1305048f6b4dSbellard 	MIPS_SYS(sys_mq_open	, 4)
1306048f6b4dSbellard 	MIPS_SYS(sys_mq_unlink	, 1)
1307048f6b4dSbellard 	MIPS_SYS(sys_mq_timedsend, 5)
1308048f6b4dSbellard 	MIPS_SYS(sys_mq_timedreceive, 5)
1309048f6b4dSbellard 	MIPS_SYS(sys_mq_notify	, 2)	/* 4275 */
1310048f6b4dSbellard 	MIPS_SYS(sys_mq_getsetattr, 3)
1311048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_vserver */
1312048f6b4dSbellard 	MIPS_SYS(sys_waitid	, 4)
1313048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* available, was setaltroot */
1314048f6b4dSbellard 	MIPS_SYS(sys_add_key	, 5)
1315048f6b4dSbellard 	MIPS_SYS(sys_request_key, 4)
1316048f6b4dSbellard 	MIPS_SYS(sys_keyctl	, 5)
13176f5b89a0Sths 	MIPS_SYS(sys_set_thread_area, 1)
1318388bb21aSths 	MIPS_SYS(sys_inotify_init, 0)
1319388bb21aSths 	MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
1320388bb21aSths 	MIPS_SYS(sys_inotify_rm_watch, 2)
1321388bb21aSths 	MIPS_SYS(sys_migrate_pages, 4)
1322388bb21aSths 	MIPS_SYS(sys_openat, 4)
1323388bb21aSths 	MIPS_SYS(sys_mkdirat, 3)
1324388bb21aSths 	MIPS_SYS(sys_mknodat, 4)	/* 4290 */
1325388bb21aSths 	MIPS_SYS(sys_fchownat, 5)
1326388bb21aSths 	MIPS_SYS(sys_futimesat, 3)
1327388bb21aSths 	MIPS_SYS(sys_fstatat64, 4)
1328388bb21aSths 	MIPS_SYS(sys_unlinkat, 3)
1329388bb21aSths 	MIPS_SYS(sys_renameat, 4)	/* 4295 */
1330388bb21aSths 	MIPS_SYS(sys_linkat, 5)
1331388bb21aSths 	MIPS_SYS(sys_symlinkat, 3)
1332388bb21aSths 	MIPS_SYS(sys_readlinkat, 4)
1333388bb21aSths 	MIPS_SYS(sys_fchmodat, 3)
1334388bb21aSths 	MIPS_SYS(sys_faccessat, 3)	/* 4300 */
1335388bb21aSths 	MIPS_SYS(sys_pselect6, 6)
1336388bb21aSths 	MIPS_SYS(sys_ppoll, 5)
1337388bb21aSths 	MIPS_SYS(sys_unshare, 1)
1338388bb21aSths 	MIPS_SYS(sys_splice, 4)
1339388bb21aSths 	MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
1340388bb21aSths 	MIPS_SYS(sys_tee, 4)
1341388bb21aSths 	MIPS_SYS(sys_vmsplice, 4)
1342388bb21aSths 	MIPS_SYS(sys_move_pages, 6)
1343388bb21aSths 	MIPS_SYS(sys_set_robust_list, 2)
1344388bb21aSths 	MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
1345388bb21aSths 	MIPS_SYS(sys_kexec_load, 4)
1346388bb21aSths 	MIPS_SYS(sys_getcpu, 3)
1347388bb21aSths 	MIPS_SYS(sys_epoll_pwait, 6)
1348388bb21aSths 	MIPS_SYS(sys_ioprio_set, 3)
1349388bb21aSths 	MIPS_SYS(sys_ioprio_get, 2)
1350048f6b4dSbellard };
1351048f6b4dSbellard 
1352048f6b4dSbellard #undef MIPS_SYS
1353048f6b4dSbellard 
1354048f6b4dSbellard void cpu_loop(CPUMIPSState *env)
1355048f6b4dSbellard {
1356048f6b4dSbellard     target_siginfo_t info;
1357388bb21aSths     int trapnr, ret;
1358048f6b4dSbellard     unsigned int syscall_num;
1359048f6b4dSbellard 
1360048f6b4dSbellard     for(;;) {
1361048f6b4dSbellard         trapnr = cpu_mips_exec(env);
1362048f6b4dSbellard         switch(trapnr) {
1363048f6b4dSbellard         case EXCP_SYSCALL:
1364048f6b4dSbellard             syscall_num = env->gpr[2] - 4000;
1365106ec879Sbellard             env->PC += 4;
1366048f6b4dSbellard             if (syscall_num >= sizeof(mips_syscall_args)) {
1367048f6b4dSbellard                 ret = -ENOSYS;
1368048f6b4dSbellard             } else {
1369388bb21aSths                 int nb_args;
1370388bb21aSths                 target_ulong sp_reg;
1371388bb21aSths                 target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
1372388bb21aSths 
1373048f6b4dSbellard                 nb_args = mips_syscall_args[syscall_num];
1374048f6b4dSbellard                 sp_reg = env->gpr[29];
1375388bb21aSths                 switch (nb_args) {
1376048f6b4dSbellard                 /* these arguments are taken from the stack */
1377388bb21aSths                 case 8: arg8 = tgetl(sp_reg + 28);
1378388bb21aSths                 case 7: arg7 = tgetl(sp_reg + 24);
1379388bb21aSths                 case 6: arg6 = tgetl(sp_reg + 20);
1380388bb21aSths                 case 5: arg5 = tgetl(sp_reg + 16);
1381388bb21aSths                 default:
1382388bb21aSths                     break;
1383048f6b4dSbellard                 }
1384388bb21aSths                 ret = do_syscall(env, env->gpr[2],
1385388bb21aSths                                  env->gpr[4], env->gpr[5],
1386388bb21aSths                                  env->gpr[6], env->gpr[7],
1387388bb21aSths                                  arg5, arg6/*, arg7, arg8*/);
1388048f6b4dSbellard             }
1389048f6b4dSbellard             if ((unsigned int)ret >= (unsigned int)(-1133)) {
1390048f6b4dSbellard                 env->gpr[7] = 1; /* error flag */
1391048f6b4dSbellard                 ret = -ret;
1392048f6b4dSbellard             } else {
1393048f6b4dSbellard                 env->gpr[7] = 0; /* error flag */
1394388bb21aSths             }
1395048f6b4dSbellard             env->gpr[2] = ret;
1396048f6b4dSbellard             break;
1397ca7c2b1bSths         case EXCP_TLBL:
1398ca7c2b1bSths         case EXCP_TLBS:
13996900e84bSbellard         case EXCP_CpU:
1400048f6b4dSbellard         case EXCP_RI:
1401048f6b4dSbellard             info.si_signo = TARGET_SIGILL;
1402048f6b4dSbellard             info.si_errno = 0;
1403048f6b4dSbellard             info.si_code = 0;
1404048f6b4dSbellard             queue_signal(info.si_signo, &info);
1405048f6b4dSbellard             break;
1406106ec879Sbellard         case EXCP_INTERRUPT:
1407106ec879Sbellard             /* just indicate that signals should be handled asap */
1408106ec879Sbellard             break;
1409d08b2a28Spbrook         case EXCP_DEBUG:
1410d08b2a28Spbrook             {
1411d08b2a28Spbrook                 int sig;
1412d08b2a28Spbrook 
1413d08b2a28Spbrook                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
1414d08b2a28Spbrook                 if (sig)
1415d08b2a28Spbrook                   {
1416d08b2a28Spbrook                     info.si_signo = sig;
1417d08b2a28Spbrook                     info.si_errno = 0;
1418d08b2a28Spbrook                     info.si_code = TARGET_TRAP_BRKPT;
1419d08b2a28Spbrook                     queue_signal(info.si_signo, &info);
1420d08b2a28Spbrook                   }
1421d08b2a28Spbrook             }
1422d08b2a28Spbrook             break;
1423048f6b4dSbellard         default:
1424048f6b4dSbellard             //        error:
1425048f6b4dSbellard             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
1426048f6b4dSbellard                     trapnr);
1427048f6b4dSbellard             cpu_dump_state(env, stderr, fprintf, 0);
1428048f6b4dSbellard             abort();
1429048f6b4dSbellard         }
1430048f6b4dSbellard         process_pending_signals(env);
1431048f6b4dSbellard     }
1432048f6b4dSbellard }
1433048f6b4dSbellard #endif
1434048f6b4dSbellard 
1435fdf9b3e8Sbellard #ifdef TARGET_SH4
1436fdf9b3e8Sbellard void cpu_loop (CPUState *env)
1437fdf9b3e8Sbellard {
1438fdf9b3e8Sbellard     int trapnr, ret;
1439355fb23dSpbrook     target_siginfo_t info;
1440fdf9b3e8Sbellard 
1441fdf9b3e8Sbellard     while (1) {
1442fdf9b3e8Sbellard         trapnr = cpu_sh4_exec (env);
1443fdf9b3e8Sbellard 
1444fdf9b3e8Sbellard         switch (trapnr) {
1445fdf9b3e8Sbellard         case 0x160:
1446fdf9b3e8Sbellard             ret = do_syscall(env,
14479c2a9ea1Spbrook                              env->gregs[3],
14489c2a9ea1Spbrook                              env->gregs[4],
14499c2a9ea1Spbrook                              env->gregs[5],
14509c2a9ea1Spbrook                              env->gregs[6],
14519c2a9ea1Spbrook                              env->gregs[7],
14529c2a9ea1Spbrook                              env->gregs[0],
1453fdf9b3e8Sbellard                              0);
14549c2a9ea1Spbrook             env->gregs[0] = ret;
1455fdf9b3e8Sbellard             env->pc += 2;
1456fdf9b3e8Sbellard             break;
1457355fb23dSpbrook         case EXCP_DEBUG:
1458355fb23dSpbrook             {
1459355fb23dSpbrook                 int sig;
1460355fb23dSpbrook 
1461355fb23dSpbrook                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
1462355fb23dSpbrook                 if (sig)
1463355fb23dSpbrook                   {
1464355fb23dSpbrook                     info.si_signo = sig;
1465355fb23dSpbrook                     info.si_errno = 0;
1466355fb23dSpbrook                     info.si_code = TARGET_TRAP_BRKPT;
1467355fb23dSpbrook                     queue_signal(info.si_signo, &info);
1468355fb23dSpbrook                   }
1469355fb23dSpbrook             }
1470355fb23dSpbrook             break;
1471fdf9b3e8Sbellard         default:
1472fdf9b3e8Sbellard             printf ("Unhandled trap: 0x%x\n", trapnr);
1473fdf9b3e8Sbellard             cpu_dump_state(env, stderr, fprintf, 0);
1474fdf9b3e8Sbellard             exit (1);
1475fdf9b3e8Sbellard         }
1476fdf9b3e8Sbellard         process_pending_signals (env);
1477fdf9b3e8Sbellard     }
1478fdf9b3e8Sbellard }
1479fdf9b3e8Sbellard #endif
1480fdf9b3e8Sbellard 
1481e6e5906bSpbrook #ifdef TARGET_M68K
1482e6e5906bSpbrook 
1483e6e5906bSpbrook void cpu_loop(CPUM68KState *env)
1484e6e5906bSpbrook {
1485e6e5906bSpbrook     int trapnr;
1486e6e5906bSpbrook     unsigned int n;
1487e6e5906bSpbrook     target_siginfo_t info;
1488e6e5906bSpbrook     TaskState *ts = env->opaque;
1489e6e5906bSpbrook 
1490e6e5906bSpbrook     for(;;) {
1491e6e5906bSpbrook         trapnr = cpu_m68k_exec(env);
1492e6e5906bSpbrook         switch(trapnr) {
1493e6e5906bSpbrook         case EXCP_ILLEGAL:
1494e6e5906bSpbrook             {
1495e6e5906bSpbrook                 if (ts->sim_syscalls) {
1496e6e5906bSpbrook                     uint16_t nr;
1497e6e5906bSpbrook                     nr = lduw(env->pc + 2);
1498e6e5906bSpbrook                     env->pc += 4;
1499e6e5906bSpbrook                     do_m68k_simcall(env, nr);
1500e6e5906bSpbrook                 } else {
1501e6e5906bSpbrook                     goto do_sigill;
1502e6e5906bSpbrook                 }
1503e6e5906bSpbrook             }
1504e6e5906bSpbrook             break;
1505*a87295e8Spbrook         case EXCP_HALT_INSN:
1506e6e5906bSpbrook             /* Semihosing syscall.  */
1507*a87295e8Spbrook             env->pc += 4;
1508e6e5906bSpbrook             do_m68k_semihosting(env, env->dregs[0]);
1509e6e5906bSpbrook             break;
1510e6e5906bSpbrook         case EXCP_LINEA:
1511e6e5906bSpbrook         case EXCP_LINEF:
1512e6e5906bSpbrook         case EXCP_UNSUPPORTED:
1513e6e5906bSpbrook         do_sigill:
1514e6e5906bSpbrook             info.si_signo = SIGILL;
1515e6e5906bSpbrook             info.si_errno = 0;
1516e6e5906bSpbrook             info.si_code = TARGET_ILL_ILLOPN;
1517e6e5906bSpbrook             info._sifields._sigfault._addr = env->pc;
1518e6e5906bSpbrook             queue_signal(info.si_signo, &info);
1519e6e5906bSpbrook             break;
1520e6e5906bSpbrook         case EXCP_TRAP0:
1521e6e5906bSpbrook             {
1522e6e5906bSpbrook                 ts->sim_syscalls = 0;
1523e6e5906bSpbrook                 n = env->dregs[0];
1524e6e5906bSpbrook                 env->pc += 2;
1525e6e5906bSpbrook                 env->dregs[0] = do_syscall(env,
1526e6e5906bSpbrook                                           n,
1527e6e5906bSpbrook                                           env->dregs[1],
1528e6e5906bSpbrook                                           env->dregs[2],
1529e6e5906bSpbrook                                           env->dregs[3],
1530e6e5906bSpbrook                                           env->dregs[4],
1531e6e5906bSpbrook                                           env->dregs[5],
1532e6e5906bSpbrook                                           env->dregs[6]);
1533e6e5906bSpbrook             }
1534e6e5906bSpbrook             break;
1535e6e5906bSpbrook         case EXCP_INTERRUPT:
1536e6e5906bSpbrook             /* just indicate that signals should be handled asap */
1537e6e5906bSpbrook             break;
1538e6e5906bSpbrook         case EXCP_ACCESS:
1539e6e5906bSpbrook             {
1540e6e5906bSpbrook                 info.si_signo = SIGSEGV;
1541e6e5906bSpbrook                 info.si_errno = 0;
1542e6e5906bSpbrook                 /* XXX: check env->error_code */
1543e6e5906bSpbrook                 info.si_code = TARGET_SEGV_MAPERR;
1544e6e5906bSpbrook                 info._sifields._sigfault._addr = env->mmu.ar;
1545e6e5906bSpbrook                 queue_signal(info.si_signo, &info);
1546e6e5906bSpbrook             }
1547e6e5906bSpbrook             break;
1548e6e5906bSpbrook         case EXCP_DEBUG:
1549e6e5906bSpbrook             {
1550e6e5906bSpbrook                 int sig;
1551e6e5906bSpbrook 
1552e6e5906bSpbrook                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
1553e6e5906bSpbrook                 if (sig)
1554e6e5906bSpbrook                   {
1555e6e5906bSpbrook                     info.si_signo = sig;
1556e6e5906bSpbrook                     info.si_errno = 0;
1557e6e5906bSpbrook                     info.si_code = TARGET_TRAP_BRKPT;
1558e6e5906bSpbrook                     queue_signal(info.si_signo, &info);
1559e6e5906bSpbrook                   }
1560e6e5906bSpbrook             }
1561e6e5906bSpbrook             break;
1562e6e5906bSpbrook         default:
1563e6e5906bSpbrook             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
1564e6e5906bSpbrook                     trapnr);
1565e6e5906bSpbrook             cpu_dump_state(env, stderr, fprintf, 0);
1566e6e5906bSpbrook             abort();
1567e6e5906bSpbrook         }
1568e6e5906bSpbrook         process_pending_signals(env);
1569e6e5906bSpbrook     }
1570e6e5906bSpbrook }
1571e6e5906bSpbrook #endif /* TARGET_M68K */
1572e6e5906bSpbrook 
15737a3148a9Sj_mayer #ifdef TARGET_ALPHA
15747a3148a9Sj_mayer void cpu_loop (CPUState *env)
15757a3148a9Sj_mayer {
1576e96efcfcSj_mayer     int trapnr;
15777a3148a9Sj_mayer     target_siginfo_t info;
15787a3148a9Sj_mayer 
15797a3148a9Sj_mayer     while (1) {
15807a3148a9Sj_mayer         trapnr = cpu_alpha_exec (env);
15817a3148a9Sj_mayer 
15827a3148a9Sj_mayer         switch (trapnr) {
15837a3148a9Sj_mayer         case EXCP_RESET:
15847a3148a9Sj_mayer             fprintf(stderr, "Reset requested. Exit\n");
15857a3148a9Sj_mayer             exit(1);
15867a3148a9Sj_mayer             break;
15877a3148a9Sj_mayer         case EXCP_MCHK:
15887a3148a9Sj_mayer             fprintf(stderr, "Machine check exception. Exit\n");
15897a3148a9Sj_mayer             exit(1);
15907a3148a9Sj_mayer             break;
15917a3148a9Sj_mayer         case EXCP_ARITH:
15927a3148a9Sj_mayer             fprintf(stderr, "Arithmetic trap.\n");
15937a3148a9Sj_mayer             exit(1);
15947a3148a9Sj_mayer             break;
15957a3148a9Sj_mayer         case EXCP_HW_INTERRUPT:
15967a3148a9Sj_mayer             fprintf(stderr, "External interrupt. Exit\n");
15977a3148a9Sj_mayer             exit(1);
15987a3148a9Sj_mayer             break;
15997a3148a9Sj_mayer         case EXCP_DFAULT:
16007a3148a9Sj_mayer             fprintf(stderr, "MMU data fault\n");
16017a3148a9Sj_mayer             exit(1);
16027a3148a9Sj_mayer             break;
16037a3148a9Sj_mayer         case EXCP_DTB_MISS_PAL:
16047a3148a9Sj_mayer             fprintf(stderr, "MMU data TLB miss in PALcode\n");
16057a3148a9Sj_mayer             exit(1);
16067a3148a9Sj_mayer             break;
16077a3148a9Sj_mayer         case EXCP_ITB_MISS:
16087a3148a9Sj_mayer             fprintf(stderr, "MMU instruction TLB miss\n");
16097a3148a9Sj_mayer             exit(1);
16107a3148a9Sj_mayer             break;
16117a3148a9Sj_mayer         case EXCP_ITB_ACV:
16127a3148a9Sj_mayer             fprintf(stderr, "MMU instruction access violation\n");
16137a3148a9Sj_mayer             exit(1);
16147a3148a9Sj_mayer             break;
16157a3148a9Sj_mayer         case EXCP_DTB_MISS_NATIVE:
16167a3148a9Sj_mayer             fprintf(stderr, "MMU data TLB miss\n");
16177a3148a9Sj_mayer             exit(1);
16187a3148a9Sj_mayer             break;
16197a3148a9Sj_mayer         case EXCP_UNALIGN:
16207a3148a9Sj_mayer             fprintf(stderr, "Unaligned access\n");
16217a3148a9Sj_mayer             exit(1);
16227a3148a9Sj_mayer             break;
16237a3148a9Sj_mayer         case EXCP_OPCDEC:
16247a3148a9Sj_mayer             fprintf(stderr, "Invalid instruction\n");
16257a3148a9Sj_mayer             exit(1);
16267a3148a9Sj_mayer             break;
16277a3148a9Sj_mayer         case EXCP_FEN:
16287a3148a9Sj_mayer             fprintf(stderr, "Floating-point not allowed\n");
16297a3148a9Sj_mayer             exit(1);
16307a3148a9Sj_mayer             break;
16317a3148a9Sj_mayer         case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
16327a3148a9Sj_mayer             fprintf(stderr, "Call to PALcode\n");
16337a3148a9Sj_mayer             call_pal(env, (trapnr >> 6) | 0x80);
16347a3148a9Sj_mayer             break;
16357a3148a9Sj_mayer         case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
16367a3148a9Sj_mayer             fprintf(stderr, "Priviledged call to PALcode\n");
16377a3148a9Sj_mayer             exit(1);
16387a3148a9Sj_mayer             break;
16397a3148a9Sj_mayer         case EXCP_DEBUG:
16407a3148a9Sj_mayer             {
16417a3148a9Sj_mayer                 int sig;
16427a3148a9Sj_mayer 
16437a3148a9Sj_mayer                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
16447a3148a9Sj_mayer                 if (sig)
16457a3148a9Sj_mayer                   {
16467a3148a9Sj_mayer                     info.si_signo = sig;
16477a3148a9Sj_mayer                     info.si_errno = 0;
16487a3148a9Sj_mayer                     info.si_code = TARGET_TRAP_BRKPT;
16497a3148a9Sj_mayer                     queue_signal(info.si_signo, &info);
16507a3148a9Sj_mayer                   }
16517a3148a9Sj_mayer             }
16527a3148a9Sj_mayer             break;
16537a3148a9Sj_mayer         default:
16547a3148a9Sj_mayer             printf ("Unhandled trap: 0x%x\n", trapnr);
16557a3148a9Sj_mayer             cpu_dump_state(env, stderr, fprintf, 0);
16567a3148a9Sj_mayer             exit (1);
16577a3148a9Sj_mayer         }
16587a3148a9Sj_mayer         process_pending_signals (env);
16597a3148a9Sj_mayer     }
16607a3148a9Sj_mayer }
16617a3148a9Sj_mayer #endif /* TARGET_ALPHA */
16627a3148a9Sj_mayer 
166331e31b8aSbellard void usage(void)
166431e31b8aSbellard {
166584f2e8efSbellard     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
1666b1f9be31Sj_mayer            "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] [-cpu model] program [arguments...]\n"
1667b346ff46Sbellard            "Linux CPU emulator (compiled for %s emulation)\n"
1668d691f669Sbellard            "\n"
1669d691f669Sbellard            "-h           print this help\n"
167074c33bedSbellard            "-g port      wait gdb connection to port\n"
1671b346ff46Sbellard            "-L path      set the elf interpreter prefix (default=%s)\n"
1672b346ff46Sbellard            "-s size      set the stack size in bytes (default=%ld)\n"
1673b1f9be31Sj_mayer            "-cpu model   select CPU (-cpu ? for list)\n"
167454936004Sbellard            "\n"
167554936004Sbellard            "debug options:\n"
1676c6981055Sbellard #ifdef USE_CODE_COPY
1677c6981055Sbellard            "-no-code-copy   disable code copy acceleration\n"
1678c6981055Sbellard #endif
16796f1f31c0Sbellard            "-d options   activate log (logfile=%s)\n"
168054936004Sbellard            "-p pagesize  set the host page size to 'pagesize'\n",
1681b346ff46Sbellard            TARGET_ARCH,
1682d691f669Sbellard            interp_prefix,
168354936004Sbellard            x86_stack_size,
168454936004Sbellard            DEBUG_LOGFILE);
168574cd30b8Sbellard     _exit(1);
168631e31b8aSbellard }
168731e31b8aSbellard 
16889de5e440Sbellard /* XXX: currently only used for async signals (see signal.c) */
1689b346ff46Sbellard CPUState *global_env;
169059faf6d6Sbellard 
1691851e67a1Sbellard /* used to free thread contexts */
1692851e67a1Sbellard TaskState *first_task_state;
16939de5e440Sbellard 
169431e31b8aSbellard int main(int argc, char **argv)
169531e31b8aSbellard {
169631e31b8aSbellard     const char *filename;
1697b1f9be31Sj_mayer     const char *cpu_model;
169801ffc75bSbellard     struct target_pt_regs regs1, *regs = &regs1;
169931e31b8aSbellard     struct image_info info1, *info = &info1;
1700851e67a1Sbellard     TaskState ts1, *ts = &ts1;
1701b346ff46Sbellard     CPUState *env;
1702586314f2Sbellard     int optind;
1703d691f669Sbellard     const char *r;
170474c33bedSbellard     int gdbstub_port = 0;
170531e31b8aSbellard 
170631e31b8aSbellard     if (argc <= 1)
170731e31b8aSbellard         usage();
1708f801f97eSbellard 
1709cc38b844Sbellard     /* init debug */
1710cc38b844Sbellard     cpu_set_log_filename(DEBUG_LOGFILE);
1711cc38b844Sbellard 
1712b1f9be31Sj_mayer     cpu_model = NULL;
1713586314f2Sbellard     optind = 1;
1714d691f669Sbellard     for(;;) {
1715d691f669Sbellard         if (optind >= argc)
1716d691f669Sbellard             break;
1717d691f669Sbellard         r = argv[optind];
1718d691f669Sbellard         if (r[0] != '-')
1719d691f669Sbellard             break;
1720586314f2Sbellard         optind++;
1721d691f669Sbellard         r++;
1722d691f669Sbellard         if (!strcmp(r, "-")) {
1723d691f669Sbellard             break;
1724d691f669Sbellard         } else if (!strcmp(r, "d")) {
1725e19e89a5Sbellard             int mask;
1726e19e89a5Sbellard             CPULogItem *item;
1727e19e89a5Sbellard 
17286f1f31c0Sbellard 	    if (optind >= argc)
17296f1f31c0Sbellard 		break;
17306f1f31c0Sbellard 
17316f1f31c0Sbellard 	    r = argv[optind++];
17326f1f31c0Sbellard             mask = cpu_str_to_log_mask(r);
1733e19e89a5Sbellard             if (!mask) {
1734e19e89a5Sbellard                 printf("Log items (comma separated):\n");
1735e19e89a5Sbellard                 for(item = cpu_log_items; item->mask != 0; item++) {
1736e19e89a5Sbellard                     printf("%-10s %s\n", item->name, item->help);
1737e19e89a5Sbellard                 }
1738e19e89a5Sbellard                 exit(1);
1739e19e89a5Sbellard             }
1740e19e89a5Sbellard             cpu_set_log(mask);
1741d691f669Sbellard         } else if (!strcmp(r, "s")) {
1742d691f669Sbellard             r = argv[optind++];
1743d691f669Sbellard             x86_stack_size = strtol(r, (char **)&r, 0);
1744d691f669Sbellard             if (x86_stack_size <= 0)
1745d691f669Sbellard                 usage();
1746d691f669Sbellard             if (*r == 'M')
1747d691f669Sbellard                 x86_stack_size *= 1024 * 1024;
1748d691f669Sbellard             else if (*r == 'k' || *r == 'K')
1749d691f669Sbellard                 x86_stack_size *= 1024;
1750d691f669Sbellard         } else if (!strcmp(r, "L")) {
1751d691f669Sbellard             interp_prefix = argv[optind++];
175254936004Sbellard         } else if (!strcmp(r, "p")) {
175383fb7adfSbellard             qemu_host_page_size = atoi(argv[optind++]);
175483fb7adfSbellard             if (qemu_host_page_size == 0 ||
175583fb7adfSbellard                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
175654936004Sbellard                 fprintf(stderr, "page size must be a power of two\n");
175754936004Sbellard                 exit(1);
175854936004Sbellard             }
17591fddef4bSbellard         } else if (!strcmp(r, "g")) {
176074c33bedSbellard             gdbstub_port = atoi(argv[optind++]);
1761c5937220Spbrook 	} else if (!strcmp(r, "r")) {
1762c5937220Spbrook 	    qemu_uname_release = argv[optind++];
1763b1f9be31Sj_mayer         } else if (!strcmp(r, "cpu")) {
1764b1f9be31Sj_mayer             cpu_model = argv[optind++];
1765b1f9be31Sj_mayer             if (strcmp(cpu_model, "?") == 0) {
1766b1f9be31Sj_mayer #if defined(TARGET_PPC)
1767b1f9be31Sj_mayer                 ppc_cpu_list(stdout, &fprintf);
1768b1f9be31Sj_mayer #elif defined(TARGET_ARM)
1769b1f9be31Sj_mayer                 arm_cpu_list();
1770b1f9be31Sj_mayer #elif defined(TARGET_MIPS)
1771b1f9be31Sj_mayer                 mips_cpu_list(stdout, &fprintf);
1772925fb139Sblueswir1 #elif defined(TARGET_SPARC)
1773925fb139Sblueswir1                 sparc_cpu_list(stdout, &fprintf);
1774b1f9be31Sj_mayer #endif
1775cff4cbedSths                 _exit(1);
1776b1f9be31Sj_mayer             }
1777c6981055Sbellard         } else
1778c6981055Sbellard #ifdef USE_CODE_COPY
1779c6981055Sbellard         if (!strcmp(r, "no-code-copy")) {
1780c6981055Sbellard             code_copy_enabled = 0;
1781c6981055Sbellard         } else
1782c6981055Sbellard #endif
1783c6981055Sbellard         {
1784d691f669Sbellard             usage();
1785586314f2Sbellard         }
1786d691f669Sbellard     }
1787d691f669Sbellard     if (optind >= argc)
1788d691f669Sbellard         usage();
1789586314f2Sbellard     filename = argv[optind];
179031e31b8aSbellard 
179131e31b8aSbellard     /* Zero out regs */
179201ffc75bSbellard     memset(regs, 0, sizeof(struct target_pt_regs));
179331e31b8aSbellard 
179431e31b8aSbellard     /* Zero out image_info */
179531e31b8aSbellard     memset(info, 0, sizeof(struct image_info));
179631e31b8aSbellard 
179774cd30b8Sbellard     /* Scan interp_prefix dir for replacement files. */
179874cd30b8Sbellard     init_paths(interp_prefix);
179974cd30b8Sbellard 
180083fb7adfSbellard     /* NOTE: we need to init the CPU at this stage to get
180183fb7adfSbellard        qemu_host_page_size */
1802b346ff46Sbellard     env = cpu_init();
180315338fd7Sbellard     global_env = env;
180454936004Sbellard 
1805e5fe0c52Spbrook     if (loader_exec(filename, argv+optind, environ, regs, info) != 0) {
180631e31b8aSbellard 	printf("Error loading %s\n", filename);
180774cd30b8Sbellard 	_exit(1);
180831e31b8aSbellard     }
180931e31b8aSbellard 
18104b74fe1fSbellard     if (loglevel) {
181154936004Sbellard         page_dump(logfile);
181254936004Sbellard 
18134b74fe1fSbellard         fprintf(logfile, "start_brk   0x%08lx\n" , info->start_brk);
18144b74fe1fSbellard         fprintf(logfile, "end_code    0x%08lx\n" , info->end_code);
18154b74fe1fSbellard         fprintf(logfile, "start_code  0x%08lx\n" , info->start_code);
1816e5fe0c52Spbrook         fprintf(logfile, "start_data  0x%08lx\n" , info->start_data);
18174b74fe1fSbellard         fprintf(logfile, "end_data    0x%08lx\n" , info->end_data);
18184b74fe1fSbellard         fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
18194b74fe1fSbellard         fprintf(logfile, "brk         0x%08lx\n" , info->brk);
1820b346ff46Sbellard         fprintf(logfile, "entry       0x%08lx\n" , info->entry);
18214b74fe1fSbellard     }
182231e31b8aSbellard 
182353a5960aSpbrook     target_set_brk(info->brk);
182431e31b8aSbellard     syscall_init();
182566fb9763Sbellard     signal_init();
182631e31b8aSbellard 
1827851e67a1Sbellard     /* build Task State */
1828851e67a1Sbellard     memset(ts, 0, sizeof(TaskState));
1829851e67a1Sbellard     env->opaque = ts;
1830851e67a1Sbellard     ts->used = 1;
1831978efd6aSpbrook     ts->info = info;
183259faf6d6Sbellard     env->user_mode_only = 1;
1833851e67a1Sbellard 
1834b346ff46Sbellard #if defined(TARGET_I386)
18352e255c6bSbellard     cpu_x86_set_cpl(env, 3);
18362e255c6bSbellard 
18373802ce26Sbellard     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
18381bde465eSbellard     env->hflags |= HF_PE_MASK;
18391bde465eSbellard     if (env->cpuid_features & CPUID_SSE) {
18401bde465eSbellard         env->cr[4] |= CR4_OSFXSR_MASK;
18411bde465eSbellard         env->hflags |= HF_OSFXSR_MASK;
18421bde465eSbellard     }
18433802ce26Sbellard 
1844415e561fSbellard     /* flags setup : we activate the IRQs by default as in user mode */
1845415e561fSbellard     env->eflags |= IF_MASK;
1846415e561fSbellard 
18476dbad63eSbellard     /* linux register setup */
184884409ddbSj_mayer #if defined(TARGET_X86_64)
184984409ddbSj_mayer     env->regs[R_EAX] = regs->rax;
185084409ddbSj_mayer     env->regs[R_EBX] = regs->rbx;
185184409ddbSj_mayer     env->regs[R_ECX] = regs->rcx;
185284409ddbSj_mayer     env->regs[R_EDX] = regs->rdx;
185384409ddbSj_mayer     env->regs[R_ESI] = regs->rsi;
185484409ddbSj_mayer     env->regs[R_EDI] = regs->rdi;
185584409ddbSj_mayer     env->regs[R_EBP] = regs->rbp;
185684409ddbSj_mayer     env->regs[R_ESP] = regs->rsp;
185784409ddbSj_mayer     env->eip = regs->rip;
185884409ddbSj_mayer #else
18590ecfa993Sbellard     env->regs[R_EAX] = regs->eax;
18600ecfa993Sbellard     env->regs[R_EBX] = regs->ebx;
18610ecfa993Sbellard     env->regs[R_ECX] = regs->ecx;
18620ecfa993Sbellard     env->regs[R_EDX] = regs->edx;
18630ecfa993Sbellard     env->regs[R_ESI] = regs->esi;
18640ecfa993Sbellard     env->regs[R_EDI] = regs->edi;
18650ecfa993Sbellard     env->regs[R_EBP] = regs->ebp;
18660ecfa993Sbellard     env->regs[R_ESP] = regs->esp;
1867dab2ed99Sbellard     env->eip = regs->eip;
186884409ddbSj_mayer #endif
186931e31b8aSbellard 
1870f4beb510Sbellard     /* linux interrupt setup */
187153a5960aSpbrook     env->idt.base = h2g(idt_table);
1872f4beb510Sbellard     env->idt.limit = sizeof(idt_table) - 1;
1873f4beb510Sbellard     set_idt(0, 0);
1874f4beb510Sbellard     set_idt(1, 0);
1875f4beb510Sbellard     set_idt(2, 0);
1876f4beb510Sbellard     set_idt(3, 3);
1877f4beb510Sbellard     set_idt(4, 3);
1878f4beb510Sbellard     set_idt(5, 3);
1879f4beb510Sbellard     set_idt(6, 0);
1880f4beb510Sbellard     set_idt(7, 0);
1881f4beb510Sbellard     set_idt(8, 0);
1882f4beb510Sbellard     set_idt(9, 0);
1883f4beb510Sbellard     set_idt(10, 0);
1884f4beb510Sbellard     set_idt(11, 0);
1885f4beb510Sbellard     set_idt(12, 0);
1886f4beb510Sbellard     set_idt(13, 0);
1887f4beb510Sbellard     set_idt(14, 0);
1888f4beb510Sbellard     set_idt(15, 0);
1889f4beb510Sbellard     set_idt(16, 0);
1890f4beb510Sbellard     set_idt(17, 0);
1891f4beb510Sbellard     set_idt(18, 0);
1892f4beb510Sbellard     set_idt(19, 0);
1893f4beb510Sbellard     set_idt(0x80, 3);
1894f4beb510Sbellard 
18956dbad63eSbellard     /* linux segment setup */
189653a5960aSpbrook     env->gdt.base = h2g(gdt_table);
18976dbad63eSbellard     env->gdt.limit = sizeof(gdt_table) - 1;
1898f4beb510Sbellard     write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
1899f4beb510Sbellard              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1900f4beb510Sbellard              (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
1901f4beb510Sbellard     write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
1902f4beb510Sbellard              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1903f4beb510Sbellard              (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
19046dbad63eSbellard     cpu_x86_load_seg(env, R_CS, __USER_CS);
19056dbad63eSbellard     cpu_x86_load_seg(env, R_DS, __USER_DS);
19066dbad63eSbellard     cpu_x86_load_seg(env, R_ES, __USER_DS);
19076dbad63eSbellard     cpu_x86_load_seg(env, R_SS, __USER_DS);
19086dbad63eSbellard     cpu_x86_load_seg(env, R_FS, __USER_DS);
19096dbad63eSbellard     cpu_x86_load_seg(env, R_GS, __USER_DS);
191092ccca6aSbellard 
1911b346ff46Sbellard #elif defined(TARGET_ARM)
1912b346ff46Sbellard     {
1913b346ff46Sbellard         int i;
1914b1f9be31Sj_mayer         if (cpu_model == NULL)
1915b1f9be31Sj_mayer             cpu_model = "arm926";
1916b1f9be31Sj_mayer         cpu_arm_set_model(env, cpu_model);
1917b5ff1b31Sbellard         cpsr_write(env, regs->uregs[16], 0xffffffff);
1918b346ff46Sbellard         for(i = 0; i < 16; i++) {
1919b346ff46Sbellard             env->regs[i] = regs->uregs[i];
1920b346ff46Sbellard         }
1921b346ff46Sbellard     }
192293ac68bcSbellard #elif defined(TARGET_SPARC)
1923060366c5Sbellard     {
1924060366c5Sbellard         int i;
1925925fb139Sblueswir1         const sparc_def_t *def;
1926925fb139Sblueswir1 #ifdef TARGET_SPARC64
1927925fb139Sblueswir1         if (cpu_model == NULL)
1928925fb139Sblueswir1             cpu_model = "TI UltraSparc II";
1929925fb139Sblueswir1 #else
1930925fb139Sblueswir1         if (cpu_model == NULL)
1931925fb139Sblueswir1             cpu_model = "Fujitsu MB86904";
1932925fb139Sblueswir1 #endif
1933925fb139Sblueswir1         sparc_find_by_name(cpu_model, &def);
1934925fb139Sblueswir1         if (def == NULL) {
1935925fb139Sblueswir1             fprintf(stderr, "Unable to find Sparc CPU definition\n");
1936925fb139Sblueswir1             exit(1);
1937925fb139Sblueswir1         }
1938925fb139Sblueswir1         cpu_sparc_register(env, def);
1939060366c5Sbellard 	env->pc = regs->pc;
1940060366c5Sbellard 	env->npc = regs->npc;
1941060366c5Sbellard         env->y = regs->y;
1942060366c5Sbellard         for(i = 0; i < 8; i++)
1943060366c5Sbellard             env->gregs[i] = regs->u_regs[i];
1944060366c5Sbellard         for(i = 0; i < 8; i++)
1945060366c5Sbellard             env->regwptr[i] = regs->u_regs[i + 8];
1946060366c5Sbellard     }
194767867308Sbellard #elif defined(TARGET_PPC)
194867867308Sbellard     {
19493fc6c082Sbellard         ppc_def_t *def;
195067867308Sbellard         int i;
19513fc6c082Sbellard 
19523fc6c082Sbellard         /* Choose and initialise CPU */
1953b1f9be31Sj_mayer         if (cpu_model == NULL)
1954b1f9be31Sj_mayer             cpu_model = "750";
1955b1f9be31Sj_mayer         ppc_find_by_name(cpu_model, &def);
19563fc6c082Sbellard         if (def == NULL) {
1957c68ea704Sbellard             cpu_abort(env,
19583fc6c082Sbellard                       "Unable to find PowerPC CPU definition\n");
19593fc6c082Sbellard         }
1960c68ea704Sbellard         cpu_ppc_register(env, def);
19613fc6c082Sbellard 
196261190b14Sbellard         for (i = 0; i < 32; i++) {
19634c2e770fSbellard             if (i != 12 && i != 6 && i != 13)
196467867308Sbellard                 env->msr[i] = (regs->msr >> i) & 1;
196561190b14Sbellard         }
196684409ddbSj_mayer #if defined(TARGET_PPC64)
196784409ddbSj_mayer         msr_sf = 1;
196884409ddbSj_mayer #endif
196967867308Sbellard         env->nip = regs->nip;
197067867308Sbellard         for(i = 0; i < 32; i++) {
197167867308Sbellard             env->gpr[i] = regs->gpr[i];
197267867308Sbellard         }
197367867308Sbellard     }
1974e6e5906bSpbrook #elif defined(TARGET_M68K)
1975e6e5906bSpbrook     {
19760633879fSpbrook         if (cpu_model == NULL)
19770633879fSpbrook             cpu_model = "cfv4e";
19780633879fSpbrook         if (cpu_m68k_set_model(env, cpu_model)) {
1979e6e5906bSpbrook             cpu_abort(cpu_single_env,
1980e6e5906bSpbrook                       "Unable to find m68k CPU definition\n");
1981e6e5906bSpbrook         }
1982e6e5906bSpbrook         env->pc = regs->pc;
1983e6e5906bSpbrook         env->dregs[0] = regs->d0;
1984e6e5906bSpbrook         env->dregs[1] = regs->d1;
1985e6e5906bSpbrook         env->dregs[2] = regs->d2;
1986e6e5906bSpbrook         env->dregs[3] = regs->d3;
1987e6e5906bSpbrook         env->dregs[4] = regs->d4;
1988e6e5906bSpbrook         env->dregs[5] = regs->d5;
1989e6e5906bSpbrook         env->dregs[6] = regs->d6;
1990e6e5906bSpbrook         env->dregs[7] = regs->d7;
1991e6e5906bSpbrook         env->aregs[0] = regs->a0;
1992e6e5906bSpbrook         env->aregs[1] = regs->a1;
1993e6e5906bSpbrook         env->aregs[2] = regs->a2;
1994e6e5906bSpbrook         env->aregs[3] = regs->a3;
1995e6e5906bSpbrook         env->aregs[4] = regs->a4;
1996e6e5906bSpbrook         env->aregs[5] = regs->a5;
1997e6e5906bSpbrook         env->aregs[6] = regs->a6;
1998e6e5906bSpbrook         env->aregs[7] = regs->usp;
1999e6e5906bSpbrook         env->sr = regs->sr;
2000e6e5906bSpbrook         ts->sim_syscalls = 1;
2001e6e5906bSpbrook     }
2002048f6b4dSbellard #elif defined(TARGET_MIPS)
2003048f6b4dSbellard     {
2004cff4cbedSths         mips_def_t *def;
2005048f6b4dSbellard         int i;
2006048f6b4dSbellard 
2007cff4cbedSths         /* Choose and initialise CPU */
2008cff4cbedSths         if (cpu_model == NULL)
2009cff4cbedSths             cpu_model = "24Kf";
2010cff4cbedSths         mips_find_by_name(cpu_model, &def);
2011cff4cbedSths         if (def == NULL)
2012cff4cbedSths             cpu_abort(env, "Unable to find MIPS CPU definition\n");
2013cff4cbedSths         cpu_mips_register(env, def);
2014cff4cbedSths 
2015048f6b4dSbellard         for(i = 0; i < 32; i++) {
2016048f6b4dSbellard             env->gpr[i] = regs->regs[i];
2017048f6b4dSbellard         }
2018048f6b4dSbellard         env->PC = regs->cp0_epc;
201936d23958Sths         if (env->CP0_Config1 & (1 << CP0C1_FP)) {
2020bc1ad2deSbellard             env->CP0_Status |= (1 << CP0St_CU1);
202136d23958Sths         }
2022048f6b4dSbellard     }
2023fdf9b3e8Sbellard #elif defined(TARGET_SH4)
2024fdf9b3e8Sbellard     {
2025fdf9b3e8Sbellard         int i;
2026fdf9b3e8Sbellard 
2027fdf9b3e8Sbellard         for(i = 0; i < 16; i++) {
2028fdf9b3e8Sbellard             env->gregs[i] = regs->regs[i];
2029fdf9b3e8Sbellard         }
2030fdf9b3e8Sbellard         env->pc = regs->pc;
2031fdf9b3e8Sbellard     }
20327a3148a9Sj_mayer #elif defined(TARGET_ALPHA)
20337a3148a9Sj_mayer     {
20347a3148a9Sj_mayer         int i;
20357a3148a9Sj_mayer 
20367a3148a9Sj_mayer         for(i = 0; i < 28; i++) {
20377a3148a9Sj_mayer             env->ir[i] = ((target_ulong *)regs)[i];
20387a3148a9Sj_mayer         }
20397a3148a9Sj_mayer         env->ipr[IPR_USP] = regs->usp;
20407a3148a9Sj_mayer         env->ir[30] = regs->usp;
20417a3148a9Sj_mayer         env->pc = regs->pc;
20427a3148a9Sj_mayer         env->unique = regs->unique;
20437a3148a9Sj_mayer     }
2044b346ff46Sbellard #else
2045b346ff46Sbellard #error unsupported target CPU
2046b346ff46Sbellard #endif
204731e31b8aSbellard 
2048*a87295e8Spbrook #if defined(TARGET_ARM) || defined(TARGET_M68K)
2049*a87295e8Spbrook     ts->stack_base = info->start_stack;
2050*a87295e8Spbrook     ts->heap_base = info->brk;
2051*a87295e8Spbrook     /* This will be filled in on the first SYS_HEAPINFO call.  */
2052*a87295e8Spbrook     ts->heap_limit = 0;
2053*a87295e8Spbrook #endif
2054*a87295e8Spbrook 
205574c33bedSbellard     if (gdbstub_port) {
205674c33bedSbellard         gdbserver_start (gdbstub_port);
20571fddef4bSbellard         gdb_handlesig(env, 0);
20581fddef4bSbellard     }
20591b6b029eSbellard     cpu_loop(env);
20601b6b029eSbellard     /* never exits */
206131e31b8aSbellard     return 0;
206231e31b8aSbellard }
2063