Commit 61190b14fc96d4e19c9bdde25643be4c5eb90e62
1 parent
9886cc16
PowerPC update (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@536 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
315 additions
and
86 deletions
linux-user/main.c
| @@ -59,44 +59,44 @@ void gemu_log(const char *fmt, ...) | @@ -59,44 +59,44 @@ void gemu_log(const char *fmt, ...) | ||
| 59 | va_end(ap); | 59 | va_end(ap); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | -#ifdef TARGET_I386 | ||
| 63 | -/***********************************************************/ | ||
| 64 | -/* CPUX86 core interface */ | ||
| 65 | - | ||
| 66 | -void cpu_x86_outb(CPUX86State *env, int addr, int val) | 62 | +void cpu_outb(CPUState *env, int addr, int val) |
| 67 | { | 63 | { |
| 68 | fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); | 64 | fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); |
| 69 | } | 65 | } |
| 70 | 66 | ||
| 71 | -void cpu_x86_outw(CPUX86State *env, int addr, int val) | 67 | +void cpu_outw(CPUState *env, int addr, int val) |
| 72 | { | 68 | { |
| 73 | fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); | 69 | fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); |
| 74 | } | 70 | } |
| 75 | 71 | ||
| 76 | -void cpu_x86_outl(CPUX86State *env, int addr, int val) | 72 | +void cpu_outl(CPUState *env, int addr, int val) |
| 77 | { | 73 | { |
| 78 | fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); | 74 | fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); |
| 79 | } | 75 | } |
| 80 | 76 | ||
| 81 | -int cpu_x86_inb(CPUX86State *env, int addr) | 77 | +int cpu_inb(CPUState *env, int addr) |
| 82 | { | 78 | { |
| 83 | fprintf(stderr, "inb: port=0x%04x\n", addr); | 79 | fprintf(stderr, "inb: port=0x%04x\n", addr); |
| 84 | return 0; | 80 | return 0; |
| 85 | } | 81 | } |
| 86 | 82 | ||
| 87 | -int cpu_x86_inw(CPUX86State *env, int addr) | 83 | +int cpu_inw(CPUState *env, int addr) |
| 88 | { | 84 | { |
| 89 | fprintf(stderr, "inw: port=0x%04x\n", addr); | 85 | fprintf(stderr, "inw: port=0x%04x\n", addr); |
| 90 | return 0; | 86 | return 0; |
| 91 | } | 87 | } |
| 92 | 88 | ||
| 93 | -int cpu_x86_inl(CPUX86State *env, int addr) | 89 | +int cpu_inl(CPUState *env, int addr) |
| 94 | { | 90 | { |
| 95 | fprintf(stderr, "inl: port=0x%04x\n", addr); | 91 | fprintf(stderr, "inl: port=0x%04x\n", addr); |
| 96 | return 0; | 92 | return 0; |
| 97 | } | 93 | } |
| 98 | 94 | ||
| 99 | -int cpu_x86_get_pic_interrupt(CPUX86State *env) | 95 | +#ifdef TARGET_I386 |
| 96 | +/***********************************************************/ | ||
| 97 | +/* CPUX86 core interface */ | ||
| 98 | + | ||
| 99 | +int cpu_x86_get_pic_interrupt(CPUState *env) | ||
| 100 | { | 100 | { |
| 101 | return -1; | 101 | return -1; |
| 102 | } | 102 | } |
| @@ -428,119 +428,346 @@ void cpu_loop (CPUSPARCState *env) | @@ -428,119 +428,346 @@ void cpu_loop (CPUSPARCState *env) | ||
| 428 | 428 | ||
| 429 | void cpu_loop(CPUPPCState *env) | 429 | void cpu_loop(CPUPPCState *env) |
| 430 | { | 430 | { |
| 431 | - int trapnr; | ||
| 432 | target_siginfo_t info; | 431 | target_siginfo_t info; |
| 432 | + int trapnr; | ||
| 433 | + uint32_t ret; | ||
| 433 | 434 | ||
| 434 | for(;;) { | 435 | for(;;) { |
| 435 | trapnr = cpu_ppc_exec(env); | 436 | trapnr = cpu_ppc_exec(env); |
| 437 | + if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH && | ||
| 438 | + trapnr != EXCP_TRACE) { | ||
| 439 | + if (loglevel > 0) { | ||
| 440 | + cpu_ppc_dump_state(env, logfile, 0); | ||
| 441 | + } | ||
| 442 | + } | ||
| 436 | switch(trapnr) { | 443 | switch(trapnr) { |
| 437 | case EXCP_NONE: | 444 | case EXCP_NONE: |
| 438 | - case EXCP_INTERRUPT: | ||
| 439 | - case EXCP_MTMSR: /* mtmsr instruction: */ | ||
| 440 | - case EXCP_BRANCH: /* branch instruction */ | ||
| 441 | - /* Single step mode */ | ||
| 442 | break; | 445 | break; |
| 446 | + case EXCP_SYSCALL_USER: | ||
| 447 | + /* system call */ | ||
| 448 | + /* WARNING: | ||
| 449 | + * PPC ABI uses overflow flag in cr0 to signal an error | ||
| 450 | + * in syscalls. | ||
| 451 | + */ | ||
| 443 | #if 0 | 452 | #if 0 |
| 444 | - case EXCP_RESET: /* System reset */ | ||
| 445 | - fprintf(stderr, "RESET asked... Stop emulation\n"); | ||
| 446 | - cpu_ppc_dump_state(env, stderr, 0); | ||
| 447 | - abort(); | 453 | + printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0], |
| 454 | + env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]); | ||
| 448 | #endif | 455 | #endif |
| 449 | - case EXCP_MACHINE_CHECK: /* Machine check exception */ | ||
| 450 | - fprintf(stderr, "Machine check exeption... " | ||
| 451 | - "See you in kernel code !\n"); | ||
| 452 | - cpu_ppc_dump_state(env, stderr, 0); | 456 | + env->crf[0] &= ~0x1; |
| 457 | + ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], | ||
| 458 | + env->gpr[5], env->gpr[6], env->gpr[7], | ||
| 459 | + env->gpr[8]); | ||
| 460 | + if (ret > (uint32_t)(-515)) { | ||
| 461 | + env->crf[0] |= 0x1; | ||
| 462 | + ret = -ret; | ||
| 463 | + } | ||
| 464 | + env->gpr[3] = ret; | ||
| 465 | +#if 0 | ||
| 466 | + printf("syscall returned 0x%08x (%d)\n", ret, ret); | ||
| 467 | +#endif | ||
| 468 | + break; | ||
| 469 | + case EXCP_RESET: | ||
| 470 | + /* Should not happen ! */ | ||
| 471 | + fprintf(stderr, "RESET asked... Stop emulation\n"); | ||
| 472 | + if (loglevel) | ||
| 473 | + fprintf(logfile, "RESET asked... Stop emulation\n"); | ||
| 453 | abort(); | 474 | abort(); |
| 454 | - case EXCP_DSI: /* Impossible memory access */ | ||
| 455 | - fprintf(stderr, "Invalid memory access\n"); | ||
| 456 | - info.si_signo = SIGSEGV; | 475 | + case EXCP_MACHINE_CHECK: |
| 476 | + fprintf(stderr, "Machine check exeption... Stop emulation\n"); | ||
| 477 | + if (loglevel) | ||
| 478 | + fprintf(logfile, "RESET asked... Stop emulation\n"); | ||
| 479 | + info.si_signo = TARGET_SIGBUS; | ||
| 457 | info.si_errno = 0; | 480 | info.si_errno = 0; |
| 458 | - info.si_code = TARGET_ILL_ILLOPN; | 481 | + info.si_code = TARGET_BUS_OBJERR; |
| 482 | + info._sifields._sigfault._addr = env->nip - 4; | ||
| 483 | + queue_signal(info.si_signo, &info); | ||
| 484 | + case EXCP_DSI: | ||
| 485 | + fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]); | ||
| 486 | + if (loglevel) { | ||
| 487 | + fprintf(logfile, "Invalid data memory access: 0x%08x\n", | ||
| 488 | + env->spr[DAR]); | ||
| 489 | + } | ||
| 490 | + switch (env->error_code & 0xF) { | ||
| 491 | + case EXCP_DSI_TRANSLATE: | ||
| 492 | + info.si_signo = TARGET_SIGSEGV; | ||
| 493 | + info.si_errno = 0; | ||
| 494 | + info.si_code = TARGET_SEGV_MAPERR; | ||
| 495 | + break; | ||
| 496 | + case EXCP_DSI_NOTSUP: | ||
| 497 | + case EXCP_DSI_EXTERNAL: | ||
| 498 | + info.si_signo = TARGET_SIGILL; | ||
| 499 | + info.si_errno = 0; | ||
| 500 | + info.si_code = TARGET_ILL_ILLADR; | ||
| 501 | + break; | ||
| 502 | + case EXCP_DSI_PROT: | ||
| 503 | + info.si_signo = TARGET_SIGSEGV; | ||
| 504 | + info.si_errno = 0; | ||
| 505 | + info.si_code = TARGET_SEGV_ACCERR; | ||
| 506 | + break; | ||
| 507 | + case EXCP_DSI_DABR: | ||
| 508 | + info.si_signo = TARGET_SIGTRAP; | ||
| 509 | + info.si_errno = 0; | ||
| 510 | + info.si_code = TARGET_TRAP_BRKPT; | ||
| 511 | + break; | ||
| 512 | + default: | ||
| 513 | + /* Let's send a regular segfault... */ | ||
| 514 | + fprintf(stderr, "Invalid segfault errno (%02x)\n", | ||
| 515 | + env->error_code); | ||
| 516 | + if (loglevel) { | ||
| 517 | + fprintf(logfile, "Invalid segfault errno (%02x)\n", | ||
| 518 | + env->error_code); | ||
| 519 | + } | ||
| 520 | + info.si_signo = TARGET_SIGSEGV; | ||
| 521 | + info.si_errno = 0; | ||
| 522 | + info.si_code = TARGET_SEGV_MAPERR; | ||
| 523 | + break; | ||
| 524 | + } | ||
| 459 | info._sifields._sigfault._addr = env->nip; | 525 | info._sifields._sigfault._addr = env->nip; |
| 460 | queue_signal(info.si_signo, &info); | 526 | queue_signal(info.si_signo, &info); |
| 461 | break; | 527 | break; |
| 462 | - case EXCP_ISI: /* Impossible instruction fetch */ | 528 | + case EXCP_ISI: |
| 463 | fprintf(stderr, "Invalid instruction fetch\n"); | 529 | fprintf(stderr, "Invalid instruction fetch\n"); |
| 464 | - info.si_signo = SIGBUS; | 530 | + if (loglevel) |
| 531 | + fprintf(logfile, "Invalid instruction fetch\n"); | ||
| 532 | + switch (env->error_code) { | ||
| 533 | + case EXCP_ISI_TRANSLATE: | ||
| 534 | + info.si_signo = TARGET_SIGSEGV; | ||
| 465 | info.si_errno = 0; | 535 | info.si_errno = 0; |
| 466 | - info.si_code = TARGET_ILL_ILLOPN; | ||
| 467 | - info._sifields._sigfault._addr = env->nip; | 536 | + info.si_code = TARGET_SEGV_MAPERR; |
| 537 | + break; | ||
| 538 | + case EXCP_ISI_GUARD: | ||
| 539 | + info.si_signo = TARGET_SIGILL; | ||
| 540 | + info.si_errno = 0; | ||
| 541 | + info.si_code = TARGET_ILL_ILLADR; | ||
| 542 | + break; | ||
| 543 | + case EXCP_ISI_NOEXEC: | ||
| 544 | + case EXCP_ISI_PROT: | ||
| 545 | + info.si_signo = TARGET_SIGSEGV; | ||
| 546 | + info.si_errno = 0; | ||
| 547 | + info.si_code = TARGET_SEGV_ACCERR; | ||
| 548 | + break; | ||
| 549 | + default: | ||
| 550 | + /* Let's send a regular segfault... */ | ||
| 551 | + fprintf(stderr, "Invalid segfault errno (%02x)\n", | ||
| 552 | + env->error_code); | ||
| 553 | + if (loglevel) { | ||
| 554 | + fprintf(logfile, "Invalid segfault errno (%02x)\n", | ||
| 555 | + env->error_code); | ||
| 556 | + } | ||
| 557 | + info.si_signo = TARGET_SIGSEGV; | ||
| 558 | + info.si_errno = 0; | ||
| 559 | + info.si_code = TARGET_SEGV_MAPERR; | ||
| 560 | + break; | ||
| 561 | + } | ||
| 562 | + info._sifields._sigfault._addr = env->nip - 4; | ||
| 468 | queue_signal(info.si_signo, &info); | 563 | queue_signal(info.si_signo, &info); |
| 469 | break; | 564 | break; |
| 470 | - case EXCP_EXTERNAL: /* External interruption */ | ||
| 471 | - fprintf(stderr, "External access exeption\n"); | ||
| 472 | - cpu_ppc_dump_state(env, stderr, 0); | ||
| 473 | - abort(); | ||
| 474 | - case EXCP_ALIGN: /* Alignment exception */ | ||
| 475 | - fprintf(stderr, "Alignment exception\n"); | ||
| 476 | - cpu_ppc_dump_state(env, stderr, 0); | ||
| 477 | - abort(); | ||
| 478 | - case EXCP_PROGRAM: /* Program exception */ | ||
| 479 | - fprintf(stderr, "Program exception\n"); | ||
| 480 | - cpu_ppc_dump_state(env, stderr, 0); | 565 | + case EXCP_EXTERNAL: |
| 566 | + /* Should not happen ! */ | ||
| 567 | + fprintf(stderr, "External interruption... Stop emulation\n"); | ||
| 568 | + if (loglevel) | ||
| 569 | + fprintf(logfile, "External interruption... Stop emulation\n"); | ||
| 481 | abort(); | 570 | abort(); |
| 482 | - break; | ||
| 483 | - /* Trap */ | ||
| 484 | - case EXCP_TRAP: /* Trap */ | ||
| 485 | - case EXCP_TRACE: /* Trace exception (optional) */ | ||
| 486 | - info.si_signo = SIGTRAP; | 571 | + case EXCP_ALIGN: |
| 572 | + fprintf(stderr, "Invalid unaligned memory access\n"); | ||
| 573 | + if (loglevel) | ||
| 574 | + fprintf(logfile, "Invalid unaligned memory access\n"); | ||
| 575 | + info.si_signo = TARGET_SIGBUS; | ||
| 487 | info.si_errno = 0; | 576 | info.si_errno = 0; |
| 488 | - info.si_code = TARGET_ILL_ILLOPN; | ||
| 489 | - info._sifields._sigfault._addr = env->nip; | 577 | + info.si_code = TARGET_BUS_ADRALN; |
| 578 | + info._sifields._sigfault._addr = env->nip - 4; | ||
| 490 | queue_signal(info.si_signo, &info); | 579 | queue_signal(info.si_signo, &info); |
| 491 | break; | 580 | break; |
| 492 | - /* Invalid instruction */ | 581 | + case EXCP_PROGRAM: |
| 582 | + switch (env->error_code & ~0xF) { | ||
| 583 | + case EXCP_FP: | ||
| 584 | + fprintf(stderr, "Program exception\n"); | ||
| 585 | + if (loglevel) | ||
| 586 | + fprintf(logfile, "Program exception\n"); | ||
| 587 | + /* Set FX */ | ||
| 588 | + env->fpscr[7] |= 0x8; | ||
| 589 | + /* Finally, update FEX */ | ||
| 590 | + if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) & | ||
| 591 | + ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3))) | ||
| 592 | + env->fpscr[7] |= 0x4; | ||
| 593 | + info.si_signo = TARGET_SIGFPE; | ||
| 594 | + info.si_errno = 0; | ||
| 595 | + switch (env->error_code & 0xF) { | ||
| 596 | + case EXCP_FP_OX: | ||
| 597 | + info.si_code = TARGET_FPE_FLTOVF; | ||
| 598 | + break; | ||
| 599 | + case EXCP_FP_UX: | ||
| 600 | + info.si_code = TARGET_FPE_FLTUND; | ||
| 601 | + break; | ||
| 602 | + case EXCP_FP_ZX: | ||
| 603 | + case EXCP_FP_VXZDZ: | ||
| 604 | + info.si_code = TARGET_FPE_FLTDIV; | ||
| 605 | + break; | ||
| 606 | + case EXCP_FP_XX: | ||
| 607 | + info.si_code = TARGET_FPE_FLTRES; | ||
| 608 | + break; | ||
| 609 | + case EXCP_FP_VXSOFT: | ||
| 610 | + info.si_code = TARGET_FPE_FLTINV; | ||
| 611 | + break; | ||
| 612 | + case EXCP_FP_VXNAN: | ||
| 613 | + case EXCP_FP_VXISI: | ||
| 614 | + case EXCP_FP_VXIDI: | ||
| 615 | + case EXCP_FP_VXIMZ: | ||
| 616 | + case EXCP_FP_VXVC: | ||
| 617 | + case EXCP_FP_VXSQRT: | ||
| 618 | + case EXCP_FP_VXCVI: | ||
| 619 | + info.si_code = TARGET_FPE_FLTSUB; | ||
| 620 | + break; | ||
| 621 | + default: | ||
| 622 | + fprintf(stderr, "Unknown floating point exception " | ||
| 623 | + "(%02x)\n", env->error_code); | ||
| 624 | + if (loglevel) { | ||
| 625 | + fprintf(logfile, "Unknown floating point exception " | ||
| 626 | + "(%02x)\n", env->error_code & 0xF); | ||
| 627 | + } | ||
| 628 | + } | ||
| 629 | + break; | ||
| 493 | case EXCP_INVAL: | 630 | case EXCP_INVAL: |
| 494 | - info.si_signo = SIGILL; | ||
| 495 | - info.si_errno = 0; | 631 | + fprintf(stderr, "Invalid instruction\n"); |
| 632 | + if (loglevel) | ||
| 633 | + fprintf(logfile, "Invalid instruction\n"); | ||
| 634 | + info.si_signo = TARGET_SIGILL; | ||
| 635 | + info.si_errno = 0; | ||
| 636 | + switch (env->error_code & 0xF) { | ||
| 637 | + case EXCP_INVAL_INVAL: | ||
| 638 | + info.si_code = TARGET_ILL_ILLOPC; | ||
| 639 | + break; | ||
| 640 | + case EXCP_INVAL_LSWX: | ||
| 496 | info.si_code = TARGET_ILL_ILLOPN; | 641 | info.si_code = TARGET_ILL_ILLOPN; |
| 497 | - info._sifields._sigfault._addr = env->nip; | 642 | + break; |
| 643 | + case EXCP_INVAL_SPR: | ||
| 644 | + info.si_code = TARGET_ILL_PRVREG; | ||
| 645 | + break; | ||
| 646 | + case EXCP_INVAL_FP: | ||
| 647 | + info.si_code = TARGET_ILL_COPROC; | ||
| 648 | + break; | ||
| 649 | + default: | ||
| 650 | + fprintf(stderr, "Unknown invalid operation (%02x)\n", | ||
| 651 | + env->error_code & 0xF); | ||
| 652 | + if (loglevel) { | ||
| 653 | + fprintf(logfile, "Unknown invalid operation (%02x)\n", | ||
| 654 | + env->error_code & 0xF); | ||
| 655 | + } | ||
| 656 | + info.si_code = TARGET_ILL_ILLADR; | ||
| 657 | + break; | ||
| 658 | + } | ||
| 659 | + break; | ||
| 660 | + case EXCP_PRIV: | ||
| 661 | + fprintf(stderr, "Privilege violation\n"); | ||
| 662 | + if (loglevel) | ||
| 663 | + fprintf(logfile, "Privilege violation\n"); | ||
| 664 | + info.si_signo = TARGET_SIGILL; | ||
| 665 | + info.si_errno = 0; | ||
| 666 | + switch (env->error_code & 0xF) { | ||
| 667 | + case EXCP_PRIV_OPC: | ||
| 668 | + info.si_code = TARGET_ILL_PRVOPC; | ||
| 669 | + break; | ||
| 670 | + case EXCP_PRIV_REG: | ||
| 671 | + info.si_code = TARGET_ILL_PRVREG; | ||
| 672 | + break; | ||
| 673 | + default: | ||
| 674 | + fprintf(stderr, "Unknown privilege violation (%02x)\n", | ||
| 675 | + env->error_code & 0xF); | ||
| 676 | + info.si_code = TARGET_ILL_PRVOPC; | ||
| 677 | + break; | ||
| 678 | + } | ||
| 679 | + break; | ||
| 680 | + case EXCP_TRAP: | ||
| 681 | + fprintf(stderr, "Tried to call a TRAP\n"); | ||
| 682 | + if (loglevel) | ||
| 683 | + fprintf(logfile, "Tried to call a TRAP\n"); | ||
| 684 | + abort(); | ||
| 685 | + default: | ||
| 686 | + /* Should not happen ! */ | ||
| 687 | + fprintf(stderr, "Unknown program exception (%02x)\n", | ||
| 688 | + env->error_code); | ||
| 689 | + if (loglevel) { | ||
| 690 | + fprintf(logfile, "Unknwon program exception (%02x)\n", | ||
| 691 | + env->error_code); | ||
| 692 | + } | ||
| 693 | + abort(); | ||
| 694 | + } | ||
| 695 | + info._sifields._sigfault._addr = env->nip - 4; | ||
| 498 | queue_signal(info.si_signo, &info); | 696 | queue_signal(info.si_signo, &info); |
| 499 | break; | 697 | break; |
| 500 | - /* Privileged instruction */ | ||
| 501 | - case EXCP_PRIV: /* Privileged instruction */ | ||
| 502 | - info.si_signo = SIGILL; | 698 | + case EXCP_NO_FP: |
| 699 | + fprintf(stderr, "No floating point allowed\n"); | ||
| 700 | + if (loglevel) | ||
| 701 | + fprintf(logfile, "No floating point allowed\n"); | ||
| 702 | + info.si_signo = TARGET_SIGILL; | ||
| 503 | info.si_errno = 0; | 703 | info.si_errno = 0; |
| 504 | - info.si_code = TARGET_ILL_ILLOPN; | ||
| 505 | - info._sifields._sigfault._addr = env->nip; | 704 | + info.si_code = TARGET_ILL_COPROC; |
| 705 | + info._sifields._sigfault._addr = env->nip - 4; | ||
| 506 | queue_signal(info.si_signo, &info); | 706 | queue_signal(info.si_signo, &info); |
| 507 | break; | 707 | break; |
| 508 | - case EXCP_NO_FP: /* No floating point */ | ||
| 509 | - case EXCP_DECR: /* Decrementer exception */ | 708 | + case EXCP_DECR: |
| 709 | + /* Should not happen ! */ | ||
| 710 | + fprintf(stderr, "Decrementer exception\n"); | ||
| 711 | + if (loglevel) | ||
| 712 | + fprintf(logfile, "Decrementer exception\n"); | ||
| 713 | + abort(); | ||
| 510 | case EXCP_RESA: /* Implementation specific */ | 714 | case EXCP_RESA: /* Implementation specific */ |
| 715 | + /* Should not happen ! */ | ||
| 716 | + fprintf(stderr, "RESA exception should never happen !\n"); | ||
| 717 | + if (loglevel) | ||
| 718 | + fprintf(logfile, "RESA exception should never happen !\n"); | ||
| 719 | + abort(); | ||
| 511 | case EXCP_RESB: /* Implementation specific */ | 720 | case EXCP_RESB: /* Implementation specific */ |
| 512 | - case EXCP_FP_ASSIST: /* Floating-point assist (optional) */ | ||
| 513 | - fprintf(stderr, "Misc expt...\n"); | ||
| 514 | - cpu_ppc_dump_state(env, stderr, 0); | 721 | + /* Should not happen ! */ |
| 722 | + fprintf(stderr, "RESB exception should never happen !\n"); | ||
| 723 | + if (loglevel) | ||
| 724 | + fprintf(logfile, "RESB exception should never happen !\n"); | ||
| 515 | abort(); | 725 | abort(); |
| 516 | - | ||
| 517 | - case EXCP_SYSCALL: | ||
| 518 | - { | ||
| 519 | - uint32_t ret; | ||
| 520 | - /* system call */ | ||
| 521 | - /* WARNING: | ||
| 522 | - * PPC ABI uses overflow flag in cr0 to signal an error | ||
| 523 | - * in syscalls. | ||
| 524 | - */ | ||
| 525 | - env->crf[0] &= ~0x1; | ||
| 526 | - ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], | ||
| 527 | - env->gpr[5], env->gpr[6], env->gpr[7], | ||
| 528 | - env->gpr[8]); | ||
| 529 | - if (ret > (uint32_t)(-515)) { | ||
| 530 | - env->crf[0] |= 0x1; | ||
| 531 | - ret = -ret; | ||
| 532 | - } | ||
| 533 | - env->gpr[3] = ret; | 726 | + case EXCP_TRACE: |
| 727 | + /* Do nothing: we use this to trace execution */ | ||
| 534 | break; | 728 | break; |
| 729 | + case EXCP_FP_ASSIST: | ||
| 730 | + /* Should not happen ! */ | ||
| 731 | + fprintf(stderr, "Floating point assist exception\n"); | ||
| 732 | + if (loglevel) | ||
| 733 | + fprintf(logfile, "Floating point assist exception\n"); | ||
| 734 | + abort(); | ||
| 735 | + case EXCP_MTMSR: | ||
| 736 | + /* We reloaded the msr, just go on */ | ||
| 737 | + if (msr_pr) { | ||
| 738 | + fprintf(stderr, "Tried to go into supervisor mode !\n"); | ||
| 739 | + if (loglevel) | ||
| 740 | + fprintf(logfile, "Tried to go into supervisor mode !\n"); | ||
| 741 | + abort(); | ||
| 535 | } | 742 | } |
| 743 | + break; | ||
| 744 | + case EXCP_BRANCH: | ||
| 745 | + /* We stopped because of a jump... */ | ||
| 746 | + break; | ||
| 747 | + case EXCP_RFI: | ||
| 748 | + /* Should not occur: we always are in user mode */ | ||
| 749 | + fprintf(stderr, "Return from interrupt ?\n"); | ||
| 750 | + if (loglevel) | ||
| 751 | + fprintf(logfile, "Return from interrupt ?\n"); | ||
| 752 | + abort(); | ||
| 753 | + case EXCP_INTERRUPT: | ||
| 754 | + /* Don't know why this should ever happen... */ | ||
| 755 | + break; | ||
| 536 | default: | 756 | default: |
| 537 | -// error: | ||
| 538 | fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", | 757 | fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", |
| 539 | trapnr); | 758 | trapnr); |
| 540 | - cpu_ppc_dump_state(env, stderr, 0); | 759 | + if (loglevel) { |
| 760 | + fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - " | ||
| 761 | + "0x%02x - aborting\n", trapnr, env->error_code); | ||
| 762 | + } | ||
| 541 | abort(); | 763 | abort(); |
| 542 | } | 764 | } |
| 765 | + if (trapnr < EXCP_PPC_MAX) | ||
| 766 | + env->exceptions &= ~(1 << trapnr); | ||
| 543 | process_pending_signals(env); | 767 | process_pending_signals(env); |
| 768 | + if (env->exceptions != 0) { | ||
| 769 | + check_exception_state(env); | ||
| 770 | + } | ||
| 544 | } | 771 | } |
| 545 | } | 772 | } |
| 546 | #endif | 773 | #endif |
| @@ -750,8 +977,10 @@ int main(int argc, char **argv) | @@ -750,8 +977,10 @@ int main(int argc, char **argv) | ||
| 750 | #elif defined(TARGET_PPC) | 977 | #elif defined(TARGET_PPC) |
| 751 | { | 978 | { |
| 752 | int i; | 979 | int i; |
| 753 | - for (i = 0; i < 32; i++) | ||
| 754 | - env->msr[i] = (regs->msr >> i) & 1; | 980 | + for (i = 0; i < 32; i++) { |
| 981 | + if (i != 12 && i != 6) | ||
| 982 | + env->msr[i] = (regs->msr >> i) & 1; | ||
| 983 | + } | ||
| 755 | env->nip = regs->nip; | 984 | env->nip = regs->nip; |
| 756 | for(i = 0; i < 32; i++) { | 985 | for(i = 0; i < 32; i++) { |
| 757 | env->gpr[i] = regs->gpr[i]; | 986 | env->gpr[i] = regs->gpr[i]; |