Commit 61190b14fc96d4e19c9bdde25643be4c5eb90e62

Authored by bellard
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];