Statistics
| Branch: | Revision:

root / linux-user / main.c @ 3475187d

History | View | Annotate | Download (39.2 kB)

1 31e31b8a bellard
/*
2 93ac68bc bellard
 *  qemu user main
3 31e31b8a bellard
 * 
4 31e31b8a bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 31e31b8a bellard
 *
6 31e31b8a bellard
 *  This program is free software; you can redistribute it and/or modify
7 31e31b8a bellard
 *  it under the terms of the GNU General Public License as published by
8 31e31b8a bellard
 *  the Free Software Foundation; either version 2 of the License, or
9 31e31b8a bellard
 *  (at your option) any later version.
10 31e31b8a bellard
 *
11 31e31b8a bellard
 *  This program is distributed in the hope that it will be useful,
12 31e31b8a bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 31e31b8a bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 31e31b8a bellard
 *  GNU General Public License for more details.
15 31e31b8a bellard
 *
16 31e31b8a bellard
 *  You should have received a copy of the GNU General Public License
17 31e31b8a bellard
 *  along with this program; if not, write to the Free Software
18 31e31b8a bellard
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 31e31b8a bellard
 */
20 31e31b8a bellard
#include <stdlib.h>
21 31e31b8a bellard
#include <stdio.h>
22 31e31b8a bellard
#include <stdarg.h>
23 04369ff2 bellard
#include <string.h>
24 31e31b8a bellard
#include <errno.h>
25 0ecfa993 bellard
#include <unistd.h>
26 31e31b8a bellard
27 3ef693a0 bellard
#include "qemu.h"
28 31e31b8a bellard
29 3ef693a0 bellard
#define DEBUG_LOGFILE "/tmp/qemu.log"
30 586314f2 bellard
31 83fb7adf bellard
#ifdef __APPLE__
32 83fb7adf bellard
#include <crt_externs.h>
33 83fb7adf bellard
# define environ  (*_NSGetEnviron())
34 83fb7adf bellard
#endif
35 83fb7adf bellard
36 74cd30b8 bellard
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
37 586314f2 bellard
38 3a4739d6 bellard
#if defined(__i386__) && !defined(CONFIG_STATIC)
39 f801f97e bellard
/* Force usage of an ELF interpreter even if it is an ELF shared
40 f801f97e bellard
   object ! */
41 f801f97e bellard
const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
42 4304763b bellard
#endif
43 74cd30b8 bellard
44 93ac68bc bellard
/* for recent libc, we add these dummy symbols which are not declared
45 74cd30b8 bellard
   when generating a linked object (bug in ld ?) */
46 fbf59244 bellard
#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
47 c6981055 bellard
long __preinit_array_start[0];
48 c6981055 bellard
long __preinit_array_end[0];
49 74cd30b8 bellard
long __init_array_start[0];
50 74cd30b8 bellard
long __init_array_end[0];
51 74cd30b8 bellard
long __fini_array_start[0];
52 74cd30b8 bellard
long __fini_array_end[0];
53 74cd30b8 bellard
#endif
54 74cd30b8 bellard
55 9de5e440 bellard
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
56 9de5e440 bellard
   we allocate a bigger stack. Need a better solution, for example
57 9de5e440 bellard
   by remapping the process stack directly at the right place */
58 9de5e440 bellard
unsigned long x86_stack_size = 512 * 1024;
59 31e31b8a bellard
60 31e31b8a bellard
void gemu_log(const char *fmt, ...)
61 31e31b8a bellard
{
62 31e31b8a bellard
    va_list ap;
63 31e31b8a bellard
64 31e31b8a bellard
    va_start(ap, fmt);
65 31e31b8a bellard
    vfprintf(stderr, fmt, ap);
66 31e31b8a bellard
    va_end(ap);
67 31e31b8a bellard
}
68 31e31b8a bellard
69 61190b14 bellard
void cpu_outb(CPUState *env, int addr, int val)
70 367e86e8 bellard
{
71 367e86e8 bellard
    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
72 367e86e8 bellard
}
73 367e86e8 bellard
74 61190b14 bellard
void cpu_outw(CPUState *env, int addr, int val)
75 367e86e8 bellard
{
76 367e86e8 bellard
    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
77 367e86e8 bellard
}
78 367e86e8 bellard
79 61190b14 bellard
void cpu_outl(CPUState *env, int addr, int val)
80 367e86e8 bellard
{
81 367e86e8 bellard
    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
82 367e86e8 bellard
}
83 367e86e8 bellard
84 61190b14 bellard
int cpu_inb(CPUState *env, int addr)
85 367e86e8 bellard
{
86 367e86e8 bellard
    fprintf(stderr, "inb: port=0x%04x\n", addr);
87 367e86e8 bellard
    return 0;
88 367e86e8 bellard
}
89 367e86e8 bellard
90 61190b14 bellard
int cpu_inw(CPUState *env, int addr)
91 367e86e8 bellard
{
92 367e86e8 bellard
    fprintf(stderr, "inw: port=0x%04x\n", addr);
93 367e86e8 bellard
    return 0;
94 367e86e8 bellard
}
95 367e86e8 bellard
96 61190b14 bellard
int cpu_inl(CPUState *env, int addr)
97 367e86e8 bellard
{
98 367e86e8 bellard
    fprintf(stderr, "inl: port=0x%04x\n", addr);
99 367e86e8 bellard
    return 0;
100 367e86e8 bellard
}
101 367e86e8 bellard
102 a541f297 bellard
int cpu_get_pic_interrupt(CPUState *env)
103 92ccca6a bellard
{
104 92ccca6a bellard
    return -1;
105 92ccca6a bellard
}
106 92ccca6a bellard
107 28ab0e2e bellard
/* timers for rdtsc */
108 28ab0e2e bellard
109 28ab0e2e bellard
#if defined(__i386__)
110 28ab0e2e bellard
111 28ab0e2e bellard
int64_t cpu_get_real_ticks(void)
112 28ab0e2e bellard
{
113 28ab0e2e bellard
    int64_t val;
114 28ab0e2e bellard
    asm volatile ("rdtsc" : "=A" (val));
115 28ab0e2e bellard
    return val;
116 28ab0e2e bellard
}
117 28ab0e2e bellard
118 28ab0e2e bellard
#elif defined(__x86_64__)
119 28ab0e2e bellard
120 28ab0e2e bellard
int64_t cpu_get_real_ticks(void)
121 28ab0e2e bellard
{
122 28ab0e2e bellard
    uint32_t low,high;
123 28ab0e2e bellard
    int64_t val;
124 28ab0e2e bellard
    asm volatile("rdtsc" : "=a" (low), "=d" (high));
125 28ab0e2e bellard
    val = high;
126 28ab0e2e bellard
    val <<= 32;
127 28ab0e2e bellard
    val |= low;
128 28ab0e2e bellard
    return val;
129 28ab0e2e bellard
}
130 28ab0e2e bellard
131 28ab0e2e bellard
#else
132 28ab0e2e bellard
133 28ab0e2e bellard
static uint64_t emu_time;
134 28ab0e2e bellard
135 28ab0e2e bellard
int64_t cpu_get_real_ticks(void)
136 28ab0e2e bellard
{
137 28ab0e2e bellard
    return emu_time++;
138 28ab0e2e bellard
}
139 28ab0e2e bellard
140 28ab0e2e bellard
#endif
141 28ab0e2e bellard
142 a541f297 bellard
#ifdef TARGET_I386
143 a541f297 bellard
/***********************************************************/
144 a541f297 bellard
/* CPUX86 core interface */
145 a541f297 bellard
146 28ab0e2e bellard
uint64_t cpu_get_tsc(CPUX86State *env)
147 28ab0e2e bellard
{
148 28ab0e2e bellard
    return cpu_get_real_ticks();
149 28ab0e2e bellard
}
150 28ab0e2e bellard
151 f4beb510 bellard
static void write_dt(void *ptr, unsigned long addr, unsigned long limit, 
152 f4beb510 bellard
                     int flags)
153 6dbad63e bellard
{
154 f4beb510 bellard
    unsigned int e1, e2;
155 6dbad63e bellard
    e1 = (addr << 16) | (limit & 0xffff);
156 6dbad63e bellard
    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
157 f4beb510 bellard
    e2 |= flags;
158 f4beb510 bellard
    stl((uint8_t *)ptr, e1);
159 f4beb510 bellard
    stl((uint8_t *)ptr + 4, e2);
160 f4beb510 bellard
}
161 f4beb510 bellard
162 f4beb510 bellard
static void set_gate(void *ptr, unsigned int type, unsigned int dpl, 
163 f4beb510 bellard
                     unsigned long addr, unsigned int sel)
