1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "cpu.h"
20#include "helper.h"
21
22#include "helper_regs.h"
23
24
25
26
27#ifdef DEBUG_EXCEPTIONS
28# define LOG_EXCP(...) qemu_log(__VA_ARGS__)
29#else
30# define LOG_EXCP(...) do { } while (0)
31#endif
32
33
34
35
36void (*cpu_ppc_hypercall)(CPUPPCState *);
37
38
39
40#if defined(CONFIG_USER_ONLY)
41void do_interrupt(CPUPPCState *env)
42{
43 env->exception_index = POWERPC_EXCP_NONE;
44 env->error_code = 0;
45}
46
47void ppc_hw_interrupt(CPUPPCState *env)
48{
49 env->exception_index = POWERPC_EXCP_NONE;
50 env->error_code = 0;
51}
52#else
53static inline void dump_syscall(CPUPPCState *env)
54{
55 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
56 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
57 " nip=" TARGET_FMT_lx "\n",
58 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
59 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
60 ppc_dump_gpr(env, 6), env->nip);
61}
62
63
64
65
66static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
67{
68 target_ulong msr, new_msr, vector;
69 int srr0, srr1, asrr0, asrr1;
70 int lpes0, lpes1, lev;
71
72 if (0) {
73
74 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
75 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
76 } else {
77
78 lpes0 = 0;
79 lpes1 = 1;
80 }
81
82 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
83 " => %08x (%02x)\n", env->nip, excp, env->error_code);
84
85
86 msr = env->msr & ~0x783f0000ULL;
87
88
89 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
90
91
92 srr0 = SPR_SRR0;
93 srr1 = SPR_SRR1;
94 asrr0 = -1;
95 asrr1 = -1;
96
97 switch (excp) {
98 case POWERPC_EXCP_NONE:
99
100 return;
101 case POWERPC_EXCP_CRITICAL:
102 switch (excp_model) {
103 case POWERPC_EXCP_40x:
104 srr0 = SPR_40x_SRR2;
105 srr1 = SPR_40x_SRR3;
106 break;
107 case POWERPC_EXCP_BOOKE:
108 srr0 = SPR_BOOKE_CSRR0;
109 srr1 = SPR_BOOKE_CSRR1;
110 break;
111 case POWERPC_EXCP_G2:
112 break;
113 default:
114 goto excp_invalid;
115 }
116 goto store_next;
117 case POWERPC_EXCP_MCHECK:
118 if (msr_me == 0) {
119
120
121
122 if (qemu_log_enabled()) {
123 qemu_log("Machine check while not allowed. "
124 "Entering checkstop state\n");
125 } else {
126 fprintf(stderr, "Machine check while not allowed. "
127 "Entering checkstop state\n");
128 }
129 env->halted = 1;
130 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
131 }
132 if (0) {
133
134 new_msr |= (target_ulong)MSR_HVB;
135 }
136
137
138 new_msr &= ~((target_ulong)1 << MSR_ME);
139
140
141 switch (excp_model) {
142 case POWERPC_EXCP_40x:
143 srr0 = SPR_40x_SRR2;
144 srr1 = SPR_40x_SRR3;
145 break;
146 case POWERPC_EXCP_BOOKE:
147 srr0 = SPR_BOOKE_MCSRR0;
148 srr1 = SPR_BOOKE_MCSRR1;
149 asrr0 = SPR_BOOKE_CSRR0;
150 asrr1 = SPR_BOOKE_CSRR1;
151 break;
152 default:
153 break;
154 }
155 goto store_next;
156 case POWERPC_EXCP_DSI:
157 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
158 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
159 if (lpes1 == 0) {
160 new_msr |= (target_ulong)MSR_HVB;
161 }
162 goto store_next;
163 case POWERPC_EXCP_ISI:
164 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
165 "\n", msr, env->nip);
166 if (lpes1 == 0) {
167 new_msr |= (target_ulong)MSR_HVB;
168 }
169 msr |= env->error_code;
170 goto store_next;
171 case POWERPC_EXCP_EXTERNAL:
172 if (lpes0 == 1) {
173 new_msr |= (target_ulong)MSR_HVB;
174 }
175 goto store_next;
176 case POWERPC_EXCP_ALIGN:
177 if (lpes1 == 0) {
178 new_msr |= (target_ulong)MSR_HVB;
179 }
180
181
182 env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
183 & 0x03FF0000) >> 16;
184 goto store_current;
185 case POWERPC_EXCP_PROGRAM:
186 switch (env->error_code & ~0xF) {
187 case POWERPC_EXCP_FP:
188 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
189 LOG_EXCP("Ignore floating point exception\n");
190 env->exception_index = POWERPC_EXCP_NONE;
191 env->error_code = 0;
192 return;
193 }
194 if (lpes1 == 0) {
195 new_msr |= (target_ulong)MSR_HVB;
196 }
197 msr |= 0x00100000;
198 if (msr_fe0 == msr_fe1) {
199 goto store_next;
200 }
201 msr |= 0x00010000;
202 break;
203 case POWERPC_EXCP_INVAL:
204 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
205 if (lpes1 == 0) {
206 new_msr |= (target_ulong)MSR_HVB;
207 }
208 msr |= 0x00080000;
209 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
210 break;
211 case POWERPC_EXCP_PRIV:
212 if (lpes1 == 0) {
213 new_msr |= (target_ulong)MSR_HVB;
214 }
215 msr |= 0x00040000;
216 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
217 break;
218 case POWERPC_EXCP_TRAP:
219 if (lpes1 == 0) {
220 new_msr |= (target_ulong)MSR_HVB;
221 }
222 msr |= 0x00020000;
223 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
224 break;
225 default:
226
227 cpu_abort(env, "Invalid program exception %d. Aborting\n",
228 env->error_code);
229 break;
230 }
231 goto store_current;
232 case POWERPC_EXCP_FPU:
233 if (lpes1 == 0) {
234 new_msr |= (target_ulong)MSR_HVB;
235 }
236 goto store_current;
237 case POWERPC_EXCP_SYSCALL:
238 dump_syscall(env);
239 lev = env->error_code;
240 if ((lev == 1) && cpu_ppc_hypercall) {
241 cpu_ppc_hypercall(env);
242 return;
243 }
244 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
245 new_msr |= (target_ulong)MSR_HVB;
246 }
247 goto store_next;
248 case POWERPC_EXCP_APU:
249 goto store_current;
250 case POWERPC_EXCP_DECR:
251 if (lpes1 == 0) {
252 new_msr |= (target_ulong)MSR_HVB;
253 }
254 goto store_next;
255 case POWERPC_EXCP_FIT:
256
257 LOG_EXCP("FIT exception\n");
258 goto store_next;
259 case POWERPC_EXCP_WDT:
260 LOG_EXCP("WDT exception\n");
261 switch (excp_model) {
262 case POWERPC_EXCP_BOOKE:
263 srr0 = SPR_BOOKE_CSRR0;
264 srr1 = SPR_BOOKE_CSRR1;
265 break;
266 default:
267 break;
268 }
269 goto store_next;
270 case POWERPC_EXCP_DTLB:
271 goto store_next;
272 case POWERPC_EXCP_ITLB:
273 goto store_next;
274 case POWERPC_EXCP_DEBUG:
275 switch (excp_model) {
276 case POWERPC_EXCP_BOOKE:
277 srr0 = SPR_BOOKE_DSRR0;
278 srr1 = SPR_BOOKE_DSRR1;
279 asrr0 = SPR_BOOKE_CSRR0;
280 asrr1 = SPR_BOOKE_CSRR1;
281 break;
282 default:
283 break;
284 }
285
286 cpu_abort(env, "Debug exception is not implemented yet !\n");
287 goto store_next;
288 case POWERPC_EXCP_SPEU:
289 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
290 goto store_current;
291 case POWERPC_EXCP_EFPDI:
292
293 cpu_abort(env, "Embedded floating point data exception "
294 "is not implemented yet !\n");
295 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
296 goto store_next;
297 case POWERPC_EXCP_EFPRI:
298
299 cpu_abort(env, "Embedded floating point round exception "
300 "is not implemented yet !\n");
301 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
302 goto store_next;
303 case POWERPC_EXCP_EPERFM:
304
305 cpu_abort(env,
306 "Performance counter exception is not implemented yet !\n");
307 goto store_next;
308 case POWERPC_EXCP_DOORI:
309 goto store_next;
310 case POWERPC_EXCP_DOORCI:
311 srr0 = SPR_BOOKE_CSRR0;
312 srr1 = SPR_BOOKE_CSRR1;
313 goto store_next;
314 case POWERPC_EXCP_RESET:
315 if (msr_pow) {
316
317 msr |= 0x10000;
318 } else {
319 new_msr &= ~((target_ulong)1 << MSR_ME);
320 }
321
322 if (0) {
323
324 new_msr |= (target_ulong)MSR_HVB;
325 }
326 goto store_next;
327 case POWERPC_EXCP_DSEG:
328 if (lpes1 == 0) {
329 new_msr |= (target_ulong)MSR_HVB;
330 }
331 goto store_next;
332 case POWERPC_EXCP_ISEG:
333 if (lpes1 == 0) {
334 new_msr |= (target_ulong)MSR_HVB;
335 }
336 goto store_next;
337 case POWERPC_EXCP_HDECR:
338 srr0 = SPR_HSRR0;
339 srr1 = SPR_HSRR1;
340 new_msr |= (target_ulong)MSR_HVB;
341 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
342 goto store_next;
343 case POWERPC_EXCP_TRACE:
344 if (lpes1 == 0) {
345 new_msr |= (target_ulong)MSR_HVB;
346 }
347 goto store_next;
348 case POWERPC_EXCP_HDSI:
349 srr0 = SPR_HSRR0;
350 srr1 = SPR_HSRR1;
351 new_msr |= (target_ulong)MSR_HVB;
352 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
353 goto store_next;
354 case POWERPC_EXCP_HISI:
355 srr0 = SPR_HSRR0;
356 srr1 = SPR_HSRR1;
357 new_msr |= (target_ulong)MSR_HVB;
358 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
359 goto store_next;
360 case POWERPC_EXCP_HDSEG:
361 srr0 = SPR_HSRR0;
362 srr1 = SPR_HSRR1;
363 new_msr |= (target_ulong)MSR_HVB;
364 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
365 goto store_next;
366 case POWERPC_EXCP_HISEG:
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_VPU:
373 if (lpes1 == 0) {
374 new_msr |= (target_ulong)MSR_HVB;
375 }
376 goto store_current;
377 case POWERPC_EXCP_PIT:
378 LOG_EXCP("PIT exception\n");
379 goto store_next;
380 case POWERPC_EXCP_IO:
381
382 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
383 goto store_next;
384 case POWERPC_EXCP_RUNM:
385
386 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
387 goto store_next;
388 case POWERPC_EXCP_EMUL:
389
390 cpu_abort(env, "602 emulation trap exception "
391 "is not implemented yet !\n");
392 goto store_next;
393 case POWERPC_EXCP_IFTLB:
394 if (lpes1 == 0) {
395 new_msr |= (target_ulong)MSR_HVB;
396 }
397 switch (excp_model) {
398 case POWERPC_EXCP_602:
399 case POWERPC_EXCP_603:
400 case POWERPC_EXCP_603E:
401 case POWERPC_EXCP_G2:
402 goto tlb_miss_tgpr;
403 case POWERPC_EXCP_7x5:
404 goto tlb_miss;
405 case POWERPC_EXCP_74xx:
406 goto tlb_miss_74xx;
407 default:
408 cpu_abort(env, "Invalid instruction TLB miss exception\n");
409 break;
410 }
411 break;
412 case POWERPC_EXCP_DLTLB:
413 if (lpes1 == 0) {
414 new_msr |= (target_ulong)MSR_HVB;
415 }
416 switch (excp_model) {
417 case POWERPC_EXCP_602:
418 case POWERPC_EXCP_603:
419 case POWERPC_EXCP_603E:
420 case POWERPC_EXCP_G2:
421 goto tlb_miss_tgpr;
422 case POWERPC_EXCP_7x5:
423 goto tlb_miss;
424 case POWERPC_EXCP_74xx:
425 goto tlb_miss_74xx;
426 default:
427 cpu_abort(env, "Invalid data load TLB miss exception\n");
428 break;
429 }
430 break;
431 case POWERPC_EXCP_DSTLB:
432 if (lpes1 == 0) {
433 new_msr |= (target_ulong)MSR_HVB;
434 }
435 switch (excp_model) {
436 case POWERPC_EXCP_602:
437 case POWERPC_EXCP_603:
438 case POWERPC_EXCP_603E:
439 case POWERPC_EXCP_G2:
440 tlb_miss_tgpr:
441
442 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
443 new_msr |= (target_ulong)1 << MSR_TGPR;
444 hreg_swap_gpr_tgpr(env);
445 }
446 goto tlb_miss;
447 case POWERPC_EXCP_7x5:
448 tlb_miss:
449#if defined(DEBUG_SOFTWARE_TLB)
450 if (qemu_log_enabled()) {
451 const char *es;
452 target_ulong *miss, *cmp;
453 int en;
454
455 if (excp == POWERPC_EXCP_IFTLB) {
456 es = "I";
457 en = 'I';
458 miss = &env->spr[SPR_IMISS];
459 cmp = &env->spr[SPR_ICMP];
460 } else {
461 if (excp == POWERPC_EXCP_DLTLB) {
462 es = "DL";
463 } else {
464 es = "DS";
465 }
466 en = 'D';
467 miss = &env->spr[SPR_DMISS];
468 cmp = &env->spr[SPR_DCMP];
469 }
470 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
471 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
472 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
473 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
474 env->error_code);
475 }
476#endif
477 msr |= env->crf[0] << 28;
478 msr |= env->error_code;
479
480 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
481 break;
482 case POWERPC_EXCP_74xx:
483 tlb_miss_74xx:
484#if defined(DEBUG_SOFTWARE_TLB)
485 if (qemu_log_enabled()) {
486 const char *es;
487 target_ulong *miss, *cmp;
488 int en;
489
490 if (excp == POWERPC_EXCP_IFTLB) {
491 es = "I";
492 en = 'I';
493 miss = &env->spr[SPR_TLBMISS];
494 cmp = &env->spr[SPR_PTEHI];
495 } else {
496 if (excp == POWERPC_EXCP_DLTLB) {
497 es = "DL";
498 } else {
499 es = "DS";
500 }
501 en = 'D';
502 miss = &env->spr[SPR_TLBMISS];
503 cmp = &env->spr[SPR_PTEHI];
504 }
505 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
506 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
507 env->error_code);
508 }
509#endif
510 msr |= env->error_code;
511 break;
512 default:
513 cpu_abort(env, "Invalid data store TLB miss exception\n");
514 break;
515 }
516 goto store_next;
517 case POWERPC_EXCP_FPA:
518
519 cpu_abort(env, "Floating point assist exception "
520 "is not implemented yet !\n");
521 goto store_next;
522 case POWERPC_EXCP_DABR:
523
524 cpu_abort(env, "DABR exception is not implemented yet !\n");
525 goto store_next;
526 case POWERPC_EXCP_IABR:
527
528 cpu_abort(env, "IABR exception is not implemented yet !\n");
529 goto store_next;
530 case POWERPC_EXCP_SMI:
531
532 cpu_abort(env, "SMI exception is not implemented yet !\n");
533 goto store_next;
534 case POWERPC_EXCP_THERM:
535
536 cpu_abort(env, "Thermal management exception "
537 "is not implemented yet !\n");
538 goto store_next;
539 case POWERPC_EXCP_PERFM:
540 if (lpes1 == 0) {
541 new_msr |= (target_ulong)MSR_HVB;
542 }
543
544 cpu_abort(env,
545 "Performance counter exception is not implemented yet !\n");
546 goto store_next;
547 case POWERPC_EXCP_VPUA:
548
549 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
550 goto store_next;
551 case POWERPC_EXCP_SOFTP:
552
553 cpu_abort(env,
554 "970 soft-patch exception is not implemented yet !\n");
555 goto store_next;
556 case POWERPC_EXCP_MAINT:
557
558 cpu_abort(env,
559 "970 maintenance exception is not implemented yet !\n");
560 goto store_next;
561 case POWERPC_EXCP_MEXTBR:
562
563 cpu_abort(env, "Maskable external exception "
564 "is not implemented yet !\n");
565 goto store_next;
566 case POWERPC_EXCP_NMEXTBR:
567
568 cpu_abort(env, "Non maskable external exception "
569 "is not implemented yet !\n");
570 goto store_next;
571 default:
572 excp_invalid:
573 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
574 break;
575 store_current:
576
577 env->spr[srr0] = env->nip - 4;
578 break;
579 store_next:
580
581 env->spr[srr0] = env->nip;
582 break;
583 }
584
585 env->spr[srr1] = msr;
586
587 if (asrr0 != -1) {
588 env->spr[asrr0] = env->spr[srr0];
589 }
590 if (asrr1 != -1) {
591 env->spr[asrr1] = env->spr[srr1];
592 }
593
594 if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
595 tlb_flush(env, 1);
596 }
597
598 if (msr_ile) {
599 new_msr |= (target_ulong)1 << MSR_LE;
600 }
601
602
603 vector = env->excp_vectors[excp];
604 if (vector == (target_ulong)-1ULL) {
605 cpu_abort(env, "Raised an exception without defined vector %d\n",
606 excp);
607 }
608 vector |= env->excp_prefix;
609#if defined(TARGET_PPC64)
610 if (excp_model == POWERPC_EXCP_BOOKE) {
611 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
612
613 new_msr |= (target_ulong)1 << MSR_CM;
614 } else {
615 vector = (uint32_t)vector;
616 }
617 } else {
618 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
619 vector = (uint32_t)vector;
620 } else {
621 new_msr |= (target_ulong)1 << MSR_SF;
622 }
623 }
624#endif
625
626
627
628 env->msr = new_msr & env->msr_mask;
629 hreg_compute_hflags(env);
630 env->nip = vector;
631
632 env->exception_index = POWERPC_EXCP_NONE;
633 env->error_code = 0;
634
635 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
636 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
637
638
639
640 tlb_flush(env, 1);
641 }
642}
643
644void do_interrupt(CPUPPCState *env)
645{
646 powerpc_excp(env, env->excp_model, env->exception_index);
647}
648
649void ppc_hw_interrupt(CPUPPCState *env)
650{
651 int hdice;
652
653#if 0
654 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
655 __func__, env, env->pending_interrupts,
656 env->interrupt_request, (int)msr_me, (int)msr_ee);
657#endif
658
659 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
660 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
661 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
662 return;
663 }
664
665 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
666 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
667 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
668 return;
669 }
670#if 0
671
672 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
673 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
674 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
675 return;
676 }
677#endif
678 if (0) {
679
680 hdice = env->spr[SPR_LPCR] & 1;
681 } else {
682 hdice = 0;
683 }
684 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
685
686 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
687 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
688 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
689 return;
690 }
691 }
692 if (msr_ce != 0) {
693
694 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
695
696
697
698#if 0
699 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
700#endif
701 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
702 return;
703 }
704 }
705 if (msr_ee != 0) {
706
707 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
708 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
709 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
710 return;
711 }
712 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
713 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
714 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
715 return;
716 }
717
718 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
719 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
720 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
721 return;
722 }
723
724 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
725 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
726 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
727 return;
728 }
729
730 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
731 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
732 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
733 return;
734 }
735
736 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
737
738
739
740#if 0
741 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
742#endif
743 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
744 return;
745 }
746 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
747 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
748 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
749 return;
750 }
751 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
752 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
753 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
754 return;
755 }
756
757 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
758 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
759 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
760 return;
761 }
762 }
763}
764#endif
765
766#if defined(DEBUG_OP)
767static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
768{
769 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
770 TARGET_FMT_lx "\n", RA, msr);
771}
772#endif
773
774
775
776
777void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
778 uint32_t error_code)
779{
780#if 0
781 printf("Raise exception %3x code : %d\n", exception, error_code);
782#endif
783 env->exception_index = exception;
784 env->error_code = error_code;
785 cpu_loop_exit(env);
786}
787
788void helper_raise_exception(CPUPPCState *env, uint32_t exception)
789{
790 helper_raise_exception_err(env, exception, 0);
791}
792
793#if !defined(CONFIG_USER_ONLY)
794void helper_store_msr(CPUPPCState *env, target_ulong val)
795{
796 val = hreg_store_msr(env, val, 0);
797 if (val != 0) {
798 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
799 helper_raise_exception(env, val);
800 }
801}
802
803static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
804 target_ulong msrm, int keep_msrh)
805{
806#if defined(TARGET_PPC64)
807 if (msr_is_64bit(env, msr)) {
808 nip = (uint64_t)nip;
809 msr &= (uint64_t)msrm;
810 } else {
811 nip = (uint32_t)nip;
812 msr = (uint32_t)(msr & msrm);
813 if (keep_msrh) {
814 msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
815 }
816 }
817#else
818 nip = (uint32_t)nip;
819 msr &= (uint32_t)msrm;
820#endif
821
822 env->nip = nip & ~((target_ulong)0x00000003);
823 hreg_store_msr(env, msr, 1);
824#if defined(DEBUG_OP)
825 cpu_dump_rfi(env->nip, env->msr);
826#endif
827
828
829
830 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
831}
832
833void helper_rfi(CPUPPCState *env)
834{
835 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
836 ~((target_ulong)0x783F0000), 1);
837}
838
839#if defined(TARGET_PPC64)
840void helper_rfid(CPUPPCState *env)
841{
842 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
843 ~((target_ulong)0x783F0000), 0);
844}
845
846void helper_hrfid(CPUPPCState *env)
847{
848 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
849 ~((target_ulong)0x783F0000), 0);
850}
851#endif
852
853
854
855void helper_40x_rfci(CPUPPCState *env)
856{
857 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
858 ~((target_ulong)0xFFFF0000), 0);
859}
860
861void helper_rfci(CPUPPCState *env)
862{
863 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
864 ~((target_ulong)0x3FFF0000), 0);
865}
866
867void helper_rfdi(CPUPPCState *env)
868{
869 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
870 ~((target_ulong)0x3FFF0000), 0);
871}
872
873void helper_rfmci(CPUPPCState *env)
874{
875 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
876 ~((target_ulong)0x3FFF0000), 0);
877}
878#endif
879
880void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
881 uint32_t flags)
882{
883 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
884 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
885 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
886 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
887 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
888 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
889 POWERPC_EXCP_TRAP);
890 }
891}
892
893#if defined(TARGET_PPC64)
894void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
895 uint32_t flags)
896{
897 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
898 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
899 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
900 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
901 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
902 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
903 POWERPC_EXCP_TRAP);
904 }
905}
906#endif
907
908#if !defined(CONFIG_USER_ONLY)
909
910
911
912void helper_rfsvc(CPUPPCState *env)
913{
914 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
915}
916
917
918static int dbell2irq(target_ulong rb)
919{
920 int msg = rb & DBELL_TYPE_MASK;
921 int irq = -1;
922
923 switch (msg) {
924 case DBELL_TYPE_DBELL:
925 irq = PPC_INTERRUPT_DOORBELL;
926 break;
927 case DBELL_TYPE_DBELL_CRIT:
928 irq = PPC_INTERRUPT_CDOORBELL;
929 break;
930 case DBELL_TYPE_G_DBELL:
931 case DBELL_TYPE_G_DBELL_CRIT:
932 case DBELL_TYPE_G_DBELL_MC:
933
934 default:
935 break;
936 }
937
938 return irq;
939}
940
941void helper_msgclr(CPUPPCState *env, target_ulong rb)
942{
943 int irq = dbell2irq(rb);
944
945 if (irq < 0) {
946 return;
947 }
948
949 env->pending_interrupts &= ~(1 << irq);
950}
951
952void helper_msgsnd(target_ulong rb)
953{
954 int irq = dbell2irq(rb);
955 int pir = rb & DBELL_PIRTAG_MASK;
956 CPUPPCState *cenv;
957
958 if (irq < 0) {
959 return;
960 }
961
962 for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
963 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
964 cenv->pending_interrupts |= 1 << irq;
965 cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
966 }
967 }
968}
969#endif
970