Darwin-user: Compile fix for ppc targets, by Pierre d'Herbemont.
[qemu] / darwin-user / main.c
1 /*
2  *  qemu user main
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *  Copyright (c) 2006 Pierre d'Herbemont
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27
28 #include <sys/syscall.h>
29 #include <sys/mman.h>
30
31 #include "qemu.h"
32
33 #define DEBUG_LOGFILE "/tmp/qemu.log"
34
35 #ifdef __APPLE__
36 #include <crt_externs.h>
37 # define environ  (*_NSGetEnviron())
38 #endif
39
40 #include <mach/mach_init.h>
41 #include <mach/vm_map.h>
42
43 const char *interp_prefix = "";
44
45 asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
46
47 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
48    we allocate a bigger stack. Need a better solution, for example
49    by remapping the process stack directly at the right place */
50 unsigned long stack_size = 512 * 1024;
51
52 void qerror(const char *fmt, ...)
53 {
54     va_list ap;
55
56     va_start(ap, fmt);
57     vfprintf(stderr, fmt, ap);
58     va_end(ap);
59     fprintf(stderr, "\n");
60     exit(1);
61 }
62
63 void gemu_log(const char *fmt, ...)
64 {
65     va_list ap;
66
67     va_start(ap, fmt);
68     vfprintf(stderr, fmt, ap);
69     va_end(ap);
70 }
71
72 void cpu_outb(CPUState *env, int addr, int val)
73 {
74     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
75 }
76
77 void cpu_outw(CPUState *env, int addr, int val)
78 {
79     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
80 }
81
82 void cpu_outl(CPUState *env, int addr, int val)
83 {
84     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
85 }
86
87 int cpu_inb(CPUState *env, int addr)
88 {
89     fprintf(stderr, "inb: port=0x%04x\n", addr);
90     return 0;
91 }
92
93 int cpu_inw(CPUState *env, int addr)
94 {
95     fprintf(stderr, "inw: port=0x%04x\n", addr);
96     return 0;
97 }
98
99 int cpu_inl(CPUState *env, int addr)
100 {
101     fprintf(stderr, "inl: port=0x%04x\n", addr);
102     return 0;
103 }
104
105 int cpu_get_pic_interrupt(CPUState *env)
106 {
107     return -1;
108 }
109 #ifdef TARGET_PPC
110
111 static inline uint64_t cpu_ppc_get_tb (CPUState *env)
112 {
113     /* TO FIX */
114     return 0;
115 }
116
117 uint32_t cpu_ppc_load_tbl (CPUState *env)
118 {
119     return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
120 }
121
122 uint32_t cpu_ppc_load_tbu (CPUState *env)
123 {
124     return cpu_ppc_get_tb(env) >> 32;
125 }
126
127 static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
128 {
129     /* TO FIX */
130 }
131
132 void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
133 {
134     cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
135 }
136
137 void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
138 {
139     cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
140 }
141
142 uint32_t cpu_ppc_load_decr (CPUState *env)
143 {
144     /* TO FIX */
145     return -1;
146 }
147
148 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
149 {
150     /* TO FIX */
151 }
152
153 void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
154 {
155     cpu_ppc_store_tbu( env, value );
156 }
157
158 uint32_t cpu_ppc601_load_rtcu (CPUState *env)
159 {
160     cpu_ppc_load_tbu(env);
161 }
162
163 uint32_t cpu_ppc601_load_rtcl (CPUState *env)
164 {
165     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
166 }
167
168 void cpu_loop(CPUPPCState *env)
169 {
170     int trapnr;
171     uint32_t ret;
172     target_siginfo_t info;
173
174     for(;;) {
175         trapnr = cpu_ppc_exec(env);
176         if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
177             trapnr != EXCP_TRACE) {
178             if (loglevel > 0) {
179                 cpu_dump_state(env, logfile, fprintf, 0);
180             }
181         }
182         switch(trapnr) {
183         case EXCP_NONE:
184             break;
185         case EXCP_SYSCALL_USER:
186             /* system call */
187             if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
188                 ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
189                                       env->gpr[5], env->gpr[6], env->gpr[7],
190                                       env->gpr[8], env->gpr[9], env->gpr[10]*/);
191             else if(((int)env->gpr[0])<0)
192                 ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
193                                       env->gpr[5], env->gpr[6], env->gpr[7],
194                                       env->gpr[8], env->gpr[9], env->gpr[10]);
195             else
196                 ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
197                                         env->gpr[5], env->gpr[6], env->gpr[7],
198                                         env->gpr[8], env->gpr[9], env->gpr[10]);
199
200             /* Unix syscall error signaling */
201             if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
202             {
203                 if( (int)ret < 0 )
204                     env->nip += 0;
205                 else
206                     env->nip += 4;
207             }
208
209             /* Return value */
210             env->gpr[3] = ret;
211             break;
212         case EXCP_RESET:
213             /* Should not happen ! */
214             fprintf(stderr, "RESET asked... Stop emulation\n");
215             if (loglevel)
216                 fprintf(logfile, "RESET asked... Stop emulation\n");
217                 abort();
218         case EXCP_MACHINE_CHECK:
219             fprintf(stderr, "Machine check exeption...  Stop emulation\n");
220             if (loglevel)
221                 fprintf(logfile, "RESET asked... Stop emulation\n");
222                 info.si_signo = SIGBUS;
223             info.si_errno = 0;
224             info.si_code = BUS_OBJERR;
225             info.si_addr = (void*)(env->nip - 4);
226             queue_signal(info.si_signo, &info);
227         case EXCP_DSI:
228 #ifndef DAR
229 /* To deal with multiple qemu header version as host for the darwin-user code */
230 # define DAR SPR_DAR
231 #endif
232             fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
233             if (loglevel) {
234                 fprintf(logfile, "Invalid data memory access: 0x%08x\n",
235                         env->spr[DAR]);
236             }
237             /* Handle this via the gdb */
238             gdb_handlesig (env, SIGSEGV);
239
240             info.si_addr = (void*)env->nip;
241             queue_signal(info.si_signo, &info);
242             break;
243         case EXCP_ISI:
244             fprintf(stderr, "Invalid instruction fetch\n");
245             if (loglevel)
246                 fprintf(logfile, "Invalid instruction fetch\n");
247             /* Handle this via the gdb */
248             gdb_handlesig (env, SIGSEGV);
249
250             info.si_addr = (void*)(env->nip - 4);
251             queue_signal(info.si_signo, &info);
252             break;
253         case EXCP_EXTERNAL:
254             /* Should not happen ! */
255             fprintf(stderr, "External interruption... Stop emulation\n");
256             if (loglevel)
257                 fprintf(logfile, "External interruption... Stop emulation\n");
258                 abort();
259         case EXCP_ALIGN:
260             fprintf(stderr, "Invalid unaligned memory access\n");
261             if (loglevel)
262                 fprintf(logfile, "Invalid unaligned memory access\n");
263                 info.si_signo = SIGBUS;
264             info.si_errno = 0;
265             info.si_code = BUS_ADRALN;
266             info.si_addr = (void*)(env->nip - 4);
267             queue_signal(info.si_signo, &info);
268             break;
269         case EXCP_PROGRAM:
270             switch (env->error_code & ~0xF) {
271                 case EXCP_FP:
272                     fprintf(stderr, "Program exception\n");
273                     if (loglevel)
274                         fprintf(logfile, "Program exception\n");
275                         /* Set FX */
276                         env->fpscr[7] |= 0x8;
277                     /* Finally, update FEX */
278                     if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
279                         ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
280                         env->fpscr[7] |= 0x4;
281                         info.si_signo = SIGFPE;
282                     info.si_errno = 0;
283                     switch (env->error_code & 0xF) {
284                         case EXCP_FP_OX:
285                             info.si_code = FPE_FLTOVF;
286                             break;
287                         case EXCP_FP_UX:
288                             info.si_code = FPE_FLTUND;
289                             break;
290                         case EXCP_FP_ZX:
291                         case EXCP_FP_VXZDZ:
292                             info.si_code = FPE_FLTDIV;
293                             break;
294                         case EXCP_FP_XX:
295                             info.si_code = FPE_FLTRES;
296                             break;
297                         case EXCP_FP_VXSOFT:
298                             info.si_code = FPE_FLTINV;
299                             break;
300                         case EXCP_FP_VXNAN:
301                         case EXCP_FP_VXISI:
302                         case EXCP_FP_VXIDI:
303                         case EXCP_FP_VXIMZ:
304                         case EXCP_FP_VXVC:
305                         case EXCP_FP_VXSQRT:
306                         case EXCP_FP_VXCVI:
307                             info.si_code = FPE_FLTSUB;
308                             break;
309                         default:
310                             fprintf(stderr, "Unknown floating point exception "
311                                     "(%02x)\n", env->error_code);
312                             if (loglevel) {
313                                 fprintf(logfile, "Unknown floating point exception "
314                                         "(%02x)\n", env->error_code & 0xF);
315                             }
316                     }
317                         break;
318                 case EXCP_INVAL:
319                     fprintf(stderr, "Invalid instruction\n");
320                     if (loglevel)
321                         fprintf(logfile, "Invalid instruction\n");
322                         info.si_signo = SIGILL;
323                     info.si_errno = 0;
324                     switch (env->error_code & 0xF) {
325                         case EXCP_INVAL_INVAL:
326                             info.si_code = ILL_ILLOPC;
327                             break;
328                         case EXCP_INVAL_LSWX:
329                             info.si_code = ILL_ILLOPN;
330                             break;
331                         case EXCP_INVAL_SPR:
332                             info.si_code = ILL_PRVREG;
333                             break;
334                         case EXCP_INVAL_FP:
335                             info.si_code = ILL_COPROC;
336                             break;
337                         default:
338                             fprintf(stderr, "Unknown invalid operation (%02x)\n",
339                                     env->error_code & 0xF);
340                             if (loglevel) {
341                                 fprintf(logfile, "Unknown invalid operation (%02x)\n",
342                                         env->error_code & 0xF);
343                             }
344                                 info.si_code = ILL_ILLADR;
345                             break;
346                     }
347                         /* Handle this via the gdb */
348                         gdb_handlesig (env, SIGSEGV);
349                     break;
350                 case EXCP_PRIV:
351                     fprintf(stderr, "Privilege violation\n");
352                     if (loglevel)
353                         fprintf(logfile, "Privilege violation\n");
354                         info.si_signo = SIGILL;
355                     info.si_errno = 0;
356                     switch (env->error_code & 0xF) {
357                         case EXCP_PRIV_OPC:
358                             info.si_code = ILL_PRVOPC;
359                             break;
360                         case EXCP_PRIV_REG:
361                             info.si_code = ILL_PRVREG;
362                             break;
363                         default:
364                             fprintf(stderr, "Unknown privilege violation (%02x)\n",
365                                     env->error_code & 0xF);
366                             info.si_code = ILL_PRVOPC;
367                             break;
368                     }
369                         break;
370                 case EXCP_TRAP:
371                     fprintf(stderr, "Tried to call a TRAP\n");
372                     if (loglevel)
373                         fprintf(logfile, "Tried to call a TRAP\n");
374                         abort();
375                 default:
376                     /* Should not happen ! */
377                     fprintf(stderr, "Unknown program exception (%02x)\n",
378                             env->error_code);
379                     if (loglevel) {
380                         fprintf(logfile, "Unknwon program exception (%02x)\n",
381                                 env->error_code);
382                     }
383                         abort();
384             }
385             info.si_addr = (void*)(env->nip - 4);
386             queue_signal(info.si_signo, &info);
387             break;
388         case EXCP_NO_FP:
389             fprintf(stderr, "No floating point allowed\n");
390             if (loglevel)
391                 fprintf(logfile, "No floating point allowed\n");
392                 info.si_signo = SIGILL;
393             info.si_errno = 0;
394             info.si_code = ILL_COPROC;
395             info.si_addr = (void*)(env->nip - 4);
396             queue_signal(info.si_signo, &info);
397             break;
398         case EXCP_DECR:
399             /* Should not happen ! */
400             fprintf(stderr, "Decrementer exception\n");
401             if (loglevel)
402                 fprintf(logfile, "Decrementer exception\n");
403             abort();
404         case EXCP_TRACE:
405             /* Pass to gdb: we use this to trace execution */
406             gdb_handlesig (env, SIGTRAP);
407             break;
408         case EXCP_FP_ASSIST:
409             /* Should not happen ! */
410             fprintf(stderr, "Floating point assist exception\n");
411             if (loglevel)
412                 fprintf(logfile, "Floating point assist exception\n");
413             abort();
414         case EXCP_MTMSR:
415             /* We reloaded the msr, just go on */
416             if (msr_pr == 0) {
417                 fprintf(stderr, "Tried to go into supervisor mode !\n");
418                 if (loglevel)
419                     fprintf(logfile, "Tried to go into supervisor mode !\n");
420                 abort();
421             }
422             break;
423         case EXCP_BRANCH:
424             /* We stopped because of a jump... */
425             break;
426         case EXCP_INTERRUPT:
427             /* Don't know why this should ever happen... */
428             fprintf(stderr, "EXCP_INTERRUPT\n");
429             break;
430         case EXCP_DEBUG:
431             gdb_handlesig (env, SIGTRAP);
432             break;
433         default:
434             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
435                     trapnr);
436             if (loglevel) {
437                 fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
438                         "0x%02x - aborting\n", trapnr, env->error_code);
439             }
440                 abort();
441         }
442         process_pending_signals(env);
443     }
444 }
445 #endif
446
447
448 #ifdef TARGET_I386
449
450 /***********************************************************/
451 /* CPUX86 core interface */
452
453 uint64_t cpu_get_tsc(CPUX86State *env)
454 {
455     return cpu_get_real_ticks();
456 }
457
458 void
459 write_dt(void *ptr, unsigned long addr, unsigned long limit,
460                      int flags)
461 {
462     unsigned int e1, e2;
463     e1 = (addr << 16) | (limit & 0xffff);
464     e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
465     e2 |= flags;
466     stl((uint8_t *)ptr, e1);
467     stl((uint8_t *)ptr + 4, e2);
468 }
469
470 static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
471                      unsigned long addr, unsigned int sel)
472 {
473     unsigned int e1, e2;
474     e1 = (addr & 0xffff) | (sel << 16);
475     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
476     stl((uint8_t *)ptr, e1);
477     stl((uint8_t *)ptr + 4, e2);
478 }
479
480 #define GDT_TABLE_SIZE 14
481 #define LDT_TABLE_SIZE 15
482 #define IDT_TABLE_SIZE 256
483 #define TSS_SIZE 104
484 uint64_t gdt_table[GDT_TABLE_SIZE];
485 uint64_t ldt_table[LDT_TABLE_SIZE];
486 uint64_t idt_table[IDT_TABLE_SIZE];
487 uint32_t tss[TSS_SIZE];
488
489 /* only dpl matters as we do only user space emulation */
490 static void set_idt(int n, unsigned int dpl)
491 {
492     set_gate(idt_table + n, 0, dpl, 0, 0);
493 }
494
495 /* ABI convention: after a syscall if there was an error the CF flag is set */
496 static inline void set_error(CPUX86State *env, int ret)
497 {
498     if(ret<0)
499         env->eflags = env->eflags | 0x1;
500     else
501         env->eflags &= ~0x1;
502     env->regs[R_EAX] = ret;
503 }
504
505 void cpu_loop(CPUX86State *env)
506 {
507     int trapnr;
508     int ret;
509     uint8_t *pc;
510     target_siginfo_t info;
511
512     for(;;) {
513         trapnr = cpu_x86_exec(env);
514         uint32_t *params = (uint32_t *)env->regs[R_ESP];
515         switch(trapnr) {
516         case 0x79: /* Our commpage hack back door exit is here */
517             do_commpage(env,  env->eip,   *(params + 1), *(params + 2),
518                                           *(params + 3), *(params + 4),
519                                           *(params + 5), *(params + 6),
520                                           *(params + 7), *(params + 8));
521             break;
522         case 0x81: /* mach syscall */
523         {
524             ret = do_mach_syscall(env,  env->regs[R_EAX],
525                                           *(params + 1), *(params + 2),
526                                           *(params + 3), *(params + 4),
527                                           *(params + 5), *(params + 6),
528                                           *(params + 7), *(params + 8));
529             set_error(env, ret);
530             break;
531         }
532         case 0x90: /* unix backdoor */
533         {
534             /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
535             int saved_stack = env->regs[R_ESP];
536             env->regs[R_ESP] = env->regs[R_ECX];
537
538             ret = do_unix_syscall(env, env->regs[R_EAX]);
539
540             env->regs[R_ECX] = env->regs[R_ESP];
541             env->regs[R_ESP] = saved_stack;
542
543             set_error(env, ret);
544             break;
545         }
546         case 0x80: /* unix syscall */
547         {
548             ret = do_unix_syscall(env, env->regs[R_EAX]/*,
549                                           *(params + 1), *(params + 2),
550                                           *(params + 3), *(params + 4),
551                                           *(params + 5), *(params + 6),
552                                           *(params + 7), *(params + 8)*/);
553             set_error(env, ret);
554             break;
555         }
556         case 0x82: /* thread syscall */
557         {
558             ret = do_thread_syscall(env,  env->regs[R_EAX],
559                                           *(params + 1), *(params + 2),
560                                           *(params + 3), *(params + 4),
561                                           *(params + 5), *(params + 6),
562                                           *(params + 7), *(params + 8));
563             set_error(env, ret);
564             break;
565         }
566         case EXCP0B_NOSEG:
567         case EXCP0C_STACK:
568             info.si_signo = SIGBUS;
569             info.si_errno = 0;
570             info.si_code = BUS_NOOP;
571             info.si_addr = 0;
572             gdb_handlesig (env, SIGBUS);
573             queue_signal(info.si_signo, &info);
574             break;
575         case EXCP0D_GPF:
576             info.si_signo = SIGSEGV;
577             info.si_errno = 0;
578             info.si_code = SEGV_NOOP;
579             info.si_addr = 0;
580             gdb_handlesig (env, SIGSEGV);
581             queue_signal(info.si_signo, &info);
582             break;
583         case EXCP0E_PAGE:
584             info.si_signo = SIGSEGV;
585             info.si_errno = 0;
586             if (!(env->error_code & 1))
587                 info.si_code = SEGV_MAPERR;
588             else
589                 info.si_code = SEGV_ACCERR;
590             info.si_addr = (void*)env->cr[2];
591             gdb_handlesig (env, SIGSEGV);
592             queue_signal(info.si_signo, &info);
593             break;
594         case EXCP00_DIVZ:
595             /* division by zero */
596             info.si_signo = SIGFPE;
597             info.si_errno = 0;
598             info.si_code = FPE_INTDIV;
599             info.si_addr = (void*)env->eip;
600             gdb_handlesig (env, SIGFPE);
601             queue_signal(info.si_signo, &info);
602             break;
603         case EXCP01_SSTP:
604         case EXCP03_INT3:
605             info.si_signo = SIGTRAP;
606             info.si_errno = 0;
607             info.si_code = TRAP_BRKPT;
608             info.si_addr = (void*)env->eip;
609             gdb_handlesig (env, SIGTRAP);
610             queue_signal(info.si_signo, &info);
611             break;
612         case EXCP04_INTO:
613         case EXCP05_BOUND:
614             info.si_signo = SIGSEGV;
615             info.si_errno = 0;
616             info.si_code = SEGV_NOOP;
617             info.si_addr = 0;
618             gdb_handlesig (env, SIGSEGV);
619             queue_signal(info.si_signo, &info);
620             break;
621         case EXCP06_ILLOP:
622             info.si_signo = SIGILL;
623             info.si_errno = 0;
624             info.si_code = ILL_ILLOPN;
625             info.si_addr = (void*)env->eip;
626             gdb_handlesig (env, SIGILL);
627             queue_signal(info.si_signo, &info);
628             break;
629         case EXCP_INTERRUPT:
630             /* just indicate that signals should be handled asap */
631             break;
632         case EXCP_DEBUG:
633             {
634                 int sig;
635
636                 sig = gdb_handlesig (env, SIGTRAP);
637                 if (sig)
638                   {
639                     info.si_signo = sig;
640                     info.si_errno = 0;
641                     info.si_code = TRAP_BRKPT;
642                     queue_signal(info.si_signo, &info);
643                   }
644             }
645             break;
646         default:
647             pc = (void*)(env->segs[R_CS].base + env->eip);
648             fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
649                     (long)pc, trapnr);
650             abort();
651         }
652         process_pending_signals(env);
653     }
654 }
655 #endif
656
657 void usage(void)
658 {
659     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
660            "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
661            "Darwin CPU emulator (compiled for %s emulation)\n"
662            "\n"
663            "-h           print this help\n"
664            "-L path      set the %s library path (default='%s')\n"
665            "-s size      set the stack size in bytes (default=%ld)\n"
666            "\n"
667            "debug options:\n"
668 #ifdef USE_CODE_COPY
669            "-no-code-copy   disable code copy acceleration\n"
670 #endif
671            "-d options   activate log (logfile='%s')\n"
672            "-g wait for gdb on port 1234\n"
673            "-p pagesize  set the host page size to 'pagesize'\n",
674            TARGET_ARCH,
675            TARGET_ARCH,
676            interp_prefix,
677            stack_size,
678            DEBUG_LOGFILE);
679     _exit(1);
680 }
681
682 /* XXX: currently only used for async signals (see signal.c) */
683 CPUState *global_env;
684 /* used only if single thread */
685 CPUState *cpu_single_env = NULL;
686
687 /* used to free thread contexts */
688 TaskState *first_task_state;
689
690 int main(int argc, char **argv)
691 {
692     const char *filename;
693     struct target_pt_regs regs1, *regs = &regs1;
694     TaskState ts1, *ts = &ts1;
695     CPUState *env;
696     int optind;
697     short use_gdbstub = 0;
698     const char *r;
699
700     if (argc <= 1)
701         usage();
702
703     /* init debug */
704     cpu_set_log_filename(DEBUG_LOGFILE);
705
706     optind = 1;
707     for(;;) {
708         if (optind >= argc)
709             break;
710         r = argv[optind];
711         if (r[0] != '-')
712             break;
713         optind++;
714         r++;
715         if (!strcmp(r, "-")) {
716             break;
717         } else if (!strcmp(r, "d")) {
718             int mask;
719             CPULogItem *item;
720
721         if (optind >= argc)
722         break;
723
724         r = argv[optind++];
725             mask = cpu_str_to_log_mask(r);
726             if (!mask) {
727                 printf("Log items (comma separated):\n");
728                 for(item = cpu_log_items; item->mask != 0; item++) {
729                     printf("%-10s %s\n", item->name, item->help);
730                 }
731                 exit(1);
732             }
733             cpu_set_log(mask);
734         } else if (!strcmp(r, "s")) {
735             r = argv[optind++];
736             stack_size = strtol(r, (char **)&r, 0);
737             if (stack_size <= 0)
738                 usage();
739             if (*r == 'M')
740                 stack_size *= 1024 * 1024;
741             else if (*r == 'k' || *r == 'K')
742                 stack_size *= 1024;
743         } else if (!strcmp(r, "L")) {
744             interp_prefix = argv[optind++];
745         } else if (!strcmp(r, "p")) {
746             qemu_host_page_size = atoi(argv[optind++]);
747             if (qemu_host_page_size == 0 ||
748                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
749                 fprintf(stderr, "page size must be a power of two\n");
750                 exit(1);
751             }
752         } else
753         if (!strcmp(r, "g")) {
754             use_gdbstub = 1;
755         } else
756 #ifdef USE_CODE_COPY
757         if (!strcmp(r, "no-code-copy")) {
758             code_copy_enabled = 0;
759         } else
760 #endif
761         {
762             usage();
763         }
764     }
765     if (optind >= argc)
766         usage();
767     filename = argv[optind];
768
769     /* Zero out regs */
770     memset(regs, 0, sizeof(struct target_pt_regs));
771
772     /* NOTE: we need to init the CPU at this stage to get
773        qemu_host_page_size */
774     env = cpu_init();
775
776     printf("Starting %s with qemu\n----------------\n", filename);
777
778     commpage_init();
779
780     if (mach_exec(filename, argv+optind, environ, regs) != 0) {
781     printf("Error loading %s\n", filename);
782     _exit(1);
783     }
784
785     syscall_init();
786     signal_init();
787     global_env = env;
788
789     /* build Task State */
790     memset(ts, 0, sizeof(TaskState));
791     env->opaque = ts;
792     ts->used = 1;
793     env->user_mode_only = 1;
794
795 #if defined(TARGET_I386)
796     cpu_x86_set_cpl(env, 3);
797
798     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
799     env->hflags |= HF_PE_MASK;
800
801     if (env->cpuid_features & CPUID_SSE) {
802         env->cr[4] |= CR4_OSFXSR_MASK;
803         env->hflags |= HF_OSFXSR_MASK;
804     }
805
806     /* flags setup : we activate the IRQs by default as in user mode */
807     env->eflags |= IF_MASK;
808
809     /* darwin register setup */
810     env->regs[R_EAX] = regs->eax;
811     env->regs[R_EBX] = regs->ebx;
812     env->regs[R_ECX] = regs->ecx;
813     env->regs[R_EDX] = regs->edx;
814     env->regs[R_ESI] = regs->esi;
815     env->regs[R_EDI] = regs->edi;
816     env->regs[R_EBP] = regs->ebp;
817     env->regs[R_ESP] = regs->esp;
818     env->eip = regs->eip;
819
820     /* Darwin LDT setup */
821     /* 2 - User code segment
822        3 - User data segment
823        4 - User cthread */
824     bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
825     env->ldt.base = (uint32_t) ldt_table;
826     env->ldt.limit = sizeof(ldt_table) - 1;
827
828     write_dt(ldt_table + 2, 0, 0xfffff,
829              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
830              (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
831     write_dt(ldt_table + 3, 0, 0xfffff,
832              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
833              (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
834     write_dt(ldt_table + 4, 0, 0xfffff,
835              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
836              (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
837
838     /* Darwin GDT setup.
839      * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
840        now everything is done via  int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
841     bzero(gdt_table, sizeof(gdt_table));
842     env->gdt.base = (uint32_t)gdt_table;
843     env->gdt.limit = sizeof(gdt_table) - 1;
844
845     /* Set up a back door to handle sysenter syscalls (unix) */
846     char * syscallbackdoor = malloc(64);
847     page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
848
849     int i = 0;
850     syscallbackdoor[i++] = 0xcd;
851     syscallbackdoor[i++] = 0x90; /* int 0x90 */
852     syscallbackdoor[i++] = 0x0F;
853     syscallbackdoor[i++] = 0x35; /* sysexit */
854
855     /* Darwin sysenter/sysexit setup */
856     env->sysenter_cs = 0x1; //XXX
857     env->sysenter_eip = (int)syscallbackdoor;
858     env->sysenter_esp = (int)malloc(64);
859
860     /* Darwin TSS setup
861        This must match up with GDT[4] */
862     env->tr.base = (uint32_t) tss;
863     env->tr.limit = sizeof(tss) - 1;
864     env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
865     stw(tss + 2, 0x10);  // ss0 = 0x10 = GDT[2] = Kernel Data Segment
866
867     /* Darwin interrupt setup */
868     bzero(idt_table, sizeof(idt_table));
869     env->idt.base = (uint32_t) idt_table;
870     env->idt.limit = sizeof(idt_table) - 1;
871     set_idt(0, 0);
872     set_idt(1, 0);
873     set_idt(2, 0);
874     set_idt(3, 3);
875     set_idt(4, 3);
876     set_idt(5, 3);
877     set_idt(6, 0);
878     set_idt(7, 0);
879     set_idt(8, 0);
880     set_idt(9, 0);
881     set_idt(10, 0);
882     set_idt(11, 0);
883     set_idt(12, 0);
884     set_idt(13, 0);
885     set_idt(14, 0);
886     set_idt(15, 0);
887     set_idt(16, 0);
888     set_idt(17, 0);
889     set_idt(18, 0);
890     set_idt(19, 0);
891     /* Syscalls are done via
892         int 0x80 (unix) (rarely used)
893         int 0x81 (mach)
894         int 0x82 (thread)
895         int 0x83 (diag) (not handled here)
896         sysenter/sysexit (unix) -> we redirect that to int 0x90 */
897     set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
898     set_idt(0x80, 3); /* Unix Syscall */
899     set_idt(0x81, 3); /* Mach Syscalls */
900     set_idt(0x82, 3); /* thread Syscalls */
901
902     set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
903
904
905     cpu_x86_load_seg(env, R_CS, __USER_CS);
906     cpu_x86_load_seg(env, R_DS, __USER_DS);
907     cpu_x86_load_seg(env, R_ES, __USER_DS);
908     cpu_x86_load_seg(env, R_SS, __USER_DS);
909     cpu_x86_load_seg(env, R_FS, __USER_DS);
910     cpu_x86_load_seg(env, R_GS, __USER_DS);
911
912 #elif defined(TARGET_PPC)
913     {
914         int i;
915         env->nip = regs->nip;
916         for(i = 0; i < 32; i++) {
917             env->gpr[i] = regs->gpr[i];
918         }
919     }
920 #else
921 #error unsupported target CPU
922 #endif
923
924     if (use_gdbstub) {
925         printf("Waiting for gdb Connection on port 1234...\n");
926         gdbserver_start (1234);
927         gdb_handlesig(env, 0);
928     }
929
930     cpu_loop(env);
931     /* never exits */
932     return 0;
933 }