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