164 f4beb510 bellard
{
165 f4beb510 bellard
    unsigned int e1, e2;
166 f4beb510 bellard
    e1 = (addr & 0xffff) | (sel << 16);
167 f4beb510 bellard
    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
168 6dbad63e bellard
    stl((uint8_t *)ptr, e1);
169 6dbad63e bellard
    stl((uint8_t *)ptr + 4, e2);
170 6dbad63e bellard
}
171 6dbad63e bellard
172 6dbad63e bellard
uint64_t gdt_table[6];
173 f4beb510 bellard
uint64_t idt_table[256];
174 f4beb510 bellard
175 f4beb510 bellard
/* only dpl matters as we do only user space emulation */
176 f4beb510 bellard
static void set_idt(int n, unsigned int dpl)
177 f4beb510 bellard
{
178 f4beb510 bellard
    set_gate(idt_table + n, 0, dpl, 0, 0);
179 f4beb510 bellard
}
180 31e31b8a bellard
181 89e957e7 bellard
void cpu_loop(CPUX86State *env)
182 1b6b029e bellard
{
183 bc8a22cc bellard
    int trapnr;
184 80a9d035 bellard
    target_ulong pc;
185 9de5e440 bellard
    target_siginfo_t info;
186 851e67a1 bellard
187 1b6b029e bellard
    for(;;) {
188 bc8a22cc bellard
        trapnr = cpu_x86_exec(env);
189 bc8a22cc bellard
        switch(trapnr) {
190 f4beb510 bellard
        case 0x80:
191 f4beb510 bellard
            /* linux syscall */
192 f4beb510 bellard
            env->regs[R_EAX] = do_syscall(env, 
193 f4beb510 bellard
                                          env->regs[R_EAX], 
194 f4beb510 bellard
                                          env->regs[R_EBX],
195 f4beb510 bellard
                                          env->regs[R_ECX],
196 f4beb510 bellard
                                          env->regs[R_EDX],
197 f4beb510 bellard
                                          env->regs[R_ESI],
198 f4beb510 bellard
                                          env->regs[R_EDI],
199 f4beb510 bellard
                                          env->regs[R_EBP]);
200 f4beb510 bellard
            break;
201 f4beb510 bellard
        case EXCP0B_NOSEG:
202 f4beb510 bellard
        case EXCP0C_STACK:
203 f4beb510 bellard
            info.si_signo = SIGBUS;
204 f4beb510 bellard
            info.si_errno = 0;
205 f4beb510 bellard
            info.si_code = TARGET_SI_KERNEL;
206 f4beb510 bellard
            info._sifields._sigfault._addr = 0;
207 f4beb510 bellard
            queue_signal(info.si_signo, &info);
208 f4beb510 bellard
            break;
209 1b6b029e bellard
        case EXCP0D_GPF:
210 851e67a1 bellard
            if (env->eflags & VM_MASK) {
211 89e957e7 bellard
                handle_vm86_fault(env);
212 1b6b029e bellard
            } else {
213 f4beb510 bellard
                info.si_signo = SIGSEGV;
214 f4beb510 bellard
                info.si_errno = 0;
215 f4beb510 bellard
                info.si_code = TARGET_SI_KERNEL;
216 f4beb510 bellard
                info._sifields._sigfault._addr = 0;
217 f4beb510 bellard
                queue_signal(info.si_signo, &info);
218 1b6b029e bellard
            }
219 1b6b029e bellard
            break;
220 b689bc57 bellard
        case EXCP0E_PAGE:
221 b689bc57 bellard
            info.si_signo = SIGSEGV;
222 b689bc57 bellard
            info.si_errno = 0;
223 b689bc57 bellard
            if (!(env->error_code & 1))
224 b689bc57 bellard
                info.si_code = TARGET_SEGV_MAPERR;
225 b689bc57 bellard
            else
226 b689bc57 bellard
                info.si_code = TARGET_SEGV_ACCERR;
227 970a87a6 bellard
            info._sifields._sigfault._addr = env->cr[2];
228 b689bc57 bellard
            queue_signal(info.si_signo, &info);
229 b689bc57 bellard
            break;
230 9de5e440 bellard
        case EXCP00_DIVZ:
231 bc8a22cc bellard
            if (env->eflags & VM_MASK) {
232 447db213 bellard
                handle_vm86_trap(env, trapnr);
233 bc8a22cc bellard
            } else {
234 bc8a22cc bellard
                /* division by zero */
235 bc8a22cc bellard
                info.si_signo = SIGFPE;
236 bc8a22cc bellard
                info.si_errno = 0;
237 bc8a22cc bellard
                info.si_code = TARGET_FPE_INTDIV;
238 bc8a22cc bellard
                info._sifields._sigfault._addr = env->eip;
239 bc8a22cc bellard
                queue_signal(info.si_signo, &info);
240 bc8a22cc bellard
            }
241 9de5e440 bellard
            break;
242 447db213 bellard
        case EXCP01_SSTP:
243 447db213 bellard
        case EXCP03_INT3:
244 447db213 bellard
            if (env->eflags & VM_MASK) {
245 447db213 bellard
                handle_vm86_trap(env, trapnr);
246 447db213 bellard
            } else {
247 447db213 bellard
                info.si_signo = SIGTRAP;
248 447db213 bellard
                info.si_errno = 0;
249 447db213 bellard
                if (trapnr == EXCP01_SSTP) {
250 447db213 bellard
                    info.si_code = TARGET_TRAP_BRKPT;
251 447db213 bellard
                    info._sifields._sigfault._addr = env->eip;
252 447db213 bellard
                } else {
253 447db213 bellard
                    info.si_code = TARGET_SI_KERNEL;
254 447db213 bellard
                    info._sifields._sigfault._addr = 0;
255 447db213 bellard
                }
256 447db213 bellard
                queue_signal(info.si_signo, &info);
257 447db213 bellard
            }
258 447db213 bellard
            break;
259 9de5e440 bellard
        case EXCP04_INTO:
260 9de5e440 bellard
        case EXCP05_BOUND:
261 bc8a22cc bellard
            if (env->eflags & VM_MASK) {
262 447db213 bellard
                handle_vm86_trap(env, trapnr);
263 bc8a22cc bellard
            } else {
264 bc8a22cc bellard
                info.si_signo = SIGSEGV;
265 bc8a22cc bellard
                info.si_errno = 0;
266 b689bc57 bellard
                info.si_code = TARGET_SI_KERNEL;
267 bc8a22cc bellard
                info._sifields._sigfault._addr = 0;
268 bc8a22cc bellard
                queue_signal(info.si_signo, &info);
269 bc8a22cc bellard
            }
270 9de5e440 bellard
            break;
271 9de5e440 bellard
        case EXCP06_ILLOP:
272 9de5e440 bellard
            info.si_signo = SIGILL;
273 9de5e440 bellard
            info.si_errno = 0;
274 9de5e440 bellard
            info.si_code = TARGET_ILL_ILLOPN;
275 9de5e440 bellard
            info._sifields._sigfault._addr = env->eip;
276 9de5e440 bellard
            queue_signal(info.si_signo, &info);
277 9de5e440 bellard
            break;
278 9de5e440 bellard
        case EXCP_INTERRUPT:
279 9de5e440 bellard
            /* just indicate that signals should be handled asap */
280 9de5e440 bellard
            break;
281 1fddef4b bellard
        case EXCP_DEBUG:
282 1fddef4b bellard
            {
283 1fddef4b bellard
                int sig;
284 1fddef4b bellard
285 1fddef4b bellard
                sig = gdb_handlesig (env, TARGET_SIGTRAP);
286 1fddef4b bellard
                if (sig)
287 1fddef4b bellard
                  {
288 1fddef4b bellard
                    info.si_signo = sig;
289 1fddef4b bellard
                    info.si_errno = 0;
290 1fddef4b bellard
                    info.si_code = TARGET_TRAP_BRKPT;
291 1fddef4b bellard
                    queue_signal(info.si_signo, &info);
292 1fddef4b bellard
                  }
293 1fddef4b bellard
            }
294 1fddef4b bellard
            break;
295 1b6b029e bellard
        default:
296 970a87a6 bellard
            pc = env->segs[R_CS].base + env->eip;
297 bc8a22cc bellard
            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", 
298 bc8a22cc bellard
                    (long)pc, trapnr);
299 1b6b029e bellard
            abort();
300 1b6b029e bellard
        }
301 66fb9763 bellard
        process_pending_signals(env);
302 1b6b029e bellard
    }
