Great PowerPC emulation code resynchronisation and improvments:
[qemu] / target-ppc / helper.c
1 /*
2  *  PowerPC emulation helpers for qemu.
3  * 
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
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.
10  *
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.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
27
28 #include "cpu.h"
29 #include "exec-all.h"
30
31 //#define DEBUG_MMU
32 //#define DEBUG_BATS
33 //#define DEBUG_SOFTWARE_TLB
34 //#define DEBUG_EXCEPTIONS
35 //#define FLUSH_ALL_TLBS
36
37 /*****************************************************************************/
38 /* PowerPC MMU emulation */
39
40 #if defined(CONFIG_USER_ONLY) 
41 int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
42                               int is_user, int is_softmmu)
43 {
44     int exception, error_code;
45     
46     if (rw == 2) {
47         exception = EXCP_ISI;
48         error_code = 0;
49     } else {
50         exception = EXCP_DSI;
51         error_code = 0;
52         if (rw)
53             error_code |= 0x02000000;
54         env->spr[SPR_DAR] = address;
55         env->spr[SPR_DSISR] = error_code;
56     }
57     env->exception_index = exception;
58     env->error_code = error_code;
59
60     return 1;
61 }
62
63 target_ulong cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
64 {
65     return addr;
66 }
67 #else
68 /* Common routines used by software and hardware TLBs emulation */
69 static inline int pte_is_valid (target_ulong pte0)
70 {
71     return pte0 & 0x80000000 ? 1 : 0;
72 }
73
74 static inline void pte_invalidate (target_ulong *pte0)
75 {
76     *pte0 &= ~0x80000000;
77 }
78
79 #define PTE_PTEM_MASK 0x7FFFFFBF
80 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
81
82 static int pte_check (mmu_ctx_t *ctx,
83                       target_ulong pte0, target_ulong pte1, int h, int rw)
84 {
85     int access, ret;
86
87     access = 0;
88     ret = -1;
89     /* Check validity and table match */
90     if (pte_is_valid(pte0) && (h == ((pte0 >> 6) & 1))) {
91         /* Check vsid & api */
92         if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
93             if (ctx->raddr != (target_ulong)-1) {
94                 /* all matches should have equal RPN, WIMG & PP */
95                 if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
96                     if (loglevel > 0)
97                         fprintf(logfile, "Bad RPN/WIMG/PP\n");
98                     return -3;
99                 }
100             }
101             /* Compute access rights */
102             if (ctx->key == 0) {
103                 access = PAGE_READ;
104                 if ((pte1 & 0x00000003) != 0x3)
105                     access |= PAGE_WRITE;
106             } else {
107                 switch (pte1 & 0x00000003) {
108                 case 0x0:
109                     access = 0;
110                     break;
111                 case 0x1:
112                 case 0x3:
113                     access = PAGE_READ;
114                     break;
115                 case 0x2:
116                     access = PAGE_READ | PAGE_WRITE;
117                     break;
118                 }
119             }
120             /* Keep the matching PTE informations */
121             ctx->raddr = pte1;
122             ctx->prot = access;
123             if ((rw == 0 && (access & PAGE_READ)) ||
124                 (rw == 1 && (access & PAGE_WRITE))) {
125                 /* Access granted */
126 #if defined (DEBUG_MMU)
127                 if (loglevel > 0)
128                     fprintf(logfile, "PTE access granted !\n");
129 #endif
130                 ret = 0;
131             } else {
132                 /* Access right violation */
133 #if defined (DEBUG_MMU)
134                 if (loglevel > 0)
135                     fprintf(logfile, "PTE access rejected\n");
136 #endif
137                 ret = -2;
138             }
139         }
140     }
141
142     return ret;
143 }
144
145 static int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
146                              int ret, int rw)
147 {
148     int store = 0;
149
150     /* Update page flags */
151     if (!(*pte1p & 0x00000100)) {
152         /* Update accessed flag */
153         *pte1p |= 0x00000100;
154         store = 1;
155     }
156     if (!(*pte1p & 0x00000080)) {
157         if (rw == 1 && ret == 0) {
158             /* Update changed flag */
159             *pte1p |= 0x00000080;
160             store = 1;
161         } else {
162             /* Force page fault for first write access */
163             ctx->prot &= ~PAGE_WRITE;
164         }
165     }
166
167     return store;
168 }
169
170 /* Software driven TLB helpers */
171 static int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
172                               int way, int is_code)
173 {
174     int nr;
175
176     /* Select TLB num in a way from address */
177     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
178     /* Select TLB way */
179     nr += env->tlb_per_way * way;
180     /* 6xx have separate TLBs for instructions and data */
181     if (is_code && env->id_tlbs == 1)
182         nr += env->nb_tlb;
183
184     return nr;
185 }
186
187 void ppc6xx_tlb_invalidate_all (CPUState *env)
188 {
189     ppc_tlb_t *tlb;
190     int nr, max;
191
192 #if defined (DEBUG_SOFTWARE_TLB) && 0
193     if (loglevel != 0) {
194         fprintf(logfile, "Invalidate all TLBs\n");
195     }
196 #endif
197     /* Invalidate all defined software TLB */
198     max = env->nb_tlb;
199     if (env->id_tlbs == 1)
200         max *= 2;
201     for (nr = 0; nr < max; nr++) {
202         tlb = &env->tlb[nr];
203 #if !defined(FLUSH_ALL_TLBS)
204         tlb_flush_page(env, tlb->EPN);
205 #endif
206         pte_invalidate(&tlb->pte0);
207     }
208 #if defined(FLUSH_ALL_TLBS)
209     tlb_flush(env, 1);
210 #endif
211 }
212
213 static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
214                                                  target_ulong eaddr,
215                                                  int is_code, int match_epn)
216 {
217     ppc_tlb_t *tlb;
218     int way, nr;
219
220 #if !defined(FLUSH_ALL_TLBS)
221     /* Invalidate ITLB + DTLB, all ways */
222     for (way = 0; way < env->nb_ways; way++) {
223         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
224         tlb = &env->tlb[nr];
225         if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
226 #if defined (DEBUG_SOFTWARE_TLB)
227             if (loglevel != 0) {
228                 fprintf(logfile, "TLB invalidate %d/%d %08x\n",
229                         nr, env->nb_tlb, eaddr);
230             }
231 #endif
232             pte_invalidate(&tlb->pte0);
233             tlb_flush_page(env, tlb->EPN);
234         }
235     }
236 #else
237     /* XXX: PowerPC specification say this is valid as well */
238     ppc6xx_tlb_invalidate_all(env);
239 #endif
240 }
241
242 void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
243                                  int is_code)
244 {
245     __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
246 }
247
248 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
249                        target_ulong pte0, target_ulong pte1)
250 {
251     ppc_tlb_t *tlb;
252     int nr;
253
254     nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
255     tlb = &env->tlb[nr];
256 #if defined (DEBUG_SOFTWARE_TLB)
257     if (loglevel != 0) {
258         fprintf(logfile, "Set TLB %d/%d EPN %08lx PTE0 %08lx PTE1 %08lx\n",
259                 nr, env->nb_tlb, (unsigned long)EPN,
260                 (unsigned long)pte0, (unsigned long)pte1);
261     }
262 #endif
263     /* Invalidate any pending reference in Qemu for this virtual address */
264     __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
265     tlb->pte0 = pte0;
266     tlb->pte1 = pte1;
267     tlb->EPN = EPN;
268     tlb->PID = 0;
269     tlb->size = 1;
270     /* Store last way for LRU mechanism */
271     env->last_way = way;
272 }
273
274 static int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
275                              target_ulong eaddr, int rw, int access_type)
276 {
277     ppc_tlb_t *tlb;
278     int nr, best, way;
279     int ret;
280     
281     best = -1;
282     ret = -1; /* No TLB found */
283     for (way = 0; way < env->nb_ways; way++) {
284         nr = ppc6xx_tlb_getnum(env, eaddr, way,
285                                access_type == ACCESS_CODE ? 1 : 0);
286         tlb = &env->tlb[nr];
287         /* This test "emulates" the PTE index match for hardware TLBs */
288         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
289 #if defined (DEBUG_SOFTWARE_TLB)
290             if (loglevel != 0) {
291                 fprintf(logfile, "TLB %d/%d %s [%08x %08x] <> %08x\n",
292                         nr, env->nb_tlb,
293                         pte_is_valid(tlb->pte0) ? "valid" : "inval",
294                         tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
295             }
296 #endif
297             continue;
298         }
299 #if defined (DEBUG_SOFTWARE_TLB)
300         if (loglevel != 0) {
301             fprintf(logfile, "TLB %d/%d %s %08x <> %08x %08x %c %c\n",
302                     nr, env->nb_tlb,
303                     pte_is_valid(tlb->pte0) ? "valid" : "inval",
304                     tlb->EPN, eaddr, tlb->pte1,
305                     rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
306         }
307 #endif
308         switch (pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
309         case -3:
310             /* TLB inconsistency */
311             return -1;
312         case -2:
313             /* Access violation */
314             ret = -2;
315             best = nr;
316             break;
317         case -1:
318         default:
319             /* No match */
320             break;
321         case 0:
322             /* access granted */
323             /* XXX: we should go on looping to check all TLBs consistency
324              *      but we can speed-up the whole thing as the
325              *      result would be undefined if TLBs are not consistent.
326              */
327             ret = 0;
328             best = nr;
329             goto done;
330         }
331     }
332     if (best != -1) {
333     done:
334 #if defined (DEBUG_SOFTWARE_TLB)
335         if (loglevel > 0) {
336             fprintf(logfile, "found TLB at addr 0x%08lx prot=0x%01x ret=%d\n",
337                     ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
338         }
339 #endif
340         /* Update page flags */
341         pte_update_flags(ctx, &env->tlb[best].pte1, ret, rw);
342     }
343
344     return ret;
345 }
346
347 /* Perform BAT hit & translation */
348 static int get_bat (CPUState *env, mmu_ctx_t *ctx,
349                     target_ulong virtual, int rw, int type)
350 {
351     target_ulong *BATlt, *BATut, *BATu, *BATl;
352     target_ulong base, BEPIl, BEPIu, bl;
353     int i;
354     int ret = -1;
355
356 #if defined (DEBUG_BATS)
357     if (loglevel > 0) {
358         fprintf(logfile, "%s: %cBAT v 0x%08x\n", __func__,
359                 type == ACCESS_CODE ? 'I' : 'D', virtual);
360     }
361 #endif
362     switch (type) {
363     case ACCESS_CODE:
364         BATlt = env->IBAT[1];
365         BATut = env->IBAT[0];
366         break;
367     default:
368         BATlt = env->DBAT[1];
369         BATut = env->DBAT[0];
370         break;
371     }
372 #if defined (DEBUG_BATS)
373     if (loglevel > 0) {
374         fprintf(logfile, "%s...: %cBAT v 0x%08x\n", __func__,
375                 type == ACCESS_CODE ? 'I' : 'D', virtual);
376     }
377 #endif
378     base = virtual & 0xFFFC0000;
379     for (i = 0; i < 4; i++) {
380         BATu = &BATut[i];
381         BATl = &BATlt[i];
382         BEPIu = *BATu & 0xF0000000;
383         BEPIl = *BATu & 0x0FFE0000;
384         bl = (*BATu & 0x00001FFC) << 15;
385 #if defined (DEBUG_BATS)
386         if (loglevel > 0) {
387             fprintf(logfile, "%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x\n",
388                     __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
389                     *BATu, *BATl);
390         }
391 #endif
392         if ((virtual & 0xF0000000) == BEPIu &&
393             ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
394             /* BAT matches */
395             if ((msr_pr == 0 && (*BATu & 0x00000002)) ||
396                 (msr_pr == 1 && (*BATu & 0x00000001))) {
397                 /* Get physical address */
398                 ctx->raddr = (*BATl & 0xF0000000) |
399                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
400                     (virtual & 0x0001F000);
401                 if (*BATl & 0x00000001)
402                     ctx->prot = PAGE_READ;
403                 if (*BATl & 0x00000002)
404                     ctx->prot = PAGE_WRITE | PAGE_READ;
405 #if defined (DEBUG_BATS)
406                 if (loglevel > 0) {
407                     fprintf(logfile, "BAT %d match: r 0x%08x prot=%c%c\n",
408                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
409                             ctx->prot & PAGE_WRITE ? 'W' : '-');
410                 }
411 #endif
412                 ret = 0;
413                 break;
414             }
415         }
416     }
417     if (ret < 0) {
418 #if defined (DEBUG_BATS)
419         printf("no BAT match for 0x%08x:\n", virtual);
420         for (i = 0; i < 4; i++) {
421             BATu = &BATut[i];
422             BATl = &BATlt[i];
423             BEPIu = *BATu & 0xF0000000;
424             BEPIl = *BATu & 0x0FFE0000;
425             bl = (*BATu & 0x00001FFC) << 15;
426             printf("%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x \n\t"
427                    "0x%08x 0x%08x 0x%08x\n",
428                    __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
429                    *BATu, *BATl, BEPIu, BEPIl, bl);
430         }
431 #endif
432     }
433     /* No hit */
434     return ret;
435 }
436
437 /* PTE table lookup */
438 static int find_pte (mmu_ctx_t *ctx, int h, int rw)
439 {
440     target_ulong base, pte0, pte1;
441     int i, good = -1;
442     int ret;
443
444     ret = -1; /* No entry found */
445     base = ctx->pg_addr[h];
446     for (i = 0; i < 8; i++) {
447         pte0 = ldl_phys(base + (i * 8));
448         pte1 =  ldl_phys(base + (i * 8) + 4);
449 #if defined (DEBUG_MMU)
450         if (loglevel > 0) {
451             fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x "
452                     "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1,
453                     pte0 >> 31, h, (pte0 >> 6) & 1, ctx->ptem);
454         }
455 #endif
456         switch (pte_check(ctx, pte0, pte1, h, rw)) {
457         case -3:
458             /* PTE inconsistency */
459             return -1;
460         case -2:
461             /* Access violation */
462             ret = -2;
463             good = i;
464             break;
465         case -1:
466         default:
467             /* No PTE match */
468             break;
469         case 0:
470             /* access granted */
471             /* XXX: we should go on looping to check all PTEs consistency
472              *      but if we can speed-up the whole thing as the
473              *      result would be undefined if PTEs are not consistent.
474              */
475             ret = 0;
476             good = i;
477             goto done;
478         }
479     }
480     if (good != -1) {
481     done:
482 #if defined (DEBUG_MMU)
483         if (loglevel > 0) {
484             fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n",
485                     ctx->raddr, ctx->prot, ret);
486         }
487 #endif
488         /* Update page flags */
489         pte1 = ctx->raddr;
490         if (pte_update_flags(ctx, &pte1, ret, rw) == 1)
491             stl_phys_notdirty(base + (good * 8) + 4, pte1);
492     }
493
494     return ret;
495 }
496
497 static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
498                                              target_phys_addr_t hash,
499                                              target_phys_addr_t mask)
500 {
501     return (sdr1 & 0xFFFF0000) | (hash & mask);
502 }
503
504 /* Perform segment based translation */
505 static int get_segment (CPUState *env, mmu_ctx_t *ctx,
506                         target_ulong eaddr, int rw, int type)
507 {
508     target_phys_addr_t sdr, hash, mask;
509     target_ulong sr, vsid, pgidx;
510     int ret = -1, ret2;
511
512     sr = env->sr[eaddr >> 28];
513 #if defined (DEBUG_MMU)
514     if (loglevel > 0) {
515         fprintf(logfile, "Check segment v=0x%08x %d 0x%08x nip=0x%08x "
516                 "lr=0x%08x ir=%d dr=%d pr=%d %d t=%d\n",
517                 eaddr, eaddr >> 28, sr, env->nip,
518                 env->lr, msr_ir, msr_dr, msr_pr, rw, type);
519     }
520 #endif
521     ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
522                 ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
523     if ((sr & 0x80000000) == 0) {
524 #if defined (DEBUG_MMU)
525         if (loglevel > 0) 
526             fprintf(logfile, "pte segment: key=%d n=0x%08x\n",
527                     ctx->key, sr & 0x10000000);
528 #endif
529         /* Check if instruction fetch is allowed, if needed */
530         if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
531             /* Page address translation */
532             pgidx = (eaddr >> TARGET_PAGE_BITS) & 0xFFFF;
533             vsid = sr & 0x00FFFFFF;
534             hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
535             /* Primary table address */
536             sdr = env->sdr1;
537             mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
538             ctx->pg_addr[0] = get_pgaddr(sdr, hash, mask);
539             /* Secondary table address */
540             hash = (~hash) & 0x01FFFFC0;
541             ctx->pg_addr[1] = get_pgaddr(sdr, hash, mask);
542             ctx->ptem = (vsid << 7) | (pgidx >> 10);
543             /* Initialize real address with an invalid value */
544             ctx->raddr = (target_ulong)-1;
545             if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
546                 /* Software TLB search */
547                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
548             } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
549                 /* XXX: TODO */
550             } else {
551 #if defined (DEBUG_MMU)
552                 if (loglevel > 0) {
553                     fprintf(logfile, "0 sdr1=0x%08x vsid=0x%06x api=0x%04x "
554                             "hash=0x%07x pg_addr=0x%08x\n", sdr, vsid, pgidx,
555                             hash, ctx->pg_addr[0]);
556                 }
557 #endif
558                 /* Primary table lookup */
559                 ret = find_pte(ctx, 0, rw);
560                 if (ret < 0) {
561                     /* Secondary table lookup */
562 #if defined (DEBUG_MMU)
563                     if (eaddr != 0xEFFFFFFF && loglevel > 0) {
564                         fprintf(logfile,
565                                 "1 sdr1=0x%08x vsid=0x%06x api=0x%04x "
566                                 "hash=0x%05x pg_addr=0x%08x\n", sdr, vsid,
567                                 pgidx, hash, ctx->pg_addr[1]);
568                     }
569 #endif
570                     ret2 = find_pte(ctx, 1, rw);
571                     if (ret2 != -1)
572                         ret = ret2;
573                 }
574             }
575         } else {
576 #if defined (DEBUG_MMU)
577             if (loglevel > 0)
578                 fprintf(logfile, "No access allowed\n");
579 #endif
580             ret = -3;
581         }
582     } else {
583 #if defined (DEBUG_MMU)
584         if (loglevel > 0)
585             fprintf(logfile, "direct store...\n");
586 #endif
587         /* Direct-store segment : absolutely *BUGGY* for now */
588         switch (type) {
589         case ACCESS_INT:
590             /* Integer load/store : only access allowed */
591             break;
592         case ACCESS_CODE:
593             /* No code fetch is allowed in direct-store areas */
594             return -4;
595         case ACCESS_FLOAT:
596             /* Floating point load/store */
597             return -4;
598         case ACCESS_RES:
599             /* lwarx, ldarx or srwcx. */
600             return -4;
601         case ACCESS_CACHE:
602             /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
603             /* Should make the instruction do no-op.
604              * As it already do no-op, it's quite easy :-)
605              */
606             ctx->raddr = eaddr;
607             return 0;
608         case ACCESS_EXT:
609             /* eciwx or ecowx */
610             return -4;
611         default:
612             if (logfile) {
613                 fprintf(logfile, "ERROR: instruction should not need "
614                         "address translation\n");
615             }
616             printf("ERROR: instruction should not need "
617                    "address translation\n");
618             return -4;
619         }
620         if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
621             ctx->raddr = eaddr;
622             ret = 2;
623         } else {
624             ret = -2;
625         }
626     }
627
628     return ret;
629 }
630
631 static int check_physical (CPUState *env, mmu_ctx_t *ctx,
632                            target_ulong eaddr, int rw)
633 {
634     int in_plb, ret;
635         
636     ctx->raddr = eaddr;
637     ctx->prot = PAGE_READ;
638     ret = 0;
639     if (unlikely(msr_pe != 0 && PPC_MMU(env) == PPC_FLAGS_MMU_403)) {
640         /* 403 family add some particular protections,
641          * using PBL/PBU registers for accesses with no translation.
642          */
643         in_plb =
644             /* Check PLB validity */
645             (env->pb[0] < env->pb[1] &&
646              /* and address in plb area */
647              eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
648             (env->pb[2] < env->pb[3] &&
649              eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
650         if (in_plb ^ msr_px) {
651             /* Access in protected area */
652             if (rw == 1) {
653                 /* Access is not allowed */
654                 ret = -2;
655             }
656         } else {
657             /* Read-write access is allowed */
658             ctx->prot |= PAGE_WRITE;
659         }
660     } else {
661         ctx->prot |= PAGE_WRITE;
662     }
663
664     return ret;
665 }
666
667 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
668                           int rw, int access_type, int check_BATs)
669 {
670     int ret;
671 #if 0
672     if (loglevel > 0) {
673         fprintf(logfile, "%s\n", __func__);
674     }
675 #endif    
676     if ((access_type == ACCESS_CODE && msr_ir == 0) ||
677         (access_type != ACCESS_CODE && msr_dr == 0)) {
678         /* No address translation */
679         ret = check_physical(env, ctx, eaddr, rw);
680     } else {
681         /* Try to find a BAT */
682         ret = -1;
683         if (check_BATs)
684             ret = get_bat(env, ctx, eaddr, rw, access_type);
685         if (ret < 0) {
686             /* We didn't match any BAT entry */
687             ret = get_segment(env, ctx, eaddr, rw, access_type);
688         }
689     }
690 #if 0
691     if (loglevel > 0) {
692         fprintf(logfile, "%s address %08x => %08lx\n",
693                 __func__, eaddr, ctx->raddr);
694     }
695 #endif
696     
697     return ret;
698 }
699
700 target_ulong cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
701 {
702     mmu_ctx_t ctx;
703
704     if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
705         return -1;
706
707     return ctx.raddr & TARGET_PAGE_MASK;
708 }
709
710 /* Perform address translation */
711 int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
712                               int is_user, int is_softmmu)
713 {
714     mmu_ctx_t ctx;
715     int exception = 0, error_code = 0;
716     int access_type;
717     int ret = 0;
718     
719     if (rw == 2) {
720         /* code access */
721         rw = 0;
722         access_type = ACCESS_CODE;
723     } else {
724         /* data access */
725         /* XXX: put correct access by using cpu_restore_state()
726            correctly */
727         access_type = ACCESS_INT;
728         //        access_type = env->access_type;
729     }
730     ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
731     if (ret == 0) {
732         ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
733                            ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
734                            is_user, is_softmmu);
735     } else if (ret < 0) {
736 #if defined (DEBUG_MMU)
737         if (loglevel > 0)
738             cpu_dump_state(env, logfile, fprintf, 0);
739 #endif
740         if (access_type == ACCESS_CODE) {
741             exception = EXCP_ISI;
742             switch (ret) {
743             case -1:
744                 /* No matches in page tables or TLB */
745                 if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
746                     exception = EXCP_I_TLBMISS;
747                     env->spr[SPR_IMISS] = address;
748                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
749                     error_code = 1 << 18;
750                     goto tlb_miss;
751                 } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
752                     /* XXX: TODO */
753                 } else {
754                     error_code = 0x40000000;
755                 }
756                 break;
757             case -2:
758                 /* Access rights violation */
759                 error_code = 0x08000000;
760                 break;
761             case -3:
762                 /* No execute protection violation */
763                 error_code = 0x10000000;
764                 break;
765             case -4:
766                 /* Direct store exception */
767                 /* No code fetch is allowed in direct-store areas */
768                 error_code = 0x10000000;
769                 break;
770             case -5:
771                 /* No match in segment table */
772                 exception = EXCP_ISEG;
773                 error_code = 0;
774                 break;
775             }
776         } else {
777             exception = EXCP_DSI;
778             switch (ret) {
779             case -1:
780                 /* No matches in page tables or TLB */
781                 if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
782                     if (rw == 1) {
783                         exception = EXCP_DS_TLBMISS;
784                         error_code = 1 << 16;
785                     } else {
786                         exception = EXCP_DL_TLBMISS;
787                         error_code = 0;
788                     }
789                     env->spr[SPR_DMISS] = address;
790                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
791                 tlb_miss:
792                     error_code |= ctx.key << 19;
793                     env->spr[SPR_HASH1] = ctx.pg_addr[0];
794                     env->spr[SPR_HASH2] = ctx.pg_addr[1];
795                     /* Do not alter DAR nor DSISR */
796                     goto out;
797                 } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
798                     /* XXX: TODO */
799                 } else {
800                     error_code = 0x40000000;
801                 }
802                 break;
803             case -2:
804                 /* Access rights violation */
805                 error_code = 0x08000000;
806                 break;
807             case -4:
808                 /* Direct store exception */
809                 switch (access_type) {
810                 case ACCESS_FLOAT:
811                     /* Floating point load/store */
812                     exception = EXCP_ALIGN;
813                     error_code = EXCP_ALIGN_FP;
814                     break;
815                 case ACCESS_RES:
816                     /* lwarx, ldarx or srwcx. */
817                     error_code = 0x04000000;
818                     break;
819                 case ACCESS_EXT:
820                     /* eciwx or ecowx */
821                     error_code = 0x04100000;
822                     break;
823                 default:
824                     printf("DSI: invalid exception (%d)\n", ret);
825                     exception = EXCP_PROGRAM;
826                     error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
827                     break;
828                 }
829                 break;
830             case -5:
831                 /* No match in segment table */
832                 exception = EXCP_DSEG;
833                 error_code = 0;
834                 break;
835             }
836             if (exception == EXCP_DSI && rw == 1)
837                 error_code |= 0x02000000;
838             /* Store fault address */
839             env->spr[SPR_DAR] = address;
840             env->spr[SPR_DSISR] = error_code;
841         }
842     out:
843 #if 0
844         printf("%s: set exception to %d %02x\n",
845                __func__, exception, error_code);
846 #endif
847         env->exception_index = exception;
848         env->error_code = error_code;
849         ret = 1;
850     }
851
852     return ret;
853 }
854
855 /*****************************************************************************/
856 /* BATs management */
857 #if !defined(FLUSH_ALL_TLBS)
858 static inline void do_invalidate_BAT (CPUPPCState *env,
859                                       target_ulong BATu, target_ulong mask)
860 {
861     target_ulong base, end, page;
862
863     base = BATu & ~0x0001FFFF;
864     end = base + mask + 0x00020000;
865 #if defined (DEBUG_BATS)
866     if (loglevel != 0) {
867         fprintf(logfile, "Flush BAT from %08x to %08x (%08x)\n",
868                 base, end, mask);
869     }
870 #endif
871     for (page = base; page != end; page += TARGET_PAGE_SIZE)
872         tlb_flush_page(env, page);
873 #if defined (DEBUG_BATS)
874     if (loglevel != 0)
875         fprintf(logfile, "Flush done\n");
876 #endif
877 }
878 #endif
879
880 static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
881                                    target_ulong value)
882 {
883 #if defined (DEBUG_BATS)
884     if (loglevel != 0) {
885         fprintf(logfile, "Set %cBAT%d%c to 0x%08lx (0x%08lx)\n",
886                 ID, nr, ul == 0 ? 'u' : 'l', (unsigned long)value,
887                 (unsigned long)env->nip);
888     }
889 #endif
890 }
891
892 target_ulong do_load_ibatu (CPUPPCState *env, int nr)
893 {
894     return env->IBAT[0][nr];
895 }
896
897 target_ulong do_load_ibatl (CPUPPCState *env, int nr)
898 {
899     return env->IBAT[1][nr];
900 }
901
902 void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
903 {
904     target_ulong mask;
905
906     dump_store_bat(env, 'I', 0, nr, value);
907     if (env->IBAT[0][nr] != value) {
908         mask = (value << 15) & 0x0FFE0000UL;
909 #if !defined(FLUSH_ALL_TLBS)
910         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
911 #endif
912         /* When storing valid upper BAT, mask BEPI and BRPN
913          * and invalidate all TLBs covered by this BAT
914          */
915         mask = (value << 15) & 0x0FFE0000UL;
916         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
917             (value & ~0x0001FFFFUL & ~mask);
918         env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
919             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
920 #if !defined(FLUSH_ALL_TLBS)
921         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
922 #else
923         tlb_flush(env, 1);
924 #endif
925     }
926 }
927
928 void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
929 {
930     dump_store_bat(env, 'I', 1, nr, value);
931     env->IBAT[1][nr] = value;
932 }
933
934 target_ulong do_load_dbatu (CPUPPCState *env, int nr)
935 {
936     return env->DBAT[0][nr];
937 }
938
939 target_ulong do_load_dbatl (CPUPPCState *env, int nr)
940 {
941     return env->DBAT[1][nr];
942 }
943
944 void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
945 {
946     target_ulong mask;
947
948     dump_store_bat(env, 'D', 0, nr, value);
949     if (env->DBAT[0][nr] != value) {
950         /* When storing valid upper BAT, mask BEPI and BRPN
951          * and invalidate all TLBs covered by this BAT
952          */
953         mask = (value << 15) & 0x0FFE0000UL;
954 #if !defined(FLUSH_ALL_TLBS)
955         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
956 #endif
957         mask = (value << 15) & 0x0FFE0000UL;
958         env->DBAT[0][nr] = (value & 0x00001FFFUL) |
959             (value & ~0x0001FFFFUL & ~mask);
960         env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
961             (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
962 #if !defined(FLUSH_ALL_TLBS)
963         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
964 #else
965         tlb_flush(env, 1);
966 #endif
967     }
968 }
969
970 void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
971 {
972     dump_store_bat(env, 'D', 1, nr, value);
973     env->DBAT[1][nr] = value;
974 }
975
976 /*****************************************************************************/
977 /* Special registers manipulation */
978 target_ulong do_load_sdr1 (CPUPPCState *env)
979 {
980     return env->sdr1;
981 }
982
983 void do_store_sdr1 (CPUPPCState *env, target_ulong value)
984 {
985 #if defined (DEBUG_MMU)
986     if (loglevel != 0) {
987         fprintf(logfile, "%s: 0x%08lx\n", __func__, (unsigned long)value);
988     }
989 #endif
990     if (env->sdr1 != value) {
991         env->sdr1 = value;
992         tlb_flush(env, 1);
993     }
994 }
995
996 target_ulong do_load_sr (CPUPPCState *env, int srnum)
997 {
998     return env->sr[srnum];
999 }
1000
1001 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1002 {
1003 #if defined (DEBUG_MMU)
1004     if (loglevel != 0) {
1005         fprintf(logfile, "%s: reg=%d 0x%08lx %08lx\n",
1006                 __func__, srnum, (unsigned long)value, env->sr[srnum]);
1007     }
1008 #endif
1009     if (env->sr[srnum] != value) {
1010         env->sr[srnum] = value;
1011 #if !defined(FLUSH_ALL_TLBS) && 0
1012         {
1013             target_ulong page, end;
1014             /* Invalidate 256 MB of virtual memory */
1015             page = (16 << 20) * srnum;
1016             end = page + (16 << 20);
1017             for (; page != end; page += TARGET_PAGE_SIZE)
1018                 tlb_flush_page(env, page);
1019         }
1020 #else
1021         tlb_flush(env, 1);
1022 #endif
1023     }
1024 }
1025 #endif /* !defined (CONFIG_USER_ONLY) */
1026
1027 uint32_t ppc_load_xer (CPUPPCState *env)
1028 {
1029     return (xer_so << XER_SO) |
1030         (xer_ov << XER_OV) |
1031         (xer_ca << XER_CA) |
1032         (xer_bc << XER_BC) |
1033         (xer_cmp << XER_CMP);
1034 }
1035
1036 void ppc_store_xer (CPUPPCState *env, uint32_t value)
1037 {
1038     xer_so = (value >> XER_SO) & 0x01;
1039     xer_ov = (value >> XER_OV) & 0x01;
1040     xer_ca = (value >> XER_CA) & 0x01;
1041     xer_cmp = (value >> XER_CMP) & 0xFF;
1042     xer_bc = (value >> XER_BC) & 0x3F;
1043 }
1044
1045 /* Swap temporary saved registers with GPRs */
1046 static inline void swap_gpr_tgpr (CPUPPCState *env)
1047 {
1048     ppc_gpr_t tmp;
1049
1050     tmp = env->gpr[0];
1051     env->gpr[0] = env->tgpr[0];
1052     env->tgpr[0] = tmp;
1053     tmp = env->gpr[1];
1054     env->gpr[1] = env->tgpr[1];
1055     env->tgpr[1] = tmp;
1056     tmp = env->gpr[2];
1057     env->gpr[2] = env->tgpr[2];
1058     env->tgpr[2] = tmp;
1059     tmp = env->gpr[3];
1060     env->gpr[3] = env->tgpr[3];
1061     env->tgpr[3] = tmp;
1062 }
1063
1064 /* GDBstub can read and write MSR... */
1065 target_ulong do_load_msr (CPUPPCState *env)
1066 {
1067     return
1068 #if defined (TARGET_PPC64)
1069         (msr_sf   << MSR_SF)   |
1070         (msr_isf  << MSR_ISF)  |
1071         (msr_hv   << MSR_HV)   |
1072 #endif
1073         (msr_ucle << MSR_UCLE) |
1074         (msr_vr   << MSR_VR)   | /* VR / SPE */
1075         (msr_ap   << MSR_AP)   |
1076         (msr_sa   << MSR_SA)   |
1077         (msr_key  << MSR_KEY)  |
1078         (msr_pow  << MSR_POW)  | /* POW / WE */
1079         (msr_tlb  << MSR_TLB)  | /* TLB / TGPE / CE */
1080         (msr_ile  << MSR_ILE)  |
1081         (msr_ee   << MSR_EE)   |
1082         (msr_pr   << MSR_PR)   |
1083         (msr_fp   << MSR_FP)   |
1084         (msr_me   << MSR_ME)   |
1085         (msr_fe0  << MSR_FE0)  |
1086         (msr_se   << MSR_SE)   | /* SE / DWE / UBLE */
1087         (msr_be   << MSR_BE)   | /* BE / DE */
1088         (msr_fe1  << MSR_FE1)  |
1089         (msr_al   << MSR_AL)   |
1090         (msr_ip   << MSR_IP)   |
1091         (msr_ir   << MSR_IR)   | /* IR / IS */
1092         (msr_dr   << MSR_DR)   | /* DR / DS */
1093         (msr_pe   << MSR_PE)   | /* PE / EP */
1094         (msr_px   << MSR_PX)   | /* PX / PMM */
1095         (msr_ri   << MSR_RI)   |
1096         (msr_le   << MSR_LE);
1097 }
1098
1099 void do_store_msr (CPUPPCState *env, target_ulong value)
1100 {
1101     int enter_pm;
1102
1103     value &= env->msr_mask;
1104     if (((value >> MSR_IR) & 1) != msr_ir ||
1105         ((value >> MSR_DR) & 1) != msr_dr) {
1106         /* Flush all tlb when changing translation mode */
1107         tlb_flush(env, 1);
1108         env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1109     }
1110 #if 0
1111     if (loglevel != 0) {
1112         fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
1113     }
1114 #endif
1115     switch (PPC_EXCP(env)) {
1116     case PPC_FLAGS_EXCP_602:
1117     case PPC_FLAGS_EXCP_603:
1118         if (((value >> MSR_TGPR) & 1) != msr_tgpr) {
1119             /* Swap temporary saved registers with GPRs */
1120             swap_gpr_tgpr(env);
1121         }
1122         break;
1123     default:
1124         break;
1125     }
1126 #if defined (TARGET_PPC64)
1127     msr_sf   = (value >> MSR_SF)   & 1;
1128     msr_isf  = (value >> MSR_ISF)  & 1;
1129     msr_hv   = (value >> MSR_HV)   & 1;
1130 #endif
1131     msr_ucle = (value >> MSR_UCLE) & 1;
1132     msr_vr   = (value >> MSR_VR)   & 1; /* VR / SPE */
1133     msr_ap   = (value >> MSR_AP)   & 1;
1134     msr_sa   = (value >> MSR_SA)   & 1;
1135     msr_key  = (value >> MSR_KEY)  & 1;
1136     msr_pow  = (value >> MSR_POW)  & 1; /* POW / WE */
1137     msr_tlb  = (value >> MSR_TLB)  & 1; /* TLB / TGPR / CE */
1138     msr_ile  = (value >> MSR_ILE)  & 1;
1139     msr_ee   = (value >> MSR_EE)   & 1;
1140     msr_pr   = (value >> MSR_PR)   & 1;
1141     msr_fp   = (value >> MSR_FP)   & 1;
1142     msr_me   = (value >> MSR_ME)   & 1;
1143     msr_fe0  = (value >> MSR_FE0)  & 1;
1144     msr_se   = (value >> MSR_SE)   & 1; /* SE / DWE / UBLE */
1145     msr_be   = (value >> MSR_BE)   & 1; /* BE / DE */
1146     msr_fe1  = (value >> MSR_FE1)  & 1;
1147     msr_al   = (value >> MSR_AL)   & 1;
1148     msr_ip   = (value >> MSR_IP)   & 1;
1149     msr_ir   = (value >> MSR_IR)   & 1; /* IR / IS */
1150     msr_dr   = (value >> MSR_DR)   & 1; /* DR / DS */
1151     msr_pe   = (value >> MSR_PE)   & 1; /* PE / EP */
1152     msr_px   = (value >> MSR_PX)   & 1; /* PX / PMM */
1153     msr_ri   = (value >> MSR_RI)   & 1;
1154     msr_le   = (value >> MSR_LE)   & 1;
1155     do_compute_hflags(env);
1156
1157     enter_pm = 0;
1158     switch (PPC_EXCP(env)) {
1159     case PPC_FLAGS_EXCP_7x0:
1160         if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
1161             enter_pm = 1;
1162         break;
1163     default:
1164         break;
1165     }
1166     if (enter_pm) {
1167         /* power save: exit cpu loop */
1168         env->halted = 1;
1169         env->exception_index = EXCP_HLT;
1170         cpu_loop_exit();
1171     }
1172 }
1173
1174 void do_compute_hflags (CPUPPCState *env)
1175 {
1176     /* Compute current hflags */
1177     env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) |
1178         (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) |
1179         (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | 
1180         (msr_se << MSR_SE) | (msr_be << MSR_BE);
1181 #if defined (TARGET_PPC64)
1182     env->hflags |= (msr_sf << MSR_SF) | (msr_hv << MSR_HV);
1183 #endif
1184 }
1185
1186 /*****************************************************************************/
1187 /* Exception processing */
1188 #if defined (CONFIG_USER_ONLY)
1189 void do_interrupt (CPUState *env)
1190 {
1191     env->exception_index = -1;
1192 }
1193 #else /* defined (CONFIG_USER_ONLY) */
1194 static void dump_syscall(CPUState *env)
1195 {
1196     fprintf(logfile, "syscall r0=0x%08x r3=0x%08x r4=0x%08x "
1197             "r5=0x%08x r6=0x%08x nip=0x%08x\n",
1198             env->gpr[0], env->gpr[3], env->gpr[4],
1199             env->gpr[5], env->gpr[6], env->nip);
1200 }
1201
1202 void do_interrupt (CPUState *env)
1203 {
1204     target_ulong msr, *srr_0, *srr_1;
1205     int excp;
1206
1207     excp = env->exception_index;
1208     msr = do_load_msr(env);
1209     /* The default is to use SRR0 & SRR1 to save the exception context */
1210     srr_0 = &env->spr[SPR_SRR0];
1211     srr_1 = &env->spr[SPR_SRR1];
1212 #if defined (DEBUG_EXCEPTIONS)
1213     if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
1214         if (loglevel != 0) {
1215             fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
1216                     (unsigned long)env->nip, excp, env->error_code);
1217             cpu_dump_state(env, logfile, fprintf, 0);
1218         }
1219     }
1220 #endif
1221     if (loglevel & CPU_LOG_INT) {
1222         fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
1223                 (unsigned long)env->nip, excp, env->error_code);
1224     }
1225     msr_pow = 0;
1226     /* Generate informations in save/restore registers */
1227     switch (excp) {
1228     /* Generic PowerPC exceptions */
1229     case EXCP_RESET: /* 0x0100 */
1230         if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) {
1231             if (msr_ip)
1232                 excp += 0xFFC00;
1233             excp |= 0xFFC00000;
1234         } else {
1235             srr_0 = &env->spr[SPR_40x_SRR2];
1236             srr_1 = &env->spr[SPR_40x_SRR3];
1237         }
1238         goto store_next;
1239     case EXCP_MACHINE_CHECK: /* 0x0200 */
1240         if (msr_me == 0) {
1241             cpu_abort(env, "Machine check exception while not allowed\n");
1242         }
1243         if (unlikely(PPC_EXCP(env) == PPC_FLAGS_EXCP_40x)) {
1244             srr_0 = &env->spr[SPR_40x_SRR2];
1245             srr_1 = &env->spr[SPR_40x_SRR3];
1246         }
1247         msr_me = 0;
1248         break;
1249     case EXCP_DSI: /* 0x0300 */
1250         /* Store exception cause */
1251         /* data location address has been stored
1252          * when the fault has been detected
1253          */
1254         msr &= ~0xFFFF0000;
1255 #if defined (DEBUG_EXCEPTIONS)
1256         if (loglevel) {
1257             fprintf(logfile, "DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
1258                     env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1259         } else {
1260             printf("DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
1261                    env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1262         }
1263 #endif
1264         goto store_next;
1265     case EXCP_ISI: /* 0x0400 */
1266         /* Store exception cause */
1267         msr &= ~0xFFFF0000;
1268         msr |= env->error_code;
1269 #if defined (DEBUG_EXCEPTIONS)
1270         if (loglevel != 0) {
1271             fprintf(logfile, "ISI exception: msr=0x%08x, nip=0x%08x\n",
1272                     msr, env->nip);
1273         }
1274 #endif
1275         goto store_next;
1276     case EXCP_EXTERNAL: /* 0x0500 */
1277         if (msr_ee == 0) {
1278 #if defined (DEBUG_EXCEPTIONS)
1279             if (loglevel > 0) {
1280                 fprintf(logfile, "Skipping hardware interrupt\n");
1281             }
1282 #endif
1283             /* Requeue it */
1284             env->interrupt_request |= CPU_INTERRUPT_HARD;
1285             return;
1286         }
1287         goto store_next;
1288     case EXCP_ALIGN: /* 0x0600 */
1289         if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) {
1290             /* Store exception cause */
1291             /* Get rS/rD and rA from faulting opcode */
1292             env->spr[SPR_DSISR] |=
1293                 (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
1294             /* data location address has been stored
1295              * when the fault has been detected
1296              */
1297         } else {
1298             /* IO error exception on PowerPC 601 */
1299             /* XXX: TODO */
1300             cpu_abort(env,
1301                       "601 IO error exception is not implemented yet !\n");
1302         }
1303         goto store_current;
1304     case EXCP_PROGRAM: /* 0x0700 */
1305         msr &= ~0xFFFF0000;
1306         switch (env->error_code & ~0xF) {
1307         case EXCP_FP:
1308             if (msr_fe0 == 0 && msr_fe1 == 0) {
1309 #if defined (DEBUG_EXCEPTIONS)
1310                 printf("Ignore floating point exception\n");
1311 #endif
1312                 return;
1313             }
1314             msr |= 0x00100000;
1315             /* Set FX */
1316             env->fpscr[7] |= 0x8;
1317             /* Finally, update FEX */
1318             if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
1319                 ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
1320                 env->fpscr[7] |= 0x4;
1321             break;
1322         case EXCP_INVAL:
1323             //      printf("Invalid instruction at 0x%08x\n", env->nip);
1324             msr |= 0x00080000;
1325             break;
1326         case EXCP_PRIV:
1327             msr |= 0x00040000;
1328             break;
1329         case EXCP_TRAP:
1330             msr |= 0x00020000;
1331             break;
1332         default:
1333             /* Should never occur */
1334             break;
1335         }
1336         msr |= 0x00010000;
1337         goto store_current;
1338     case EXCP_NO_FP: /* 0x0800 */
1339         msr &= ~0xFFFF0000;
1340         goto store_current;
1341     case EXCP_DECR:
1342         if (msr_ee == 0) {
1343 #if 1
1344             /* Requeue it */
1345             env->interrupt_request |= CPU_INTERRUPT_TIMER;
1346 #endif
1347             return;
1348         }
1349         goto store_next;
1350     case EXCP_SYSCALL: /* 0x0C00 */
1351         /* NOTE: this is a temporary hack to support graphics OSI
1352            calls from the MOL driver */
1353         if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
1354             env->osi_call) {
1355             if (env->osi_call(env) != 0)
1356                 return;
1357         }
1358         if (loglevel & CPU_LOG_INT) {
1359             dump_syscall(env);
1360         }
1361         goto store_next;
1362     case EXCP_TRACE: /* 0x0D00 */
1363         goto store_next;
1364     case EXCP_PERF: /* 0x0F00 */
1365         /* XXX: TODO */
1366         cpu_abort(env,
1367                   "Performance counter exception is not implemented yet !\n");
1368         goto store_next;
1369     /* 32 bits PowerPC specific exceptions */
1370     case EXCP_FP_ASSIST: /* 0x0E00 */
1371         /* XXX: TODO */
1372         cpu_abort(env, "Floating point assist exception "
1373                   "is not implemented yet !\n");
1374         goto store_next;
1375         /* 64 bits PowerPC exceptions */
1376     case EXCP_DSEG: /* 0x0380 */
1377         /* XXX: TODO */
1378         cpu_abort(env, "Data segment exception is not implemented yet !\n");
1379         goto store_next;
1380     case EXCP_ISEG: /* 0x0480 */
1381         /* XXX: TODO */
1382         cpu_abort(env,
1383                   "Instruction segment exception is not implemented yet !\n");
1384         goto store_next;
1385     case EXCP_HDECR: /* 0x0980 */
1386         if (msr_ee == 0) {
1387 #if 1
1388             /* Requeue it */
1389             env->interrupt_request |= CPU_INTERRUPT_TIMER;
1390 #endif
1391             return;
1392         }
1393         /* XXX: TODO */
1394         cpu_abort(env, "Hypervisor decrementer exception is not implemented "
1395                   "yet !\n");
1396         goto store_next;
1397     /* Implementation specific exceptions */
1398     case 0x0A00:
1399         if (likely(env->spr[SPR_PVR] == CPU_PPC_G2 ||
1400                    env->spr[SPR_PVR] == CPU_PPC_G2LE)) {
1401             /* Critical interrupt on G2 */
1402             /* XXX: TODO */
1403             cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
1404             goto store_next;
1405         } else {
1406             cpu_abort(env, "Invalid exception 0x0A00 !\n");
1407         }
1408         return;
1409     case 0x0F20:
1410         switch (PPC_EXCP(env)) {
1411         case PPC_FLAGS_EXCP_40x:
1412             /* APU unavailable on 405 */
1413             /* XXX: TODO */
1414             cpu_abort(env,
1415                       "APU unavailable exception is not implemented yet !\n");
1416             goto store_next;
1417         case PPC_FLAGS_EXCP_74xx:
1418             /* Altivec unavailable */
1419             /* XXX: TODO */
1420             cpu_abort(env, "Altivec unavailable exception "
1421                       "is not implemented yet !\n");
1422             goto store_next;
1423         default:
1424             cpu_abort(env, "Invalid exception 0x0F20 !\n");
1425             break;
1426         }
1427         return;
1428     case 0x1000:
1429         switch (PPC_EXCP(env)) {
1430         case PPC_FLAGS_EXCP_40x:
1431             /* PIT on 4xx */
1432             /* XXX: TODO */
1433             cpu_abort(env, "40x PIT exception is not implemented yet !\n");
1434             goto store_next;
1435         case PPC_FLAGS_EXCP_602:
1436         case PPC_FLAGS_EXCP_603:
1437             /* ITLBMISS on 602/603 */
1438             goto store_gprs;
1439         case PPC_FLAGS_EXCP_7x5:
1440             /* ITLBMISS on 745/755 */
1441             goto tlb_miss;
1442         default:
1443             cpu_abort(env, "Invalid exception 0x1000 !\n");
1444             break;
1445         }
1446         return;
1447     case 0x1010:
1448         switch (PPC_EXCP(env)) {
1449         case PPC_FLAGS_EXCP_40x:
1450             /* FIT on 4xx */
1451             /* XXX: TODO */
1452             cpu_abort(env, "40x FIT exception is not implemented yet !\n");
1453             goto store_next;
1454         default:
1455             cpu_abort(env, "Invalid exception 0x1010 !\n");
1456             break;
1457         }
1458         return;
1459     case 0x1020:
1460         switch (PPC_EXCP(env)) {
1461         case PPC_FLAGS_EXCP_40x:
1462             /* Watchdog on 4xx */
1463             /* XXX: TODO */
1464             cpu_abort(env,
1465                       "40x watchdog exception is not implemented yet !\n");
1466             goto store_next;
1467         default:
1468             cpu_abort(env, "Invalid exception 0x1020 !\n");
1469             break;
1470         }
1471         return;
1472     case 0x1100:
1473         switch (PPC_EXCP(env)) {
1474         case PPC_FLAGS_EXCP_40x:
1475             /* DTLBMISS on 4xx */
1476             /* XXX: TODO */
1477             cpu_abort(env,
1478                       "40x DTLBMISS exception is not implemented yet !\n");
1479             goto store_next;
1480         case PPC_FLAGS_EXCP_602:
1481         case PPC_FLAGS_EXCP_603:
1482             /* DLTLBMISS on 602/603 */
1483             goto store_gprs;
1484         case PPC_FLAGS_EXCP_7x5:
1485             /* DLTLBMISS on 745/755 */
1486             goto tlb_miss;
1487         default:
1488             cpu_abort(env, "Invalid exception 0x1100 !\n");
1489             break;
1490         }
1491         return;
1492     case 0x1200:
1493         switch (PPC_EXCP(env)) {
1494         case PPC_FLAGS_EXCP_40x:
1495             /* ITLBMISS on 4xx */
1496             /* XXX: TODO */
1497             cpu_abort(env,
1498                       "40x ITLBMISS exception is not implemented yet !\n");
1499             goto store_next;
1500         case PPC_FLAGS_EXCP_602:
1501         case PPC_FLAGS_EXCP_603:
1502             /* DSTLBMISS on 602/603 */
1503         store_gprs:
1504             /* Swap temporary saved registers with GPRs */
1505             swap_gpr_tgpr(env);
1506             msr_tgpr = 1;
1507 #if defined (DEBUG_SOFTWARE_TLB)
1508             if (loglevel != 0) {
1509                 const unsigned char *es;
1510                 target_ulong *miss, *cmp;
1511                 int en;
1512                 if (excp == 0x1000) {
1513                     es = "I";
1514                     en = 'I';
1515                     miss = &env->spr[SPR_IMISS];
1516                     cmp = &env->spr[SPR_ICMP];
1517                 } else {
1518                     if (excp == 0x1100)
1519                         es = "DL";
1520                     else
1521                         es = "DS";
1522                     en = 'D';
1523                     miss = &env->spr[SPR_DMISS];
1524                     cmp = &env->spr[SPR_DCMP];
1525                 }
1526                 fprintf(logfile, "6xx %sTLB miss: %cM %08x %cC %08x "
1527                         "H1 %08x H2 %08x %08x\n", es, en, *miss, en, *cmp,
1528                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
1529                         env->error_code);
1530             }
1531 #endif
1532             goto tlb_miss;
1533         case PPC_FLAGS_EXCP_7x5:
1534             /* DSTLBMISS on 745/755 */
1535         tlb_miss:
1536             msr &= ~0xF83F0000;
1537             msr |= env->crf[0] << 28;
1538             msr |= env->error_code; /* key, D/I, S/L bits */
1539             /* Set way using a LRU mechanism */
1540             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
1541             goto store_next;
1542         default:
1543             cpu_abort(env, "Invalid exception 0x1200 !\n");
1544             break;
1545         }
1546         return;
1547     case 0x1300:
1548         switch (PPC_EXCP(env)) {
1549         case PPC_FLAGS_EXCP_601:
1550         case PPC_FLAGS_EXCP_602:
1551         case PPC_FLAGS_EXCP_603:
1552         case PPC_FLAGS_EXCP_604:
1553         case PPC_FLAGS_EXCP_7x0:
1554         case PPC_FLAGS_EXCP_7x5:
1555             /* IABR on 6xx/7xx */
1556             /* XXX: TODO */
1557             cpu_abort(env, "IABR exception is not implemented yet !\n");
1558             goto store_next;
1559         default:
1560             cpu_abort(env, "Invalid exception 0x1300 !\n");
1561             break;
1562         }
1563         return;
1564     case 0x1400:
1565         switch (PPC_EXCP(env)) {
1566         case PPC_FLAGS_EXCP_601:
1567         case PPC_FLAGS_EXCP_602:
1568         case PPC_FLAGS_EXCP_603:
1569         case PPC_FLAGS_EXCP_604:
1570         case PPC_FLAGS_EXCP_7x0:
1571         case PPC_FLAGS_EXCP_7x5:
1572             /* SMI on 6xx/7xx */
1573             /* XXX: TODO */
1574             cpu_abort(env, "SMI exception is not implemented yet !\n");
1575             goto store_next;
1576         default:
1577             cpu_abort(env, "Invalid exception 0x1400 !\n");
1578             break;
1579         }
1580         return;
1581     case 0x1500:
1582         switch (PPC_EXCP(env)) {
1583         case PPC_FLAGS_EXCP_602:
1584             /* Watchdog on 602 */
1585             /* XXX: TODO */
1586             cpu_abort(env,
1587                       "602 watchdog exception is not implemented yet !\n");
1588             goto store_next;
1589         case PPC_FLAGS_EXCP_970:
1590             /* Soft patch exception on 970 */
1591             /* XXX: TODO */
1592             cpu_abort(env,
1593                       "970 soft-patch exception is not implemented yet !\n");
1594             goto store_next;
1595         case PPC_FLAGS_EXCP_74xx:
1596             /* VPU assist on 74xx */
1597             /* XXX: TODO */
1598             cpu_abort(env, "VPU assist exception is not implemented yet !\n");
1599             goto store_next;
1600         default:
1601             cpu_abort(env, "Invalid exception 0x1500 !\n");
1602             break;
1603         }
1604         return;
1605     case 0x1600:
1606         switch (PPC_EXCP(env)) {
1607         case PPC_FLAGS_EXCP_602:
1608             /* Emulation trap on 602 */
1609             /* XXX: TODO */
1610             cpu_abort(env, "602 emulation trap exception "
1611                       "is not implemented yet !\n");
1612             goto store_next;
1613         case PPC_FLAGS_EXCP_970:
1614             /* Maintenance exception on 970 */
1615             /* XXX: TODO */
1616             cpu_abort(env,
1617                       "970 maintenance exception is not implemented yet !\n");
1618             goto store_next;
1619         default:
1620             cpu_abort(env, "Invalid exception 0x1600 !\n");
1621             break;
1622         }
1623         return;
1624     case 0x1700:
1625         switch (PPC_EXCP(env)) {
1626         case PPC_FLAGS_EXCP_7x0:
1627         case PPC_FLAGS_EXCP_7x5:
1628             /* Thermal management interrupt on G3 */
1629             /* XXX: TODO */
1630             cpu_abort(env, "G3 thermal management exception "
1631                       "is not implemented yet !\n");
1632             goto store_next;
1633         case PPC_FLAGS_EXCP_970:
1634             /* VPU assist on 970 */
1635             /* XXX: TODO */
1636             cpu_abort(env,
1637                       "970 VPU assist exception is not implemented yet !\n");
1638             goto store_next;
1639         default:
1640             cpu_abort(env, "Invalid exception 0x1700 !\n");
1641             break;
1642         }
1643         return;
1644     case 0x1800:
1645         switch (PPC_EXCP(env)) {
1646         case PPC_FLAGS_EXCP_970:
1647             /* Thermal exception on 970 */
1648             /* XXX: TODO */
1649             cpu_abort(env, "970 thermal management exception "
1650                       "is not implemented yet !\n");
1651             goto store_next;
1652         default:
1653             cpu_abort(env, "Invalid exception 0x1800 !\n");
1654             break;
1655         }
1656         return;
1657     case 0x2000:
1658         switch (PPC_EXCP(env)) {
1659         case PPC_FLAGS_EXCP_40x:
1660             /* DEBUG on 4xx */
1661             /* XXX: TODO */
1662             cpu_abort(env, "40x debug exception is not implemented yet !\n");
1663             goto store_next;
1664         case PPC_FLAGS_EXCP_601:
1665             /* Run mode exception on 601 */
1666             /* XXX: TODO */
1667             cpu_abort(env,
1668                       "601 run mode exception is not implemented yet !\n");
1669             goto store_next;
1670         default:
1671             cpu_abort(env, "Invalid exception 0x1800 !\n");
1672             break;
1673         }
1674         return;
1675     /* Other exceptions */
1676     /* Qemu internal exceptions:
1677      * we should never come here with those values: abort execution
1678      */
1679     default:
1680         cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
1681         return;
1682     store_current:
1683         /* save current instruction location */
1684         *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL;
1685         break;
1686     store_next:
1687         /* save next instruction location */
1688         *srr_0 = env->nip & 0xFFFFFFFFULL;
1689         break;
1690     }
1691     /* Save msr */
1692     *srr_1 = msr;
1693     /* If we disactivated any translation, flush TLBs */
1694     if (msr_ir || msr_dr) {
1695         tlb_flush(env, 1);
1696     }
1697     /* reload MSR with correct bits */
1698     msr_ee = 0;
1699     msr_pr = 0;
1700     msr_fp = 0;
1701     msr_fe0 = 0;
1702     msr_se = 0;
1703     msr_be = 0;
1704     msr_fe1 = 0;
1705     msr_ir = 0;
1706     msr_dr = 0;
1707     msr_ri = 0;
1708     msr_le = msr_ile;
1709     msr_sf = msr_isf;
1710     do_compute_hflags(env);
1711     /* Jump to handler */
1712     env->nip = excp;
1713     env->exception_index = EXCP_NONE;
1714 }
1715 #endif /* !CONFIG_USER_ONLY */