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