303 1b6b029e bellard
}
304 b346ff46 bellard
#endif
305 b346ff46 bellard
306 b346ff46 bellard
#ifdef TARGET_ARM
307 b346ff46 bellard
308 6f1f31c0 bellard
/* XXX: find a better solution */
309 6f1f31c0 bellard
extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
310 6f1f31c0 bellard
311 6f1f31c0 bellard
static void arm_cache_flush(target_ulong start, target_ulong last)
312 6f1f31c0 bellard
{
313 6f1f31c0 bellard
    target_ulong addr, last1;
314 6f1f31c0 bellard
315 6f1f31c0 bellard
    if (last < start)
316 6f1f31c0 bellard
        return;
317 6f1f31c0 bellard
    addr = start;
318 6f1f31c0 bellard
    for(;;) {
319 6f1f31c0 bellard
        last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;
320 6f1f31c0 bellard
        if (last1 > last)
321 6f1f31c0 bellard
            last1 = last;
322 6f1f31c0 bellard
        tb_invalidate_page_range(addr, last1 + 1);
323 6f1f31c0 bellard
        if (last1 == last)
324 6f1f31c0 bellard
            break;
325 6f1f31c0 bellard
        addr = last1 + 1;
326 6f1f31c0 bellard
    }
327 6f1f31c0 bellard
}
328 6f1f31c0 bellard
329 b346ff46 bellard
void cpu_loop(CPUARMState *env)
330 b346ff46 bellard
{
331 b346ff46 bellard
    int trapnr;
332 b346ff46 bellard
    unsigned int n, insn;
333 b346ff46 bellard
    target_siginfo_t info;
334 b346ff46 bellard
    
335 b346ff46 bellard
    for(;;) {
336 b346ff46 bellard
        trapnr = cpu_arm_exec(env);
337 b346ff46 bellard
        switch(trapnr) {
338 b346ff46 bellard
        case EXCP_UDEF:
339 c6981055 bellard
            {
340 c6981055 bellard
                TaskState *ts = env->opaque;
341 c6981055 bellard
                uint32_t opcode;
342 c6981055 bellard
343 c6981055 bellard
                /* we handle the FPU emulation here, as Linux */
344 c6981055 bellard
                /* we get the opcode */
345 c6981055 bellard
                opcode = ldl_raw((uint8_t *)env->regs[15]);
346 c6981055 bellard
                
347 c6981055 bellard
                if (EmulateAll(opcode, &ts->fpa, env->regs) == 0) {
348 c6981055 bellard
                    info.si_signo = SIGILL;
349 c6981055 bellard
                    info.si_errno = 0;
350 c6981055 bellard
                    info.si_code = TARGET_ILL_ILLOPN;
351 c6981055 bellard
                    info._sifields._sigfault._addr = env->regs[15];
352 c6981055 bellard
                    queue_signal(info.si_signo, &info);
353 c6981055 bellard
                } else {
354 c6981055 bellard
                    /* increment PC */
355 c6981055 bellard
                    env->regs[15] += 4;
356 c6981055 bellard
                }
357 c6981055 bellard
            }
358 b346ff46 bellard
            break;
359 b346ff46 bellard
        case EXCP_SWI:
360 b346ff46 bellard
            {
361 b346ff46 bellard
                /* system call */
362 192c7bd9 bellard
                if (env->thumb) {
363 192c7bd9 bellard
                    insn = lduw((void *)(env->regs[15] - 2));
364 192c7bd9 bellard
                    n = insn & 0xff;
365 192c7bd9 bellard
                } else {
366 192c7bd9 bellard
                    insn = ldl((void *)(env->regs[15] - 4));
367 192c7bd9 bellard
                    n = insn & 0xffffff;
368 192c7bd9 bellard
                }
369 192c7bd9 bellard
370 6f1f31c0 bellard
                if (n == ARM_NR_cacheflush) {
371 6f1f31c0 bellard
                    arm_cache_flush(env->regs[0], env->regs[1]);
372 a4f81979 bellard
                } else if (n == ARM_NR_semihosting
373 a4f81979 bellard
                           || n == ARM_NR_thumb_semihosting) {
374 a4f81979 bellard
                    env->regs[0] = do_arm_semihosting (env);
375 192c7bd9 bellard
                } else if (n >= ARM_SYSCALL_BASE
376 192c7bd9 bellard
                           || (env->thumb && n == ARM_THUMB_SYSCALL)) {
377 b346ff46 bellard
                    /* linux syscall */
378 192c7bd9 bellard
                    if (env->thumb) {
379 192c7bd9 bellard
                        n = env->regs[7];
380 192c7bd9 bellard
                    } else {
381 192c7bd9 bellard
                        n -= ARM_SYSCALL_BASE;
382 192c7bd9 bellard
                    }
383 b346ff46 bellard
                    env->regs[0] = do_syscall(env, 
384 b346ff46 bellard
                                              n, 
385 b346ff46 bellard
                                              env->regs[0],
386 b346ff46 bellard
                                              env->regs[1],
387 b346ff46 bellard
                                              env->regs[2],
388 b346ff46 bellard
                                              env->regs[3],
389 b346ff46 bellard
                                              env->regs[4],
390 e1a2849c bellard
                                              env->regs[5]);
391 b346ff46 bellard
                } else {
392 b346ff46 bellard
                    goto error;
393 b346ff46 bellard
                }
394 b346ff46 bellard
            }
395 b346ff46 bellard
            break;
396 43fff238 bellard
        case EXCP_INTERRUPT:
397 43fff238 bellard
            /* just indicate that signals should be handled asap */
398 43fff238 bellard
            break;
399 68016c62 bellard
        case EXCP_PREFETCH_ABORT:
400 68016c62 bellard
        case EXCP_DATA_ABORT:
401 68016c62 bellard
            {
402 68016c62 bellard
                info.si_signo = SIGSEGV;
403 68016c62 bellard
                info.si_errno = 0;
404 68016c62 bellard
                /* XXX: check env->error_code */
405 68016c62 bellard
                info.si_code = TARGET_SEGV_MAPERR;
406 68016c62 bellard
                info._sifields._sigfault._addr = env->cp15_6;
407 68016c62 bellard
                queue_signal(info.si_signo, &info);
408 68016c62 bellard
            }
409 68016c62 bellard
            break;
410 1fddef4b bellard
        case EXCP_DEBUG:
411 1fddef4b bellard
            {
412 1fddef4b bellard
                int sig;
413 1fddef4b bellard
414 1fddef4b bellard
                sig = gdb_handlesig (env, TARGET_SIGTRAP);
415 1fddef4b bellard
                if (sig)
416 1fddef4b bellard
                  {
417 1fddef4b bellard
                    info.si_signo = sig;
418 1fddef4b bellard
                    info.si_errno = 0;
419 1fddef4b bellard
                    info.si_code = TARGET_TRAP_BRKPT;
420 1fddef4b bellard
                    queue_signal(info.si_signo, &info);
421 1fddef4b bellard
                  }
422 1fddef4b bellard
            }
423 1fddef4b bellard
            break;
424 b346ff46 bellard
        default:
425 b346ff46 bellard
        error:
426 b346ff46 bellard
            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 
427 b346ff46 bellard
                    trapnr);
428 7fe48483 bellard
            cpu_dump_state(env, stderr, fprintf, 0);
429 b346ff46 bellard
            abort();
430 b346ff46 bellard
        }
431 b346ff46 bellard
        process_pending_signals(env);
432 b346ff46 bellard
    }
433 b346ff46 bellard
}
434 b346ff46 bellard
435 b346ff46 bellard
#endif
436 1b6b029e bellard
437 93ac68bc bellard
#ifdef TARGET_SPARC
438 93ac68bc bellard
439 060366c5 bellard
//#define DEBUG_WIN
440 060366c5 bellard
441 2623cbaf bellard
/* WARNING: dealing with register windows _is_ complicated. More info
442 2623cbaf bellard
   can be found at http://www.sics.se/~psm/sparcstack.html */
443 060366c5 bellard
static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
444 060366c5 bellard
{
445 060366c5 bellard
    index = (index + cwp * 16) & (16 * NWINDOWS - 1);
446 060366c5 bellard
    /* wrap handling : if cwp is on the last window, then we use the
447 060366c5 bellard
       registers 'after' the end */
448 060366c5 bellard
    if (index < 8 && env->cwp == (NWINDOWS - 1))
449 060366c5 bellard
        index += (16 * NWINDOWS);
450 060366c5 bellard
    return index;
451 060366c5 bellard
}
452 060366c5 bellard
453 2623cbaf bellard
/* save the register window 'cwp1' */
454 2623cbaf bellard
static inline void save_window_offset(CPUSPARCState *env, int cwp1)
455 060366c5 bellard
{
456 2623cbaf bellard
    unsigned int i;
457 060366c5 bellard
    uint32_t *sp_ptr;
458 060366c5 bellard
    
459 060366c5 bellard
    sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
460 060366c5 bellard
#if defined(DEBUG_WIN)
461 060366c5 bellard
    printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n", 
462 060366c5 bellard
           (int)sp_ptr, cwp1);
463 060366c5 bellard
#endif
464 2623cbaf bellard
    for(i = 0; i < 16; i++) {
465 2623cbaf bellard
        put_user(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
466 2623cbaf bellard
        sp_ptr++;
467 2623cbaf bellard
    }
468 060366c5 bellard
}
469 060366c5 bellard
470 060366c5 bellard
static void save_window(CPUSPARCState *env)
471 060366c5 bellard
{
472 2623cbaf bellard
    unsigned int new_wim;
473 2623cbaf bellard
    new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
474 2623cbaf bellard
        ((1LL << NWINDOWS) - 1);
475 2623cbaf bellard
    save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
476 2623cbaf bellard
    env->wim = new_wim;
477 060366c5 bellard
}
478 060366c5 bellard
479 060366c5 bellard
static void restore_window(CPUSPARCState *env)
480 060366c5 bellard
{
481 060366c5 bellard
    unsigned int new_wim, i, cwp1;
482 2623cbaf bellard
    uint32_t *sp_ptr, reg;
483 060366c5 bellard
    
484 060366c5 bellard
    new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
485 060366c5 bellard
        ((1LL << NWINDOWS) - 1);
486 060366c5 bellard
    
487 060366c5 bellard
    /* restore the invalid window */
488 060366c5 bellard
    cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
489 060366c5 bellard
    sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
490 060366c5 bellard
#if defined(DEBUG_WIN)
491 060366c5 bellard
    printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n", 
492 060366c5 bellard
           (int)sp_ptr, cwp1);
