]> Git Repo - qemu.git/blob - target-ppc/helper.c
Fix a lot of debug traces for PowerPC emulation: use logfile instead of stdout
[qemu.git] / 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, target_ulong 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_phys_addr_t 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     ppc6xx_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].tlb6;
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     ppc6xx_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].tlb6;
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 " ADDRX "\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     ppc6xx_tlb_t *tlb;
252     int nr;
253
254     nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
255     tlb = &env->tlb[nr].tlb6;
256 #if defined (DEBUG_SOFTWARE_TLB)
257     if (loglevel != 0) {
258         fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX 
259                 " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
260     }
261 #endif
262     /* Invalidate any pending reference in Qemu for this virtual address */
263     __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
264     tlb->pte0 = pte0;
265     tlb->pte1 = pte1;
266     tlb->EPN = EPN;
267     /* Store last way for LRU mechanism */
268     env->last_way = way;
269 }
270
271 static int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
272                              target_ulong eaddr, int rw, int access_type)
273 {
274     ppc6xx_tlb_t *tlb;
275     int nr, best, way;
276     int ret;
277
278     best = -1;
279     ret = -1; /* No TLB found */
280     for (way = 0; way < env->nb_ways; way++) {
281         nr = ppc6xx_tlb_getnum(env, eaddr, way,
282                                access_type == ACCESS_CODE ? 1 : 0);
283         tlb = &env->tlb[nr].tlb6;
284         /* This test "emulates" the PTE index match for hardware TLBs */
285         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
286 #if defined (DEBUG_SOFTWARE_TLB)
287             if (loglevel != 0) {
288                 fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
289                         "] <> " ADDRX "\n",
290                         nr, env->nb_tlb,
291                         pte_is_valid(tlb->pte0) ? "valid" : "inval",
292                         tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
293             }
294 #endif
295             continue;
296         }
297 #if defined (DEBUG_SOFTWARE_TLB)
298         if (loglevel != 0) {
299             fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
300                     " %c %c\n",
301                     nr, env->nb_tlb,
302                     pte_is_valid(tlb->pte0) ? "valid" : "inval",
303                     tlb->EPN, eaddr, tlb->pte1,
304                     rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
305         }
306 #endif
307         switch (pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
308         case -3:
309             /* TLB inconsistency */
310             return -1;
311         case -2:
312             /* Access violation */
313             ret = -2;
314             best = nr;
315             break;
316         case -1:
317         default:
318             /* No match */
319             break;
320         case 0:
321             /* access granted */
322             /* XXX: we should go on looping to check all TLBs consistency
323              *      but we can speed-up the whole thing as the
324              *      result would be undefined if TLBs are not consistent.
325              */
326             ret = 0;
327             best = nr;
328             goto done;
329         }
330     }
331     if (best != -1) {
332     done:
333 #if defined (DEBUG_SOFTWARE_TLB)
334         if (loglevel > 0) {
335             fprintf(logfile, "found TLB at addr 0x%08lx prot=0x%01x ret=%d\n",
336                     ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
337         }
338 #endif
339         /* Update page flags */
340         pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
341     }
342
343     return ret;
344 }
345
346 /* Perform BAT hit & translation */
347 static int get_bat (CPUState *env, mmu_ctx_t *ctx,
348                     target_ulong virtual, int rw, int type)
349 {
350     target_ulong *BATlt, *BATut, *BATu, *BATl;
351     target_ulong base, BEPIl, BEPIu, bl;
352     int i;
353     int ret = -1;
354
355 #if defined (DEBUG_BATS)
356     if (loglevel > 0) {
357         fprintf(logfile, "%s: %cBAT v 0x" ADDRX "\n", __func__,
358                 type == ACCESS_CODE ? 'I' : 'D', virtual);
359     }
360 #endif
361     switch (type) {
362     case ACCESS_CODE:
363         BATlt = env->IBAT[1];
364         BATut = env->IBAT[0];
365         break;
366     default:
367         BATlt = env->DBAT[1];
368         BATut = env->DBAT[0];
369         break;
370     }
371 #if defined (DEBUG_BATS)
372     if (loglevel > 0) {
373         fprintf(logfile, "%s...: %cBAT v 0x" ADDRX "\n", __func__,
374                 type == ACCESS_CODE ? 'I' : 'D', virtual);
375     }
376 #endif
377     base = virtual & 0xFFFC0000;
378     for (i = 0; i < 4; i++) {
379         BATu = &BATut[i];
380         BATl = &BATlt[i];
381         BEPIu = *BATu & 0xF0000000;
382         BEPIl = *BATu & 0x0FFE0000;
383         bl = (*BATu & 0x00001FFC) << 15;
384 #if defined (DEBUG_BATS)
385         if (loglevel > 0) {
386             fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX 
387                     " BATl 0x" ADDRX "\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" ADDRX
408                             " prot=%c%c\n",
409                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
410                             ctx->prot & PAGE_WRITE ? 'W' : '-');
411                 }
412 #endif
413                 ret = 0;
414                 break;
415             }
416         }
417     }
418     if (ret < 0) {
419 #if defined (DEBUG_BATS)
420         printf("no BAT match for 0x" ADDRX ":\n", virtual);
421         for (i = 0; i < 4; i++) {
422             BATu = &BATut[i];
423             BATl = &BATlt[i];
424             BEPIu = *BATu & 0xF0000000;
425             BEPIl = *BATu & 0x0FFE0000;
426             bl = (*BATu & 0x00001FFC) << 15;
427             printf("%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
428                    " BATl 0x" ADDRX " \n\t"
429                    "0x" ADDRX " 0x" ADDRX " 0x" ADDRX "\n",
430                    __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
431                    *BATu, *BATl, BEPIu, BEPIl, bl);
432         }
433 #endif
434     }
435     /* No hit */
436     return ret;
437 }
438
439 /* PTE table lookup */
440 static int find_pte (mmu_ctx_t *ctx, int h, int rw)
441 {
442     target_ulong base, pte0, pte1;
443     int i, good = -1;
444     int ret;
445
446     ret = -1; /* No entry found */
447     base = ctx->pg_addr[h];
448     for (i = 0; i < 8; i++) {
449         pte0 = ldl_phys(base + (i * 8));
450         pte1 =  ldl_phys(base + (i * 8) + 4);
451 #if defined (DEBUG_MMU)
452         if (loglevel > 0) {
453             fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX 
454                     " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
455                     base + (i * 8), pte0, pte1,
456                     pte0 >> 31, h, (pte0 >> 6) & 1, ctx->ptem);
457         }
458 #endif
459         switch (pte_check(ctx, pte0, pte1, h, rw)) {
460         case -3:
461             /* PTE inconsistency */
462             return -1;
463         case -2:
464             /* Access violation */
465             ret = -2;
466             good = i;
467             break;
468         case -1:
469         default:
470             /* No PTE match */
471             break;
472         case 0:
473             /* access granted */
474             /* XXX: we should go on looping to check all PTEs consistency
475              *      but if we can speed-up the whole thing as the
476              *      result would be undefined if PTEs are not consistent.
477              */
478             ret = 0;
479             good = i;
480             goto done;
481         }
482     }
483     if (good != -1) {
484     done:
485 #if defined (DEBUG_MMU)
486         if (loglevel > 0) {
487             fprintf(logfile, "found PTE at addr 0x" ADDRX " prot=0x%01x "
488                     "ret=%d\n",
489                     ctx->raddr, ctx->prot, ret);
490         }
491 #endif
492         /* Update page flags */
493         pte1 = ctx->raddr;
494         if (pte_update_flags(ctx, &pte1, ret, rw) == 1)
495             stl_phys_notdirty(base + (good * 8) + 4, pte1);
496     }
497
498     return ret;
499 }
500
501 static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
502                                              target_phys_addr_t hash,
503                                              target_phys_addr_t mask)
504 {
505     return (sdr1 & 0xFFFF0000) | (hash & mask);
506 }
507
508 /* Perform segment based translation */
509 static int get_segment (CPUState *env, mmu_ctx_t *ctx,
510                         target_ulong eaddr, int rw, int type)
511 {
512     target_phys_addr_t sdr, hash, mask;
513     target_ulong sr, vsid, pgidx;
514     int ret = -1, ret2;
515
516     sr = env->sr[eaddr >> 28];
517 #if defined (DEBUG_MMU)
518     if (loglevel > 0) {
519         fprintf(logfile, "Check segment v=0x" ADDRX " %d 0x" ADDRX " nip=0x"
520                 ADDRX " lr=0x" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
521                 eaddr, eaddr >> 28, sr, env->nip,
522                 env->lr, msr_ir, msr_dr, msr_pr, rw, type);
523     }
524 #endif
525     ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
526                 ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
527     if ((sr & 0x80000000) == 0) {
528 #if defined (DEBUG_MMU)
529         if (loglevel > 0) 
530             fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n",
531                     ctx->key, sr & 0x10000000);
532 #endif
533         /* Check if instruction fetch is allowed, if needed */
534         if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
535             /* Page address translation */
536             pgidx = (eaddr >> TARGET_PAGE_BITS) & 0xFFFF;
537             vsid = sr & 0x00FFFFFF;
538             hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
539             /* Primary table address */
540             sdr = env->sdr1;
541             mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
542             ctx->pg_addr[0] = get_pgaddr(sdr, hash, mask);
543             /* Secondary table address */
544             hash = (~hash) & 0x01FFFFC0;
545             ctx->pg_addr[1] = get_pgaddr(sdr, hash, mask);
546             ctx->ptem = (vsid << 7) | (pgidx >> 10);
547             /* Initialize real address with an invalid value */
548             ctx->raddr = (target_ulong)-1;
549             if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
550                 /* Software TLB search */
551                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
552             } else {
553 #if defined (DEBUG_MMU)
554                 if (loglevel > 0) {
555                     fprintf(logfile, "0 sdr1=0x" ADDRX " vsid=0x%06x "
556                             "api=0x%04x hash=0x%07x pg_addr=0x" ADDRX "\n",
557                             sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
558                 }
559 #endif
560                 /* Primary table lookup */
561                 ret = find_pte(ctx, 0, rw);
562                 if (ret < 0) {
563                     /* Secondary table lookup */
564 #if defined (DEBUG_MMU)
565                     if (eaddr != 0xEFFFFFFF && loglevel > 0) {
566                         fprintf(logfile,
567                                 "1 sdr1=0x" ADDRX " vsid=0x%06x api=0x%04x "
568                                 "hash=0x%05x pg_addr=0x" ADDRX "\n",
569                                 sdr, vsid, pgidx, hash, ctx->pg_addr[1]);
570                     }
571 #endif
572                     ret2 = find_pte(ctx, 1, rw);
573                     if (ret2 != -1)
574                         ret = ret2;
575                 }
576             }
577         } else {
578 #if defined (DEBUG_MMU)
579             if (loglevel > 0)
580                 fprintf(logfile, "No access allowed\n");
581 #endif
582             ret = -3;
583         }
584     } else {
585 #if defined (DEBUG_MMU)
586         if (loglevel > 0)
587             fprintf(logfile, "direct store...\n");
588 #endif
589         /* Direct-store segment : absolutely *BUGGY* for now */
590         switch (type) {
591         case ACCESS_INT:
592             /* Integer load/store : only access allowed */
593             break;
594         case ACCESS_CODE:
595             /* No code fetch is allowed in direct-store areas */
596             return -4;
597         case ACCESS_FLOAT:
598             /* Floating point load/store */
599             return -4;
600         case ACCESS_RES:
601             /* lwarx, ldarx or srwcx. */
602             return -4;
603         case ACCESS_CACHE:
604             /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
605             /* Should make the instruction do no-op.
606              * As it already do no-op, it's quite easy :-)
607              */
608             ctx->raddr = eaddr;
609             return 0;
610         case ACCESS_EXT:
611             /* eciwx or ecowx */
612             return -4;
613         default:
614             if (logfile) {
615                 fprintf(logfile, "ERROR: instruction should not need "
616                         "address translation\n");
617             }
618             printf("ERROR: instruction should not need "
619                    "address translation\n");
620             return -4;
621         }
622         if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
623             ctx->raddr = eaddr;
624             ret = 2;
625         } else {
626             ret = -2;
627         }
628     }
629
630     return ret;
631 }
632
633 int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
634                                  target_ulong address, int rw, int access_type)
635 {
636     ppcemb_tlb_t *tlb;
637     target_phys_addr_t raddr;
638     target_ulong mask;
639     int i, ret, zsel, zpr;
640             
641     ret = -6;
642     for (i = 0; i < env->nb_tlb; i++) {
643         tlb = &env->tlb[i].tlbe;
644         /* Check valid flag */
645         if (!(tlb->prot & PAGE_VALID)) {
646             if (loglevel)
647                 fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
648             continue;
649         }
650         mask = ~(tlb->size - 1);
651         if (loglevel) {
652             fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
653                     ADDRX " " ADDRX " %d\n",
654                     __func__, i, address, (int)env->spr[SPR_40x_PID],
655                     tlb->EPN, mask, (int)tlb->PID);
656         }
657         /* Check PID */
658         if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
659             continue;
660         /* Check effective address */
661         if ((address & mask) != tlb->EPN)
662             continue;
663         raddr = (tlb->RPN & mask) | (address & ~mask);
664         zsel = (tlb->attr >> 4) & 0xF;
665         zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
666         if (loglevel) {
667             fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
668                     __func__, i, zsel, zpr, rw, tlb->attr);
669         }
670         if (access_type == ACCESS_CODE) {
671             /* Check execute enable bit */
672             switch (zpr) {
673             case 0x0:
674                 if (msr_pr) {
675                     ret = -3;
676                     ctx->prot = 0;
677                     break;
678                 }
679                 /* No break here */
680             case 0x1:
681             case 0x2:
682                 /* Check from TLB entry */
683                 if (!(tlb->prot & PAGE_EXEC)) {
684                     ret = -3;
685                 } else {
686                     if (tlb->prot & PAGE_WRITE)
687                         ctx->prot = PAGE_READ | PAGE_WRITE;
688                     else
689                         ctx->prot = PAGE_READ;
690                     ret = 0;
691                 }
692                 break;
693             case 0x3:
694                 /* All accesses granted */
695                 ret = 0;
696                 ctx->prot = PAGE_READ | PAGE_WRITE;
697                 break;
698             }
699         } else {
700             switch (zpr) {
701             case 0x0:
702                 if (msr_pr) {
703                     ret = -2;
704                     ctx->prot = 0;
705                     break;
706                 }
707                 /* No break here */
708             case 0x1:
709             case 0x2:
710                 /* Check from TLB entry */
711                 /* Check write protection bit */
712                 if (rw && !(tlb->prot & PAGE_WRITE)) {
713                     ret = -2;
714                 } else {
715                     ret = 2;
716                     if (tlb->prot & PAGE_WRITE)
717                         ctx->prot = PAGE_READ | PAGE_WRITE;
718                     else
719                         ctx->prot = PAGE_READ;
720                 }
721                 break;
722             case 0x3:
723                 /* All accesses granted */
724                 ret = 2;
725                 ctx->prot = PAGE_READ | PAGE_WRITE;
726                 break;
727             }
728         }
729         if (ret >= 0) {
730             ctx->raddr = raddr;
731             if (loglevel) {
732                 fprintf(logfile, "%s: access granted " ADDRX " => " REGX
733                         " %d\n", __func__, address, ctx->raddr, ctx->prot);
734             }
735             return i;
736         }
737     }
738     
739     return ret;
740 }
741
742 static int check_physical (CPUState *env, mmu_ctx_t *ctx,
743                            target_ulong eaddr, int rw)
744 {
745     int in_plb, ret;
746         
747     ctx->raddr = eaddr;
748     ctx->prot = PAGE_READ;
749     ret = 0;
750     if (unlikely(msr_pe != 0 && PPC_MMU(env) == PPC_FLAGS_MMU_403)) {
751         /* 403 family add some particular protections,
752          * using PBL/PBU registers for accesses with no translation.
753          */
754         in_plb =
755             /* Check PLB validity */
756             (env->pb[0] < env->pb[1] &&
757              /* and address in plb area */
758              eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
759             (env->pb[2] < env->pb[3] &&
760              eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
761         if (in_plb ^ msr_px) {
762             /* Access in protected area */
763             if (rw == 1) {
764                 /* Access is not allowed */
765                 ret = -2;
766             }
767         } else {
768             /* Read-write access is allowed */
769             ctx->prot |= PAGE_WRITE;
770         }
771     } else {
772         ctx->prot |= PAGE_WRITE;
773     }
774
775     return ret;
776 }
777
778 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
779                           int rw, int access_type, int check_BATs)
780 {
781     int ret;
782 #if 0
783     if (loglevel > 0) {
784         fprintf(logfile, "%s\n", __func__);
785     }
786 #endif
787     if ((access_type == ACCESS_CODE && msr_ir == 0) ||
788         (access_type != ACCESS_CODE && msr_dr == 0)) {
789         /* No address translation */
790         ret = check_physical(env, ctx, eaddr, rw);
791     } else {
792         switch (PPC_MMU(env)) {
793         case PPC_FLAGS_MMU_32B:
794         case PPC_FLAGS_MMU_SOFT_6xx:
795             /* Try to find a BAT */
796             ret = -1;
797             if (check_BATs)
798                 ret = get_bat(env, ctx, eaddr, rw, access_type);
799             if (ret < 0) {
800                 /* We didn't match any BAT entry */
801                 ret = get_segment(env, ctx, eaddr, rw, access_type);
802             }
803             break;
804         case PPC_FLAGS_MMU_SOFT_4xx:
805             ret = mmu4xx_get_physical_address(env, ctx, eaddr,
806                                               rw, access_type);
807             break;
808         default:
809             /* XXX: TODO */
810             cpu_abort(env, "MMU model not implemented\n");
811             return -1;
812         }
813     }
814 #if 0
815     if (loglevel > 0) {
816         fprintf(logfile, "%s address " ADDRX " => " ADDRX "\n",
817                 __func__, eaddr, ctx->raddr);
818     }
819 #endif
820
821     return ret;
822 }
823
824 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
825 {
826     mmu_ctx_t ctx;
827
828     if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
829         return -1;
830
831     return ctx.raddr & TARGET_PAGE_MASK;
832 }
833
834 /* Perform address translation */
835 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
836                               int is_user, int is_softmmu)
837 {
838     mmu_ctx_t ctx;
839     int exception = 0, error_code = 0;
840     int access_type;
841     int ret = 0;
842
843     if (rw == 2) {
844         /* code access */
845         rw = 0;
846         access_type = ACCESS_CODE;
847     } else {
848         /* data access */
849         /* XXX: put correct access by using cpu_restore_state()
850            correctly */
851         access_type = ACCESS_INT;
852         //        access_type = env->access_type;
853     }
854     ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
855     if (ret == 0) {
856         ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
857                            ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
858                            is_user, is_softmmu);
859     } else if (ret < 0) {
860 #if defined (DEBUG_MMU)
861         if (loglevel > 0)
862             cpu_dump_state(env, logfile, fprintf, 0);
863 #endif
864         if (access_type == ACCESS_CODE) {
865             exception = EXCP_ISI;
866             switch (ret) {
867             case -1:
868                 /* No matches in page tables or TLB */
869                 if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
870                     exception = EXCP_I_TLBMISS;
871                     env->spr[SPR_IMISS] = address;
872                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
873                     error_code = 1 << 18;
874                     goto tlb_miss;
875                 } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
876                     exception = EXCP_40x_ITLBMISS;
877                     error_code = 0;
878                     env->spr[SPR_40x_DEAR] = address;
879                     env->spr[SPR_40x_ESR] = 0x00000000;
880                 } else {
881                     error_code = 0x40000000;
882                 }
883                 break;
884             case -2:
885                 /* Access rights violation */
886                 error_code = 0x08000000;
887                 break;
888             case -3:
889                 /* No execute protection violation */
890                 error_code = 0x10000000;
891                 break;
892             case -4:
893                 /* Direct store exception */
894                 /* No code fetch is allowed in direct-store areas */
895                 error_code = 0x10000000;
896                 break;
897             case -5:
898                 /* No match in segment table */
899                 exception = EXCP_ISEG;
900                 error_code = 0;
901                 break;
902             }
903         } else {
904             exception = EXCP_DSI;
905             switch (ret) {
906             case -1:
907                 /* No matches in page tables or TLB */
908                 if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
909                     if (rw == 1) {
910                         exception = EXCP_DS_TLBMISS;
911                         error_code = 1 << 16;
912                     } else {
913                         exception = EXCP_DL_TLBMISS;
914                         error_code = 0;
915                     }
916                     env->spr[SPR_DMISS] = address;
917                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
918                 tlb_miss:
919                     error_code |= ctx.key << 19;
920                     env->spr[SPR_HASH1] = ctx.pg_addr[0];
921                     env->spr[SPR_HASH2] = ctx.pg_addr[1];
922                     /* Do not alter DAR nor DSISR */
923                     goto out;
924                 } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
925                     exception = EXCP_40x_DTLBMISS;
926                     error_code = 0;
927                     env->spr[SPR_40x_DEAR] = address;
928                     if (rw)
929                         env->spr[SPR_40x_ESR] = 0x00800000;
930                     else
931                         env->spr[SPR_40x_ESR] = 0x00000000;
932                 } else {
933                     error_code = 0x40000000;
934                 }
935                 break;
936             case -2:
937                 /* Access rights violation */
938                 error_code = 0x08000000;
939                 break;
940             case -4:
941                 /* Direct store exception */
942                 switch (access_type) {
943                 case ACCESS_FLOAT:
944                     /* Floating point load/store */
945                     exception = EXCP_ALIGN;
946                     error_code = EXCP_ALIGN_FP;
947                     break;
948                 case ACCESS_RES:
949                     /* lwarx, ldarx or srwcx. */
950                     error_code = 0x04000000;
951                     break;
952                 case ACCESS_EXT:
953                     /* eciwx or ecowx */
954                     error_code = 0x04100000;
955                     break;
956                 default:
957                     printf("DSI: invalid exception (%d)\n", ret);
958                     exception = EXCP_PROGRAM;
959                     error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
960                     break;
961                 }
962                 break;
963             case -5:
964                 /* No match in segment table */
965                 exception = EXCP_DSEG;
966                 error_code = 0;
967                 break;
968             }
969             if (exception == EXCP_DSI && rw == 1)
970                 error_code |= 0x02000000;
971             /* Store fault address */
972             env->spr[SPR_DAR] = address;
973             env->spr[SPR_DSISR] = error_code;
974         }
975     out:
976 #if 0
977         printf("%s: set exception to %d %02x\n",
978                __func__, exception, error_code);
979 #endif
980         env->exception_index = exception;
981         env->error_code = error_code;
982         ret = 1;
983     }
984
985     return ret;
986 }
987
988 /*****************************************************************************/
989 /* BATs management */
990 #if !defined(FLUSH_ALL_TLBS)
991 static inline void do_invalidate_BAT (CPUPPCState *env,
992                                       target_ulong BATu, target_ulong mask)
993 {
994     target_ulong base, end, page;
995
996     base = BATu & ~0x0001FFFF;
997     end = base + mask + 0x00020000;
998 #if defined (DEBUG_BATS)
999     if (loglevel != 0) {
1000         fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1001                 base, end, mask);
1002     }
1003 #endif
1004     for (page = base; page != end; page += TARGET_PAGE_SIZE)
1005         tlb_flush_page(env, page);
1006 #if defined (DEBUG_BATS)
1007     if (loglevel != 0)
1008         fprintf(logfile, "Flush done\n");
1009 #endif
1010 }
1011 #endif
1012
1013 static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
1014                                    target_ulong value)
1015 {
1016 #if defined (DEBUG_BATS)
1017     if (loglevel != 0) {
1018         fprintf(logfile, "Set %cBAT%d%c to 0x" ADDRX " (0x" ADDRX ")\n",
1019                 ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1020     }
1021 #endif
1022 }
1023
1024 target_ulong do_load_ibatu (CPUPPCState *env, int nr)
1025 {
1026     return env->IBAT[0][nr];
1027 }
1028
1029 target_ulong do_load_ibatl (CPUPPCState *env, int nr)
1030 {
1031     return env->IBAT[1][nr];
1032 }
1033
1034 void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1035 {
1036     target_ulong mask;
1037
1038     dump_store_bat(env, 'I', 0, nr, value);
1039     if (env->IBAT[0][nr] != value) {
1040         mask = (value << 15) & 0x0FFE0000UL;
1041 #if !defined(FLUSH_ALL_TLBS)
1042         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1043 #endif
1044         /* When storing valid upper BAT, mask BEPI and BRPN
1045          * and invalidate all TLBs covered by this BAT
1046          */
1047         mask = (value << 15) & 0x0FFE0000UL;
1048         env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1049             (value & ~0x0001FFFFUL & ~mask);
1050         env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1051             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1052 #if !defined(FLUSH_ALL_TLBS)
1053         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1054 #else
1055         tlb_flush(env, 1);
1056 #endif
1057     }
1058 }
1059
1060 void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1061 {
1062     dump_store_bat(env, 'I', 1, nr, value);
1063     env->IBAT[1][nr] = value;
1064 }
1065
1066 target_ulong do_load_dbatu (CPUPPCState *env, int nr)
1067 {
1068     return env->DBAT[0][nr];
1069 }
1070
1071 target_ulong do_load_dbatl (CPUPPCState *env, int nr)
1072 {
1073     return env->DBAT[1][nr];
1074 }
1075
1076 void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1077 {
1078     target_ulong mask;
1079
1080     dump_store_bat(env, 'D', 0, nr, value);
1081     if (env->DBAT[0][nr] != value) {
1082         /* When storing valid upper BAT, mask BEPI and BRPN
1083          * and invalidate all TLBs covered by this BAT
1084          */
1085         mask = (value << 15) & 0x0FFE0000UL;
1086 #if !defined(FLUSH_ALL_TLBS)
1087         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1088 #endif
1089         mask = (value << 15) & 0x0FFE0000UL;
1090         env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1091             (value & ~0x0001FFFFUL & ~mask);
1092         env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1093             (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1094 #if !defined(FLUSH_ALL_TLBS)
1095         do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1096 #else
1097         tlb_flush(env, 1);
1098 #endif
1099     }
1100 }
1101
1102 void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1103 {
1104     dump_store_bat(env, 'D', 1, nr, value);
1105     env->DBAT[1][nr] = value;
1106 }
1107
1108 /*****************************************************************************/
1109 /* Special registers manipulation */
1110 #if defined(TARGET_PPC64)
1111 target_ulong ppc_load_asr (CPUPPCState *env)
1112 {
1113     return env->asr;
1114 }
1115
1116 void ppc_store_asr (CPUPPCState *env, target_ulong value)
1117 {
1118     if (env->asr != value) {
1119         env->asr = value;
1120         tlb_flush(env, 1);
1121     }
1122 }
1123 #endif
1124
1125 target_ulong do_load_sdr1 (CPUPPCState *env)
1126 {
1127     return env->sdr1;
1128 }
1129
1130 void do_store_sdr1 (CPUPPCState *env, target_ulong value)
1131 {
1132 #if defined (DEBUG_MMU)
1133     if (loglevel != 0) {
1134         fprintf(logfile, "%s: 0x" ADDRX "\n", __func__, value);
1135     }
1136 #endif
1137     if (env->sdr1 != value) {
1138         env->sdr1 = value;
1139         tlb_flush(env, 1);
1140     }
1141 }
1142
1143 target_ulong do_load_sr (CPUPPCState *env, int srnum)
1144 {
1145     return env->sr[srnum];
1146 }
1147
1148 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1149 {
1150 #if defined (DEBUG_MMU)
1151     if (loglevel != 0) {
1152         fprintf(logfile, "%s: reg=%d 0x" ADDRX " " ADDRX "\n",
1153                 __func__, srnum, value, env->sr[srnum]);
1154     }
1155 #endif
1156     if (env->sr[srnum] != value) {
1157         env->sr[srnum] = value;
1158 #if !defined(FLUSH_ALL_TLBS) && 0
1159         {
1160             target_ulong page, end;
1161             /* Invalidate 256 MB of virtual memory */
1162             page = (16 << 20) * srnum;
1163             end = page + (16 << 20);
1164             for (; page != end; page += TARGET_PAGE_SIZE)
1165                 tlb_flush_page(env, page);
1166         }
1167 #else
1168         tlb_flush(env, 1);
1169 #endif
1170     }
1171 }
1172 #endif /* !defined (CONFIG_USER_ONLY) */
1173
1174 uint32_t ppc_load_xer (CPUPPCState *env)
1175 {
1176     return (xer_so << XER_SO) |
1177         (xer_ov << XER_OV) |
1178         (xer_ca << XER_CA) |
1179         (xer_bc << XER_BC) |
1180         (xer_cmp << XER_CMP);
1181 }
1182
1183 void ppc_store_xer (CPUPPCState *env, uint32_t value)
1184 {
1185     xer_so = (value >> XER_SO) & 0x01;
1186     xer_ov = (value >> XER_OV) & 0x01;
1187     xer_ca = (value >> XER_CA) & 0x01;
1188     xer_cmp = (value >> XER_CMP) & 0xFF;
1189     xer_bc = (value >> XER_BC) & 0x7F;
1190 }
1191
1192 /* Swap temporary saved registers with GPRs */
1193 static inline void swap_gpr_tgpr (CPUPPCState *env)
1194 {
1195     ppc_gpr_t tmp;
1196
1197     tmp = env->gpr[0];
1198     env->gpr[0] = env->tgpr[0];
1199     env->tgpr[0] = tmp;
1200     tmp = env->gpr[1];
1201     env->gpr[1] = env->tgpr[1];
1202     env->tgpr[1] = tmp;
1203     tmp = env->gpr[2];
1204     env->gpr[2] = env->tgpr[2];
1205     env->tgpr[2] = tmp;
1206     tmp = env->gpr[3];
1207     env->gpr[3] = env->tgpr[3];
1208     env->tgpr[3] = tmp;
1209 }
1210
1211 /* GDBstub can read and write MSR... */
1212 target_ulong do_load_msr (CPUPPCState *env)
1213 {
1214     return
1215 #if defined (TARGET_PPC64)
1216         ((target_ulong)msr_sf   << MSR_SF)   |
1217         ((target_ulong)msr_isf  << MSR_ISF)  |
1218         ((target_ulong)msr_hv   << MSR_HV)   |
1219 #endif
1220         ((target_ulong)msr_ucle << MSR_UCLE) |
1221         ((target_ulong)msr_vr   << MSR_VR)   | /* VR / SPE */
1222         ((target_ulong)msr_ap   << MSR_AP)   |
1223         ((target_ulong)msr_sa   << MSR_SA)   |
1224         ((target_ulong)msr_key  << MSR_KEY)  |
1225         ((target_ulong)msr_pow  << MSR_POW)  | /* POW / WE */
1226         ((target_ulong)msr_tlb  << MSR_TLB)  | /* TLB / TGPE / CE */
1227         ((target_ulong)msr_ile  << MSR_ILE)  |
1228         ((target_ulong)msr_ee   << MSR_EE)   |
1229         ((target_ulong)msr_pr   << MSR_PR)   |
1230         ((target_ulong)msr_fp   << MSR_FP)   |
1231         ((target_ulong)msr_me   << MSR_ME)   |
1232         ((target_ulong)msr_fe0  << MSR_FE0)  |
1233         ((target_ulong)msr_se   << MSR_SE)   | /* SE / DWE / UBLE */
1234         ((target_ulong)msr_be   << MSR_BE)   | /* BE / DE */
1235         ((target_ulong)msr_fe1  << MSR_FE1)  |
1236         ((target_ulong)msr_al   << MSR_AL)   |
1237         ((target_ulong)msr_ip   << MSR_IP)   |
1238         ((target_ulong)msr_ir   << MSR_IR)   | /* IR / IS */
1239         ((target_ulong)msr_dr   << MSR_DR)   | /* DR / DS */
1240         ((target_ulong)msr_pe   << MSR_PE)   | /* PE / EP */
1241         ((target_ulong)msr_px   << MSR_PX)   | /* PX / PMM */
1242         ((target_ulong)msr_ri   << MSR_RI)   |
1243         ((target_ulong)msr_le   << MSR_LE);
1244 }
1245
1246 void do_store_msr (CPUPPCState *env, target_ulong value)
1247 {
1248     int enter_pm;
1249
1250     value &= env->msr_mask;
1251     if (((value >> MSR_IR) & 1) != msr_ir ||
1252         ((value >> MSR_DR) & 1) != msr_dr) {
1253         /* Flush all tlb when changing translation mode */
1254         tlb_flush(env, 1);
1255         env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1256     }
1257 #if 0
1258     if (loglevel != 0) {
1259         fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
1260     }
1261 #endif
1262     switch (PPC_EXCP(env)) {
1263     case PPC_FLAGS_EXCP_602:
1264     case PPC_FLAGS_EXCP_603:
1265         if (((value >> MSR_TGPR) & 1) != msr_tgpr) {
1266             /* Swap temporary saved registers with GPRs */
1267             swap_gpr_tgpr(env);
1268         }
1269         break;
1270     default:
1271         break;
1272     }
1273 #if defined (TARGET_PPC64)
1274     msr_sf   = (value >> MSR_SF)   & 1;
1275     msr_isf  = (value >> MSR_ISF)  & 1;
1276     msr_hv   = (value >> MSR_HV)   & 1;
1277 #endif
1278     msr_ucle = (value >> MSR_UCLE) & 1;
1279     msr_vr   = (value >> MSR_VR)   & 1; /* VR / SPE */
1280     msr_ap   = (value >> MSR_AP)   & 1;
1281     msr_sa   = (value >> MSR_SA)   & 1;
1282     msr_key  = (value >> MSR_KEY)  & 1;
1283     msr_pow  = (value >> MSR_POW)  & 1; /* POW / WE */
1284     msr_tlb  = (value >> MSR_TLB)  & 1; /* TLB / TGPR / CE */
1285     msr_ile  = (value >> MSR_ILE)  & 1;
1286     msr_ee   = (value >> MSR_EE)   & 1;
1287     msr_pr   = (value >> MSR_PR)   & 1;
1288     msr_fp   = (value >> MSR_FP)   & 1;
1289     msr_me   = (value >> MSR_ME)   & 1;
1290     msr_fe0  = (value >> MSR_FE0)  & 1;
1291     msr_se   = (value >> MSR_SE)   & 1; /* SE / DWE / UBLE */
1292     msr_be   = (value >> MSR_BE)   & 1; /* BE / DE */
1293     msr_fe1  = (value >> MSR_FE1)  & 1;
1294     msr_al   = (value >> MSR_AL)   & 1;
1295     msr_ip   = (value >> MSR_IP)   & 1;
1296     msr_ir   = (value >> MSR_IR)   & 1; /* IR / IS */
1297     msr_dr   = (value >> MSR_DR)   & 1; /* DR / DS */
1298     msr_pe   = (value >> MSR_PE)   & 1; /* PE / EP */
1299     msr_px   = (value >> MSR_PX)   & 1; /* PX / PMM */
1300     msr_ri   = (value >> MSR_RI)   & 1;
1301     msr_le   = (value >> MSR_LE)   & 1;
1302     do_compute_hflags(env);
1303
1304     enter_pm = 0;
1305     switch (PPC_EXCP(env)) {
1306     case PPC_FLAGS_EXCP_603:
1307         /* Don't handle SLEEP mode: we should disable all clocks...
1308          * No dynamic power-management.
1309          */
1310         if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00C00000) != 0)
1311             enter_pm = 1;
1312         break;
1313     case PPC_FLAGS_EXCP_604:
1314         if (msr_pow == 1)
1315             enter_pm = 1;
1316         break;
1317     case PPC_FLAGS_EXCP_7x0:
1318         if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
1319             enter_pm = 1;
1320         break;
1321     default:
1322         break;
1323     }
1324     if (enter_pm) {
1325         /* power save: exit cpu loop */
1326         env->halted = 1;
1327         env->exception_index = EXCP_HLT;
1328         cpu_loop_exit();
1329     }
1330 }
1331
1332 #if defined(TARGET_PPC64)
1333 void ppc_store_msr_32 (CPUPPCState *env, uint32_t value)
1334 {
1335     do_store_msr(env,
1336                  (do_load_msr(env) & ~0xFFFFFFFFULL) | (value & 0xFFFFFFFF));
1337 }
1338 #endif
1339
1340 void do_compute_hflags (CPUPPCState *env)
1341 {
1342     /* Compute current hflags */
1343     env->hflags = (msr_cm << MSR_CM) | (msr_vr << MSR_VR) |
1344         (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | (msr_pr << MSR_PR) |
1345         (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) |
1346         (msr_be << MSR_BE) | (msr_fe1 << MSR_FE1) | (msr_le << MSR_LE);
1347 #if defined (TARGET_PPC64)
1348     /* No care here: PowerPC 64 MSR_SF means the same as MSR_CM for BookE */
1349     env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32));
1350 #endif
1351 }
1352
1353 /*****************************************************************************/
1354 /* Exception processing */
1355 #if defined (CONFIG_USER_ONLY)
1356 void do_interrupt (CPUState *env)
1357 {
1358     env->exception_index = -1;
1359 }
1360
1361 void ppc_hw_interrupt (CPUState *env)
1362 {
1363     env->exception_index = -1;
1364 }
1365 #else /* defined (CONFIG_USER_ONLY) */
1366 static void dump_syscall(CPUState *env)
1367 {
1368     fprintf(logfile, "syscall r0=0x" REGX " r3=0x" REGX " r4=0x" REGX
1369             " r5=0x" REGX " r6=0x" REGX " nip=0x" ADDRX "\n",
1370             env->gpr[0], env->gpr[3], env->gpr[4],
1371             env->gpr[5], env->gpr[6], env->nip);
1372 }
1373
1374 void do_interrupt (CPUState *env)
1375 {
1376     target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1;
1377     int excp, idx;
1378
1379     excp = env->exception_index;
1380     msr = do_load_msr(env);
1381     /* The default is to use SRR0 & SRR1 to save the exception context */
1382     srr_0 = &env->spr[SPR_SRR0];
1383     srr_1 = &env->spr[SPR_SRR1];
1384     asrr_0 = NULL;
1385     asrr_1 = NULL;
1386 #if defined (DEBUG_EXCEPTIONS)
1387     if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
1388         if (loglevel != 0) {
1389             fprintf(logfile,
1390                     "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
1391                     env->nip, excp, env->error_code);
1392             cpu_dump_state(env, logfile, fprintf, 0);
1393         }
1394     }
1395 #endif
1396     if (loglevel & CPU_LOG_INT) {
1397         fprintf(logfile, "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
1398                 env->nip, excp, env->error_code);
1399     }
1400     msr_pow = 0;
1401     idx = -1;
1402     /* Generate informations in save/restore registers */
1403     switch (excp) {
1404     /* Generic PowerPC exceptions */
1405     case EXCP_RESET: /* 0x0100 */
1406         switch (PPC_EXCP(env)) {
1407         case PPC_FLAGS_EXCP_40x:
1408             srr_0 = &env->spr[SPR_40x_SRR2];
1409             srr_1 = &env->spr[SPR_40x_SRR3];
1410             break;
1411         case PPC_FLAGS_EXCP_BOOKE:
1412             idx = 0;
1413             srr_0 = &env->spr[SPR_BOOKE_CSRR0];
1414             srr_1 = &env->spr[SPR_BOOKE_CSRR1];
1415             break;
1416         default:
1417             if (msr_ip)
1418                 excp += 0xFFC00;
1419             excp |= 0xFFC00000;
1420             break;
1421         }
1422         goto store_next;
1423     case EXCP_MACHINE_CHECK: /* 0x0200 */
1424         switch (PPC_EXCP(env)) {
1425         case PPC_FLAGS_EXCP_40x:
1426             srr_0 = &env->spr[SPR_40x_SRR2];
1427             srr_1 = &env->spr[SPR_40x_SRR3];
1428             break;
1429         case PPC_FLAGS_EXCP_BOOKE:
1430             idx = 1;
1431             srr_0 = &env->spr[SPR_BOOKE_MCSRR0];
1432             srr_1 = &env->spr[SPR_BOOKE_MCSRR1];
1433             asrr_0 = &env->spr[SPR_BOOKE_CSRR0];
1434             asrr_1 = &env->spr[SPR_BOOKE_CSRR1];
1435             msr_ce = 0;
1436             break;
1437         default:
1438             break;
1439         }
1440         msr_me = 0;
1441         break;
1442     case EXCP_DSI: /* 0x0300 */
1443         /* Store exception cause */
1444         /* data location address has been stored
1445          * when the fault has been detected
1446          */
1447         idx = 2;
1448         msr &= ~0xFFFF0000;
1449 #if defined (DEBUG_EXCEPTIONS)
1450         if (loglevel) {
1451             fprintf(logfile, "DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX
1452                     "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1453         }
1454 #endif
1455         goto store_next;
1456     case EXCP_ISI: /* 0x0400 */
1457         /* Store exception cause */
1458         idx = 3;
1459         msr &= ~0xFFFF0000;
1460         msr |= env->error_code;
1461 #if defined (DEBUG_EXCEPTIONS)
1462         if (loglevel != 0) {
1463             fprintf(logfile, "ISI exception: msr=0x" ADDRX ", nip=0x" ADDRX
1464                     "\n", msr, env->nip);
1465         }
1466 #endif
1467         goto store_next;
1468     case EXCP_EXTERNAL: /* 0x0500 */
1469         idx = 4;
1470         goto store_next;
1471     case EXCP_ALIGN: /* 0x0600 */
1472         if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) {
1473             /* Store exception cause */
1474             idx = 5;
1475             /* Get rS/rD and rA from faulting opcode */
1476             env->spr[SPR_DSISR] |=
1477                 (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
1478             /* data location address has been stored
1479              * when the fault has been detected
1480              */
1481         } else {
1482             /* IO error exception on PowerPC 601 */
1483             /* XXX: TODO */
1484             cpu_abort(env,
1485                       "601 IO error exception is not implemented yet !\n");
1486         }
1487         goto store_current;
1488     case EXCP_PROGRAM: /* 0x0700 */
1489         idx = 6;
1490         msr &= ~0xFFFF0000;
1491         switch (env->error_code & ~0xF) {
1492         case EXCP_FP:
1493             if (msr_fe0 == 0 && msr_fe1 == 0) {
1494 #if defined (DEBUG_EXCEPTIONS)
1495                 if (loglevel) {
1496                     fprintf(logfile, "Ignore floating point exception\n");
1497                 }
1498 #endif
1499                 return;
1500             }
1501             msr |= 0x00100000;
1502             /* Set FX */
1503             env->fpscr[7] |= 0x8;
1504             /* Finally, update FEX */
1505             if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
1506                 ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
1507                 env->fpscr[7] |= 0x4;
1508             break;
1509         case EXCP_INVAL:
1510 #if defined (DEBUG_EXCEPTIONS)
1511             if (loglevel) {
1512                 fprintf(logfile, "Invalid instruction at 0x" ADDRX "\n",
1513                         env->nip);
1514             }
1515 #endif
1516             msr |= 0x00080000;
1517             break;
1518         case EXCP_PRIV:
1519             msr |= 0x00040000;
1520             break;
1521         case EXCP_TRAP:
1522             idx = 15;
1523             msr |= 0x00020000;
1524             break;
1525         default:
1526             /* Should never occur */
1527             break;
1528         }
1529         msr |= 0x00010000;
1530         goto store_current;
1531     case EXCP_NO_FP: /* 0x0800 */
1532         idx = 7;
1533         msr &= ~0xFFFF0000;
1534         goto store_current;
1535     case EXCP_DECR:
1536         goto store_next;
1537     case EXCP_SYSCALL: /* 0x0C00 */
1538         idx = 8;
1539         /* NOTE: this is a temporary hack to support graphics OSI
1540            calls from the MOL driver */
1541         if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
1542             env->osi_call) {
1543             if (env->osi_call(env) != 0)
1544                 return;
1545         }
1546         if (loglevel & CPU_LOG_INT) {
1547             dump_syscall(env);
1548         }
1549         goto store_next;
1550     case EXCP_TRACE: /* 0x0D00 */
1551         goto store_next;
1552     case EXCP_PERF: /* 0x0F00 */
1553         /* XXX: TODO */
1554         cpu_abort(env,
1555                   "Performance counter exception is not implemented yet !\n");
1556         goto store_next;
1557     /* 32 bits PowerPC specific exceptions */
1558     case EXCP_FP_ASSIST: /* 0x0E00 */
1559         /* XXX: TODO */
1560         cpu_abort(env, "Floating point assist exception "
1561                   "is not implemented yet !\n");
1562         goto store_next;
1563         /* 64 bits PowerPC exceptions */
1564     case EXCP_DSEG: /* 0x0380 */
1565         /* XXX: TODO */
1566         cpu_abort(env, "Data segment exception is not implemented yet !\n");
1567         goto store_next;
1568     case EXCP_ISEG: /* 0x0480 */
1569         /* XXX: TODO */
1570         cpu_abort(env,
1571                   "Instruction segment exception is not implemented yet !\n");
1572         goto store_next;
1573     case EXCP_HDECR: /* 0x0980 */
1574         /* XXX: TODO */
1575         cpu_abort(env, "Hypervisor decrementer exception is not implemented "
1576                   "yet !\n");
1577         goto store_next;
1578     /* Implementation specific exceptions */
1579     case 0x0A00:
1580         if (likely(env->spr[SPR_PVR] == CPU_PPC_G2 ||
1581                    env->spr[SPR_PVR] == CPU_PPC_G2LE)) {
1582             /* Critical interrupt on G2 */
1583             /* XXX: TODO */
1584             cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
1585             goto store_next;
1586         } else {
1587             cpu_abort(env, "Invalid exception 0x0A00 !\n");
1588         }
1589         return;
1590     case 0x0F20:
1591         idx = 9;
1592         switch (PPC_EXCP(env)) {
1593         case PPC_FLAGS_EXCP_40x:
1594             /* APU unavailable on 405 */
1595             /* XXX: TODO */
1596             cpu_abort(env,
1597                       "APU unavailable exception is not implemented yet !\n");
1598             goto store_next;
1599         case PPC_FLAGS_EXCP_74xx:
1600             /* Altivec unavailable */
1601             /* XXX: TODO */
1602             cpu_abort(env, "Altivec unavailable exception "
1603                       "is not implemented yet !\n");
1604             goto store_next;
1605         default:
1606             cpu_abort(env, "Invalid exception 0x0F20 !\n");
1607             break;
1608         }
1609         return;
1610     case 0x1000:
1611         idx = 10;
1612         switch (PPC_EXCP(env)) {
1613         case PPC_FLAGS_EXCP_40x:
1614             /* PIT on 4xx */
1615             msr &= ~0xFFFF0000;
1616 #if defined (DEBUG_EXCEPTIONS)
1617             if (loglevel != 0)
1618                 fprintf(logfile, "PIT exception\n");
1619 #endif
1620             goto store_next;
1621         case PPC_FLAGS_EXCP_602:
1622         case PPC_FLAGS_EXCP_603:
1623             /* ITLBMISS on 602/603 */
1624             goto store_gprs;
1625         case PPC_FLAGS_EXCP_7x5:
1626             /* ITLBMISS on 745/755 */
1627             goto tlb_miss;
1628         default:
1629             cpu_abort(env, "Invalid exception 0x1000 !\n");
1630             break;
1631         }
1632         return;
1633     case 0x1010:
1634         idx = 11;
1635         switch (PPC_EXCP(env)) {
1636         case PPC_FLAGS_EXCP_40x:
1637             /* FIT on 4xx */
1638             msr &= ~0xFFFF0000;
1639 #if defined (DEBUG_EXCEPTIONS)
1640             if (loglevel != 0)
1641                 fprintf(logfile, "FIT exception\n");
1642 #endif
1643             goto store_next;
1644         default:
1645             cpu_abort(env, "Invalid exception 0x1010 !\n");
1646             break;
1647         }
1648         return;
1649     case 0x1020:
1650         idx = 12;
1651         switch (PPC_EXCP(env)) {
1652         case PPC_FLAGS_EXCP_40x:
1653             /* Watchdog on 4xx */
1654             msr &= ~0xFFFF0000;
1655 #if defined (DEBUG_EXCEPTIONS)
1656             if (loglevel != 0)
1657                 fprintf(logfile, "WDT exception\n");
1658 #endif
1659             goto store_next;
1660         case PPC_FLAGS_EXCP_BOOKE:
1661             srr_0 = &env->spr[SPR_BOOKE_CSRR0];
1662             srr_1 = &env->spr[SPR_BOOKE_CSRR1];
1663             break;
1664         default:
1665             cpu_abort(env, "Invalid exception 0x1020 !\n");
1666             break;
1667         }
1668         return;
1669     case 0x1100:
1670         idx = 13;
1671         switch (PPC_EXCP(env)) {
1672         case PPC_FLAGS_EXCP_40x:
1673             /* DTLBMISS on 4xx */
1674             msr &= ~0xFFFF0000;
1675             goto store_next;
1676         case PPC_FLAGS_EXCP_602:
1677         case PPC_FLAGS_EXCP_603:
1678             /* DLTLBMISS on 602/603 */
1679             goto store_gprs;
1680         case PPC_FLAGS_EXCP_7x5:
1681             /* DLTLBMISS on 745/755 */
1682             goto tlb_miss;
1683         default:
1684             cpu_abort(env, "Invalid exception 0x1100 !\n");
1685             break;
1686         }
1687         return;
1688     case 0x1200:
1689         idx = 14;
1690         switch (PPC_EXCP(env)) {
1691         case PPC_FLAGS_EXCP_40x:
1692             /* ITLBMISS on 4xx */
1693             msr &= ~0xFFFF0000;
1694             goto store_next;
1695         case PPC_FLAGS_EXCP_602:
1696         case PPC_FLAGS_EXCP_603:
1697             /* DSTLBMISS on 602/603 */
1698         store_gprs:
1699             /* Swap temporary saved registers with GPRs */
1700             swap_gpr_tgpr(env);
1701             msr_tgpr = 1;
1702 #if defined (DEBUG_SOFTWARE_TLB)
1703             if (loglevel != 0) {
1704                 const unsigned char *es;
1705                 target_ulong *miss, *cmp;
1706                 int en;
1707                 if (excp == 0x1000) {
1708                     es = "I";
1709                     en = 'I';
1710                     miss = &env->spr[SPR_IMISS];
1711                     cmp = &env->spr[SPR_ICMP];
1712                 } else {
1713                     if (excp == 0x1100)
1714                         es = "DL";
1715                     else
1716                         es = "DS";
1717                     en = 'D';
1718                     miss = &env->spr[SPR_DMISS];
1719                     cmp = &env->spr[SPR_DCMP];
1720                 }
1721                 fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
1722                         " H1 " ADDRX " H2 " ADDRX " " ADDRX "\n",
1723                         es, en, *miss, en, *cmp,
1724                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
1725                         env->error_code);
1726             }
1727 #endif
1728             goto tlb_miss;
1729         case PPC_FLAGS_EXCP_7x5:
1730             /* DSTLBMISS on 745/755 */
1731         tlb_miss:
1732             msr &= ~0xF83F0000;
1733             msr |= env->crf[0] << 28;
1734             msr |= env->error_code; /* key, D/I, S/L bits */
1735             /* Set way using a LRU mechanism */
1736             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
1737             goto store_next;
1738         default:
1739             cpu_abort(env, "Invalid exception 0x1200 !\n");
1740             break;
1741         }
1742         return;
1743     case 0x1300:
1744         switch (PPC_EXCP(env)) {
1745         case PPC_FLAGS_EXCP_601:
1746         case PPC_FLAGS_EXCP_602:
1747         case PPC_FLAGS_EXCP_603:
1748         case PPC_FLAGS_EXCP_604:
1749         case PPC_FLAGS_EXCP_7x0:
1750         case PPC_FLAGS_EXCP_7x5:
1751             /* IABR on 6xx/7xx */
1752             /* XXX: TODO */
1753             cpu_abort(env, "IABR exception is not implemented yet !\n");
1754             goto store_next;
1755         default:
1756             cpu_abort(env, "Invalid exception 0x1300 !\n");
1757             break;
1758         }
1759         return;
1760     case 0x1400:
1761         switch (PPC_EXCP(env)) {
1762         case PPC_FLAGS_EXCP_601:
1763         case PPC_FLAGS_EXCP_602:
1764         case PPC_FLAGS_EXCP_603:
1765         case PPC_FLAGS_EXCP_604:
1766         case PPC_FLAGS_EXCP_7x0:
1767         case PPC_FLAGS_EXCP_7x5:
1768             /* SMI on 6xx/7xx */
1769             /* XXX: TODO */
1770             cpu_abort(env, "SMI exception is not implemented yet !\n");
1771             goto store_next;
1772         default:
1773             cpu_abort(env, "Invalid exception 0x1400 !\n");
1774             break;
1775         }
1776         return;
1777     case 0x1500:
1778         switch (PPC_EXCP(env)) {
1779         case PPC_FLAGS_EXCP_602:
1780             /* Watchdog on 602 */
1781             /* XXX: TODO */
1782             cpu_abort(env,
1783                       "602 watchdog exception is not implemented yet !\n");
1784             goto store_next;
1785         case PPC_FLAGS_EXCP_970:
1786             /* Soft patch exception on 970 */
1787             /* XXX: TODO */
1788             cpu_abort(env,
1789                       "970 soft-patch exception is not implemented yet !\n");
1790             goto store_next;
1791         case PPC_FLAGS_EXCP_74xx:
1792             /* VPU assist on 74xx */
1793             /* XXX: TODO */
1794             cpu_abort(env, "VPU assist exception is not implemented yet !\n");
1795             goto store_next;
1796         default:
1797             cpu_abort(env, "Invalid exception 0x1500 !\n");
1798             break;
1799         }
1800         return;
1801     case 0x1600:
1802         switch (PPC_EXCP(env)) {
1803         case PPC_FLAGS_EXCP_602:
1804             /* Emulation trap on 602 */
1805             /* XXX: TODO */
1806             cpu_abort(env, "602 emulation trap exception "
1807                       "is not implemented yet !\n");
1808             goto store_next;
1809         case PPC_FLAGS_EXCP_970:
1810             /* Maintenance exception on 970 */
1811             /* XXX: TODO */
1812             cpu_abort(env,
1813                       "970 maintenance exception is not implemented yet !\n");
1814             goto store_next;
1815         default:
1816             cpu_abort(env, "Invalid exception 0x1600 !\n");
1817             break;
1818         }
1819         return;
1820     case 0x1700:
1821         switch (PPC_EXCP(env)) {
1822         case PPC_FLAGS_EXCP_7x0:
1823         case PPC_FLAGS_EXCP_7x5:
1824             /* Thermal management interrupt on G3 */
1825             /* XXX: TODO */
1826             cpu_abort(env, "G3 thermal management exception "
1827                       "is not implemented yet !\n");
1828             goto store_next;
1829         case PPC_FLAGS_EXCP_970:
1830             /* VPU assist on 970 */
1831             /* XXX: TODO */
1832             cpu_abort(env,
1833                       "970 VPU assist exception is not implemented yet !\n");
1834             goto store_next;
1835         default:
1836             cpu_abort(env, "Invalid exception 0x1700 !\n");
1837             break;
1838         }
1839         return;
1840     case 0x1800:
1841         switch (PPC_EXCP(env)) {
1842         case PPC_FLAGS_EXCP_970:
1843             /* Thermal exception on 970 */
1844             /* XXX: TODO */
1845             cpu_abort(env, "970 thermal management exception "
1846                       "is not implemented yet !\n");
1847             goto store_next;
1848         default:
1849             cpu_abort(env, "Invalid exception 0x1800 !\n");
1850             break;
1851         }
1852         return;
1853     case 0x2000:
1854         switch (PPC_EXCP(env)) {
1855         case PPC_FLAGS_EXCP_40x:
1856             /* DEBUG on 4xx */
1857             /* XXX: TODO */
1858             cpu_abort(env, "40x debug exception is not implemented yet !\n");
1859             goto store_next;
1860         case PPC_FLAGS_EXCP_601:
1861             /* Run mode exception on 601 */
1862             /* XXX: TODO */
1863             cpu_abort(env,
1864                       "601 run mode exception is not implemented yet !\n");
1865             goto store_next;
1866         case PPC_FLAGS_EXCP_BOOKE:
1867             srr_0 = &env->spr[SPR_BOOKE_CSRR0];
1868             srr_1 = &env->spr[SPR_BOOKE_CSRR1];
1869             break;
1870         default:
1871             cpu_abort(env, "Invalid exception 0x1800 !\n");
1872             break;
1873         }
1874         return;
1875     /* Other exceptions */
1876     /* Qemu internal exceptions:
1877      * we should never come here with those values: abort execution
1878      */
1879     default:
1880         cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
1881         return;
1882     store_current:
1883         /* save current instruction location */
1884         *srr_0 = env->nip - 4;
1885         break;
1886     store_next:
1887         /* save next instruction location */
1888         *srr_0 = env->nip;
1889         break;
1890     }
1891     /* Save msr */
1892     *srr_1 = msr;
1893     if (asrr_0 != NULL)
1894         *asrr_0 = *srr_0;
1895     if (asrr_1 != NULL)
1896         *asrr_1 = *srr_1;
1897     /* If we disactivated any translation, flush TLBs */
1898     if (msr_ir || msr_dr) {
1899         tlb_flush(env, 1);
1900     }
1901     /* reload MSR with correct bits */
1902     msr_ee = 0;
1903     msr_pr = 0;
1904     msr_fp = 0;
1905     msr_fe0 = 0;
1906     msr_se = 0;
1907     msr_be = 0;
1908     msr_fe1 = 0;
1909     msr_ir = 0;
1910     msr_dr = 0;
1911     msr_ri = 0;
1912     msr_le = msr_ile;
1913     if (PPC_EXCP(env) == PPC_FLAGS_EXCP_BOOKE) {
1914         msr_cm = msr_icm;
1915         if (idx == -1 || (idx >= 16 && idx < 32)) {
1916             cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n",
1917                       excp, excp, idx);
1918         }
1919 #if defined(TARGET_PPC64)
1920         if (msr_cm)
1921             env->nip = (uint64_t)env->spr[SPR_BOOKE_IVPR];
1922         else
1923 #endif
1924             env->nip = (uint32_t)env->spr[SPR_BOOKE_IVPR];
1925         if (idx < 16)
1926             env->nip |= env->spr[SPR_BOOKE_IVOR0 + idx];
1927         else if (idx < 38)
1928             env->nip |= env->spr[SPR_BOOKE_IVOR32 + idx - 32];
1929     } else {
1930         msr_sf = msr_isf;
1931         env->nip = excp;
1932     }
1933     do_compute_hflags(env);
1934     /* Jump to handler */
1935     env->exception_index = EXCP_NONE;
1936 }
1937
1938 void ppc_hw_interrupt (CPUPPCState *env)
1939 {
1940     int raised = 0;
1941
1942 #if 1
1943     if (loglevel & CPU_LOG_INT) {
1944         fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
1945                 __func__, env, env->pending_interrupts,
1946                 env->interrupt_request, msr_me, msr_ee);
1947     }
1948 #endif
1949     /* Raise it */
1950     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
1951         /* External reset / critical input */
1952         /* XXX: critical input should be handled another way.
1953          *      This code is not correct !
1954          */
1955         env->exception_index = EXCP_RESET;
1956         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
1957         raised = 1;
1958     }
1959     if (raised == 0 && msr_me != 0) {
1960         /* Machine check exception */
1961         if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
1962             env->exception_index = EXCP_MACHINE_CHECK;
1963             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
1964             raised = 1;
1965         }
1966     }
1967     if (raised == 0 && msr_ee != 0) {
1968 #if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
1969         /* Hypervisor decrementer exception */
1970         if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
1971             env->exception_index = EXCP_HDECR;
1972             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1973             raised = 1;
1974         } else
1975 #endif
1976         /* Decrementer exception */
1977         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
1978             env->exception_index = EXCP_DECR;
1979             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
1980             raised = 1;
1981         /* Programmable interval timer on embedded PowerPC */
1982         } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
1983             env->exception_index = EXCP_40x_PIT;
1984             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
1985             raised = 1;
1986         /* Fixed interval timer on embedded PowerPC */
1987         } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
1988             env->exception_index = EXCP_40x_FIT;
1989             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
1990             raised = 1;
1991         /* Watchdog timer on embedded PowerPC */
1992         } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
1993             env->exception_index = EXCP_40x_WATCHDOG;
1994             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
1995             raised = 1;
1996         /* External interrupt */
1997         } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
1998             env->exception_index = EXCP_EXTERNAL;
1999             /* Taking an external interrupt does not clear the external
2000              * interrupt status
2001              */
2002 #if 0
2003             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2004 #endif
2005             raised = 1;
2006         }
2007 #if 0 // TODO
2008     /* External debug exception */
2009     } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2010         env->exception_index = EXCP_xxx;
2011         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2012         raised = 1;
2013 #endif
2014     }
2015     if (raised != 0) {
2016         env->error_code = 0;
2017         do_interrupt(env);
2018     }
2019 }
2020 #endif /* !CONFIG_USER_ONLY */
2021
2022 void cpu_dump_EA (target_ulong EA)
2023 {
2024     FILE *f;
2025
2026     if (logfile) {
2027         f = logfile;
2028     } else {
2029         f = stdout;
2030         return;
2031     }
2032     fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);
2033 }
2034
This page took 0.135399 seconds and 4 git commands to generate.