|
|
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 = ®s1; ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.