493 060366c5 bellard
#endif
494 2623cbaf bellard
    for(i = 0; i < 16; i++) {
495 2623cbaf bellard
        get_user(reg, sp_ptr);
496 2623cbaf bellard
        env->regbase[get_reg_index(env, cwp1, 8 + i)] = reg;
497 2623cbaf bellard
        sp_ptr++;
498 2623cbaf bellard
    }
499 060366c5 bellard
    env->wim = new_wim;
500 060366c5 bellard
}
501 060366c5 bellard
502 060366c5 bellard
static void flush_windows(CPUSPARCState *env)
503 060366c5 bellard
{
504 060366c5 bellard
    int offset, cwp1;
505 2623cbaf bellard
506 2623cbaf bellard
    offset = 1;
507 060366c5 bellard
    for(;;) {
508 060366c5 bellard
        /* if restore would invoke restore_window(), then we can stop */
509 2623cbaf bellard
        cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
510 060366c5 bellard
        if (env->wim & (1 << cwp1))
511 060366c5 bellard
            break;
512 2623cbaf bellard
        save_window_offset(env, cwp1);
513 060366c5 bellard
        offset++;
514 060366c5 bellard
    }
515 2623cbaf bellard
    /* set wim so that restore will reload the registers */
516 2623cbaf bellard
    cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
517 2623cbaf bellard
    env->wim = 1 << cwp1;
518 2623cbaf bellard
#if defined(DEBUG_WIN)
519 2623cbaf bellard
    printf("flush_windows: nb=%d\n", offset - 1);
520 80a9d035 bellard
#endif
521 2623cbaf bellard
}
522 060366c5 bellard
523 93ac68bc bellard
void cpu_loop (CPUSPARCState *env)
524 93ac68bc bellard
{
525 060366c5 bellard
    int trapnr, ret;
526 61ff6f58 bellard
    target_siginfo_t info;
527 060366c5 bellard
    
528 060366c5 bellard
    while (1) {
529 060366c5 bellard
        trapnr = cpu_sparc_exec (env);
530 060366c5 bellard
        
531 060366c5 bellard
        switch (trapnr) {
532 060366c5 bellard
        case 0x88: 
533 060366c5 bellard
        case 0x90:
534 060366c5 bellard
            ret = do_syscall (env, env->gregs[1],
535 060366c5 bellard
                              env->regwptr[0], env->regwptr[1], 
536 060366c5 bellard
                              env->regwptr[2], env->regwptr[3], 
537 060366c5 bellard
                              env->regwptr[4], env->regwptr[5]);
538 060366c5 bellard
            if ((unsigned int)ret >= (unsigned int)(-515)) {
539 060366c5 bellard
                env->psr |= PSR_CARRY;
540 060366c5 bellard
                ret = -ret;
541 060366c5 bellard
            } else {
542 060366c5 bellard
                env->psr &= ~PSR_CARRY;
543 060366c5 bellard
            }
544 060366c5 bellard
            env->regwptr[0] = ret;
545 060366c5 bellard
            /* next instruction */
546 060366c5 bellard
            env->pc = env->npc;
547 060366c5 bellard
            env->npc = env->npc + 4;
548 060366c5 bellard
            break;
549 060366c5 bellard
        case 0x83: /* flush windows */
550 2623cbaf bellard
            flush_windows(env);
551 060366c5 bellard
            /* next instruction */
552 060366c5 bellard
            env->pc = env->npc;
553 060366c5 bellard
            env->npc = env->npc + 4;
554 060366c5 bellard
            break;
555 3475187d bellard
#ifndef TARGET_SPARC64
556 060366c5 bellard
        case TT_WIN_OVF: /* window overflow */
557 060366c5 bellard
            save_window(env);
558 060366c5 bellard
            break;
559 060366c5 bellard
        case TT_WIN_UNF: /* window underflow */
560 060366c5 bellard
            restore_window(env);
561 060366c5 bellard
            break;
562 61ff6f58 bellard
        case TT_TFAULT:
563 61ff6f58 bellard
        case TT_DFAULT:
564 61ff6f58 bellard
            {
565 61ff6f58 bellard
                info.si_signo = SIGSEGV;
566 61ff6f58 bellard
                info.si_errno = 0;
567 61ff6f58 bellard
                /* XXX: check env->error_code */
568 61ff6f58 bellard
                info.si_code = TARGET_SEGV_MAPERR;
569 61ff6f58 bellard
                info._sifields._sigfault._addr = env->mmuregs[4];
570 61ff6f58 bellard
                queue_signal(info.si_signo, &info);
571 61ff6f58 bellard
            }
572 61ff6f58 bellard
            break;
573 3475187d bellard
#else
574 3475187d bellard
            // XXX
575 3475187d bellard
#endif
576 e80cfcfc bellard
        case 0x100: // XXX, why do we get these?
577 e80cfcfc bellard
            break;
578 1fddef4b bellard
        case EXCP_DEBUG:
579 1fddef4b bellard
            {
580 1fddef4b bellard
                int sig;
581 1fddef4b bellard
582 1fddef4b bellard
                sig = gdb_handlesig (env, TARGET_SIGTRAP);
583 1fddef4b bellard
                if (sig)
584 1fddef4b bellard
                  {
585 1fddef4b bellard
                    info.si_signo = sig;
586 1fddef4b bellard
                    info.si_errno = 0;
587 1fddef4b bellard
                    info.si_code = TARGET_TRAP_BRKPT;
588 1fddef4b bellard
                    queue_signal(info.si_signo, &info);
589 1fddef4b bellard
                  }
590 1fddef4b bellard
            }
591 1fddef4b bellard
            break;
592 060366c5 bellard
        default:
593 060366c5 bellard
            printf ("Unhandled trap: 0x%x\n", trapnr);
594 7fe48483 bellard
            cpu_dump_state(env, stderr, fprintf, 0);
595 060366c5 bellard
            exit (1);
596 060366c5 bellard
        }
597 060366c5 bellard
        process_pending_signals (env);
598 060366c5 bellard
    }
599 93ac68bc bellard
}
600 93ac68bc bellard
601 93ac68bc bellard
#endif
602 93ac68bc bellard
603 67867308 bellard
#ifdef TARGET_PPC
604 9fddaa0c bellard
605 9fddaa0c bellard
static inline uint64_t cpu_ppc_get_tb (CPUState *env)
606 9fddaa0c bellard
{
607 9fddaa0c bellard
    /* TO FIX */
608 9fddaa0c bellard
    return 0;
609 9fddaa0c bellard
}
610 9fddaa0c bellard
  
611 9fddaa0c bellard
uint32_t cpu_ppc_load_tbl (CPUState *env)
612 9fddaa0c bellard
{
613 9fddaa0c bellard
    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
614 9fddaa0c bellard
}
615 9fddaa0c bellard
  
616 9fddaa0c bellard
uint32_t cpu_ppc_load_tbu (CPUState *env)
617 9fddaa0c bellard
{
618 9fddaa0c bellard
    return cpu_ppc_get_tb(env) >> 32;
619 9fddaa0c bellard
}
620 9fddaa0c bellard
  
621 9fddaa0c bellard
static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
622 9fddaa0c bellard
{
623 9fddaa0c bellard
    /* TO FIX */
624 9fddaa0c bellard
}
625 9fddaa0c bellard
626 9fddaa0c bellard
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
627 9fddaa0c bellard
{
628 9fddaa0c bellard
    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
629 9fddaa0c bellard
}
630 9fddaa0c bellard
 
631 9fddaa0c bellard
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
632 9fddaa0c bellard
{
633 9fddaa0c bellard
    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
634 9fddaa0c bellard
}
635 9fddaa0c bellard
  
636 9fddaa0c bellard
uint32_t cpu_ppc_load_decr (CPUState *env)
637 9fddaa0c bellard
{
638 9fddaa0c bellard
    /* TO FIX */
639 9fddaa0c bellard
    return -1;
640 9fddaa0c bellard
}
641 9fddaa0c bellard
 
642 9fddaa0c bellard
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
643 9fddaa0c bellard
{
644 9fddaa0c bellard
    /* TO FIX */
645 9fddaa0c bellard
}
646 9fddaa0c bellard
 
647 67867308 bellard
void cpu_loop(CPUPPCState *env)
648 67867308 bellard
{
649 67867308 bellard
    target_siginfo_t info;
650 61190b14 bellard
    int trapnr;
651 61190b14 bellard
    uint32_t ret;
652 67867308 bellard
    
653 67867308 bellard
    for(;;) {
654 67867308 bellard
        trapnr = cpu_ppc_exec(env);
655 61190b14 bellard
        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
656 61190b14 bellard
            trapnr != EXCP_TRACE) {
657 61190b14 bellard
            if (loglevel > 0) {
658 7fe48483 bellard
                cpu_dump_state(env, logfile, fprintf, 0);
659 61190b14 bellard
            }
660 61190b14 bellard
        }
661 67867308 bellard
        switch(trapnr) {
662 67867308 bellard
        case EXCP_NONE:
663 67867308 bellard
            break;
664 61190b14 bellard
        case EXCP_SYSCALL_USER:
665 61190b14 bellard
            /* system call */
666 61190b14 bellard
            /* WARNING:
667 61190b14 bellard
             * PPC ABI uses overflow flag in cr0 to signal an error
668 61190b14 bellard
             * in syscalls.
669 61190b14 bellard
             */
670 67867308 bellard
#if 0
671 61190b14 bellard
            printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
672 61190b14 bellard
                   env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
673 67867308 bellard
#endif
674 61190b14 bellard
            env->crf[0] &= ~0x1;
675 61190b14 bellard
            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
676 61190b14 bellard
                             env->gpr[5], env->gpr[6], env->gpr[7],
677 61190b14 bellard
                             env->gpr[8]);
678 61190b14 bellard
            if (ret > (uint32_t)(-515)) {
679 61190b14 bellard
                env->crf[0] |= 0x1;
680 61190b14 bellard
                ret = -ret;
681 61190b14 bellard
            }
682 61190b14 bellard
            env->gpr[3] = ret;
683 61190b14 bellard
#if 0
684 61190b14 bellard
            printf("syscall returned 0x%08x (%d)\n", ret, ret);
685 61190b14 bellard
#endif
686 61190b14 bellard
            break;
687 61190b14 bellard
        case EXCP_RESET:
688 61190b14 bellard
            /* Should not happen ! */
689 61190b14 bellard
            fprintf(stderr, "RESET asked... Stop emulation\n");
690 61190b14 bellard
            if (loglevel)
691 61190b14 bellard
                fprintf(logfile, "RESET asked... Stop emulation\n");
692 67867308 bellard
            abort();
693 61190b14 bellard
        case EXCP_MACHINE_CHECK:
694 61190b14 bellard
            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
695 61190b14 bellard
            if (loglevel)
696 61190b14 bellard
                fprintf(logfile, "RESET asked... Stop emulation\n");
697 61190b14 bellard
            info.si_signo = TARGET_SIGBUS;
698 67867308 bellard
            info.si_errno = 0;
699 61190b14 bellard
            info.si_code = TARGET_BUS_OBJERR;
700 61190b14 bellard
            info._sifields._sigfault._addr = env->nip - 4;
701 61190b14 bellard
            queue_signal(info.si_signo, &info);
702 61190b14 bellard
        case EXCP_DSI:
703 61190b14 bellard
            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
704 61190b14 bellard
            if (loglevel) {
705 61190b14 bellard
                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
706 61190b14 bellard
                        env->spr[DAR]);
707 61190b14 bellard
            }
708 61190b14 bellard
            switch (env->error_code & 0xF) {
709 61190b14 bellard
            case EXCP_DSI_TRANSLATE:
710 61190b14 bellard
                info.si_signo = TARGET_SIGSEGV;
711 61190b14 bellard
                info.si_errno = 0;
712 61190b14 bellard
                info.si_code = TARGET_SEGV_MAPERR;
713 61190b14 bellard
                break;
714 61190b14 bellard
            case EXCP_DSI_NOTSUP:
715 61190b14 bellard
            case EXCP_DSI_EXTERNAL:
716 61190b14 bellard
                info.si_signo = TARGET_SIGILL;
717 61190b14 bellard
                info.si_errno = 0;
718 61190b14 bellard
                info.si_code = TARGET_ILL_ILLADR;
719 61190b14 bellard
                break;
720 61190b14 bellard
            case EXCP_DSI_PROT: 
721 61190b14 bellard
                info.si_signo = TARGET_SIGSEGV;
722 61190b14 bellard
                info.si_errno = 0;
723 61190b14 bellard
                info.si_code = TARGET_SEGV_ACCERR;
724 61190b14 bellard
                break;
725 61190b14 bellard
            case EXCP_DSI_DABR:
726 61190b14 bellard
                info.si_signo = TARGET_SIGTRAP;
727 61190b14 bellard
                info.si_errno = 0;
728 61190b14 bellard
                info.si_code = TARGET_TRAP_BRKPT;
729 61190b14 bellard
                break;
730 61190b14 bellard
            default:
731 61190b14 bellard
                /* Let's send a regular segfault... */
732 61190b14 bellard
                fprintf(stderr, "Invalid segfault errno (%02x)\n",
733 61190b14 bellard
                        env->error_code);
734 61190b14 bellard
                if (loglevel) {
735 61190b14 bellard
                    fprintf(logfile, "Invalid segfault errno (%02x)\n",
736 61190b14 bellard
                            env->error_code);
737 61190b14 bellard
                }
738 61190b14 bellard
                info.si_signo = TARGET_SIGSEGV;
739 61190b14 bellard
                info.si_errno = 0;
740 61190b14 bellard
                info.si_code = TARGET_SEGV_MAPERR;
741 61190b14 bellard
                break;
742 61190b14 bellard
            }
743 67867308 bellard
            info._sifields._sigfault._addr = env->nip;
744 67867308 bellard
            queue_signal(info.si_signo, &info);
745 67867308 bellard
            break;
746 61190b14 bellard
        case EXCP_ISI:
747 67867308 bellard
            fprintf(stderr, "Invalid instruction fetch\n");
748 61190b14 bellard
            if (loglevel)
749 61190b14 bellard
                fprintf(logfile, "Invalid instruction fetch\n");
750 61190b14 bellard
            switch (env->error_code) {
751 61190b14 bellard
            case EXCP_ISI_TRANSLATE:
752 61190b14 bellard
                info.si_signo = TARGET_SIGSEGV;
753 67867308 bellard
            info.si_errno = 0;
754 61190b14 bellard
                info.si_code = TARGET_SEGV_MAPERR;
755 61190b14 bellard
                break;
756 61190b14 bellard
            case EXCP_ISI_GUARD:
757 61190b14 bellard
                info.si_signo = TARGET_SIGILL;
758 61190b14 bellard
                info.si_errno = 0;
759 61190b14 bellard
                info.si_code = TARGET_ILL_ILLADR;
760 61190b14 bellard
                break;
761 61190b14 bellard
            case EXCP_ISI_NOEXEC:
762 61190b14 bellard
            case EXCP_ISI_PROT:
763 61190b14 bellard
                info.si_signo = TARGET_SIGSEGV;
764 61190b14 bellard
                info.si_errno = 0;
765 61190b14 bellard
                info.si_code = TARGET_SEGV_ACCERR;
766 61190b14 bellard
                break;
767 61190b14 bellard
            default:
768 61190b14 bellard
                /* Let's send a regular segfault... */
769 61190b14 bellard
                fprintf(stderr, "Invalid segfault errno (%02x)\n",
770 61190b14 bellard
                        env->error_code);
771 61190b14 bellard
                if (loglevel) {
772 61190b14 bellard
                    fprintf(logfile, "Invalid segfault errno (%02x)\n",
773 61190b14 bellard
                            env->error_code);
774 61190b14 bellard
                }
775 61190b14 bellard
                info.si_signo = TARGET_SIGSEGV;
776 61190b14 bellard
                info.si_errno = 0;
777 61190b14 bellard
                info.si_code = TARGET_SEGV_MAPERR;
778 61190b14 bellard
                break;
779 61190b14 bellard
            }
780 61190b14 bellard
            info._sifields._sigfault._addr = env->nip - 4;
781 67867308 bellard
            queue_signal(info.si_signo, &info);
782 67867308 bellard
            break;
783 61190b14 bellard
        case EXCP_EXTERNAL:
784 61190b14 bellard
            /* Should not happen ! */
785 61190b14 bellard
            fprintf(stderr, "External interruption... Stop emulation\n");
786 61190b14 bellard
            if (loglevel)
787 61190b14 bellard
                fprintf(logfile, "External interruption... Stop emulation\n");
788 67867308 bellard
            abort();
789 61190b14 bellard
        case EXCP_ALIGN:
790 61190b14 bellard
            fprintf(stderr, "Invalid unaligned memory access\n");
791 61190b14 bellard
            if (loglevel)
792 61190b14 bellard
                fprintf(logfile, "Invalid unaligned memory access\n");
793 61190b14 bellard
            info.si_signo = TARGET_SIGBUS;
794 67867308 bellard
            info.si_errno = 0;
795 61190b14 bellard
            info.si_code = TARGET_BUS_ADRALN;
796 61190b14 bellard
            info._sifields._sigfault._addr = env->nip - 4;
797 67867308 bellard
            queue_signal(info.si_signo, &info);
798 67867308 bellard
            break;
799 61190b14 bellard
        case EXCP_PROGRAM:
