📄 helper.c
字号:
fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n", (unsigned long)env->nip, excp, env->error_code); } msr_pow = 0; /* Generate informations in save/restore registers */ switch (excp) { /* Generic PowerPC exceptions */ case EXCP_RESET: /* 0x0100 */ if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) { if (msr_ip) excp += 0xFFC00; excp |= 0xFFC00000; } else { srr_0 = &env->spr[SPR_40x_SRR2]; srr_1 = &env->spr[SPR_40x_SRR3]; } goto store_next; case EXCP_MACHINE_CHECK: /* 0x0200 */ if (msr_me == 0) { cpu_abort(env, "Machine check exception while not allowed\n"); } if (PPC_EXCP(env) == PPC_FLAGS_EXCP_40x) { srr_0 = &env->spr[SPR_40x_SRR2]; srr_1 = &env->spr[SPR_40x_SRR3]; } msr_me = 0; break; case EXCP_DSI: /* 0x0300 */ /* Store exception cause */ /* data location address has been stored * when the fault has been detected */ msr &= ~0xFFFF0000;#if defined (DEBUG_EXCEPTIONS) if (loglevel) { fprintf(logfile, "DSI exception: DSISR=0x%08x, DAR=0x%08x\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); } else { printf("DSI exception: DSISR=0x%08x, DAR=0x%08x\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); }#endif goto store_next; case EXCP_ISI: /* 0x0400 */ /* Store exception cause */ msr &= ~0xFFFF0000; msr |= env->error_code;#if defined (DEBUG_EXCEPTIONS) if (loglevel != 0) { fprintf(logfile, "ISI exception: msr=0x%08x, nip=0x%08x\n", msr, env->nip); }#endif goto store_next; case EXCP_EXTERNAL: /* 0x0500 */ if (msr_ee == 0) {#if defined (DEBUG_EXCEPTIONS) if (loglevel > 0) { fprintf(logfile, "Skipping hardware interrupt\n"); }#endif /* Requeue it */ env->interrupt_request |= CPU_INTERRUPT_HARD; return; } goto store_next; case EXCP_ALIGN: /* 0x0600 */ if (PPC_EXCP(env) != PPC_FLAGS_EXCP_601) { /* Store exception cause */ /* Get rS/rD and rA from faulting opcode */ env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16; /* data location address has been stored * when the fault has been detected */ } else { /* IO error exception on PowerPC 601 */ /* XXX: TODO */ cpu_abort(env, "601 IO error exception is not implemented yet !\n"); } goto store_current; case EXCP_PROGRAM: /* 0x0700 */ msr &= ~0xFFFF0000; switch (env->error_code & ~0xF) { case EXCP_FP: if (msr_fe0 == 0 && msr_fe1 == 0) {#if defined (DEBUG_EXCEPTIONS) printf("Ignore floating point exception\n");#endif return; } msr |= 0x00100000; /* Set FX */ env->fpscr[7] |= 0x8; /* Finally, update FEX */ if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) & ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3))) env->fpscr[7] |= 0x4; break; case EXCP_INVAL: // printf("Invalid instruction at 0x%08x\n", env->nip); msr |= 0x00080000; break; case EXCP_PRIV: msr |= 0x00040000; break; case EXCP_TRAP: msr |= 0x00020000; break; default: /* Should never occur */ break; } msr |= 0x00010000; goto store_current; case EXCP_NO_FP: /* 0x0800 */ msr &= ~0xFFFF0000; goto store_current; case EXCP_DECR: if (msr_ee == 0) {#if 1 /* Requeue it */ env->interrupt_request |= CPU_INTERRUPT_TIMER;#endif return; } goto store_next; case EXCP_SYSCALL: /* 0x0C00 */ /* NOTE: this is a temporary hack to support graphics OSI calls from the MOL driver */ if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && env->osi_call) { if (env->osi_call(env) != 0) return; } if (loglevel & CPU_LOG_INT) { dump_syscall(env); } goto store_next; case EXCP_TRACE: /* 0x0D00 */ /* XXX: TODO */ cpu_abort(env, "Trace exception is not implemented yet !\n"); goto store_next; case EXCP_PERF: /* 0x0F00 */ /* XXX: TODO */ cpu_abort(env, "Performance counter exception is not implemented yet !\n"); goto store_next; /* 32 bits PowerPC specific exceptions */ case EXCP_FP_ASSIST: /* 0x0E00 */ /* XXX: TODO */ cpu_abort(env, "Floating point assist exception " "is not implemented yet !\n"); goto store_next; /* 64 bits PowerPC exceptions */ case EXCP_DSEG: /* 0x0380 */ /* XXX: TODO */ cpu_abort(env, "Data segment exception is not implemented yet !\n"); goto store_next; case EXCP_ISEG: /* 0x0480 */ /* XXX: TODO */ cpu_abort(env, "Instruction segment exception is not implemented yet !\n"); goto store_next; case EXCP_HDECR: /* 0x0980 */ if (msr_ee == 0) {#if 1 /* Requeue it */ env->interrupt_request |= CPU_INTERRUPT_TIMER;#endif return; } cpu_abort(env, "Hypervisor decrementer exception is not implemented yet !\n"); goto store_next; /* Implementation specific exceptions */ case 0x0A00: if (PPC_EXCP(env) != PPC_FLAGS_EXCP_602) { /* Critical interrupt on G2 */ /* XXX: TODO */ cpu_abort(env, "G2 critical interrupt is not implemented yet !\n"); goto store_next; } else { cpu_abort(env, "Invalid exception 0x0A00 !\n"); } return; case 0x0F20: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* APU unavailable on 405 */ /* XXX: TODO */ cpu_abort(env, "APU unavailable exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_74xx: /* Altivec unavailable */ /* XXX: TODO */ cpu_abort(env, "Altivec unavailable exception " "is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x0F20 !\n"); break; } return; case 0x1000: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* PIT on 4xx */ /* XXX: TODO */ cpu_abort(env, "40x PIT exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_602: case PPC_FLAGS_EXCP_603: /* ITLBMISS on 602/603 */ msr &= ~0xF00F0000; msr_tgpr = 1; goto store_gprs; default: cpu_abort(env, "Invalid exception 0x1000 !\n"); break; } return; case 0x1010: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* FIT on 4xx */ cpu_abort(env, "40x FIT exception is not implemented yet !\n"); /* XXX: TODO */ goto store_next; default: cpu_abort(env, "Invalid exception 0x1010 !\n"); break; } return; case 0x1020: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* Watchdog on 4xx */ /* XXX: TODO */ cpu_abort(env, "40x watchdog exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1020 !\n"); break; } return; case 0x1100: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* DTLBMISS on 4xx */ /* XXX: TODO */ cpu_abort(env, "40x DTLBMISS exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_602: case PPC_FLAGS_EXCP_603: /* DLTLBMISS on 602/603 */ msr &= ~0xF00F0000; msr_tgpr = 1; goto store_gprs; default: cpu_abort(env, "Invalid exception 0x1100 !\n"); break; } return; case 0x1200: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* ITLBMISS on 4xx */ /* XXX: TODO */ cpu_abort(env, "40x ITLBMISS exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_602: case PPC_FLAGS_EXCP_603: /* DSTLBMISS on 602/603 */ msr &= ~0xF00F0000; msr_tgpr = 1; store_gprs:#if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "6xx %sTLB miss: IM %08x DM %08x IC %08x " "DC %08x H1 %08x H2 %08x %08x\n", excp == 0x1000 ? "I" : excp == 0x1100 ? "DL" : "DS", env->spr[SPR_IMISS], env->spr[SPR_DMISS], env->spr[SPR_ICMP], env->spr[SPR_DCMP], env->spr[SPR_DHASH1], env->spr[SPR_DHASH2], env->error_code); }#endif /* Swap temporary saved registers with GPRs */ tmp = env->gpr[0]; env->gpr[0] = env->tgpr[0]; env->tgpr[0] = tmp; tmp = env->gpr[1]; env->gpr[1] = env->tgpr[1]; env->tgpr[1] = tmp; tmp = env->gpr[2]; env->gpr[2] = env->tgpr[2]; env->tgpr[2] = tmp; tmp = env->gpr[3]; env->gpr[3] = env->tgpr[3]; env->tgpr[3] = tmp; msr |= env->crf[0] << 28; msr |= env->error_code; /* key, D/I, S/L bits */ /* Set way using a LRU mechanism */ msr |= (env->last_way ^ 1) << 17; goto store_next; default: cpu_abort(env, "Invalid exception 0x1200 !\n"); break; } return; case 0x1300: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_601: case PPC_FLAGS_EXCP_602: case PPC_FLAGS_EXCP_603: case PPC_FLAGS_EXCP_604: case PPC_FLAGS_EXCP_7x0: case PPC_FLAGS_EXCP_7x5: /* IABR on 6xx/7xx */ /* XXX: TODO */ cpu_abort(env, "IABR exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1300 !\n"); break; } return; case 0x1400: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_601: case PPC_FLAGS_EXCP_602: case PPC_FLAGS_EXCP_603: case PPC_FLAGS_EXCP_604: case PPC_FLAGS_EXCP_7x0: case PPC_FLAGS_EXCP_7x5: /* SMI on 6xx/7xx */ /* XXX: TODO */ cpu_abort(env, "SMI exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1400 !\n"); break; } return; case 0x1500: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_602: /* Watchdog on 602 */ cpu_abort(env, "602 watchdog exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_970: /* Soft patch exception on 970 */ /* XXX: TODO */ cpu_abort(env, "970 soft-patch exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_74xx: /* VPU assist on 74xx */ /* XXX: TODO */ cpu_abort(env, "VPU assist exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1500 !\n"); break; } return; case 0x1600: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_602: /* Emulation trap on 602 */ /* XXX: TODO */ cpu_abort(env, "602 emulation trap exception " "is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_970: /* Maintenance exception on 970 */ /* XXX: TODO */ cpu_abort(env, "970 maintenance exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1600 !\n"); break; } return; case 0x1700: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_7x0: case PPC_FLAGS_EXCP_7x5: /* Thermal management interrupt on G3 */ /* XXX: TODO */ cpu_abort(env, "G3 thermal management exception " "is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_970: /* VPU assist on 970 */ /* XXX: TODO */ cpu_abort(env, "970 VPU assist exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1700 !\n"); break; } return; case 0x1800: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_970: /* Thermal exception on 970 */ /* XXX: TODO */ cpu_abort(env, "970 thermal management exception " "is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1800 !\n"); break; } return; case 0x2000: switch (PPC_EXCP(env)) { case PPC_FLAGS_EXCP_40x: /* DEBUG on 4xx */ /* XXX: TODO */ cpu_abort(env, "40x debug exception is not implemented yet !\n"); goto store_next; case PPC_FLAGS_EXCP_601: /* Run mode exception on 601 */ /* XXX: TODO */ cpu_abort(env, "601 run mode exception is not implemented yet !\n"); goto store_next; default: cpu_abort(env, "Invalid exception 0x1800 !\n"); break; } return; /* Other exceptions */ /* Qemu internal exceptions: * we should never come here with those values: abort execution */ default: cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp); return; store_current: /* save current instruction location */ *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL; break; store_next: /* save next instruction location */ *srr_0 = env->nip & 0xFFFFFFFFULL; break; } /* Save msr */ *srr_1 = msr; /* If we disactivated any translation, flush TLBs */ if (msr_ir || msr_dr) { tlb_flush(env, 1); } /* reload MSR with correct bits */ msr_ee = 0; msr_pr = 0; msr_fp = 0; msr_fe0 = 0; msr_se = 0; msr_be = 0; msr_fe1 = 0; msr_ir = 0; msr_dr = 0; msr_ri = 0; msr_le = msr_ile; msr_sf = msr_isf; do_compute_hflags(env); /* Jump to handler */ env->nip = excp; env->exception_index = EXCP_NONE;}#endif /* !CONFIG_USER_ONLY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -