2 * PowerPC exception emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "exec/helper-proto.h"
21 #include "exec/cpu_ldst.h"
23 #include "helper_regs.h"
26 //#define DEBUG_EXCEPTIONS
28 #ifdef DEBUG_EXCEPTIONS
29 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
31 # define LOG_EXCP(...) do { } while (0)
34 /*****************************************************************************/
35 /* PowerPC Hypercall emulation */
37 void (*cpu_ppc_hypercall)(PowerPCCPU *);
39 /*****************************************************************************/
40 /* Exception processing */
41 #if defined(CONFIG_USER_ONLY)
42 void ppc_cpu_do_interrupt(CPUState *cs)
44 PowerPCCPU *cpu = POWERPC_CPU(cs);
45 CPUPPCState *env = &cpu->env;
47 cs->exception_index = POWERPC_EXCP_NONE;
51 static void ppc_hw_interrupt(CPUPPCState *env)
53 CPUState *cs = CPU(ppc_env_get_cpu(env));
55 cs->exception_index = POWERPC_EXCP_NONE;
58 #else /* defined(CONFIG_USER_ONLY) */
59 static inline void dump_syscall(CPUPPCState *env)
61 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
62 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
63 " nip=" TARGET_FMT_lx "\n",
64 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
65 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
66 ppc_dump_gpr(env, 6), env->nip);
69 /* Note that this function should be greatly optimized
70 * when called with a constant excp, from ppc_hw_interrupt
72 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
74 CPUState *cs = CPU(cpu);
75 CPUPPCState *env = &cpu->env;
76 target_ulong msr, new_msr, vector;
77 int srr0, srr1, asrr0, asrr1;
78 int lpes0, lpes1, lev;
81 /* XXX: find a suitable condition to enable the hypervisor mode */
82 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
83 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
85 /* Those values ensure we won't enter the hypervisor mode */
90 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
91 " => %08x (%02x)\n", env->nip, excp, env->error_code);
93 /* new srr1 value excluding must-be-zero bits */
94 if (excp_model == POWERPC_EXCP_BOOKE) {
97 msr = env->msr & ~0x783f0000ULL;
100 /* new interrupt handler msr */
101 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
103 /* target registers */
110 case POWERPC_EXCP_NONE:
111 /* Should never happen */
113 case POWERPC_EXCP_CRITICAL: /* Critical input */
114 switch (excp_model) {
115 case POWERPC_EXCP_40x:
119 case POWERPC_EXCP_BOOKE:
120 srr0 = SPR_BOOKE_CSRR0;
121 srr1 = SPR_BOOKE_CSRR1;
123 case POWERPC_EXCP_G2:
129 case POWERPC_EXCP_MCHECK: /* Machine check exception */
131 /* Machine check exception is not enabled.
132 * Enter checkstop state.
134 if (qemu_log_enabled()) {
135 qemu_log("Machine check while not allowed. "
136 "Entering checkstop state\n");
138 fprintf(stderr, "Machine check while not allowed. "
139 "Entering checkstop state\n");
142 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
145 /* XXX: find a suitable condition to enable the hypervisor mode */
146 new_msr |= (target_ulong)MSR_HVB;
149 /* machine check exceptions don't have ME set */
150 new_msr &= ~((target_ulong)1 << MSR_ME);
152 /* XXX: should also have something loaded in DAR / DSISR */
153 switch (excp_model) {
154 case POWERPC_EXCP_40x:
158 case POWERPC_EXCP_BOOKE:
159 /* FIXME: choose one or the other based on CPU type */
160 srr0 = SPR_BOOKE_MCSRR0;
161 srr1 = SPR_BOOKE_MCSRR1;
162 asrr0 = SPR_BOOKE_CSRR0;
163 asrr1 = SPR_BOOKE_CSRR1;
169 case POWERPC_EXCP_DSI: /* Data storage exception */
170 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
171 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
173 new_msr |= (target_ulong)MSR_HVB;
176 case POWERPC_EXCP_ISI: /* Instruction storage exception */
177 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
178 "\n", msr, env->nip);
180 new_msr |= (target_ulong)MSR_HVB;
182 msr |= env->error_code;
184 case POWERPC_EXCP_EXTERNAL: /* External input */
188 new_msr |= (target_ulong)MSR_HVB;
190 if (env->mpic_proxy) {
191 /* IACK the IRQ on delivery */
192 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
195 case POWERPC_EXCP_ALIGN: /* Alignment exception */
197 new_msr |= (target_ulong)MSR_HVB;
199 /* XXX: this is false */
200 /* Get rS/rD and rA from faulting opcode */
201 env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
204 case POWERPC_EXCP_PROGRAM: /* Program exception */
205 switch (env->error_code & ~0xF) {
206 case POWERPC_EXCP_FP:
207 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
208 LOG_EXCP("Ignore floating point exception\n");
209 cs->exception_index = POWERPC_EXCP_NONE;
214 new_msr |= (target_ulong)MSR_HVB;
217 if (msr_fe0 == msr_fe1) {
222 case POWERPC_EXCP_INVAL:
223 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
225 new_msr |= (target_ulong)MSR_HVB;
228 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
230 case POWERPC_EXCP_PRIV:
232 new_msr |= (target_ulong)MSR_HVB;
235 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
237 case POWERPC_EXCP_TRAP:
239 new_msr |= (target_ulong)MSR_HVB;
242 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
245 /* Should never occur */
246 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
251 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
253 new_msr |= (target_ulong)MSR_HVB;
256 case POWERPC_EXCP_SYSCALL: /* System call exception */
258 lev = env->error_code;
259 if ((lev == 1) && cpu_ppc_hypercall) {
260 cpu_ppc_hypercall(cpu);
263 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
264 new_msr |= (target_ulong)MSR_HVB;
267 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
269 case POWERPC_EXCP_DECR: /* Decrementer exception */
271 new_msr |= (target_ulong)MSR_HVB;
274 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
276 LOG_EXCP("FIT exception\n");
278 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
279 LOG_EXCP("WDT exception\n");
280 switch (excp_model) {
281 case POWERPC_EXCP_BOOKE:
282 srr0 = SPR_BOOKE_CSRR0;
283 srr1 = SPR_BOOKE_CSRR1;
289 case POWERPC_EXCP_DTLB: /* Data TLB error */
291 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
293 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
294 switch (excp_model) {
295 case POWERPC_EXCP_BOOKE:
296 /* FIXME: choose one or the other based on CPU type */
297 srr0 = SPR_BOOKE_DSRR0;
298 srr1 = SPR_BOOKE_DSRR1;
299 asrr0 = SPR_BOOKE_CSRR0;
300 asrr1 = SPR_BOOKE_CSRR1;
306 cpu_abort(cs, "Debug exception is not implemented yet !\n");
308 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
309 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
311 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
313 cpu_abort(cs, "Embedded floating point data exception "
314 "is not implemented yet !\n");
315 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
317 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
319 cpu_abort(cs, "Embedded floating point round exception "
320 "is not implemented yet !\n");
321 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
323 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
326 "Performance counter exception is not implemented yet !\n");
328 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
330 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
331 srr0 = SPR_BOOKE_CSRR0;
332 srr1 = SPR_BOOKE_CSRR1;
334 case POWERPC_EXCP_RESET: /* System reset exception */
336 /* indicate that we resumed from power save mode */
339 new_msr &= ~((target_ulong)1 << MSR_ME);
343 /* XXX: find a suitable condition to enable the hypervisor mode */
344 new_msr |= (target_ulong)MSR_HVB;
347 case POWERPC_EXCP_DSEG: /* Data segment exception */
349 new_msr |= (target_ulong)MSR_HVB;
352 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
354 new_msr |= (target_ulong)MSR_HVB;
357 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
360 new_msr |= (target_ulong)MSR_HVB;
361 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
363 case POWERPC_EXCP_TRACE: /* Trace exception */
365 new_msr |= (target_ulong)MSR_HVB;
368 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
371 new_msr |= (target_ulong)MSR_HVB;
372 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
374 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
377 new_msr |= (target_ulong)MSR_HVB;
378 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
380 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
383 new_msr |= (target_ulong)MSR_HVB;
384 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
386 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
389 new_msr |= (target_ulong)MSR_HVB;
390 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
392 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
394 new_msr |= (target_ulong)MSR_HVB;
397 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
399 new_msr |= (target_ulong)MSR_HVB;
402 case POWERPC_EXCP_FU: /* Facility unavailable exception */
404 new_msr |= (target_ulong)MSR_HVB;
407 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
408 LOG_EXCP("PIT exception\n");
410 case POWERPC_EXCP_IO: /* IO error exception */
412 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
414 case POWERPC_EXCP_RUNM: /* Run mode exception */
416 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
418 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
420 cpu_abort(cs, "602 emulation trap exception "
421 "is not implemented yet !\n");
423 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
424 if (lpes1 == 0) { /* XXX: check this */
425 new_msr |= (target_ulong)MSR_HVB;
427 switch (excp_model) {
428 case POWERPC_EXCP_602:
429 case POWERPC_EXCP_603:
430 case POWERPC_EXCP_603E:
431 case POWERPC_EXCP_G2:
433 case POWERPC_EXCP_7x5:
435 case POWERPC_EXCP_74xx:
438 cpu_abort(cs, "Invalid instruction TLB miss exception\n");
442 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
443 if (lpes1 == 0) { /* XXX: check this */
444 new_msr |= (target_ulong)MSR_HVB;
446 switch (excp_model) {
447 case POWERPC_EXCP_602:
448 case POWERPC_EXCP_603:
449 case POWERPC_EXCP_603E:
450 case POWERPC_EXCP_G2:
452 case POWERPC_EXCP_7x5:
454 case POWERPC_EXCP_74xx:
457 cpu_abort(cs, "Invalid data load TLB miss exception\n");
461 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
462 if (lpes1 == 0) { /* XXX: check this */
463 new_msr |= (target_ulong)MSR_HVB;
465 switch (excp_model) {
466 case POWERPC_EXCP_602:
467 case POWERPC_EXCP_603:
468 case POWERPC_EXCP_603E:
469 case POWERPC_EXCP_G2:
471 /* Swap temporary saved registers with GPRs */
472 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
473 new_msr |= (target_ulong)1 << MSR_TGPR;
474 hreg_swap_gpr_tgpr(env);
477 case POWERPC_EXCP_7x5:
479 #if defined(DEBUG_SOFTWARE_TLB)
480 if (qemu_log_enabled()) {
482 target_ulong *miss, *cmp;
485 if (excp == POWERPC_EXCP_IFTLB) {
488 miss = &env->spr[SPR_IMISS];
489 cmp = &env->spr[SPR_ICMP];
491 if (excp == POWERPC_EXCP_DLTLB) {
497 miss = &env->spr[SPR_DMISS];
498 cmp = &env->spr[SPR_DCMP];
500 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
501 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
502 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
503 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
507 msr |= env->crf[0] << 28;
508 msr |= env->error_code; /* key, D/I, S/L bits */
509 /* Set way using a LRU mechanism */
510 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
512 case POWERPC_EXCP_74xx:
514 #if defined(DEBUG_SOFTWARE_TLB)
515 if (qemu_log_enabled()) {
517 target_ulong *miss, *cmp;
520 if (excp == POWERPC_EXCP_IFTLB) {
523 miss = &env->spr[SPR_TLBMISS];
524 cmp = &env->spr[SPR_PTEHI];
526 if (excp == POWERPC_EXCP_DLTLB) {
532 miss = &env->spr[SPR_TLBMISS];
533 cmp = &env->spr[SPR_PTEHI];
535 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
536 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
540 msr |= env->error_code; /* key bit */
543 cpu_abort(cs, "Invalid data store TLB miss exception\n");
547 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
549 cpu_abort(cs, "Floating point assist exception "
550 "is not implemented yet !\n");
552 case POWERPC_EXCP_DABR: /* Data address breakpoint */
554 cpu_abort(cs, "DABR exception is not implemented yet !\n");
556 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
558 cpu_abort(cs, "IABR exception is not implemented yet !\n");
560 case POWERPC_EXCP_SMI: /* System management interrupt */
562 cpu_abort(cs, "SMI exception is not implemented yet !\n");
564 case POWERPC_EXCP_THERM: /* Thermal interrupt */
566 cpu_abort(cs, "Thermal management exception "
567 "is not implemented yet !\n");
569 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
571 new_msr |= (target_ulong)MSR_HVB;
575 "Performance counter exception is not implemented yet !\n");
577 case POWERPC_EXCP_VPUA: /* Vector assist exception */
579 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
581 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
584 "970 soft-patch exception is not implemented yet !\n");
586 case POWERPC_EXCP_MAINT: /* Maintenance exception */
589 "970 maintenance exception is not implemented yet !\n");
591 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
593 cpu_abort(cs, "Maskable external exception "
594 "is not implemented yet !\n");
596 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
598 cpu_abort(cs, "Non maskable external exception "
599 "is not implemented yet !\n");
603 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
606 /* save current instruction location */
607 env->spr[srr0] = env->nip - 4;
610 /* save next instruction location */
611 env->spr[srr0] = env->nip;
615 env->spr[srr1] = msr;
616 /* If any alternate SRR register are defined, duplicate saved values */
618 env->spr[asrr0] = env->spr[srr0];
621 env->spr[asrr1] = env->spr[srr1];
624 if (env->spr[SPR_LPCR] & LPCR_AIL) {
625 new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
626 } else if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
627 /* If we disactivated any translation, flush TLBs */
632 if (excp_model == POWERPC_EXCP_POWER7) {
633 if (env->spr[SPR_LPCR] & LPCR_ILE) {
634 new_msr |= (target_ulong)1 << MSR_LE;
636 } else if (msr_ile) {
637 new_msr |= (target_ulong)1 << MSR_LE;
641 new_msr |= (target_ulong)1 << MSR_LE;
645 /* Jump to handler */
646 vector = env->excp_vectors[excp];
647 if (vector == (target_ulong)-1ULL) {
648 cpu_abort(cs, "Raised an exception without defined vector %d\n",
651 vector |= env->excp_prefix;
652 #if defined(TARGET_PPC64)
653 if (excp_model == POWERPC_EXCP_BOOKE) {
654 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
655 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
656 new_msr |= (target_ulong)1 << MSR_CM;
658 vector = (uint32_t)vector;
661 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
662 vector = (uint32_t)vector;
664 new_msr |= (target_ulong)1 << MSR_SF;
668 /* XXX: we don't use hreg_store_msr here as already have treated
669 * any special case that could occur. Just store MSR and update hflags
671 env->msr = new_msr & env->msr_mask;
672 hreg_compute_hflags(env);
674 /* Reset exception state */
675 cs->exception_index = POWERPC_EXCP_NONE;
678 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
679 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
680 /* XXX: The BookE changes address space when switching modes,
681 we should probably implement that as different MMU indexes,
682 but for the moment we do it the slow way and flush all. */
687 void ppc_cpu_do_interrupt(CPUState *cs)
689 PowerPCCPU *cpu = POWERPC_CPU(cs);
690 CPUPPCState *env = &cpu->env;
692 powerpc_excp(cpu, env->excp_model, cs->exception_index);
695 static void ppc_hw_interrupt(CPUPPCState *env)
697 PowerPCCPU *cpu = ppc_env_get_cpu(env);
700 CPUState *cs = CPU(cpu);
702 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
703 __func__, env, env->pending_interrupts,
704 cs->interrupt_request, (int)msr_me, (int)msr_ee);
707 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
708 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
709 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
712 /* Machine check exception */
713 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
714 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
715 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
719 /* External debug exception */
720 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
721 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
722 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
727 /* XXX: find a suitable condition to enable the hypervisor mode */
728 hdice = env->spr[SPR_LPCR] & 1;
732 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
733 /* Hypervisor decrementer exception */
734 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
735 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
740 /* External critical interrupt */
741 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
742 /* Taking a critical external interrupt does not clear the external
743 * critical interrupt status
746 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
748 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
753 /* Watchdog timer on embedded PowerPC */
754 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
755 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
756 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
759 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
760 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
761 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
764 /* Fixed interval timer on embedded PowerPC */
765 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
766 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
767 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
770 /* Programmable interval timer on embedded PowerPC */
771 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
772 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
773 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
776 /* Decrementer exception */
777 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
778 if (ppc_decr_clear_on_delivery(env)) {
779 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
781 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
784 /* External interrupt */
785 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
786 /* Taking an external interrupt does not clear the external
790 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
792 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
795 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
796 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
797 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
800 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
801 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
802 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
805 /* Thermal interrupt */
806 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
807 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
808 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
814 void ppc_cpu_do_system_reset(CPUState *cs)
816 PowerPCCPU *cpu = POWERPC_CPU(cs);
817 CPUPPCState *env = &cpu->env;
819 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
821 #endif /* !CONFIG_USER_ONLY */
823 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
825 PowerPCCPU *cpu = POWERPC_CPU(cs);
826 CPUPPCState *env = &cpu->env;
828 if (interrupt_request & CPU_INTERRUPT_HARD) {
829 ppc_hw_interrupt(env);
830 if (env->pending_interrupts == 0) {
831 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
838 #if defined(DEBUG_OP)
839 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
841 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
842 TARGET_FMT_lx "\n", RA, msr);
846 /*****************************************************************************/
847 /* Exceptions processing helpers */
849 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
852 CPUState *cs = CPU(ppc_env_get_cpu(env));
855 printf("Raise exception %3x code : %d\n", exception, error_code);
857 cs->exception_index = exception;
858 env->error_code = error_code;
862 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
864 helper_raise_exception_err(env, exception, 0);
867 #if !defined(CONFIG_USER_ONLY)
868 void helper_store_msr(CPUPPCState *env, target_ulong val)
872 val = hreg_store_msr(env, val, 0);
874 cs = CPU(ppc_env_get_cpu(env));
875 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
876 helper_raise_exception(env, val);
880 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
881 target_ulong msrm, int keep_msrh)
883 CPUState *cs = CPU(ppc_env_get_cpu(env));
885 #if defined(TARGET_PPC64)
886 if (msr_is_64bit(env, msr)) {
888 msr &= (uint64_t)msrm;
891 msr = (uint32_t)(msr & msrm);
893 msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
898 msr &= (uint32_t)msrm;
900 /* XXX: beware: this is false if VLE is supported */
901 env->nip = nip & ~((target_ulong)0x00000003);
902 hreg_store_msr(env, msr, 1);
903 #if defined(DEBUG_OP)
904 cpu_dump_rfi(env->nip, env->msr);
906 /* No need to raise an exception here,
907 * as rfi is always the last insn of a TB
909 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
912 void helper_rfi(CPUPPCState *env)
914 if (env->excp_model == POWERPC_EXCP_BOOKE) {
915 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
916 ~((target_ulong)0), 0);
918 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
919 ~((target_ulong)0x783F0000), 1);
923 #if defined(TARGET_PPC64)
924 void helper_rfid(CPUPPCState *env)
926 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
927 ~((target_ulong)0x783F0000), 0);
930 void helper_hrfid(CPUPPCState *env)
932 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
933 ~((target_ulong)0x783F0000), 0);
937 /*****************************************************************************/
938 /* Embedded PowerPC specific helpers */
939 void helper_40x_rfci(CPUPPCState *env)
941 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
942 ~((target_ulong)0xFFFF0000), 0);
945 void helper_rfci(CPUPPCState *env)
947 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
948 ~((target_ulong)0), 0);
951 void helper_rfdi(CPUPPCState *env)
953 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
954 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
955 ~((target_ulong)0), 0);
958 void helper_rfmci(CPUPPCState *env)
960 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
961 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
962 ~((target_ulong)0), 0);
966 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
969 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
970 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
971 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
972 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
973 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
974 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
979 #if defined(TARGET_PPC64)
980 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
983 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
984 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
985 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
986 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
987 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
988 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
994 #if !defined(CONFIG_USER_ONLY)
995 /*****************************************************************************/
996 /* PowerPC 601 specific instructions (POWER bridge) */
998 void helper_rfsvc(CPUPPCState *env)
1000 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
1003 /* Embedded.Processor Control */
1004 static int dbell2irq(target_ulong rb)
1006 int msg = rb & DBELL_TYPE_MASK;
1010 case DBELL_TYPE_DBELL:
1011 irq = PPC_INTERRUPT_DOORBELL;
1013 case DBELL_TYPE_DBELL_CRIT:
1014 irq = PPC_INTERRUPT_CDOORBELL;
1016 case DBELL_TYPE_G_DBELL:
1017 case DBELL_TYPE_G_DBELL_CRIT:
1018 case DBELL_TYPE_G_DBELL_MC:
1027 void helper_msgclr(CPUPPCState *env, target_ulong rb)
1029 int irq = dbell2irq(rb);
1035 env->pending_interrupts &= ~(1 << irq);
1038 void helper_msgsnd(target_ulong rb)
1040 int irq = dbell2irq(rb);
1041 int pir = rb & DBELL_PIRTAG_MASK;
1049 PowerPCCPU *cpu = POWERPC_CPU(cs);
1050 CPUPPCState *cenv = &cpu->env;
1052 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1053 cenv->pending_interrupts |= 1 << irq;
1054 cpu_interrupt(cs, CPU_INTERRUPT_HARD);