800 61190b14 bellard
            switch (env->error_code & ~0xF) {
801 61190b14 bellard
            case EXCP_FP:
802 61190b14 bellard
            fprintf(stderr, "Program exception\n");
803 61190b14 bellard
                if (loglevel)
804 61190b14 bellard
                    fprintf(logfile, "Program exception\n");
805 61190b14 bellard
                /* Set FX */
806 61190b14 bellard
                env->fpscr[7] |= 0x8;
807 61190b14 bellard
                /* Finally, update FEX */
808 61190b14 bellard
                if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
809 61190b14 bellard
                    ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
810 61190b14 bellard
                    env->fpscr[7] |= 0x4;
811 61190b14 bellard
                info.si_signo = TARGET_SIGFPE;
812 61190b14 bellard
                info.si_errno = 0;
813 61190b14 bellard
                switch (env->error_code & 0xF) {
814 61190b14 bellard
                case EXCP_FP_OX:
815 61190b14 bellard
                    info.si_code = TARGET_FPE_FLTOVF;
816 61190b14 bellard
                    break;
817 61190b14 bellard
                case EXCP_FP_UX:
818 61190b14 bellard
                    info.si_code = TARGET_FPE_FLTUND;
819 61190b14 bellard
                    break;
820 61190b14 bellard
                case EXCP_FP_ZX:
821 61190b14 bellard
                case EXCP_FP_VXZDZ:
822 61190b14 bellard
                    info.si_code = TARGET_FPE_FLTDIV;
823 61190b14 bellard
                    break;
824 61190b14 bellard
                case EXCP_FP_XX:
825 61190b14 bellard
                    info.si_code = TARGET_FPE_FLTRES;
826 61190b14 bellard
                    break;
827 61190b14 bellard
                case EXCP_FP_VXSOFT:
828 61190b14 bellard
                    info.si_code = TARGET_FPE_FLTINV;
829 61190b14 bellard
                    break;
830 61190b14 bellard
                case EXCP_FP_VXNAN:
831 61190b14 bellard
                case EXCP_FP_VXISI:
832 61190b14 bellard
                case EXCP_FP_VXIDI:
833 61190b14 bellard
                case EXCP_FP_VXIMZ:
834 61190b14 bellard
                case EXCP_FP_VXVC:
835 61190b14 bellard
                case EXCP_FP_VXSQRT:
836 61190b14 bellard
                case EXCP_FP_VXCVI:
837 61190b14 bellard
                    info.si_code = TARGET_FPE_FLTSUB;
838 61190b14 bellard
                    break;
839 61190b14 bellard
                default:
840 61190b14 bellard
                    fprintf(stderr, "Unknown floating point exception "
841 61190b14 bellard
                            "(%02x)\n", env->error_code);
842 61190b14 bellard
                    if (loglevel) {
843 61190b14 bellard
                        fprintf(logfile, "Unknown floating point exception "
844 61190b14 bellard
                                "(%02x)\n", env->error_code & 0xF);
845 61190b14 bellard
                    }
846 61190b14 bellard
                }
847 61190b14 bellard
            break;
848 67867308 bellard
        case EXCP_INVAL:
849 61190b14 bellard
                fprintf(stderr, "Invalid instruction\n");
850 61190b14 bellard
                if (loglevel)
851 61190b14 bellard
                    fprintf(logfile, "Invalid instruction\n");
852 61190b14 bellard
                info.si_signo = TARGET_SIGILL;
853 61190b14 bellard
                info.si_errno = 0;
854 61190b14 bellard
                switch (env->error_code & 0xF) {
855 61190b14 bellard
                case EXCP_INVAL_INVAL:
856 61190b14 bellard
                    info.si_code = TARGET_ILL_ILLOPC;
857 61190b14 bellard
                    break;
858 61190b14 bellard
                case EXCP_INVAL_LSWX:
859 67867308 bellard
            info.si_code = TARGET_ILL_ILLOPN;
860 61190b14 bellard
                    break;
861 61190b14 bellard
                case EXCP_INVAL_SPR:
862 61190b14 bellard
                    info.si_code = TARGET_ILL_PRVREG;
863 61190b14 bellard
                    break;
864 61190b14 bellard
                case EXCP_INVAL_FP:
865 61190b14 bellard
                    info.si_code = TARGET_ILL_COPROC;
866 61190b14 bellard
                    break;
867 61190b14 bellard
                default:
868 61190b14 bellard
                    fprintf(stderr, "Unknown invalid operation (%02x)\n",
869 61190b14 bellard
                            env->error_code & 0xF);
870 61190b14 bellard
                    if (loglevel) {
871 61190b14 bellard
                        fprintf(logfile, "Unknown invalid operation (%02x)\n",
872 61190b14 bellard
                                env->error_code & 0xF);
873 61190b14 bellard
                    }
874 61190b14 bellard
                    info.si_code = TARGET_ILL_ILLADR;
875 61190b14 bellard
                    break;
876 61190b14 bellard
                }
877 61190b14 bellard
                break;
878 61190b14 bellard
            case EXCP_PRIV:
879 61190b14 bellard
                fprintf(stderr, "Privilege violation\n");
880 61190b14 bellard
                if (loglevel)
881 61190b14 bellard
                    fprintf(logfile, "Privilege violation\n");
882 61190b14 bellard
                info.si_signo = TARGET_SIGILL;
883 61190b14 bellard
                info.si_errno = 0;
884 61190b14 bellard
                switch (env->error_code & 0xF) {
885 61190b14 bellard
                case EXCP_PRIV_OPC:
886 61190b14 bellard
                    info.si_code = TARGET_ILL_PRVOPC;
887 61190b14 bellard
                    break;
888 61190b14 bellard
                case EXCP_PRIV_REG:
889 61190b14 bellard
                    info.si_code = TARGET_ILL_PRVREG;
890 61190b14 bellard
                break;
891 61190b14 bellard
                default:
892 61190b14 bellard
                    fprintf(stderr, "Unknown privilege violation (%02x)\n",
893 61190b14 bellard
                            env->error_code & 0xF);
894 61190b14 bellard
                    info.si_code = TARGET_ILL_PRVOPC;
895 61190b14 bellard
                    break;
896 61190b14 bellard
                }
897 61190b14 bellard
                break;
898 61190b14 bellard
            case EXCP_TRAP:
899 61190b14 bellard
                fprintf(stderr, "Tried to call a TRAP\n");
900 61190b14 bellard
                if (loglevel)
901 61190b14 bellard
                    fprintf(logfile, "Tried to call a TRAP\n");
902 61190b14 bellard
                abort();
903 61190b14 bellard
            default:
904 61190b14 bellard
                /* Should not happen ! */
905 61190b14 bellard
                fprintf(stderr, "Unknown program exception (%02x)\n",
906 61190b14 bellard
                        env->error_code);
907 61190b14 bellard
                if (loglevel) {
908 61190b14 bellard
                    fprintf(logfile, "Unknwon program exception (%02x)\n",
909 61190b14 bellard
                            env->error_code);
910 61190b14 bellard
                }
911 61190b14 bellard
                abort();
912 61190b14 bellard
            }
913 61190b14 bellard
            info._sifields._sigfault._addr = env->nip - 4;
914 67867308 bellard
            queue_signal(info.si_signo, &info);
915 67867308 bellard
            break;
916 61190b14 bellard
        case EXCP_NO_FP:
917 61190b14 bellard
            fprintf(stderr, "No floating point allowed\n");
918 61190b14 bellard
            if (loglevel)
919 61190b14 bellard
                fprintf(logfile, "No floating point allowed\n");
920 61190b14 bellard
            info.si_signo = TARGET_SIGILL;
921 67867308 bellard
            info.si_errno = 0;
922 61190b14 bellard
            info.si_code = TARGET_ILL_COPROC;
923 61190b14 bellard
            info._sifields._sigfault._addr = env->nip - 4;
924 67867308 bellard
            queue_signal(info.si_signo, &info);
925 67867308 bellard
            break;
926 61190b14 bellard
        case EXCP_DECR:
927 61190b14 bellard
            /* Should not happen ! */
928 61190b14 bellard
            fprintf(stderr, "Decrementer exception\n");
929 61190b14 bellard
            if (loglevel)
930 61190b14 bellard
                fprintf(logfile, "Decrementer exception\n");
931 61190b14 bellard
            abort();
932 67867308 bellard
        case EXCP_RESA: /* Implementation specific          */
933 61190b14 bellard
            /* Should not happen ! */
934 61190b14 bellard
            fprintf(stderr, "RESA exception should never happen !\n");
935 61190b14 bellard
            if (loglevel)
936 61190b14 bellard
                fprintf(logfile, "RESA exception should never happen !\n");
937 61190b14 bellard
            abort();
938 67867308 bellard
        case EXCP_RESB: /* Implementation specific          */
939 61190b14 bellard
            /* Should not happen ! */
940 61190b14 bellard
            fprintf(stderr, "RESB exception should never happen !\n");
941 61190b14 bellard
            if (loglevel)
942 61190b14 bellard
                fprintf(logfile, "RESB exception should never happen !\n");
943 67867308 bellard
            abort();
944 61190b14 bellard
        case EXCP_TRACE:
945 61190b14 bellard
            /* Do nothing: we use this to trace execution */
946 67867308 bellard
            break;
947 61190b14 bellard
        case EXCP_FP_ASSIST:
948 61190b14 bellard
            /* Should not happen ! */
949 61190b14 bellard
            fprintf(stderr, "Floating point assist exception\n");
950 61190b14 bellard
            if (loglevel)
951 61190b14 bellard
                fprintf(logfile, "Floating point assist exception\n");
952 61190b14 bellard
            abort();
953 61190b14 bellard
        case EXCP_MTMSR:
954 61190b14 bellard
            /* We reloaded the msr, just go on */
955 9fddaa0c bellard
            if (msr_pr == 0) {
956 61190b14 bellard
                fprintf(stderr, "Tried to go into supervisor mode !\n");
957 61190b14 bellard
                if (loglevel)
958 61190b14 bellard
                    fprintf(logfile, "Tried to go into supervisor mode !\n");
959 61190b14 bellard
                abort();
960 67867308 bellard
        }
961 61190b14 bellard
            break;
962 61190b14 bellard
        case EXCP_BRANCH:
