xilinx: Inline usages of xilinx_intc_create()
[qemu.git] / target-ppc / excp_helper.c
blobd541929743572c22100a115cfbb4f24a1243a2c3
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 "helper.h"
22 #include "helper_regs.h"
24 //#define DEBUG_OP
25 //#define DEBUG_EXCEPTIONS
27 #ifdef DEBUG_EXCEPTIONS
28 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
29 #else
30 # define LOG_EXCP(...) do { } while (0)
31 #endif
33 /*****************************************************************************/
34 /* PowerPC Hypercall emulation */
36 void (*cpu_ppc_hypercall)(PowerPCCPU *);
38 /*****************************************************************************/
39 /* Exception processing */
40 #if defined(CONFIG_USER_ONLY)
41 void ppc_cpu_do_interrupt(CPUState *cs)
43 PowerPCCPU *cpu = POWERPC_CPU(cs);
44 CPUPPCState *env = &cpu->env;
46 env->exception_index = POWERPC_EXCP_NONE;
47 env->error_code = 0;
50 void ppc_hw_interrupt(CPUPPCState *env)
52 env->exception_index = POWERPC_EXCP_NONE;
53 env->error_code = 0;
55 #else /* defined(CONFIG_USER_ONLY) */
56 static inline void dump_syscall(CPUPPCState *env)
58 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
59 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
60 " nip=" TARGET_FMT_lx "\n",
61 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
62 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
63 ppc_dump_gpr(env, 6), env->nip);
66 /* Note that this function should be greatly optimized
67 * when called with a constant excp, from ppc_hw_interrupt
69 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
71 CPUPPCState *env = &cpu->env;
72 CPUState *cs;
73 target_ulong msr, new_msr, vector;
74 int srr0, srr1, asrr0, asrr1;
75 int lpes0, lpes1, lev;
77 if (0) {
78 /* XXX: find a suitable condition to enable the hypervisor mode */
79 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
80 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
81 } else {
82 /* Those values ensure we won't enter the hypervisor mode */
83 lpes0 = 0;
84 lpes1 = 1;
87 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
88 " => %08x (%02x)\n", env->nip, excp, env->error_code);
90 /* new srr1 value excluding must-be-zero bits */
91 if (excp_model == POWERPC_EXCP_BOOKE) {
92 msr = env->msr;
93 } else {
94 msr = env->msr & ~0x783f0000ULL;
97 /* new interrupt handler msr */
98 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
100 /* target registers */
101 srr0 = SPR_SRR0;
102 srr1 = SPR_SRR1;
103 asrr0 = -1;
104 asrr1 = -1;
106 switch (excp) {
107 case POWERPC_EXCP_NONE:
108 /* Should never happen */
109 return;
110 case POWERPC_EXCP_CRITICAL: /* Critical input */
111 switch (excp_model) {
112 case POWERPC_EXCP_40x:
113 srr0 = SPR_40x_SRR2;
114 srr1 = SPR_40x_SRR3;
115 break;
116 case POWERPC_EXCP_BOOKE:
117 srr0 = SPR_BOOKE_CSRR0;
118 srr1 = SPR_BOOKE_CSRR1;
119 break;
120 case POWERPC_EXCP_G2:
121 break;
122 default:
123 goto excp_invalid;
125 goto store_next;
126 case POWERPC_EXCP_MCHECK: /* Machine check exception */
127 if (msr_me == 0) {
128 /* Machine check exception is not enabled.
129 * Enter checkstop state.
131 if (qemu_log_enabled()) {
132 qemu_log("Machine check while not allowed. "
133 "Entering checkstop state\n");
134 } else {
135 fprintf(stderr, "Machine check while not allowed. "
136 "Entering checkstop state\n");
138 cs = CPU(cpu);
139 cs->halted = 1;
140 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
142 if (0) {
143 /* XXX: find a suitable condition to enable the hypervisor mode */
144 new_msr |= (target_ulong)MSR_HVB;
147 /* machine check exceptions don't have ME set */
148 new_msr &= ~((target_ulong)1 << MSR_ME);
150 /* XXX: should also have something loaded in DAR / DSISR */
151 switch (excp_model) {
152 case POWERPC_EXCP_40x:
153 srr0 = SPR_40x_SRR2;
154 srr1 = SPR_40x_SRR3;
155 break;
156 case POWERPC_EXCP_BOOKE:
157 /* FIXME: choose one or the other based on CPU type */
158 srr0 = SPR_BOOKE_MCSRR0;
159 srr1 = SPR_BOOKE_MCSRR1;
160 asrr0 = SPR_BOOKE_CSRR0;
161 asrr1 = SPR_BOOKE_CSRR1;
162 break;
163 default:
164 break;
166 goto store_next;
167 case POWERPC_EXCP_DSI: /* Data storage exception */
168 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
169 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
170 if (lpes1 == 0) {
171 new_msr |= (target_ulong)MSR_HVB;
173 goto store_next;
174 case POWERPC_EXCP_ISI: /* Instruction storage exception */
175 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
176 "\n", msr, env->nip);
177 if (lpes1 == 0) {
178 new_msr |= (target_ulong)MSR_HVB;
180 msr |= env->error_code;
181 goto store_next;
182 case POWERPC_EXCP_EXTERNAL: /* External input */
183 cs = CPU(cpu);
185 if (lpes0 == 1) {
186 new_msr |= (target_ulong)MSR_HVB;
188 if (env->mpic_proxy) {
189 /* IACK the IRQ on delivery */
190 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
192 goto store_next;
193 case POWERPC_EXCP_ALIGN: /* Alignment exception */
194 if (lpes1 == 0) {
195 new_msr |= (target_ulong)MSR_HVB;
197 /* XXX: this is false */
198 /* Get rS/rD and rA from faulting opcode */
199 env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
200 & 0x03FF0000) >> 16;
201 goto store_current;
202 case POWERPC_EXCP_PROGRAM: /* Program exception */
203 switch (env->error_code & ~0xF) {
204 case POWERPC_EXCP_FP:
205 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
206 LOG_EXCP("Ignore floating point exception\n");
207 env->exception_index = POWERPC_EXCP_NONE;
208 env->error_code = 0;
209 return;
211 if (lpes1 == 0) {
212 new_msr |= (target_ulong)MSR_HVB;
214 msr |= 0x00100000;
215 if (msr_fe0 == msr_fe1) {
216 goto store_next;
218 msr |= 0x00010000;
219 break;
220 case POWERPC_EXCP_INVAL:
221 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
222 if (lpes1 == 0) {
223 new_msr |= (target_ulong)MSR_HVB;
225 msr |= 0x00080000;
226 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
227 break;
228 case POWERPC_EXCP_PRIV:
229 if (lpes1 == 0) {
230 new_msr |= (target_ulong)MSR_HVB;
232 msr |= 0x00040000;
233 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
234 break;
235 case POWERPC_EXCP_TRAP:
236 if (lpes1 == 0) {
237 new_msr |= (target_ulong)MSR_HVB;
239 msr |= 0x00020000;
240 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
241 break;
242 default:
243 /* Should never occur */
244 cpu_abort(env, "Invalid program exception %d. Aborting\n",
245 env->error_code);
246 break;
248 goto store_current;
249 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
250 if (lpes1 == 0) {
251 new_msr |= (target_ulong)MSR_HVB;
253 goto store_current;
254 case POWERPC_EXCP_SYSCALL: /* System call exception */
255 dump_syscall(env);
256 lev = env->error_code;
257 if ((lev == 1) && cpu_ppc_hypercall) {
258 cpu_ppc_hypercall(cpu);
259 return;
261 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
262 new_msr |= (target_ulong)MSR_HVB;
264 goto store_next;
265 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
266 goto store_current;
267 case POWERPC_EXCP_DECR: /* Decrementer exception */
268 if (lpes1 == 0) {
269 new_msr |= (target_ulong)MSR_HVB;
271 goto store_next;
272 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
273 /* FIT on 4xx */
274 LOG_EXCP("FIT exception\n");
275 goto store_next;
276 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
277 LOG_EXCP("WDT exception\n");
278 switch (excp_model) {
279 case POWERPC_EXCP_BOOKE:
280 srr0 = SPR_BOOKE_CSRR0;
281 srr1 = SPR_BOOKE_CSRR1;
282 break;
283 default:
284 break;
286 goto store_next;
287 case POWERPC_EXCP_DTLB: /* Data TLB error */
288 goto store_next;
289 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
290 goto store_next;
291 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
292 switch (excp_model) {
293 case POWERPC_EXCP_BOOKE:
294 /* FIXME: choose one or the other based on CPU type */
295 srr0 = SPR_BOOKE_DSRR0;
296 srr1 = SPR_BOOKE_DSRR1;
297 asrr0 = SPR_BOOKE_CSRR0;
298 asrr1 = SPR_BOOKE_CSRR1;
299 break;
300 default:
301 break;
303 /* XXX: TODO */
304 cpu_abort(env, "Debug exception is not implemented yet !\n");
305 goto store_next;
306 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
307 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
308 goto store_current;
309 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
310 /* XXX: TODO */
311 cpu_abort(env, "Embedded floating point data exception "
312 "is not implemented yet !\n");
313 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
314 goto store_next;
315 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
316 /* XXX: TODO */
317 cpu_abort(env, "Embedded floating point round exception "
318 "is not implemented yet !\n");
319 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
320 goto store_next;
321 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
322 /* XXX: TODO */
323 cpu_abort(env,
324 "Performance counter exception is not implemented yet !\n");
325 goto store_next;
326 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
327 goto store_next;
328 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
329 srr0 = SPR_BOOKE_CSRR0;
330 srr1 = SPR_BOOKE_CSRR1;
331 goto store_next;
332 case POWERPC_EXCP_RESET: /* System reset exception */
333 if (msr_pow) {
334 /* indicate that we resumed from power save mode */
335 msr |= 0x10000;
336 } else {
337 new_msr &= ~((target_ulong)1 << MSR_ME);
340 if (0) {
341 /* XXX: find a suitable condition to enable the hypervisor mode */
342 new_msr |= (target_ulong)MSR_HVB;
344 goto store_next;
345 case POWERPC_EXCP_DSEG: /* Data segment exception */
346 if (lpes1 == 0) {
347 new_msr |= (target_ulong)MSR_HVB;
349 goto store_next;
350 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
351 if (lpes1 == 0) {
352 new_msr |= (target_ulong)MSR_HVB;
354 goto store_next;
355 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
356 srr0 = SPR_HSRR0;
357 srr1 = SPR_HSRR1;
358 new_msr |= (target_ulong)MSR_HVB;
359 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
360 goto store_next;
361 case POWERPC_EXCP_TRACE: /* Trace exception */
362 if (lpes1 == 0) {
363 new_msr |= (target_ulong)MSR_HVB;
365 goto store_next;
366 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
367 srr0 = SPR_HSRR0;
368 srr1 = SPR_HSRR1;
369 new_msr |= (target_ulong)MSR_HVB;
370 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
371 goto store_next;
372 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
373 srr0 = SPR_HSRR0;
374 srr1 = SPR_HSRR1;
375 new_msr |= (target_ulong)MSR_HVB;
376 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
377 goto store_next;
378 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
379 srr0 = SPR_HSRR0;
380 srr1 = SPR_HSRR1;
381 new_msr |= (target_ulong)MSR_HVB;
382 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
383 goto store_next;
384 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
385 srr0 = SPR_HSRR0;
386 srr1 = SPR_HSRR1;
387 new_msr |= (target_ulong)MSR_HVB;
388 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
389 goto store_next;
390 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
391 if (lpes1 == 0) {
392 new_msr |= (target_ulong)MSR_HVB;
394 goto store_current;
395 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
396 if (lpes1 == 0) {
397 new_msr |= (target_ulong)MSR_HVB;
399 goto store_current;
400 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
401 LOG_EXCP("PIT exception\n");
402 goto store_next;
403 case POWERPC_EXCP_IO: /* IO error exception */
404 /* XXX: TODO */
405 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
406 goto store_next;
407 case POWERPC_EXCP_RUNM: /* Run mode exception */
408 /* XXX: TODO */
409 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
410 goto store_next;
411 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
412 /* XXX: TODO */
413 cpu_abort(env, "602 emulation trap exception "
414 "is not implemented yet !\n");
415 goto store_next;
416 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
417 if (lpes1 == 0) { /* XXX: check this */
418 new_msr |= (target_ulong)MSR_HVB;
420 switch (excp_model) {
421 case POWERPC_EXCP_602:
422 case POWERPC_EXCP_603:
423 case POWERPC_EXCP_603E:
424 case POWERPC_EXCP_G2:
425 goto tlb_miss_tgpr;
426 case POWERPC_EXCP_7x5:
427 goto tlb_miss;
428 case POWERPC_EXCP_74xx:
429 goto tlb_miss_74xx;
430 default:
431 cpu_abort(env, "Invalid instruction TLB miss exception\n");
432 break;
434 break;
435 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
436 if (lpes1 == 0) { /* XXX: check this */
437 new_msr |= (target_ulong)MSR_HVB;
439 switch (excp_model) {
440 case POWERPC_EXCP_602:
441 case POWERPC_EXCP_603:
442 case POWERPC_EXCP_603E:
443 case POWERPC_EXCP_G2:
444 goto tlb_miss_tgpr;
445 case POWERPC_EXCP_7x5:
446 goto tlb_miss;
447 case POWERPC_EXCP_74xx:
448 goto tlb_miss_74xx;
449 default:
450 cpu_abort(env, "Invalid data load TLB miss exception\n");
451 break;
453 break;
454 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
455 if (lpes1 == 0) { /* XXX: check this */
456 new_msr |= (target_ulong)MSR_HVB;
458 switch (excp_model) {
459 case POWERPC_EXCP_602:
460 case POWERPC_EXCP_603:
461 case POWERPC_EXCP_603E:
462 case POWERPC_EXCP_G2:
463 tlb_miss_tgpr:
464 /* Swap temporary saved registers with GPRs */
465 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
466 new_msr |= (target_ulong)1 << MSR_TGPR;
467 hreg_swap_gpr_tgpr(env);
469 goto tlb_miss;
470 case POWERPC_EXCP_7x5:
471 tlb_miss:
472 #if defined(DEBUG_SOFTWARE_TLB)
473 if (qemu_log_enabled()) {
474 const char *es;
475 target_ulong *miss, *cmp;
476 int en;
478 if (excp == POWERPC_EXCP_IFTLB) {
479 es = "I";
480 en = 'I';
481 miss = &env->spr[SPR_IMISS];
482 cmp = &env->spr[SPR_ICMP];
483 } else {
484 if (excp == POWERPC_EXCP_DLTLB) {
485 es = "DL";
486 } else {
487 es = "DS";
489 en = 'D';
490 miss = &env->spr[SPR_DMISS];
491 cmp = &env->spr[SPR_DCMP];
493 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
494 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
495 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
496 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
497 env->error_code);
499 #endif
500 msr |= env->crf[0] << 28;
501 msr |= env->error_code; /* key, D/I, S/L bits */
502 /* Set way using a LRU mechanism */
503 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
504 break;
505 case POWERPC_EXCP_74xx:
506 tlb_miss_74xx:
507 #if defined(DEBUG_SOFTWARE_TLB)
508 if (qemu_log_enabled()) {
509 const char *es;
510 target_ulong *miss, *cmp;
511 int en;
513 if (excp == POWERPC_EXCP_IFTLB) {
514 es = "I";
515 en = 'I';
516 miss = &env->spr[SPR_TLBMISS];
517 cmp = &env->spr[SPR_PTEHI];
518 } else {
519 if (excp == POWERPC_EXCP_DLTLB) {
520 es = "DL";
521 } else {
522 es = "DS";
524 en = 'D';
525 miss = &env->spr[SPR_TLBMISS];
526 cmp = &env->spr[SPR_PTEHI];
528 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
529 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
530 env->error_code);
532 #endif
533 msr |= env->error_code; /* key bit */
534 break;
535 default:
536 cpu_abort(env, "Invalid data store TLB miss exception\n");
537 break;
539 goto store_next;
540 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
541 /* XXX: TODO */
542 cpu_abort(env, "Floating point assist exception "
543 "is not implemented yet !\n");
544 goto store_next;
545 case POWERPC_EXCP_DABR: /* Data address breakpoint */
546 /* XXX: TODO */
547 cpu_abort(env, "DABR exception is not implemented yet !\n");
548 goto store_next;
549 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
550 /* XXX: TODO */
551 cpu_abort(env, "IABR exception is not implemented yet !\n");
552 goto store_next;
553 case POWERPC_EXCP_SMI: /* System management interrupt */
554 /* XXX: TODO */
555 cpu_abort(env, "SMI exception is not implemented yet !\n");
556 goto store_next;
557 case POWERPC_EXCP_THERM: /* Thermal interrupt */
558 /* XXX: TODO */
559 cpu_abort(env, "Thermal management exception "
560 "is not implemented yet !\n");
561 goto store_next;
562 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
563 if (lpes1 == 0) {
564 new_msr |= (target_ulong)MSR_HVB;
566 /* XXX: TODO */
567 cpu_abort(env,
568 "Performance counter exception is not implemented yet !\n");
569 goto store_next;
570 case POWERPC_EXCP_VPUA: /* Vector assist exception */
571 /* XXX: TODO */
572 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
573 goto store_next;
574 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
575 /* XXX: TODO */
576 cpu_abort(env,
577 "970 soft-patch exception is not implemented yet !\n");
578 goto store_next;
579 case POWERPC_EXCP_MAINT: /* Maintenance exception */
580 /* XXX: TODO */
581 cpu_abort(env,
582 "970 maintenance exception is not implemented yet !\n");
583 goto store_next;
584 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
585 /* XXX: TODO */
586 cpu_abort(env, "Maskable external exception "
587 "is not implemented yet !\n");
588 goto store_next;
589 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
590 /* XXX: TODO */
591 cpu_abort(env, "Non maskable external exception "
592 "is not implemented yet !\n");
593 goto store_next;
594 default:
595 excp_invalid:
596 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
597 break;
598 store_current:
599 /* save current instruction location */
600 env->spr[srr0] = env->nip - 4;
601 break;
602 store_next:
603 /* save next instruction location */
604 env->spr[srr0] = env->nip;
605 break;
607 /* Save MSR */
608 env->spr[srr1] = msr;
609 /* If any alternate SRR register are defined, duplicate saved values */
610 if (asrr0 != -1) {
611 env->spr[asrr0] = env->spr[srr0];
613 if (asrr1 != -1) {
614 env->spr[asrr1] = env->spr[srr1];
616 /* If we disactivated any translation, flush TLBs */
617 if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
618 tlb_flush(env, 1);
621 #ifdef TARGET_PPC64
622 if (excp_model == POWERPC_EXCP_POWER7) {
623 if (env->spr[SPR_LPCR] & LPCR_ILE) {
624 new_msr |= (target_ulong)1 << MSR_LE;
626 } else if (msr_ile) {
627 new_msr |= (target_ulong)1 << MSR_LE;
629 #else
630 if (msr_ile) {
631 new_msr |= (target_ulong)1 << MSR_LE;
633 #endif
635 /* Jump to handler */
636 vector = env->excp_vectors[excp];
637 if (vector == (target_ulong)-1ULL) {
638 cpu_abort(env, "Raised an exception without defined vector %d\n",
639 excp);
641 vector |= env->excp_prefix;
642 #if defined(TARGET_PPC64)
643 if (excp_model == POWERPC_EXCP_BOOKE) {
644 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
645 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
646 new_msr |= (target_ulong)1 << MSR_CM;
647 } else {
648 vector = (uint32_t)vector;
650 } else {
651 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
652 vector = (uint32_t)vector;
653 } else {
654 new_msr |= (target_ulong)1 << MSR_SF;
657 #endif
658 /* XXX: we don't use hreg_store_msr here as already have treated
659 * any special case that could occur. Just store MSR and update hflags
661 env->msr = new_msr & env->msr_mask;
662 hreg_compute_hflags(env);
663 env->nip = vector;
664 /* Reset exception state */
665 env->exception_index = POWERPC_EXCP_NONE;
666 env->error_code = 0;
668 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
669 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
670 /* XXX: The BookE changes address space when switching modes,
671 we should probably implement that as different MMU indexes,
672 but for the moment we do it the slow way and flush all. */
673 tlb_flush(env, 1);
677 void ppc_cpu_do_interrupt(CPUState *cs)
679 PowerPCCPU *cpu = POWERPC_CPU(cs);
680 CPUPPCState *env = &cpu->env;
682 powerpc_excp(cpu, env->excp_model, env->exception_index);
685 void ppc_hw_interrupt(CPUPPCState *env)
687 PowerPCCPU *cpu = ppc_env_get_cpu(env);
688 int hdice;
689 #if 0
690 CPUState *cs = CPU(cpu);
692 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
693 __func__, env, env->pending_interrupts,
694 cs->interrupt_request, (int)msr_me, (int)msr_ee);
695 #endif
696 /* External reset */
697 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
698 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
699 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
700 return;
702 /* Machine check exception */
703 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
704 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
705 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
706 return;
708 #if 0 /* TODO */
709 /* External debug exception */
710 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
711 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
712 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
713 return;
715 #endif
716 if (0) {
717 /* XXX: find a suitable condition to enable the hypervisor mode */
718 hdice = env->spr[SPR_LPCR] & 1;
719 } else {
720 hdice = 0;
722 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
723 /* Hypervisor decrementer exception */
724 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
725 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
726 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
727 return;
730 if (msr_ce != 0) {
731 /* External critical interrupt */
732 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
733 /* Taking a critical external interrupt does not clear the external
734 * critical interrupt status
736 #if 0
737 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
738 #endif
739 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
740 return;
743 if (msr_ee != 0) {
744 /* Watchdog timer on embedded PowerPC */
745 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
746 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
747 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
748 return;
750 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
751 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
752 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
753 return;
755 /* Fixed interval timer on embedded PowerPC */
756 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
757 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
758 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
759 return;
761 /* Programmable interval timer on embedded PowerPC */
762 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
763 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
764 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
765 return;
767 /* Decrementer exception */
768 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
769 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
770 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
771 return;
773 /* External interrupt */
774 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
775 /* Taking an external interrupt does not clear the external
776 * interrupt status
778 #if 0
779 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
780 #endif
781 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
782 return;
784 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
785 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
786 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
787 return;
789 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
790 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
791 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
792 return;
794 /* Thermal interrupt */
795 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
796 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
797 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
798 return;
802 #endif /* !CONFIG_USER_ONLY */
804 #if defined(DEBUG_OP)
805 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
807 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
808 TARGET_FMT_lx "\n", RA, msr);
810 #endif
812 /*****************************************************************************/
813 /* Exceptions processing helpers */
815 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
816 uint32_t error_code)
818 #if 0
819 printf("Raise exception %3x code : %d\n", exception, error_code);
820 #endif
821 env->exception_index = exception;
822 env->error_code = error_code;
823 cpu_loop_exit(env);
826 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
828 helper_raise_exception_err(env, exception, 0);
831 #if !defined(CONFIG_USER_ONLY)
832 void helper_store_msr(CPUPPCState *env, target_ulong val)
834 CPUState *cs;
836 val = hreg_store_msr(env, val, 0);
837 if (val != 0) {
838 cs = CPU(ppc_env_get_cpu(env));
839 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
840 helper_raise_exception(env, val);
844 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
845 target_ulong msrm, int keep_msrh)
847 CPUState *cs = CPU(ppc_env_get_cpu(env));
849 #if defined(TARGET_PPC64)
850 if (msr_is_64bit(env, msr)) {
851 nip = (uint64_t)nip;
852 msr &= (uint64_t)msrm;
853 } else {
854 nip = (uint32_t)nip;
855 msr = (uint32_t)(msr & msrm);
856 if (keep_msrh) {
857 msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
860 #else
861 nip = (uint32_t)nip;
862 msr &= (uint32_t)msrm;
863 #endif
864 /* XXX: beware: this is false if VLE is supported */
865 env->nip = nip & ~((target_ulong)0x00000003);
866 hreg_store_msr(env, msr, 1);
867 #if defined(DEBUG_OP)
868 cpu_dump_rfi(env->nip, env->msr);
869 #endif
870 /* No need to raise an exception here,
871 * as rfi is always the last insn of a TB
873 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
876 void helper_rfi(CPUPPCState *env)
878 if (env->excp_model == POWERPC_EXCP_BOOKE) {
879 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
880 ~((target_ulong)0), 0);
881 } else {
882 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
883 ~((target_ulong)0x783F0000), 1);
887 #if defined(TARGET_PPC64)
888 void helper_rfid(CPUPPCState *env)
890 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
891 ~((target_ulong)0x783F0000), 0);
894 void helper_hrfid(CPUPPCState *env)
896 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
897 ~((target_ulong)0x783F0000), 0);
899 #endif
901 /*****************************************************************************/
902 /* Embedded PowerPC specific helpers */
903 void helper_40x_rfci(CPUPPCState *env)
905 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
906 ~((target_ulong)0xFFFF0000), 0);
909 void helper_rfci(CPUPPCState *env)
911 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
912 ~((target_ulong)0), 0);
915 void helper_rfdi(CPUPPCState *env)
917 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
918 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
919 ~((target_ulong)0), 0);
922 void helper_rfmci(CPUPPCState *env)
924 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
925 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
926 ~((target_ulong)0), 0);
928 #endif
930 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
931 uint32_t flags)
933 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
934 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
935 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
936 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
937 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
938 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
939 POWERPC_EXCP_TRAP);
943 #if defined(TARGET_PPC64)
944 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
945 uint32_t flags)
947 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
948 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
949 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
950 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
951 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
952 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
953 POWERPC_EXCP_TRAP);
956 #endif
958 #if !defined(CONFIG_USER_ONLY)
959 /*****************************************************************************/
960 /* PowerPC 601 specific instructions (POWER bridge) */
962 void helper_rfsvc(CPUPPCState *env)
964 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
967 /* Embedded.Processor Control */
968 static int dbell2irq(target_ulong rb)
970 int msg = rb & DBELL_TYPE_MASK;
971 int irq = -1;
973 switch (msg) {
974 case DBELL_TYPE_DBELL:
975 irq = PPC_INTERRUPT_DOORBELL;
976 break;
977 case DBELL_TYPE_DBELL_CRIT:
978 irq = PPC_INTERRUPT_CDOORBELL;
979 break;
980 case DBELL_TYPE_G_DBELL:
981 case DBELL_TYPE_G_DBELL_CRIT:
982 case DBELL_TYPE_G_DBELL_MC:
983 /* XXX implement */
984 default:
985 break;
988 return irq;
991 void helper_msgclr(CPUPPCState *env, target_ulong rb)
993 int irq = dbell2irq(rb);
995 if (irq < 0) {
996 return;
999 env->pending_interrupts &= ~(1 << irq);
1002 void helper_msgsnd(target_ulong rb)
1004 int irq = dbell2irq(rb);
1005 int pir = rb & DBELL_PIRTAG_MASK;
1006 CPUState *cs;
1008 if (irq < 0) {
1009 return;
1012 CPU_FOREACH(cs) {
1013 PowerPCCPU *cpu = POWERPC_CPU(cs);
1014 CPUPPCState *cenv = &cpu->env;
1016 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1017 cenv->pending_interrupts |= 1 << irq;
1018 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1022 #endif