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