963 61190b14 bellard
            /* We stopped because of a jump... */
964 61190b14 bellard
            break;
965 61190b14 bellard
        case EXCP_RFI:
966 61190b14 bellard
            /* Should not occur: we always are in user mode */
967 61190b14 bellard
            fprintf(stderr, "Return from interrupt ?\n");
968 61190b14 bellard
            if (loglevel)
969 61190b14 bellard
                fprintf(logfile, "Return from interrupt ?\n");
970 61190b14 bellard
            abort();
971 61190b14 bellard
        case EXCP_INTERRUPT:
972 61190b14 bellard
            /* Don't know why this should ever happen... */
973 61190b14 bellard
            break;
974 1fddef4b bellard
        case EXCP_DEBUG:
975 1fddef4b bellard
            {
976 1fddef4b bellard
                int sig;
977 1fddef4b bellard
978 1fddef4b bellard
                sig = gdb_handlesig (env, TARGET_SIGTRAP);
979 1fddef4b bellard
                if (sig)
980 1fddef4b bellard
                  {
981 1fddef4b bellard
                    info.si_signo = sig;
982 1fddef4b bellard
                    info.si_errno = 0;
983 1fddef4b bellard
                    info.si_code = TARGET_TRAP_BRKPT;
984 1fddef4b bellard
                    queue_signal(info.si_signo, &info);
985 1fddef4b bellard
                  }
986 1fddef4b bellard
            }
987 1fddef4b bellard
            break;
988 67867308 bellard
        default:
989 67867308 bellard
            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 
990 67867308 bellard
                    trapnr);
991 61190b14 bellard
            if (loglevel) {
992 61190b14 bellard
                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
993 61190b14 bellard
                        "0x%02x - aborting\n", trapnr, env->error_code);
994 61190b14 bellard
            }
995 67867308 bellard
            abort();
996 67867308 bellard
        }
997 67867308 bellard
        process_pending_signals(env);
998 67867308 bellard
    }
999 67867308 bellard
}
1000 67867308 bellard
#endif
1001 67867308 bellard
1002 31e31b8a bellard
void usage(void)
1003 31e31b8a bellard
{
1004 4606bb3f bellard
    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
1005 1fddef4b bellard
           "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] program [arguments...]\n"
1006 b346ff46 bellard
           "Linux CPU emulator (compiled for %s emulation)\n"
1007 d691f669 bellard
           "\n"
1008 54936004 bellard
           "-h           print this help\n"
1009 1fddef4b bellard
           "-g           wait gdb connection to port %d\n"
1010 b346ff46 bellard
           "-L path      set the elf interpreter prefix (default=%s)\n"
1011 b346ff46 bellard
           "-s size      set the stack size in bytes (default=%ld)\n"
1012 54936004 bellard
           "\n"
1013 54936004 bellard
           "debug options:\n"
1014 c6981055 bellard
#ifdef USE_CODE_COPY
1015 c6981055 bellard
           "-no-code-copy   disable code copy acceleration\n"
1016 c6981055 bellard
#endif
1017 6f1f31c0 bellard
           "-d options   activate log (logfile=%s)\n"
1018 54936004 bellard
           "-p pagesize  set the host page size to 'pagesize'\n",
1019 b346ff46 bellard
           TARGET_ARCH,
1020 1fddef4b bellard
           DEFAULT_GDBSTUB_PORT,
1021 d691f669 bellard
           interp_prefix, 
1022 54936004 bellard
           x86_stack_size,
1023 54936004 bellard
           DEBUG_LOGFILE);
1024 74cd30b8 bellard
    _exit(1);
