configure: unset interfering variables
[qemu.git] / target-ppc / excp_helper.c
blob7dfc52d1598da26fb235cd70f6f975ffe1470002
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 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 if (qemu_log_enabled()) {
135 qemu_log("Machine check while not allowed. "
136 "Entering checkstop state\n");
137 } else {
138 fprintf(stderr, "Machine check while not allowed. "
139 "Entering checkstop state\n");
141 cs->halted = 1;
142 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
144 if (0) {
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:
155 srr0 = SPR_40x_SRR2;
156 srr1 = SPR_40x_SRR3;
157 break;
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;
164 break;
165 default:
166 break;
168 goto store_next;
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]);
172 if (lpes1 == 0) {
173 new_msr |= (target_ulong)MSR_HVB;
175 goto store_next;
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);
179 if (lpes1 == 0) {
180 new_msr |= (target_ulong)MSR_HVB;
182 msr |= env->error_code;
183 goto store_next;
184 case POWERPC_EXCP_EXTERNAL: /* External input */
185 cs = CPU(cpu);
187 if (lpes0 == 1) {
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);
194 goto store_next;
195 case POWERPC_EXCP_ALIGN: /* Alignment exception */
196 if (lpes1 == 0) {
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))
202 & 0x03FF0000) >> 16;
203 goto store_current;
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;
210 env->error_code = 0;
211 return;
213 if (lpes1 == 0) {
214 new_msr |= (target_ulong)MSR_HVB;
216 msr |= 0x00100000;
217 if (msr_fe0 == msr_fe1) {
218 goto store_next;
220 msr |= 0x00010000;
221 break;
222 case POWERPC_EXCP_INVAL:
223 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
224 if (lpes1 == 0) {
225 new_msr |= (target_ulong)MSR_HVB;
227 msr |= 0x00080000;
228 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
229 break;
230 case POWERPC_EXCP_PRIV:
231 if (lpes1 == 0) {
232 new_msr |= (target_ulong)MSR_HVB;
234 msr |= 0x00040000;
235 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
236 break;
237 case POWERPC_EXCP_TRAP:
238 if (lpes1 == 0) {
239 new_msr |= (target_ulong)MSR_HVB;
241 msr |= 0x00020000;
242 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
243 break;
244 default:
245 /* Should never occur */
246 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
247 env->error_code);
248 break;
250 goto store_current;
251 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
252 if (lpes1 == 0) {
253 new_msr |= (target_ulong)MSR_HVB;
255 goto store_current;
256 case POWERPC_EXCP_SYSCALL: /* System call exception */
257 dump_syscall(env);
258 lev = env->error_code;
259 if ((lev == 1) && cpu_ppc_hypercall) {
260 cpu_ppc_hypercall(cpu);
261 return;
263 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
264 new_msr |= (target_ulong)MSR_HVB;
266 goto store_next;
267 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
268 goto store_current;
269 case POWERPC_EXCP_DECR: /* Decrementer exception */
270 if (lpes1 == 0) {
271 new_msr |= (target_ulong)MSR_HVB;
273 goto store_next;
274 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
275 /* FIT on 4xx */
276 LOG_EXCP("FIT exception\n");
277 goto store_next;
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;
284 break;
285 default:
286 break;
288 goto store_next;
289 case POWERPC_EXCP_DTLB: /* Data TLB error */
290 goto store_next;
291 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
292 goto store_next;
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;
301 break;
302 default:
303 break;
305 /* XXX: TODO */
306 cpu_abort(cs, "Debug exception is not implemented yet !\n");
307 goto store_next;
308 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
309 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
310 goto store_current;
311 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
312 /* XXX: TODO */
313 cpu_abort(cs, "Embedded floating point data exception "
314 "is not implemented yet !\n");
315 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
316 goto store_next;
317 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
318 /* XXX: TODO */
319 cpu_abort(cs, "Embedded floating point round exception "
320 "is not implemented yet !\n");
321 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
322 goto store_next;
323 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
324 /* XXX: TODO */
325 cpu_abort(cs,
326 "Performance counter exception is not implemented yet !\n");
327 goto store_next;
328 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
329 goto store_next;
330 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
331 srr0 = SPR_BOOKE_CSRR0;
332 srr1 = SPR_BOOKE_CSRR1;
333 goto store_next;
334 case POWERPC_EXCP_RESET: /* System reset exception */
335 if (msr_pow) {
336 /* indicate that we resumed from power save mode */
337 msr |= 0x10000;
338 } else {
339 new_msr &= ~((target_ulong)1 << MSR_ME);
342 if (0) {
343 /* XXX: find a suitable condition to enable the hypervisor mode */
344 new_msr |= (target_ulong)MSR_HVB;
346 goto store_next;
347 case POWERPC_EXCP_DSEG: /* Data segment exception */
348 if (lpes1 == 0) {
349 new_msr |= (target_ulong)MSR_HVB;
351 goto store_next;
352 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
353 if (lpes1 == 0) {
354 new_msr |= (target_ulong)MSR_HVB;
356 goto store_next;
357 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
358 srr0 = SPR_HSRR0;
359 srr1 = SPR_HSRR1;
360 new_msr |= (target_ulong)MSR_HVB;
361 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
362 goto store_next;
363 case POWERPC_EXCP_TRACE: /* Trace exception */
364 if (lpes1 == 0) {
365 new_msr |= (target_ulong)MSR_HVB;
367 goto store_next;
368 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
369 srr0 = SPR_HSRR0;
370 srr1 = SPR_HSRR1;
371 new_msr |= (target_ulong)MSR_HVB;
372 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
373 goto store_next;
374 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
375 srr0 = SPR_HSRR0;
376 srr1 = SPR_HSRR1;
377 new_msr |= (target_ulong)MSR_HVB;
378 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
379 goto store_next;
380 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
381 srr0 = SPR_HSRR0;
382 srr1 = SPR_HSRR1;
383 new_msr |= (target_ulong)MSR_HVB;
384 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
385 goto store_next;
386 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
387 srr0 = SPR_HSRR0;
388 srr1 = SPR_HSRR1;
389 new_msr |= (target_ulong)MSR_HVB;
390 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
391 goto store_next;
392 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
393 if (lpes1 == 0) {
394 new_msr |= (target_ulong)MSR_HVB;
396 goto store_current;
397 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
398 if (lpes1 == 0) {
399 new_msr |= (target_ulong)MSR_HVB;
401 goto store_current;
402 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
403 LOG_EXCP("PIT exception\n");
404 goto store_next;
405 case POWERPC_EXCP_IO: /* IO error exception */
406 /* XXX: TODO */
407 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
408 goto store_next;
409 case POWERPC_EXCP_RUNM: /* Run mode exception */
410 /* XXX: TODO */
411 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
412 goto store_next;
413 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
414 /* XXX: TODO */
415 cpu_abort(cs, "602 emulation trap exception "
416 "is not implemented yet !\n");
417 goto store_next;
418 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
419 if (lpes1 == 0) { /* XXX: check this */
420 new_msr |= (target_ulong)MSR_HVB;
422 switch (excp_model) {
423 case POWERPC_EXCP_602:
424 case POWERPC_EXCP_603:
425 case POWERPC_EXCP_603E:
426 case POWERPC_EXCP_G2:
427 goto tlb_miss_tgpr;
428 case POWERPC_EXCP_7x5:
429 goto tlb_miss;
430 case POWERPC_EXCP_74xx:
431 goto tlb_miss_74xx;
432 default:
433 cpu_abort(cs, "Invalid instruction TLB miss exception\n");
434 break;
436 break;
437 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
438 if (lpes1 == 0) { /* XXX: check this */
439 new_msr |= (target_ulong)MSR_HVB;
441 switch (excp_model) {
442 case POWERPC_EXCP_602:
443 case POWERPC_EXCP_603:
444 case POWERPC_EXCP_603E:
445 case POWERPC_EXCP_G2:
446 goto tlb_miss_tgpr;
447 case POWERPC_EXCP_7x5:
448 goto tlb_miss;
449 case POWERPC_EXCP_74xx:
450 goto tlb_miss_74xx;
451 default:
452 cpu_abort(cs, "Invalid data load TLB miss exception\n");
453 break;
455 break;
456 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
457 if (lpes1 == 0) { /* XXX: check this */
458 new_msr |= (target_ulong)MSR_HVB;
460 switch (excp_model) {
461 case POWERPC_EXCP_602:
462 case POWERPC_EXCP_603:
463 case POWERPC_EXCP_603E:
464 case POWERPC_EXCP_G2:
465 tlb_miss_tgpr:
466 /* Swap temporary saved registers with GPRs */
467 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
468 new_msr |= (target_ulong)1 << MSR_TGPR;
469 hreg_swap_gpr_tgpr(env);
471 goto tlb_miss;
472 case POWERPC_EXCP_7x5:
473 tlb_miss:
474 #if defined(DEBUG_SOFTWARE_TLB)
475 if (qemu_log_enabled()) {
476 const char *es;
477 target_ulong *miss, *cmp;
478 int en;
480 if (excp == POWERPC_EXCP_IFTLB) {
481 es = "I";
482 en = 'I';
483 miss = &env->spr[SPR_IMISS];
484 cmp = &env->spr[SPR_ICMP];
485 } else {
486 if (excp == POWERPC_EXCP_DLTLB) {
487 es = "DL";
488 } else {
489 es = "DS";
491 en = 'D';
492 miss = &env->spr[SPR_DMISS];
493 cmp = &env->spr[SPR_DCMP];
495 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
496 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
497 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
498 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
499 env->error_code);
501 #endif
502 msr |= env->crf[0] << 28;
503 msr |= env->error_code; /* key, D/I, S/L bits */
504 /* Set way using a LRU mechanism */
505 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
506 break;
507 case POWERPC_EXCP_74xx:
508 tlb_miss_74xx:
509 #if defined(DEBUG_SOFTWARE_TLB)
510 if (qemu_log_enabled()) {
511 const char *es;
512 target_ulong *miss, *cmp;
513 int en;
515 if (excp == POWERPC_EXCP_IFTLB) {
516 es = "I";
517 en = 'I';
518 miss = &env->spr[SPR_TLBMISS];
519 cmp = &env->spr[SPR_PTEHI];
520 } else {
521 if (excp == POWERPC_EXCP_DLTLB) {
522 es = "DL";
523 } else {
524 es = "DS";
526 en = 'D';
527 miss = &env->spr[SPR_TLBMISS];
528 cmp = &env->spr[SPR_PTEHI];
530 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
531 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
532 env->error_code);
534 #endif
535 msr |= env->error_code; /* key bit */
536 break;
537 default:
538 cpu_abort(cs, "Invalid data store TLB miss exception\n");
539 break;
541 goto store_next;
542 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
543 /* XXX: TODO */
544 cpu_abort(cs, "Floating point assist exception "
545 "is not implemented yet !\n");
546 goto store_next;
547 case POWERPC_EXCP_DABR: /* Data address breakpoint */
548 /* XXX: TODO */
549 cpu_abort(cs, "DABR exception is not implemented yet !\n");
550 goto store_next;
551 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
552 /* XXX: TODO */
553 cpu_abort(cs, "IABR exception is not implemented yet !\n");
554 goto store_next;
555 case POWERPC_EXCP_SMI: /* System management interrupt */
556 /* XXX: TODO */
557 cpu_abort(cs, "SMI exception is not implemented yet !\n");
558 goto store_next;
559 case POWERPC_EXCP_THERM: /* Thermal interrupt */
560 /* XXX: TODO */
561 cpu_abort(cs, "Thermal management exception "
562 "is not implemented yet !\n");
563 goto store_next;
564 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
565 if (lpes1 == 0) {
566 new_msr |= (target_ulong)MSR_HVB;
568 /* XXX: TODO */
569 cpu_abort(cs,
570 "Performance counter exception is not implemented yet !\n");
571 goto store_next;
572 case POWERPC_EXCP_VPUA: /* Vector assist exception */
573 /* XXX: TODO */
574 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
575 goto store_next;
576 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
577 /* XXX: TODO */
578 cpu_abort(cs,
579 "970 soft-patch exception is not implemented yet !\n");
580 goto store_next;
581 case POWERPC_EXCP_MAINT: /* Maintenance exception */
582 /* XXX: TODO */
583 cpu_abort(cs,
584 "970 maintenance exception is not implemented yet !\n");
585 goto store_next;
586 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
587 /* XXX: TODO */
588 cpu_abort(cs, "Maskable external exception "
589 "is not implemented yet !\n");
590 goto store_next;
591 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
592 /* XXX: TODO */
593 cpu_abort(cs, "Non maskable external exception "
594 "is not implemented yet !\n");
595 goto store_next;
596 default:
597 excp_invalid:
598 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
599 break;
600 store_current:
601 /* save current instruction location */
602 env->spr[srr0] = env->nip - 4;
603 break;
604 store_next:
605 /* save next instruction location */
606 env->spr[srr0] = env->nip;
607 break;
609 /* Save MSR */
610 env->spr[srr1] = msr;
611 /* If any alternate SRR register are defined, duplicate saved values */
612 if (asrr0 != -1) {
613 env->spr[asrr0] = env->spr[srr0];
615 if (asrr1 != -1) {
616 env->spr[asrr1] = env->spr[srr1];
618 /* If we disactivated any translation, flush TLBs */
619 if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
620 tlb_flush(cs, 1);
623 #ifdef TARGET_PPC64
624 if (excp_model == POWERPC_EXCP_POWER7) {
625 if (env->spr[SPR_LPCR] & LPCR_ILE) {
626 new_msr |= (target_ulong)1 << MSR_LE;
628 } else if (msr_ile) {
629 new_msr |= (target_ulong)1 << MSR_LE;
631 #else
632 if (msr_ile) {
633 new_msr |= (target_ulong)1 << MSR_LE;
635 #endif
637 /* Jump to handler */
638 vector = env->excp_vectors[excp];
639 if (vector == (target_ulong)-1ULL) {
640 cpu_abort(cs, "Raised an exception without defined vector %d\n",
641 excp);
643 vector |= env->excp_prefix;
644 #if defined(TARGET_PPC64)
645 if (excp_model == POWERPC_EXCP_BOOKE) {
646 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
647 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
648 new_msr |= (target_ulong)1 << MSR_CM;
649 } else {
650 vector = (uint32_t)vector;
652 } else {
653 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
654 vector = (uint32_t)vector;
655 } else {
656 new_msr |= (target_ulong)1 << MSR_SF;
659 #endif
660 /* XXX: we don't use hreg_store_msr here as already have treated
661 * any special case that could occur. Just store MSR and update hflags
663 env->msr = new_msr & env->msr_mask;
664 hreg_compute_hflags(env);
665 env->nip = vector;
666 /* Reset exception state */
667 cs->exception_index = POWERPC_EXCP_NONE;
668 env->error_code = 0;
670 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
671 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
672 /* XXX: The BookE changes address space when switching modes,
673 we should probably implement that as different MMU indexes,
674 but for the moment we do it the slow way and flush all. */
675 tlb_flush(cs, 1);
679 void ppc_cpu_do_interrupt(CPUState *cs)
681 PowerPCCPU *cpu = POWERPC_CPU(cs);
682 CPUPPCState *env = &cpu->env;
684 powerpc_excp(cpu, env->excp_model, cs->exception_index);
687 void ppc_hw_interrupt(CPUPPCState *env)
689 PowerPCCPU *cpu = ppc_env_get_cpu(env);
690 int hdice;
691 #if 0
692 CPUState *cs = CPU(cpu);
694 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
695 __func__, env, env->pending_interrupts,
696 cs->interrupt_request, (int)msr_me, (int)msr_ee);
697 #endif
698 /* External reset */
699 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
700 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
701 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
702 return;
704 /* Machine check exception */
705 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
706 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
707 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
708 return;
710 #if 0 /* TODO */
711 /* External debug exception */
712 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
713 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
714 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
715 return;
717 #endif
718 if (0) {
719 /* XXX: find a suitable condition to enable the hypervisor mode */
720 hdice = env->spr[SPR_LPCR] & 1;
721 } else {
722 hdice = 0;
724 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
725 /* Hypervisor decrementer exception */
726 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
727 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
728 return;
731 if (msr_ce != 0) {
732 /* External critical interrupt */
733 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
734 /* Taking a critical external interrupt does not clear the external
735 * critical interrupt status
737 #if 0
738 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
739 #endif
740 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
741 return;
744 if (msr_ee != 0) {
745 /* Watchdog timer on embedded PowerPC */
746 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
747 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
748 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
749 return;
751 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
752 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
753 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
754 return;
756 /* Fixed interval timer on embedded PowerPC */
757 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
758 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
759 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
760 return;
762 /* Programmable interval timer on embedded PowerPC */
763 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
764 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
765 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
766 return;
768 /* Decrementer exception */
769 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
770 if (ppc_decr_clear_on_delivery(env)) {
771 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
773 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
774 return;
776 /* External interrupt */
777 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
778 /* Taking an external interrupt does not clear the external
779 * interrupt status
781 #if 0
782 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
783 #endif
784 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
785 return;
787 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
788 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
789 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
790 return;
792 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
793 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
794 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
795 return;
797 /* Thermal interrupt */
798 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
799 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
800 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
801 return;
805 #endif /* !CONFIG_USER_ONLY */
807 #if defined(DEBUG_OP)
808 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
810 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
811 TARGET_FMT_lx "\n", RA, msr);
813 #endif
815 /*****************************************************************************/
816 /* Exceptions processing helpers */
818 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
819 uint32_t error_code)
821 CPUState *cs = CPU(ppc_env_get_cpu(env));
823 #if 0
824 printf("Raise exception %3x code : %d\n", exception, error_code);
825 #endif
826 cs->exception_index = exception;
827 env->error_code = error_code;
828 cpu_loop_exit(cs);
831 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
833 helper_raise_exception_err(env, exception, 0);
836 #if !defined(CONFIG_USER_ONLY)
837 void helper_store_msr(CPUPPCState *env, target_ulong val)
839 CPUState *cs;
841 val = hreg_store_msr(env, val, 0);
842 if (val != 0) {
843 cs = CPU(ppc_env_get_cpu(env));
844 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
845 helper_raise_exception(env, val);
849 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
850 target_ulong msrm, int keep_msrh)
852 CPUState *cs = CPU(ppc_env_get_cpu(env));
854 #if defined(TARGET_PPC64)
855 if (msr_is_64bit(env, msr)) {
856 nip = (uint64_t)nip;
857 msr &= (uint64_t)msrm;
858 } else {
859 nip = (uint32_t)nip;
860 msr = (uint32_t)(msr & msrm);
861 if (keep_msrh) {
862 msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
865 #else
866 nip = (uint32_t)nip;
867 msr &= (uint32_t)msrm;
868 #endif
869 /* XXX: beware: this is false if VLE is supported */
870 env->nip = nip & ~((target_ulong)0x00000003);
871 hreg_store_msr(env, msr, 1);
872 #if defined(DEBUG_OP)
873 cpu_dump_rfi(env->nip, env->msr);
874 #endif
875 /* No need to raise an exception here,
876 * as rfi is always the last insn of a TB
878 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
881 void helper_rfi(CPUPPCState *env)
883 if (env->excp_model == POWERPC_EXCP_BOOKE) {
884 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
885 ~((target_ulong)0), 0);
886 } else {
887 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
888 ~((target_ulong)0x783F0000), 1);
892 #if defined(TARGET_PPC64)
893 void helper_rfid(CPUPPCState *env)
895 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
896 ~((target_ulong)0x783F0000), 0);
899 void helper_hrfid(CPUPPCState *env)
901 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
902 ~((target_ulong)0x783F0000), 0);
904 #endif
906 /*****************************************************************************/
907 /* Embedded PowerPC specific helpers */
908 void helper_40x_rfci(CPUPPCState *env)
910 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
911 ~((target_ulong)0xFFFF0000), 0);
914 void helper_rfci(CPUPPCState *env)
916 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
917 ~((target_ulong)0), 0);
920 void helper_rfdi(CPUPPCState *env)
922 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
923 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
924 ~((target_ulong)0), 0);
927 void helper_rfmci(CPUPPCState *env)
929 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
930 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
931 ~((target_ulong)0), 0);
933 #endif
935 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
936 uint32_t flags)
938 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
939 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
940 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
941 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
942 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
943 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
944 POWERPC_EXCP_TRAP);
948 #if defined(TARGET_PPC64)
949 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
950 uint32_t flags)
952 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
953 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
954 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
955 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
956 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
957 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
958 POWERPC_EXCP_TRAP);
961 #endif
963 #if !defined(CONFIG_USER_ONLY)
964 /*****************************************************************************/
965 /* PowerPC 601 specific instructions (POWER bridge) */
967 void helper_rfsvc(CPUPPCState *env)
969 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
972 /* Embedded.Processor Control */
973 static int dbell2irq(target_ulong rb)
975 int msg = rb & DBELL_TYPE_MASK;
976 int irq = -1;
978 switch (msg) {
979 case DBELL_TYPE_DBELL:
980 irq = PPC_INTERRUPT_DOORBELL;
981 break;
982 case DBELL_TYPE_DBELL_CRIT:
983 irq = PPC_INTERRUPT_CDOORBELL;
984 break;
985 case DBELL_TYPE_G_DBELL:
986 case DBELL_TYPE_G_DBELL_CRIT:
987 case DBELL_TYPE_G_DBELL_MC:
988 /* XXX implement */
989 default:
990 break;
993 return irq;
996 void helper_msgclr(CPUPPCState *env, target_ulong rb)
998 int irq = dbell2irq(rb);
1000 if (irq < 0) {
1001 return;
1004 env->pending_interrupts &= ~(1 << irq);
1007 void helper_msgsnd(target_ulong rb)
1009 int irq = dbell2irq(rb);
1010 int pir = rb & DBELL_PIRTAG_MASK;
1011 CPUState *cs;
1013 if (irq < 0) {
1014 return;
1017 CPU_FOREACH(cs) {
1018 PowerPCCPU *cpu = POWERPC_CPU(cs);
1019 CPUPPCState *cenv = &cpu->env;
1021 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1022 cenv->pending_interrupts |= 1 << irq;
1023 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1027 #endif