Revision e1833e1f linux-user/main.c
b/linux-user/main.c | ||
---|---|---|
723 | 723 |
return -1; |
724 | 724 |
} |
725 | 725 |
|
726 |
#define EXCP_DUMP(env, fmt, args...) \ |
|
727 |
do { \ |
|
728 |
fprintf(stderr, fmt , ##args); \ |
|
729 |
cpu_dump_state(env, stderr, fprintf, 0); \ |
|
730 |
if (loglevel != 0) { \ |
|
731 |
fprintf(logfile, fmt , ##args); \ |
|
732 |
cpu_dump_state(env, logfile, fprintf, 0); \ |
|
733 |
} \ |
|
734 |
} while (0) |
|
735 |
|
|
726 | 736 |
void cpu_loop(CPUPPCState *env) |
727 | 737 |
{ |
728 | 738 |
target_siginfo_t info; |
... | ... | |
731 | 741 |
|
732 | 742 |
for(;;) { |
733 | 743 |
trapnr = cpu_ppc_exec(env); |
734 |
if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH && |
|
735 |
trapnr != EXCP_TRACE) { |
|
736 |
if (loglevel > 0) { |
|
737 |
cpu_dump_state(env, logfile, fprintf, 0); |
|
738 |
} |
|
739 |
} |
|
740 | 744 |
switch(trapnr) { |
741 |
case EXCP_NONE: |
|
745 |
case POWERPC_EXCP_NONE: |
|
746 |
/* Just go on */ |
|
742 | 747 |
break; |
743 |
case EXCP_SYSCALL_USER: |
|
744 |
/* system call */ |
|
745 |
/* WARNING: |
|
746 |
* PPC ABI uses overflow flag in cr0 to signal an error |
|
747 |
* in syscalls. |
|
748 |
*/ |
|
749 |
#if 0 |
|
750 |
printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0], |
|
751 |
env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]); |
|
752 |
#endif |
|
753 |
env->crf[0] &= ~0x1; |
|
754 |
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], |
|
755 |
env->gpr[5], env->gpr[6], env->gpr[7], |
|
756 |
env->gpr[8]); |
|
757 |
if (ret > (uint32_t)(-515)) { |
|
758 |
env->crf[0] |= 0x1; |
|
759 |
ret = -ret; |
|
760 |
} |
|
761 |
env->gpr[3] = ret; |
|
762 |
#if 0 |
|
763 |
printf("syscall returned 0x%08x (%d)\n", ret, ret); |
|
764 |
#endif |
|
748 |
case POWERPC_EXCP_CRITICAL: /* Critical input */ |
|
749 |
cpu_abort(env, "Critical interrupt while in user mode. " |
|
750 |
"Aborting\n"); |
|
765 | 751 |
break; |
766 |
case EXCP_RESET: |
|
767 |
/* Should not happen ! */ |
|
768 |
fprintf(stderr, "RESET asked... Stop emulation\n"); |
|
769 |
if (loglevel) |
|
770 |
fprintf(logfile, "RESET asked... Stop emulation\n"); |
|
771 |
abort(); |
|
772 |
case EXCP_MACHINE_CHECK: |
|
773 |
fprintf(stderr, "Machine check exeption... Stop emulation\n"); |
|
774 |
if (loglevel) |
|
775 |
fprintf(logfile, "Machine check exception. Stop emulation\n"); |
|
776 |
info.si_signo = TARGET_SIGBUS; |
|
777 |
info.si_errno = 0; |
|
778 |
info.si_code = TARGET_BUS_OBJERR; |
|
779 |
info._sifields._sigfault._addr = env->nip - 4; |
|
780 |
queue_signal(info.si_signo, &info); |
|
781 |
case EXCP_DSI: |
|
782 |
fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n", |
|
783 |
env->spr[SPR_DAR]); |
|
784 |
if (loglevel) { |
|
785 |
fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n", |
|
786 |
env->spr[SPR_DAR]); |
|
787 |
} |
|
752 |
case POWERPC_EXCP_MCHECK: /* Machine check exception */ |
|
753 |
cpu_abort(env, "Machine check exception while in user mode. " |
|
754 |
"Aborting\n"); |
|
755 |
break; |
|
756 |
case POWERPC_EXCP_DSI: /* Data storage exception */ |
|
757 |
EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n", |
|
758 |
env->spr[SPR_DAR]); |
|
759 |
/* XXX: check this. Seems bugged */ |
|
788 | 760 |
switch (env->error_code & 0xFF000000) { |
789 | 761 |
case 0x40000000: |
790 | 762 |
info.si_signo = TARGET_SIGSEGV; |
... | ... | |
803 | 775 |
break; |
804 | 776 |
default: |
805 | 777 |
/* Let's send a regular segfault... */ |
806 |
fprintf(stderr, "Invalid segfault errno (%02x)\n", |
|
807 |
env->error_code); |
|
808 |
if (loglevel) { |
|
809 |
fprintf(logfile, "Invalid segfault errno (%02x)\n", |
|
810 |
env->error_code); |
|
811 |
} |
|
778 |
EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", |
|
779 |
env->error_code); |
|
812 | 780 |
info.si_signo = TARGET_SIGSEGV; |
813 | 781 |
info.si_errno = 0; |
814 | 782 |
info.si_code = TARGET_SEGV_MAPERR; |
... | ... | |
817 | 785 |
info._sifields._sigfault._addr = env->nip; |
818 | 786 |
queue_signal(info.si_signo, &info); |
819 | 787 |
break; |
820 |
case EXCP_ISI:
|
|
821 |
fprintf(stderr, "Invalid instruction fetch\n");
|
|
822 |
if (loglevel)
|
|
823 |
fprintf(logfile, "Invalid instruction fetch\n");
|
|
788 |
case POWERPC_EXCP_ISI: /* Instruction storage exception */
|
|
789 |
EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
|
|
790 |
env->spr[SPR_DAR]);
|
|
791 |
/* XXX: check this */
|
|
824 | 792 |
switch (env->error_code & 0xFF000000) { |
825 | 793 |
case 0x40000000: |
826 | 794 |
info.si_signo = TARGET_SIGSEGV; |
... | ... | |
835 | 803 |
break; |
836 | 804 |
default: |
837 | 805 |
/* Let's send a regular segfault... */ |
838 |
fprintf(stderr, "Invalid segfault errno (%02x)\n", |
|
839 |
env->error_code); |
|
840 |
if (loglevel) { |
|
841 |
fprintf(logfile, "Invalid segfault errno (%02x)\n", |
|
842 |
env->error_code); |
|
843 |
} |
|
806 |
EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", |
|
807 |
env->error_code); |
|
844 | 808 |
info.si_signo = TARGET_SIGSEGV; |
845 | 809 |
info.si_errno = 0; |
846 | 810 |
info.si_code = TARGET_SEGV_MAPERR; |
... | ... | |
849 | 813 |
info._sifields._sigfault._addr = env->nip - 4; |
850 | 814 |
queue_signal(info.si_signo, &info); |
851 | 815 |
break; |
852 |
case EXCP_EXTERNAL: |
|
853 |
/* Should not happen ! */ |
|
854 |
fprintf(stderr, "External interruption... Stop emulation\n"); |
|
855 |
if (loglevel) |
|
856 |
fprintf(logfile, "External interruption... Stop emulation\n"); |
|
857 |
abort(); |
|
858 |
case EXCP_ALIGN: |
|
859 |
fprintf(stderr, "Invalid unaligned memory access\n"); |
|
860 |
if (loglevel) |
|
861 |
fprintf(logfile, "Invalid unaligned memory access\n"); |
|
816 |
case POWERPC_EXCP_EXTERNAL: /* External input */ |
|
817 |
cpu_abort(env, "External interrupt while in user mode. " |
|
818 |
"Aborting\n"); |
|
819 |
break; |
|
820 |
case POWERPC_EXCP_ALIGN: /* Alignment exception */ |
|
821 |
EXCP_DUMP(env, "Unaligned memory access\n"); |
|
822 |
/* XXX: check this */ |
|
862 | 823 |
info.si_signo = TARGET_SIGBUS; |
863 | 824 |
info.si_errno = 0; |
864 | 825 |
info.si_code = TARGET_BUS_ADRALN; |
865 | 826 |
info._sifields._sigfault._addr = env->nip - 4; |
866 | 827 |
queue_signal(info.si_signo, &info); |
867 | 828 |
break; |
868 |
case EXCP_PROGRAM: |
|
829 |
case POWERPC_EXCP_PROGRAM: /* Program exception */ |
|
830 |
/* XXX: check this */ |
|
869 | 831 |
switch (env->error_code & ~0xF) { |
870 |
case EXCP_FP: |
|
871 |
fprintf(stderr, "Program exception\n"); |
|
872 |
if (loglevel) |
|
873 |
fprintf(logfile, "Program exception\n"); |
|
832 |
case POWERPC_EXCP_FP: |
|
833 |
EXCP_DUMP(env, "Floating point program exception\n"); |
|
874 | 834 |
/* Set FX */ |
875 | 835 |
env->fpscr[7] |= 0x8; |
876 | 836 |
/* Finally, update FEX */ |
... | ... | |
880 | 840 |
info.si_signo = TARGET_SIGFPE; |
881 | 841 |
info.si_errno = 0; |
882 | 842 |
switch (env->error_code & 0xF) { |
883 |
case EXCP_FP_OX: |
|
843 |
case POWERPC_EXCP_FP_OX:
|
|
884 | 844 |
info.si_code = TARGET_FPE_FLTOVF; |
885 | 845 |
break; |
886 |
case EXCP_FP_UX: |
|
846 |
case POWERPC_EXCP_FP_UX:
|
|
887 | 847 |
info.si_code = TARGET_FPE_FLTUND; |
888 | 848 |
break; |
889 |
case EXCP_FP_ZX: |
|
890 |
case EXCP_FP_VXZDZ: |
|
849 |
case POWERPC_EXCP_FP_ZX:
|
|
850 |
case POWERPC_EXCP_FP_VXZDZ:
|
|
891 | 851 |
info.si_code = TARGET_FPE_FLTDIV; |
892 | 852 |
break; |
893 |
case EXCP_FP_XX: |
|
853 |
case POWERPC_EXCP_FP_XX:
|
|
894 | 854 |
info.si_code = TARGET_FPE_FLTRES; |
895 | 855 |
break; |
896 |
case EXCP_FP_VXSOFT: |
|
856 |
case POWERPC_EXCP_FP_VXSOFT:
|
|
897 | 857 |
info.si_code = TARGET_FPE_FLTINV; |
898 | 858 |
break; |
899 |
case EXCP_FP_VXNAN: |
|
900 |
case EXCP_FP_VXISI: |
|
901 |
case EXCP_FP_VXIDI: |
|
902 |
case EXCP_FP_VXIMZ: |
|
903 |
case EXCP_FP_VXVC: |
|
904 |
case EXCP_FP_VXSQRT: |
|
905 |
case EXCP_FP_VXCVI: |
|
859 |
case POWERPC_EXCP_FP_VXNAN:
|
|
860 |
case POWERPC_EXCP_FP_VXISI:
|
|
861 |
case POWERPC_EXCP_FP_VXIDI:
|
|
862 |
case POWERPC_EXCP_FP_VXIMZ:
|
|
863 |
case POWERPC_EXCP_FP_VXVC:
|
|
864 |
case POWERPC_EXCP_FP_VXSQRT:
|
|
865 |
case POWERPC_EXCP_FP_VXCVI:
|
|
906 | 866 |
info.si_code = TARGET_FPE_FLTSUB; |
907 | 867 |
break; |
908 | 868 |
default: |
909 |
fprintf(stderr, "Unknown floating point exception " |
|
910 |
"(%02x)\n", env->error_code); |
|
911 |
if (loglevel) { |
|
912 |
fprintf(logfile, "Unknown floating point exception " |
|
913 |
"(%02x)\n", env->error_code & 0xF); |
|
914 |
} |
|
869 |
EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", |
|
870 |
env->error_code); |
|
871 |
break; |
|
915 | 872 |
} |
916 |
break; |
|
917 |
case EXCP_INVAL: |
|
918 |
fprintf(stderr, "Invalid instruction\n"); |
|
919 |
if (loglevel) |
|
920 |
fprintf(logfile, "Invalid instruction\n"); |
|
873 |
break; |
|
874 |
case POWERPC_EXCP_INVAL: |
|
875 |
EXCP_DUMP(env, "Invalid instruction\n"); |
|
921 | 876 |
info.si_signo = TARGET_SIGILL; |
922 | 877 |
info.si_errno = 0; |
923 | 878 |
switch (env->error_code & 0xF) { |
924 |
case EXCP_INVAL_INVAL: |
|
879 |
case POWERPC_EXCP_INVAL_INVAL:
|
|
925 | 880 |
info.si_code = TARGET_ILL_ILLOPC; |
926 | 881 |
break; |
927 |
case EXCP_INVAL_LSWX: |
|
882 |
case POWERPC_EXCP_INVAL_LSWX:
|
|
928 | 883 |
info.si_code = TARGET_ILL_ILLOPN; |
929 | 884 |
break; |
930 |
case EXCP_INVAL_SPR: |
|
885 |
case POWERPC_EXCP_INVAL_SPR:
|
|
931 | 886 |
info.si_code = TARGET_ILL_PRVREG; |
932 | 887 |
break; |
933 |
case EXCP_INVAL_FP: |
|
888 |
case POWERPC_EXCP_INVAL_FP:
|
|
934 | 889 |
info.si_code = TARGET_ILL_COPROC; |
935 | 890 |
break; |
936 | 891 |
default: |
937 |
fprintf(stderr, "Unknown invalid operation (%02x)\n", |
|
938 |
env->error_code & 0xF); |
|
939 |
if (loglevel) { |
|
940 |
fprintf(logfile, "Unknown invalid operation (%02x)\n", |
|
941 |
env->error_code & 0xF); |
|
942 |
} |
|
892 |
EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", |
|
893 |
env->error_code & 0xF); |
|
943 | 894 |
info.si_code = TARGET_ILL_ILLADR; |
944 | 895 |
break; |
945 | 896 |
} |
946 | 897 |
break; |
947 |
case EXCP_PRIV: |
|
948 |
fprintf(stderr, "Privilege violation\n"); |
|
949 |
if (loglevel) |
|
950 |
fprintf(logfile, "Privilege violation\n"); |
|
898 |
case POWERPC_EXCP_PRIV: |
|
899 |
EXCP_DUMP(env, "Privilege violation\n"); |
|
951 | 900 |
info.si_signo = TARGET_SIGILL; |
952 | 901 |
info.si_errno = 0; |
953 | 902 |
switch (env->error_code & 0xF) { |
954 |
case EXCP_PRIV_OPC: |
|
903 |
case POWERPC_EXCP_PRIV_OPC:
|
|
955 | 904 |
info.si_code = TARGET_ILL_PRVOPC; |
956 | 905 |
break; |
957 |
case EXCP_PRIV_REG: |
|
906 |
case POWERPC_EXCP_PRIV_REG:
|
|
958 | 907 |
info.si_code = TARGET_ILL_PRVREG; |
959 |
break; |
|
908 |
break;
|
|
960 | 909 |
default: |
961 |
fprintf(stderr, "Unknown privilege violation (%02x)\n",
|
|
962 |
env->error_code & 0xF); |
|
910 |
EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
|
|
911 |
env->error_code & 0xF);
|
|
963 | 912 |
info.si_code = TARGET_ILL_PRVOPC; |
964 | 913 |
break; |
965 | 914 |
} |
966 | 915 |
break; |
967 |
case EXCP_TRAP: |
|
968 |
fprintf(stderr, "Tried to call a TRAP\n"); |
|
969 |
if (loglevel) |
|
970 |
fprintf(logfile, "Tried to call a TRAP\n"); |
|
971 |
abort(); |
|
916 |
case POWERPC_EXCP_TRAP: |
|
917 |
cpu_abort(env, "Tried to call a TRAP\n"); |
|
918 |
break; |
|
972 | 919 |
default: |
973 | 920 |
/* Should not happen ! */ |
974 |
fprintf(stderr, "Unknown program exception (%02x)\n", |
|
975 |
env->error_code); |
|
976 |
if (loglevel) { |
|
977 |
fprintf(logfile, "Unknwon program exception (%02x)\n", |
|
978 |
env->error_code); |
|
979 |
} |
|
980 |
abort(); |
|
921 |
cpu_abort(env, "Unknown program exception (%02x)\n", |
|
922 |
env->error_code); |
|
923 |
break; |
|
981 | 924 |
} |
982 | 925 |
info._sifields._sigfault._addr = env->nip - 4; |
983 | 926 |
queue_signal(info.si_signo, &info); |
984 | 927 |
break; |
985 |
case EXCP_NO_FP: |
|
986 |
fprintf(stderr, "No floating point allowed\n"); |
|
987 |
if (loglevel) |
|
988 |
fprintf(logfile, "No floating point allowed\n"); |
|
928 |
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ |
|
929 |
EXCP_DUMP(env, "No floating point allowed\n"); |
|
989 | 930 |
info.si_signo = TARGET_SIGILL; |
990 | 931 |
info.si_errno = 0; |
991 | 932 |
info.si_code = TARGET_ILL_COPROC; |
992 | 933 |
info._sifields._sigfault._addr = env->nip - 4; |
993 | 934 |
queue_signal(info.si_signo, &info); |
994 | 935 |
break; |
995 |
case EXCP_DECR: |
|
996 |
/* Should not happen ! */ |
|
997 |
fprintf(stderr, "Decrementer exception\n"); |
|
998 |
if (loglevel) |
|
999 |
fprintf(logfile, "Decrementer exception\n"); |
|
1000 |
abort(); |
|
1001 |
case EXCP_TRACE: |
|
1002 |
/* Do nothing: we use this to trace execution */ |
|
1003 |
break; |
|
1004 |
case EXCP_FP_ASSIST: |
|
1005 |
/* Should not happen ! */ |
|
1006 |
fprintf(stderr, "Floating point assist exception\n"); |
|
1007 |
if (loglevel) |
|
1008 |
fprintf(logfile, "Floating point assist exception\n"); |
|
1009 |
abort(); |
|
1010 |
case EXCP_MTMSR: |
|
1011 |
/* We reloaded the msr, just go on */ |
|
1012 |
if (msr_pr == 0) { |
|
1013 |
fprintf(stderr, "Tried to go into supervisor mode !\n"); |
|
1014 |
if (loglevel) |
|
1015 |
fprintf(logfile, "Tried to go into supervisor mode !\n"); |
|
1016 |
abort(); |
|
1017 |
} |
|
936 |
case POWERPC_EXCP_SYSCALL: /* System call exception */ |
|
937 |
cpu_abort(env, "Syscall exception while in user mode. " |
|
938 |
"Aborting\n"); |
|
1018 | 939 |
break; |
1019 |
case EXCP_BRANCH: |
|
1020 |
/* We stopped because of a jump... */ |
|
940 |
case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ |
|
941 |
EXCP_DUMP(env, "No APU instruction allowed\n"); |
|
942 |
info.si_signo = TARGET_SIGILL; |
|
943 |
info.si_errno = 0; |
|
944 |
info.si_code = TARGET_ILL_COPROC; |
|
945 |
info._sifields._sigfault._addr = env->nip - 4; |
|
946 |
queue_signal(info.si_signo, &info); |
|
1021 | 947 |
break; |
1022 |
case EXCP_INTERRUPT: |
|
1023 |
/* Don't know why this should ever happen... */ |
|
948 |
case POWERPC_EXCP_DECR: /* Decrementer exception */ |
|
949 |
cpu_abort(env, "Decrementer interrupt while in user mode. " |
|
950 |
"Aborting\n"); |
|
1024 | 951 |
break; |
1025 |
case EXCP_DEBUG: |
|
952 |
case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ |
|
953 |
cpu_abort(env, "Fix interval timer interrupt while in user mode. " |
|
954 |
"Aborting\n"); |
|
955 |
break; |
|
956 |
case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ |
|
957 |
cpu_abort(env, "Watchdog timer interrupt while in user mode. " |
|
958 |
"Aborting\n"); |
|
959 |
break; |
|
960 |
case POWERPC_EXCP_DTLB: /* Data TLB error */ |
|
961 |
cpu_abort(env, "Data TLB exception while in user mode. " |
|
962 |
"Aborting\n"); |
|
963 |
break; |
|
964 |
case POWERPC_EXCP_ITLB: /* Instruction TLB error */ |
|
965 |
cpu_abort(env, "Instruction TLB exception while in user mode. " |
|
966 |
"Aborting\n"); |
|
967 |
break; |
|
968 |
case POWERPC_EXCP_DEBUG: /* Debug interrupt */ |
|
969 |
/* XXX: check this */ |
|
1026 | 970 |
{ |
1027 | 971 |
int sig; |
1028 | 972 |
|
1029 |
sig = gdb_handlesig (env, TARGET_SIGTRAP); |
|
1030 |
if (sig) |
|
1031 |
{ |
|
973 |
sig = gdb_handlesig(env, TARGET_SIGTRAP); |
|
974 |
if (sig) { |
|
1032 | 975 |
info.si_signo = sig; |
1033 | 976 |
info.si_errno = 0; |
1034 | 977 |
info.si_code = TARGET_TRAP_BRKPT; |
... | ... | |
1036 | 979 |
} |
1037 | 980 |
} |
1038 | 981 |
break; |
1039 |
default: |
|
1040 |
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", |
|
1041 |
trapnr); |
|
1042 |
if (loglevel) { |
|
1043 |
fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - " |
|
1044 |
"0x%02x - aborting\n", trapnr, env->error_code); |
|
982 |
#if defined(TARGET_PPCEMB) |
|
983 |
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ |
|
984 |
EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); |
|
985 |
info.si_signo = TARGET_SIGILL; |
|
986 |
info.si_errno = 0; |
|
987 |
info.si_code = TARGET_ILL_COPROC; |
|
988 |
info._sifields._sigfault._addr = env->nip - 4; |
|
989 |
queue_signal(info.si_signo, &info); |
|
990 |
break; |
|
991 |
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ |
|
992 |
cpu_abort(env, "Embedded floating-point data IRQ not handled\n"); |
|
993 |
break; |
|
994 |
case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ |
|
995 |
cpu_abort(env, "Embedded floating-point round IRQ not handled\n"); |
|
996 |
break; |
|
997 |
case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ |
|
998 |
cpu_abort(env, "Performance monitor exception not handled\n"); |
|
999 |
break; |
|
1000 |
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ |
|
1001 |
cpu_abort(env, "Doorbell interrupt while in user mode. " |
|
1002 |
"Aborting\n"); |
|
1003 |
break; |
|
1004 |
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ |
|
1005 |
cpu_abort(env, "Doorbell critical interrupt while in user mode. " |
|
1006 |
"Aborting\n"); |
|
1007 |
break; |
|
1008 |
case POWERPC_EXCP_RESET: /* System reset exception */ |
|
1009 |
cpu_abort(env, "Reset interrupt while in user mode. " |
|
1010 |
"Aborting\n"); |
|
1011 |
break; |
|
1012 |
#endif /* defined(TARGET_PPCEMB) */ |
|
1013 |
#if defined(TARGET_PPC64) /* PowerPC 64 */ |
|
1014 |
case POWERPC_EXCP_DSEG: /* Data segment exception */ |
|
1015 |
cpu_abort(env, "Data segment exception while in user mode. " |
|
1016 |
"Aborting\n"); |
|
1017 |
break; |
|
1018 |
case POWERPC_EXCP_ISEG: /* Instruction segment exception */ |
|
1019 |
cpu_abort(env, "Instruction segment exception " |
|
1020 |
"while in user mode. Aborting\n"); |
|
1021 |
break; |
|
1022 |
#endif /* defined(TARGET_PPC64) */ |
|
1023 |
#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */ |
|
1024 |
case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ |
|
1025 |
cpu_abort(env, "Hypervisor decrementer interrupt " |
|
1026 |
"while in user mode. Aborting\n"); |
|
1027 |
break; |
|
1028 |
#endif /* defined(TARGET_PPC64H) */ |
|
1029 |
case POWERPC_EXCP_TRACE: /* Trace exception */ |
|
1030 |
/* Nothing to do: |
|
1031 |
* we use this exception to emulate step-by-step execution mode. |
|
1032 |
*/ |
|
1033 |
break; |
|
1034 |
#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */ |
|
1035 |
case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ |
|
1036 |
cpu_abort(env, "Hypervisor data storage exception " |
|
1037 |
"while in user mode. Aborting\n"); |
|
1038 |
break; |
|
1039 |
case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ |
|
1040 |
cpu_abort(env, "Hypervisor instruction storage exception " |
|
1041 |
"while in user mode. Aborting\n"); |
|
1042 |
break; |
|
1043 |
case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ |
|
1044 |
cpu_abort(env, "Hypervisor data segment exception " |
|
1045 |
"while in user mode. Aborting\n"); |
|
1046 |
break; |
|
1047 |
case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ |
|
1048 |
cpu_abort(env, "Hypervisor instruction segment exception " |
|
1049 |
"while in user mode. Aborting\n"); |
|
1050 |
break; |
|
1051 |
#endif /* defined(TARGET_PPC64H) */ |
|
1052 |
case POWERPC_EXCP_VPU: /* Vector unavailable exception */ |
|
1053 |
EXCP_DUMP(env, "No Altivec instructions allowed\n"); |
|
1054 |
info.si_signo = TARGET_SIGILL; |
|
1055 |
info.si_errno = 0; |
|
1056 |
info.si_code = TARGET_ILL_COPROC; |
|
1057 |
info._sifields._sigfault._addr = env->nip - 4; |
|
1058 |
queue_signal(info.si_signo, &info); |
|
1059 |
break; |
|
1060 |
case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ |
|
1061 |
cpu_abort(env, "Programable interval timer interrupt " |
|
1062 |
"while in user mode. Aborting\n"); |
|
1063 |
break; |
|
1064 |
case POWERPC_EXCP_IO: /* IO error exception */ |
|
1065 |
cpu_abort(env, "IO error exception while in user mode. " |
|
1066 |
"Aborting\n"); |
|
1067 |
break; |
|
1068 |
case POWERPC_EXCP_RUNM: /* Run mode exception */ |
|
1069 |
cpu_abort(env, "Run mode exception while in user mode. " |
|
1070 |
"Aborting\n"); |
|
1071 |
break; |
|
1072 |
case POWERPC_EXCP_EMUL: /* Emulation trap exception */ |
|
1073 |
cpu_abort(env, "Emulation trap exception not handled\n"); |
|
1074 |
break; |
|
1075 |
case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ |
|
1076 |
cpu_abort(env, "Instruction fetch TLB exception " |
|
1077 |
"while in user-mode. Aborting"); |
|
1078 |
break; |
|
1079 |
case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ |
|
1080 |
cpu_abort(env, "Data load TLB exception while in user-mode. " |
|
1081 |
"Aborting"); |
|
1082 |
break; |
|
1083 |
case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ |
|
1084 |
cpu_abort(env, "Data store TLB exception while in user-mode. " |
|
1085 |
"Aborting"); |
|
1086 |
break; |
|
1087 |
case POWERPC_EXCP_FPA: /* Floating-point assist exception */ |
|
1088 |
cpu_abort(env, "Floating-point assist exception not handled\n"); |
|
1089 |
break; |
|
1090 |
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ |
|
1091 |
cpu_abort(env, "Instruction address breakpoint exception " |
|
1092 |
"not handled\n"); |
|
1093 |
break; |
|
1094 |
case POWERPC_EXCP_SMI: /* System management interrupt */ |
|
1095 |
cpu_abort(env, "System management interrupt while in user mode. " |
|
1096 |
"Aborting\n"); |
|
1097 |
break; |
|
1098 |
case POWERPC_EXCP_THERM: /* Thermal interrupt */ |
|
1099 |
cpu_abort(env, "Thermal interrupt interrupt while in user mode. " |
|
1100 |
"Aborting\n"); |
|
1101 |
break; |
|
1102 |
case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ |
|
1103 |
cpu_abort(env, "Performance monitor exception not handled\n"); |
|
1104 |
break; |
|
1105 |
case POWERPC_EXCP_VPUA: /* Vector assist exception */ |
|
1106 |
cpu_abort(env, "Vector assist exception not handled\n"); |
|
1107 |
break; |
|
1108 |
case POWERPC_EXCP_SOFTP: /* Soft patch exception */ |
|
1109 |
cpu_abort(env, "Soft patch exception not handled\n"); |
|
1110 |
break; |
|
1111 |
case POWERPC_EXCP_MAINT: /* Maintenance exception */ |
|
1112 |
cpu_abort(env, "Maintenance exception while in user mode. " |
|
1113 |
"Aborting\n"); |
|
1114 |
break; |
|
1115 |
case POWERPC_EXCP_STOP: /* stop translation */ |
|
1116 |
/* We did invalidate the instruction cache. Go on */ |
|
1117 |
break; |
|
1118 |
case POWERPC_EXCP_BRANCH: /* branch instruction: */ |
|
1119 |
/* We just stopped because of a branch. Go on */ |
|
1120 |
break; |
|
1121 |
case POWERPC_EXCP_SYSCALL_USER: |
|
1122 |
/* system call in user-mode emulation */ |
|
1123 |
/* WARNING: |
|
1124 |
* PPC ABI uses overflow flag in cr0 to signal an error |
|
1125 |
* in syscalls. |
|
1126 |
*/ |
|
1127 |
#if 0 |
|
1128 |
printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0], |
|
1129 |
env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]); |
|
1130 |
#endif |
|
1131 |
env->crf[0] &= ~0x1; |
|
1132 |
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], |
|
1133 |
env->gpr[5], env->gpr[6], env->gpr[7], |
|
1134 |
env->gpr[8]); |
|
1135 |
if (ret > (uint32_t)(-515)) { |
|
1136 |
env->crf[0] |= 0x1; |
|
1137 |
ret = -ret; |
|
1045 | 1138 |
} |
1046 |
abort(); |
|
1139 |
env->gpr[3] = ret; |
|
1140 |
#if 0 |
|
1141 |
printf("syscall returned 0x%08x (%d)\n", ret, ret); |
|
1142 |
#endif |
|
1143 |
break; |
|
1144 |
default: |
|
1145 |
cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr); |
|
1146 |
break; |
|
1047 | 1147 |
} |
1048 | 1148 |
process_pending_signals(env); |
1049 | 1149 |
} |
Also available in: Unified diff