1025 31e31b8a bellard
}
1026 31e31b8a bellard
1027 9de5e440 bellard
/* XXX: currently only used for async signals (see signal.c) */
1028 b346ff46 bellard
CPUState *global_env;
1029 59faf6d6 bellard
/* used only if single thread */
1030 59faf6d6 bellard
CPUState *cpu_single_env = NULL;
1031 59faf6d6 bellard
1032 851e67a1 bellard
/* used to free thread contexts */
1033 851e67a1 bellard
TaskState *first_task_state;
1034 9de5e440 bellard
1035 31e31b8a bellard
int main(int argc, char **argv)
1036 31e31b8a bellard
{
1037 31e31b8a bellard
    const char *filename;
1038 01ffc75b bellard
    struct target_pt_regs regs1, *regs = &regs1;
1039 31e31b8a bellard
    struct image_info info1, *info = &info1;
1040 851e67a1 bellard
    TaskState ts1, *ts = &ts1;
1041 b346ff46 bellard
    CPUState *env;
1042 586314f2 bellard
    int optind;
1043 d691f669 bellard
    const char *r;
1044 1fddef4b bellard
    int use_gdbstub = 0;
1045 d691f669 bellard
    
1046 31e31b8a bellard
    if (argc <= 1)
1047 31e31b8a bellard
        usage();
1048 f801f97e bellard
1049 cc38b844 bellard
    /* init debug */
1050 cc38b844 bellard
    cpu_set_log_filename(DEBUG_LOGFILE);
1051 cc38b844 bellard
1052 586314f2 bellard
    optind = 1;
1053 d691f669 bellard
    for(;;) {
1054 d691f669 bellard
        if (optind >= argc)
1055 d691f669 bellard
            break;
1056 d691f669 bellard
        r = argv[optind];
1057 d691f669 bellard
        if (r[0] != '-')
1058 d691f669 bellard
            break;
1059 586314f2 bellard
        optind++;
1060 d691f669 bellard
        r++;
1061 d691f669 bellard
        if (!strcmp(r, "-")) {
1062 d691f669 bellard
            break;
1063 d691f669 bellard
        } else if (!strcmp(r, "d")) {
1064 e19e89a5 bellard
            int mask;
1065 e19e89a5 bellard
            CPULogItem *item;
1066 6f1f31c0 bellard
1067 6f1f31c0 bellard
            if (optind >= argc)
1068 6f1f31c0 bellard
                break;
1069 e19e89a5 bellard
            
1070 6f1f31c0 bellard
            r = argv[optind++];
1071 6f1f31c0 bellard
            mask = cpu_str_to_log_mask(r);
1072 e19e89a5 bellard
            if (!mask) {
1073 e19e89a5 bellard
                printf("Log items (comma separated):\n");
1074 e19e89a5 bellard
                for(item = cpu_log_items; item->mask != 0; item++) {
1075 e19e89a5 bellard
                    printf("%-10s %s\n", item->name, item->help);
1076 e19e89a5 bellard
                }
1077 e19e89a5 bellard
                exit(1);
1078 e19e89a5 bellard
            }
1079 e19e89a5 bellard
            cpu_set_log(mask);
1080 d691f669 bellard
        } else if (!strcmp(r, "s")) {
1081 d691f669 bellard
            r = argv[optind++];
1082 d691f669 bellard
            x86_stack_size = strtol(r, (char **)&r, 0);
1083 d691f669 bellard
            if (x86_stack_size <= 0)
1084 d691f669 bellard
                usage();
1085 d691f669 bellard
            if (*r == 'M')
1086 d691f669 bellard
                x86_stack_size *= 1024 * 1024;
1087 d691f669 bellard
            else if (*r == 'k' || *r == 'K')
1088 d691f669 bellard
                x86_stack_size *= 1024;
1089 d691f669 bellard
        } else if (!strcmp(r, "L")) {
1090 d691f669 bellard
            interp_prefix = argv[optind++];
1091 54936004 bellard
        } else if (!strcmp(r, "p")) {
1092 83fb7adf bellard
            qemu_host_page_size = atoi(argv[optind++]);
1093 83fb7adf bellard
            if (qemu_host_page_size == 0 ||
1094 83fb7adf bellard
                (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
1095 54936004 bellard
                fprintf(stderr, "page size must be a power of two\n");
1096 54936004 bellard
                exit(1);
1097 54936004 bellard
            }
1098 1fddef4b bellard
        } else if (!strcmp(r, "g")) {
1099 1fddef4b bellard
            use_gdbstub = 1;
1100 c6981055 bellard
        } else 
1101 c6981055 bellard
#ifdef USE_CODE_COPY
1102 c6981055 bellard
        if (!strcmp(r, "no-code-copy")) {
1103 c6981055 bellard
            code_copy_enabled = 0;
1104 c6981055 bellard
        } else 
1105 c6981055 bellard
#endif
1106 c6981055 bellard
        {
1107 d691f669 bellard
            usage();
1108 d691f669 bellard
        }
1109 586314f2 bellard
    }
1110 d691f669 bellard
    if (optind >= argc)
1111 d691f669 bellard
        usage();
1112 586314f2 bellard
    filename = argv[optind];
1113 586314f2 bellard
1114 31e31b8a bellard
    /* Zero out regs */
1115 01ffc75b bellard
    memset(regs, 0, sizeof(struct target_pt_regs));
1116 31e31b8a bellard
1117 31e31b8a bellard
    /* Zero out image_info */
1118 31e31b8a bellard
    memset(info, 0, sizeof(struct image_info));
1119 31e31b8a bellard
1120 74cd30b8 bellard
    /* Scan interp_prefix dir for replacement files. */
1121 74cd30b8 bellard
    init_paths(interp_prefix);
1122 74cd30b8 bellard
1123 83fb7adf bellard
    /* NOTE: we need to init the CPU at this stage to get
1124 83fb7adf bellard
       qemu_host_page_size */
1125 b346ff46 bellard
    env = cpu_init();
1126 92ccca6a bellard
    
1127 74cd30b8 bellard
    if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
1128 31e31b8a bellard
        printf("Error loading %s\n", filename);
1129 74cd30b8 bellard
        _exit(1);
1130 31e31b8a bellard
    }
1131 31e31b8a bellard
    
1132 4b74fe1f bellard
    if (loglevel) {
1133 54936004 bellard
        page_dump(logfile);
1134 54936004 bellard
    
1135 4b74fe1f bellard
        fprintf(logfile, "start_brk   0x%08lx\n" , info->start_brk);
1136 4b74fe1f bellard
        fprintf(logfile, "end_code    0x%08lx\n" , info->end_code);
1137 4b74fe1f bellard
        fprintf(logfile, "start_code  0x%08lx\n" , info->start_code);
1138 4b74fe1f bellard
        fprintf(logfile, "end_data    0x%08lx\n" , info->end_data);
1139 4b74fe1f bellard
        fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
1140 4b74fe1f bellard
        fprintf(logfile, "brk         0x%08lx\n" , info->brk);
1141 b346ff46 bellard
        fprintf(logfile, "entry       0x%08lx\n" , info->entry);
1142 4b74fe1f bellard
    }
1143 31e31b8a bellard
1144 31e31b8a bellard
    target_set_brk((char *)info->brk);
1145 31e31b8a bellard
    syscall_init();
1146 66fb9763 bellard
    signal_init();
1147 31e31b8a bellard
1148 9de5e440 bellard
    global_env = env;
1149 0ecfa993 bellard
1150 851e67a1 bellard
    /* build Task State */
1151 851e67a1 bellard
    memset(ts, 0, sizeof(TaskState));
1152 851e67a1 bellard
    env->opaque = ts;
1153 851e67a1 bellard
    ts->used = 1;
1154 59faf6d6 bellard
    env->user_mode_only = 1;
1155 851e67a1 bellard
    
1156 b346ff46 bellard
#if defined(TARGET_I386)
1157 2e255c6b bellard
    cpu_x86_set_cpl(env, 3);
1158 2e255c6b bellard
1159 3802ce26 bellard
    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
1160 1bde465e bellard
    env->hflags |= HF_PE_MASK;
1161 1bde465e bellard
    if (env->cpuid_features & CPUID_SSE) {
1162 1bde465e bellard
        env->cr[4] |= CR4_OSFXSR_MASK;
1163 1bde465e bellard
        env->hflags |= HF_OSFXSR_MASK;
1164 1bde465e bellard
    }
1165 1bde465e bellard
1166 415e561f bellard
    /* flags setup : we activate the IRQs by default as in user mode */
1167 415e561f bellard
    env->eflags |= IF_MASK;
1168 415e561f bellard
    
1169 6dbad63e bellard
    /* linux register setup */
1170 0ecfa993 bellard
    env->regs[R_EAX] = regs->eax;
1171 0ecfa993 bellard
    env->regs[R_EBX] = regs->ebx;
1172 0ecfa993 bellard
    env->regs[R_ECX] = regs->ecx;
1173 0ecfa993 bellard
    env->regs[R_EDX] = regs->edx;
1174 0ecfa993 bellard
    env->regs[R_ESI] = regs->esi;
1175 0ecfa993 bellard
    env->regs[R_EDI] = regs->edi;
1176 0ecfa993 bellard
    env->regs[R_EBP] = regs->ebp;
1177 0ecfa993 bellard
    env->regs[R_ESP] = regs->esp;
1178 dab2ed99 bellard
    env->eip = regs->eip;
1179 31e31b8a bellard
1180 f4beb510 bellard
    /* linux interrupt setup */
1181 80a9d035 bellard
    env->idt.base = (long)idt_table;
1182 f4beb510 bellard
    env->idt.limit = sizeof(idt_table) - 1;
1183 f4beb510 bellard
    set_idt(0, 0);
1184 f4beb510 bellard
    set_idt(1, 0);
1185 f4beb510 bellard
    set_idt(2, 0);
1186 f4beb510 bellard
    set_idt(3, 3);
1187 f4beb510 bellard
    set_idt(4, 3);
1188 f4beb510 bellard
    set_idt(5, 3);
1189 f4beb510 bellard
    set_idt(6, 0);
1190 f4beb510 bellard
    set_idt(7, 0);
1191 f4beb510 bellard
    set_idt(8, 0);
1192 f4beb510 bellard
    set_idt(9, 0);
1193 f4beb510 bellard
    set_idt(10, 0);
1194 f4beb510 bellard
    set_idt(11, 0);
1195 f4beb510 bellard
    set_idt(12, 0);
1196 f4beb510 bellard
    set_idt(13, 0);
1197 f4beb510 bellard
    set_idt(14, 0);
1198 f4beb510 bellard
    set_idt(15, 0);
1199 f4beb510 bellard
    set_idt(16, 0);
1200 f4beb510 bellard
    set_idt(17, 0);
1201 f4beb510 bellard
    set_idt(18, 0);
1202 f4beb510 bellard
    set_idt(19, 0);
1203 f4beb510 bellard
    set_idt(0x80, 3);
1204 f4beb510 bellard
1205 6dbad63e bellard
    /* linux segment setup */
1206 80a9d035 bellard
    env->gdt.base = (long)gdt_table;
1207 6dbad63e bellard
    env->gdt.limit = sizeof(gdt_table) - 1;
1208 f4beb510 bellard
    write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
1209 f4beb510 bellard
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 
1210 f4beb510 bellard
             (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
1211 f4beb510 bellard
    write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
1212 f4beb510 bellard
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 
1213 f4beb510 bellard
             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
1214 6dbad63e bellard
    cpu_x86_load_seg(env, R_CS, __USER_CS);
1215 6dbad63e bellard
    cpu_x86_load_seg(env, R_DS, __USER_DS);
1216 6dbad63e bellard
    cpu_x86_load_seg(env, R_ES, __USER_DS);
1217 6dbad63e bellard
    cpu_x86_load_seg(env, R_SS, __USER_DS);
1218 6dbad63e bellard
    cpu_x86_load_seg(env, R_FS, __USER_DS);
1219 6dbad63e bellard
    cpu_x86_load_seg(env, R_GS, __USER_DS);
1220 92ccca6a bellard
1221 b346ff46 bellard
#elif defined(TARGET_ARM)
1222 b346ff46 bellard
    {
1223 b346ff46 bellard
        int i;
1224 b346ff46 bellard
        for(i = 0; i < 16; i++) {
1225 b346ff46 bellard
            env->regs[i] = regs->uregs[i];
1226 b346ff46 bellard
        }
1227 b346ff46 bellard
        env->cpsr = regs->uregs[16];
1228 a4f81979 bellard
        ts->stack_base = info->start_stack;
1229 a4f81979 bellard
        ts->heap_base = info->brk;
1230 a4f81979 bellard
        /* This will be filled in on the first SYS_HEAPINFO call.  */
1231 a4f81979 bellard
        ts->heap_limit = 0;
1232 b346ff46 bellard
    }
1233 93ac68bc bellard
#elif defined(TARGET_SPARC)
1234 060366c5 bellard
    {
1235 060366c5 bellard
        int i;
1236 060366c5 bellard
        env->pc = regs->pc;
1237 060366c5 bellard
        env->npc = regs->npc;
1238 060366c5 bellard
        env->y = regs->y;
1239 060366c5 bellard
        for(i = 0; i < 8; i++)
1240 060366c5 bellard
            env->gregs[i] = regs->u_regs[i];
1241 060366c5 bellard
        for(i = 0; i < 8; i++)
1242 060366c5 bellard
            env->regwptr[i] = regs->u_regs[i + 8];
1243 060366c5 bellard
    }
1244 67867308 bellard
#elif defined(TARGET_PPC)
1245 67867308 bellard
    {
1246 67867308 bellard
        int i;
1247 61190b14 bellard
        for (i = 0; i < 32; i++) {
1248 4c2e770f bellard
            if (i != 12 && i != 6 && i != 13)
1249 61190b14 bellard
                env->msr[i] = (regs->msr >> i) & 1;
1250 61190b14 bellard
        }
1251 67867308 bellard
        env->nip = regs->nip;
1252 67867308 bellard
        for(i = 0; i < 32; i++) {
1253 67867308 bellard
            env->gpr[i] = regs->gpr[i];
1254 67867308 bellard
        }
1255 67867308 bellard
    }
1256 b346ff46 bellard
#else
1257 b346ff46 bellard
#error unsupported target CPU
1258 b346ff46 bellard
#endif
1259 31e31b8a bellard
1260 1fddef4b bellard
    if (use_gdbstub) {
1261 1fddef4b bellard
        gdbserver_start (DEFAULT_GDBSTUB_PORT);
1262 1fddef4b bellard
        gdb_handlesig(env, 0);
1263 1fddef4b bellard
    }
1264 1b6b029e bellard
    cpu_loop(env);
1265 1b6b029e bellard
    /* never exits */
1266 31e31b8a bellard
    return 0;
1267 31e31b8a bellard
}