cris: avoid "naked" qemu_log
[qemu/ar7.git] / target-ppc / excp_helper.c
blob102d789d2db59f45d0b63fe086cdaf50ba482987
1 /*
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/>.
19 #include "cpu.h"
20 #include "exec/helper-proto.h"
21 #include "exec/cpu_ldst.h"
23 #include "helper_regs.h"
25 //#define DEBUG_OP
26 //#define DEBUG_EXCEPTIONS
28 #ifdef DEBUG_EXCEPTIONS
29 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
30 #else
31 # define LOG_EXCP(...) do { } while (0)
32 #endif
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;
48 env->error_code = 0;
51 static void ppc_hw_interrupt(CPUPPCState *env)
53 CPUState *cs = CPU(ppc_env_get_cpu(env));
55 cs->exception_index = POWERPC_EXCP_NONE;
56 env->error_code = 0;
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;
80 if (0) {
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;
84 } else {
85 /* Those values ensure we won't enter the hypervisor mode */
86 lpes0 = 0;
87 lpes1 = 1;
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) {
95 msr = env->msr;
96 } else {
97 msr = env->msr & ~0x783f0000ULL;
100 /* new interrupt handler msr */
101 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
103 /* target registers */
104 srr0 = SPR_SRR0;
105 srr1 = SPR_SRR1;
106 asrr0 = -1;
107 asrr1 = -1;
109 switch (excp) {
110 case POWERPC_EXCP_NONE:
111 /* Should never happen */
112 return;
113 case POWERPC_EXCP_CRITICAL: /* Critical input */
114 switch (excp_model) {
115 case POWERPC_EXCP_40x:
116 srr0 = SPR_40x_SRR2;
117 srr1 = SPR_40x_SRR3;
118 break;
119 case POWERPC_EXCP_BOOKE:
120 srr0 = SPR_BOOKE_CSRR0;
121 srr1 = SPR_BOOKE_CSRR1;
122 break;
123 case POWERPC_EXCP_G2:
124 break;
125 default:
126 goto excp_invalid;
128 goto store_next;
129 case POWERPC_EXCP_MCHECK: /* Machine check exception */
130 if (msr_me == 0) {
131 /* Machine check exception is not enabled.
132 * Enter checkstop state.
134 fprintf(stderr, "Machine check while not allowed. "
135 "Entering checkstop state\n");
136 if (qemu_log_separate()) {
137 qemu_log("Machine check while not allowed. "
138 "Entering checkstop state\n");
140 cs->halted = 1;
141 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
143 if (0) {
144 /* XXX: find a suitable condition to enable the hypervisor mode */
145 new_msr |= (target_ulong)MSR_HVB;
148 /* machine check exceptions don't have ME set */
149 new_msr &= ~((target_ulong)1 << MSR_ME);
151 /* XXX: should also have something loaded in DAR / DSISR */
152 switch (excp_model) {
153 case POWERPC_EXCP_40x:
154 srr0 = SPR_40x_SRR2;
155 srr1 = SPR_40x_SRR3;
156 break;
157 case POWERPC_EXCP_BOOKE:
158 /* FIXME: choose one or the other based on CPU type */
159 srr0 = SPR_BOOKE_MCSRR0;
160 srr1 = SPR_BOOKE_MCSRR1;
161 asrr0 = SPR_BOOKE_CSRR0;
162 asrr1 = SPR_BOOKE_CSRR1;
163 break;
164 default:
165 break;
167 goto store_next;
168 case POWERPC_EXCP_DSI: /* Data storage exception */
169 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
170 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
171 if (lpes1 == 0) {
172 new_msr |= (target_ulong)MSR_HVB;
174 goto store_next;
175 case POWERPC_EXCP_ISI: /* Instruction storage exception */
176 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
177 "\n", msr, env->nip);
178 if (lpes1 == 0) {
179 new_msr |= (target_ulong)MSR_HVB;
181 msr |= env->error_code;
182 goto store_next;
183 case POWERPC_EXCP_EXTERNAL: /* External input */
184 cs = CPU(cpu);
186 if (lpes0 == 1) {
187 new_msr |= (target_ulong)MSR_HVB;
189 if (env->mpic_proxy) {
190 /* IACK the IRQ on delivery */
191 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
193 goto store_next;
194 case POWERPC_EXCP_ALIGN: /* Alignment exception */
195 if (lpes1 == 0) {
196 new_msr |= (target_ulong)MSR_HVB;
198 /* XXX: this is false */
199 /* Get rS/rD and rA from faulting opcode */
200 env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
201 & 0x03FF0000) >> 16;
202 goto store_next;
203 case POWERPC_EXCP_PROGRAM: /* Program exception */
204 switch (env->error_code & ~0xF) {
205 case POWERPC_EXCP_FP:
206 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
207 LOG_EXCP("Ignore floating point exception\n");
208 cs->exception_index = POWERPC_EXCP_NONE;
209 env->error_code = 0;
210 return;
212 if (lpes1 == 0) {
213 new_msr |= (target_ulong)MSR_HVB;
215 msr |= 0x00100000;
216 if (msr_fe0 == msr_fe1) {
217 goto store_next;
219 msr |= 0x00010000;
220 break;
221 case POWERPC_EXCP_INVAL:
222 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
223 if (lpes1 == 0) {
224 new_msr |= (target_ulong)MSR_HVB;
226 msr |= 0x00080000;
227 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
228 break;
229 case POWERPC_EXCP_PRIV:
230 if (lpes1 == 0) {
231 new_msr |= (target_ulong)MSR_HVB;
233 msr |= 0x00040000;
234 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
235 break;
236 case POWERPC_EXCP_TRAP:
237 if (lpes1 == 0) {
238 new_msr |= (target_ulong)MSR_HVB;
240 msr |= 0x00020000;
241 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
242 break;
243 default:
244 /* Should never occur */
245 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
246 env->error_code);
247 break;
249 goto store_current;
250 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
251 if (lpes1 == 0) {
252 new_msr |= (target_ulong)MSR_HVB;
254 goto store_current;
255 case POWERPC_EXCP_SYSCALL: /* System call exception */
256 dump_syscall(env);
257 lev = env->error_code;
258 if ((lev == 1) && cpu_ppc_hypercall) {
259 cpu_ppc_hypercall(cpu);
260 return;
262 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
263 new_msr |= (target_ulong)MSR_HVB;
265 goto store_next;
266 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
267 goto store_current;
268 case POWERPC_EXCP_DECR: /* Decrementer exception */
269 if (lpes1 == 0) {
270 new_msr |= (target_ulong)MSR_HVB;
272 goto store_next;
273 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
274 /* FIT on 4xx */
275 LOG_EXCP("FIT exception\n");
276 goto store_next;
277 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
278 LOG_EXCP("WDT exception\n");
279 switch (excp_model) {
280 case POWERPC_EXCP_BOOKE:
281 srr0 = SPR_BOOKE_CSRR0;
282 srr1 = SPR_BOOKE_CSRR1;
283 break;
284 default:
285 break;
287 goto store_next;
288 case POWERPC_EXCP_DTLB: /* Data TLB error */
289 goto store_next;
290 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
291 goto store_next;
292 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
293 switch (excp_model) {
294 case POWERPC_EXCP_BOOKE:
295 /* FIXME: choose one or the other based on CPU type */
296 srr0 = SPR_BOOKE_DSRR0;
297 srr1 = SPR_BOOKE_DSRR1;
298 asrr0 = SPR_BOOKE_CSRR0;
299 asrr1 = SPR_BOOKE_CSRR1;
300 break;
301 default:
302 break;
304 /* XXX: TODO */
305 cpu_abort(cs, "Debug exception is not implemented yet !\n");
306 goto store_next;
307 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
308 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
309 goto store_current;
310 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
311 /* XXX: TODO */
312 cpu_abort(cs, "Embedded floating point data exception "
313 "is not implemented yet !\n");
314 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
315 goto store_next;
316 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
317 /* XXX: TODO */
318 cpu_abort(cs, "Embedded floating point round exception "
319 "is not implemented yet !\n");
320 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
321 goto store_next;
322 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
323 /* XXX: TODO */
324 cpu_abort(cs,
325 "Performance counter exception is not implemented yet !\n");
326 goto store_next;
327 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
328 goto store_next;
329 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
330 srr0 = SPR_BOOKE_CSRR0;
331 srr1 = SPR_BOOKE_CSRR1;
332 goto store_next;
333 case POWERPC_EXCP_RESET: /* System reset exception */
334 if (msr_pow) {
335 /* indicate that we resumed from power save mode */
336 msr |= 0x10000;
337 } else {
338 new_msr &= ~((target_ulong)1 << MSR_ME);
341 if (0) {
342 /* XXX: find a suitable condition to enable the hypervisor mode */
343 new_msr |= (target_ulong)MSR_HVB;
345 goto store_next;
346 case POWERPC_EXCP_DSEG: /* Data segment exception */
347 if (lpes1 == 0) {
348 new_msr |= (target_ulong)MSR_HVB;
350 goto store_next;
351 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
352 if (lpes1 == 0) {
353 new_msr |= (target_ulong)MSR_HVB;
355 goto store_next;
356 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
357 srr0 = SPR_HSRR0;
358 srr1 = SPR_HSRR1;
359 new_msr |= (target_ulong)MSR_HVB;
360 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
361 goto store_next;
362 case POWERPC_EXCP_TRACE: /* Trace exception */
363 if (lpes1 == 0) {
364 new_msr |= (target_ulong)MSR_HVB;
366 goto store_next;
367 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
368 srr0 = SPR_HSRR0;
369 srr1 = SPR_HSRR1;
370 new_msr |= (target_ulong)MSR_HVB;
371 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
372 goto store_next;
373 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
374 srr0 = SPR_HSRR0;
375 srr1 = SPR_HSRR1;
376 new_msr |= (target_ulong)MSR_HVB;
377 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
378 goto store_next;
379 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
380 srr0 = SPR_HSRR0;
381 srr1 = SPR_HSRR1;
382 new_msr |= (target_ulong)MSR_HVB;
383 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
384 goto store_next;
385 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
386 srr0 = SPR_HSRR0;
387 srr1 = SPR_HSRR1;
388 new_msr |= (target_ulong)MSR_HVB;
389 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
390 goto store_next;
391 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
392 if (lpes1 == 0) {
393 new_msr |= (target_ulong)MSR_HVB;
395 goto store_current;
396 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
397 if (lpes1 == 0) {
398 new_msr |= (target_ulong)MSR_HVB;
400 goto store_current;
401 case POWERPC_EXCP_FU: /* Facility unavailable exception */
402 if (lpes1 == 0) {
403 new_msr |= (target_ulong)MSR_HVB;
405 goto store_current;
406 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
407 LOG_EXCP("PIT exception\n");
408 goto store_next;
409 case POWERPC_EXCP_IO: /* IO error exception */
410 /* XXX: TODO */
411 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
412 goto store_next;
413 case POWERPC_EXCP_RUNM: /* Run mode exception */
414 /* XXX: TODO */
415 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
416 goto store_next;
417 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
418 /* XXX: TODO */
419 cpu_abort(cs, "602 emulation trap exception "
420 "is not implemented yet !\n");
421 goto store_next;
422 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
423 if (lpes1 == 0) { /* XXX: check this */
424 new_msr |= (target_ulong)MSR_HVB;
426 switch (excp_model) {
427 case POWERPC_EXCP_602:
428 case POWERPC_EXCP_603:
429 case POWERPC_EXCP_603E:
430 case POWERPC_EXCP_G2:
431 goto tlb_miss_tgpr;
432 case POWERPC_EXCP_7x5:
433 goto tlb_miss;
434 case POWERPC_EXCP_74xx:
435 goto tlb_miss_74xx;
436 default:
437 cpu_abort(cs, "Invalid instruction TLB miss exception\n");
438 break;
440 break;
441 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
442 if (lpes1 == 0) { /* XXX: check this */
443 new_msr |= (target_ulong)MSR_HVB;
445 switch (excp_model) {
446 case POWERPC_EXCP_602:
447 case POWERPC_EXCP_603:
448 case POWERPC_EXCP_603E:
449 case POWERPC_EXCP_G2:
450 goto tlb_miss_tgpr;
451 case POWERPC_EXCP_7x5:
452 goto tlb_miss;
453 case POWERPC_EXCP_74xx:
454 goto tlb_miss_74xx;
455 default:
456 cpu_abort(cs, "Invalid data load TLB miss exception\n");
457 break;
459 break;
460 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
461 if (lpes1 == 0) { /* XXX: check this */
462 new_msr |= (target_ulong)MSR_HVB;
464 switch (excp_model) {
465 case POWERPC_EXCP_602:
466 case POWERPC_EXCP_603:
467 case POWERPC_EXCP_603E:
468 case POWERPC_EXCP_G2:
469 tlb_miss_tgpr:
470 /* Swap temporary saved registers with GPRs */
471 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
472 new_msr |= (target_ulong)1 << MSR_TGPR;
473 hreg_swap_gpr_tgpr(env);
475 goto tlb_miss;
476 case POWERPC_EXCP_7x5:
477 tlb_miss:
478 #if defined(DEBUG_SOFTWARE_TLB)
479 if (qemu_log_enabled()) {
480 const char *es;
481 target_ulong *miss, *cmp;
482 int en;
484 if (excp == POWERPC_EXCP_IFTLB) {
485 es = "I";
486 en = 'I';
487 miss = &env->spr[SPR_IMISS];
488 cmp = &env->spr[SPR_ICMP];
489 } else {
490 if (excp == POWERPC_EXCP_DLTLB) {
491 es = "DL";
492 } else {
493 es = "DS";
495 en = 'D';
496 miss = &env->spr[SPR_DMISS];
497 cmp = &env->spr[SPR_DCMP];
499 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
500 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
501 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
502 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
503 env->error_code);
505 #endif
506 msr |= env->crf[0] << 28;
507 msr |= env->error_code; /* key, D/I, S/L bits */
508 /* Set way using a LRU mechanism */
509 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
510 break;
511 case POWERPC_EXCP_74xx:
512 tlb_miss_74xx:
513 #if defined(DEBUG_SOFTWARE_TLB)
514 if (qemu_log_enabled()) {
515 const char *es;
516 target_ulong *miss, *cmp;
517 int en;
519 if (excp == POWERPC_EXCP_IFTLB) {
520 es = "I";
521 en = 'I';
522 miss = &env->spr[SPR_TLBMISS];
523 cmp = &env->spr[SPR_PTEHI];
524 } else {
525 if (excp == POWERPC_EXCP_DLTLB) {
526 es = "DL";
527 } else {
528 es = "DS";
530 en = 'D';
531 miss = &env->spr[SPR_TLBMISS];
532 cmp = &env->spr[SPR_PTEHI];
534 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
535 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
536 env->error_code);
538 #endif
539 msr |= env->error_code; /* key bit */
540 break;
541 default:
542 cpu_abort(cs, "Invalid data store TLB miss exception\n");
543 break;
545 goto store_next;
546 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
547 /* XXX: TODO */
548 cpu_abort(cs, "Floating point assist exception "
549 "is not implemented yet !\n");
550 goto store_next;
551 case POWERPC_EXCP_DABR: /* Data address breakpoint */
552 /* XXX: TODO */
553 cpu_abort(cs, "DABR exception is not implemented yet !\n");
554 goto store_next;
555 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
556 /* XXX: TODO */
557 cpu_abort(cs, "IABR exception is not implemented yet !\n");
558 goto store_next;
559 case POWERPC_EXCP_SMI: /* System management interrupt */
560 /* XXX: TODO */
561 cpu_abort(cs, "SMI exception is not implemented yet !\n");
562 goto store_next;
563 case POWERPC_EXCP_THERM: /* Thermal interrupt */
564 /* XXX: TODO */
565 cpu_abort(cs, "Thermal management exception "
566 "is not implemented yet !\n");
567 goto store_next;
568 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
569 if (lpes1 == 0) {
570 new_msr |= (target_ulong)MSR_HVB;
572 /* XXX: TODO */
573 cpu_abort(cs,
574 "Performance counter exception is not implemented yet !\n");
575 goto store_next;
576 case POWERPC_EXCP_VPUA: /* Vector assist exception */
577 /* XXX: TODO */
578 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
579 goto store_next;
580 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
581 /* XXX: TODO */
582 cpu_abort(cs,
583 "970 soft-patch exception is not implemented yet !\n");
584 goto store_next;
585 case POWERPC_EXCP_MAINT: /* Maintenance exception */
586 /* XXX: TODO */
587 cpu_abort(cs,
588 "970 maintenance exception is not implemented yet !\n");
589 goto store_next;
590 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
591 /* XXX: TODO */
592 cpu_abort(cs, "Maskable external exception "
593 "is not implemented yet !\n");
594 goto store_next;
595 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
596 /* XXX: TODO */
597 cpu_abort(cs, "Non maskable external exception "
598 "is not implemented yet !\n");
599 goto store_next;
600 default:
601 excp_invalid:
602 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
603 break;
604 store_current:
605 /* save current instruction location */
606 env->spr[srr0] = env->nip - 4;
607 break;
608 store_next:
609 /* save next instruction location */
610 env->spr[srr0] = env->nip;
611 break;
613 /* Save MSR */
614 env->spr[srr1] = msr;
615 /* If any alternate SRR register are defined, duplicate saved values */
616 if (asrr0 != -1) {
617 env->spr[asrr0] = env->spr[srr0];
619 if (asrr1 != -1) {
620 env->spr[asrr1] = env->spr[srr1];
623 if (env->spr[SPR_LPCR] & LPCR_AIL) {
624 new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
625 } else if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
626 /* If we disactivated any translation, flush TLBs */
627 tlb_flush(cs, 1);
630 #ifdef TARGET_PPC64
631 if (excp_model == POWERPC_EXCP_POWER7) {
632 if (env->spr[SPR_LPCR] & LPCR_ILE) {
633 new_msr |= (target_ulong)1 << MSR_LE;
635 } else if (msr_ile) {
636 new_msr |= (target_ulong)1 << MSR_LE;
638 #else
639 if (msr_ile) {
640 new_msr |= (target_ulong)1 << MSR_LE;
642 #endif
644 /* Jump to handler */
645 vector = env->excp_vectors[excp];
646 if (vector == (target_ulong)-1ULL) {
647 cpu_abort(cs, "Raised an exception without defined vector %d\n",
648 excp);
650 vector |= env->excp_prefix;
651 #if defined(TARGET_PPC64)
652 if (excp_model == POWERPC_EXCP_BOOKE) {
653 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
654 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
655 new_msr |= (target_ulong)1 << MSR_CM;
656 } else {
657 vector = (uint32_t)vector;
659 } else {
660 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
661 vector = (uint32_t)vector;
662 } else {
663 new_msr |= (target_ulong)1 << MSR_SF;
666 #endif
667 /* XXX: we don't use hreg_store_msr here as already have treated
668 * any special case that could occur. Just store MSR and update hflags
670 env->msr = new_msr & env->msr_mask;
671 hreg_compute_hflags(env);
672 env->nip = vector;
673 /* Reset exception state */
674 cs->exception_index = POWERPC_EXCP_NONE;
675 env->error_code = 0;
677 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
678 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
679 /* XXX: The BookE changes address space when switching modes,
680 we should probably implement that as different MMU indexes,
681 but for the moment we do it the slow way and flush all. */
682 tlb_flush(cs, 1);
686 void ppc_cpu_do_interrupt(CPUState *cs)
688 PowerPCCPU *cpu = POWERPC_CPU(cs);
689 CPUPPCState *env = &cpu->env;
691 powerpc_excp(cpu, env->excp_model, cs->exception_index);
694 static void ppc_hw_interrupt(CPUPPCState *env)
696 PowerPCCPU *cpu = ppc_env_get_cpu(env);
697 int hdice;
698 #if 0
699 CPUState *cs = CPU(cpu);
701 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
702 __func__, env, env->pending_interrupts,
703 cs->interrupt_request, (int)msr_me, (int)msr_ee);
704 #endif
705 /* External reset */
706 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
707 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
708 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
709 return;
711 /* Machine check exception */
712 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
713 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
714 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
715 return;
717 #if 0 /* TODO */
718 /* External debug exception */
719 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
720 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
721 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
722 return;
724 #endif
725 if (0) {
726 /* XXX: find a suitable condition to enable the hypervisor mode */
727 hdice = env->spr[SPR_LPCR] & 1;
728 } else {
729 hdice = 0;
731 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
732 /* Hypervisor decrementer exception */
733 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
734 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
735 return;
738 if (msr_ce != 0) {
739 /* External critical interrupt */
740 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
741 /* Taking a critical external interrupt does not clear the external
742 * critical interrupt status
744 #if 0
745 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
746 #endif
747 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
748 return;
751 if (msr_ee != 0) {
752 /* Watchdog timer on embedded PowerPC */
753 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
754 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
755 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
756 return;
758 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
759 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
760 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
761 return;
763 /* Fixed interval timer on embedded PowerPC */
764 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
765 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
766 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
767 return;
769 /* Programmable interval timer on embedded PowerPC */
770 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
771 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
772 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
773 return;
775 /* Decrementer exception */
776 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
777 if (ppc_decr_clear_on_delivery(env)) {
778 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
780 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
781 return;
783 /* External interrupt */
784 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
785 /* Taking an external interrupt does not clear the external
786 * interrupt status
788 #if 0
789 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
790 #endif
791 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
792 return;
794 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
795 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
796 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
797 return;
799 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
800 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
801 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
802 return;
804 /* Thermal interrupt */
805 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
806 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
807 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
808 return;
813 void ppc_cpu_do_system_reset(CPUState *cs)
815 PowerPCCPU *cpu = POWERPC_CPU(cs);
816 CPUPPCState *env = &cpu->env;
818 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
820 #endif /* !CONFIG_USER_ONLY */
822 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
824 PowerPCCPU *cpu = POWERPC_CPU(cs);
825 CPUPPCState *env = &cpu->env;
827 if (interrupt_request & CPU_INTERRUPT_HARD) {
828 ppc_hw_interrupt(env);
829 if (env->pending_interrupts == 0) {
830 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
832 return true;
834 return false;
837 #if defined(DEBUG_OP)
838 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
840 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
841 TARGET_FMT_lx "\n", RA, msr);
843 #endif
845 /*****************************************************************************/
846 /* Exceptions processing helpers */
848 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
849 uint32_t error_code)
851 CPUState *cs = CPU(ppc_env_get_cpu(env));
853 #if 0
854 printf("Raise exception %3x code : %d\n", exception, error_code);
855 #endif
856 cs->exception_index = exception;
857 env->error_code = error_code;
858 cpu_loop_exit(cs);
861 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
863 helper_raise_exception_err(env, exception, 0);
866 #if !defined(CONFIG_USER_ONLY)
867 void helper_store_msr(CPUPPCState *env, target_ulong val)
869 CPUState *cs;
871 val = hreg_store_msr(env, val, 0);
872 if (val != 0) {
873 cs = CPU(ppc_env_get_cpu(env));
874 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
875 helper_raise_exception(env, val);
879 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
880 target_ulong msrm, int keep_msrh)
882 CPUState *cs = CPU(ppc_env_get_cpu(env));
884 #if defined(TARGET_PPC64)
885 if (msr_is_64bit(env, msr)) {
886 nip = (uint64_t)nip;
887 msr &= (uint64_t)msrm;
888 } else {
889 nip = (uint32_t)nip;
890 msr = (uint32_t)(msr & msrm);
891 if (keep_msrh) {
892 msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
895 #else
896 nip = (uint32_t)nip;
897 msr &= (uint32_t)msrm;
898 #endif
899 /* XXX: beware: this is false if VLE is supported */
900 env->nip = nip & ~((target_ulong)0x00000003);
901 hreg_store_msr(env, msr, 1);
902 #if defined(DEBUG_OP)
903 cpu_dump_rfi(env->nip, env->msr);
904 #endif
905 /* No need to raise an exception here,
906 * as rfi is always the last insn of a TB
908 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
911 void helper_rfi(CPUPPCState *env)
913 if (env->excp_model == POWERPC_EXCP_BOOKE) {
914 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
915 ~((target_ulong)0), 0);
916 } else {
917 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
918 ~((target_ulong)0x783F0000), 1);
922 #if defined(TARGET_PPC64)
923 void helper_rfid(CPUPPCState *env)
925 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
926 ~((target_ulong)0x783F0000), 0);
929 void helper_hrfid(CPUPPCState *env)
931 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
932 ~((target_ulong)0x783F0000), 0);
934 #endif
936 /*****************************************************************************/
937 /* Embedded PowerPC specific helpers */
938 void helper_40x_rfci(CPUPPCState *env)
940 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
941 ~((target_ulong)0xFFFF0000), 0);
944 void helper_rfci(CPUPPCState *env)
946 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
947 ~((target_ulong)0), 0);
950 void helper_rfdi(CPUPPCState *env)
952 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
953 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
954 ~((target_ulong)0), 0);
957 void helper_rfmci(CPUPPCState *env)
959 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
960 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
961 ~((target_ulong)0), 0);
963 #endif
965 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
966 uint32_t flags)
968 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
969 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
970 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
971 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
972 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
973 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
974 POWERPC_EXCP_TRAP);
978 #if defined(TARGET_PPC64)
979 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
980 uint32_t flags)
982 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
983 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
984 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
985 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
986 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
987 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
988 POWERPC_EXCP_TRAP);
991 #endif
993 #if !defined(CONFIG_USER_ONLY)
994 /*****************************************************************************/
995 /* PowerPC 601 specific instructions (POWER bridge) */
997 void helper_rfsvc(CPUPPCState *env)
999 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
1002 /* Embedded.Processor Control */
1003 static int dbell2irq(target_ulong rb)
1005 int msg = rb & DBELL_TYPE_MASK;
1006 int irq = -1;
1008 switch (msg) {
1009 case DBELL_TYPE_DBELL:
1010 irq = PPC_INTERRUPT_DOORBELL;
1011 break;
1012 case DBELL_TYPE_DBELL_CRIT:
1013 irq = PPC_INTERRUPT_CDOORBELL;
1014 break;
1015 case DBELL_TYPE_G_DBELL:
1016 case DBELL_TYPE_G_DBELL_CRIT:
1017 case DBELL_TYPE_G_DBELL_MC:
1018 /* XXX implement */
1019 default:
1020 break;
1023 return irq;
1026 void helper_msgclr(CPUPPCState *env, target_ulong rb)
1028 int irq = dbell2irq(rb);
1030 if (irq < 0) {
1031 return;
1034 env->pending_interrupts &= ~(1 << irq);
1037 void helper_msgsnd(target_ulong rb)
1039 int irq = dbell2irq(rb);
1040 int pir = rb & DBELL_PIRTAG_MASK;
1041 CPUState *cs;
1043 if (irq < 0) {
1044 return;
1047 CPU_FOREACH(cs) {
1048 PowerPCCPU *cpu = POWERPC_CPU(cs);
1049 CPUPPCState *cenv = &cpu->env;
1051 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1052 cenv->pending_interrupts |= 1 << irq;
1053 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1057 #endif