xref: /qemu/linux-user/main.c (revision b1311c4a)
131e31b8aSbellard /*
293ac68bcSbellard  *  qemu user main
331e31b8aSbellard  *
468d0f70eSbellard  *  Copyright (c) 2003-2008 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
178167ee88SBlue Swirl  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1831e31b8aSbellard  */
19d39594e9SPeter Maydell #include "qemu/osdep.h"
2067a1de0dSFam Zheng #include "qemu-version.h"
21edf8e2afSMika Westerberg #include <sys/syscall.h>
22703e0e89SRichard Henderson #include <sys/resource.h>
2331e31b8aSbellard 
24daa76aa4SMarkus Armbruster #include "qapi/error.h"
253ef693a0Sbellard #include "qemu.h"
26f348b6d1SVeronia Bahaa #include "qemu/path.h"
276533dd6eSLluís Vilanova #include "qemu/config-file.h"
28f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
29f348b6d1SVeronia Bahaa #include "qemu/help_option.h"
302b41f10eSBlue Swirl #include "cpu.h"
3163c91552SPaolo Bonzini #include "exec/exec-all.h"
329002ec79SRichard Henderson #include "tcg.h"
331de7afc9SPaolo Bonzini #include "qemu/timer.h"
341de7afc9SPaolo Bonzini #include "qemu/envlist.h"
35d8fd2954SPaul Brook #include "elf.h"
36508127e2SPaolo Bonzini #include "exec/log.h"
376533dd6eSLluís Vilanova #include "trace/control.h"
386533dd6eSLluís Vilanova #include "glib-compat.h"
3904a6dfebSaurel32 
40d088d664Saurel32 char *exec_path;
41d088d664Saurel32 
421b530a6dSaurel32 int singlestep;
438cb76755SStefan Weil static const char *filename;
448cb76755SStefan Weil static const char *argv0;
458cb76755SStefan Weil static int gdbstub_port;
468cb76755SStefan Weil static envlist_t *envlist;
4751fb256aSAndreas Färber static const char *cpu_model;
48379f6698SPaul Brook unsigned long mmap_min_addr;
49379f6698SPaul Brook unsigned long guest_base;
50379f6698SPaul Brook int have_guest_base;
51120a9848SPaolo Bonzini 
52120a9848SPaolo Bonzini #define EXCP_DUMP(env, fmt, ...)                                        \
53120a9848SPaolo Bonzini do {                                                                    \
54120a9848SPaolo Bonzini     CPUState *cs = ENV_GET_CPU(env);                                    \
55120a9848SPaolo Bonzini     fprintf(stderr, fmt , ## __VA_ARGS__);                              \
56120a9848SPaolo Bonzini     cpu_dump_state(cs, stderr, fprintf, 0);                             \
57120a9848SPaolo Bonzini     if (qemu_log_separate()) {                                          \
58120a9848SPaolo Bonzini         qemu_log(fmt, ## __VA_ARGS__);                                  \
59120a9848SPaolo Bonzini         log_cpu_state(cs, 0);                                           \
60120a9848SPaolo Bonzini     }                                                                   \
61120a9848SPaolo Bonzini } while (0)
62120a9848SPaolo Bonzini 
63288e65b9SAlexander Graf /*
64288e65b9SAlexander Graf  * When running 32-on-64 we should make sure we can fit all of the possible
65288e65b9SAlexander Graf  * guest address space into a contiguous chunk of virtual host memory.
66288e65b9SAlexander Graf  *
67288e65b9SAlexander Graf  * This way we will never overlap with our own libraries or binaries or stack
68288e65b9SAlexander Graf  * or anything else that QEMU maps.
6918e80c55SRichard Henderson  *
7018e80c55SRichard Henderson  * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
7118e80c55SRichard Henderson  * of the address for the kernel.  Some cpus rely on this and user space
7218e80c55SRichard Henderson  * uses the high bit(s) for pointer tagging and the like.  For them, we
7318e80c55SRichard Henderson  * must preserve the expected address space.
74288e65b9SAlexander Graf  */
7518e80c55SRichard Henderson #ifndef MAX_RESERVED_VA
7618e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
7718e80c55SRichard Henderson #  if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
7818e80c55SRichard Henderson       (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
7918e80c55SRichard Henderson /* There are a number of places where we assign reserved_va to a variable
8018e80c55SRichard Henderson    of type abi_ulong and expect it to fit.  Avoid the last page.  */
8118e80c55SRichard Henderson #   define MAX_RESERVED_VA  (0xfffffffful & TARGET_PAGE_MASK)
82314992b1SAlexander Graf #  else
8318e80c55SRichard Henderson #   define MAX_RESERVED_VA  (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
84314992b1SAlexander Graf #  endif
85288e65b9SAlexander Graf # else
8618e80c55SRichard Henderson #  define MAX_RESERVED_VA  0
8718e80c55SRichard Henderson # endif
8818e80c55SRichard Henderson #endif
8918e80c55SRichard Henderson 
9018e80c55SRichard Henderson /* That said, reserving *too* much vm space via mmap can run into problems
9118e80c55SRichard Henderson    with rlimits, oom due to page table creation, etc.  We will still try it,
9218e80c55SRichard Henderson    if directed by the command-line option, but not by default.  */
9318e80c55SRichard Henderson #if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32
9418e80c55SRichard Henderson unsigned long reserved_va = MAX_RESERVED_VA;
9518e80c55SRichard Henderson #else
9668a1c816SPaul Brook unsigned long reserved_va;
97379f6698SPaul Brook #endif
981b530a6dSaurel32 
99d03f9c32SMeador Inge static void usage(int exitcode);
100fc9c5412SJohannes Schauer 
1017ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
102e586822aSRiku Voipio const char *qemu_uname_release;
103586314f2Sbellard 
1049de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
1059de5e440Sbellard    we allocate a bigger stack. Need a better solution, for example
1069de5e440Sbellard    by remapping the process stack directly at the right place */
107703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL;
10831e31b8aSbellard 
10931e31b8aSbellard void gemu_log(const char *fmt, ...)
11031e31b8aSbellard {
11131e31b8aSbellard     va_list ap;
11231e31b8aSbellard 
11331e31b8aSbellard     va_start(ap, fmt);
11431e31b8aSbellard     vfprintf(stderr, fmt, ap);
11531e31b8aSbellard     va_end(ap);
11631e31b8aSbellard }
11731e31b8aSbellard 
1188fcd3692Sblueswir1 #if defined(TARGET_I386)
11905390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env)
12092ccca6aSbellard {
12192ccca6aSbellard     return -1;
12292ccca6aSbellard }
1238fcd3692Sblueswir1 #endif
12492ccca6aSbellard 
125d5975363Spbrook /***********************************************************/
126d5975363Spbrook /* Helper routines for implementing atomic operations.  */
127d5975363Spbrook 
128d5975363Spbrook /* Make sure everything is in a consistent state for calling fork().  */
129d5975363Spbrook void fork_start(void)
130d5975363Spbrook {
131267f685bSPaolo Bonzini     cpu_list_lock();
13244ded3d0SEmilio G. Cota     qemu_mutex_lock(&tb_ctx.tb_lock);
133d032d1b4SRiku Voipio     mmap_fork_start();
134d5975363Spbrook }
135d5975363Spbrook 
136d5975363Spbrook void fork_end(int child)
137d5975363Spbrook {
138d032d1b4SRiku Voipio     mmap_fork_end(child);
139d5975363Spbrook     if (child) {
140bdc44640SAndreas Färber         CPUState *cpu, *next_cpu;
141d5975363Spbrook         /* Child processes created by fork() only have a single thread.
142d5975363Spbrook            Discard information about the parent threads.  */
143bdc44640SAndreas Färber         CPU_FOREACH_SAFE(cpu, next_cpu) {
144bdc44640SAndreas Färber             if (cpu != thread_cpu) {
145014628a7SPeter Maydell                 QTAILQ_REMOVE(&cpus, cpu, node);
146bdc44640SAndreas Färber             }
147bdc44640SAndreas Färber         }
14844ded3d0SEmilio G. Cota         qemu_mutex_init(&tb_ctx.tb_lock);
149267f685bSPaolo Bonzini         qemu_init_cpu_list();
150f7ec7f7bSPeter Crosthwaite         gdbserver_fork(thread_cpu);
151d5975363Spbrook     } else {
15244ded3d0SEmilio G. Cota         qemu_mutex_unlock(&tb_ctx.tb_lock);
153267f685bSPaolo Bonzini         cpu_list_unlock();
154d5975363Spbrook     }
155d5975363Spbrook }
156d5975363Spbrook 
157a541f297Sbellard #ifdef TARGET_I386
158a541f297Sbellard /***********************************************************/
159a541f297Sbellard /* CPUX86 core interface */
160a541f297Sbellard 
16128ab0e2eSbellard uint64_t cpu_get_tsc(CPUX86State *env)
16228ab0e2eSbellard {
1634a7428c5SChristopher Covington     return cpu_get_host_ticks();
16428ab0e2eSbellard }
16528ab0e2eSbellard 
166f4beb510Sbellard static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
167f4beb510Sbellard                      int flags)
1686dbad63eSbellard {
169f4beb510Sbellard     unsigned int e1, e2;
17053a5960aSpbrook     uint32_t *p;
1716dbad63eSbellard     e1 = (addr << 16) | (limit & 0xffff);
1726dbad63eSbellard     e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
173f4beb510Sbellard     e2 |= flags;
17453a5960aSpbrook     p = ptr;
175d538e8f5Smalc     p[0] = tswap32(e1);
176d538e8f5Smalc     p[1] = tswap32(e2);
177f4beb510Sbellard }
178f4beb510Sbellard 
179e441570fSbalrog static uint64_t *idt_table;
180eb38c52cSblueswir1 #ifdef TARGET_X86_64
181d2fd1af7Sbellard static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
182d2fd1af7Sbellard                        uint64_t addr, unsigned int sel)
183d2fd1af7Sbellard {
1844dbc422bSbellard     uint32_t *p, e1, e2;
185d2fd1af7Sbellard     e1 = (addr & 0xffff) | (sel << 16);
186d2fd1af7Sbellard     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
187d2fd1af7Sbellard     p = ptr;
1884dbc422bSbellard     p[0] = tswap32(e1);
1894dbc422bSbellard     p[1] = tswap32(e2);
1904dbc422bSbellard     p[2] = tswap32(addr >> 32);
1914dbc422bSbellard     p[3] = 0;
192d2fd1af7Sbellard }
193d2fd1af7Sbellard /* only dpl matters as we do only user space emulation */
194d2fd1af7Sbellard static void set_idt(int n, unsigned int dpl)
195d2fd1af7Sbellard {
196d2fd1af7Sbellard     set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
197d2fd1af7Sbellard }
198d2fd1af7Sbellard #else
199f4beb510Sbellard static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
200d2fd1af7Sbellard                      uint32_t addr, unsigned int sel)
201f4beb510Sbellard {
2024dbc422bSbellard     uint32_t *p, e1, e2;
203f4beb510Sbellard     e1 = (addr & 0xffff) | (sel << 16);
204f4beb510Sbellard     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
20553a5960aSpbrook     p = ptr;
2064dbc422bSbellard     p[0] = tswap32(e1);
2074dbc422bSbellard     p[1] = tswap32(e2);
2086dbad63eSbellard }
2096dbad63eSbellard 
210f4beb510Sbellard /* only dpl matters as we do only user space emulation */
211f4beb510Sbellard static void set_idt(int n, unsigned int dpl)
212f4beb510Sbellard {
213f4beb510Sbellard     set_gate(idt_table + n, 0, dpl, 0, 0);
214f4beb510Sbellard }
215d2fd1af7Sbellard #endif
21631e31b8aSbellard 
21789e957e7Sbellard void cpu_loop(CPUX86State *env)
218bc8a22ccSbellard {
219db6b81d4SAndreas Färber     CPUState *cs = CPU(x86_env_get_cpu(env));
220bc8a22ccSbellard     int trapnr;
221992f48a0Sblueswir1     abi_ulong pc;
2220284b03bSTimothy E Baldwin     abi_ulong ret;
223c227f099SAnthony Liguori     target_siginfo_t info;
224bc8a22ccSbellard 
225bc8a22ccSbellard     for(;;) {
226b040bc9cSPeter Maydell         cpu_exec_start(cs);
2278642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
228b040bc9cSPeter Maydell         cpu_exec_end(cs);
229d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
230d148d90eSSergey Fedorov 
231bc8a22ccSbellard         switch(trapnr) {
232f4beb510Sbellard         case 0x80:
233d2fd1af7Sbellard             /* linux syscall from int $0x80 */
2340284b03bSTimothy E Baldwin             ret = do_syscall(env,
2351b6b029eSbellard                              env->regs[R_EAX],
2361b6b029eSbellard                              env->regs[R_EBX],
2371b6b029eSbellard                              env->regs[R_ECX],
2381b6b029eSbellard                              env->regs[R_EDX],
2391b6b029eSbellard                              env->regs[R_ESI],
2401b6b029eSbellard                              env->regs[R_EDI],
2415945cfcbSPeter Maydell                              env->regs[R_EBP],
2425945cfcbSPeter Maydell                              0, 0);
2430284b03bSTimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
2440284b03bSTimothy E Baldwin                 env->eip -= 2;
2450284b03bSTimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
2460284b03bSTimothy E Baldwin                 env->regs[R_EAX] = ret;
2470284b03bSTimothy E Baldwin             }
248f4beb510Sbellard             break;
249d2fd1af7Sbellard #ifndef TARGET_ABI32
250d2fd1af7Sbellard         case EXCP_SYSCALL:
2515ba18547SStefan Weil             /* linux syscall from syscall instruction */
2520284b03bSTimothy E Baldwin             ret = do_syscall(env,
253d2fd1af7Sbellard                              env->regs[R_EAX],
254d2fd1af7Sbellard                              env->regs[R_EDI],
255d2fd1af7Sbellard                              env->regs[R_ESI],
256d2fd1af7Sbellard                              env->regs[R_EDX],
257d2fd1af7Sbellard                              env->regs[10],
258d2fd1af7Sbellard                              env->regs[8],
2595945cfcbSPeter Maydell                              env->regs[9],
2605945cfcbSPeter Maydell                              0, 0);
2610284b03bSTimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
2620284b03bSTimothy E Baldwin                 env->eip -= 2;
2630284b03bSTimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
2640284b03bSTimothy E Baldwin                 env->regs[R_EAX] = ret;
2650284b03bSTimothy E Baldwin             }
266d2fd1af7Sbellard             break;
267d2fd1af7Sbellard #endif
268f4beb510Sbellard         case EXCP0B_NOSEG:
269f4beb510Sbellard         case EXCP0C_STACK:
270a86b3c64SChen Gang S             info.si_signo = TARGET_SIGBUS;
271f4beb510Sbellard             info.si_errno = 0;
272f4beb510Sbellard             info.si_code = TARGET_SI_KERNEL;
273f4beb510Sbellard             info._sifields._sigfault._addr = 0;
2749d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
275f4beb510Sbellard             break;
276f4beb510Sbellard         case EXCP0D_GPF:
277d2fd1af7Sbellard             /* XXX: potential problem if ABI32 */
27884409ddbSj_mayer #ifndef TARGET_X86_64
279f4beb510Sbellard             if (env->eflags & VM_MASK) {
280f4beb510Sbellard                 handle_vm86_fault(env);
28184409ddbSj_mayer             } else
28284409ddbSj_mayer #endif
28384409ddbSj_mayer             {
284a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGSEGV;
2859de5e440Sbellard                 info.si_errno = 0;
286b689bc57Sbellard                 info.si_code = TARGET_SI_KERNEL;
2879de5e440Sbellard                 info._sifields._sigfault._addr = 0;
2889d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2891b6b029eSbellard             }
2901b6b029eSbellard             break;
291b689bc57Sbellard         case EXCP0E_PAGE:
292a86b3c64SChen Gang S             info.si_signo = TARGET_SIGSEGV;
293b689bc57Sbellard             info.si_errno = 0;
294b689bc57Sbellard             if (!(env->error_code & 1))
295b689bc57Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
296b689bc57Sbellard             else
297b689bc57Sbellard                 info.si_code = TARGET_SEGV_ACCERR;
298970a87a6Sbellard             info._sifields._sigfault._addr = env->cr[2];
2999d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
300b689bc57Sbellard             break;
3019de5e440Sbellard         case EXCP00_DIVZ:
30284409ddbSj_mayer #ifndef TARGET_X86_64
303bc8a22ccSbellard             if (env->eflags & VM_MASK) {
304447db213Sbellard                 handle_vm86_trap(env, trapnr);
30584409ddbSj_mayer             } else
30684409ddbSj_mayer #endif
30784409ddbSj_mayer             {
3089de5e440Sbellard                 /* division by zero */
309a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGFPE;
3109de5e440Sbellard                 info.si_errno = 0;
3119de5e440Sbellard                 info.si_code = TARGET_FPE_INTDIV;
3129de5e440Sbellard                 info._sifields._sigfault._addr = env->eip;
3139d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
314bc8a22ccSbellard             }
3159de5e440Sbellard             break;
31601df040bSaliguori         case EXCP01_DB:
317447db213Sbellard         case EXCP03_INT3:
31884409ddbSj_mayer #ifndef TARGET_X86_64
319447db213Sbellard             if (env->eflags & VM_MASK) {
320447db213Sbellard                 handle_vm86_trap(env, trapnr);
32184409ddbSj_mayer             } else
32284409ddbSj_mayer #endif
32384409ddbSj_mayer             {
324a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGTRAP;
325447db213Sbellard                 info.si_errno = 0;
32601df040bSaliguori                 if (trapnr == EXCP01_DB) {
327447db213Sbellard                     info.si_code = TARGET_TRAP_BRKPT;
328447db213Sbellard                     info._sifields._sigfault._addr = env->eip;
329447db213Sbellard                 } else {
330447db213Sbellard                     info.si_code = TARGET_SI_KERNEL;
331447db213Sbellard                     info._sifields._sigfault._addr = 0;
332447db213Sbellard                 }
3339d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
334447db213Sbellard             }
335447db213Sbellard             break;
3369de5e440Sbellard         case EXCP04_INTO:
3379de5e440Sbellard         case EXCP05_BOUND:
33884409ddbSj_mayer #ifndef TARGET_X86_64
339bc8a22ccSbellard             if (env->eflags & VM_MASK) {
340447db213Sbellard                 handle_vm86_trap(env, trapnr);
34184409ddbSj_mayer             } else
34284409ddbSj_mayer #endif
34384409ddbSj_mayer             {
344a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGSEGV;
3459de5e440Sbellard                 info.si_errno = 0;
346b689bc57Sbellard                 info.si_code = TARGET_SI_KERNEL;
3479de5e440Sbellard                 info._sifields._sigfault._addr = 0;
3489d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
349bc8a22ccSbellard             }
3509de5e440Sbellard             break;
3519de5e440Sbellard         case EXCP06_ILLOP:
352a86b3c64SChen Gang S             info.si_signo = TARGET_SIGILL;
3539de5e440Sbellard             info.si_errno = 0;
3549de5e440Sbellard             info.si_code = TARGET_ILL_ILLOPN;
3559de5e440Sbellard             info._sifields._sigfault._addr = env->eip;
3569d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3579de5e440Sbellard             break;
3589de5e440Sbellard         case EXCP_INTERRUPT:
3599de5e440Sbellard             /* just indicate that signals should be handled asap */
3609de5e440Sbellard             break;
3611fddef4bSbellard         case EXCP_DEBUG:
3621fddef4bSbellard             {
3631fddef4bSbellard                 int sig;
3641fddef4bSbellard 
365db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
3661fddef4bSbellard                 if (sig)
3671fddef4bSbellard                   {
3681fddef4bSbellard                     info.si_signo = sig;
3691fddef4bSbellard                     info.si_errno = 0;
3701fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
3719d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3721fddef4bSbellard                   }
3731fddef4bSbellard             }
3741fddef4bSbellard             break;
375fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
376fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
377fdbc2b57SRichard Henderson             break;
3781b6b029eSbellard         default:
379970a87a6Sbellard             pc = env->segs[R_CS].base + env->eip;
380120a9848SPaolo Bonzini             EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
381bc8a22ccSbellard                       (long)pc, trapnr);
3821b6b029eSbellard             abort();
3831b6b029eSbellard         }
38466fb9763Sbellard         process_pending_signals(env);
3851b6b029eSbellard     }
3861b6b029eSbellard }
387b346ff46Sbellard #endif
388b346ff46Sbellard 
389b346ff46Sbellard #ifdef TARGET_ARM
390b346ff46Sbellard 
39149017bd8SPaolo Bonzini #define get_user_code_u32(x, gaddr, env)                \
392d8fd2954SPaul Brook     ({ abi_long __r = get_user_u32((x), (gaddr));       \
393f9fd40ebSPaolo Bonzini         if (!__r && bswap_code(arm_sctlr_b(env))) {     \
394d8fd2954SPaul Brook             (x) = bswap32(x);                           \
395d8fd2954SPaul Brook         }                                               \
396d8fd2954SPaul Brook         __r;                                            \
397d8fd2954SPaul Brook     })
398d8fd2954SPaul Brook 
39949017bd8SPaolo Bonzini #define get_user_code_u16(x, gaddr, env)                \
400d8fd2954SPaul Brook     ({ abi_long __r = get_user_u16((x), (gaddr));       \
401f9fd40ebSPaolo Bonzini         if (!__r && bswap_code(arm_sctlr_b(env))) {     \
402d8fd2954SPaul Brook             (x) = bswap16(x);                           \
403d8fd2954SPaul Brook         }                                               \
404d8fd2954SPaul Brook         __r;                                            \
405d8fd2954SPaul Brook     })
406d8fd2954SPaul Brook 
407c3ae85fcSPaolo Bonzini #define get_user_data_u32(x, gaddr, env)                \
408c3ae85fcSPaolo Bonzini     ({ abi_long __r = get_user_u32((x), (gaddr));       \
409c3ae85fcSPaolo Bonzini         if (!__r && arm_cpu_bswap_data(env)) {          \
410c3ae85fcSPaolo Bonzini             (x) = bswap32(x);                           \
411c3ae85fcSPaolo Bonzini         }                                               \
412c3ae85fcSPaolo Bonzini         __r;                                            \
413c3ae85fcSPaolo Bonzini     })
414c3ae85fcSPaolo Bonzini 
415c3ae85fcSPaolo Bonzini #define get_user_data_u16(x, gaddr, env)                \
416c3ae85fcSPaolo Bonzini     ({ abi_long __r = get_user_u16((x), (gaddr));       \
417c3ae85fcSPaolo Bonzini         if (!__r && arm_cpu_bswap_data(env)) {          \
418c3ae85fcSPaolo Bonzini             (x) = bswap16(x);                           \
419c3ae85fcSPaolo Bonzini         }                                               \
420c3ae85fcSPaolo Bonzini         __r;                                            \
421c3ae85fcSPaolo Bonzini     })
422c3ae85fcSPaolo Bonzini 
423c3ae85fcSPaolo Bonzini #define put_user_data_u32(x, gaddr, env)                \
424c3ae85fcSPaolo Bonzini     ({ typeof(x) __x = (x);                             \
425c3ae85fcSPaolo Bonzini         if (arm_cpu_bswap_data(env)) {                  \
426c3ae85fcSPaolo Bonzini             __x = bswap32(__x);                         \
427c3ae85fcSPaolo Bonzini         }                                               \
428c3ae85fcSPaolo Bonzini         put_user_u32(__x, (gaddr));                     \
429c3ae85fcSPaolo Bonzini     })
430c3ae85fcSPaolo Bonzini 
431c3ae85fcSPaolo Bonzini #define put_user_data_u16(x, gaddr, env)                \
432c3ae85fcSPaolo Bonzini     ({ typeof(x) __x = (x);                             \
433c3ae85fcSPaolo Bonzini         if (arm_cpu_bswap_data(env)) {                  \
434c3ae85fcSPaolo Bonzini             __x = bswap16(__x);                         \
435c3ae85fcSPaolo Bonzini         }                                               \
436c3ae85fcSPaolo Bonzini         put_user_u16(__x, (gaddr));                     \
437c3ae85fcSPaolo Bonzini     })
438c3ae85fcSPaolo Bonzini 
4391861c454SPeter Maydell #ifdef TARGET_ABI32
4401861c454SPeter Maydell /* Commpage handling -- there is no commpage for AArch64 */
4411861c454SPeter Maydell 
44297cc7560SDr. David Alan Gilbert /*
44397cc7560SDr. David Alan Gilbert  * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
44497cc7560SDr. David Alan Gilbert  * Input:
44597cc7560SDr. David Alan Gilbert  * r0 = pointer to oldval
44697cc7560SDr. David Alan Gilbert  * r1 = pointer to newval
44797cc7560SDr. David Alan Gilbert  * r2 = pointer to target value
44897cc7560SDr. David Alan Gilbert  *
44997cc7560SDr. David Alan Gilbert  * Output:
45097cc7560SDr. David Alan Gilbert  * r0 = 0 if *ptr was changed, non-0 if no exchange happened
45197cc7560SDr. David Alan Gilbert  * C set if *ptr was changed, clear if no exchange happened
45297cc7560SDr. David Alan Gilbert  *
45397cc7560SDr. David Alan Gilbert  * Note segv's in kernel helpers are a bit tricky, we can set the
45497cc7560SDr. David Alan Gilbert  * data address sensibly but the PC address is just the entry point.
45597cc7560SDr. David Alan Gilbert  */
45697cc7560SDr. David Alan Gilbert static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
45797cc7560SDr. David Alan Gilbert {
45897cc7560SDr. David Alan Gilbert     uint64_t oldval, newval, val;
45997cc7560SDr. David Alan Gilbert     uint32_t addr, cpsr;
46097cc7560SDr. David Alan Gilbert     target_siginfo_t info;
46197cc7560SDr. David Alan Gilbert 
46297cc7560SDr. David Alan Gilbert     /* Based on the 32 bit code in do_kernel_trap */
46397cc7560SDr. David Alan Gilbert 
46497cc7560SDr. David Alan Gilbert     /* XXX: This only works between threads, not between processes.
46597cc7560SDr. David Alan Gilbert        It's probably possible to implement this with native host
46697cc7560SDr. David Alan Gilbert        operations. However things like ldrex/strex are much harder so
46797cc7560SDr. David Alan Gilbert        there's not much point trying.  */
46897cc7560SDr. David Alan Gilbert     start_exclusive();
46997cc7560SDr. David Alan Gilbert     cpsr = cpsr_read(env);
47097cc7560SDr. David Alan Gilbert     addr = env->regs[2];
47197cc7560SDr. David Alan Gilbert 
47297cc7560SDr. David Alan Gilbert     if (get_user_u64(oldval, env->regs[0])) {
473abf1172fSPeter Maydell         env->exception.vaddress = env->regs[0];
47497cc7560SDr. David Alan Gilbert         goto segv;
47597cc7560SDr. David Alan Gilbert     };
47697cc7560SDr. David Alan Gilbert 
47797cc7560SDr. David Alan Gilbert     if (get_user_u64(newval, env->regs[1])) {
478abf1172fSPeter Maydell         env->exception.vaddress = env->regs[1];
47997cc7560SDr. David Alan Gilbert         goto segv;
48097cc7560SDr. David Alan Gilbert     };
48197cc7560SDr. David Alan Gilbert 
48297cc7560SDr. David Alan Gilbert     if (get_user_u64(val, addr)) {
483abf1172fSPeter Maydell         env->exception.vaddress = addr;
48497cc7560SDr. David Alan Gilbert         goto segv;
48597cc7560SDr. David Alan Gilbert     }
48697cc7560SDr. David Alan Gilbert 
48797cc7560SDr. David Alan Gilbert     if (val == oldval) {
48897cc7560SDr. David Alan Gilbert         val = newval;
48997cc7560SDr. David Alan Gilbert 
49097cc7560SDr. David Alan Gilbert         if (put_user_u64(val, addr)) {
491abf1172fSPeter Maydell             env->exception.vaddress = addr;
49297cc7560SDr. David Alan Gilbert             goto segv;
49397cc7560SDr. David Alan Gilbert         };
49497cc7560SDr. David Alan Gilbert 
49597cc7560SDr. David Alan Gilbert         env->regs[0] = 0;
49697cc7560SDr. David Alan Gilbert         cpsr |= CPSR_C;
49797cc7560SDr. David Alan Gilbert     } else {
49897cc7560SDr. David Alan Gilbert         env->regs[0] = -1;
49997cc7560SDr. David Alan Gilbert         cpsr &= ~CPSR_C;
50097cc7560SDr. David Alan Gilbert     }
50150866ba5SPeter Maydell     cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
50297cc7560SDr. David Alan Gilbert     end_exclusive();
50397cc7560SDr. David Alan Gilbert     return;
50497cc7560SDr. David Alan Gilbert 
50597cc7560SDr. David Alan Gilbert segv:
50697cc7560SDr. David Alan Gilbert     end_exclusive();
50797cc7560SDr. David Alan Gilbert     /* We get the PC of the entry address - which is as good as anything,
50897cc7560SDr. David Alan Gilbert        on a real kernel what you get depends on which mode it uses. */
509a86b3c64SChen Gang S     info.si_signo = TARGET_SIGSEGV;
51097cc7560SDr. David Alan Gilbert     info.si_errno = 0;
51197cc7560SDr. David Alan Gilbert     /* XXX: check env->error_code */
51297cc7560SDr. David Alan Gilbert     info.si_code = TARGET_SEGV_MAPERR;
513abf1172fSPeter Maydell     info._sifields._sigfault._addr = env->exception.vaddress;
5149d2803f7SPeter Maydell     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
51597cc7560SDr. David Alan Gilbert }
51697cc7560SDr. David Alan Gilbert 
517fbb4a2e3Spbrook /* Handle a jump to the kernel code page.  */
518fbb4a2e3Spbrook static int
519fbb4a2e3Spbrook do_kernel_trap(CPUARMState *env)
520fbb4a2e3Spbrook {
521fbb4a2e3Spbrook     uint32_t addr;
522fbb4a2e3Spbrook     uint32_t cpsr;
523fbb4a2e3Spbrook     uint32_t val;
524fbb4a2e3Spbrook 
525fbb4a2e3Spbrook     switch (env->regs[15]) {
526fbb4a2e3Spbrook     case 0xffff0fa0: /* __kernel_memory_barrier */
527fbb4a2e3Spbrook         /* ??? No-op. Will need to do better for SMP.  */
528fbb4a2e3Spbrook         break;
529fbb4a2e3Spbrook     case 0xffff0fc0: /* __kernel_cmpxchg */
530d5975363Spbrook          /* XXX: This only works between threads, not between processes.
531d5975363Spbrook             It's probably possible to implement this with native host
532d5975363Spbrook             operations. However things like ldrex/strex are much harder so
533d5975363Spbrook             there's not much point trying.  */
534d5975363Spbrook         start_exclusive();
535fbb4a2e3Spbrook         cpsr = cpsr_read(env);
536fbb4a2e3Spbrook         addr = env->regs[2];
537fbb4a2e3Spbrook         /* FIXME: This should SEGV if the access fails.  */
538fbb4a2e3Spbrook         if (get_user_u32(val, addr))
539fbb4a2e3Spbrook             val = ~env->regs[0];
540fbb4a2e3Spbrook         if (val == env->regs[0]) {
541fbb4a2e3Spbrook             val = env->regs[1];
542fbb4a2e3Spbrook             /* FIXME: Check for segfaults.  */
543fbb4a2e3Spbrook             put_user_u32(val, addr);
544fbb4a2e3Spbrook             env->regs[0] = 0;
545fbb4a2e3Spbrook             cpsr |= CPSR_C;
546fbb4a2e3Spbrook         } else {
547fbb4a2e3Spbrook             env->regs[0] = -1;
548fbb4a2e3Spbrook             cpsr &= ~CPSR_C;
549fbb4a2e3Spbrook         }
55050866ba5SPeter Maydell         cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
551d5975363Spbrook         end_exclusive();
552fbb4a2e3Spbrook         break;
553fbb4a2e3Spbrook     case 0xffff0fe0: /* __kernel_get_tls */
554b8d43285SMikhail Ilyin         env->regs[0] = cpu_get_tls(env);
555fbb4a2e3Spbrook         break;
55697cc7560SDr. David Alan Gilbert     case 0xffff0f60: /* __kernel_cmpxchg64 */
55797cc7560SDr. David Alan Gilbert         arm_kernel_cmpxchg64_helper(env);
55897cc7560SDr. David Alan Gilbert         break;
55997cc7560SDr. David Alan Gilbert 
560fbb4a2e3Spbrook     default:
561fbb4a2e3Spbrook         return 1;
562fbb4a2e3Spbrook     }
563fbb4a2e3Spbrook     /* Jump back to the caller.  */
564fbb4a2e3Spbrook     addr = env->regs[14];
565fbb4a2e3Spbrook     if (addr & 1) {
566fbb4a2e3Spbrook         env->thumb = 1;
567fbb4a2e3Spbrook         addr &= ~1;
568fbb4a2e3Spbrook     }
569fbb4a2e3Spbrook     env->regs[15] = addr;
570fbb4a2e3Spbrook 
571fbb4a2e3Spbrook     return 0;
572fbb4a2e3Spbrook }
573fbb4a2e3Spbrook 
574b346ff46Sbellard void cpu_loop(CPUARMState *env)
575b346ff46Sbellard {
5760315c31cSAndreas Färber     CPUState *cs = CPU(arm_env_get_cpu(env));
577b346ff46Sbellard     int trapnr;
578b346ff46Sbellard     unsigned int n, insn;
579c227f099SAnthony Liguori     target_siginfo_t info;
580b5ff1b31Sbellard     uint32_t addr;
581f0267ef7STimothy E Baldwin     abi_ulong ret;
582b346ff46Sbellard 
583b346ff46Sbellard     for(;;) {
5840315c31cSAndreas Färber         cpu_exec_start(cs);
5858642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
5860315c31cSAndreas Färber         cpu_exec_end(cs);
587d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
588d148d90eSSergey Fedorov 
589b346ff46Sbellard         switch(trapnr) {
590b346ff46Sbellard         case EXCP_UDEF:
5917517748eSPeter Maydell         case EXCP_NOCP:
592e13886e3SPeter Maydell         case EXCP_INVSTATE:
593c6981055Sbellard             {
5940429a971SAndreas Färber                 TaskState *ts = cs->opaque;
595c6981055Sbellard                 uint32_t opcode;
5966d9a42beSaurel32                 int rc;
597c6981055Sbellard 
598c6981055Sbellard                 /* we handle the FPU emulation here, as Linux */
599c6981055Sbellard                 /* we get the opcode */
6002f619698Sbellard                 /* FIXME - what to do if get_user() fails? */
60149017bd8SPaolo Bonzini                 get_user_code_u32(opcode, env->regs[15], env);
602c6981055Sbellard 
6036d9a42beSaurel32                 rc = EmulateAll(opcode, &ts->fpa, env);
6046d9a42beSaurel32                 if (rc == 0) { /* illegal instruction */
605a86b3c64SChen Gang S                     info.si_signo = TARGET_SIGILL;
606b346ff46Sbellard                     info.si_errno = 0;
607b346ff46Sbellard                     info.si_code = TARGET_ILL_ILLOPN;
608b346ff46Sbellard                     info._sifields._sigfault._addr = env->regs[15];
6099d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
6106d9a42beSaurel32                 } else if (rc < 0) { /* FP exception */
6116d9a42beSaurel32                     int arm_fpe=0;
6126d9a42beSaurel32 
6136d9a42beSaurel32                     /* translate softfloat flags to FPSR flags */
6146d9a42beSaurel32                     if (-rc & float_flag_invalid)
6156d9a42beSaurel32                       arm_fpe |= BIT_IOC;
6166d9a42beSaurel32                     if (-rc & float_flag_divbyzero)
6176d9a42beSaurel32                       arm_fpe |= BIT_DZC;
6186d9a42beSaurel32                     if (-rc & float_flag_overflow)
6196d9a42beSaurel32                       arm_fpe |= BIT_OFC;
6206d9a42beSaurel32                     if (-rc & float_flag_underflow)
6216d9a42beSaurel32                       arm_fpe |= BIT_UFC;
6226d9a42beSaurel32                     if (-rc & float_flag_inexact)
6236d9a42beSaurel32                       arm_fpe |= BIT_IXC;
6246d9a42beSaurel32 
6256d9a42beSaurel32                     FPSR fpsr = ts->fpa.fpsr;
6266d9a42beSaurel32                     //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
6276d9a42beSaurel32 
6286d9a42beSaurel32                     if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
629a86b3c64SChen Gang S                       info.si_signo = TARGET_SIGFPE;
6306d9a42beSaurel32                       info.si_errno = 0;
6316d9a42beSaurel32 
6326d9a42beSaurel32                       /* ordered by priority, least first */
6336d9a42beSaurel32                       if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
6346d9a42beSaurel32                       if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
6356d9a42beSaurel32                       if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
6366d9a42beSaurel32                       if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
6376d9a42beSaurel32                       if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
6386d9a42beSaurel32 
6396d9a42beSaurel32                       info._sifields._sigfault._addr = env->regs[15];
6409d2803f7SPeter Maydell                       queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
641c6981055Sbellard                     } else {
6426d9a42beSaurel32                       env->regs[15] += 4;
6436d9a42beSaurel32                     }
6446d9a42beSaurel32 
6456d9a42beSaurel32                     /* accumulate unenabled exceptions */
6466d9a42beSaurel32                     if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
6476d9a42beSaurel32                       fpsr |= BIT_IXC;
6486d9a42beSaurel32                     if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
6496d9a42beSaurel32                       fpsr |= BIT_UFC;
6506d9a42beSaurel32                     if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
6516d9a42beSaurel32                       fpsr |= BIT_OFC;
6526d9a42beSaurel32                     if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
6536d9a42beSaurel32                       fpsr |= BIT_DZC;
6546d9a42beSaurel32                     if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
6556d9a42beSaurel32                       fpsr |= BIT_IOC;
6566d9a42beSaurel32                     ts->fpa.fpsr=fpsr;
6576d9a42beSaurel32                 } else { /* everything OK */
658c6981055Sbellard                     /* increment PC */
659c6981055Sbellard                     env->regs[15] += 4;
660c6981055Sbellard                 }
661c6981055Sbellard             }
662b346ff46Sbellard             break;
663b346ff46Sbellard         case EXCP_SWI:
66406c949e6Spbrook         case EXCP_BKPT:
665b346ff46Sbellard             {
666ce4defa0Spbrook                 env->eabi = 1;
667b346ff46Sbellard                 /* system call */
66806c949e6Spbrook                 if (trapnr == EXCP_BKPT) {
66906c949e6Spbrook                     if (env->thumb) {
6702f619698Sbellard                         /* FIXME - what to do if get_user() fails? */
67149017bd8SPaolo Bonzini                         get_user_code_u16(insn, env->regs[15], env);
67206c949e6Spbrook                         n = insn & 0xff;
67306c949e6Spbrook                         env->regs[15] += 2;
67406c949e6Spbrook                     } else {
6752f619698Sbellard                         /* FIXME - what to do if get_user() fails? */
67649017bd8SPaolo Bonzini                         get_user_code_u32(insn, env->regs[15], env);
67706c949e6Spbrook                         n = (insn & 0xf) | ((insn >> 4) & 0xff0);
67806c949e6Spbrook                         env->regs[15] += 4;
67906c949e6Spbrook                     }
68006c949e6Spbrook                 } else {
681192c7bd9Sbellard                     if (env->thumb) {
6822f619698Sbellard                         /* FIXME - what to do if get_user() fails? */
68349017bd8SPaolo Bonzini                         get_user_code_u16(insn, env->regs[15] - 2, env);
684192c7bd9Sbellard                         n = insn & 0xff;
685192c7bd9Sbellard                     } else {
6862f619698Sbellard                         /* FIXME - what to do if get_user() fails? */
68749017bd8SPaolo Bonzini                         get_user_code_u32(insn, env->regs[15] - 4, env);
688b346ff46Sbellard                         n = insn & 0xffffff;
689192c7bd9Sbellard                     }
69006c949e6Spbrook                 }
691192c7bd9Sbellard 
6926f1f31c0Sbellard                 if (n == ARM_NR_cacheflush) {
693dcfd14b3SBlue Swirl                     /* nop */
694a4f81979Sbellard                 } else if (n == ARM_NR_semihosting
695a4f81979Sbellard                            || n == ARM_NR_thumb_semihosting) {
696a4f81979Sbellard                     env->regs[0] = do_arm_semihosting (env);
6973a1363acSAlexander Graf                 } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
698b346ff46Sbellard                     /* linux syscall */
699ce4defa0Spbrook                     if (env->thumb || n == 0) {
700192c7bd9Sbellard                         n = env->regs[7];
701192c7bd9Sbellard                     } else {
702b346ff46Sbellard                         n -= ARM_SYSCALL_BASE;
703ce4defa0Spbrook                         env->eabi = 0;
704192c7bd9Sbellard                     }
705fbb4a2e3Spbrook                     if ( n > ARM_NR_BASE) {
706fbb4a2e3Spbrook                         switch (n) {
707fbb4a2e3Spbrook                         case ARM_NR_cacheflush:
708dcfd14b3SBlue Swirl                             /* nop */
709fbb4a2e3Spbrook                             break;
710fbb4a2e3Spbrook                         case ARM_NR_set_tls:
711fbb4a2e3Spbrook                             cpu_set_tls(env, env->regs[0]);
712fbb4a2e3Spbrook                             env->regs[0] = 0;
713fbb4a2e3Spbrook                             break;
714d5355087SHunter Laux                         case ARM_NR_breakpoint:
715d5355087SHunter Laux                             env->regs[15] -= env->thumb ? 2 : 4;
716d5355087SHunter Laux                             goto excp_debug;
717fbb4a2e3Spbrook                         default:
718fbb4a2e3Spbrook                             gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
719fbb4a2e3Spbrook                                      n);
720fbb4a2e3Spbrook                             env->regs[0] = -TARGET_ENOSYS;
721fbb4a2e3Spbrook                             break;
722fbb4a2e3Spbrook                         }
723fbb4a2e3Spbrook                     } else {
724f0267ef7STimothy E Baldwin                         ret = do_syscall(env,
725b346ff46Sbellard                                          n,
726b346ff46Sbellard                                          env->regs[0],
727b346ff46Sbellard                                          env->regs[1],
728b346ff46Sbellard                                          env->regs[2],
729b346ff46Sbellard                                          env->regs[3],
730b346ff46Sbellard                                          env->regs[4],
7315945cfcbSPeter Maydell                                          env->regs[5],
7325945cfcbSPeter Maydell                                          0, 0);
733f0267ef7STimothy E Baldwin                         if (ret == -TARGET_ERESTARTSYS) {
734f0267ef7STimothy E Baldwin                             env->regs[15] -= env->thumb ? 2 : 4;
735f0267ef7STimothy E Baldwin                         } else if (ret != -TARGET_QEMU_ESIGRETURN) {
736f0267ef7STimothy E Baldwin                             env->regs[0] = ret;
737f0267ef7STimothy E Baldwin                         }
738fbb4a2e3Spbrook                     }
739b346ff46Sbellard                 } else {
740b346ff46Sbellard                     goto error;
741b346ff46Sbellard                 }
742b346ff46Sbellard             }
743b346ff46Sbellard             break;
74419a6e31cSPeter Maydell         case EXCP_SEMIHOST:
74519a6e31cSPeter Maydell             env->regs[0] = do_arm_semihosting(env);
74619a6e31cSPeter Maydell             break;
74743fff238Sbellard         case EXCP_INTERRUPT:
74843fff238Sbellard             /* just indicate that signals should be handled asap */
74943fff238Sbellard             break;
75068016c62Sbellard         case EXCP_PREFETCH_ABORT:
75168016c62Sbellard         case EXCP_DATA_ABORT:
752abf1172fSPeter Maydell             addr = env->exception.vaddress;
75368016c62Sbellard             {
754a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGSEGV;
75568016c62Sbellard                 info.si_errno = 0;
75668016c62Sbellard                 /* XXX: check env->error_code */
75768016c62Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
758b5ff1b31Sbellard                 info._sifields._sigfault._addr = addr;
7599d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
76068016c62Sbellard             }
76168016c62Sbellard             break;
7621fddef4bSbellard         case EXCP_DEBUG:
763d5355087SHunter Laux         excp_debug:
7641fddef4bSbellard             {
7651fddef4bSbellard                 int sig;
7661fddef4bSbellard 
767db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
7681fddef4bSbellard                 if (sig)
7691fddef4bSbellard                   {
7701fddef4bSbellard                     info.si_signo = sig;
7711fddef4bSbellard                     info.si_errno = 0;
7721fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
7739d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
7741fddef4bSbellard                   }
7751fddef4bSbellard             }
7761fddef4bSbellard             break;
777fbb4a2e3Spbrook         case EXCP_KERNEL_TRAP:
778fbb4a2e3Spbrook             if (do_kernel_trap(env))
779fbb4a2e3Spbrook               goto error;
780fbb4a2e3Spbrook             break;
781f911e0a3SPeter Maydell         case EXCP_YIELD:
782f911e0a3SPeter Maydell             /* nothing to do here for user-mode, just resume guest code */
783f911e0a3SPeter Maydell             break;
784fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
785fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
786fdbc2b57SRichard Henderson             break;
787b346ff46Sbellard         default:
788b346ff46Sbellard         error:
789120a9848SPaolo Bonzini             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
790b346ff46Sbellard             abort();
791b346ff46Sbellard         }
792b346ff46Sbellard         process_pending_signals(env);
793b346ff46Sbellard     }
794b346ff46Sbellard }
795b346ff46Sbellard 
7961861c454SPeter Maydell #else
7971861c454SPeter Maydell 
7981861c454SPeter Maydell /* AArch64 main loop */
7991861c454SPeter Maydell void cpu_loop(CPUARMState *env)
8001861c454SPeter Maydell {
8011861c454SPeter Maydell     CPUState *cs = CPU(arm_env_get_cpu(env));
8021861c454SPeter Maydell     int trapnr, sig;
803f0267ef7STimothy E Baldwin     abi_long ret;
8041861c454SPeter Maydell     target_siginfo_t info;
8051861c454SPeter Maydell 
8061861c454SPeter Maydell     for (;;) {
8071861c454SPeter Maydell         cpu_exec_start(cs);
8088642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
8091861c454SPeter Maydell         cpu_exec_end(cs);
810d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
8111861c454SPeter Maydell 
8121861c454SPeter Maydell         switch (trapnr) {
8131861c454SPeter Maydell         case EXCP_SWI:
814f0267ef7STimothy E Baldwin             ret = do_syscall(env,
8151861c454SPeter Maydell                              env->xregs[8],
8161861c454SPeter Maydell                              env->xregs[0],
8171861c454SPeter Maydell                              env->xregs[1],
8181861c454SPeter Maydell                              env->xregs[2],
8191861c454SPeter Maydell                              env->xregs[3],
8201861c454SPeter Maydell                              env->xregs[4],
8211861c454SPeter Maydell                              env->xregs[5],
8221861c454SPeter Maydell                              0, 0);
823f0267ef7STimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
824f0267ef7STimothy E Baldwin                 env->pc -= 4;
825f0267ef7STimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
826f0267ef7STimothy E Baldwin                 env->xregs[0] = ret;
827f0267ef7STimothy E Baldwin             }
8281861c454SPeter Maydell             break;
8291861c454SPeter Maydell         case EXCP_INTERRUPT:
8301861c454SPeter Maydell             /* just indicate that signals should be handled asap */
8311861c454SPeter Maydell             break;
8321861c454SPeter Maydell         case EXCP_UDEF:
833a86b3c64SChen Gang S             info.si_signo = TARGET_SIGILL;
8341861c454SPeter Maydell             info.si_errno = 0;
8351861c454SPeter Maydell             info.si_code = TARGET_ILL_ILLOPN;
8361861c454SPeter Maydell             info._sifields._sigfault._addr = env->pc;
8379d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
8381861c454SPeter Maydell             break;
8391861c454SPeter Maydell         case EXCP_PREFETCH_ABORT:
8401861c454SPeter Maydell         case EXCP_DATA_ABORT:
841a86b3c64SChen Gang S             info.si_signo = TARGET_SIGSEGV;
8421861c454SPeter Maydell             info.si_errno = 0;
8431861c454SPeter Maydell             /* XXX: check env->error_code */
8441861c454SPeter Maydell             info.si_code = TARGET_SEGV_MAPERR;
845686581adSRiku Voipio             info._sifields._sigfault._addr = env->exception.vaddress;
8469d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
8471861c454SPeter Maydell             break;
8481861c454SPeter Maydell         case EXCP_DEBUG:
8491861c454SPeter Maydell         case EXCP_BKPT:
8501861c454SPeter Maydell             sig = gdb_handlesig(cs, TARGET_SIGTRAP);
8511861c454SPeter Maydell             if (sig) {
8521861c454SPeter Maydell                 info.si_signo = sig;
8531861c454SPeter Maydell                 info.si_errno = 0;
8541861c454SPeter Maydell                 info.si_code = TARGET_TRAP_BRKPT;
8559d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
8561861c454SPeter Maydell             }
8571861c454SPeter Maydell             break;
8588012c84fSPeter Maydell         case EXCP_SEMIHOST:
8598012c84fSPeter Maydell             env->xregs[0] = do_arm_semihosting(env);
8608012c84fSPeter Maydell             break;
861f911e0a3SPeter Maydell         case EXCP_YIELD:
862f911e0a3SPeter Maydell             /* nothing to do here for user-mode, just resume guest code */
863f911e0a3SPeter Maydell             break;
864fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
865fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
866fdbc2b57SRichard Henderson             break;
8671861c454SPeter Maydell         default:
868120a9848SPaolo Bonzini             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
8691861c454SPeter Maydell             abort();
8701861c454SPeter Maydell         }
8711861c454SPeter Maydell         process_pending_signals(env);
872fa2ef212SMichael Matz         /* Exception return on AArch64 always clears the exclusive monitor,
873fa2ef212SMichael Matz          * so any return to running guest code implies this.
874fa2ef212SMichael Matz          */
875fa2ef212SMichael Matz         env->exclusive_addr = -1;
8761861c454SPeter Maydell     }
8771861c454SPeter Maydell }
8781861c454SPeter Maydell #endif /* ndef TARGET_ABI32 */
8791861c454SPeter Maydell 
880b346ff46Sbellard #endif
8811b6b029eSbellard 
882d2fbca94SGuan Xuetao #ifdef TARGET_UNICORE32
883d2fbca94SGuan Xuetao 
88405390248SAndreas Färber void cpu_loop(CPUUniCore32State *env)
885d2fbca94SGuan Xuetao {
8860315c31cSAndreas Färber     CPUState *cs = CPU(uc32_env_get_cpu(env));
887d2fbca94SGuan Xuetao     int trapnr;
888d2fbca94SGuan Xuetao     unsigned int n, insn;
889d2fbca94SGuan Xuetao     target_siginfo_t info;
890d2fbca94SGuan Xuetao 
891d2fbca94SGuan Xuetao     for (;;) {
8920315c31cSAndreas Färber         cpu_exec_start(cs);
8938642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
8940315c31cSAndreas Färber         cpu_exec_end(cs);
895d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
896d148d90eSSergey Fedorov 
897d2fbca94SGuan Xuetao         switch (trapnr) {
898d2fbca94SGuan Xuetao         case UC32_EXCP_PRIV:
899d2fbca94SGuan Xuetao             {
900d2fbca94SGuan Xuetao                 /* system call */
901d2fbca94SGuan Xuetao                 get_user_u32(insn, env->regs[31] - 4);
902d2fbca94SGuan Xuetao                 n = insn & 0xffffff;
903d2fbca94SGuan Xuetao 
904d2fbca94SGuan Xuetao                 if (n >= UC32_SYSCALL_BASE) {
905d2fbca94SGuan Xuetao                     /* linux syscall */
906d2fbca94SGuan Xuetao                     n -= UC32_SYSCALL_BASE;
907d2fbca94SGuan Xuetao                     if (n == UC32_SYSCALL_NR_set_tls) {
908d2fbca94SGuan Xuetao                             cpu_set_tls(env, env->regs[0]);
909d2fbca94SGuan Xuetao                             env->regs[0] = 0;
910d2fbca94SGuan Xuetao                     } else {
911256cb6afSTimothy E Baldwin                         abi_long ret = do_syscall(env,
912d2fbca94SGuan Xuetao                                                   n,
913d2fbca94SGuan Xuetao                                                   env->regs[0],
914d2fbca94SGuan Xuetao                                                   env->regs[1],
915d2fbca94SGuan Xuetao                                                   env->regs[2],
916d2fbca94SGuan Xuetao                                                   env->regs[3],
917d2fbca94SGuan Xuetao                                                   env->regs[4],
9185945cfcbSPeter Maydell                                                   env->regs[5],
9195945cfcbSPeter Maydell                                                   0, 0);
920256cb6afSTimothy E Baldwin                         if (ret == -TARGET_ERESTARTSYS) {
921256cb6afSTimothy E Baldwin                             env->regs[31] -= 4;
922256cb6afSTimothy E Baldwin                         } else if (ret != -TARGET_QEMU_ESIGRETURN) {
923256cb6afSTimothy E Baldwin                             env->regs[0] = ret;
924256cb6afSTimothy E Baldwin                         }
925d2fbca94SGuan Xuetao                     }
926d2fbca94SGuan Xuetao                 } else {
927d2fbca94SGuan Xuetao                     goto error;
928d2fbca94SGuan Xuetao                 }
929d2fbca94SGuan Xuetao             }
930d2fbca94SGuan Xuetao             break;
931d48813ddSGuan Xuetao         case UC32_EXCP_DTRAP:
932d48813ddSGuan Xuetao         case UC32_EXCP_ITRAP:
933a86b3c64SChen Gang S             info.si_signo = TARGET_SIGSEGV;
934d2fbca94SGuan Xuetao             info.si_errno = 0;
935d2fbca94SGuan Xuetao             /* XXX: check env->error_code */
936d2fbca94SGuan Xuetao             info.si_code = TARGET_SEGV_MAPERR;
937d2fbca94SGuan Xuetao             info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
9389d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
939d2fbca94SGuan Xuetao             break;
940d2fbca94SGuan Xuetao         case EXCP_INTERRUPT:
941d2fbca94SGuan Xuetao             /* just indicate that signals should be handled asap */
942d2fbca94SGuan Xuetao             break;
943d2fbca94SGuan Xuetao         case EXCP_DEBUG:
944d2fbca94SGuan Xuetao             {
945d2fbca94SGuan Xuetao                 int sig;
946d2fbca94SGuan Xuetao 
947db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
948d2fbca94SGuan Xuetao                 if (sig) {
949d2fbca94SGuan Xuetao                     info.si_signo = sig;
950d2fbca94SGuan Xuetao                     info.si_errno = 0;
951d2fbca94SGuan Xuetao                     info.si_code = TARGET_TRAP_BRKPT;
9529d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
953d2fbca94SGuan Xuetao                 }
954d2fbca94SGuan Xuetao             }
955d2fbca94SGuan Xuetao             break;
956fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
957fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
958fdbc2b57SRichard Henderson             break;
959d2fbca94SGuan Xuetao         default:
960d2fbca94SGuan Xuetao             goto error;
961d2fbca94SGuan Xuetao         }
962d2fbca94SGuan Xuetao         process_pending_signals(env);
963d2fbca94SGuan Xuetao     }
964d2fbca94SGuan Xuetao 
965d2fbca94SGuan Xuetao error:
966120a9848SPaolo Bonzini     EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
967d2fbca94SGuan Xuetao     abort();
968d2fbca94SGuan Xuetao }
969d2fbca94SGuan Xuetao #endif
970d2fbca94SGuan Xuetao 
97193ac68bcSbellard #ifdef TARGET_SPARC
972ed23fbd9Sblueswir1 #define SPARC64_STACK_BIAS 2047
97393ac68bcSbellard 
974060366c5Sbellard //#define DEBUG_WIN
975060366c5Sbellard 
9762623cbafSbellard /* WARNING: dealing with register windows _is_ complicated. More info
9772623cbafSbellard    can be found at http://www.sics.se/~psm/sparcstack.html */
978060366c5Sbellard static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
979060366c5Sbellard {
9801a14026eSblueswir1     index = (index + cwp * 16) % (16 * env->nwindows);
981060366c5Sbellard     /* wrap handling : if cwp is on the last window, then we use the
982060366c5Sbellard        registers 'after' the end */
9831a14026eSblueswir1     if (index < 8 && env->cwp == env->nwindows - 1)
9841a14026eSblueswir1         index += 16 * env->nwindows;
985060366c5Sbellard     return index;
986060366c5Sbellard }
987060366c5Sbellard 
9882623cbafSbellard /* save the register window 'cwp1' */
9892623cbafSbellard static inline void save_window_offset(CPUSPARCState *env, int cwp1)
990060366c5Sbellard {
9912623cbafSbellard     unsigned int i;
992992f48a0Sblueswir1     abi_ulong sp_ptr;
993060366c5Sbellard 
99453a5960aSpbrook     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
995ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64
996ed23fbd9Sblueswir1     if (sp_ptr & 3)
997ed23fbd9Sblueswir1         sp_ptr += SPARC64_STACK_BIAS;
998ed23fbd9Sblueswir1 #endif
999060366c5Sbellard #if defined(DEBUG_WIN)
10002daf0284Sblueswir1     printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
10012daf0284Sblueswir1            sp_ptr, cwp1);
1002060366c5Sbellard #endif
10032623cbafSbellard     for(i = 0; i < 16; i++) {
10042f619698Sbellard         /* FIXME - what to do if put_user() fails? */
10052f619698Sbellard         put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
1006992f48a0Sblueswir1         sp_ptr += sizeof(abi_ulong);
10072623cbafSbellard     }
1008060366c5Sbellard }
1009060366c5Sbellard 
1010060366c5Sbellard static void save_window(CPUSPARCState *env)
1011060366c5Sbellard {
10125ef54116Sbellard #ifndef TARGET_SPARC64
10132623cbafSbellard     unsigned int new_wim;
10141a14026eSblueswir1     new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
10151a14026eSblueswir1         ((1LL << env->nwindows) - 1);
10161a14026eSblueswir1     save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
10172623cbafSbellard     env->wim = new_wim;
10185ef54116Sbellard #else
10191a14026eSblueswir1     save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
10205ef54116Sbellard     env->cansave++;
10215ef54116Sbellard     env->canrestore--;
10225ef54116Sbellard #endif
1023060366c5Sbellard }
1024060366c5Sbellard 
1025060366c5Sbellard static void restore_window(CPUSPARCState *env)
1026060366c5Sbellard {
1027eda52953Sblueswir1 #ifndef TARGET_SPARC64
1028eda52953Sblueswir1     unsigned int new_wim;
1029eda52953Sblueswir1 #endif
1030eda52953Sblueswir1     unsigned int i, cwp1;
1031992f48a0Sblueswir1     abi_ulong sp_ptr;
1032060366c5Sbellard 
1033eda52953Sblueswir1 #ifndef TARGET_SPARC64
10341a14026eSblueswir1     new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
10351a14026eSblueswir1         ((1LL << env->nwindows) - 1);
1036eda52953Sblueswir1 #endif
1037060366c5Sbellard 
1038060366c5Sbellard     /* restore the invalid window */
10391a14026eSblueswir1     cwp1 = cpu_cwp_inc(env, env->cwp + 1);
104053a5960aSpbrook     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
1041ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64
1042ed23fbd9Sblueswir1     if (sp_ptr & 3)
1043ed23fbd9Sblueswir1         sp_ptr += SPARC64_STACK_BIAS;
1044ed23fbd9Sblueswir1 #endif
1045060366c5Sbellard #if defined(DEBUG_WIN)
10462daf0284Sblueswir1     printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
10472daf0284Sblueswir1            sp_ptr, cwp1);
1048060366c5Sbellard #endif
10492623cbafSbellard     for(i = 0; i < 16; i++) {
10502f619698Sbellard         /* FIXME - what to do if get_user() fails? */
10512f619698Sbellard         get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
1052992f48a0Sblueswir1         sp_ptr += sizeof(abi_ulong);
10532623cbafSbellard     }
10545ef54116Sbellard #ifdef TARGET_SPARC64
10555ef54116Sbellard     env->canrestore++;
10561a14026eSblueswir1     if (env->cleanwin < env->nwindows - 1)
10575ef54116Sbellard         env->cleanwin++;
10585ef54116Sbellard     env->cansave--;
1059eda52953Sblueswir1 #else
1060eda52953Sblueswir1     env->wim = new_wim;
10615ef54116Sbellard #endif
1062060366c5Sbellard }
1063060366c5Sbellard 
1064060366c5Sbellard static void flush_windows(CPUSPARCState *env)
1065060366c5Sbellard {
1066060366c5Sbellard     int offset, cwp1;
10672623cbafSbellard 
10682623cbafSbellard     offset = 1;
1069060366c5Sbellard     for(;;) {
1070060366c5Sbellard         /* if restore would invoke restore_window(), then we can stop */
10711a14026eSblueswir1         cwp1 = cpu_cwp_inc(env, env->cwp + offset);
1072eda52953Sblueswir1 #ifndef TARGET_SPARC64
1073060366c5Sbellard         if (env->wim & (1 << cwp1))
1074060366c5Sbellard             break;
1075eda52953Sblueswir1 #else
1076eda52953Sblueswir1         if (env->canrestore == 0)
1077eda52953Sblueswir1             break;
1078eda52953Sblueswir1         env->cansave++;
1079eda52953Sblueswir1         env->canrestore--;
1080eda52953Sblueswir1 #endif
10812623cbafSbellard         save_window_offset(env, cwp1);
1082060366c5Sbellard         offset++;
1083060366c5Sbellard     }
10841a14026eSblueswir1     cwp1 = cpu_cwp_inc(env, env->cwp + 1);
1085eda52953Sblueswir1 #ifndef TARGET_SPARC64
1086eda52953Sblueswir1     /* set wim so that restore will reload the registers */
10872623cbafSbellard     env->wim = 1 << cwp1;
1088eda52953Sblueswir1 #endif
10892623cbafSbellard #if defined(DEBUG_WIN)
10902623cbafSbellard     printf("flush_windows: nb=%d\n", offset - 1);
109180a9d035Sbellard #endif
10922623cbafSbellard }
1093060366c5Sbellard 
109493ac68bcSbellard void cpu_loop (CPUSPARCState *env)
109593ac68bcSbellard {
1096878096eeSAndreas Färber     CPUState *cs = CPU(sparc_env_get_cpu(env));
10972cc20260SRichard Henderson     int trapnr;
10982cc20260SRichard Henderson     abi_long ret;
1099c227f099SAnthony Liguori     target_siginfo_t info;
110093ac68bcSbellard 
110193ac68bcSbellard     while (1) {
1102b040bc9cSPeter Maydell         cpu_exec_start(cs);
11038642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
1104b040bc9cSPeter Maydell         cpu_exec_end(cs);
1105d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
110693ac68bcSbellard 
110720132b96SRichard Henderson         /* Compute PSR before exposing state.  */
110820132b96SRichard Henderson         if (env->cc_op != CC_OP_FLAGS) {
110920132b96SRichard Henderson             cpu_get_psr(env);
111020132b96SRichard Henderson         }
111120132b96SRichard Henderson 
111293ac68bcSbellard         switch (trapnr) {
11135ef54116Sbellard #ifndef TARGET_SPARC64
1114060366c5Sbellard         case 0x88:
1115060366c5Sbellard         case 0x90:
11165ef54116Sbellard #else
1117cb33da57Sblueswir1         case 0x110:
11185ef54116Sbellard         case 0x16d:
11195ef54116Sbellard #endif
1120060366c5Sbellard             ret = do_syscall (env, env->gregs[1],
1121060366c5Sbellard                               env->regwptr[0], env->regwptr[1],
1122060366c5Sbellard                               env->regwptr[2], env->regwptr[3],
11235945cfcbSPeter Maydell                               env->regwptr[4], env->regwptr[5],
11245945cfcbSPeter Maydell                               0, 0);
1125c0bea68fSTimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) {
1126c0bea68fSTimothy E Baldwin                 break;
1127c0bea68fSTimothy E Baldwin             }
11282cc20260SRichard Henderson             if ((abi_ulong)ret >= (abi_ulong)(-515)) {
1129992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
113027908725Sbellard                 env->xcc |= PSR_CARRY;
113127908725Sbellard #else
113293ac68bcSbellard                 env->psr |= PSR_CARRY;
113327908725Sbellard #endif
1134060366c5Sbellard                 ret = -ret;
1135060366c5Sbellard             } else {
1136992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
113727908725Sbellard                 env->xcc &= ~PSR_CARRY;
113827908725Sbellard #else
1139060366c5Sbellard                 env->psr &= ~PSR_CARRY;
114027908725Sbellard #endif
1141060366c5Sbellard             }
1142060366c5Sbellard             env->regwptr[0] = ret;
1143060366c5Sbellard             /* next instruction */
1144060366c5Sbellard             env->pc = env->npc;
1145060366c5Sbellard             env->npc = env->npc + 4;
1146060366c5Sbellard             break;
1147060366c5Sbellard         case 0x83: /* flush windows */
1148992f48a0Sblueswir1 #ifdef TARGET_ABI32
1149992f48a0Sblueswir1         case 0x103:
1150992f48a0Sblueswir1 #endif
11512623cbafSbellard             flush_windows(env);
1152060366c5Sbellard             /* next instruction */
1153060366c5Sbellard             env->pc = env->npc;
1154060366c5Sbellard             env->npc = env->npc + 4;
1155060366c5Sbellard             break;
11563475187dSbellard #ifndef TARGET_SPARC64
1157060366c5Sbellard         case TT_WIN_OVF: /* window overflow */
1158060366c5Sbellard             save_window(env);
1159060366c5Sbellard             break;
1160060366c5Sbellard         case TT_WIN_UNF: /* window underflow */
1161060366c5Sbellard             restore_window(env);
116293ac68bcSbellard             break;
116361ff6f58Sbellard         case TT_TFAULT:
116461ff6f58Sbellard         case TT_DFAULT:
116561ff6f58Sbellard             {
116659f7182fSRichard Henderson                 info.si_signo = TARGET_SIGSEGV;
116761ff6f58Sbellard                 info.si_errno = 0;
116861ff6f58Sbellard                 /* XXX: check env->error_code */
116961ff6f58Sbellard                 info.si_code = TARGET_SEGV_MAPERR;
117061ff6f58Sbellard                 info._sifields._sigfault._addr = env->mmuregs[4];
11719d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
117261ff6f58Sbellard             }
117361ff6f58Sbellard             break;
11743475187dSbellard #else
11755ef54116Sbellard         case TT_SPILL: /* window overflow */
11765ef54116Sbellard             save_window(env);
11775ef54116Sbellard             break;
11785ef54116Sbellard         case TT_FILL: /* window underflow */
11795ef54116Sbellard             restore_window(env);
11805ef54116Sbellard             break;
11817f84a729Sblueswir1         case TT_TFAULT:
11827f84a729Sblueswir1         case TT_DFAULT:
11837f84a729Sblueswir1             {
118459f7182fSRichard Henderson                 info.si_signo = TARGET_SIGSEGV;
11857f84a729Sblueswir1                 info.si_errno = 0;
11867f84a729Sblueswir1                 /* XXX: check env->error_code */
11877f84a729Sblueswir1                 info.si_code = TARGET_SEGV_MAPERR;
11887f84a729Sblueswir1                 if (trapnr == TT_DFAULT)
118996df2bc9SArtyom Tarasenko                     info._sifields._sigfault._addr = env->dmmu.mmuregs[4];
11907f84a729Sblueswir1                 else
11918194f35aSIgor Kovalenko                     info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
11929d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
11937f84a729Sblueswir1             }
11947f84a729Sblueswir1             break;
119527524dc3Sbellard #ifndef TARGET_ABI32
11965bfb56b2Sblueswir1         case 0x16e:
11975bfb56b2Sblueswir1             flush_windows(env);
11985bfb56b2Sblueswir1             sparc64_get_context(env);
11995bfb56b2Sblueswir1             break;
12005bfb56b2Sblueswir1         case 0x16f:
12015bfb56b2Sblueswir1             flush_windows(env);
12025bfb56b2Sblueswir1             sparc64_set_context(env);
12035bfb56b2Sblueswir1             break;
12043475187dSbellard #endif
120527524dc3Sbellard #endif
120648dc41ebSbellard         case EXCP_INTERRUPT:
120748dc41ebSbellard             /* just indicate that signals should be handled asap */
1208e80cfcfcSbellard             break;
120975f22e4eSRichard Henderson         case TT_ILL_INSN:
121075f22e4eSRichard Henderson             {
121175f22e4eSRichard Henderson                 info.si_signo = TARGET_SIGILL;
121275f22e4eSRichard Henderson                 info.si_errno = 0;
121375f22e4eSRichard Henderson                 info.si_code = TARGET_ILL_ILLOPC;
121475f22e4eSRichard Henderson                 info._sifields._sigfault._addr = env->pc;
12159d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
121675f22e4eSRichard Henderson             }
121775f22e4eSRichard Henderson             break;
12181fddef4bSbellard         case EXCP_DEBUG:
12191fddef4bSbellard             {
12201fddef4bSbellard                 int sig;
12211fddef4bSbellard 
1222db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
12231fddef4bSbellard                 if (sig)
12241fddef4bSbellard                   {
12251fddef4bSbellard                     info.si_signo = sig;
12261fddef4bSbellard                     info.si_errno = 0;
12271fddef4bSbellard                     info.si_code = TARGET_TRAP_BRKPT;
12289d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
12291fddef4bSbellard                   }
12301fddef4bSbellard             }
12311fddef4bSbellard             break;
1232fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
1233fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
1234fdbc2b57SRichard Henderson             break;
123593ac68bcSbellard         default:
1236060366c5Sbellard             printf ("Unhandled trap: 0x%x\n", trapnr);
1237878096eeSAndreas Färber             cpu_dump_state(cs, stderr, fprintf, 0);
12384d1275c2SRiku Voipio             exit(EXIT_FAILURE);
123993ac68bcSbellard         }
124093ac68bcSbellard         process_pending_signals (env);
124193ac68bcSbellard     }
124293ac68bcSbellard }
124393ac68bcSbellard 
124493ac68bcSbellard #endif
124593ac68bcSbellard 
124667867308Sbellard #ifdef TARGET_PPC
124705390248SAndreas Färber static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
12489fddaa0cSbellard {
12494a7428c5SChristopher Covington     return cpu_get_host_ticks();
12509fddaa0cSbellard }
12519fddaa0cSbellard 
125205390248SAndreas Färber uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
12539fddaa0cSbellard {
1254e3ea6529SAlexander Graf     return cpu_ppc_get_tb(env);
12559fddaa0cSbellard }
12569fddaa0cSbellard 
125705390248SAndreas Färber uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
12589fddaa0cSbellard {
12599fddaa0cSbellard     return cpu_ppc_get_tb(env) >> 32;
12609fddaa0cSbellard }
12619fddaa0cSbellard 
126205390248SAndreas Färber uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
12639fddaa0cSbellard {
1264b711de95SAurelien Jarno     return cpu_ppc_get_tb(env);
12659fddaa0cSbellard }
12669fddaa0cSbellard 
126705390248SAndreas Färber uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
12689fddaa0cSbellard {
1269a062e36cSj_mayer     return cpu_ppc_get_tb(env) >> 32;
12709fddaa0cSbellard }
12719fddaa0cSbellard 
127205390248SAndreas Färber uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
127376a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_load_tbu") ));
127476a66253Sj_mayer 
127505390248SAndreas Färber uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
12769fddaa0cSbellard {
127776a66253Sj_mayer     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
12789fddaa0cSbellard }
12799fddaa0cSbellard 
1280a750fc0bSj_mayer /* XXX: to be fixed */
128173b01960SAlexander Graf int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
1282a750fc0bSj_mayer {
1283a750fc0bSj_mayer     return -1;
1284a750fc0bSj_mayer }
1285a750fc0bSj_mayer 
128673b01960SAlexander Graf int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
1287a750fc0bSj_mayer {
1288a750fc0bSj_mayer     return -1;
1289a750fc0bSj_mayer }
1290a750fc0bSj_mayer 
129156f066bbSNathan Froyd static int do_store_exclusive(CPUPPCState *env)
129256f066bbSNathan Froyd {
129356f066bbSNathan Froyd     target_ulong addr;
129456f066bbSNathan Froyd     target_ulong page_addr;
1295e22c357bSDoug Kwan     target_ulong val, val2 __attribute__((unused)) = 0;
129656f066bbSNathan Froyd     int flags;
129756f066bbSNathan Froyd     int segv = 0;
129856f066bbSNathan Froyd 
129956f066bbSNathan Froyd     addr = env->reserve_ea;
130056f066bbSNathan Froyd     page_addr = addr & TARGET_PAGE_MASK;
130156f066bbSNathan Froyd     start_exclusive();
130256f066bbSNathan Froyd     mmap_lock();
130356f066bbSNathan Froyd     flags = page_get_flags(page_addr);
130456f066bbSNathan Froyd     if ((flags & PAGE_READ) == 0) {
130556f066bbSNathan Froyd         segv = 1;
130656f066bbSNathan Froyd     } else {
130756f066bbSNathan Froyd         int reg = env->reserve_info & 0x1f;
13084b1daa72STom Musta         int size = env->reserve_info >> 5;
130956f066bbSNathan Froyd         int stored = 0;
131056f066bbSNathan Froyd 
131156f066bbSNathan Froyd         if (addr == env->reserve_addr) {
131256f066bbSNathan Froyd             switch (size) {
131356f066bbSNathan Froyd             case 1: segv = get_user_u8(val, addr); break;
131456f066bbSNathan Froyd             case 2: segv = get_user_u16(val, addr); break;
131556f066bbSNathan Froyd             case 4: segv = get_user_u32(val, addr); break;
131656f066bbSNathan Froyd #if defined(TARGET_PPC64)
131756f066bbSNathan Froyd             case 8: segv = get_user_u64(val, addr); break;
131827b95bfeSTom Musta             case 16: {
131927b95bfeSTom Musta                 segv = get_user_u64(val, addr);
132027b95bfeSTom Musta                 if (!segv) {
132127b95bfeSTom Musta                     segv = get_user_u64(val2, addr + 8);
132227b95bfeSTom Musta                 }
132327b95bfeSTom Musta                 break;
132427b95bfeSTom Musta             }
132556f066bbSNathan Froyd #endif
132656f066bbSNathan Froyd             default: abort();
132756f066bbSNathan Froyd             }
132856f066bbSNathan Froyd             if (!segv && val == env->reserve_val) {
132956f066bbSNathan Froyd                 val = env->gpr[reg];
133056f066bbSNathan Froyd                 switch (size) {
133156f066bbSNathan Froyd                 case 1: segv = put_user_u8(val, addr); break;
133256f066bbSNathan Froyd                 case 2: segv = put_user_u16(val, addr); break;
133356f066bbSNathan Froyd                 case 4: segv = put_user_u32(val, addr); break;
133456f066bbSNathan Froyd #if defined(TARGET_PPC64)
133556f066bbSNathan Froyd                 case 8: segv = put_user_u64(val, addr); break;
133627b95bfeSTom Musta                 case 16: {
133727b95bfeSTom Musta                     if (val2 == env->reserve_val2) {
1338e22c357bSDoug Kwan                         if (msr_le) {
1339e22c357bSDoug Kwan                             val2 = val;
1340e22c357bSDoug Kwan                             val = env->gpr[reg+1];
1341e22c357bSDoug Kwan                         } else {
1342e22c357bSDoug Kwan                             val2 = env->gpr[reg+1];
1343e22c357bSDoug Kwan                         }
134427b95bfeSTom Musta                         segv = put_user_u64(val, addr);
134527b95bfeSTom Musta                         if (!segv) {
134627b95bfeSTom Musta                             segv = put_user_u64(val2, addr + 8);
134727b95bfeSTom Musta                         }
134827b95bfeSTom Musta                     }
134927b95bfeSTom Musta                     break;
135027b95bfeSTom Musta                 }
135156f066bbSNathan Froyd #endif
135256f066bbSNathan Froyd                 default: abort();
135356f066bbSNathan Froyd                 }
135456f066bbSNathan Froyd                 if (!segv) {
135556f066bbSNathan Froyd                     stored = 1;
135656f066bbSNathan Froyd                 }
135756f066bbSNathan Froyd             }
135856f066bbSNathan Froyd         }
135956f066bbSNathan Froyd         env->crf[0] = (stored << 1) | xer_so;
136056f066bbSNathan Froyd         env->reserve_addr = (target_ulong)-1;
136156f066bbSNathan Froyd     }
136256f066bbSNathan Froyd     if (!segv) {
136356f066bbSNathan Froyd         env->nip += 4;
136456f066bbSNathan Froyd     }
136556f066bbSNathan Froyd     mmap_unlock();
136656f066bbSNathan Froyd     end_exclusive();
136756f066bbSNathan Froyd     return segv;
136856f066bbSNathan Froyd }
136956f066bbSNathan Froyd 
137067867308Sbellard void cpu_loop(CPUPPCState *env)
137167867308Sbellard {
13720315c31cSAndreas Färber     CPUState *cs = CPU(ppc_env_get_cpu(env));
1373c227f099SAnthony Liguori     target_siginfo_t info;
137461190b14Sbellard     int trapnr;
13759e0e2f96SRichard Henderson     target_ulong ret;
137667867308Sbellard 
137767867308Sbellard     for(;;) {
13780315c31cSAndreas Färber         cpu_exec_start(cs);
13798642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
13800315c31cSAndreas Färber         cpu_exec_end(cs);
1381d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
1382d148d90eSSergey Fedorov 
138367867308Sbellard         switch(trapnr) {
1384e1833e1fSj_mayer         case POWERPC_EXCP_NONE:
1385e1833e1fSj_mayer             /* Just go on */
138667867308Sbellard             break;
1387e1833e1fSj_mayer         case POWERPC_EXCP_CRITICAL: /* Critical input                        */
1388a47dddd7SAndreas Färber             cpu_abort(cs, "Critical interrupt while in user mode. "
1389e1833e1fSj_mayer                       "Aborting\n");
1390e1833e1fSj_mayer             break;
1391e1833e1fSj_mayer         case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
1392a47dddd7SAndreas Färber             cpu_abort(cs, "Machine check exception while in user mode. "
1393e1833e1fSj_mayer                       "Aborting\n");
1394e1833e1fSj_mayer             break;
1395e1833e1fSj_mayer         case POWERPC_EXCP_DSI:      /* Data storage exception                */
1396e1833e1fSj_mayer             /* XXX: check this. Seems bugged */
1397e1833e1fSj_mayer             switch (env->error_code & 0xFF000000) {
1398e1833e1fSj_mayer             case 0x40000000:
1399ba4a8df8SBenjamin Herrenschmidt             case 0x42000000:
1400e1833e1fSj_mayer                 info.si_signo = TARGET_SIGSEGV;
1401e1833e1fSj_mayer                 info.si_errno = 0;
1402e1833e1fSj_mayer                 info.si_code = TARGET_SEGV_MAPERR;
1403e1833e1fSj_mayer                 break;
1404e1833e1fSj_mayer             case 0x04000000:
1405e1833e1fSj_mayer                 info.si_signo = TARGET_SIGILL;
1406e1833e1fSj_mayer                 info.si_errno = 0;
1407e1833e1fSj_mayer                 info.si_code = TARGET_ILL_ILLADR;
1408e1833e1fSj_mayer                 break;
1409e1833e1fSj_mayer             case 0x08000000:
1410e1833e1fSj_mayer                 info.si_signo = TARGET_SIGSEGV;
1411e1833e1fSj_mayer                 info.si_errno = 0;
1412e1833e1fSj_mayer                 info.si_code = TARGET_SEGV_ACCERR;
1413e1833e1fSj_mayer                 break;
1414e1833e1fSj_mayer             default:
1415e1833e1fSj_mayer                 /* Let's send a regular segfault... */
1416e1833e1fSj_mayer                 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1417e1833e1fSj_mayer                           env->error_code);
1418e1833e1fSj_mayer                 info.si_signo = TARGET_SIGSEGV;
1419e1833e1fSj_mayer                 info.si_errno = 0;
1420e1833e1fSj_mayer                 info.si_code = TARGET_SEGV_MAPERR;
1421e1833e1fSj_mayer                 break;
1422e1833e1fSj_mayer             }
1423e1833e1fSj_mayer             info._sifields._sigfault._addr = env->nip;
14249d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1425e1833e1fSj_mayer             break;
1426e1833e1fSj_mayer         case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
1427e1833e1fSj_mayer             /* XXX: check this */
1428e1833e1fSj_mayer             switch (env->error_code & 0xFF000000) {
1429e1833e1fSj_mayer             case 0x40000000:
1430e1833e1fSj_mayer                 info.si_signo = TARGET_SIGSEGV;
1431e1833e1fSj_mayer             info.si_errno = 0;
1432e1833e1fSj_mayer                 info.si_code = TARGET_SEGV_MAPERR;
1433e1833e1fSj_mayer                 break;
1434e1833e1fSj_mayer             case 0x10000000:
1435e1833e1fSj_mayer             case 0x08000000:
1436e1833e1fSj_mayer                 info.si_signo = TARGET_SIGSEGV;
1437e1833e1fSj_mayer                 info.si_errno = 0;
1438e1833e1fSj_mayer                 info.si_code = TARGET_SEGV_ACCERR;
1439e1833e1fSj_mayer                 break;
1440e1833e1fSj_mayer             default:
1441e1833e1fSj_mayer                 /* Let's send a regular segfault... */
1442e1833e1fSj_mayer                 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1443e1833e1fSj_mayer                           env->error_code);
1444e1833e1fSj_mayer                 info.si_signo = TARGET_SIGSEGV;
1445e1833e1fSj_mayer                 info.si_errno = 0;
1446e1833e1fSj_mayer                 info.si_code = TARGET_SEGV_MAPERR;
1447e1833e1fSj_mayer                 break;
1448e1833e1fSj_mayer             }
1449e1833e1fSj_mayer             info._sifields._sigfault._addr = env->nip - 4;
14509d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1451e1833e1fSj_mayer             break;
1452e1833e1fSj_mayer         case POWERPC_EXCP_EXTERNAL: /* External input                        */
1453a47dddd7SAndreas Färber             cpu_abort(cs, "External interrupt while in user mode. "
1454e1833e1fSj_mayer                       "Aborting\n");
1455e1833e1fSj_mayer             break;
1456e1833e1fSj_mayer         case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
1457e1833e1fSj_mayer             /* XXX: check this */
1458e1833e1fSj_mayer             info.si_signo = TARGET_SIGBUS;
1459e1833e1fSj_mayer             info.si_errno = 0;
1460e1833e1fSj_mayer             info.si_code = TARGET_BUS_ADRALN;
14616bb9a0a9SAnton Blanchard             info._sifields._sigfault._addr = env->nip;
14629d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1463e1833e1fSj_mayer             break;
1464e1833e1fSj_mayer         case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
14659b2faddaSBenjamin Herrenschmidt         case POWERPC_EXCP_HV_EMU:   /* HV emulation                          */
1466e1833e1fSj_mayer             /* XXX: check this */
1467e1833e1fSj_mayer             switch (env->error_code & ~0xF) {
1468e1833e1fSj_mayer             case POWERPC_EXCP_FP:
1469e1833e1fSj_mayer                 info.si_signo = TARGET_SIGFPE;
1470e1833e1fSj_mayer                 info.si_errno = 0;
1471e1833e1fSj_mayer                 switch (env->error_code & 0xF) {
1472e1833e1fSj_mayer                 case POWERPC_EXCP_FP_OX:
1473e1833e1fSj_mayer                     info.si_code = TARGET_FPE_FLTOVF;
1474e1833e1fSj_mayer                     break;
1475e1833e1fSj_mayer                 case POWERPC_EXCP_FP_UX:
1476e1833e1fSj_mayer                     info.si_code = TARGET_FPE_FLTUND;
1477e1833e1fSj_mayer                     break;
1478e1833e1fSj_mayer                 case POWERPC_EXCP_FP_ZX:
1479e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXZDZ:
1480e1833e1fSj_mayer                     info.si_code = TARGET_FPE_FLTDIV;
1481e1833e1fSj_mayer                     break;
1482e1833e1fSj_mayer                 case POWERPC_EXCP_FP_XX:
1483e1833e1fSj_mayer                     info.si_code = TARGET_FPE_FLTRES;
1484e1833e1fSj_mayer                     break;
1485e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXSOFT:
1486e1833e1fSj_mayer                     info.si_code = TARGET_FPE_FLTINV;
1487e1833e1fSj_mayer                     break;
14887c58044cSj_mayer                 case POWERPC_EXCP_FP_VXSNAN:
1489e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXISI:
1490e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXIDI:
1491e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXIMZ:
1492e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXVC:
1493e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXSQRT:
1494e1833e1fSj_mayer                 case POWERPC_EXCP_FP_VXCVI:
1495e1833e1fSj_mayer                     info.si_code = TARGET_FPE_FLTSUB;
1496e1833e1fSj_mayer                     break;
1497e1833e1fSj_mayer                 default:
1498e1833e1fSj_mayer                     EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
1499e1833e1fSj_mayer                               env->error_code);
1500e1833e1fSj_mayer                     break;
1501e1833e1fSj_mayer                 }
1502e1833e1fSj_mayer                 break;
1503e1833e1fSj_mayer             case POWERPC_EXCP_INVAL:
1504e1833e1fSj_mayer                 info.si_signo = TARGET_SIGILL;
1505e1833e1fSj_mayer                 info.si_errno = 0;
1506e1833e1fSj_mayer                 switch (env->error_code & 0xF) {
1507e1833e1fSj_mayer                 case POWERPC_EXCP_INVAL_INVAL:
1508e1833e1fSj_mayer                     info.si_code = TARGET_ILL_ILLOPC;
1509e1833e1fSj_mayer                     break;
1510e1833e1fSj_mayer                 case POWERPC_EXCP_INVAL_LSWX:
1511e1833e1fSj_mayer                     info.si_code = TARGET_ILL_ILLOPN;
1512e1833e1fSj_mayer                     break;
1513e1833e1fSj_mayer                 case POWERPC_EXCP_INVAL_SPR:
1514e1833e1fSj_mayer                     info.si_code = TARGET_ILL_PRVREG;
1515e1833e1fSj_mayer                     break;
1516e1833e1fSj_mayer                 case POWERPC_EXCP_INVAL_FP:
1517e1833e1fSj_mayer                     info.si_code = TARGET_ILL_COPROC;
1518e1833e1fSj_mayer                     break;
1519e1833e1fSj_mayer                 default:
1520e1833e1fSj_mayer                     EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
1521e1833e1fSj_mayer                               env->error_code & 0xF);
1522e1833e1fSj_mayer                     info.si_code = TARGET_ILL_ILLADR;
1523e1833e1fSj_mayer                     break;
1524e1833e1fSj_mayer                 }
1525e1833e1fSj_mayer                 break;
1526e1833e1fSj_mayer             case POWERPC_EXCP_PRIV:
1527e1833e1fSj_mayer                 info.si_signo = TARGET_SIGILL;
1528e1833e1fSj_mayer                 info.si_errno = 0;
1529e1833e1fSj_mayer                 switch (env->error_code & 0xF) {
1530e1833e1fSj_mayer                 case POWERPC_EXCP_PRIV_OPC:
1531e1833e1fSj_mayer                     info.si_code = TARGET_ILL_PRVOPC;
1532e1833e1fSj_mayer                     break;
1533e1833e1fSj_mayer                 case POWERPC_EXCP_PRIV_REG:
1534e1833e1fSj_mayer                     info.si_code = TARGET_ILL_PRVREG;
1535e1833e1fSj_mayer                     break;
1536e1833e1fSj_mayer                 default:
1537e1833e1fSj_mayer                     EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
1538e1833e1fSj_mayer                               env->error_code & 0xF);
1539e1833e1fSj_mayer                     info.si_code = TARGET_ILL_PRVOPC;
1540e1833e1fSj_mayer                     break;
1541e1833e1fSj_mayer                 }
1542e1833e1fSj_mayer                 break;
1543e1833e1fSj_mayer             case POWERPC_EXCP_TRAP:
1544a47dddd7SAndreas Färber                 cpu_abort(cs, "Tried to call a TRAP\n");
1545e1833e1fSj_mayer                 break;
1546e1833e1fSj_mayer             default:
1547e1833e1fSj_mayer                 /* Should not happen ! */
1548a47dddd7SAndreas Färber                 cpu_abort(cs, "Unknown program exception (%02x)\n",
1549e1833e1fSj_mayer                           env->error_code);
1550e1833e1fSj_mayer                 break;
1551e1833e1fSj_mayer             }
1552bd6fefe7SBenjamin Herrenschmidt             info._sifields._sigfault._addr = env->nip;
15539d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1554e1833e1fSj_mayer             break;
1555e1833e1fSj_mayer         case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
1556e1833e1fSj_mayer             info.si_signo = TARGET_SIGILL;
1557e1833e1fSj_mayer             info.si_errno = 0;
1558e1833e1fSj_mayer             info.si_code = TARGET_ILL_COPROC;
1559bd6fefe7SBenjamin Herrenschmidt             info._sifields._sigfault._addr = env->nip;
15609d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1561e1833e1fSj_mayer             break;
1562e1833e1fSj_mayer         case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
1563a47dddd7SAndreas Färber             cpu_abort(cs, "Syscall exception while in user mode. "
1564e1833e1fSj_mayer                       "Aborting\n");
1565e1833e1fSj_mayer             break;
1566e1833e1fSj_mayer         case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
1567e1833e1fSj_mayer             info.si_signo = TARGET_SIGILL;
1568e1833e1fSj_mayer             info.si_errno = 0;
1569e1833e1fSj_mayer             info.si_code = TARGET_ILL_COPROC;
1570bd6fefe7SBenjamin Herrenschmidt             info._sifields._sigfault._addr = env->nip;
15719d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1572e1833e1fSj_mayer             break;
1573e1833e1fSj_mayer         case POWERPC_EXCP_DECR:     /* Decrementer exception                 */
1574a47dddd7SAndreas Färber             cpu_abort(cs, "Decrementer interrupt while in user mode. "
1575e1833e1fSj_mayer                       "Aborting\n");
1576e1833e1fSj_mayer             break;
1577e1833e1fSj_mayer         case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
1578a47dddd7SAndreas Färber             cpu_abort(cs, "Fix interval timer interrupt while in user mode. "
1579e1833e1fSj_mayer                       "Aborting\n");
1580e1833e1fSj_mayer             break;
1581e1833e1fSj_mayer         case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
1582a47dddd7SAndreas Färber             cpu_abort(cs, "Watchdog timer interrupt while in user mode. "
1583e1833e1fSj_mayer                       "Aborting\n");
1584e1833e1fSj_mayer             break;
1585e1833e1fSj_mayer         case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
1586a47dddd7SAndreas Färber             cpu_abort(cs, "Data TLB exception while in user mode. "
1587e1833e1fSj_mayer                       "Aborting\n");
1588e1833e1fSj_mayer             break;
1589e1833e1fSj_mayer         case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
1590a47dddd7SAndreas Färber             cpu_abort(cs, "Instruction TLB exception while in user mode. "
1591e1833e1fSj_mayer                       "Aborting\n");
1592e1833e1fSj_mayer             break;
1593e1833e1fSj_mayer         case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
1594e1833e1fSj_mayer             info.si_signo = TARGET_SIGILL;
1595e1833e1fSj_mayer             info.si_errno = 0;
1596e1833e1fSj_mayer             info.si_code = TARGET_ILL_COPROC;
1597bd6fefe7SBenjamin Herrenschmidt             info._sifields._sigfault._addr = env->nip;
15989d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1599e1833e1fSj_mayer             break;
1600e1833e1fSj_mayer         case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
1601a47dddd7SAndreas Färber             cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
1602e1833e1fSj_mayer             break;
1603e1833e1fSj_mayer         case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
1604a47dddd7SAndreas Färber             cpu_abort(cs, "Embedded floating-point round IRQ not handled\n");
1605e1833e1fSj_mayer             break;
1606e1833e1fSj_mayer         case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
1607a47dddd7SAndreas Färber             cpu_abort(cs, "Performance monitor exception not handled\n");
1608e1833e1fSj_mayer             break;
1609e1833e1fSj_mayer         case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
1610a47dddd7SAndreas Färber             cpu_abort(cs, "Doorbell interrupt while in user mode. "
1611e1833e1fSj_mayer                        "Aborting\n");
1612e1833e1fSj_mayer             break;
1613e1833e1fSj_mayer         case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
1614a47dddd7SAndreas Färber             cpu_abort(cs, "Doorbell critical interrupt while in user mode. "
1615e1833e1fSj_mayer                       "Aborting\n");
1616e1833e1fSj_mayer             break;
1617e1833e1fSj_mayer         case POWERPC_EXCP_RESET:    /* System reset exception                */
1618a47dddd7SAndreas Färber             cpu_abort(cs, "Reset interrupt while in user mode. "
1619e1833e1fSj_mayer                       "Aborting\n");
1620e1833e1fSj_mayer             break;
1621e1833e1fSj_mayer         case POWERPC_EXCP_DSEG:     /* Data segment exception                */
1622a47dddd7SAndreas Färber             cpu_abort(cs, "Data segment exception while in user mode. "
1623e1833e1fSj_mayer                       "Aborting\n");
1624e1833e1fSj_mayer             break;
1625e1833e1fSj_mayer         case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
1626a47dddd7SAndreas Färber             cpu_abort(cs, "Instruction segment exception "
1627e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1628e1833e1fSj_mayer             break;
1629e85e7c6eSj_mayer         /* PowerPC 64 with hypervisor mode support */
1630e1833e1fSj_mayer         case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
1631a47dddd7SAndreas Färber             cpu_abort(cs, "Hypervisor decrementer interrupt "
1632e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1633e1833e1fSj_mayer             break;
1634e1833e1fSj_mayer         case POWERPC_EXCP_TRACE:    /* Trace exception                       */
1635e1833e1fSj_mayer             /* Nothing to do:
1636e1833e1fSj_mayer              * we use this exception to emulate step-by-step execution mode.
1637e1833e1fSj_mayer              */
1638e1833e1fSj_mayer             break;
1639e85e7c6eSj_mayer         /* PowerPC 64 with hypervisor mode support */
1640e1833e1fSj_mayer         case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
1641a47dddd7SAndreas Färber             cpu_abort(cs, "Hypervisor data storage exception "
1642e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1643e1833e1fSj_mayer             break;
1644e1833e1fSj_mayer         case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
1645a47dddd7SAndreas Färber             cpu_abort(cs, "Hypervisor instruction storage exception "
1646e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1647e1833e1fSj_mayer             break;
1648e1833e1fSj_mayer         case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
1649a47dddd7SAndreas Färber             cpu_abort(cs, "Hypervisor data segment exception "
1650e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1651e1833e1fSj_mayer             break;
1652e1833e1fSj_mayer         case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
1653a47dddd7SAndreas Färber             cpu_abort(cs, "Hypervisor instruction segment exception "
1654e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1655e1833e1fSj_mayer             break;
1656e1833e1fSj_mayer         case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
1657e1833e1fSj_mayer             info.si_signo = TARGET_SIGILL;
1658e1833e1fSj_mayer             info.si_errno = 0;
1659e1833e1fSj_mayer             info.si_code = TARGET_ILL_COPROC;
1660bd6fefe7SBenjamin Herrenschmidt             info._sifields._sigfault._addr = env->nip;
16619d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
1662e1833e1fSj_mayer             break;
1663e1833e1fSj_mayer         case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
1664a47dddd7SAndreas Färber             cpu_abort(cs, "Programmable interval timer interrupt "
1665e1833e1fSj_mayer                       "while in user mode. Aborting\n");
1666e1833e1fSj_mayer             break;
1667e1833e1fSj_mayer         case POWERPC_EXCP_IO:       /* IO error exception                    */
1668a47dddd7SAndreas Färber             cpu_abort(cs, "IO error exception while in user mode. "
1669e1833e1fSj_mayer                       "Aborting\n");
1670e1833e1fSj_mayer             break;
1671e1833e1fSj_mayer         case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
1672a47dddd7SAndreas Färber             cpu_abort(cs, "Run mode exception while in user mode. "
1673e1833e1fSj_mayer                       "Aborting\n");
1674e1833e1fSj_mayer             break;
1675e1833e1fSj_mayer         case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
1676a47dddd7SAndreas Färber             cpu_abort(cs, "Emulation trap exception not handled\n");
1677e1833e1fSj_mayer             break;
1678e1833e1fSj_mayer         case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
1679a47dddd7SAndreas Färber             cpu_abort(cs, "Instruction fetch TLB exception "
1680e1833e1fSj_mayer                       "while in user-mode. Aborting");
1681e1833e1fSj_mayer             break;
1682e1833e1fSj_mayer         case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
1683a47dddd7SAndreas Färber             cpu_abort(cs, "Data load TLB exception while in user-mode. "
1684e1833e1fSj_mayer                       "Aborting");
1685e1833e1fSj_mayer             break;
1686e1833e1fSj_mayer         case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
1687a47dddd7SAndreas Färber             cpu_abort(cs, "Data store TLB exception while in user-mode. "
1688e1833e1fSj_mayer                       "Aborting");
1689e1833e1fSj_mayer             break;
1690e1833e1fSj_mayer         case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
1691a47dddd7SAndreas Färber             cpu_abort(cs, "Floating-point assist exception not handled\n");
1692e1833e1fSj_mayer             break;
1693e1833e1fSj_mayer         case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
1694a47dddd7SAndreas Färber             cpu_abort(cs, "Instruction address breakpoint exception "
1695e1833e1fSj_mayer                       "not handled\n");
1696e1833e1fSj_mayer             break;
1697e1833e1fSj_mayer         case POWERPC_EXCP_SMI:      /* System management interrupt           */
1698a47dddd7SAndreas Färber             cpu_abort(cs, "System management interrupt while in user mode. "
1699e1833e1fSj_mayer                       "Aborting\n");
1700e1833e1fSj_mayer             break;
1701e1833e1fSj_mayer         case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
1702a47dddd7SAndreas Färber             cpu_abort(cs, "Thermal interrupt interrupt while in user mode. "
1703e1833e1fSj_mayer                       "Aborting\n");
1704e1833e1fSj_mayer             break;
1705e1833e1fSj_mayer         case POWERPC_EXCP_PERFM:   /* Embedded performance monitor IRQ      */
1706a47dddd7SAndreas Färber             cpu_abort(cs, "Performance monitor exception not handled\n");
1707e1833e1fSj_mayer             break;
1708e1833e1fSj_mayer         case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
1709a47dddd7SAndreas Färber             cpu_abort(cs, "Vector assist exception not handled\n");
1710e1833e1fSj_mayer             break;
1711e1833e1fSj_mayer         case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
1712a47dddd7SAndreas Färber             cpu_abort(cs, "Soft patch exception not handled\n");
1713e1833e1fSj_mayer             break;
1714e1833e1fSj_mayer         case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
1715a47dddd7SAndreas Färber             cpu_abort(cs, "Maintenance exception while in user mode. "
1716e1833e1fSj_mayer                       "Aborting\n");
1717e1833e1fSj_mayer             break;
1718e1833e1fSj_mayer         case POWERPC_EXCP_STOP:     /* stop translation                      */
1719e1833e1fSj_mayer             /* We did invalidate the instruction cache. Go on */
1720e1833e1fSj_mayer             break;
1721e1833e1fSj_mayer         case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */
1722e1833e1fSj_mayer             /* We just stopped because of a branch. Go on */
1723e1833e1fSj_mayer             break;
1724e1833e1fSj_mayer         case POWERPC_EXCP_SYSCALL_USER:
1725e1833e1fSj_mayer             /* system call in user-mode emulation */
172667867308Sbellard             /* WARNING:
172767867308Sbellard              * PPC ABI uses overflow flag in cr0 to signal an error
172867867308Sbellard              * in syscalls.
172967867308Sbellard              */
173067867308Sbellard             env->crf[0] &= ~0x1;
17312635531fSSam Bobroff             env->nip += 4;
173267867308Sbellard             ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
173367867308Sbellard                              env->gpr[5], env->gpr[6], env->gpr[7],
17345945cfcbSPeter Maydell                              env->gpr[8], 0, 0);
17356db9d00eSTimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
17362635531fSSam Bobroff                 env->nip -= 4;
17376db9d00eSTimothy E Baldwin                 break;
17386db9d00eSTimothy E Baldwin             }
17399e0e2f96SRichard Henderson             if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
1740bcd4933aSNathan Froyd                 /* Returning from a successful sigreturn syscall.
1741bcd4933aSNathan Froyd                    Avoid corrupting register state.  */
1742bcd4933aSNathan Froyd                 break;
1743bcd4933aSNathan Froyd             }
17449e0e2f96SRichard Henderson             if (ret > (target_ulong)(-515)) {
174567867308Sbellard                 env->crf[0] |= 0x1;
174667867308Sbellard                 ret = -ret;
174767867308Sbellard             }
174867867308Sbellard             env->gpr[3] = ret;
174961190b14Sbellard             break;
175056f066bbSNathan Froyd         case POWERPC_EXCP_STCX:
175156f066bbSNathan Froyd             if (do_store_exclusive(env)) {
175256f066bbSNathan Froyd                 info.si_signo = TARGET_SIGSEGV;
175356f066bbSNathan Froyd                 info.si_errno = 0;
175456f066bbSNathan Froyd                 info.si_code = TARGET_SEGV_MAPERR;
175556f066bbSNathan Froyd                 info._sifields._sigfault._addr = env->nip;
17569d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
175756f066bbSNathan Froyd             }
175856f066bbSNathan Froyd             break;
175971f75756Saurel32         case EXCP_DEBUG:
176071f75756Saurel32             {
176171f75756Saurel32                 int sig;
176271f75756Saurel32 
1763db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
176471f75756Saurel32                 if (sig) {
176571f75756Saurel32                     info.si_signo = sig;
176671f75756Saurel32                     info.si_errno = 0;
176771f75756Saurel32                     info.si_code = TARGET_TRAP_BRKPT;
17689d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
176971f75756Saurel32                   }
177071f75756Saurel32             }
177171f75756Saurel32             break;
177256ba31ffSj_mayer         case EXCP_INTERRUPT:
177356ba31ffSj_mayer             /* just indicate that signals should be handled asap */
177456ba31ffSj_mayer             break;
1775fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
1776fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
1777fdbc2b57SRichard Henderson             break;
177861190b14Sbellard         default:
17798223f345SLaurent Vivier             cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
178067867308Sbellard             break;
178167867308Sbellard         }
178267867308Sbellard         process_pending_signals(env);
178367867308Sbellard     }
178467867308Sbellard }
178567867308Sbellard #endif
178667867308Sbellard 
1787048f6b4dSbellard #ifdef TARGET_MIPS
1788048f6b4dSbellard 
1789ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32
1790048f6b4dSbellard #  define MIPS_SYS(name, args) args,
1791048f6b4dSbellard static const uint8_t mips_syscall_args[] = {
179229fb0f25SAn-Cheng Huang 	MIPS_SYS(sys_syscall	, 8)	/* 4000 */
1793048f6b4dSbellard 	MIPS_SYS(sys_exit	, 1)
1794048f6b4dSbellard 	MIPS_SYS(sys_fork	, 0)
1795048f6b4dSbellard 	MIPS_SYS(sys_read	, 3)
1796048f6b4dSbellard 	MIPS_SYS(sys_write	, 3)
1797048f6b4dSbellard 	MIPS_SYS(sys_open	, 3)	/* 4005 */
1798048f6b4dSbellard 	MIPS_SYS(sys_close	, 1)
1799048f6b4dSbellard 	MIPS_SYS(sys_waitpid	, 3)
1800048f6b4dSbellard 	MIPS_SYS(sys_creat	, 2)
1801048f6b4dSbellard 	MIPS_SYS(sys_link	, 2)
1802048f6b4dSbellard 	MIPS_SYS(sys_unlink	, 1)	/* 4010 */
1803048f6b4dSbellard 	MIPS_SYS(sys_execve	, 0)
1804048f6b4dSbellard 	MIPS_SYS(sys_chdir	, 1)
1805048f6b4dSbellard 	MIPS_SYS(sys_time	, 1)
1806048f6b4dSbellard 	MIPS_SYS(sys_mknod	, 3)
1807048f6b4dSbellard 	MIPS_SYS(sys_chmod	, 2)	/* 4015 */
1808048f6b4dSbellard 	MIPS_SYS(sys_lchown	, 3)
1809048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1810048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_stat */
1811048f6b4dSbellard 	MIPS_SYS(sys_lseek	, 3)
1812048f6b4dSbellard 	MIPS_SYS(sys_getpid	, 0)	/* 4020 */
1813048f6b4dSbellard 	MIPS_SYS(sys_mount	, 5)
1814868e34d7SRichard Henderson 	MIPS_SYS(sys_umount	, 1)
1815048f6b4dSbellard 	MIPS_SYS(sys_setuid	, 1)
1816048f6b4dSbellard 	MIPS_SYS(sys_getuid	, 0)
1817048f6b4dSbellard 	MIPS_SYS(sys_stime	, 1)	/* 4025 */
1818048f6b4dSbellard 	MIPS_SYS(sys_ptrace	, 4)
1819048f6b4dSbellard 	MIPS_SYS(sys_alarm	, 1)
1820048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_fstat */
1821048f6b4dSbellard 	MIPS_SYS(sys_pause	, 0)
1822048f6b4dSbellard 	MIPS_SYS(sys_utime	, 2)	/* 4030 */
1823048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1824048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1825048f6b4dSbellard 	MIPS_SYS(sys_access	, 2)
1826048f6b4dSbellard 	MIPS_SYS(sys_nice	, 1)
1827048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4035 */
1828048f6b4dSbellard 	MIPS_SYS(sys_sync	, 0)
1829048f6b4dSbellard 	MIPS_SYS(sys_kill	, 2)
1830048f6b4dSbellard 	MIPS_SYS(sys_rename	, 2)
1831048f6b4dSbellard 	MIPS_SYS(sys_mkdir	, 2)
1832048f6b4dSbellard 	MIPS_SYS(sys_rmdir	, 1)	/* 4040 */
1833048f6b4dSbellard 	MIPS_SYS(sys_dup		, 1)
1834048f6b4dSbellard 	MIPS_SYS(sys_pipe	, 0)
1835048f6b4dSbellard 	MIPS_SYS(sys_times	, 1)
1836048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1837048f6b4dSbellard 	MIPS_SYS(sys_brk		, 1)	/* 4045 */
1838048f6b4dSbellard 	MIPS_SYS(sys_setgid	, 1)
1839048f6b4dSbellard 	MIPS_SYS(sys_getgid	, 0)
1840048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was signal(2) */
1841048f6b4dSbellard 	MIPS_SYS(sys_geteuid	, 0)
1842048f6b4dSbellard 	MIPS_SYS(sys_getegid	, 0)	/* 4050 */
1843048f6b4dSbellard 	MIPS_SYS(sys_acct	, 0)
1844868e34d7SRichard Henderson 	MIPS_SYS(sys_umount2	, 2)
1845048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1846048f6b4dSbellard 	MIPS_SYS(sys_ioctl	, 3)
1847048f6b4dSbellard 	MIPS_SYS(sys_fcntl	, 3)	/* 4055 */
1848048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 2)
1849048f6b4dSbellard 	MIPS_SYS(sys_setpgid	, 2)
1850048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1851048f6b4dSbellard 	MIPS_SYS(sys_olduname	, 1)
1852048f6b4dSbellard 	MIPS_SYS(sys_umask	, 1)	/* 4060 */
1853048f6b4dSbellard 	MIPS_SYS(sys_chroot	, 1)
1854048f6b4dSbellard 	MIPS_SYS(sys_ustat	, 2)
1855048f6b4dSbellard 	MIPS_SYS(sys_dup2	, 2)
1856048f6b4dSbellard 	MIPS_SYS(sys_getppid	, 0)
1857048f6b4dSbellard 	MIPS_SYS(sys_getpgrp	, 0)	/* 4065 */
1858048f6b4dSbellard 	MIPS_SYS(sys_setsid	, 0)
1859048f6b4dSbellard 	MIPS_SYS(sys_sigaction	, 3)
1860048f6b4dSbellard 	MIPS_SYS(sys_sgetmask	, 0)
1861048f6b4dSbellard 	MIPS_SYS(sys_ssetmask	, 1)
1862048f6b4dSbellard 	MIPS_SYS(sys_setreuid	, 2)	/* 4070 */
1863048f6b4dSbellard 	MIPS_SYS(sys_setregid	, 2)
1864048f6b4dSbellard 	MIPS_SYS(sys_sigsuspend	, 0)
1865048f6b4dSbellard 	MIPS_SYS(sys_sigpending	, 1)
1866048f6b4dSbellard 	MIPS_SYS(sys_sethostname	, 2)
1867048f6b4dSbellard 	MIPS_SYS(sys_setrlimit	, 2)	/* 4075 */
1868048f6b4dSbellard 	MIPS_SYS(sys_getrlimit	, 2)
1869048f6b4dSbellard 	MIPS_SYS(sys_getrusage	, 2)
1870048f6b4dSbellard 	MIPS_SYS(sys_gettimeofday, 2)
1871048f6b4dSbellard 	MIPS_SYS(sys_settimeofday, 2)
1872048f6b4dSbellard 	MIPS_SYS(sys_getgroups	, 2)	/* 4080 */
1873048f6b4dSbellard 	MIPS_SYS(sys_setgroups	, 2)
1874048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* old_select */
1875048f6b4dSbellard 	MIPS_SYS(sys_symlink	, 2)
1876048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_lstat */
1877048f6b4dSbellard 	MIPS_SYS(sys_readlink	, 3)	/* 4085 */
1878048f6b4dSbellard 	MIPS_SYS(sys_uselib	, 1)
1879048f6b4dSbellard 	MIPS_SYS(sys_swapon	, 2)
1880048f6b4dSbellard 	MIPS_SYS(sys_reboot	, 3)
1881048f6b4dSbellard 	MIPS_SYS(old_readdir	, 3)
1882048f6b4dSbellard 	MIPS_SYS(old_mmap	, 6)	/* 4090 */
1883048f6b4dSbellard 	MIPS_SYS(sys_munmap	, 2)
1884048f6b4dSbellard 	MIPS_SYS(sys_truncate	, 2)
1885048f6b4dSbellard 	MIPS_SYS(sys_ftruncate	, 2)
1886048f6b4dSbellard 	MIPS_SYS(sys_fchmod	, 2)
1887048f6b4dSbellard 	MIPS_SYS(sys_fchown	, 3)	/* 4095 */
1888048f6b4dSbellard 	MIPS_SYS(sys_getpriority	, 2)
1889048f6b4dSbellard 	MIPS_SYS(sys_setpriority	, 3)
1890048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
1891048f6b4dSbellard 	MIPS_SYS(sys_statfs	, 2)
1892048f6b4dSbellard 	MIPS_SYS(sys_fstatfs	, 2)	/* 4100 */
1893048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was ioperm(2) */
1894048f6b4dSbellard 	MIPS_SYS(sys_socketcall	, 2)
1895048f6b4dSbellard 	MIPS_SYS(sys_syslog	, 3)
1896048f6b4dSbellard 	MIPS_SYS(sys_setitimer	, 3)
1897048f6b4dSbellard 	MIPS_SYS(sys_getitimer	, 2)	/* 4105 */
1898048f6b4dSbellard 	MIPS_SYS(sys_newstat	, 2)
1899048f6b4dSbellard 	MIPS_SYS(sys_newlstat	, 2)
1900048f6b4dSbellard 	MIPS_SYS(sys_newfstat	, 2)
1901048f6b4dSbellard 	MIPS_SYS(sys_uname	, 1)
1902048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4110 was iopl(2) */
1903048f6b4dSbellard 	MIPS_SYS(sys_vhangup	, 0)
1904048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_idle() */
1905048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_vm86 */
1906048f6b4dSbellard 	MIPS_SYS(sys_wait4	, 4)
1907048f6b4dSbellard 	MIPS_SYS(sys_swapoff	, 1)	/* 4115 */
1908048f6b4dSbellard 	MIPS_SYS(sys_sysinfo	, 1)
1909048f6b4dSbellard 	MIPS_SYS(sys_ipc		, 6)
1910048f6b4dSbellard 	MIPS_SYS(sys_fsync	, 1)
1911048f6b4dSbellard 	MIPS_SYS(sys_sigreturn	, 0)
191218113962SPaul Brook 	MIPS_SYS(sys_clone	, 6)	/* 4120 */
1913048f6b4dSbellard 	MIPS_SYS(sys_setdomainname, 2)
1914048f6b4dSbellard 	MIPS_SYS(sys_newuname	, 1)
1915048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_modify_ldt */
1916048f6b4dSbellard 	MIPS_SYS(sys_adjtimex	, 1)
1917048f6b4dSbellard 	MIPS_SYS(sys_mprotect	, 3)	/* 4125 */
1918048f6b4dSbellard 	MIPS_SYS(sys_sigprocmask	, 3)
1919048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was create_module */
1920048f6b4dSbellard 	MIPS_SYS(sys_init_module	, 5)
1921048f6b4dSbellard 	MIPS_SYS(sys_delete_module, 1)
1922048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4130	was get_kernel_syms */
1923048f6b4dSbellard 	MIPS_SYS(sys_quotactl	, 0)
1924048f6b4dSbellard 	MIPS_SYS(sys_getpgid	, 1)
1925048f6b4dSbellard 	MIPS_SYS(sys_fchdir	, 1)
1926048f6b4dSbellard 	MIPS_SYS(sys_bdflush	, 2)
1927048f6b4dSbellard 	MIPS_SYS(sys_sysfs	, 3)	/* 4135 */
1928048f6b4dSbellard 	MIPS_SYS(sys_personality	, 1)
1929048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* for afs_syscall */
1930048f6b4dSbellard 	MIPS_SYS(sys_setfsuid	, 1)
1931048f6b4dSbellard 	MIPS_SYS(sys_setfsgid	, 1)
1932048f6b4dSbellard 	MIPS_SYS(sys_llseek	, 5)	/* 4140 */
1933048f6b4dSbellard 	MIPS_SYS(sys_getdents	, 3)
1934048f6b4dSbellard 	MIPS_SYS(sys_select	, 5)
1935048f6b4dSbellard 	MIPS_SYS(sys_flock	, 2)
1936048f6b4dSbellard 	MIPS_SYS(sys_msync	, 3)
1937048f6b4dSbellard 	MIPS_SYS(sys_readv	, 3)	/* 4145 */
1938048f6b4dSbellard 	MIPS_SYS(sys_writev	, 3)
1939048f6b4dSbellard 	MIPS_SYS(sys_cacheflush	, 3)
1940048f6b4dSbellard 	MIPS_SYS(sys_cachectl	, 3)
1941048f6b4dSbellard 	MIPS_SYS(sys_sysmips	, 4)
1942048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4150 */
1943048f6b4dSbellard 	MIPS_SYS(sys_getsid	, 1)
1944048f6b4dSbellard 	MIPS_SYS(sys_fdatasync	, 0)
1945048f6b4dSbellard 	MIPS_SYS(sys_sysctl	, 1)
1946048f6b4dSbellard 	MIPS_SYS(sys_mlock	, 2)
1947048f6b4dSbellard 	MIPS_SYS(sys_munlock	, 2)	/* 4155 */
1948048f6b4dSbellard 	MIPS_SYS(sys_mlockall	, 1)
1949048f6b4dSbellard 	MIPS_SYS(sys_munlockall	, 0)
1950048f6b4dSbellard 	MIPS_SYS(sys_sched_setparam, 2)
1951048f6b4dSbellard 	MIPS_SYS(sys_sched_getparam, 2)
1952048f6b4dSbellard 	MIPS_SYS(sys_sched_setscheduler, 3)	/* 4160 */
1953048f6b4dSbellard 	MIPS_SYS(sys_sched_getscheduler, 1)
1954048f6b4dSbellard 	MIPS_SYS(sys_sched_yield	, 0)
1955048f6b4dSbellard 	MIPS_SYS(sys_sched_get_priority_max, 1)
1956048f6b4dSbellard 	MIPS_SYS(sys_sched_get_priority_min, 1)
1957048f6b4dSbellard 	MIPS_SYS(sys_sched_rr_get_interval, 2)	/* 4165 */
1958048f6b4dSbellard 	MIPS_SYS(sys_nanosleep,	2)
1959b0932e06SPetar Jovanovic 	MIPS_SYS(sys_mremap	, 5)
1960048f6b4dSbellard 	MIPS_SYS(sys_accept	, 3)
1961048f6b4dSbellard 	MIPS_SYS(sys_bind	, 3)
1962048f6b4dSbellard 	MIPS_SYS(sys_connect	, 3)	/* 4170 */
1963048f6b4dSbellard 	MIPS_SYS(sys_getpeername	, 3)
1964048f6b4dSbellard 	MIPS_SYS(sys_getsockname	, 3)
1965048f6b4dSbellard 	MIPS_SYS(sys_getsockopt	, 5)
1966048f6b4dSbellard 	MIPS_SYS(sys_listen	, 2)
1967048f6b4dSbellard 	MIPS_SYS(sys_recv	, 4)	/* 4175 */
1968048f6b4dSbellard 	MIPS_SYS(sys_recvfrom	, 6)
1969048f6b4dSbellard 	MIPS_SYS(sys_recvmsg	, 3)
1970048f6b4dSbellard 	MIPS_SYS(sys_send	, 4)
1971048f6b4dSbellard 	MIPS_SYS(sys_sendmsg	, 3)
1972048f6b4dSbellard 	MIPS_SYS(sys_sendto	, 6)	/* 4180 */
1973048f6b4dSbellard 	MIPS_SYS(sys_setsockopt	, 5)
1974048f6b4dSbellard 	MIPS_SYS(sys_shutdown	, 2)
1975048f6b4dSbellard 	MIPS_SYS(sys_socket	, 3)
1976048f6b4dSbellard 	MIPS_SYS(sys_socketpair	, 4)
1977048f6b4dSbellard 	MIPS_SYS(sys_setresuid	, 3)	/* 4185 */
1978048f6b4dSbellard 	MIPS_SYS(sys_getresuid	, 3)
1979048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_query_module */
1980048f6b4dSbellard 	MIPS_SYS(sys_poll	, 3)
1981048f6b4dSbellard 	MIPS_SYS(sys_nfsservctl	, 3)
1982048f6b4dSbellard 	MIPS_SYS(sys_setresgid	, 3)	/* 4190 */
1983048f6b4dSbellard 	MIPS_SYS(sys_getresgid	, 3)
1984048f6b4dSbellard 	MIPS_SYS(sys_prctl	, 5)
1985048f6b4dSbellard 	MIPS_SYS(sys_rt_sigreturn, 0)
1986048f6b4dSbellard 	MIPS_SYS(sys_rt_sigaction, 4)
1987048f6b4dSbellard 	MIPS_SYS(sys_rt_sigprocmask, 4)	/* 4195 */
1988048f6b4dSbellard 	MIPS_SYS(sys_rt_sigpending, 2)
1989048f6b4dSbellard 	MIPS_SYS(sys_rt_sigtimedwait, 4)
1990048f6b4dSbellard 	MIPS_SYS(sys_rt_sigqueueinfo, 3)
1991048f6b4dSbellard 	MIPS_SYS(sys_rt_sigsuspend, 0)
1992048f6b4dSbellard 	MIPS_SYS(sys_pread64	, 6)	/* 4200 */
1993048f6b4dSbellard 	MIPS_SYS(sys_pwrite64	, 6)
1994048f6b4dSbellard 	MIPS_SYS(sys_chown	, 3)
1995048f6b4dSbellard 	MIPS_SYS(sys_getcwd	, 2)
1996048f6b4dSbellard 	MIPS_SYS(sys_capget	, 2)
1997048f6b4dSbellard 	MIPS_SYS(sys_capset	, 2)	/* 4205 */
1998053ebb27SWesley W. Terpstra 	MIPS_SYS(sys_sigaltstack	, 2)
1999048f6b4dSbellard 	MIPS_SYS(sys_sendfile	, 4)
2000048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
2001048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
2002048f6b4dSbellard 	MIPS_SYS(sys_mmap2	, 6)	/* 4210 */
2003048f6b4dSbellard 	MIPS_SYS(sys_truncate64	, 4)
2004048f6b4dSbellard 	MIPS_SYS(sys_ftruncate64	, 4)
2005048f6b4dSbellard 	MIPS_SYS(sys_stat64	, 2)
2006048f6b4dSbellard 	MIPS_SYS(sys_lstat64	, 2)
2007048f6b4dSbellard 	MIPS_SYS(sys_fstat64	, 2)	/* 4215 */
2008048f6b4dSbellard 	MIPS_SYS(sys_pivot_root	, 2)
2009048f6b4dSbellard 	MIPS_SYS(sys_mincore	, 3)
2010048f6b4dSbellard 	MIPS_SYS(sys_madvise	, 3)
2011048f6b4dSbellard 	MIPS_SYS(sys_getdents64	, 3)
2012048f6b4dSbellard 	MIPS_SYS(sys_fcntl64	, 3)	/* 4220 */
2013048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)
2014048f6b4dSbellard 	MIPS_SYS(sys_gettid	, 0)
2015048f6b4dSbellard 	MIPS_SYS(sys_readahead	, 5)
2016048f6b4dSbellard 	MIPS_SYS(sys_setxattr	, 5)
2017048f6b4dSbellard 	MIPS_SYS(sys_lsetxattr	, 5)	/* 4225 */
2018048f6b4dSbellard 	MIPS_SYS(sys_fsetxattr	, 5)
2019048f6b4dSbellard 	MIPS_SYS(sys_getxattr	, 4)
2020048f6b4dSbellard 	MIPS_SYS(sys_lgetxattr	, 4)
2021048f6b4dSbellard 	MIPS_SYS(sys_fgetxattr	, 4)
2022048f6b4dSbellard 	MIPS_SYS(sys_listxattr	, 3)	/* 4230 */
2023048f6b4dSbellard 	MIPS_SYS(sys_llistxattr	, 3)
2024048f6b4dSbellard 	MIPS_SYS(sys_flistxattr	, 3)
2025048f6b4dSbellard 	MIPS_SYS(sys_removexattr	, 2)
2026048f6b4dSbellard 	MIPS_SYS(sys_lremovexattr, 2)
2027048f6b4dSbellard 	MIPS_SYS(sys_fremovexattr, 2)	/* 4235 */
2028048f6b4dSbellard 	MIPS_SYS(sys_tkill	, 2)
2029048f6b4dSbellard 	MIPS_SYS(sys_sendfile64	, 5)
203043be1343SPetar Jovanovic 	MIPS_SYS(sys_futex	, 6)
2031048f6b4dSbellard 	MIPS_SYS(sys_sched_setaffinity, 3)
2032048f6b4dSbellard 	MIPS_SYS(sys_sched_getaffinity, 3)	/* 4240 */
2033048f6b4dSbellard 	MIPS_SYS(sys_io_setup	, 2)
2034048f6b4dSbellard 	MIPS_SYS(sys_io_destroy	, 1)
2035048f6b4dSbellard 	MIPS_SYS(sys_io_getevents, 5)
2036048f6b4dSbellard 	MIPS_SYS(sys_io_submit	, 3)
2037048f6b4dSbellard 	MIPS_SYS(sys_io_cancel	, 3)	/* 4245 */
2038048f6b4dSbellard 	MIPS_SYS(sys_exit_group	, 1)
2039048f6b4dSbellard 	MIPS_SYS(sys_lookup_dcookie, 3)
2040048f6b4dSbellard 	MIPS_SYS(sys_epoll_create, 1)
2041048f6b4dSbellard 	MIPS_SYS(sys_epoll_ctl	, 4)
2042048f6b4dSbellard 	MIPS_SYS(sys_epoll_wait	, 3)	/* 4250 */
2043048f6b4dSbellard 	MIPS_SYS(sys_remap_file_pages, 5)
2044048f6b4dSbellard 	MIPS_SYS(sys_set_tid_address, 1)
2045048f6b4dSbellard 	MIPS_SYS(sys_restart_syscall, 0)
2046048f6b4dSbellard 	MIPS_SYS(sys_fadvise64_64, 7)
2047048f6b4dSbellard 	MIPS_SYS(sys_statfs64	, 3)	/* 4255 */
2048048f6b4dSbellard 	MIPS_SYS(sys_fstatfs64	, 2)
2049048f6b4dSbellard 	MIPS_SYS(sys_timer_create, 3)
2050048f6b4dSbellard 	MIPS_SYS(sys_timer_settime, 4)
2051048f6b4dSbellard 	MIPS_SYS(sys_timer_gettime, 2)
2052048f6b4dSbellard 	MIPS_SYS(sys_timer_getoverrun, 1)	/* 4260 */
2053048f6b4dSbellard 	MIPS_SYS(sys_timer_delete, 1)
2054048f6b4dSbellard 	MIPS_SYS(sys_clock_settime, 2)
2055048f6b4dSbellard 	MIPS_SYS(sys_clock_gettime, 2)
2056048f6b4dSbellard 	MIPS_SYS(sys_clock_getres, 2)
2057048f6b4dSbellard 	MIPS_SYS(sys_clock_nanosleep, 4)	/* 4265 */
2058048f6b4dSbellard 	MIPS_SYS(sys_tgkill	, 3)
2059048f6b4dSbellard 	MIPS_SYS(sys_utimes	, 2)
2060048f6b4dSbellard 	MIPS_SYS(sys_mbind	, 4)
2061048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_get_mempolicy */
2062048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* 4270 sys_set_mempolicy */
2063048f6b4dSbellard 	MIPS_SYS(sys_mq_open	, 4)
2064048f6b4dSbellard 	MIPS_SYS(sys_mq_unlink	, 1)
2065048f6b4dSbellard 	MIPS_SYS(sys_mq_timedsend, 5)
2066048f6b4dSbellard 	MIPS_SYS(sys_mq_timedreceive, 5)
2067048f6b4dSbellard 	MIPS_SYS(sys_mq_notify	, 2)	/* 4275 */
2068048f6b4dSbellard 	MIPS_SYS(sys_mq_getsetattr, 3)
2069048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_vserver */
2070048f6b4dSbellard 	MIPS_SYS(sys_waitid	, 4)
2071048f6b4dSbellard 	MIPS_SYS(sys_ni_syscall	, 0)	/* available, was setaltroot */
2072048f6b4dSbellard 	MIPS_SYS(sys_add_key	, 5)
2073048f6b4dSbellard 	MIPS_SYS(sys_request_key, 4)
2074048f6b4dSbellard 	MIPS_SYS(sys_keyctl	, 5)
20756f5b89a0Sths 	MIPS_SYS(sys_set_thread_area, 1)
2076388bb21aSths 	MIPS_SYS(sys_inotify_init, 0)
2077388bb21aSths 	MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
2078388bb21aSths 	MIPS_SYS(sys_inotify_rm_watch, 2)
2079388bb21aSths 	MIPS_SYS(sys_migrate_pages, 4)
2080388bb21aSths 	MIPS_SYS(sys_openat, 4)
2081388bb21aSths 	MIPS_SYS(sys_mkdirat, 3)
2082388bb21aSths 	MIPS_SYS(sys_mknodat, 4)	/* 4290 */
2083388bb21aSths 	MIPS_SYS(sys_fchownat, 5)
2084388bb21aSths 	MIPS_SYS(sys_futimesat, 3)
2085388bb21aSths 	MIPS_SYS(sys_fstatat64, 4)
2086388bb21aSths 	MIPS_SYS(sys_unlinkat, 3)
2087388bb21aSths 	MIPS_SYS(sys_renameat, 4)	/* 4295 */
2088388bb21aSths 	MIPS_SYS(sys_linkat, 5)
2089388bb21aSths 	MIPS_SYS(sys_symlinkat, 3)
2090388bb21aSths 	MIPS_SYS(sys_readlinkat, 4)
2091388bb21aSths 	MIPS_SYS(sys_fchmodat, 3)
2092388bb21aSths 	MIPS_SYS(sys_faccessat, 3)	/* 4300 */
2093388bb21aSths 	MIPS_SYS(sys_pselect6, 6)
2094388bb21aSths 	MIPS_SYS(sys_ppoll, 5)
2095388bb21aSths 	MIPS_SYS(sys_unshare, 1)
2096b0932e06SPetar Jovanovic 	MIPS_SYS(sys_splice, 6)
2097388bb21aSths 	MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
2098388bb21aSths 	MIPS_SYS(sys_tee, 4)
2099388bb21aSths 	MIPS_SYS(sys_vmsplice, 4)
2100388bb21aSths 	MIPS_SYS(sys_move_pages, 6)
2101388bb21aSths 	MIPS_SYS(sys_set_robust_list, 2)
2102388bb21aSths 	MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
2103388bb21aSths 	MIPS_SYS(sys_kexec_load, 4)
2104388bb21aSths 	MIPS_SYS(sys_getcpu, 3)
2105388bb21aSths 	MIPS_SYS(sys_epoll_pwait, 6)
2106388bb21aSths 	MIPS_SYS(sys_ioprio_set, 3)
2107388bb21aSths 	MIPS_SYS(sys_ioprio_get, 2)
2108d979e8ebSPeter Maydell         MIPS_SYS(sys_utimensat, 4)
2109d979e8ebSPeter Maydell         MIPS_SYS(sys_signalfd, 3)
2110d979e8ebSPeter Maydell         MIPS_SYS(sys_ni_syscall, 0)     /* was timerfd */
2111d979e8ebSPeter Maydell         MIPS_SYS(sys_eventfd, 1)
2112d979e8ebSPeter Maydell         MIPS_SYS(sys_fallocate, 6)      /* 4320 */
2113d979e8ebSPeter Maydell         MIPS_SYS(sys_timerfd_create, 2)
2114d979e8ebSPeter Maydell         MIPS_SYS(sys_timerfd_gettime, 2)
2115d979e8ebSPeter Maydell         MIPS_SYS(sys_timerfd_settime, 4)
2116d979e8ebSPeter Maydell         MIPS_SYS(sys_signalfd4, 4)
2117d979e8ebSPeter Maydell         MIPS_SYS(sys_eventfd2, 2)       /* 4325 */
2118d979e8ebSPeter Maydell         MIPS_SYS(sys_epoll_create1, 1)
2119d979e8ebSPeter Maydell         MIPS_SYS(sys_dup3, 3)
2120d979e8ebSPeter Maydell         MIPS_SYS(sys_pipe2, 2)
2121d979e8ebSPeter Maydell         MIPS_SYS(sys_inotify_init1, 1)
21222e6eeb67SAleksandar Markovic         MIPS_SYS(sys_preadv, 5)         /* 4330 */
21232e6eeb67SAleksandar Markovic         MIPS_SYS(sys_pwritev, 5)
2124d979e8ebSPeter Maydell         MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
2125d979e8ebSPeter Maydell         MIPS_SYS(sys_perf_event_open, 5)
2126d979e8ebSPeter Maydell         MIPS_SYS(sys_accept4, 4)
2127d979e8ebSPeter Maydell         MIPS_SYS(sys_recvmmsg, 5)       /* 4335 */
2128d979e8ebSPeter Maydell         MIPS_SYS(sys_fanotify_init, 2)
2129d979e8ebSPeter Maydell         MIPS_SYS(sys_fanotify_mark, 6)
2130d979e8ebSPeter Maydell         MIPS_SYS(sys_prlimit64, 4)
2131d979e8ebSPeter Maydell         MIPS_SYS(sys_name_to_handle_at, 5)
2132d979e8ebSPeter Maydell         MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
2133d979e8ebSPeter Maydell         MIPS_SYS(sys_clock_adjtime, 2)
2134d979e8ebSPeter Maydell         MIPS_SYS(sys_syncfs, 1)
21352e6eeb67SAleksandar Markovic         MIPS_SYS(sys_sendmmsg, 4)
21362e6eeb67SAleksandar Markovic         MIPS_SYS(sys_setns, 2)
21372e6eeb67SAleksandar Markovic         MIPS_SYS(sys_process_vm_readv, 6) /* 345 */
21382e6eeb67SAleksandar Markovic         MIPS_SYS(sys_process_vm_writev, 6)
21392e6eeb67SAleksandar Markovic         MIPS_SYS(sys_kcmp, 5)
21402e6eeb67SAleksandar Markovic         MIPS_SYS(sys_finit_module, 3)
21412e6eeb67SAleksandar Markovic         MIPS_SYS(sys_sched_setattr, 2)
21422e6eeb67SAleksandar Markovic         MIPS_SYS(sys_sched_getattr, 3)  /* 350 */
21432e6eeb67SAleksandar Markovic         MIPS_SYS(sys_renameat2, 5)
21442e6eeb67SAleksandar Markovic         MIPS_SYS(sys_seccomp, 3)
21452e6eeb67SAleksandar Markovic         MIPS_SYS(sys_getrandom, 3)
21462e6eeb67SAleksandar Markovic         MIPS_SYS(sys_memfd_create, 2)
21472e6eeb67SAleksandar Markovic         MIPS_SYS(sys_bpf, 3)            /* 355 */
21482e6eeb67SAleksandar Markovic         MIPS_SYS(sys_execveat, 5)
21492e6eeb67SAleksandar Markovic         MIPS_SYS(sys_userfaultfd, 1)
21502e6eeb67SAleksandar Markovic         MIPS_SYS(sys_membarrier, 2)
21512e6eeb67SAleksandar Markovic         MIPS_SYS(sys_mlock2, 3)
21522e6eeb67SAleksandar Markovic         MIPS_SYS(sys_copy_file_range, 6) /* 360 */
21532e6eeb67SAleksandar Markovic         MIPS_SYS(sys_preadv2, 6)
21542e6eeb67SAleksandar Markovic         MIPS_SYS(sys_pwritev2, 6)
2155048f6b4dSbellard };
2156048f6b4dSbellard #  undef MIPS_SYS
2157ff4f7382SRichard Henderson # endif /* O32 */
2158048f6b4dSbellard 
2159590bc601SPaul Brook static int do_store_exclusive(CPUMIPSState *env)
2160590bc601SPaul Brook {
2161590bc601SPaul Brook     target_ulong addr;
2162590bc601SPaul Brook     target_ulong page_addr;
2163590bc601SPaul Brook     target_ulong val;
2164590bc601SPaul Brook     int flags;
2165590bc601SPaul Brook     int segv = 0;
2166590bc601SPaul Brook     int reg;
2167590bc601SPaul Brook     int d;
2168590bc601SPaul Brook 
21695499b6ffSAurelien Jarno     addr = env->lladdr;
2170590bc601SPaul Brook     page_addr = addr & TARGET_PAGE_MASK;
2171590bc601SPaul Brook     start_exclusive();
2172590bc601SPaul Brook     mmap_lock();
2173590bc601SPaul Brook     flags = page_get_flags(page_addr);
2174590bc601SPaul Brook     if ((flags & PAGE_READ) == 0) {
2175590bc601SPaul Brook         segv = 1;
2176590bc601SPaul Brook     } else {
2177590bc601SPaul Brook         reg = env->llreg & 0x1f;
2178590bc601SPaul Brook         d = (env->llreg & 0x20) != 0;
2179590bc601SPaul Brook         if (d) {
2180590bc601SPaul Brook             segv = get_user_s64(val, addr);
2181590bc601SPaul Brook         } else {
2182590bc601SPaul Brook             segv = get_user_s32(val, addr);
2183590bc601SPaul Brook         }
2184590bc601SPaul Brook         if (!segv) {
2185590bc601SPaul Brook             if (val != env->llval) {
2186590bc601SPaul Brook                 env->active_tc.gpr[reg] = 0;
2187590bc601SPaul Brook             } else {
2188590bc601SPaul Brook                 if (d) {
2189590bc601SPaul Brook                     segv = put_user_u64(env->llnewval, addr);
2190590bc601SPaul Brook                 } else {
2191590bc601SPaul Brook                     segv = put_user_u32(env->llnewval, addr);
2192590bc601SPaul Brook                 }
2193590bc601SPaul Brook                 if (!segv) {
2194590bc601SPaul Brook                     env->active_tc.gpr[reg] = 1;
2195590bc601SPaul Brook                 }
2196590bc601SPaul Brook             }
2197590bc601SPaul Brook         }
2198590bc601SPaul Brook     }
21995499b6ffSAurelien Jarno     env->lladdr = -1;
2200590bc601SPaul Brook     if (!segv) {
2201590bc601SPaul Brook         env->active_tc.PC += 4;
2202590bc601SPaul Brook     }
2203590bc601SPaul Brook     mmap_unlock();
2204590bc601SPaul Brook     end_exclusive();
2205590bc601SPaul Brook     return segv;
2206590bc601SPaul Brook }
2207590bc601SPaul Brook 
220854b2f42cSMeador Inge /* Break codes */
220954b2f42cSMeador Inge enum {
221054b2f42cSMeador Inge     BRK_OVERFLOW = 6,
221154b2f42cSMeador Inge     BRK_DIVZERO = 7
221254b2f42cSMeador Inge };
221354b2f42cSMeador Inge 
221454b2f42cSMeador Inge static int do_break(CPUMIPSState *env, target_siginfo_t *info,
221554b2f42cSMeador Inge                     unsigned int code)
221654b2f42cSMeador Inge {
221754b2f42cSMeador Inge     int ret = -1;
221854b2f42cSMeador Inge 
221954b2f42cSMeador Inge     switch (code) {
222054b2f42cSMeador Inge     case BRK_OVERFLOW:
222154b2f42cSMeador Inge     case BRK_DIVZERO:
222254b2f42cSMeador Inge         info->si_signo = TARGET_SIGFPE;
222354b2f42cSMeador Inge         info->si_errno = 0;
222454b2f42cSMeador Inge         info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
22259d2803f7SPeter Maydell         queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
222654b2f42cSMeador Inge         ret = 0;
222754b2f42cSMeador Inge         break;
222854b2f42cSMeador Inge     default:
2229b51910baSPetar Jovanovic         info->si_signo = TARGET_SIGTRAP;
2230b51910baSPetar Jovanovic         info->si_errno = 0;
22319d2803f7SPeter Maydell         queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
2232b51910baSPetar Jovanovic         ret = 0;
223354b2f42cSMeador Inge         break;
223454b2f42cSMeador Inge     }
223554b2f42cSMeador Inge 
223654b2f42cSMeador Inge     return ret;
223754b2f42cSMeador Inge }
223854b2f42cSMeador Inge 
2239048f6b4dSbellard void cpu_loop(CPUMIPSState *env)
2240048f6b4dSbellard {
22410315c31cSAndreas Färber     CPUState *cs = CPU(mips_env_get_cpu(env));
2242c227f099SAnthony Liguori     target_siginfo_t info;
2243ff4f7382SRichard Henderson     int trapnr;
2244ff4f7382SRichard Henderson     abi_long ret;
2245ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32
2246048f6b4dSbellard     unsigned int syscall_num;
2247ff4f7382SRichard Henderson # endif
2248048f6b4dSbellard 
2249048f6b4dSbellard     for(;;) {
22500315c31cSAndreas Färber         cpu_exec_start(cs);
22518642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
22520315c31cSAndreas Färber         cpu_exec_end(cs);
2253d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
2254d148d90eSSergey Fedorov 
2255048f6b4dSbellard         switch(trapnr) {
2256048f6b4dSbellard         case EXCP_SYSCALL:
2257b5dc7732Sths             env->active_tc.PC += 4;
2258ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32
2259ff4f7382SRichard Henderson             syscall_num = env->active_tc.gpr[2] - 4000;
2260048f6b4dSbellard             if (syscall_num >= sizeof(mips_syscall_args)) {
22617c2f6157SWesley W. Terpstra                 ret = -TARGET_ENOSYS;
2262048f6b4dSbellard             } else {
2263388bb21aSths                 int nb_args;
2264992f48a0Sblueswir1                 abi_ulong sp_reg;
2265992f48a0Sblueswir1                 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
2266388bb21aSths 
2267048f6b4dSbellard                 nb_args = mips_syscall_args[syscall_num];
2268b5dc7732Sths                 sp_reg = env->active_tc.gpr[29];
2269388bb21aSths                 switch (nb_args) {
2270048f6b4dSbellard                 /* these arguments are taken from the stack */
227194c19610SAn-Cheng Huang                 case 8:
227294c19610SAn-Cheng Huang                     if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
227394c19610SAn-Cheng Huang                         goto done_syscall;
227494c19610SAn-Cheng Huang                     }
227594c19610SAn-Cheng Huang                 case 7:
227694c19610SAn-Cheng Huang                     if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
227794c19610SAn-Cheng Huang                         goto done_syscall;
227894c19610SAn-Cheng Huang                     }
227994c19610SAn-Cheng Huang                 case 6:
228094c19610SAn-Cheng Huang                     if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
228194c19610SAn-Cheng Huang                         goto done_syscall;
228294c19610SAn-Cheng Huang                     }
228394c19610SAn-Cheng Huang                 case 5:
228494c19610SAn-Cheng Huang                     if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
228594c19610SAn-Cheng Huang                         goto done_syscall;
228694c19610SAn-Cheng Huang                     }
2287388bb21aSths                 default:
2288388bb21aSths                     break;
2289048f6b4dSbellard                 }
2290b5dc7732Sths                 ret = do_syscall(env, env->active_tc.gpr[2],
2291b5dc7732Sths                                  env->active_tc.gpr[4],
2292b5dc7732Sths                                  env->active_tc.gpr[5],
2293b5dc7732Sths                                  env->active_tc.gpr[6],
2294b5dc7732Sths                                  env->active_tc.gpr[7],
22955945cfcbSPeter Maydell                                  arg5, arg6, arg7, arg8);
2296048f6b4dSbellard             }
229794c19610SAn-Cheng Huang done_syscall:
2298ff4f7382SRichard Henderson # else
2299ff4f7382SRichard Henderson             ret = do_syscall(env, env->active_tc.gpr[2],
2300ff4f7382SRichard Henderson                              env->active_tc.gpr[4], env->active_tc.gpr[5],
2301ff4f7382SRichard Henderson                              env->active_tc.gpr[6], env->active_tc.gpr[7],
2302ff4f7382SRichard Henderson                              env->active_tc.gpr[8], env->active_tc.gpr[9],
2303ff4f7382SRichard Henderson                              env->active_tc.gpr[10], env->active_tc.gpr[11]);
2304ff4f7382SRichard Henderson # endif /* O32 */
23052eb3ae27STimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
23062eb3ae27STimothy E Baldwin                 env->active_tc.PC -= 4;
23072eb3ae27STimothy E Baldwin                 break;
23082eb3ae27STimothy E Baldwin             }
23090b1bcb00Spbrook             if (ret == -TARGET_QEMU_ESIGRETURN) {
23100b1bcb00Spbrook                 /* Returning from a successful sigreturn syscall.
23110b1bcb00Spbrook                    Avoid clobbering register state.  */
23120b1bcb00Spbrook                 break;
23130b1bcb00Spbrook             }
2314ff4f7382SRichard Henderson             if ((abi_ulong)ret >= (abi_ulong)-1133) {
2315b5dc7732Sths                 env->active_tc.gpr[7] = 1; /* error flag */
2316048f6b4dSbellard                 ret = -ret;
2317048f6b4dSbellard             } else {
2318b5dc7732Sths                 env->active_tc.gpr[7] = 0; /* error flag */
2319388bb21aSths             }
2320b5dc7732Sths             env->active_tc.gpr[2] = ret;
2321048f6b4dSbellard             break;
2322ca7c2b1bSths         case EXCP_TLBL:
2323ca7c2b1bSths         case EXCP_TLBS:
2324e6e5bd2dSWesley W. Terpstra         case EXCP_AdEL:
2325e6e5bd2dSWesley W. Terpstra         case EXCP_AdES:
2326e4474235Spbrook             info.si_signo = TARGET_SIGSEGV;
2327e4474235Spbrook             info.si_errno = 0;
2328e4474235Spbrook             /* XXX: check env->error_code */
2329e4474235Spbrook             info.si_code = TARGET_SEGV_MAPERR;
2330e4474235Spbrook             info._sifields._sigfault._addr = env->CP0_BadVAddr;
23319d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2332e4474235Spbrook             break;
23336900e84bSbellard         case EXCP_CpU:
2334048f6b4dSbellard         case EXCP_RI:
2335048f6b4dSbellard             info.si_signo = TARGET_SIGILL;
2336048f6b4dSbellard             info.si_errno = 0;
2337048f6b4dSbellard             info.si_code = 0;
23389d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2339048f6b4dSbellard             break;
2340106ec879Sbellard         case EXCP_INTERRUPT:
2341106ec879Sbellard             /* just indicate that signals should be handled asap */
2342106ec879Sbellard             break;
2343d08b2a28Spbrook         case EXCP_DEBUG:
2344d08b2a28Spbrook             {
2345d08b2a28Spbrook                 int sig;
2346d08b2a28Spbrook 
2347db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
2348d08b2a28Spbrook                 if (sig)
2349d08b2a28Spbrook                   {
2350d08b2a28Spbrook                     info.si_signo = sig;
2351d08b2a28Spbrook                     info.si_errno = 0;
2352d08b2a28Spbrook                     info.si_code = TARGET_TRAP_BRKPT;
23539d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2354d08b2a28Spbrook                   }
2355d08b2a28Spbrook             }
2356d08b2a28Spbrook             break;
2357590bc601SPaul Brook         case EXCP_SC:
2358590bc601SPaul Brook             if (do_store_exclusive(env)) {
2359590bc601SPaul Brook                 info.si_signo = TARGET_SIGSEGV;
2360590bc601SPaul Brook                 info.si_errno = 0;
2361590bc601SPaul Brook                 info.si_code = TARGET_SEGV_MAPERR;
2362590bc601SPaul Brook                 info._sifields._sigfault._addr = env->active_tc.PC;
23639d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2364590bc601SPaul Brook             }
2365590bc601SPaul Brook             break;
2366853c3240SJia Liu         case EXCP_DSPDIS:
2367853c3240SJia Liu             info.si_signo = TARGET_SIGILL;
2368853c3240SJia Liu             info.si_errno = 0;
2369853c3240SJia Liu             info.si_code = TARGET_ILL_ILLOPC;
23709d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2371853c3240SJia Liu             break;
237254b2f42cSMeador Inge         /* The code below was inspired by the MIPS Linux kernel trap
237354b2f42cSMeador Inge          * handling code in arch/mips/kernel/traps.c.
237454b2f42cSMeador Inge          */
237554b2f42cSMeador Inge         case EXCP_BREAK:
237654b2f42cSMeador Inge             {
237754b2f42cSMeador Inge                 abi_ulong trap_instr;
237854b2f42cSMeador Inge                 unsigned int code;
237954b2f42cSMeador Inge 
2380a0333817SKwok Cheung Yeung                 if (env->hflags & MIPS_HFLAG_M16) {
2381a0333817SKwok Cheung Yeung                     if (env->insn_flags & ASE_MICROMIPS) {
2382a0333817SKwok Cheung Yeung                         /* microMIPS mode */
23831308c464SKwok Cheung Yeung                         ret = get_user_u16(trap_instr, env->active_tc.PC);
23841308c464SKwok Cheung Yeung                         if (ret != 0) {
23851308c464SKwok Cheung Yeung                             goto error;
23861308c464SKwok Cheung Yeung                         }
2387a0333817SKwok Cheung Yeung 
23881308c464SKwok Cheung Yeung                         if ((trap_instr >> 10) == 0x11) {
23891308c464SKwok Cheung Yeung                             /* 16-bit instruction */
23901308c464SKwok Cheung Yeung                             code = trap_instr & 0xf;
23911308c464SKwok Cheung Yeung                         } else {
23921308c464SKwok Cheung Yeung                             /* 32-bit instruction */
23931308c464SKwok Cheung Yeung                             abi_ulong instr_lo;
2394a0333817SKwok Cheung Yeung 
23951308c464SKwok Cheung Yeung                             ret = get_user_u16(instr_lo,
23961308c464SKwok Cheung Yeung                                                env->active_tc.PC + 2);
23971308c464SKwok Cheung Yeung                             if (ret != 0) {
23981308c464SKwok Cheung Yeung                                 goto error;
23991308c464SKwok Cheung Yeung                             }
24001308c464SKwok Cheung Yeung                             trap_instr = (trap_instr << 16) | instr_lo;
24011308c464SKwok Cheung Yeung                             code = ((trap_instr >> 6) & ((1 << 20) - 1));
24021308c464SKwok Cheung Yeung                             /* Unfortunately, microMIPS also suffers from
24031308c464SKwok Cheung Yeung                                the old assembler bug...  */
24041308c464SKwok Cheung Yeung                             if (code >= (1 << 10)) {
24051308c464SKwok Cheung Yeung                                 code >>= 10;
24061308c464SKwok Cheung Yeung                             }
24071308c464SKwok Cheung Yeung                         }
2408a0333817SKwok Cheung Yeung                     } else {
2409a0333817SKwok Cheung Yeung                         /* MIPS16e mode */
2410a0333817SKwok Cheung Yeung                         ret = get_user_u16(trap_instr, env->active_tc.PC);
2411a0333817SKwok Cheung Yeung                         if (ret != 0) {
2412a0333817SKwok Cheung Yeung                             goto error;
2413a0333817SKwok Cheung Yeung                         }
2414a0333817SKwok Cheung Yeung                         code = (trap_instr >> 6) & 0x3f;
2415a0333817SKwok Cheung Yeung                     }
2416a0333817SKwok Cheung Yeung                 } else {
2417f01a361bSAndrew Bennett                     ret = get_user_u32(trap_instr, env->active_tc.PC);
241854b2f42cSMeador Inge                     if (ret != 0) {
241954b2f42cSMeador Inge                         goto error;
242054b2f42cSMeador Inge                     }
242154b2f42cSMeador Inge 
242254b2f42cSMeador Inge                     /* As described in the original Linux kernel code, the
242354b2f42cSMeador Inge                      * below checks on 'code' are to work around an old
242454b2f42cSMeador Inge                      * assembly bug.
242554b2f42cSMeador Inge                      */
242654b2f42cSMeador Inge                     code = ((trap_instr >> 6) & ((1 << 20) - 1));
242754b2f42cSMeador Inge                     if (code >= (1 << 10)) {
242854b2f42cSMeador Inge                         code >>= 10;
242954b2f42cSMeador Inge                     }
24301308c464SKwok Cheung Yeung                 }
243154b2f42cSMeador Inge 
243254b2f42cSMeador Inge                 if (do_break(env, &info, code) != 0) {
243354b2f42cSMeador Inge                     goto error;
243454b2f42cSMeador Inge                 }
243554b2f42cSMeador Inge             }
243654b2f42cSMeador Inge             break;
243754b2f42cSMeador Inge         case EXCP_TRAP:
243854b2f42cSMeador Inge             {
243954b2f42cSMeador Inge                 abi_ulong trap_instr;
244054b2f42cSMeador Inge                 unsigned int code = 0;
244154b2f42cSMeador Inge 
2442a0333817SKwok Cheung Yeung                 if (env->hflags & MIPS_HFLAG_M16) {
2443a0333817SKwok Cheung Yeung                     /* microMIPS mode */
2444a0333817SKwok Cheung Yeung                     abi_ulong instr[2];
2445a0333817SKwok Cheung Yeung 
2446a0333817SKwok Cheung Yeung                     ret = get_user_u16(instr[0], env->active_tc.PC) ||
2447a0333817SKwok Cheung Yeung                           get_user_u16(instr[1], env->active_tc.PC + 2);
2448a0333817SKwok Cheung Yeung 
2449a0333817SKwok Cheung Yeung                     trap_instr = (instr[0] << 16) | instr[1];
2450a0333817SKwok Cheung Yeung                 } else {
2451f01a361bSAndrew Bennett                     ret = get_user_u32(trap_instr, env->active_tc.PC);
2452a0333817SKwok Cheung Yeung                 }
2453a0333817SKwok Cheung Yeung 
245454b2f42cSMeador Inge                 if (ret != 0) {
245554b2f42cSMeador Inge                     goto error;
245654b2f42cSMeador Inge                 }
245754b2f42cSMeador Inge 
245854b2f42cSMeador Inge                 /* The immediate versions don't provide a code.  */
245954b2f42cSMeador Inge                 if (!(trap_instr & 0xFC000000)) {
2460a0333817SKwok Cheung Yeung                     if (env->hflags & MIPS_HFLAG_M16) {
2461a0333817SKwok Cheung Yeung                         /* microMIPS mode */
2462a0333817SKwok Cheung Yeung                         code = ((trap_instr >> 12) & ((1 << 4) - 1));
2463a0333817SKwok Cheung Yeung                     } else {
246454b2f42cSMeador Inge                         code = ((trap_instr >> 6) & ((1 << 10) - 1));
246554b2f42cSMeador Inge                     }
2466a0333817SKwok Cheung Yeung                 }
246754b2f42cSMeador Inge 
246854b2f42cSMeador Inge                 if (do_break(env, &info, code) != 0) {
246954b2f42cSMeador Inge                     goto error;
247054b2f42cSMeador Inge                 }
247154b2f42cSMeador Inge             }
247254b2f42cSMeador Inge             break;
2473fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
2474fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
2475fdbc2b57SRichard Henderson             break;
2476048f6b4dSbellard         default:
247754b2f42cSMeador Inge error:
2478120a9848SPaolo Bonzini             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
2479048f6b4dSbellard             abort();
2480048f6b4dSbellard         }
2481048f6b4dSbellard         process_pending_signals(env);
2482048f6b4dSbellard     }
2483048f6b4dSbellard }
2484048f6b4dSbellard #endif
2485048f6b4dSbellard 
2486a0a839b6SMarek Vasut #ifdef TARGET_NIOS2
2487a0a839b6SMarek Vasut 
2488a0a839b6SMarek Vasut void cpu_loop(CPUNios2State *env)
2489a0a839b6SMarek Vasut {
2490a0a839b6SMarek Vasut     CPUState *cs = ENV_GET_CPU(env);
2491a0a839b6SMarek Vasut     Nios2CPU *cpu = NIOS2_CPU(cs);
2492a0a839b6SMarek Vasut     target_siginfo_t info;
2493a0a839b6SMarek Vasut     int trapnr, gdbsig, ret;
2494a0a839b6SMarek Vasut 
2495a0a839b6SMarek Vasut     for (;;) {
2496a0a839b6SMarek Vasut         cpu_exec_start(cs);
2497a0a839b6SMarek Vasut         trapnr = cpu_exec(cs);
2498a0a839b6SMarek Vasut         cpu_exec_end(cs);
2499a0a839b6SMarek Vasut         gdbsig = 0;
2500a0a839b6SMarek Vasut 
2501a0a839b6SMarek Vasut         switch (trapnr) {
2502a0a839b6SMarek Vasut         case EXCP_INTERRUPT:
2503a0a839b6SMarek Vasut             /* just indicate that signals should be handled asap */
2504a0a839b6SMarek Vasut             break;
2505a0a839b6SMarek Vasut         case EXCP_TRAP:
2506a0a839b6SMarek Vasut             if (env->regs[R_AT] == 0) {
2507a0a839b6SMarek Vasut                 abi_long ret;
2508a0a839b6SMarek Vasut                 qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
2509a0a839b6SMarek Vasut 
2510a0a839b6SMarek Vasut                 ret = do_syscall(env, env->regs[2],
2511a0a839b6SMarek Vasut                                  env->regs[4], env->regs[5], env->regs[6],
2512a0a839b6SMarek Vasut                                  env->regs[7], env->regs[8], env->regs[9],
2513a0a839b6SMarek Vasut                                  0, 0);
2514a0a839b6SMarek Vasut 
2515a0a839b6SMarek Vasut                 if (env->regs[2] == 0) {    /* FIXME: syscall 0 workaround */
2516a0a839b6SMarek Vasut                     ret = 0;
2517a0a839b6SMarek Vasut                 }
2518a0a839b6SMarek Vasut 
2519a0a839b6SMarek Vasut                 env->regs[2] = abs(ret);
2520a0a839b6SMarek Vasut                 /* Return value is 0..4096 */
2521a0a839b6SMarek Vasut                 env->regs[7] = (ret > 0xfffffffffffff000ULL);
2522a0a839b6SMarek Vasut                 env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
2523a0a839b6SMarek Vasut                 env->regs[CR_STATUS] &= ~0x3;
2524a0a839b6SMarek Vasut                 env->regs[R_EA] = env->regs[R_PC] + 4;
2525a0a839b6SMarek Vasut                 env->regs[R_PC] += 4;
2526a0a839b6SMarek Vasut                 break;
2527a0a839b6SMarek Vasut             } else {
2528a0a839b6SMarek Vasut                 qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
2529a0a839b6SMarek Vasut 
2530a0a839b6SMarek Vasut                 env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
2531a0a839b6SMarek Vasut                 env->regs[CR_STATUS] &= ~0x3;
2532a0a839b6SMarek Vasut                 env->regs[R_EA] = env->regs[R_PC] + 4;
2533a0a839b6SMarek Vasut                 env->regs[R_PC] = cpu->exception_addr;
2534a0a839b6SMarek Vasut 
2535a0a839b6SMarek Vasut                 gdbsig = TARGET_SIGTRAP;
2536a0a839b6SMarek Vasut                 break;
2537a0a839b6SMarek Vasut             }
2538a0a839b6SMarek Vasut         case 0xaa:
2539a0a839b6SMarek Vasut             switch (env->regs[R_PC]) {
2540a0a839b6SMarek Vasut             /*case 0x1000:*/  /* TODO:__kuser_helper_version */
2541a0a839b6SMarek Vasut             case 0x1004:      /* __kuser_cmpxchg */
2542a0a839b6SMarek Vasut                 start_exclusive();
2543a0a839b6SMarek Vasut                 if (env->regs[4] & 0x3) {
2544a0a839b6SMarek Vasut                     goto kuser_fail;
2545a0a839b6SMarek Vasut                 }
2546a0a839b6SMarek Vasut                 ret = get_user_u32(env->regs[2], env->regs[4]);
2547a0a839b6SMarek Vasut                 if (ret) {
2548a0a839b6SMarek Vasut                     end_exclusive();
2549a0a839b6SMarek Vasut                     goto kuser_fail;
2550a0a839b6SMarek Vasut                 }
2551a0a839b6SMarek Vasut                 env->regs[2] -= env->regs[5];
2552a0a839b6SMarek Vasut                 if (env->regs[2] == 0) {
2553a0a839b6SMarek Vasut                     put_user_u32(env->regs[6], env->regs[4]);
2554a0a839b6SMarek Vasut                 }
2555a0a839b6SMarek Vasut                 end_exclusive();
2556a0a839b6SMarek Vasut                 env->regs[R_PC] = env->regs[R_RA];
2557a0a839b6SMarek Vasut                 break;
2558a0a839b6SMarek Vasut             /*case 0x1040:*/  /* TODO:__kuser_sigtramp */
2559a0a839b6SMarek Vasut             default:
2560a0a839b6SMarek Vasut                 ;
2561a0a839b6SMarek Vasut kuser_fail:
2562a0a839b6SMarek Vasut                 info.si_signo = TARGET_SIGSEGV;
2563a0a839b6SMarek Vasut                 info.si_errno = 0;
2564a0a839b6SMarek Vasut                 /* TODO: check env->error_code */
2565a0a839b6SMarek Vasut                 info.si_code = TARGET_SEGV_MAPERR;
2566a0a839b6SMarek Vasut                 info._sifields._sigfault._addr = env->regs[R_PC];
2567a0a839b6SMarek Vasut                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2568a0a839b6SMarek Vasut             }
2569a0a839b6SMarek Vasut             break;
2570a0a839b6SMarek Vasut         default:
2571a0a839b6SMarek Vasut             EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
2572a0a839b6SMarek Vasut                      trapnr);
2573a0a839b6SMarek Vasut             gdbsig = TARGET_SIGILL;
2574a0a839b6SMarek Vasut             break;
2575a0a839b6SMarek Vasut         }
2576a0a839b6SMarek Vasut         if (gdbsig) {
2577a0a839b6SMarek Vasut             gdb_handlesig(cs, gdbsig);
2578a0a839b6SMarek Vasut             if (gdbsig != TARGET_SIGTRAP) {
2579a0a839b6SMarek Vasut                 exit(EXIT_FAILURE);
2580a0a839b6SMarek Vasut             }
2581a0a839b6SMarek Vasut         }
2582a0a839b6SMarek Vasut 
2583a0a839b6SMarek Vasut         process_pending_signals(env);
2584a0a839b6SMarek Vasut     }
2585a0a839b6SMarek Vasut }
2586a0a839b6SMarek Vasut 
2587a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */
2588a0a839b6SMarek Vasut 
2589d962783eSJia Liu #ifdef TARGET_OPENRISC
2590d962783eSJia Liu 
2591d962783eSJia Liu void cpu_loop(CPUOpenRISCState *env)
2592d962783eSJia Liu {
2593878096eeSAndreas Färber     CPUState *cs = CPU(openrisc_env_get_cpu(env));
2594a0adc417SRichard Henderson     int trapnr;
25957fe7231aSTimothy E Baldwin     abi_long ret;
2596a0adc417SRichard Henderson     target_siginfo_t info;
2597d962783eSJia Liu 
2598d962783eSJia Liu     for (;;) {
2599b040bc9cSPeter Maydell         cpu_exec_start(cs);
26008642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
2601b040bc9cSPeter Maydell         cpu_exec_end(cs);
2602d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
2603d962783eSJia Liu 
2604d962783eSJia Liu         switch (trapnr) {
2605d962783eSJia Liu         case EXCP_SYSCALL:
2606d962783eSJia Liu             env->pc += 4;   /* 0xc00; */
26077fe7231aSTimothy E Baldwin             ret = do_syscall(env,
2608d89e71e8SStafford Horne                              cpu_get_gpr(env, 11), /* return value       */
2609d89e71e8SStafford Horne                              cpu_get_gpr(env, 3),  /* r3 - r7 are params */
2610d89e71e8SStafford Horne                              cpu_get_gpr(env, 4),
2611d89e71e8SStafford Horne                              cpu_get_gpr(env, 5),
2612d89e71e8SStafford Horne                              cpu_get_gpr(env, 6),
2613d89e71e8SStafford Horne                              cpu_get_gpr(env, 7),
2614d89e71e8SStafford Horne                              cpu_get_gpr(env, 8), 0, 0);
26157fe7231aSTimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
26167fe7231aSTimothy E Baldwin                 env->pc -= 4;
26177fe7231aSTimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
2618d89e71e8SStafford Horne                 cpu_set_gpr(env, 11, ret);
26197fe7231aSTimothy E Baldwin             }
2620d962783eSJia Liu             break;
2621a0adc417SRichard Henderson         case EXCP_DPF:
2622a0adc417SRichard Henderson         case EXCP_IPF:
2623a0adc417SRichard Henderson         case EXCP_RANGE:
2624a0adc417SRichard Henderson             info.si_signo = TARGET_SIGSEGV;
2625a0adc417SRichard Henderson             info.si_errno = 0;
2626a0adc417SRichard Henderson             info.si_code = TARGET_SEGV_MAPERR;
2627a0adc417SRichard Henderson             info._sifields._sigfault._addr = env->pc;
2628a0adc417SRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2629a0adc417SRichard Henderson             break;
2630a0adc417SRichard Henderson         case EXCP_ALIGN:
2631a0adc417SRichard Henderson             info.si_signo = TARGET_SIGBUS;
2632a0adc417SRichard Henderson             info.si_errno = 0;
2633a0adc417SRichard Henderson             info.si_code = TARGET_BUS_ADRALN;
2634a0adc417SRichard Henderson             info._sifields._sigfault._addr = env->pc;
2635a0adc417SRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2636a0adc417SRichard Henderson             break;
2637a0adc417SRichard Henderson         case EXCP_ILLEGAL:
2638a0adc417SRichard Henderson             info.si_signo = TARGET_SIGILL;
2639a0adc417SRichard Henderson             info.si_errno = 0;
2640a0adc417SRichard Henderson             info.si_code = TARGET_ILL_ILLOPC;
2641a0adc417SRichard Henderson             info._sifields._sigfault._addr = env->pc;
2642a0adc417SRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2643a0adc417SRichard Henderson             break;
2644d962783eSJia Liu         case EXCP_FPE:
2645a0adc417SRichard Henderson             info.si_signo = TARGET_SIGFPE;
2646a0adc417SRichard Henderson             info.si_errno = 0;
2647a0adc417SRichard Henderson             info.si_code = 0;
2648a0adc417SRichard Henderson             info._sifields._sigfault._addr = env->pc;
2649a0adc417SRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2650d962783eSJia Liu             break;
2651a0adc417SRichard Henderson         case EXCP_INTERRUPT:
2652a0adc417SRichard Henderson             /* We processed the pending cpu work above.  */
2653d962783eSJia Liu             break;
2654a0adc417SRichard Henderson         case EXCP_DEBUG:
2655a0adc417SRichard Henderson             trapnr = gdb_handlesig(cs, TARGET_SIGTRAP);
2656a0adc417SRichard Henderson             if (trapnr) {
2657a0adc417SRichard Henderson                 info.si_signo = trapnr;
2658a0adc417SRichard Henderson                 info.si_errno = 0;
2659a0adc417SRichard Henderson                 info.si_code = TARGET_TRAP_BRKPT;
2660a0adc417SRichard Henderson                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2661a0adc417SRichard Henderson             }
2662d962783eSJia Liu             break;
2663fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
2664fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
2665fdbc2b57SRichard Henderson             break;
2666d962783eSJia Liu         default:
2667a0adc417SRichard Henderson             g_assert_not_reached();
2668d962783eSJia Liu         }
2669d962783eSJia Liu         process_pending_signals(env);
2670d962783eSJia Liu     }
2671d962783eSJia Liu }
2672d962783eSJia Liu 
2673d962783eSJia Liu #endif /* TARGET_OPENRISC */
2674d962783eSJia Liu 
2675fdf9b3e8Sbellard #ifdef TARGET_SH4
267605390248SAndreas Färber void cpu_loop(CPUSH4State *env)
2677fdf9b3e8Sbellard {
2678878096eeSAndreas Färber     CPUState *cs = CPU(sh_env_get_cpu(env));
2679fdf9b3e8Sbellard     int trapnr, ret;
2680c227f099SAnthony Liguori     target_siginfo_t info;
2681fdf9b3e8Sbellard 
2682fdf9b3e8Sbellard     while (1) {
2683b040bc9cSPeter Maydell         cpu_exec_start(cs);
26848642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
2685b040bc9cSPeter Maydell         cpu_exec_end(cs);
2686d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
2687fdf9b3e8Sbellard 
2688fdf9b3e8Sbellard         switch (trapnr) {
2689fdf9b3e8Sbellard         case 0x160:
26900b6d3ae0Saurel32             env->pc += 2;
2691fdf9b3e8Sbellard             ret = do_syscall(env,
26929c2a9ea1Spbrook                              env->gregs[3],
26939c2a9ea1Spbrook                              env->gregs[4],
26949c2a9ea1Spbrook                              env->gregs[5],
26959c2a9ea1Spbrook                              env->gregs[6],
26969c2a9ea1Spbrook                              env->gregs[7],
26979c2a9ea1Spbrook                              env->gregs[0],
26985945cfcbSPeter Maydell                              env->gregs[1],
26995945cfcbSPeter Maydell                              0, 0);
2700ba412496STimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
2701ba412496STimothy E Baldwin                 env->pc -= 2;
2702ba412496STimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
27039c2a9ea1Spbrook                 env->gregs[0] = ret;
2704ba412496STimothy E Baldwin             }
2705fdf9b3e8Sbellard             break;
2706c3b5bc8aSths         case EXCP_INTERRUPT:
2707c3b5bc8aSths             /* just indicate that signals should be handled asap */
2708c3b5bc8aSths             break;
2709355fb23dSpbrook         case EXCP_DEBUG:
2710355fb23dSpbrook             {
2711355fb23dSpbrook                 int sig;
2712355fb23dSpbrook 
2713db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
2714355fb23dSpbrook                 if (sig)
2715355fb23dSpbrook                   {
2716355fb23dSpbrook                     info.si_signo = sig;
2717355fb23dSpbrook                     info.si_errno = 0;
2718355fb23dSpbrook                     info.si_code = TARGET_TRAP_BRKPT;
27199d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2720355fb23dSpbrook                   }
2721355fb23dSpbrook             }
2722355fb23dSpbrook             break;
2723c3b5bc8aSths 	case 0xa0:
2724c3b5bc8aSths 	case 0xc0:
2725a86b3c64SChen Gang S             info.si_signo = TARGET_SIGSEGV;
2726c3b5bc8aSths             info.si_errno = 0;
2727c3b5bc8aSths             info.si_code = TARGET_SEGV_MAPERR;
2728c3b5bc8aSths             info._sifields._sigfault._addr = env->tea;
27299d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2730c3b5bc8aSths 	    break;
2731c3b5bc8aSths 
2732fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
2733fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
2734fdbc2b57SRichard Henderson             break;
2735fdf9b3e8Sbellard         default:
2736fdf9b3e8Sbellard             printf ("Unhandled trap: 0x%x\n", trapnr);
2737878096eeSAndreas Färber             cpu_dump_state(cs, stderr, fprintf, 0);
27384d1275c2SRiku Voipio             exit(EXIT_FAILURE);
2739fdf9b3e8Sbellard         }
2740fdf9b3e8Sbellard         process_pending_signals (env);
2741fdf9b3e8Sbellard     }
2742fdf9b3e8Sbellard }
2743fdf9b3e8Sbellard #endif
2744fdf9b3e8Sbellard 
274548733d19Sths #ifdef TARGET_CRIS
274605390248SAndreas Färber void cpu_loop(CPUCRISState *env)
274748733d19Sths {
2748878096eeSAndreas Färber     CPUState *cs = CPU(cris_env_get_cpu(env));
274948733d19Sths     int trapnr, ret;
2750c227f099SAnthony Liguori     target_siginfo_t info;
275148733d19Sths 
275248733d19Sths     while (1) {
2753b040bc9cSPeter Maydell         cpu_exec_start(cs);
27548642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
2755b040bc9cSPeter Maydell         cpu_exec_end(cs);
2756d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
2757d148d90eSSergey Fedorov 
275848733d19Sths         switch (trapnr) {
275948733d19Sths         case 0xaa:
276048733d19Sths             {
2761a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGSEGV;
276248733d19Sths                 info.si_errno = 0;
276348733d19Sths                 /* XXX: check env->error_code */
276448733d19Sths                 info.si_code = TARGET_SEGV_MAPERR;
2765e00c1e71Sedgar_igl                 info._sifields._sigfault._addr = env->pregs[PR_EDA];
27669d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
276748733d19Sths             }
276848733d19Sths             break;
2769b6d3abdaSedgar_igl 	case EXCP_INTERRUPT:
2770b6d3abdaSedgar_igl 	  /* just indicate that signals should be handled asap */
2771b6d3abdaSedgar_igl 	  break;
277248733d19Sths         case EXCP_BREAK:
277348733d19Sths             ret = do_syscall(env,
277448733d19Sths                              env->regs[9],
277548733d19Sths                              env->regs[10],
277648733d19Sths                              env->regs[11],
277748733d19Sths                              env->regs[12],
277848733d19Sths                              env->regs[13],
277948733d19Sths                              env->pregs[7],
27805945cfcbSPeter Maydell                              env->pregs[11],
27815945cfcbSPeter Maydell                              0, 0);
278262050865STimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
278362050865STimothy E Baldwin                 env->pc -= 2;
278462050865STimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
278548733d19Sths                 env->regs[10] = ret;
278662050865STimothy E Baldwin             }
278748733d19Sths             break;
278848733d19Sths         case EXCP_DEBUG:
278948733d19Sths             {
279048733d19Sths                 int sig;
279148733d19Sths 
2792db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
279348733d19Sths                 if (sig)
279448733d19Sths                   {
279548733d19Sths                     info.si_signo = sig;
279648733d19Sths                     info.si_errno = 0;
279748733d19Sths                     info.si_code = TARGET_TRAP_BRKPT;
27989d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
279948733d19Sths                   }
280048733d19Sths             }
280148733d19Sths             break;
2802fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
2803fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
2804fdbc2b57SRichard Henderson             break;
280548733d19Sths         default:
280648733d19Sths             printf ("Unhandled trap: 0x%x\n", trapnr);
2807878096eeSAndreas Färber             cpu_dump_state(cs, stderr, fprintf, 0);
28084d1275c2SRiku Voipio             exit(EXIT_FAILURE);
280948733d19Sths         }
281048733d19Sths         process_pending_signals (env);
281148733d19Sths     }
281248733d19Sths }
281348733d19Sths #endif
281448733d19Sths 
2815b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
281605390248SAndreas Färber void cpu_loop(CPUMBState *env)
2817b779e29eSEdgar E. Iglesias {
2818878096eeSAndreas Färber     CPUState *cs = CPU(mb_env_get_cpu(env));
2819b779e29eSEdgar E. Iglesias     int trapnr, ret;
2820c227f099SAnthony Liguori     target_siginfo_t info;
2821b779e29eSEdgar E. Iglesias 
2822b779e29eSEdgar E. Iglesias     while (1) {
2823b040bc9cSPeter Maydell         cpu_exec_start(cs);
28248642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
2825b040bc9cSPeter Maydell         cpu_exec_end(cs);
2826d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
2827d148d90eSSergey Fedorov 
2828b779e29eSEdgar E. Iglesias         switch (trapnr) {
2829b779e29eSEdgar E. Iglesias         case 0xaa:
2830b779e29eSEdgar E. Iglesias             {
2831a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGSEGV;
2832b779e29eSEdgar E. Iglesias                 info.si_errno = 0;
2833b779e29eSEdgar E. Iglesias                 /* XXX: check env->error_code */
2834b779e29eSEdgar E. Iglesias                 info.si_code = TARGET_SEGV_MAPERR;
2835b779e29eSEdgar E. Iglesias                 info._sifields._sigfault._addr = 0;
28369d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2837b779e29eSEdgar E. Iglesias             }
2838b779e29eSEdgar E. Iglesias             break;
2839b779e29eSEdgar E. Iglesias 	case EXCP_INTERRUPT:
2840b779e29eSEdgar E. Iglesias 	  /* just indicate that signals should be handled asap */
2841b779e29eSEdgar E. Iglesias 	  break;
2842b779e29eSEdgar E. Iglesias         case EXCP_BREAK:
2843b779e29eSEdgar E. Iglesias             /* Return address is 4 bytes after the call.  */
2844b779e29eSEdgar E. Iglesias             env->regs[14] += 4;
2845d7dce494SEdgar E. Iglesias             env->sregs[SR_PC] = env->regs[14];
2846b779e29eSEdgar E. Iglesias             ret = do_syscall(env,
2847b779e29eSEdgar E. Iglesias                              env->regs[12],
2848b779e29eSEdgar E. Iglesias                              env->regs[5],
2849b779e29eSEdgar E. Iglesias                              env->regs[6],
2850b779e29eSEdgar E. Iglesias                              env->regs[7],
2851b779e29eSEdgar E. Iglesias                              env->regs[8],
2852b779e29eSEdgar E. Iglesias                              env->regs[9],
28535945cfcbSPeter Maydell                              env->regs[10],
28545945cfcbSPeter Maydell                              0, 0);
28554134ecfeSTimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
28564134ecfeSTimothy E Baldwin                 /* Wind back to before the syscall. */
28574134ecfeSTimothy E Baldwin                 env->sregs[SR_PC] -= 4;
28584134ecfeSTimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
2859b779e29eSEdgar E. Iglesias                 env->regs[3] = ret;
28604134ecfeSTimothy E Baldwin             }
2861d7749ab7SPeter Maydell             /* All syscall exits result in guest r14 being equal to the
2862d7749ab7SPeter Maydell              * PC we return to, because the kernel syscall exit "rtbd" does
2863d7749ab7SPeter Maydell              * this. (This is true even for sigreturn(); note that r14 is
2864d7749ab7SPeter Maydell              * not a userspace-usable register, as the kernel may clobber it
2865d7749ab7SPeter Maydell              * at any point.)
2866d7749ab7SPeter Maydell              */
2867d7749ab7SPeter Maydell             env->regs[14] = env->sregs[SR_PC];
2868b779e29eSEdgar E. Iglesias             break;
2869b76da7e3SEdgar E. Iglesias         case EXCP_HW_EXCP:
2870b76da7e3SEdgar E. Iglesias             env->regs[17] = env->sregs[SR_PC] + 4;
2871b76da7e3SEdgar E. Iglesias             if (env->iflags & D_FLAG) {
2872b76da7e3SEdgar E. Iglesias                 env->sregs[SR_ESR] |= 1 << 12;
2873b76da7e3SEdgar E. Iglesias                 env->sregs[SR_PC] -= 4;
2874b76da7e3SEdgar E. Iglesias                 /* FIXME: if branch was immed, replay the imm as well.  */
2875b76da7e3SEdgar E. Iglesias             }
2876b76da7e3SEdgar E. Iglesias 
2877b76da7e3SEdgar E. Iglesias             env->iflags &= ~(IMM_FLAG | D_FLAG);
2878b76da7e3SEdgar E. Iglesias 
2879b76da7e3SEdgar E. Iglesias             switch (env->sregs[SR_ESR] & 31) {
288022a78d64SEdgar E. Iglesias                 case ESR_EC_DIVZERO:
2881a86b3c64SChen Gang S                     info.si_signo = TARGET_SIGFPE;
288222a78d64SEdgar E. Iglesias                     info.si_errno = 0;
288322a78d64SEdgar E. Iglesias                     info.si_code = TARGET_FPE_FLTDIV;
288422a78d64SEdgar E. Iglesias                     info._sifields._sigfault._addr = 0;
28859d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
288622a78d64SEdgar E. Iglesias                     break;
2887b76da7e3SEdgar E. Iglesias                 case ESR_EC_FPU:
2888a86b3c64SChen Gang S                     info.si_signo = TARGET_SIGFPE;
2889b76da7e3SEdgar E. Iglesias                     info.si_errno = 0;
2890b76da7e3SEdgar E. Iglesias                     if (env->sregs[SR_FSR] & FSR_IO) {
2891b76da7e3SEdgar E. Iglesias                         info.si_code = TARGET_FPE_FLTINV;
2892b76da7e3SEdgar E. Iglesias                     }
2893b76da7e3SEdgar E. Iglesias                     if (env->sregs[SR_FSR] & FSR_DZ) {
2894b76da7e3SEdgar E. Iglesias                         info.si_code = TARGET_FPE_FLTDIV;
2895b76da7e3SEdgar E. Iglesias                     }
2896b76da7e3SEdgar E. Iglesias                     info._sifields._sigfault._addr = 0;
28979d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2898b76da7e3SEdgar E. Iglesias                     break;
2899b76da7e3SEdgar E. Iglesias                 default:
2900b76da7e3SEdgar E. Iglesias                     printf ("Unhandled hw-exception: 0x%x\n",
29012e42d52dSEdgar E. Iglesias                             env->sregs[SR_ESR] & ESR_EC_MASK);
2902878096eeSAndreas Färber                     cpu_dump_state(cs, stderr, fprintf, 0);
29034d1275c2SRiku Voipio                     exit(EXIT_FAILURE);
2904b76da7e3SEdgar E. Iglesias                     break;
2905b76da7e3SEdgar E. Iglesias             }
2906b76da7e3SEdgar E. Iglesias             break;
2907b779e29eSEdgar E. Iglesias         case EXCP_DEBUG:
2908b779e29eSEdgar E. Iglesias             {
2909b779e29eSEdgar E. Iglesias                 int sig;
2910b779e29eSEdgar E. Iglesias 
2911db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
2912b779e29eSEdgar E. Iglesias                 if (sig)
2913b779e29eSEdgar E. Iglesias                   {
2914b779e29eSEdgar E. Iglesias                     info.si_signo = sig;
2915b779e29eSEdgar E. Iglesias                     info.si_errno = 0;
2916b779e29eSEdgar E. Iglesias                     info.si_code = TARGET_TRAP_BRKPT;
29179d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2918b779e29eSEdgar E. Iglesias                   }
2919b779e29eSEdgar E. Iglesias             }
2920b779e29eSEdgar E. Iglesias             break;
2921fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
2922fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
2923fdbc2b57SRichard Henderson             break;
2924b779e29eSEdgar E. Iglesias         default:
2925b779e29eSEdgar E. Iglesias             printf ("Unhandled trap: 0x%x\n", trapnr);
2926878096eeSAndreas Färber             cpu_dump_state(cs, stderr, fprintf, 0);
29274d1275c2SRiku Voipio             exit(EXIT_FAILURE);
2928b779e29eSEdgar E. Iglesias         }
2929b779e29eSEdgar E. Iglesias         process_pending_signals (env);
2930b779e29eSEdgar E. Iglesias     }
2931b779e29eSEdgar E. Iglesias }
2932b779e29eSEdgar E. Iglesias #endif
2933b779e29eSEdgar E. Iglesias 
2934e6e5906bSpbrook #ifdef TARGET_M68K
2935e6e5906bSpbrook 
2936e6e5906bSpbrook void cpu_loop(CPUM68KState *env)
2937e6e5906bSpbrook {
2938878096eeSAndreas Färber     CPUState *cs = CPU(m68k_env_get_cpu(env));
2939e6e5906bSpbrook     int trapnr;
2940e6e5906bSpbrook     unsigned int n;
2941c227f099SAnthony Liguori     target_siginfo_t info;
29420429a971SAndreas Färber     TaskState *ts = cs->opaque;
2943e6e5906bSpbrook 
2944e6e5906bSpbrook     for(;;) {
2945b040bc9cSPeter Maydell         cpu_exec_start(cs);
29468642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
2947b040bc9cSPeter Maydell         cpu_exec_end(cs);
2948d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
2949d148d90eSSergey Fedorov 
2950e6e5906bSpbrook         switch(trapnr) {
2951e6e5906bSpbrook         case EXCP_ILLEGAL:
2952e6e5906bSpbrook             {
2953e6e5906bSpbrook                 if (ts->sim_syscalls) {
2954e6e5906bSpbrook                     uint16_t nr;
2955d8d5119cSPeter Maydell                     get_user_u16(nr, env->pc + 2);
2956e6e5906bSpbrook                     env->pc += 4;
2957e6e5906bSpbrook                     do_m68k_simcall(env, nr);
2958e6e5906bSpbrook                 } else {
2959e6e5906bSpbrook                     goto do_sigill;
2960e6e5906bSpbrook                 }
2961e6e5906bSpbrook             }
2962e6e5906bSpbrook             break;
2963a87295e8Spbrook         case EXCP_HALT_INSN:
2964e6e5906bSpbrook             /* Semihosing syscall.  */
2965a87295e8Spbrook             env->pc += 4;
2966e6e5906bSpbrook             do_m68k_semihosting(env, env->dregs[0]);
2967e6e5906bSpbrook             break;
2968e6e5906bSpbrook         case EXCP_LINEA:
2969e6e5906bSpbrook         case EXCP_LINEF:
2970e6e5906bSpbrook         case EXCP_UNSUPPORTED:
2971e6e5906bSpbrook         do_sigill:
2972a86b3c64SChen Gang S             info.si_signo = TARGET_SIGILL;
2973e6e5906bSpbrook             info.si_errno = 0;
2974e6e5906bSpbrook             info.si_code = TARGET_ILL_ILLOPN;
2975e6e5906bSpbrook             info._sifields._sigfault._addr = env->pc;
29769d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
2977e6e5906bSpbrook             break;
29780ccb9c1dSLaurent Vivier         case EXCP_DIV0:
29790ccb9c1dSLaurent Vivier             info.si_signo = TARGET_SIGFPE;
29800ccb9c1dSLaurent Vivier             info.si_errno = 0;
29810ccb9c1dSLaurent Vivier             info.si_code = TARGET_FPE_INTDIV;
29820ccb9c1dSLaurent Vivier             info._sifields._sigfault._addr = env->pc;
29830ccb9c1dSLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
29840ccb9c1dSLaurent Vivier             break;
2985e6e5906bSpbrook         case EXCP_TRAP0:
2986e6e5906bSpbrook             {
29877ccb84a9STimothy E Baldwin                 abi_long ret;
2988e6e5906bSpbrook                 ts->sim_syscalls = 0;
2989e6e5906bSpbrook                 n = env->dregs[0];
2990e6e5906bSpbrook                 env->pc += 2;
29917ccb84a9STimothy E Baldwin                 ret = do_syscall(env,
2992e6e5906bSpbrook                                  n,
2993e6e5906bSpbrook                                  env->dregs[1],
2994e6e5906bSpbrook                                  env->dregs[2],
2995e6e5906bSpbrook                                  env->dregs[3],
2996e6e5906bSpbrook                                  env->dregs[4],
2997e6e5906bSpbrook                                  env->dregs[5],
29985945cfcbSPeter Maydell                                  env->aregs[0],
29995945cfcbSPeter Maydell                                  0, 0);
30007ccb84a9STimothy E Baldwin                 if (ret == -TARGET_ERESTARTSYS) {
30017ccb84a9STimothy E Baldwin                     env->pc -= 2;
30027ccb84a9STimothy E Baldwin                 } else if (ret != -TARGET_QEMU_ESIGRETURN) {
30037ccb84a9STimothy E Baldwin                     env->dregs[0] = ret;
30047ccb84a9STimothy E Baldwin                 }
3005e6e5906bSpbrook             }
3006e6e5906bSpbrook             break;
3007e6e5906bSpbrook         case EXCP_INTERRUPT:
3008e6e5906bSpbrook             /* just indicate that signals should be handled asap */
3009e6e5906bSpbrook             break;
3010e6e5906bSpbrook         case EXCP_ACCESS:
3011e6e5906bSpbrook             {
3012a86b3c64SChen Gang S                 info.si_signo = TARGET_SIGSEGV;
3013e6e5906bSpbrook                 info.si_errno = 0;
3014e6e5906bSpbrook                 /* XXX: check env->error_code */
3015e6e5906bSpbrook                 info.si_code = TARGET_SEGV_MAPERR;
3016e6e5906bSpbrook                 info._sifields._sigfault._addr = env->mmu.ar;
30179d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3018e6e5906bSpbrook             }
3019e6e5906bSpbrook             break;
3020e6e5906bSpbrook         case EXCP_DEBUG:
3021e6e5906bSpbrook             {
3022e6e5906bSpbrook                 int sig;
3023e6e5906bSpbrook 
3024db6b81d4SAndreas Färber                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
3025e6e5906bSpbrook                 if (sig)
3026e6e5906bSpbrook                   {
3027e6e5906bSpbrook                     info.si_signo = sig;
3028e6e5906bSpbrook                     info.si_errno = 0;
3029e6e5906bSpbrook                     info.si_code = TARGET_TRAP_BRKPT;
30309d2803f7SPeter Maydell                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3031e6e5906bSpbrook                   }
3032e6e5906bSpbrook             }
3033e6e5906bSpbrook             break;
3034fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
3035fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
3036fdbc2b57SRichard Henderson             break;
3037e6e5906bSpbrook         default:
3038120a9848SPaolo Bonzini             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
3039e6e5906bSpbrook             abort();
3040e6e5906bSpbrook         }
3041e6e5906bSpbrook         process_pending_signals(env);
3042e6e5906bSpbrook     }
3043e6e5906bSpbrook }
3044e6e5906bSpbrook #endif /* TARGET_M68K */
3045e6e5906bSpbrook 
30467a3148a9Sj_mayer #ifdef TARGET_ALPHA
304705390248SAndreas Färber void cpu_loop(CPUAlphaState *env)
30487a3148a9Sj_mayer {
3049878096eeSAndreas Färber     CPUState *cs = CPU(alpha_env_get_cpu(env));
3050e96efcfcSj_mayer     int trapnr;
3051c227f099SAnthony Liguori     target_siginfo_t info;
30526049f4f8SRichard Henderson     abi_long sysret;
30537a3148a9Sj_mayer 
30547a3148a9Sj_mayer     while (1) {
3055bcd2625dSRichard Henderson         bool arch_interrupt = true;
3056bcd2625dSRichard Henderson 
3057b040bc9cSPeter Maydell         cpu_exec_start(cs);
30588642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
3059b040bc9cSPeter Maydell         cpu_exec_end(cs);
3060d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
30617a3148a9Sj_mayer 
30627a3148a9Sj_mayer         switch (trapnr) {
30637a3148a9Sj_mayer         case EXCP_RESET:
30647a3148a9Sj_mayer             fprintf(stderr, "Reset requested. Exit\n");
30654d1275c2SRiku Voipio             exit(EXIT_FAILURE);
30667a3148a9Sj_mayer             break;
30677a3148a9Sj_mayer         case EXCP_MCHK:
30687a3148a9Sj_mayer             fprintf(stderr, "Machine check exception. Exit\n");
30694d1275c2SRiku Voipio             exit(EXIT_FAILURE);
30707a3148a9Sj_mayer             break;
307107b6c13bSRichard Henderson         case EXCP_SMP_INTERRUPT:
307207b6c13bSRichard Henderson         case EXCP_CLK_INTERRUPT:
307307b6c13bSRichard Henderson         case EXCP_DEV_INTERRUPT:
30747a3148a9Sj_mayer             fprintf(stderr, "External interrupt. Exit\n");
30754d1275c2SRiku Voipio             exit(EXIT_FAILURE);
30767a3148a9Sj_mayer             break;
307707b6c13bSRichard Henderson         case EXCP_MMFAULT:
30786049f4f8SRichard Henderson             info.si_signo = TARGET_SIGSEGV;
30796049f4f8SRichard Henderson             info.si_errno = 0;
3080129d8aa5SRichard Henderson             info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
30810be1d07cSRichard Henderson                             ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
3082129d8aa5SRichard Henderson             info._sifields._sigfault._addr = env->trap_arg0;
30839d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
30847a3148a9Sj_mayer             break;
30857a3148a9Sj_mayer         case EXCP_UNALIGN:
30866049f4f8SRichard Henderson             info.si_signo = TARGET_SIGBUS;
30876049f4f8SRichard Henderson             info.si_errno = 0;
30886049f4f8SRichard Henderson             info.si_code = TARGET_BUS_ADRALN;
3089129d8aa5SRichard Henderson             info._sifields._sigfault._addr = env->trap_arg0;
30909d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
30917a3148a9Sj_mayer             break;
30927a3148a9Sj_mayer         case EXCP_OPCDEC:
30936049f4f8SRichard Henderson         do_sigill:
30946049f4f8SRichard Henderson             info.si_signo = TARGET_SIGILL;
30956049f4f8SRichard Henderson             info.si_errno = 0;
30966049f4f8SRichard Henderson             info.si_code = TARGET_ILL_ILLOPC;
30976049f4f8SRichard Henderson             info._sifields._sigfault._addr = env->pc;
30989d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
30997a3148a9Sj_mayer             break;
310007b6c13bSRichard Henderson         case EXCP_ARITH:
310107b6c13bSRichard Henderson             info.si_signo = TARGET_SIGFPE;
310207b6c13bSRichard Henderson             info.si_errno = 0;
310307b6c13bSRichard Henderson             info.si_code = TARGET_FPE_FLTINV;
310407b6c13bSRichard Henderson             info._sifields._sigfault._addr = env->pc;
31059d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
310607b6c13bSRichard Henderson             break;
31077a3148a9Sj_mayer         case EXCP_FEN:
31086049f4f8SRichard Henderson             /* No-op.  Linux simply re-enables the FPU.  */
31097a3148a9Sj_mayer             break;
311007b6c13bSRichard Henderson         case EXCP_CALL_PAL:
311107b6c13bSRichard Henderson             switch (env->error_code) {
31126049f4f8SRichard Henderson             case 0x80:
31136049f4f8SRichard Henderson                 /* BPT */
31146049f4f8SRichard Henderson                 info.si_signo = TARGET_SIGTRAP;
31156049f4f8SRichard Henderson                 info.si_errno = 0;
31166049f4f8SRichard Henderson                 info.si_code = TARGET_TRAP_BRKPT;
31176049f4f8SRichard Henderson                 info._sifields._sigfault._addr = env->pc;
31189d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
31196049f4f8SRichard Henderson                 break;
31206049f4f8SRichard Henderson             case 0x81:
31216049f4f8SRichard Henderson                 /* BUGCHK */
31226049f4f8SRichard Henderson                 info.si_signo = TARGET_SIGTRAP;
31236049f4f8SRichard Henderson                 info.si_errno = 0;
31246049f4f8SRichard Henderson                 info.si_code = 0;
31256049f4f8SRichard Henderson                 info._sifields._sigfault._addr = env->pc;
31269d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
31276049f4f8SRichard Henderson                 break;
31286049f4f8SRichard Henderson             case 0x83:
31296049f4f8SRichard Henderson                 /* CALLSYS */
31306049f4f8SRichard Henderson                 trapnr = env->ir[IR_V0];
31316049f4f8SRichard Henderson                 sysret = do_syscall(env, trapnr,
31326049f4f8SRichard Henderson                                     env->ir[IR_A0], env->ir[IR_A1],
31336049f4f8SRichard Henderson                                     env->ir[IR_A2], env->ir[IR_A3],
31345945cfcbSPeter Maydell                                     env->ir[IR_A4], env->ir[IR_A5],
31355945cfcbSPeter Maydell                                     0, 0);
3136338c858cSTimothy E Baldwin                 if (sysret == -TARGET_ERESTARTSYS) {
3137338c858cSTimothy E Baldwin                     env->pc -= 4;
3138338c858cSTimothy E Baldwin                     break;
3139338c858cSTimothy E Baldwin                 }
3140338c858cSTimothy E Baldwin                 if (sysret == -TARGET_QEMU_ESIGRETURN) {
3141a5b3b13bSRichard Henderson                     break;
3142a5b3b13bSRichard Henderson                 }
3143a5b3b13bSRichard Henderson                 /* Syscall writes 0 to V0 to bypass error check, similar
31440e141977SRichard Henderson                    to how this is handled internal to Linux kernel.
31450e141977SRichard Henderson                    (Ab)use trapnr temporarily as boolean indicating error.  */
31460e141977SRichard Henderson                 trapnr = (env->ir[IR_V0] != 0 && sysret < 0);
31470e141977SRichard Henderson                 env->ir[IR_V0] = (trapnr ? -sysret : sysret);
31480e141977SRichard Henderson                 env->ir[IR_A3] = trapnr;
31496049f4f8SRichard Henderson                 break;
31506049f4f8SRichard Henderson             case 0x86:
31516049f4f8SRichard Henderson                 /* IMB */
31526049f4f8SRichard Henderson                 /* ??? We can probably elide the code using page_unprotect
31536049f4f8SRichard Henderson                    that is checking for self-modifying code.  Instead we
31546049f4f8SRichard Henderson                    could simply call tb_flush here.  Until we work out the
31556049f4f8SRichard Henderson                    changes required to turn off the extra write protection,
31566049f4f8SRichard Henderson                    this can be a no-op.  */
31576049f4f8SRichard Henderson                 break;
31586049f4f8SRichard Henderson             case 0x9E:
31596049f4f8SRichard Henderson                 /* RDUNIQUE */
31606049f4f8SRichard Henderson                 /* Handled in the translator for usermode.  */
31616049f4f8SRichard Henderson                 abort();
31626049f4f8SRichard Henderson             case 0x9F:
31636049f4f8SRichard Henderson                 /* WRUNIQUE */
31646049f4f8SRichard Henderson                 /* Handled in the translator for usermode.  */
31656049f4f8SRichard Henderson                 abort();
31666049f4f8SRichard Henderson             case 0xAA:
31676049f4f8SRichard Henderson                 /* GENTRAP */
31686049f4f8SRichard Henderson                 info.si_signo = TARGET_SIGFPE;
31696049f4f8SRichard Henderson                 switch (env->ir[IR_A0]) {
31706049f4f8SRichard Henderson                 case TARGET_GEN_INTOVF:
31716049f4f8SRichard Henderson                     info.si_code = TARGET_FPE_INTOVF;
31726049f4f8SRichard Henderson                     break;
31736049f4f8SRichard Henderson                 case TARGET_GEN_INTDIV:
31746049f4f8SRichard Henderson                     info.si_code = TARGET_FPE_INTDIV;
31756049f4f8SRichard Henderson                     break;
31766049f4f8SRichard Henderson                 case TARGET_GEN_FLTOVF:
31776049f4f8SRichard Henderson                     info.si_code = TARGET_FPE_FLTOVF;
31786049f4f8SRichard Henderson                     break;
31796049f4f8SRichard Henderson                 case TARGET_GEN_FLTUND:
31806049f4f8SRichard Henderson                     info.si_code = TARGET_FPE_FLTUND;
31816049f4f8SRichard Henderson                     break;
31826049f4f8SRichard Henderson                 case TARGET_GEN_FLTINV:
31836049f4f8SRichard Henderson                     info.si_code = TARGET_FPE_FLTINV;
31846049f4f8SRichard Henderson                     break;
31856049f4f8SRichard Henderson                 case TARGET_GEN_FLTINE:
31866049f4f8SRichard Henderson                     info.si_code = TARGET_FPE_FLTRES;
31876049f4f8SRichard Henderson                     break;
31886049f4f8SRichard Henderson                 case TARGET_GEN_ROPRAND:
31896049f4f8SRichard Henderson                     info.si_code = 0;
31906049f4f8SRichard Henderson                     break;
31916049f4f8SRichard Henderson                 default:
31926049f4f8SRichard Henderson                     info.si_signo = TARGET_SIGTRAP;
31936049f4f8SRichard Henderson                     info.si_code = 0;
31946049f4f8SRichard Henderson                     break;
31956049f4f8SRichard Henderson                 }
31966049f4f8SRichard Henderson                 info.si_errno = 0;
31976049f4f8SRichard Henderson                 info._sifields._sigfault._addr = env->pc;
31989d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
31996049f4f8SRichard Henderson                 break;
32006049f4f8SRichard Henderson             default:
32016049f4f8SRichard Henderson                 goto do_sigill;
32026049f4f8SRichard Henderson             }
32037a3148a9Sj_mayer             break;
32047a3148a9Sj_mayer         case EXCP_DEBUG:
3205db6b81d4SAndreas Färber             info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP);
32066049f4f8SRichard Henderson             if (info.si_signo) {
32077a3148a9Sj_mayer                 info.si_errno = 0;
32087a3148a9Sj_mayer                 info.si_code = TARGET_TRAP_BRKPT;
32099d2803f7SPeter Maydell                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3210bcd2625dSRichard Henderson             } else {
3211bcd2625dSRichard Henderson                 arch_interrupt = false;
32127a3148a9Sj_mayer             }
32137a3148a9Sj_mayer             break;
3214d0f20495SRichard Henderson         case EXCP_INTERRUPT:
3215d0f20495SRichard Henderson             /* Just indicate that signals should be handled asap.  */
3216d0f20495SRichard Henderson             break;
3217fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
3218fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
3219bcd2625dSRichard Henderson             arch_interrupt = false;
3220fdbc2b57SRichard Henderson             break;
32217a3148a9Sj_mayer         default:
32227a3148a9Sj_mayer             printf ("Unhandled trap: 0x%x\n", trapnr);
3223878096eeSAndreas Färber             cpu_dump_state(cs, stderr, fprintf, 0);
32244d1275c2SRiku Voipio             exit(EXIT_FAILURE);
32257a3148a9Sj_mayer         }
32267a3148a9Sj_mayer         process_pending_signals (env);
3227bcd2625dSRichard Henderson 
3228bcd2625dSRichard Henderson         /* Most of the traps imply a transition through PALcode, which
3229bcd2625dSRichard Henderson            implies an REI instruction has been executed.  Which means
3230bcd2625dSRichard Henderson            that RX and LOCK_ADDR should be cleared.  But there are a
3231bcd2625dSRichard Henderson            few exceptions for traps internal to QEMU.  */
3232bcd2625dSRichard Henderson         if (arch_interrupt) {
3233bcd2625dSRichard Henderson             env->flags &= ~ENV_FLAG_RX_FLAG;
3234bcd2625dSRichard Henderson             env->lock_addr = -1;
3235bcd2625dSRichard Henderson         }
32367a3148a9Sj_mayer     }
32377a3148a9Sj_mayer }
32387a3148a9Sj_mayer #endif /* TARGET_ALPHA */
32397a3148a9Sj_mayer 
3240a4c075f1SUlrich Hecht #ifdef TARGET_S390X
3241a4c075f1SUlrich Hecht void cpu_loop(CPUS390XState *env)
3242a4c075f1SUlrich Hecht {
3243878096eeSAndreas Färber     CPUState *cs = CPU(s390_env_get_cpu(env));
3244d5a103cdSRichard Henderson     int trapnr, n, sig;
3245a4c075f1SUlrich Hecht     target_siginfo_t info;
3246d5a103cdSRichard Henderson     target_ulong addr;
324747405ab6STimothy E Baldwin     abi_long ret;
3248a4c075f1SUlrich Hecht 
3249a4c075f1SUlrich Hecht     while (1) {
3250b040bc9cSPeter Maydell         cpu_exec_start(cs);
32518642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
3252b040bc9cSPeter Maydell         cpu_exec_end(cs);
3253d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
3254d148d90eSSergey Fedorov 
3255a4c075f1SUlrich Hecht         switch (trapnr) {
3256a4c075f1SUlrich Hecht         case EXCP_INTERRUPT:
3257d5a103cdSRichard Henderson             /* Just indicate that signals should be handled asap.  */
3258a4c075f1SUlrich Hecht             break;
3259a4c075f1SUlrich Hecht 
3260a4c075f1SUlrich Hecht         case EXCP_SVC:
3261d5a103cdSRichard Henderson             n = env->int_svc_code;
3262a4c075f1SUlrich Hecht             if (!n) {
3263a4c075f1SUlrich Hecht                 /* syscalls > 255 */
3264a4c075f1SUlrich Hecht                 n = env->regs[1];
3265a4c075f1SUlrich Hecht             }
3266d5a103cdSRichard Henderson             env->psw.addr += env->int_svc_ilen;
326747405ab6STimothy E Baldwin             ret = do_syscall(env, n, env->regs[2], env->regs[3],
3268d5a103cdSRichard Henderson                              env->regs[4], env->regs[5],
3269d5a103cdSRichard Henderson                              env->regs[6], env->regs[7], 0, 0);
327047405ab6STimothy E Baldwin             if (ret == -TARGET_ERESTARTSYS) {
327147405ab6STimothy E Baldwin                 env->psw.addr -= env->int_svc_ilen;
327247405ab6STimothy E Baldwin             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
327347405ab6STimothy E Baldwin                 env->regs[2] = ret;
327447405ab6STimothy E Baldwin             }
3275d5a103cdSRichard Henderson             break;
3276d5a103cdSRichard Henderson 
3277d5a103cdSRichard Henderson         case EXCP_DEBUG:
3278db6b81d4SAndreas Färber             sig = gdb_handlesig(cs, TARGET_SIGTRAP);
3279d5a103cdSRichard Henderson             if (sig) {
3280d5a103cdSRichard Henderson                 n = TARGET_TRAP_BRKPT;
3281d5a103cdSRichard Henderson                 goto do_signal_pc;
3282a4c075f1SUlrich Hecht             }
3283a4c075f1SUlrich Hecht             break;
3284d5a103cdSRichard Henderson         case EXCP_PGM:
3285d5a103cdSRichard Henderson             n = env->int_pgm_code;
3286d5a103cdSRichard Henderson             switch (n) {
3287d5a103cdSRichard Henderson             case PGM_OPERATION:
3288d5a103cdSRichard Henderson             case PGM_PRIVILEGED:
3289a86b3c64SChen Gang S                 sig = TARGET_SIGILL;
3290d5a103cdSRichard Henderson                 n = TARGET_ILL_ILLOPC;
3291d5a103cdSRichard Henderson                 goto do_signal_pc;
3292d5a103cdSRichard Henderson             case PGM_PROTECTION:
3293d5a103cdSRichard Henderson             case PGM_ADDRESSING:
3294a86b3c64SChen Gang S                 sig = TARGET_SIGSEGV;
3295a4c075f1SUlrich Hecht                 /* XXX: check env->error_code */
3296d5a103cdSRichard Henderson                 n = TARGET_SEGV_MAPERR;
3297d5a103cdSRichard Henderson                 addr = env->__excp_addr;
3298d5a103cdSRichard Henderson                 goto do_signal;
3299d5a103cdSRichard Henderson             case PGM_EXECUTE:
3300d5a103cdSRichard Henderson             case PGM_SPECIFICATION:
3301d5a103cdSRichard Henderson             case PGM_SPECIAL_OP:
3302d5a103cdSRichard Henderson             case PGM_OPERAND:
3303d5a103cdSRichard Henderson             do_sigill_opn:
3304a86b3c64SChen Gang S                 sig = TARGET_SIGILL;
3305d5a103cdSRichard Henderson                 n = TARGET_ILL_ILLOPN;
3306d5a103cdSRichard Henderson                 goto do_signal_pc;
3307d5a103cdSRichard Henderson 
3308d5a103cdSRichard Henderson             case PGM_FIXPT_OVERFLOW:
3309a86b3c64SChen Gang S                 sig = TARGET_SIGFPE;
3310d5a103cdSRichard Henderson                 n = TARGET_FPE_INTOVF;
3311d5a103cdSRichard Henderson                 goto do_signal_pc;
3312d5a103cdSRichard Henderson             case PGM_FIXPT_DIVIDE:
3313a86b3c64SChen Gang S                 sig = TARGET_SIGFPE;
3314d5a103cdSRichard Henderson                 n = TARGET_FPE_INTDIV;
3315d5a103cdSRichard Henderson                 goto do_signal_pc;
3316d5a103cdSRichard Henderson 
3317d5a103cdSRichard Henderson             case PGM_DATA:
3318d5a103cdSRichard Henderson                 n = (env->fpc >> 8) & 0xff;
3319d5a103cdSRichard Henderson                 if (n == 0xff) {
3320d5a103cdSRichard Henderson                     /* compare-and-trap */
3321d5a103cdSRichard Henderson                     goto do_sigill_opn;
3322d5a103cdSRichard Henderson                 } else {
3323d5a103cdSRichard Henderson                     /* An IEEE exception, simulated or otherwise.  */
3324d5a103cdSRichard Henderson                     if (n & 0x80) {
3325d5a103cdSRichard Henderson                         n = TARGET_FPE_FLTINV;
3326d5a103cdSRichard Henderson                     } else if (n & 0x40) {
3327d5a103cdSRichard Henderson                         n = TARGET_FPE_FLTDIV;
3328d5a103cdSRichard Henderson                     } else if (n & 0x20) {
3329d5a103cdSRichard Henderson                         n = TARGET_FPE_FLTOVF;
3330d5a103cdSRichard Henderson                     } else if (n & 0x10) {
3331d5a103cdSRichard Henderson                         n = TARGET_FPE_FLTUND;
3332d5a103cdSRichard Henderson                     } else if (n & 0x08) {
3333d5a103cdSRichard Henderson                         n = TARGET_FPE_FLTRES;
3334d5a103cdSRichard Henderson                     } else {
3335d5a103cdSRichard Henderson                         /* ??? Quantum exception; BFP, DFP error.  */
3336d5a103cdSRichard Henderson                         goto do_sigill_opn;
3337a4c075f1SUlrich Hecht                     }
3338a86b3c64SChen Gang S                     sig = TARGET_SIGFPE;
3339d5a103cdSRichard Henderson                     goto do_signal_pc;
3340a4c075f1SUlrich Hecht                 }
3341d5a103cdSRichard Henderson 
3342a4c075f1SUlrich Hecht             default:
3343d5a103cdSRichard Henderson                 fprintf(stderr, "Unhandled program exception: %#x\n", n);
3344878096eeSAndreas Färber                 cpu_dump_state(cs, stderr, fprintf, 0);
33454d1275c2SRiku Voipio                 exit(EXIT_FAILURE);
3346d5a103cdSRichard Henderson             }
3347d5a103cdSRichard Henderson             break;
3348d5a103cdSRichard Henderson 
3349d5a103cdSRichard Henderson         do_signal_pc:
3350d5a103cdSRichard Henderson             addr = env->psw.addr;
3351d5a103cdSRichard Henderson         do_signal:
3352d5a103cdSRichard Henderson             info.si_signo = sig;
3353d5a103cdSRichard Henderson             info.si_errno = 0;
3354d5a103cdSRichard Henderson             info.si_code = n;
3355d5a103cdSRichard Henderson             info._sifields._sigfault._addr = addr;
33569d2803f7SPeter Maydell             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3357d5a103cdSRichard Henderson             break;
3358d5a103cdSRichard Henderson 
3359fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
3360fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
3361fdbc2b57SRichard Henderson             break;
3362d5a103cdSRichard Henderson         default:
3363d5a103cdSRichard Henderson             fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
3364878096eeSAndreas Färber             cpu_dump_state(cs, stderr, fprintf, 0);
33654d1275c2SRiku Voipio             exit(EXIT_FAILURE);
3366a4c075f1SUlrich Hecht         }
3367a4c075f1SUlrich Hecht         process_pending_signals (env);
3368a4c075f1SUlrich Hecht     }
3369a4c075f1SUlrich Hecht }
3370a4c075f1SUlrich Hecht 
3371a4c075f1SUlrich Hecht #endif /* TARGET_S390X */
3372a4c075f1SUlrich Hecht 
3373b16189b2SChen Gang #ifdef TARGET_TILEGX
3374b16189b2SChen Gang 
3375b16189b2SChen Gang static void gen_sigill_reg(CPUTLGState *env)
3376b16189b2SChen Gang {
3377b16189b2SChen Gang     target_siginfo_t info;
3378b16189b2SChen Gang 
3379b16189b2SChen Gang     info.si_signo = TARGET_SIGILL;
3380b16189b2SChen Gang     info.si_errno = 0;
3381b16189b2SChen Gang     info.si_code = TARGET_ILL_PRVREG;
3382b16189b2SChen Gang     info._sifields._sigfault._addr = env->pc;
33839d2803f7SPeter Maydell     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3384b16189b2SChen Gang }
3385b16189b2SChen Gang 
3386a0577d2aSRichard Henderson static void do_signal(CPUTLGState *env, int signo, int sigcode)
3387dd8070d8SChen Gang {
3388dd8070d8SChen Gang     target_siginfo_t info;
3389dd8070d8SChen Gang 
3390a0577d2aSRichard Henderson     info.si_signo = signo;
3391dd8070d8SChen Gang     info.si_errno = 0;
3392dd8070d8SChen Gang     info._sifields._sigfault._addr = env->pc;
3393a0577d2aSRichard Henderson 
3394a0577d2aSRichard Henderson     if (signo == TARGET_SIGSEGV) {
3395a0577d2aSRichard Henderson         /* The passed in sigcode is a dummy; check for a page mapping
3396a0577d2aSRichard Henderson            and pass either MAPERR or ACCERR.  */
3397a0577d2aSRichard Henderson         target_ulong addr = env->excaddr;
3398a0577d2aSRichard Henderson         info._sifields._sigfault._addr = addr;
3399a0577d2aSRichard Henderson         if (page_check_range(addr, 1, PAGE_VALID) < 0) {
3400a0577d2aSRichard Henderson             sigcode = TARGET_SEGV_MAPERR;
3401a0577d2aSRichard Henderson         } else {
3402a0577d2aSRichard Henderson             sigcode = TARGET_SEGV_ACCERR;
3403a0577d2aSRichard Henderson         }
3404a0577d2aSRichard Henderson     }
3405a0577d2aSRichard Henderson     info.si_code = sigcode;
3406a0577d2aSRichard Henderson 
34079d2803f7SPeter Maydell     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
3408dd8070d8SChen Gang }
3409dd8070d8SChen Gang 
3410a0577d2aSRichard Henderson static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr)
3411a0577d2aSRichard Henderson {
3412a0577d2aSRichard Henderson     env->excaddr = addr;
3413a0577d2aSRichard Henderson     do_signal(env, TARGET_SIGSEGV, 0);
3414a0577d2aSRichard Henderson }
3415a0577d2aSRichard Henderson 
34160583b233SRichard Henderson static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val)
34170583b233SRichard Henderson {
34180583b233SRichard Henderson     if (unlikely(reg >= TILEGX_R_COUNT)) {
34190583b233SRichard Henderson         switch (reg) {
34200583b233SRichard Henderson         case TILEGX_R_SN:
34210583b233SRichard Henderson         case TILEGX_R_ZERO:
34220583b233SRichard Henderson             return;
34230583b233SRichard Henderson         case TILEGX_R_IDN0:
34240583b233SRichard Henderson         case TILEGX_R_IDN1:
34250583b233SRichard Henderson         case TILEGX_R_UDN0:
34260583b233SRichard Henderson         case TILEGX_R_UDN1:
34270583b233SRichard Henderson         case TILEGX_R_UDN2:
34280583b233SRichard Henderson         case TILEGX_R_UDN3:
34290583b233SRichard Henderson             gen_sigill_reg(env);
34300583b233SRichard Henderson             return;
34310583b233SRichard Henderson         default:
34320583b233SRichard Henderson             g_assert_not_reached();
34330583b233SRichard Henderson         }
34340583b233SRichard Henderson     }
34350583b233SRichard Henderson     env->regs[reg] = val;
34360583b233SRichard Henderson }
34370583b233SRichard Henderson 
34380583b233SRichard Henderson /*
34390583b233SRichard Henderson  * Compare the 8-byte contents of the CmpValue SPR with the 8-byte value in
34400583b233SRichard Henderson  * memory at the address held in the first source register. If the values are
34410583b233SRichard Henderson  * not equal, then no memory operation is performed. If the values are equal,
34420583b233SRichard Henderson  * the 8-byte quantity from the second source register is written into memory
34430583b233SRichard Henderson  * at the address held in the first source register. In either case, the result
34440583b233SRichard Henderson  * of the instruction is the value read from memory. The compare and write to
34450583b233SRichard Henderson  * memory are atomic and thus can be used for synchronization purposes. This
34460583b233SRichard Henderson  * instruction only operates for addresses aligned to a 8-byte boundary.
34470583b233SRichard Henderson  * Unaligned memory access causes an Unaligned Data Reference interrupt.
34480583b233SRichard Henderson  *
34490583b233SRichard Henderson  * Functional Description (64-bit)
34500583b233SRichard Henderson  *       uint64_t memVal = memoryReadDoubleWord (rf[SrcA]);
34510583b233SRichard Henderson  *       rf[Dest] = memVal;
34520583b233SRichard Henderson  *       if (memVal == SPR[CmpValueSPR])
34530583b233SRichard Henderson  *           memoryWriteDoubleWord (rf[SrcA], rf[SrcB]);
34540583b233SRichard Henderson  *
34550583b233SRichard Henderson  * Functional Description (32-bit)
34560583b233SRichard Henderson  *       uint64_t memVal = signExtend32 (memoryReadWord (rf[SrcA]));
34570583b233SRichard Henderson  *       rf[Dest] = memVal;
34580583b233SRichard Henderson  *       if (memVal == signExtend32 (SPR[CmpValueSPR]))
34590583b233SRichard Henderson  *           memoryWriteWord (rf[SrcA], rf[SrcB]);
34600583b233SRichard Henderson  *
34610583b233SRichard Henderson  *
34620583b233SRichard Henderson  * This function also processes exch and exch4 which need not process SPR.
34630583b233SRichard Henderson  */
34640583b233SRichard Henderson static void do_exch(CPUTLGState *env, bool quad, bool cmp)
34650583b233SRichard Henderson {
34660583b233SRichard Henderson     target_ulong addr;
34670583b233SRichard Henderson     target_long val, sprval;
34680583b233SRichard Henderson 
34690583b233SRichard Henderson     start_exclusive();
34700583b233SRichard Henderson 
34710583b233SRichard Henderson     addr = env->atomic_srca;
34720583b233SRichard Henderson     if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
34730583b233SRichard Henderson         goto sigsegv_maperr;
34740583b233SRichard Henderson     }
34750583b233SRichard Henderson 
34760583b233SRichard Henderson     if (cmp) {
34770583b233SRichard Henderson         if (quad) {
34780583b233SRichard Henderson             sprval = env->spregs[TILEGX_SPR_CMPEXCH];
34790583b233SRichard Henderson         } else {
34800583b233SRichard Henderson             sprval = sextract64(env->spregs[TILEGX_SPR_CMPEXCH], 0, 32);
34810583b233SRichard Henderson         }
34820583b233SRichard Henderson     }
34830583b233SRichard Henderson 
34840583b233SRichard Henderson     if (!cmp || val == sprval) {
34850583b233SRichard Henderson         target_long valb = env->atomic_srcb;
34860583b233SRichard Henderson         if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) {
34870583b233SRichard Henderson             goto sigsegv_maperr;
34880583b233SRichard Henderson         }
34890583b233SRichard Henderson     }
34900583b233SRichard Henderson 
34910583b233SRichard Henderson     set_regval(env, env->atomic_dstr, val);
34920583b233SRichard Henderson     end_exclusive();
34930583b233SRichard Henderson     return;
34940583b233SRichard Henderson 
34950583b233SRichard Henderson  sigsegv_maperr:
34960583b233SRichard Henderson     end_exclusive();
34970583b233SRichard Henderson     gen_sigsegv_maperr(env, addr);
34980583b233SRichard Henderson }
34990583b233SRichard Henderson 
35000583b233SRichard Henderson static void do_fetch(CPUTLGState *env, int trapnr, bool quad)
35010583b233SRichard Henderson {
35020583b233SRichard Henderson     int8_t write = 1;
35030583b233SRichard Henderson     target_ulong addr;
35040583b233SRichard Henderson     target_long val, valb;
35050583b233SRichard Henderson 
35060583b233SRichard Henderson     start_exclusive();
35070583b233SRichard Henderson 
35080583b233SRichard Henderson     addr = env->atomic_srca;
35090583b233SRichard Henderson     valb = env->atomic_srcb;
35100583b233SRichard Henderson     if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
35110583b233SRichard Henderson         goto sigsegv_maperr;
35120583b233SRichard Henderson     }
35130583b233SRichard Henderson 
35140583b233SRichard Henderson     switch (trapnr) {
35150583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHADD:
35160583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHADD4:
35170583b233SRichard Henderson         valb += val;
35180583b233SRichard Henderson         break;
35190583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHADDGEZ:
35200583b233SRichard Henderson         valb += val;
35210583b233SRichard Henderson         if (valb < 0) {
35220583b233SRichard Henderson             write = 0;
35230583b233SRichard Henderson         }
35240583b233SRichard Henderson         break;
35250583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHADDGEZ4:
35260583b233SRichard Henderson         valb += val;
35270583b233SRichard Henderson         if ((int32_t)valb < 0) {
35280583b233SRichard Henderson             write = 0;
35290583b233SRichard Henderson         }
35300583b233SRichard Henderson         break;
35310583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHAND:
35320583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHAND4:
35330583b233SRichard Henderson         valb &= val;
35340583b233SRichard Henderson         break;
35350583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHOR:
35360583b233SRichard Henderson     case TILEGX_EXCP_OPCODE_FETCHOR4:
35370583b233SRichard Henderson         valb |= val;
35380583b233SRichard Henderson         break;
35390583b233SRichard Henderson     default:
35400583b233SRichard Henderson         g_assert_not_reached();
35410583b233SRichard Henderson     }
35420583b233SRichard Henderson 
35430583b233SRichard Henderson     if (write) {
35440583b233SRichard Henderson         if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) {
35450583b233SRichard Henderson             goto sigsegv_maperr;
35460583b233SRichard Henderson         }
35470583b233SRichard Henderson     }
35480583b233SRichard Henderson 
35490583b233SRichard Henderson     set_regval(env, env->atomic_dstr, val);
35500583b233SRichard Henderson     end_exclusive();
35510583b233SRichard Henderson     return;
35520583b233SRichard Henderson 
35530583b233SRichard Henderson  sigsegv_maperr:
35540583b233SRichard Henderson     end_exclusive();
35550583b233SRichard Henderson     gen_sigsegv_maperr(env, addr);
35560583b233SRichard Henderson }
35570583b233SRichard Henderson 
3558b16189b2SChen Gang void cpu_loop(CPUTLGState *env)
3559b16189b2SChen Gang {
3560b16189b2SChen Gang     CPUState *cs = CPU(tilegx_env_get_cpu(env));
3561b16189b2SChen Gang     int trapnr;
3562b16189b2SChen Gang 
3563b16189b2SChen Gang     while (1) {
3564b16189b2SChen Gang         cpu_exec_start(cs);
35658642c1b8SPeter Crosthwaite         trapnr = cpu_exec(cs);
3566b16189b2SChen Gang         cpu_exec_end(cs);
3567d148d90eSSergey Fedorov         process_queued_cpu_work(cs);
3568d148d90eSSergey Fedorov 
3569b16189b2SChen Gang         switch (trapnr) {
3570b16189b2SChen Gang         case TILEGX_EXCP_SYSCALL:
3571a9175169SPeter Maydell         {
3572a9175169SPeter Maydell             abi_ulong ret = do_syscall(env, env->regs[TILEGX_R_NR],
3573b16189b2SChen Gang                                        env->regs[0], env->regs[1],
3574b16189b2SChen Gang                                        env->regs[2], env->regs[3],
3575b16189b2SChen Gang                                        env->regs[4], env->regs[5],
3576b16189b2SChen Gang                                        env->regs[6], env->regs[7]);
3577a9175169SPeter Maydell             if (ret == -TARGET_ERESTARTSYS) {
3578a9175169SPeter Maydell                 env->pc -= 8;
3579a9175169SPeter Maydell             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
3580a9175169SPeter Maydell                 env->regs[TILEGX_R_RE] = ret;
3581a9175169SPeter Maydell                 env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(ret) ? -ret : 0;
3582a9175169SPeter Maydell             }
3583b16189b2SChen Gang             break;
3584a9175169SPeter Maydell         }
35850583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_EXCH:
35860583b233SRichard Henderson             do_exch(env, true, false);
35870583b233SRichard Henderson             break;
35880583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_EXCH4:
35890583b233SRichard Henderson             do_exch(env, false, false);
35900583b233SRichard Henderson             break;
35910583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_CMPEXCH:
35920583b233SRichard Henderson             do_exch(env, true, true);
35930583b233SRichard Henderson             break;
35940583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_CMPEXCH4:
35950583b233SRichard Henderson             do_exch(env, false, true);
35960583b233SRichard Henderson             break;
35970583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHADD:
35980583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHADDGEZ:
35990583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHAND:
36000583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHOR:
36010583b233SRichard Henderson             do_fetch(env, trapnr, true);
36020583b233SRichard Henderson             break;
36030583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHADD4:
36040583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHADDGEZ4:
36050583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHAND4:
36060583b233SRichard Henderson         case TILEGX_EXCP_OPCODE_FETCHOR4:
36070583b233SRichard Henderson             do_fetch(env, trapnr, false);
36080583b233SRichard Henderson             break;
3609dd8070d8SChen Gang         case TILEGX_EXCP_SIGNAL:
3610a0577d2aSRichard Henderson             do_signal(env, env->signo, env->sigcode);
3611dd8070d8SChen Gang             break;
3612b16189b2SChen Gang         case TILEGX_EXCP_REG_IDN_ACCESS:
3613b16189b2SChen Gang         case TILEGX_EXCP_REG_UDN_ACCESS:
3614b16189b2SChen Gang             gen_sigill_reg(env);
3615b16189b2SChen Gang             break;
3616fdbc2b57SRichard Henderson         case EXCP_ATOMIC:
3617fdbc2b57SRichard Henderson             cpu_exec_step_atomic(cs);
3618fdbc2b57SRichard Henderson             break;
3619b16189b2SChen Gang         default:
3620b16189b2SChen Gang             fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr);
3621b16189b2SChen Gang             g_assert_not_reached();
3622b16189b2SChen Gang         }
3623b16189b2SChen Gang         process_pending_signals(env);
3624b16189b2SChen Gang     }
3625b16189b2SChen Gang }
3626b16189b2SChen Gang 
3627b16189b2SChen Gang #endif
3628b16189b2SChen Gang 
36297c248bcdSRichard Henderson #ifdef TARGET_HPPA
36307c248bcdSRichard Henderson 
36317c248bcdSRichard Henderson static abi_ulong hppa_lws(CPUHPPAState *env)
36327c248bcdSRichard Henderson {
36337c248bcdSRichard Henderson     uint32_t which = env->gr[20];
36347c248bcdSRichard Henderson     abi_ulong addr = env->gr[26];
36357c248bcdSRichard Henderson     abi_ulong old = env->gr[25];
36367c248bcdSRichard Henderson     abi_ulong new = env->gr[24];
36377c248bcdSRichard Henderson     abi_ulong size, ret;
36387c248bcdSRichard Henderson 
36397c248bcdSRichard Henderson     switch (which) {
36407c248bcdSRichard Henderson     default:
36417c248bcdSRichard Henderson         return -TARGET_ENOSYS;
36427c248bcdSRichard Henderson 
36437c248bcdSRichard Henderson     case 0: /* elf32 atomic 32bit cmpxchg */
36447c248bcdSRichard Henderson         if ((addr & 3) || !access_ok(VERIFY_WRITE, addr, 4)) {
36457c248bcdSRichard Henderson             return -TARGET_EFAULT;
36467c248bcdSRichard Henderson         }
36477c248bcdSRichard Henderson         old = tswap32(old);
36487c248bcdSRichard Henderson         new = tswap32(new);
36497c248bcdSRichard Henderson         ret = atomic_cmpxchg((uint32_t *)g2h(addr), old, new);
36507c248bcdSRichard Henderson         ret = tswap32(ret);
36517c248bcdSRichard Henderson         break;
36527c248bcdSRichard Henderson 
36537c248bcdSRichard Henderson     case 2: /* elf32 atomic "new" cmpxchg */
36547c248bcdSRichard Henderson         size = env->gr[23];
36557c248bcdSRichard Henderson         if (size >= 4) {
36567c248bcdSRichard Henderson             return -TARGET_ENOSYS;
36577c248bcdSRichard Henderson         }
36587c248bcdSRichard Henderson         if (((addr | old | new) & ((1 << size) - 1))
36597c248bcdSRichard Henderson             || !access_ok(VERIFY_WRITE, addr, 1 << size)
36607c248bcdSRichard Henderson             || !access_ok(VERIFY_READ, old, 1 << size)
36617c248bcdSRichard Henderson             || !access_ok(VERIFY_READ, new, 1 << size)) {
36627c248bcdSRichard Henderson             return -TARGET_EFAULT;
36637c248bcdSRichard Henderson         }
36647c248bcdSRichard Henderson         /* Note that below we use host-endian loads so that the cmpxchg
36657c248bcdSRichard Henderson            can be host-endian as well.  */
36667c248bcdSRichard Henderson         switch (size) {
36677c248bcdSRichard Henderson         case 0:
36687c248bcdSRichard Henderson             old = *(uint8_t *)g2h(old);
36697c248bcdSRichard Henderson             new = *(uint8_t *)g2h(new);
36707c248bcdSRichard Henderson             ret = atomic_cmpxchg((uint8_t *)g2h(addr), old, new);
36717c248bcdSRichard Henderson             ret = ret != old;
36727c248bcdSRichard Henderson             break;
36737c248bcdSRichard Henderson         case 1:
36747c248bcdSRichard Henderson             old = *(uint16_t *)g2h(old);
36757c248bcdSRichard Henderson             new = *(uint16_t *)g2h(new);
36767c248bcdSRichard Henderson             ret = atomic_cmpxchg((uint16_t *)g2h(addr), old, new);
36777c248bcdSRichard Henderson             ret = ret != old;
36787c248bcdSRichard Henderson             break;
36797c248bcdSRichard Henderson         case 2:
36807c248bcdSRichard Henderson             old = *(uint32_t *)g2h(old);
36817c248bcdSRichard Henderson             new = *(uint32_t *)g2h(new);
36827c248bcdSRichard Henderson             ret = atomic_cmpxchg((uint32_t *)g2h(addr), old, new);
36837c248bcdSRichard Henderson             ret = ret != old;
36847c248bcdSRichard Henderson             break;
36857c248bcdSRichard Henderson         case 3:
36867c248bcdSRichard Henderson             {
36877c248bcdSRichard Henderson                 uint64_t o64, n64, r64;
36887c248bcdSRichard Henderson                 o64 = *(uint64_t *)g2h(old);
36897c248bcdSRichard Henderson                 n64 = *(uint64_t *)g2h(new);
36907c248bcdSRichard Henderson #ifdef CONFIG_ATOMIC64
36917c248bcdSRichard Henderson                 r64 = atomic_cmpxchg__nocheck((uint64_t *)g2h(addr), o64, n64);
36927c248bcdSRichard Henderson                 ret = r64 != o64;
36937c248bcdSRichard Henderson #else
36947c248bcdSRichard Henderson                 start_exclusive();
36957c248bcdSRichard Henderson                 r64 = *(uint64_t *)g2h(addr);
36967c248bcdSRichard Henderson                 ret = 1;
36977c248bcdSRichard Henderson                 if (r64 == o64) {
36987c248bcdSRichard Henderson                     *(uint64_t *)g2h(addr) = n64;
36997c248bcdSRichard Henderson                     ret = 0;
37007c248bcdSRichard Henderson                 }
37017c248bcdSRichard Henderson                 end_exclusive();
37027c248bcdSRichard Henderson #endif
37037c248bcdSRichard Henderson             }
37047c248bcdSRichard Henderson             break;
37057c248bcdSRichard Henderson         }
37067c248bcdSRichard Henderson         break;
37077c248bcdSRichard Henderson     }
37087c248bcdSRichard Henderson 
37097c248bcdSRichard Henderson     env->gr[28] = ret;
37107c248bcdSRichard Henderson     return 0;
37117c248bcdSRichard Henderson }
37127c248bcdSRichard Henderson 
37137c248bcdSRichard Henderson void cpu_loop(CPUHPPAState *env)
37147c248bcdSRichard Henderson {
37157c248bcdSRichard Henderson     CPUState *cs = CPU(hppa_env_get_cpu(env));
37167c248bcdSRichard Henderson     target_siginfo_t info;
37177c248bcdSRichard Henderson     abi_ulong ret;
37187c248bcdSRichard Henderson     int trapnr;
37197c248bcdSRichard Henderson 
37207c248bcdSRichard Henderson     while (1) {
37217c248bcdSRichard Henderson         cpu_exec_start(cs);
37227c248bcdSRichard Henderson         trapnr = cpu_exec(cs);
37237c248bcdSRichard Henderson         cpu_exec_end(cs);
37247c248bcdSRichard Henderson         process_queued_cpu_work(cs);
37257c248bcdSRichard Henderson 
37267c248bcdSRichard Henderson         switch (trapnr) {
37277c248bcdSRichard Henderson         case EXCP_SYSCALL:
37287c248bcdSRichard Henderson             ret = do_syscall(env, env->gr[20],
37297c248bcdSRichard Henderson                              env->gr[26], env->gr[25],
37307c248bcdSRichard Henderson                              env->gr[24], env->gr[23],
37317c248bcdSRichard Henderson                              env->gr[22], env->gr[21], 0, 0);
37327c248bcdSRichard Henderson             switch (ret) {
37337c248bcdSRichard Henderson             default:
37347c248bcdSRichard Henderson                 env->gr[28] = ret;
37357c248bcdSRichard Henderson                 /* We arrived here by faking the gateway page.  Return.  */
37367c248bcdSRichard Henderson                 env->iaoq_f = env->gr[31];
37377c248bcdSRichard Henderson                 env->iaoq_b = env->gr[31] + 4;
37387c248bcdSRichard Henderson                 break;
37397c248bcdSRichard Henderson             case -TARGET_ERESTARTSYS:
37407c248bcdSRichard Henderson             case -TARGET_QEMU_ESIGRETURN:
37417c248bcdSRichard Henderson                 break;
37427c248bcdSRichard Henderson             }
37437c248bcdSRichard Henderson             break;
37447c248bcdSRichard Henderson         case EXCP_SYSCALL_LWS:
37457c248bcdSRichard Henderson             env->gr[21] = hppa_lws(env);
37467c248bcdSRichard Henderson             /* We arrived here by faking the gateway page.  Return.  */
37477c248bcdSRichard Henderson             env->iaoq_f = env->gr[31];
37487c248bcdSRichard Henderson             env->iaoq_b = env->gr[31] + 4;
37497c248bcdSRichard Henderson             break;
37507c248bcdSRichard Henderson         case EXCP_SIGSEGV:
37517c248bcdSRichard Henderson             info.si_signo = TARGET_SIGSEGV;
37527c248bcdSRichard Henderson             info.si_errno = 0;
37537c248bcdSRichard Henderson             info.si_code = TARGET_SEGV_ACCERR;
37547c248bcdSRichard Henderson             info._sifields._sigfault._addr = env->ior;
37557c248bcdSRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
37567c248bcdSRichard Henderson             break;
37577c248bcdSRichard Henderson         case EXCP_SIGILL:
37587c248bcdSRichard Henderson             info.si_signo = TARGET_SIGILL;
37597c248bcdSRichard Henderson             info.si_errno = 0;
37607c248bcdSRichard Henderson             info.si_code = TARGET_ILL_ILLOPN;
37617c248bcdSRichard Henderson             info._sifields._sigfault._addr = env->iaoq_f;
37627c248bcdSRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
37637c248bcdSRichard Henderson             break;
37647c248bcdSRichard Henderson         case EXCP_SIGFPE:
37657c248bcdSRichard Henderson             info.si_signo = TARGET_SIGFPE;
37667c248bcdSRichard Henderson             info.si_errno = 0;
37677c248bcdSRichard Henderson             info.si_code = 0;
37687c248bcdSRichard Henderson             info._sifields._sigfault._addr = env->iaoq_f;
37697c248bcdSRichard Henderson             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
37707c248bcdSRichard Henderson             break;
37717c248bcdSRichard Henderson         case EXCP_DEBUG:
37727c248bcdSRichard Henderson             trapnr = gdb_handlesig(cs, TARGET_SIGTRAP);
37737c248bcdSRichard Henderson             if (trapnr) {
37747c248bcdSRichard Henderson                 info.si_signo = trapnr;
37757c248bcdSRichard Henderson                 info.si_errno = 0;
37767c248bcdSRichard Henderson                 info.si_code = TARGET_TRAP_BRKPT;
37777c248bcdSRichard Henderson                 queue_signal(env, trapnr, QEMU_SI_FAULT, &info);
37787c248bcdSRichard Henderson             }
37797c248bcdSRichard Henderson             break;
37807c248bcdSRichard Henderson         case EXCP_INTERRUPT:
37817c248bcdSRichard Henderson             /* just indicate that signals should be handled asap */
37827c248bcdSRichard Henderson             break;
37837c248bcdSRichard Henderson         default:
37847c248bcdSRichard Henderson             g_assert_not_reached();
37857c248bcdSRichard Henderson         }
37867c248bcdSRichard Henderson         process_pending_signals(env);
37877c248bcdSRichard Henderson     }
37887c248bcdSRichard Henderson }
37897c248bcdSRichard Henderson 
37907c248bcdSRichard Henderson #endif /* TARGET_HPPA */
37917c248bcdSRichard Henderson 
3792a2247f8eSAndreas Färber THREAD CPUState *thread_cpu;
379359faf6d6Sbellard 
3794178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu)
3795178f9429SSergey Fedorov {
3796178f9429SSergey Fedorov     return thread_cpu == cpu;
3797178f9429SSergey Fedorov }
3798178f9429SSergey Fedorov 
3799178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu)
3800178f9429SSergey Fedorov {
3801178f9429SSergey Fedorov     cpu_exit(cpu);
3802178f9429SSergey Fedorov }
3803178f9429SSergey Fedorov 
3804edf8e2afSMika Westerberg void task_settid(TaskState *ts)
3805edf8e2afSMika Westerberg {
3806edf8e2afSMika Westerberg     if (ts->ts_tid == 0) {
3807edf8e2afSMika Westerberg         ts->ts_tid = (pid_t)syscall(SYS_gettid);
3808edf8e2afSMika Westerberg     }
3809edf8e2afSMika Westerberg }
3810edf8e2afSMika Westerberg 
3811edf8e2afSMika Westerberg void stop_all_tasks(void)
3812edf8e2afSMika Westerberg {
3813edf8e2afSMika Westerberg     /*
3814edf8e2afSMika Westerberg      * We trust that when using NPTL, start_exclusive()
3815edf8e2afSMika Westerberg      * handles thread stopping correctly.
3816edf8e2afSMika Westerberg      */
3817edf8e2afSMika Westerberg     start_exclusive();
3818edf8e2afSMika Westerberg }
3819edf8e2afSMika Westerberg 
3820c3a92833Spbrook /* Assumes contents are already zeroed.  */
3821624f7979Spbrook void init_task_state(TaskState *ts)
3822624f7979Spbrook {
3823624f7979Spbrook     ts->used = 1;
3824624f7979Spbrook }
38259de5e440Sbellard 
382630ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env)
382730ba0ee5SAndreas Färber {
3828ff4700b0SAndreas Färber     CPUState *cpu = ENV_GET_CPU(env);
38292994fd96SEduardo Habkost     CPUState *new_cpu = cpu_init(cpu_model);
383061c7480fSLeon Alrae     CPUArchState *new_env = new_cpu->env_ptr;
383130ba0ee5SAndreas Färber     CPUBreakpoint *bp;
383230ba0ee5SAndreas Färber     CPUWatchpoint *wp;
383330ba0ee5SAndreas Färber 
383430ba0ee5SAndreas Färber     /* Reset non arch specific state */
383575a34036SAndreas Färber     cpu_reset(new_cpu);
383630ba0ee5SAndreas Färber 
383730ba0ee5SAndreas Färber     memcpy(new_env, env, sizeof(CPUArchState));
383830ba0ee5SAndreas Färber 
383930ba0ee5SAndreas Färber     /* Clone all break/watchpoints.
384030ba0ee5SAndreas Färber        Note: Once we support ptrace with hw-debug register access, make sure
384130ba0ee5SAndreas Färber        BP_CPU break/watchpoints are handled correctly on clone. */
38421d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->breakpoints);
38431d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->watchpoints);
3844f0c3c505SAndreas Färber     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
3845b3310ab3SAndreas Färber         cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
384630ba0ee5SAndreas Färber     }
3847ff4700b0SAndreas Färber     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
384805068c0dSPeter Maydell         cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL);
384930ba0ee5SAndreas Färber     }
385030ba0ee5SAndreas Färber 
385130ba0ee5SAndreas Färber     return new_env;
385230ba0ee5SAndreas Färber }
385330ba0ee5SAndreas Färber 
3854fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg)
3855fc9c5412SJohannes Schauer {
38564d1275c2SRiku Voipio     usage(EXIT_SUCCESS);
3857fc9c5412SJohannes Schauer }
3858fc9c5412SJohannes Schauer 
3859fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg)
3860fc9c5412SJohannes Schauer {
3861fc9c5412SJohannes Schauer     int mask;
3862fc9c5412SJohannes Schauer 
38634fde1ebaSPeter Maydell     mask = qemu_str_to_log_mask(arg);
3864fc9c5412SJohannes Schauer     if (!mask) {
386559a6fa6eSPeter Maydell         qemu_print_log_usage(stdout);
38664d1275c2SRiku Voipio         exit(EXIT_FAILURE);
3867fc9c5412SJohannes Schauer     }
3868f2937a33SPaolo Bonzini     qemu_log_needs_buffers();
386924537a01SPeter Maydell     qemu_set_log(mask);
3870fc9c5412SJohannes Schauer }
3871fc9c5412SJohannes Schauer 
38728423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg)
38738423fa90SAlex Bennée {
38748423fa90SAlex Bennée     qemu_set_dfilter_ranges(arg, NULL);
38758423fa90SAlex Bennée }
38768423fa90SAlex Bennée 
387750171d42S陳韋任 static void handle_arg_log_filename(const char *arg)
387850171d42S陳韋任 {
3879daa76aa4SMarkus Armbruster     qemu_set_log_filename(arg, &error_fatal);
388050171d42S陳韋任 }
388150171d42S陳韋任 
3882fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg)
3883fc9c5412SJohannes Schauer {
3884fc9c5412SJohannes Schauer     char *r, *p, *token;
3885fc9c5412SJohannes Schauer     r = p = strdup(arg);
3886fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
3887fc9c5412SJohannes Schauer         if (envlist_setenv(envlist, token) != 0) {
38884d1275c2SRiku Voipio             usage(EXIT_FAILURE);
3889fc9c5412SJohannes Schauer         }
3890fc9c5412SJohannes Schauer     }
3891fc9c5412SJohannes Schauer     free(r);
3892fc9c5412SJohannes Schauer }
3893fc9c5412SJohannes Schauer 
3894fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg)
3895fc9c5412SJohannes Schauer {
3896fc9c5412SJohannes Schauer     char *r, *p, *token;
3897fc9c5412SJohannes Schauer     r = p = strdup(arg);
3898fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
3899fc9c5412SJohannes Schauer         if (envlist_unsetenv(envlist, token) != 0) {
39004d1275c2SRiku Voipio             usage(EXIT_FAILURE);
3901fc9c5412SJohannes Schauer         }
3902fc9c5412SJohannes Schauer     }
3903fc9c5412SJohannes Schauer     free(r);
3904fc9c5412SJohannes Schauer }
3905fc9c5412SJohannes Schauer 
3906fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg)
3907fc9c5412SJohannes Schauer {
3908fc9c5412SJohannes Schauer     argv0 = strdup(arg);
3909fc9c5412SJohannes Schauer }
3910fc9c5412SJohannes Schauer 
3911fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg)
3912fc9c5412SJohannes Schauer {
3913fc9c5412SJohannes Schauer     char *p;
3914fc9c5412SJohannes Schauer     guest_stack_size = strtoul(arg, &p, 0);
3915fc9c5412SJohannes Schauer     if (guest_stack_size == 0) {
39164d1275c2SRiku Voipio         usage(EXIT_FAILURE);
3917fc9c5412SJohannes Schauer     }
3918fc9c5412SJohannes Schauer 
3919fc9c5412SJohannes Schauer     if (*p == 'M') {
3920fc9c5412SJohannes Schauer         guest_stack_size *= 1024 * 1024;
3921fc9c5412SJohannes Schauer     } else if (*p == 'k' || *p == 'K') {
3922fc9c5412SJohannes Schauer         guest_stack_size *= 1024;
3923fc9c5412SJohannes Schauer     }
3924fc9c5412SJohannes Schauer }
3925fc9c5412SJohannes Schauer 
3926fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg)
3927fc9c5412SJohannes Schauer {
3928fc9c5412SJohannes Schauer     interp_prefix = strdup(arg);
3929fc9c5412SJohannes Schauer }
3930fc9c5412SJohannes Schauer 
3931fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg)
3932fc9c5412SJohannes Schauer {
3933fc9c5412SJohannes Schauer     qemu_host_page_size = atoi(arg);
3934fc9c5412SJohannes Schauer     if (qemu_host_page_size == 0 ||
3935fc9c5412SJohannes Schauer         (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
3936fc9c5412SJohannes Schauer         fprintf(stderr, "page size must be a power of two\n");
39374d1275c2SRiku Voipio         exit(EXIT_FAILURE);
3938fc9c5412SJohannes Schauer     }
3939fc9c5412SJohannes Schauer }
3940fc9c5412SJohannes Schauer 
3941c5e4a5a9SMagnus Reftel static void handle_arg_randseed(const char *arg)
3942c5e4a5a9SMagnus Reftel {
3943c5e4a5a9SMagnus Reftel     unsigned long long seed;
3944c5e4a5a9SMagnus Reftel 
3945c5e4a5a9SMagnus Reftel     if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) {
3946c5e4a5a9SMagnus Reftel         fprintf(stderr, "Invalid seed number: %s\n", arg);
39474d1275c2SRiku Voipio         exit(EXIT_FAILURE);
3948c5e4a5a9SMagnus Reftel     }
3949c5e4a5a9SMagnus Reftel     srand(seed);
3950c5e4a5a9SMagnus Reftel }
3951c5e4a5a9SMagnus Reftel 
3952fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg)
3953fc9c5412SJohannes Schauer {
3954fc9c5412SJohannes Schauer     gdbstub_port = atoi(arg);
3955fc9c5412SJohannes Schauer }
3956fc9c5412SJohannes Schauer 
3957fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg)
3958fc9c5412SJohannes Schauer {
3959fc9c5412SJohannes Schauer     qemu_uname_release = strdup(arg);
3960fc9c5412SJohannes Schauer }
3961fc9c5412SJohannes Schauer 
3962fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg)
3963fc9c5412SJohannes Schauer {
3964fc9c5412SJohannes Schauer     cpu_model = strdup(arg);
3965c8057f95SPeter Maydell     if (cpu_model == NULL || is_help_option(cpu_model)) {
3966fc9c5412SJohannes Schauer         /* XXX: implement xxx_cpu_list for targets that still miss it */
3967e916cbf8SPeter Maydell #if defined(cpu_list)
3968e916cbf8SPeter Maydell         cpu_list(stdout, &fprintf);
3969fc9c5412SJohannes Schauer #endif
39704d1275c2SRiku Voipio         exit(EXIT_FAILURE);
3971fc9c5412SJohannes Schauer     }
3972fc9c5412SJohannes Schauer }
3973fc9c5412SJohannes Schauer 
3974fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg)
3975fc9c5412SJohannes Schauer {
3976fc9c5412SJohannes Schauer     guest_base = strtol(arg, NULL, 0);
3977fc9c5412SJohannes Schauer     have_guest_base = 1;
3978fc9c5412SJohannes Schauer }
3979fc9c5412SJohannes Schauer 
3980fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg)
3981fc9c5412SJohannes Schauer {
3982fc9c5412SJohannes Schauer     char *p;
3983fc9c5412SJohannes Schauer     int shift = 0;
3984fc9c5412SJohannes Schauer     reserved_va = strtoul(arg, &p, 0);
3985fc9c5412SJohannes Schauer     switch (*p) {
3986fc9c5412SJohannes Schauer     case 'k':
3987fc9c5412SJohannes Schauer     case 'K':
3988fc9c5412SJohannes Schauer         shift = 10;
3989fc9c5412SJohannes Schauer         break;
3990fc9c5412SJohannes Schauer     case 'M':
3991fc9c5412SJohannes Schauer         shift = 20;
3992fc9c5412SJohannes Schauer         break;
3993fc9c5412SJohannes Schauer     case 'G':
3994fc9c5412SJohannes Schauer         shift = 30;
3995fc9c5412SJohannes Schauer         break;
3996fc9c5412SJohannes Schauer     }
3997fc9c5412SJohannes Schauer     if (shift) {
3998fc9c5412SJohannes Schauer         unsigned long unshifted = reserved_va;
3999fc9c5412SJohannes Schauer         p++;
4000fc9c5412SJohannes Schauer         reserved_va <<= shift;
400118e80c55SRichard Henderson         if (reserved_va >> shift != unshifted
400218e80c55SRichard Henderson             || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
4003fc9c5412SJohannes Schauer             fprintf(stderr, "Reserved virtual address too big\n");
40044d1275c2SRiku Voipio             exit(EXIT_FAILURE);
4005fc9c5412SJohannes Schauer         }
4006fc9c5412SJohannes Schauer     }
4007fc9c5412SJohannes Schauer     if (*p) {
4008fc9c5412SJohannes Schauer         fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
40094d1275c2SRiku Voipio         exit(EXIT_FAILURE);
4010fc9c5412SJohannes Schauer     }
4011fc9c5412SJohannes Schauer }
4012fc9c5412SJohannes Schauer 
4013fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg)
4014fc9c5412SJohannes Schauer {
4015fc9c5412SJohannes Schauer     singlestep = 1;
4016fc9c5412SJohannes Schauer }
4017fc9c5412SJohannes Schauer 
4018fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg)
4019fc9c5412SJohannes Schauer {
4020fc9c5412SJohannes Schauer     do_strace = 1;
4021fc9c5412SJohannes Schauer }
4022fc9c5412SJohannes Schauer 
4023fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg)
4024fc9c5412SJohannes Schauer {
40252e59915dSPaolo Bonzini     printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
40260781dd6eSThomas Huth            "\n" QEMU_COPYRIGHT "\n");
40274d1275c2SRiku Voipio     exit(EXIT_SUCCESS);
4028fc9c5412SJohannes Schauer }
4029fc9c5412SJohannes Schauer 
40306533dd6eSLluís Vilanova static char *trace_file;
40316533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg)
40326533dd6eSLluís Vilanova {
40336533dd6eSLluís Vilanova     g_free(trace_file);
40346533dd6eSLluís Vilanova     trace_file = trace_opt_parse(arg);
40356533dd6eSLluís Vilanova }
40366533dd6eSLluís Vilanova 
4037fc9c5412SJohannes Schauer struct qemu_argument {
4038fc9c5412SJohannes Schauer     const char *argv;
4039fc9c5412SJohannes Schauer     const char *env;
4040fc9c5412SJohannes Schauer     bool has_arg;
4041fc9c5412SJohannes Schauer     void (*handle_opt)(const char *arg);
4042fc9c5412SJohannes Schauer     const char *example;
4043fc9c5412SJohannes Schauer     const char *help;
4044fc9c5412SJohannes Schauer };
4045fc9c5412SJohannes Schauer 
404642644ceeSJim Meyering static const struct qemu_argument arg_table[] = {
4047fc9c5412SJohannes Schauer     {"h",          "",                 false, handle_arg_help,
4048fc9c5412SJohannes Schauer      "",           "print this help"},
4049daaf8c8eSMeador Inge     {"help",       "",                 false, handle_arg_help,
4050daaf8c8eSMeador Inge      "",           ""},
4051fc9c5412SJohannes Schauer     {"g",          "QEMU_GDB",         true,  handle_arg_gdb,
4052fc9c5412SJohannes Schauer      "port",       "wait gdb connection to 'port'"},
4053fc9c5412SJohannes Schauer     {"L",          "QEMU_LD_PREFIX",   true,  handle_arg_ld_prefix,
4054fc9c5412SJohannes Schauer      "path",       "set the elf interpreter prefix to 'path'"},
4055fc9c5412SJohannes Schauer     {"s",          "QEMU_STACK_SIZE",  true,  handle_arg_stack_size,
4056fc9c5412SJohannes Schauer      "size",       "set the stack size to 'size' bytes"},
4057fc9c5412SJohannes Schauer     {"cpu",        "QEMU_CPU",         true,  handle_arg_cpu,
4058c8057f95SPeter Maydell      "model",      "select CPU (-cpu help for list)"},
4059fc9c5412SJohannes Schauer     {"E",          "QEMU_SET_ENV",     true,  handle_arg_set_env,
4060fc9c5412SJohannes Schauer      "var=value",  "sets targets environment variable (see below)"},
4061fc9c5412SJohannes Schauer     {"U",          "QEMU_UNSET_ENV",   true,  handle_arg_unset_env,
4062fc9c5412SJohannes Schauer      "var",        "unsets targets environment variable (see below)"},
4063fc9c5412SJohannes Schauer     {"0",          "QEMU_ARGV0",       true,  handle_arg_argv0,
4064fc9c5412SJohannes Schauer      "argv0",      "forces target process argv[0] to be 'argv0'"},
4065fc9c5412SJohannes Schauer     {"r",          "QEMU_UNAME",       true,  handle_arg_uname,
4066fc9c5412SJohannes Schauer      "uname",      "set qemu uname release string to 'uname'"},
4067fc9c5412SJohannes Schauer     {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
4068fc9c5412SJohannes Schauer      "address",    "set guest_base address to 'address'"},
4069fc9c5412SJohannes Schauer     {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
4070fc9c5412SJohannes Schauer      "size",       "reserve 'size' bytes for guest virtual address space"},
4071fc9c5412SJohannes Schauer     {"d",          "QEMU_LOG",         true,  handle_arg_log,
4072989b697dSPeter Maydell      "item[,...]", "enable logging of specified items "
4073989b697dSPeter Maydell      "(use '-d help' for a list of items)"},
40748423fa90SAlex Bennée     {"dfilter",    "QEMU_DFILTER",     true,  handle_arg_dfilter,
40758423fa90SAlex Bennée      "range[,...]","filter logging based on address range"},
407650171d42S陳韋任     {"D",          "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
4077989b697dSPeter Maydell      "logfile",     "write logs to 'logfile' (default stderr)"},
4078fc9c5412SJohannes Schauer     {"p",          "QEMU_PAGESIZE",    true,  handle_arg_pagesize,
4079fc9c5412SJohannes Schauer      "pagesize",   "set the host page size to 'pagesize'"},
4080fc9c5412SJohannes Schauer     {"singlestep", "QEMU_SINGLESTEP",  false, handle_arg_singlestep,
4081fc9c5412SJohannes Schauer      "",           "run in singlestep mode"},
4082fc9c5412SJohannes Schauer     {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
4083fc9c5412SJohannes Schauer      "",           "log system calls"},
4084c5e4a5a9SMagnus Reftel     {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_randseed,
4085c5e4a5a9SMagnus Reftel      "",           "Seed for pseudo-random number generator"},
40866533dd6eSLluís Vilanova     {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
40876533dd6eSLluís Vilanova      "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
4088fc9c5412SJohannes Schauer     {"version",    "QEMU_VERSION",     false, handle_arg_version,
40891386d4c0SPeter Maydell      "",           "display version information and exit"},
4090fc9c5412SJohannes Schauer     {NULL, NULL, false, NULL, NULL, NULL}
4091fc9c5412SJohannes Schauer };
4092fc9c5412SJohannes Schauer 
4093d03f9c32SMeador Inge static void usage(int exitcode)
4094fc9c5412SJohannes Schauer {
409542644ceeSJim Meyering     const struct qemu_argument *arginfo;
4096fc9c5412SJohannes Schauer     int maxarglen;
4097fc9c5412SJohannes Schauer     int maxenvlen;
4098fc9c5412SJohannes Schauer 
40992e59915dSPaolo Bonzini     printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
41002e59915dSPaolo Bonzini            "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
4101fc9c5412SJohannes Schauer            "\n"
4102fc9c5412SJohannes Schauer            "Options and associated environment variables:\n"
4103fc9c5412SJohannes Schauer            "\n");
4104fc9c5412SJohannes Schauer 
410563ec54d7SPeter Maydell     /* Calculate column widths. We must always have at least enough space
410663ec54d7SPeter Maydell      * for the column header.
410763ec54d7SPeter Maydell      */
410863ec54d7SPeter Maydell     maxarglen = strlen("Argument");
410963ec54d7SPeter Maydell     maxenvlen = strlen("Env-variable");
4110fc9c5412SJohannes Schauer 
4111fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
411263ec54d7SPeter Maydell         int arglen = strlen(arginfo->argv);
411363ec54d7SPeter Maydell         if (arginfo->has_arg) {
411463ec54d7SPeter Maydell             arglen += strlen(arginfo->example) + 1;
411563ec54d7SPeter Maydell         }
4116fc9c5412SJohannes Schauer         if (strlen(arginfo->env) > maxenvlen) {
4117fc9c5412SJohannes Schauer             maxenvlen = strlen(arginfo->env);
4118fc9c5412SJohannes Schauer         }
411963ec54d7SPeter Maydell         if (arglen > maxarglen) {
412063ec54d7SPeter Maydell             maxarglen = arglen;
4121fc9c5412SJohannes Schauer         }
4122fc9c5412SJohannes Schauer     }
4123fc9c5412SJohannes Schauer 
412463ec54d7SPeter Maydell     printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
412563ec54d7SPeter Maydell             maxenvlen, "Env-variable");
4126fc9c5412SJohannes Schauer 
4127fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
4128fc9c5412SJohannes Schauer         if (arginfo->has_arg) {
4129fc9c5412SJohannes Schauer             printf("-%s %-*s %-*s %s\n", arginfo->argv,
413063ec54d7SPeter Maydell                    (int)(maxarglen - strlen(arginfo->argv) - 1),
413163ec54d7SPeter Maydell                    arginfo->example, maxenvlen, arginfo->env, arginfo->help);
4132fc9c5412SJohannes Schauer         } else {
413363ec54d7SPeter Maydell             printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
4134fc9c5412SJohannes Schauer                     maxenvlen, arginfo->env,
4135fc9c5412SJohannes Schauer                     arginfo->help);
4136fc9c5412SJohannes Schauer         }
4137fc9c5412SJohannes Schauer     }
4138fc9c5412SJohannes Schauer 
4139fc9c5412SJohannes Schauer     printf("\n"
4140fc9c5412SJohannes Schauer            "Defaults:\n"
4141fc9c5412SJohannes Schauer            "QEMU_LD_PREFIX  = %s\n"
4142989b697dSPeter Maydell            "QEMU_STACK_SIZE = %ld byte\n",
4143fc9c5412SJohannes Schauer            interp_prefix,
4144989b697dSPeter Maydell            guest_stack_size);
4145fc9c5412SJohannes Schauer 
4146fc9c5412SJohannes Schauer     printf("\n"
4147fc9c5412SJohannes Schauer            "You can use -E and -U options or the QEMU_SET_ENV and\n"
4148fc9c5412SJohannes Schauer            "QEMU_UNSET_ENV environment variables to set and unset\n"
4149fc9c5412SJohannes Schauer            "environment variables for the target process.\n"
4150fc9c5412SJohannes Schauer            "It is possible to provide several variables by separating them\n"
4151fc9c5412SJohannes Schauer            "by commas in getsubopt(3) style. Additionally it is possible to\n"
4152fc9c5412SJohannes Schauer            "provide the -E and -U options multiple times.\n"
4153fc9c5412SJohannes Schauer            "The following lines are equivalent:\n"
4154fc9c5412SJohannes Schauer            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
4155fc9c5412SJohannes Schauer            "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
4156fc9c5412SJohannes Schauer            "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
4157fc9c5412SJohannes Schauer            "Note that if you provide several changes to a single variable\n"
4158f5048cb7SEric Blake            "the last change will stay in effect.\n"
4159f5048cb7SEric Blake            "\n"
4160f5048cb7SEric Blake            QEMU_HELP_BOTTOM "\n");
4161fc9c5412SJohannes Schauer 
4162d03f9c32SMeador Inge     exit(exitcode);
4163fc9c5412SJohannes Schauer }
4164fc9c5412SJohannes Schauer 
4165fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
4166fc9c5412SJohannes Schauer {
4167fc9c5412SJohannes Schauer     const char *r;
4168fc9c5412SJohannes Schauer     int optind;
416942644ceeSJim Meyering     const struct qemu_argument *arginfo;
4170fc9c5412SJohannes Schauer 
4171fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
4172fc9c5412SJohannes Schauer         if (arginfo->env == NULL) {
4173fc9c5412SJohannes Schauer             continue;
4174fc9c5412SJohannes Schauer         }
4175fc9c5412SJohannes Schauer 
4176fc9c5412SJohannes Schauer         r = getenv(arginfo->env);
4177fc9c5412SJohannes Schauer         if (r != NULL) {
4178fc9c5412SJohannes Schauer             arginfo->handle_opt(r);
4179fc9c5412SJohannes Schauer         }
4180fc9c5412SJohannes Schauer     }
4181fc9c5412SJohannes Schauer 
4182fc9c5412SJohannes Schauer     optind = 1;
4183fc9c5412SJohannes Schauer     for (;;) {
4184fc9c5412SJohannes Schauer         if (optind >= argc) {
4185fc9c5412SJohannes Schauer             break;
4186fc9c5412SJohannes Schauer         }
4187fc9c5412SJohannes Schauer         r = argv[optind];
4188fc9c5412SJohannes Schauer         if (r[0] != '-') {
4189fc9c5412SJohannes Schauer             break;
4190fc9c5412SJohannes Schauer         }
4191fc9c5412SJohannes Schauer         optind++;
4192fc9c5412SJohannes Schauer         r++;
4193fc9c5412SJohannes Schauer         if (!strcmp(r, "-")) {
4194fc9c5412SJohannes Schauer             break;
4195fc9c5412SJohannes Schauer         }
4196ba02577cSMeador Inge         /* Treat --foo the same as -foo.  */
4197ba02577cSMeador Inge         if (r[0] == '-') {
4198ba02577cSMeador Inge             r++;
4199ba02577cSMeador Inge         }
4200fc9c5412SJohannes Schauer 
4201fc9c5412SJohannes Schauer         for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
4202fc9c5412SJohannes Schauer             if (!strcmp(r, arginfo->argv)) {
42031386d4c0SPeter Maydell                 if (arginfo->has_arg) {
4204fc9c5412SJohannes Schauer                     if (optind >= argc) {
4205138940bfSMeador Inge                         (void) fprintf(stderr,
4206138940bfSMeador Inge                             "qemu: missing argument for option '%s'\n", r);
42074d1275c2SRiku Voipio                         exit(EXIT_FAILURE);
4208fc9c5412SJohannes Schauer                     }
4209fc9c5412SJohannes Schauer                     arginfo->handle_opt(argv[optind]);
4210fc9c5412SJohannes Schauer                     optind++;
42111386d4c0SPeter Maydell                 } else {
42121386d4c0SPeter Maydell                     arginfo->handle_opt(NULL);
4213fc9c5412SJohannes Schauer                 }
4214fc9c5412SJohannes Schauer                 break;
4215fc9c5412SJohannes Schauer             }
4216fc9c5412SJohannes Schauer         }
4217fc9c5412SJohannes Schauer 
4218fc9c5412SJohannes Schauer         /* no option matched the current argv */
4219fc9c5412SJohannes Schauer         if (arginfo->handle_opt == NULL) {
4220138940bfSMeador Inge             (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
42214d1275c2SRiku Voipio             exit(EXIT_FAILURE);
4222fc9c5412SJohannes Schauer         }
4223fc9c5412SJohannes Schauer     }
4224fc9c5412SJohannes Schauer 
4225fc9c5412SJohannes Schauer     if (optind >= argc) {
4226138940bfSMeador Inge         (void) fprintf(stderr, "qemu: no user program specified\n");
42274d1275c2SRiku Voipio         exit(EXIT_FAILURE);
4228fc9c5412SJohannes Schauer     }
4229fc9c5412SJohannes Schauer 
4230fc9c5412SJohannes Schauer     filename = argv[optind];
4231fc9c5412SJohannes Schauer     exec_path = argv[optind];
4232fc9c5412SJohannes Schauer 
4233fc9c5412SJohannes Schauer     return optind;
4234fc9c5412SJohannes Schauer }
4235fc9c5412SJohannes Schauer 
4236902b3d5cSmalc int main(int argc, char **argv, char **envp)
423731e31b8aSbellard {
423801ffc75bSbellard     struct target_pt_regs regs1, *regs = &regs1;
423931e31b8aSbellard     struct image_info info1, *info = &info1;
4240edf8e2afSMika Westerberg     struct linux_binprm bprm;
424148e15fc2SNathan Froyd     TaskState *ts;
42429349b4f9SAndreas Färber     CPUArchState *env;
4243db6b81d4SAndreas Färber     CPUState *cpu;
4244586314f2Sbellard     int optind;
424504a6dfebSaurel32     char **target_environ, **wrk;
42467d8cec95Saurel32     char **target_argv;
42477d8cec95Saurel32     int target_argc;
42487d8cec95Saurel32     int i;
4249fd4d81ddSArnaud Patard     int ret;
425003cfd8faSLaurent Vivier     int execfd;
425131e31b8aSbellard 
4252fe4db84dSDaniel P. Berrange     module_call_init(MODULE_INIT_TRACE);
4253267f685bSPaolo Bonzini     qemu_init_cpu_list();
4254ce008c1fSAndreas Färber     module_call_init(MODULE_INIT_QOM);
4255ce008c1fSAndreas Färber 
4256ec45bbe5SSaurav Sachidanand     envlist = envlist_create();
425704a6dfebSaurel32 
425804a6dfebSaurel32     /* add current environment into the list */
425904a6dfebSaurel32     for (wrk = environ; *wrk != NULL; wrk++) {
426004a6dfebSaurel32         (void) envlist_setenv(envlist, *wrk);
426104a6dfebSaurel32     }
426204a6dfebSaurel32 
4263703e0e89SRichard Henderson     /* Read the stack limit from the kernel.  If it's "unlimited",
4264703e0e89SRichard Henderson        then we can do little else besides use the default.  */
4265703e0e89SRichard Henderson     {
4266703e0e89SRichard Henderson         struct rlimit lim;
4267703e0e89SRichard Henderson         if (getrlimit(RLIMIT_STACK, &lim) == 0
426881bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur != RLIM_INFINITY
426981bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur == (target_long)lim.rlim_cur) {
4270703e0e89SRichard Henderson             guest_stack_size = lim.rlim_cur;
4271703e0e89SRichard Henderson         }
4272703e0e89SRichard Henderson     }
4273703e0e89SRichard Henderson 
4274b1f9be31Sj_mayer     cpu_model = NULL;
4275b5ec5ce0Sjohn cooper 
4276c5e4a5a9SMagnus Reftel     srand(time(NULL));
4277c5e4a5a9SMagnus Reftel 
42786533dd6eSLluís Vilanova     qemu_add_opts(&qemu_trace_opts);
42796533dd6eSLluís Vilanova 
4280fc9c5412SJohannes Schauer     optind = parse_args(argc, argv);
42814b5dfd82SPeter Maydell 
42826533dd6eSLluís Vilanova     if (!trace_init_backends()) {
42836533dd6eSLluís Vilanova         exit(1);
42846533dd6eSLluís Vilanova     }
42856533dd6eSLluís Vilanova     trace_init_file(trace_file);
42866533dd6eSLluís Vilanova 
428731e31b8aSbellard     /* Zero out regs */
428801ffc75bSbellard     memset(regs, 0, sizeof(struct target_pt_regs));
428931e31b8aSbellard 
429031e31b8aSbellard     /* Zero out image_info */
429131e31b8aSbellard     memset(info, 0, sizeof(struct image_info));
429231e31b8aSbellard 
4293edf8e2afSMika Westerberg     memset(&bprm, 0, sizeof (bprm));
4294edf8e2afSMika Westerberg 
429574cd30b8Sbellard     /* Scan interp_prefix dir for replacement files. */
429674cd30b8Sbellard     init_paths(interp_prefix);
429774cd30b8Sbellard 
42984a24a758SPeter Maydell     init_qemu_uname_release();
42994a24a758SPeter Maydell 
430046027c07Sbellard     if (cpu_model == NULL) {
4301aaed909aSbellard #if defined(TARGET_I386)
430246027c07Sbellard #ifdef TARGET_X86_64
430346027c07Sbellard         cpu_model = "qemu64";
430446027c07Sbellard #else
430546027c07Sbellard         cpu_model = "qemu32";
430646027c07Sbellard #endif
4307aaed909aSbellard #elif defined(TARGET_ARM)
4308088ab16cSpbrook         cpu_model = "any";
4309d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32)
4310d2fbca94SGuan Xuetao         cpu_model = "any";
4311aaed909aSbellard #elif defined(TARGET_M68K)
4312aaed909aSbellard         cpu_model = "any";
4313aaed909aSbellard #elif defined(TARGET_SPARC)
4314aaed909aSbellard #ifdef TARGET_SPARC64
4315aaed909aSbellard         cpu_model = "TI UltraSparc II";
4316aaed909aSbellard #else
4317aaed909aSbellard         cpu_model = "Fujitsu MB86904";
431846027c07Sbellard #endif
4319aaed909aSbellard #elif defined(TARGET_MIPS)
4320aaed909aSbellard #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
432174797f40SMaciej W. Rozycki         cpu_model = "5KEf";
4322aaed909aSbellard #else
4323aaed909aSbellard         cpu_model = "24Kf";
4324aaed909aSbellard #endif
4325d962783eSJia Liu #elif defined TARGET_OPENRISC
4326d962783eSJia Liu         cpu_model = "or1200";
4327aaed909aSbellard #elif defined(TARGET_PPC)
43287ded4f52Sbellard # ifdef TARGET_PPC64
4329de3f1b98SLaurent Vivier         cpu_model = "POWER8";
43307ded4f52Sbellard # else
4331aaed909aSbellard         cpu_model = "750";
43327ded4f52Sbellard # endif
433391c45a38SRichard Henderson #elif defined TARGET_SH4
433491c45a38SRichard Henderson         cpu_model = TYPE_SH7785_CPU;
4335d8923bc7SDavid Hildenbrand #elif defined TARGET_S390X
4336d8923bc7SDavid Hildenbrand         cpu_model = "qemu";
4337aaed909aSbellard #else
4338aaed909aSbellard         cpu_model = "any";
4339aaed909aSbellard #endif
4340aaed909aSbellard     }
4341d5ab9713SJan Kiszka     tcg_exec_init(0);
434283fb7adfSbellard     /* NOTE: we need to init the CPU at this stage to get
434383fb7adfSbellard        qemu_host_page_size */
43442994fd96SEduardo Habkost     cpu = cpu_init(cpu_model);
43452994fd96SEduardo Habkost     env = cpu->env_ptr;
43460ac46af3SAndreas Färber     cpu_reset(cpu);
4347b55a37c9SBlue Swirl 
4348db6b81d4SAndreas Färber     thread_cpu = cpu;
434954936004Sbellard 
4350b92c47c1Sths     if (getenv("QEMU_STRACE")) {
4351b92c47c1Sths         do_strace = 1;
4352b92c47c1Sths     }
4353b92c47c1Sths 
4354c5e4a5a9SMagnus Reftel     if (getenv("QEMU_RAND_SEED")) {
4355c5e4a5a9SMagnus Reftel         handle_arg_randseed(getenv("QEMU_RAND_SEED"));
4356c5e4a5a9SMagnus Reftel     }
4357c5e4a5a9SMagnus Reftel 
435804a6dfebSaurel32     target_environ = envlist_to_environ(envlist, NULL);
435904a6dfebSaurel32     envlist_free(envlist);
4360b12b6a18Sths 
4361379f6698SPaul Brook     /*
4362379f6698SPaul Brook      * Now that page sizes are configured in cpu_init() we can do
4363379f6698SPaul Brook      * proper page alignment for guest_base.
4364379f6698SPaul Brook      */
4365379f6698SPaul Brook     guest_base = HOST_PAGE_ALIGN(guest_base);
436668a1c816SPaul Brook 
436797cc7560SDr. David Alan Gilbert     if (reserved_va || have_guest_base) {
4368806d1021SMeador Inge         guest_base = init_guest_space(guest_base, reserved_va, 0,
4369806d1021SMeador Inge                                       have_guest_base);
4370806d1021SMeador Inge         if (guest_base == (unsigned long)-1) {
4371097b8cb8SPeter Maydell             fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
4372097b8cb8SPeter Maydell                     "space for use as guest address space (check your virtual "
4373097b8cb8SPeter Maydell                     "memory ulimit setting or reserve less using -R option)\n",
4374097b8cb8SPeter Maydell                     reserved_va);
43754d1275c2SRiku Voipio             exit(EXIT_FAILURE);
437697cc7560SDr. David Alan Gilbert         }
4377806d1021SMeador Inge 
4378806d1021SMeador Inge         if (reserved_va) {
4379806d1021SMeador Inge             mmap_next_start = reserved_va;
4380806d1021SMeador Inge         }
438197cc7560SDr. David Alan Gilbert     }
4382379f6698SPaul Brook 
4383379f6698SPaul Brook     /*
4384379f6698SPaul Brook      * Read in mmap_min_addr kernel parameter.  This value is used
4385379f6698SPaul Brook      * When loading the ELF image to determine whether guest_base
438614f24e14SRichard Henderson      * is needed.  It is also used in mmap_find_vma.
4387379f6698SPaul Brook      */
438814f24e14SRichard Henderson     {
4389379f6698SPaul Brook         FILE *fp;
4390379f6698SPaul Brook 
4391379f6698SPaul Brook         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
4392379f6698SPaul Brook             unsigned long tmp;
4393379f6698SPaul Brook             if (fscanf(fp, "%lu", &tmp) == 1) {
4394379f6698SPaul Brook                 mmap_min_addr = tmp;
439513829020SPaolo Bonzini                 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr);
4396379f6698SPaul Brook             }
4397379f6698SPaul Brook             fclose(fp);
4398379f6698SPaul Brook         }
4399379f6698SPaul Brook     }
4400379f6698SPaul Brook 
44017d8cec95Saurel32     /*
44027d8cec95Saurel32      * Prepare copy of argv vector for target.
44037d8cec95Saurel32      */
44047d8cec95Saurel32     target_argc = argc - optind;
44057d8cec95Saurel32     target_argv = calloc(target_argc + 1, sizeof (char *));
44067d8cec95Saurel32     if (target_argv == NULL) {
44077d8cec95Saurel32 	(void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
44084d1275c2SRiku Voipio 	exit(EXIT_FAILURE);
44097d8cec95Saurel32     }
44107d8cec95Saurel32 
44117d8cec95Saurel32     /*
44127d8cec95Saurel32      * If argv0 is specified (using '-0' switch) we replace
44137d8cec95Saurel32      * argv[0] pointer with the given one.
44147d8cec95Saurel32      */
44157d8cec95Saurel32     i = 0;
44167d8cec95Saurel32     if (argv0 != NULL) {
44177d8cec95Saurel32         target_argv[i++] = strdup(argv0);
44187d8cec95Saurel32     }
44197d8cec95Saurel32     for (; i < target_argc; i++) {
44207d8cec95Saurel32         target_argv[i] = strdup(argv[optind + i]);
44217d8cec95Saurel32     }
44227d8cec95Saurel32     target_argv[target_argc] = NULL;
44237d8cec95Saurel32 
4424c78d65e8SMarkus Armbruster     ts = g_new0(TaskState, 1);
4425edf8e2afSMika Westerberg     init_task_state(ts);
4426edf8e2afSMika Westerberg     /* build Task State */
4427edf8e2afSMika Westerberg     ts->info = info;
4428edf8e2afSMika Westerberg     ts->bprm = &bprm;
44290429a971SAndreas Färber     cpu->opaque = ts;
4430edf8e2afSMika Westerberg     task_settid(ts);
4431edf8e2afSMika Westerberg 
44320b959cf5SRichard Henderson     execfd = qemu_getauxval(AT_EXECFD);
44330b959cf5SRichard Henderson     if (execfd == 0) {
443403cfd8faSLaurent Vivier         execfd = open(filename, O_RDONLY);
443503cfd8faSLaurent Vivier         if (execfd < 0) {
44360b959cf5SRichard Henderson             printf("Error while loading %s: %s\n", filename, strerror(errno));
44374d1275c2SRiku Voipio             _exit(EXIT_FAILURE);
443803cfd8faSLaurent Vivier         }
44390b959cf5SRichard Henderson     }
444003cfd8faSLaurent Vivier 
444103cfd8faSLaurent Vivier     ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
4442fd4d81ddSArnaud Patard         info, &bprm);
4443fd4d81ddSArnaud Patard     if (ret != 0) {
4444885c1d10SPeter Maydell         printf("Error while loading %s: %s\n", filename, strerror(-ret));
44454d1275c2SRiku Voipio         _exit(EXIT_FAILURE);
444631e31b8aSbellard     }
444731e31b8aSbellard 
4448b12b6a18Sths     for (wrk = target_environ; *wrk; wrk++) {
4449ec45bbe5SSaurav Sachidanand         g_free(*wrk);
4450b12b6a18Sths     }
4451b12b6a18Sths 
4452ec45bbe5SSaurav Sachidanand     g_free(target_environ);
4453b12b6a18Sths 
445413829020SPaolo Bonzini     if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
4455379f6698SPaul Brook         qemu_log("guest_base  0x%lx\n", guest_base);
445693fcfe39Saliguori         log_page_dump();
445754936004Sbellard 
445893fcfe39Saliguori         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
445993fcfe39Saliguori         qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
44607c4ee5bcSRichard Henderson         qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n", info->start_code);
44617c4ee5bcSRichard Henderson         qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n", info->start_data);
446293fcfe39Saliguori         qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
44637c4ee5bcSRichard Henderson         qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", info->start_stack);
446493fcfe39Saliguori         qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
446593fcfe39Saliguori         qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
44667c4ee5bcSRichard Henderson         qemu_log("argv_start  0x" TARGET_ABI_FMT_lx "\n", info->arg_start);
44677c4ee5bcSRichard Henderson         qemu_log("env_start   0x" TARGET_ABI_FMT_lx "\n",
44687c4ee5bcSRichard Henderson                  info->arg_end + (abi_ulong)sizeof(abi_ulong));
44697c4ee5bcSRichard Henderson         qemu_log("auxv_start  0x" TARGET_ABI_FMT_lx "\n", info->saved_auxv);
44702e77eac6Sblueswir1     }
447131e31b8aSbellard 
447253a5960aSpbrook     target_set_brk(info->brk);
447331e31b8aSbellard     syscall_init();
447466fb9763Sbellard     signal_init();
447531e31b8aSbellard 
44769002ec79SRichard Henderson     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
44779002ec79SRichard Henderson        generating the prologue until now so that the prologue can take
44789002ec79SRichard Henderson        the real value of GUEST_BASE into account.  */
4479*b1311c4aSEmilio G. Cota     tcg_prologue_init(tcg_ctx);
44809002ec79SRichard Henderson 
4481b346ff46Sbellard #if defined(TARGET_I386)
44823802ce26Sbellard     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
4483b98dbc90SPaolo Bonzini     env->hflags |= HF_PE_MASK | HF_CPL_MASK;
44840514ef2fSEduardo Habkost     if (env->features[FEAT_1_EDX] & CPUID_SSE) {
44851bde465eSbellard         env->cr[4] |= CR4_OSFXSR_MASK;
44861bde465eSbellard         env->hflags |= HF_OSFXSR_MASK;
44871bde465eSbellard     }
4488d2fd1af7Sbellard #ifndef TARGET_ABI32
44894dbc422bSbellard     /* enable 64 bit mode if possible */
44900514ef2fSEduardo Habkost     if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
44914dbc422bSbellard         fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
44924d1275c2SRiku Voipio         exit(EXIT_FAILURE);
44934dbc422bSbellard     }
4494d2fd1af7Sbellard     env->cr[4] |= CR4_PAE_MASK;
44954dbc422bSbellard     env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
4496d2fd1af7Sbellard     env->hflags |= HF_LMA_MASK;
4497d2fd1af7Sbellard #endif
44983802ce26Sbellard 
4499415e561fSbellard     /* flags setup : we activate the IRQs by default as in user mode */
4500415e561fSbellard     env->eflags |= IF_MASK;
4501415e561fSbellard 
45026dbad63eSbellard     /* linux register setup */
4503d2fd1af7Sbellard #ifndef TARGET_ABI32
450484409ddbSj_mayer     env->regs[R_EAX] = regs->rax;
450584409ddbSj_mayer     env->regs[R_EBX] = regs->rbx;
450684409ddbSj_mayer     env->regs[R_ECX] = regs->rcx;
450784409ddbSj_mayer     env->regs[R_EDX] = regs->rdx;
450884409ddbSj_mayer     env->regs[R_ESI] = regs->rsi;
450984409ddbSj_mayer     env->regs[R_EDI] = regs->rdi;
451084409ddbSj_mayer     env->regs[R_EBP] = regs->rbp;
451184409ddbSj_mayer     env->regs[R_ESP] = regs->rsp;
451284409ddbSj_mayer     env->eip = regs->rip;
451384409ddbSj_mayer #else
45140ecfa993Sbellard     env->regs[R_EAX] = regs->eax;
45150ecfa993Sbellard     env->regs[R_EBX] = regs->ebx;
45160ecfa993Sbellard     env->regs[R_ECX] = regs->ecx;
45170ecfa993Sbellard     env->regs[R_EDX] = regs->edx;
45180ecfa993Sbellard     env->regs[R_ESI] = regs->esi;
45190ecfa993Sbellard     env->regs[R_EDI] = regs->edi;
45200ecfa993Sbellard     env->regs[R_EBP] = regs->ebp;
45210ecfa993Sbellard     env->regs[R_ESP] = regs->esp;
4522dab2ed99Sbellard     env->eip = regs->eip;
452384409ddbSj_mayer #endif
452431e31b8aSbellard 
4525f4beb510Sbellard     /* linux interrupt setup */
4526e441570fSbalrog #ifndef TARGET_ABI32
4527e441570fSbalrog     env->idt.limit = 511;
4528e441570fSbalrog #else
4529e441570fSbalrog     env->idt.limit = 255;
4530e441570fSbalrog #endif
4531e441570fSbalrog     env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
4532e441570fSbalrog                                 PROT_READ|PROT_WRITE,
4533e441570fSbalrog                                 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
4534e441570fSbalrog     idt_table = g2h(env->idt.base);
4535f4beb510Sbellard     set_idt(0, 0);
4536f4beb510Sbellard     set_idt(1, 0);
4537f4beb510Sbellard     set_idt(2, 0);
4538f4beb510Sbellard     set_idt(3, 3);
4539f4beb510Sbellard     set_idt(4, 3);
4540ec95da6cSbellard     set_idt(5, 0);
4541f4beb510Sbellard     set_idt(6, 0);
4542f4beb510Sbellard     set_idt(7, 0);
4543f4beb510Sbellard     set_idt(8, 0);
4544f4beb510Sbellard     set_idt(9, 0);
4545f4beb510Sbellard     set_idt(10, 0);
4546f4beb510Sbellard     set_idt(11, 0);
4547f4beb510Sbellard     set_idt(12, 0);
4548f4beb510Sbellard     set_idt(13, 0);
4549f4beb510Sbellard     set_idt(14, 0);
4550f4beb510Sbellard     set_idt(15, 0);
4551f4beb510Sbellard     set_idt(16, 0);
4552f4beb510Sbellard     set_idt(17, 0);
4553f4beb510Sbellard     set_idt(18, 0);
4554f4beb510Sbellard     set_idt(19, 0);
4555f4beb510Sbellard     set_idt(0x80, 3);
4556f4beb510Sbellard 
45576dbad63eSbellard     /* linux segment setup */
45588d18e893Sbellard     {
45598d18e893Sbellard         uint64_t *gdt_table;
4560e441570fSbalrog         env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
4561e441570fSbalrog                                     PROT_READ|PROT_WRITE,
4562e441570fSbalrog                                     MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
45638d18e893Sbellard         env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
4564e441570fSbalrog         gdt_table = g2h(env->gdt.base);
4565d2fd1af7Sbellard #ifdef TARGET_ABI32
4566f4beb510Sbellard         write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
4567f4beb510Sbellard                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
4568f4beb510Sbellard                  (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
4569d2fd1af7Sbellard #else
4570d2fd1af7Sbellard         /* 64 bit code segment */
4571d2fd1af7Sbellard         write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
4572d2fd1af7Sbellard                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
4573d2fd1af7Sbellard                  DESC_L_MASK |
4574d2fd1af7Sbellard                  (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
4575d2fd1af7Sbellard #endif
4576f4beb510Sbellard         write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
4577f4beb510Sbellard                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
4578f4beb510Sbellard                  (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
45798d18e893Sbellard     }
45806dbad63eSbellard     cpu_x86_load_seg(env, R_CS, __USER_CS);
4581d2fd1af7Sbellard     cpu_x86_load_seg(env, R_SS, __USER_DS);
4582d2fd1af7Sbellard #ifdef TARGET_ABI32
45836dbad63eSbellard     cpu_x86_load_seg(env, R_DS, __USER_DS);
45846dbad63eSbellard     cpu_x86_load_seg(env, R_ES, __USER_DS);
45856dbad63eSbellard     cpu_x86_load_seg(env, R_FS, __USER_DS);
45866dbad63eSbellard     cpu_x86_load_seg(env, R_GS, __USER_DS);
4587d6eb40f6Sths     /* This hack makes Wine work... */
4588d6eb40f6Sths     env->segs[R_FS].selector = 0;
4589d2fd1af7Sbellard #else
4590d2fd1af7Sbellard     cpu_x86_load_seg(env, R_DS, 0);
4591d2fd1af7Sbellard     cpu_x86_load_seg(env, R_ES, 0);
4592d2fd1af7Sbellard     cpu_x86_load_seg(env, R_FS, 0);
4593d2fd1af7Sbellard     cpu_x86_load_seg(env, R_GS, 0);
4594d2fd1af7Sbellard #endif
459599033caeSAlexander Graf #elif defined(TARGET_AARCH64)
459699033caeSAlexander Graf     {
459799033caeSAlexander Graf         int i;
459899033caeSAlexander Graf 
459999033caeSAlexander Graf         if (!(arm_feature(env, ARM_FEATURE_AARCH64))) {
460099033caeSAlexander Graf             fprintf(stderr,
460199033caeSAlexander Graf                     "The selected ARM CPU does not support 64 bit mode\n");
46024d1275c2SRiku Voipio             exit(EXIT_FAILURE);
460399033caeSAlexander Graf         }
460499033caeSAlexander Graf 
460599033caeSAlexander Graf         for (i = 0; i < 31; i++) {
460699033caeSAlexander Graf             env->xregs[i] = regs->regs[i];
460799033caeSAlexander Graf         }
460899033caeSAlexander Graf         env->pc = regs->pc;
460999033caeSAlexander Graf         env->xregs[31] = regs->sp;
461099033caeSAlexander Graf     }
4611b346ff46Sbellard #elif defined(TARGET_ARM)
4612b346ff46Sbellard     {
4613b346ff46Sbellard         int i;
4614ae087923SPeter Maydell         cpsr_write(env, regs->uregs[16], CPSR_USER | CPSR_EXEC,
4615ae087923SPeter Maydell                    CPSRWriteByInstr);
4616b346ff46Sbellard         for(i = 0; i < 16; i++) {
4617b346ff46Sbellard             env->regs[i] = regs->uregs[i];
4618b346ff46Sbellard         }
4619f9fd40ebSPaolo Bonzini #ifdef TARGET_WORDS_BIGENDIAN
4620d8fd2954SPaul Brook         /* Enable BE8.  */
4621d8fd2954SPaul Brook         if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
4622d8fd2954SPaul Brook             && (info->elf_flags & EF_ARM_BE8)) {
46239c5a7460SPeter Crosthwaite             env->uncached_cpsr |= CPSR_E;
46249c5a7460SPeter Crosthwaite             env->cp15.sctlr_el[1] |= SCTLR_E0E;
4625f9fd40ebSPaolo Bonzini         } else {
4626f9fd40ebSPaolo Bonzini             env->cp15.sctlr_el[1] |= SCTLR_B;
4627d8fd2954SPaul Brook         }
4628f9fd40ebSPaolo Bonzini #endif
4629b346ff46Sbellard     }
4630d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32)
4631d2fbca94SGuan Xuetao     {
4632d2fbca94SGuan Xuetao         int i;
4633d2fbca94SGuan Xuetao         cpu_asr_write(env, regs->uregs[32], 0xffffffff);
4634d2fbca94SGuan Xuetao         for (i = 0; i < 32; i++) {
4635d2fbca94SGuan Xuetao             env->regs[i] = regs->uregs[i];
4636d2fbca94SGuan Xuetao         }
4637d2fbca94SGuan Xuetao     }
463893ac68bcSbellard #elif defined(TARGET_SPARC)
4639060366c5Sbellard     {
4640060366c5Sbellard         int i;
4641060366c5Sbellard 	env->pc = regs->pc;
4642060366c5Sbellard 	env->npc = regs->npc;
4643060366c5Sbellard         env->y = regs->y;
4644060366c5Sbellard         for(i = 0; i < 8; i++)
4645060366c5Sbellard             env->gregs[i] = regs->u_regs[i];
4646060366c5Sbellard         for(i = 0; i < 8; i++)
4647060366c5Sbellard             env->regwptr[i] = regs->u_regs[i + 8];
4648060366c5Sbellard     }
464967867308Sbellard #elif defined(TARGET_PPC)
465067867308Sbellard     {
465167867308Sbellard         int i;
46523fc6c082Sbellard 
46530411a972Sj_mayer #if defined(TARGET_PPC64)
4654c8361129SMichael Walle         int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF;
46550411a972Sj_mayer #if defined(TARGET_ABI32)
4656c8361129SMichael Walle         env->msr &= ~((target_ulong)1 << flag);
4657e85e7c6eSj_mayer #else
4658c8361129SMichael Walle         env->msr |= (target_ulong)1 << flag;
46590411a972Sj_mayer #endif
466084409ddbSj_mayer #endif
466167867308Sbellard         env->nip = regs->nip;
466267867308Sbellard         for(i = 0; i < 32; i++) {
466367867308Sbellard             env->gpr[i] = regs->gpr[i];
466467867308Sbellard         }
466567867308Sbellard     }
4666e6e5906bSpbrook #elif defined(TARGET_M68K)
4667e6e5906bSpbrook     {
4668e6e5906bSpbrook         env->pc = regs->pc;
4669e6e5906bSpbrook         env->dregs[0] = regs->d0;
4670e6e5906bSpbrook         env->dregs[1] = regs->d1;
4671e6e5906bSpbrook         env->dregs[2] = regs->d2;
4672e6e5906bSpbrook         env->dregs[3] = regs->d3;
4673e6e5906bSpbrook         env->dregs[4] = regs->d4;
4674e6e5906bSpbrook         env->dregs[5] = regs->d5;
4675e6e5906bSpbrook         env->dregs[6] = regs->d6;
4676e6e5906bSpbrook         env->dregs[7] = regs->d7;
4677e6e5906bSpbrook         env->aregs[0] = regs->a0;
4678e6e5906bSpbrook         env->aregs[1] = regs->a1;
4679e6e5906bSpbrook         env->aregs[2] = regs->a2;
4680e6e5906bSpbrook         env->aregs[3] = regs->a3;
4681e6e5906bSpbrook         env->aregs[4] = regs->a4;
4682e6e5906bSpbrook         env->aregs[5] = regs->a5;
4683e6e5906bSpbrook         env->aregs[6] = regs->a6;
4684e6e5906bSpbrook         env->aregs[7] = regs->usp;
4685e6e5906bSpbrook         env->sr = regs->sr;
4686e6e5906bSpbrook         ts->sim_syscalls = 1;
4687e6e5906bSpbrook     }
4688b779e29eSEdgar E. Iglesias #elif defined(TARGET_MICROBLAZE)
4689b779e29eSEdgar E. Iglesias     {
4690b779e29eSEdgar E. Iglesias         env->regs[0] = regs->r0;
4691b779e29eSEdgar E. Iglesias         env->regs[1] = regs->r1;
4692b779e29eSEdgar E. Iglesias         env->regs[2] = regs->r2;
4693b779e29eSEdgar E. Iglesias         env->regs[3] = regs->r3;
4694b779e29eSEdgar E. Iglesias         env->regs[4] = regs->r4;
4695b779e29eSEdgar E. Iglesias         env->regs[5] = regs->r5;
4696b779e29eSEdgar E. Iglesias         env->regs[6] = regs->r6;
4697b779e29eSEdgar E. Iglesias         env->regs[7] = regs->r7;
4698b779e29eSEdgar E. Iglesias         env->regs[8] = regs->r8;
4699b779e29eSEdgar E. Iglesias         env->regs[9] = regs->r9;
4700b779e29eSEdgar E. Iglesias         env->regs[10] = regs->r10;
4701b779e29eSEdgar E. Iglesias         env->regs[11] = regs->r11;
4702b779e29eSEdgar E. Iglesias         env->regs[12] = regs->r12;
4703b779e29eSEdgar E. Iglesias         env->regs[13] = regs->r13;
4704b779e29eSEdgar E. Iglesias         env->regs[14] = regs->r14;
4705b779e29eSEdgar E. Iglesias         env->regs[15] = regs->r15;
4706b779e29eSEdgar E. Iglesias         env->regs[16] = regs->r16;
4707b779e29eSEdgar E. Iglesias         env->regs[17] = regs->r17;
4708b779e29eSEdgar E. Iglesias         env->regs[18] = regs->r18;
4709b779e29eSEdgar E. Iglesias         env->regs[19] = regs->r19;
4710b779e29eSEdgar E. Iglesias         env->regs[20] = regs->r20;
4711b779e29eSEdgar E. Iglesias         env->regs[21] = regs->r21;
4712b779e29eSEdgar E. Iglesias         env->regs[22] = regs->r22;
4713b779e29eSEdgar E. Iglesias         env->regs[23] = regs->r23;
4714b779e29eSEdgar E. Iglesias         env->regs[24] = regs->r24;
4715b779e29eSEdgar E. Iglesias         env->regs[25] = regs->r25;
4716b779e29eSEdgar E. Iglesias         env->regs[26] = regs->r26;
4717b779e29eSEdgar E. Iglesias         env->regs[27] = regs->r27;
4718b779e29eSEdgar E. Iglesias         env->regs[28] = regs->r28;
4719b779e29eSEdgar E. Iglesias         env->regs[29] = regs->r29;
4720b779e29eSEdgar E. Iglesias         env->regs[30] = regs->r30;
4721b779e29eSEdgar E. Iglesias         env->regs[31] = regs->r31;
4722b779e29eSEdgar E. Iglesias         env->sregs[SR_PC] = regs->pc;
4723b779e29eSEdgar E. Iglesias     }
4724048f6b4dSbellard #elif defined(TARGET_MIPS)
4725048f6b4dSbellard     {
4726048f6b4dSbellard         int i;
4727048f6b4dSbellard 
4728048f6b4dSbellard         for(i = 0; i < 32; i++) {
4729b5dc7732Sths             env->active_tc.gpr[i] = regs->regs[i];
4730048f6b4dSbellard         }
47310fddbbf2SNathan Froyd         env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
47320fddbbf2SNathan Froyd         if (regs->cp0_epc & 1) {
47330fddbbf2SNathan Froyd             env->hflags |= MIPS_HFLAG_M16;
47340fddbbf2SNathan Froyd         }
4735599bc5e8SAleksandar Markovic         if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
4736599bc5e8SAleksandar Markovic             ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
4737599bc5e8SAleksandar Markovic             if ((env->active_fpu.fcr31_rw_bitmask &
4738599bc5e8SAleksandar Markovic                   (1 << FCR31_NAN2008)) == 0) {
4739599bc5e8SAleksandar Markovic                 fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
4740599bc5e8SAleksandar Markovic                 exit(1);
4741599bc5e8SAleksandar Markovic             }
4742599bc5e8SAleksandar Markovic             if ((info->elf_flags & EF_MIPS_NAN2008) != 0) {
4743599bc5e8SAleksandar Markovic                 env->active_fpu.fcr31 |= (1 << FCR31_NAN2008);
4744599bc5e8SAleksandar Markovic             } else {
4745599bc5e8SAleksandar Markovic                 env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008);
4746599bc5e8SAleksandar Markovic             }
4747599bc5e8SAleksandar Markovic             restore_snan_bit_mode(env);
4748599bc5e8SAleksandar Markovic         }
4749048f6b4dSbellard     }
4750a0a839b6SMarek Vasut #elif defined(TARGET_NIOS2)
4751a0a839b6SMarek Vasut     {
4752a0a839b6SMarek Vasut         env->regs[0] = 0;
4753a0a839b6SMarek Vasut         env->regs[1] = regs->r1;
4754a0a839b6SMarek Vasut         env->regs[2] = regs->r2;
4755a0a839b6SMarek Vasut         env->regs[3] = regs->r3;
4756a0a839b6SMarek Vasut         env->regs[4] = regs->r4;
4757a0a839b6SMarek Vasut         env->regs[5] = regs->r5;
4758a0a839b6SMarek Vasut         env->regs[6] = regs->r6;
4759a0a839b6SMarek Vasut         env->regs[7] = regs->r7;
4760a0a839b6SMarek Vasut         env->regs[8] = regs->r8;
4761a0a839b6SMarek Vasut         env->regs[9] = regs->r9;
4762a0a839b6SMarek Vasut         env->regs[10] = regs->r10;
4763a0a839b6SMarek Vasut         env->regs[11] = regs->r11;
4764a0a839b6SMarek Vasut         env->regs[12] = regs->r12;
4765a0a839b6SMarek Vasut         env->regs[13] = regs->r13;
4766a0a839b6SMarek Vasut         env->regs[14] = regs->r14;
4767a0a839b6SMarek Vasut         env->regs[15] = regs->r15;
4768a0a839b6SMarek Vasut         /* TODO: unsigned long  orig_r2; */
4769a0a839b6SMarek Vasut         env->regs[R_RA] = regs->ra;
4770a0a839b6SMarek Vasut         env->regs[R_FP] = regs->fp;
4771a0a839b6SMarek Vasut         env->regs[R_SP] = regs->sp;
4772a0a839b6SMarek Vasut         env->regs[R_GP] = regs->gp;
4773a0a839b6SMarek Vasut         env->regs[CR_ESTATUS] = regs->estatus;
4774a0a839b6SMarek Vasut         env->regs[R_EA] = regs->ea;
4775a0a839b6SMarek Vasut         /* TODO: unsigned long  orig_r7; */
4776a0a839b6SMarek Vasut 
4777a0a839b6SMarek Vasut         /* Emulate eret when starting thread. */
4778a0a839b6SMarek Vasut         env->regs[R_PC] = regs->ea;
4779a0a839b6SMarek Vasut     }
4780d962783eSJia Liu #elif defined(TARGET_OPENRISC)
4781d962783eSJia Liu     {
4782d962783eSJia Liu         int i;
4783d962783eSJia Liu 
4784d962783eSJia Liu         for (i = 0; i < 32; i++) {
4785d89e71e8SStafford Horne             cpu_set_gpr(env, i, regs->gpr[i]);
4786d962783eSJia Liu         }
4787d962783eSJia Liu         env->pc = regs->pc;
478884775c43SRichard Henderson         cpu_set_sr(env, regs->sr);
4789d962783eSJia Liu     }
4790fdf9b3e8Sbellard #elif defined(TARGET_SH4)
4791fdf9b3e8Sbellard     {
4792fdf9b3e8Sbellard         int i;
4793fdf9b3e8Sbellard 
4794fdf9b3e8Sbellard         for(i = 0; i < 16; i++) {
4795fdf9b3e8Sbellard             env->gregs[i] = regs->regs[i];
4796fdf9b3e8Sbellard         }
4797fdf9b3e8Sbellard         env->pc = regs->pc;
4798fdf9b3e8Sbellard     }
47997a3148a9Sj_mayer #elif defined(TARGET_ALPHA)
48007a3148a9Sj_mayer     {
48017a3148a9Sj_mayer         int i;
48027a3148a9Sj_mayer 
48037a3148a9Sj_mayer         for(i = 0; i < 28; i++) {
4804992f48a0Sblueswir1             env->ir[i] = ((abi_ulong *)regs)[i];
48057a3148a9Sj_mayer         }
4806dad081eeSRichard Henderson         env->ir[IR_SP] = regs->usp;
48077a3148a9Sj_mayer         env->pc = regs->pc;
48087a3148a9Sj_mayer     }
480948733d19Sths #elif defined(TARGET_CRIS)
481048733d19Sths     {
481148733d19Sths 	    env->regs[0] = regs->r0;
481248733d19Sths 	    env->regs[1] = regs->r1;
481348733d19Sths 	    env->regs[2] = regs->r2;
481448733d19Sths 	    env->regs[3] = regs->r3;
481548733d19Sths 	    env->regs[4] = regs->r4;
481648733d19Sths 	    env->regs[5] = regs->r5;
481748733d19Sths 	    env->regs[6] = regs->r6;
481848733d19Sths 	    env->regs[7] = regs->r7;
481948733d19Sths 	    env->regs[8] = regs->r8;
482048733d19Sths 	    env->regs[9] = regs->r9;
482148733d19Sths 	    env->regs[10] = regs->r10;
482248733d19Sths 	    env->regs[11] = regs->r11;
482348733d19Sths 	    env->regs[12] = regs->r12;
482448733d19Sths 	    env->regs[13] = regs->r13;
482548733d19Sths 	    env->regs[14] = info->start_stack;
482648733d19Sths 	    env->regs[15] = regs->acr;
482748733d19Sths 	    env->pc = regs->erp;
482848733d19Sths     }
4829a4c075f1SUlrich Hecht #elif defined(TARGET_S390X)
4830a4c075f1SUlrich Hecht     {
4831a4c075f1SUlrich Hecht             int i;
4832a4c075f1SUlrich Hecht             for (i = 0; i < 16; i++) {
4833a4c075f1SUlrich Hecht                 env->regs[i] = regs->gprs[i];
4834a4c075f1SUlrich Hecht             }
4835a4c075f1SUlrich Hecht             env->psw.mask = regs->psw.mask;
4836a4c075f1SUlrich Hecht             env->psw.addr = regs->psw.addr;
4837a4c075f1SUlrich Hecht     }
4838b16189b2SChen Gang #elif defined(TARGET_TILEGX)
4839b16189b2SChen Gang     {
4840b16189b2SChen Gang         int i;
4841b16189b2SChen Gang         for (i = 0; i < TILEGX_R_COUNT; i++) {
4842b16189b2SChen Gang             env->regs[i] = regs->regs[i];
4843b16189b2SChen Gang         }
4844b16189b2SChen Gang         for (i = 0; i < TILEGX_SPR_COUNT; i++) {
4845b16189b2SChen Gang             env->spregs[i] = 0;
4846b16189b2SChen Gang         }
4847b16189b2SChen Gang         env->pc = regs->pc;
4848b16189b2SChen Gang     }
48497c248bcdSRichard Henderson #elif defined(TARGET_HPPA)
48507c248bcdSRichard Henderson     {
48517c248bcdSRichard Henderson         int i;
48527c248bcdSRichard Henderson         for (i = 1; i < 32; i++) {
48537c248bcdSRichard Henderson             env->gr[i] = regs->gr[i];
48547c248bcdSRichard Henderson         }
48557c248bcdSRichard Henderson         env->iaoq_f = regs->iaoq[0];
48567c248bcdSRichard Henderson         env->iaoq_b = regs->iaoq[1];
48577c248bcdSRichard Henderson     }
4858b346ff46Sbellard #else
4859b346ff46Sbellard #error unsupported target CPU
4860b346ff46Sbellard #endif
486131e31b8aSbellard 
4862d2fbca94SGuan Xuetao #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
4863a87295e8Spbrook     ts->stack_base = info->start_stack;
4864a87295e8Spbrook     ts->heap_base = info->brk;
4865a87295e8Spbrook     /* This will be filled in on the first SYS_HEAPINFO call.  */
4866a87295e8Spbrook     ts->heap_limit = 0;
4867a87295e8Spbrook #endif
4868a87295e8Spbrook 
486974c33bedSbellard     if (gdbstub_port) {
4870ff7a981aSPeter Maydell         if (gdbserver_start(gdbstub_port) < 0) {
4871ff7a981aSPeter Maydell             fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
4872ff7a981aSPeter Maydell                     gdbstub_port);
48734d1275c2SRiku Voipio             exit(EXIT_FAILURE);
4874ff7a981aSPeter Maydell         }
4875db6b81d4SAndreas Färber         gdb_handlesig(cpu, 0);
48761fddef4bSbellard     }
48771b6b029eSbellard     cpu_loop(env);
48781b6b029eSbellard     /* never exits */
487931e31b8aSbellard     return 0;
488031e31b8aSbellard }
4881