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