Annotation of qemu/linux-user/main.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.