CPU feature selection support
[qemu] / target-sparc / helper.c
1 /*
2  *  sparc helpers
3  *
4  *  Copyright (c) 2003-2005 Fabrice Bellard
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 #include "qemu-common.h"
31
32 //#define DEBUG_MMU
33 //#define DEBUG_FEATURES
34
35 typedef struct sparc_def_t sparc_def_t;
36
37 struct sparc_def_t {
38     const unsigned char *name;
39     target_ulong iu_version;
40     uint32_t fpu_version;
41     uint32_t mmu_version;
42     uint32_t mmu_bm;
43     uint32_t mmu_ctpr_mask;
44     uint32_t mmu_cxr_mask;
45     uint32_t mmu_sfsr_mask;
46     uint32_t mmu_trcr_mask;
47     uint32_t features;
48 };
49
50 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const unsigned char *cpu_model);
51
52 /* Sparc MMU emulation */
53
54 /* thread support */
55
56 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
57
58 void cpu_lock(void)
59 {
60     spin_lock(&global_cpu_lock);
61 }
62
63 void cpu_unlock(void)
64 {
65     spin_unlock(&global_cpu_lock);
66 }
67
68 #if defined(CONFIG_USER_ONLY)
69
70 int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
71                                int mmu_idx, int is_softmmu)
72 {
73     if (rw & 2)
74         env->exception_index = TT_TFAULT;
75     else
76         env->exception_index = TT_DFAULT;
77     return 1;
78 }
79
80 #else
81
82 #ifndef TARGET_SPARC64
83 /*
84  * Sparc V8 Reference MMU (SRMMU)
85  */
86 static const int access_table[8][8] = {
87     { 0, 0, 0, 0, 2, 0, 3, 3 },
88     { 0, 0, 0, 0, 2, 0, 0, 0 },
89     { 2, 2, 0, 0, 0, 2, 3, 3 },
90     { 2, 2, 0, 0, 0, 2, 0, 0 },
91     { 2, 0, 2, 0, 2, 2, 3, 3 },
92     { 2, 0, 2, 0, 2, 0, 2, 0 },
93     { 2, 2, 2, 0, 2, 2, 3, 3 },
94     { 2, 2, 2, 0, 2, 2, 2, 0 }
95 };
96
97 static const int perm_table[2][8] = {
98     {
99         PAGE_READ,
100         PAGE_READ | PAGE_WRITE,
101         PAGE_READ | PAGE_EXEC,
102         PAGE_READ | PAGE_WRITE | PAGE_EXEC,
103         PAGE_EXEC,
104         PAGE_READ | PAGE_WRITE,
105         PAGE_READ | PAGE_EXEC,
106         PAGE_READ | PAGE_WRITE | PAGE_EXEC
107     },
108     {
109         PAGE_READ,
110         PAGE_READ | PAGE_WRITE,
111         PAGE_READ | PAGE_EXEC,
112         PAGE_READ | PAGE_WRITE | PAGE_EXEC,
113         PAGE_EXEC,
114         PAGE_READ,
115         0,
116         0,
117     }
118 };
119
120 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
121                                 int *prot, int *access_index,
122                                 target_ulong address, int rw, int mmu_idx)
123 {
124     int access_perms = 0;
125     target_phys_addr_t pde_ptr;
126     uint32_t pde;
127     target_ulong virt_addr;
128     int error_code = 0, is_dirty, is_user;
129     unsigned long page_offset;
130
131     is_user = mmu_idx == MMU_USER_IDX;
132     virt_addr = address & TARGET_PAGE_MASK;
133
134     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
135         // Boot mode: instruction fetches are taken from PROM
136         if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
137             *physical = env->prom_addr | (address & 0x7ffffULL);
138             *prot = PAGE_READ | PAGE_EXEC;
139             return 0;
140         }
141         *physical = address;
142         *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
143         return 0;
144     }
145
146     *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
147     *physical = 0xffffffffffff0000ULL;
148
149     /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
150     /* Context base + context number */
151     pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
152     pde = ldl_phys(pde_ptr);
153
154     /* Ctx pde */
155     switch (pde & PTE_ENTRYTYPE_MASK) {
156     default:
157     case 0: /* Invalid */
158         return 1 << 2;
159     case 2: /* L0 PTE, maybe should not happen? */
160     case 3: /* Reserved */
161         return 4 << 2;
162     case 1: /* L0 PDE */
163         pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
164         pde = ldl_phys(pde_ptr);
165
166         switch (pde & PTE_ENTRYTYPE_MASK) {
167         default:
168         case 0: /* Invalid */
169             return (1 << 8) | (1 << 2);
170         case 3: /* Reserved */
171             return (1 << 8) | (4 << 2);
172         case 1: /* L1 PDE */
173             pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
174             pde = ldl_phys(pde_ptr);
175
176             switch (pde & PTE_ENTRYTYPE_MASK) {
177             default:
178             case 0: /* Invalid */
179                 return (2 << 8) | (1 << 2);
180             case 3: /* Reserved */
181                 return (2 << 8) | (4 << 2);
182             case 1: /* L2 PDE */
183                 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
184                 pde = ldl_phys(pde_ptr);
185
186                 switch (pde & PTE_ENTRYTYPE_MASK) {
187                 default:
188                 case 0: /* Invalid */
189                     return (3 << 8) | (1 << 2);
190                 case 1: /* PDE, should not happen */
191                 case 3: /* Reserved */
192                     return (3 << 8) | (4 << 2);
193                 case 2: /* L3 PTE */
194                     virt_addr = address & TARGET_PAGE_MASK;
195                     page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
196                 }
197                 break;
198             case 2: /* L2 PTE */
199                 virt_addr = address & ~0x3ffff;
200                 page_offset = address & 0x3ffff;
201             }
202             break;
203         case 2: /* L1 PTE */
204             virt_addr = address & ~0xffffff;
205             page_offset = address & 0xffffff;
206         }
207     }
208
209     /* update page modified and dirty bits */
210     is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
211     if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
212         pde |= PG_ACCESSED_MASK;
213         if (is_dirty)
214             pde |= PG_MODIFIED_MASK;
215         stl_phys_notdirty(pde_ptr, pde);
216     }
217     /* check access */
218     access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
219     error_code = access_table[*access_index][access_perms];
220     if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
221         return error_code;
222
223     /* the page can be put in the TLB */
224     *prot = perm_table[is_user][access_perms];
225     if (!(pde & PG_MODIFIED_MASK)) {
226         /* only set write access if already dirty... otherwise wait
227            for dirty access */
228         *prot &= ~PAGE_WRITE;
229     }
230
231     /* Even if large ptes, we map only one 4KB page in the cache to
232        avoid filling it too fast */
233     *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
234     return error_code;
235 }
236
237 /* Perform address translation */
238 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
239                               int mmu_idx, int is_softmmu)
240 {
241     target_phys_addr_t paddr;
242     target_ulong vaddr;
243     int error_code = 0, prot, ret = 0, access_index;
244
245     error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
246     if (error_code == 0) {
247         vaddr = address & TARGET_PAGE_MASK;
248         paddr &= TARGET_PAGE_MASK;
249 #ifdef DEBUG_MMU
250         printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
251                TARGET_FMT_lx "\n", address, paddr, vaddr);
252 #endif
253         ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
254         return ret;
255     }
256
257     if (env->mmuregs[3]) /* Fault status register */
258         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
259     env->mmuregs[3] |= (access_index << 5) | error_code | 2;
260     env->mmuregs[4] = address; /* Fault address register */
261
262     if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
263         // No fault mode: if a mapping is available, just override
264         // permissions. If no mapping is available, redirect accesses to
265         // neverland. Fake/overridden mappings will be flushed when
266         // switching to normal mode.
267         vaddr = address & TARGET_PAGE_MASK;
268         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
269         ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
270         return ret;
271     } else {
272         if (rw & 2)
273             env->exception_index = TT_TFAULT;
274         else
275             env->exception_index = TT_DFAULT;
276         return 1;
277     }
278 }
279
280 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
281 {
282     target_phys_addr_t pde_ptr;
283     uint32_t pde;
284
285     /* Context base + context number */
286     pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
287         (env->mmuregs[2] << 2);
288     pde = ldl_phys(pde_ptr);
289
290     switch (pde & PTE_ENTRYTYPE_MASK) {
291     default:
292     case 0: /* Invalid */
293     case 2: /* PTE, maybe should not happen? */
294     case 3: /* Reserved */
295         return 0;
296     case 1: /* L1 PDE */
297         if (mmulev == 3)
298             return pde;
299         pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
300         pde = ldl_phys(pde_ptr);
301
302         switch (pde & PTE_ENTRYTYPE_MASK) {
303         default:
304         case 0: /* Invalid */
305         case 3: /* Reserved */
306             return 0;
307         case 2: /* L1 PTE */
308             return pde;
309         case 1: /* L2 PDE */
310             if (mmulev == 2)
311                 return pde;
312             pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
313             pde = ldl_phys(pde_ptr);
314
315             switch (pde & PTE_ENTRYTYPE_MASK) {
316             default:
317             case 0: /* Invalid */
318             case 3: /* Reserved */
319                 return 0;
320             case 2: /* L2 PTE */
321                 return pde;
322             case 1: /* L3 PDE */
323                 if (mmulev == 1)
324                     return pde;
325                 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
326                 pde = ldl_phys(pde_ptr);
327
328                 switch (pde & PTE_ENTRYTYPE_MASK) {
329                 default:
330                 case 0: /* Invalid */
331                 case 1: /* PDE, should not happen */
332                 case 3: /* Reserved */
333                     return 0;
334                 case 2: /* L3 PTE */
335                     return pde;
336                 }
337             }
338         }
339     }
340     return 0;
341 }
342
343 #ifdef DEBUG_MMU
344 void dump_mmu(CPUState *env)
345 {
346     target_ulong va, va1, va2;
347     unsigned int n, m, o;
348     target_phys_addr_t pde_ptr, pa;
349     uint32_t pde;
350
351     printf("MMU dump:\n");
352     pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
353     pde = ldl_phys(pde_ptr);
354     printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
355            (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
356     for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
357         pde = mmu_probe(env, va, 2);
358         if (pde) {
359             pa = cpu_get_phys_page_debug(env, va);
360             printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
361                    " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
362             for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
363                 pde = mmu_probe(env, va1, 1);
364                 if (pde) {
365                     pa = cpu_get_phys_page_debug(env, va1);
366                     printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
367                            " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
368                     for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
369                         pde = mmu_probe(env, va2, 0);
370                         if (pde) {
371                             pa = cpu_get_phys_page_debug(env, va2);
372                             printf("  VA: " TARGET_FMT_lx ", PA: "
373                                    TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
374                                    va2, pa, pde);
375                         }
376                     }
377                 }
378             }
379         }
380     }
381     printf("MMU dump ends\n");
382 }
383 #endif /* DEBUG_MMU */
384
385 #else /* !TARGET_SPARC64 */
386 /*
387  * UltraSparc IIi I/DMMUs
388  */
389 static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
390                           int *access_index, target_ulong address, int rw,
391                           int is_user)
392 {
393     target_ulong mask;
394     unsigned int i;
395
396     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
397         *physical = address;
398         *prot = PAGE_READ | PAGE_WRITE;
399         return 0;
400     }
401
402     for (i = 0; i < 64; i++) {
403         switch ((env->dtlb_tte[i] >> 61) & 3) {
404         default:
405         case 0x0: // 8k
406             mask = 0xffffffffffffe000ULL;
407             break;
408         case 0x1: // 64k
409             mask = 0xffffffffffff0000ULL;
410             break;
411         case 0x2: // 512k
412             mask = 0xfffffffffff80000ULL;
413             break;
414         case 0x3: // 4M
415             mask = 0xffffffffffc00000ULL;
416             break;
417         }
418         // ctx match, vaddr match?
419         if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
420             (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
421             // valid, access ok?
422             if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
423                 ((env->dtlb_tte[i] & 0x4) && is_user) ||
424                 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
425                 if (env->dmmuregs[3]) /* Fault status register */
426                     env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
427                 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
428                 env->dmmuregs[4] = address; /* Fault address register */
429                 env->exception_index = TT_DFAULT;
430 #ifdef DEBUG_MMU
431                 printf("DFAULT at 0x%" PRIx64 "\n", address);
432 #endif
433                 return 1;
434             }
435             *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
436             *prot = PAGE_READ;
437             if (env->dtlb_tte[i] & 0x2)
438                 *prot |= PAGE_WRITE;
439             return 0;
440         }
441     }
442 #ifdef DEBUG_MMU
443     printf("DMISS at 0x%" PRIx64 "\n", address);
444 #endif
445     env->exception_index = TT_DMISS;
446     return 1;
447 }
448
449 static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
450                           int *access_index, target_ulong address, int rw,
451                           int is_user)
452 {
453     target_ulong mask;
454     unsigned int i;
455
456     if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
457         *physical = address;
458         *prot = PAGE_EXEC;
459         return 0;
460     }
461
462     for (i = 0; i < 64; i++) {
463         switch ((env->itlb_tte[i] >> 61) & 3) {
464         default:
465         case 0x0: // 8k
466             mask = 0xffffffffffffe000ULL;
467             break;
468         case 0x1: // 64k
469             mask = 0xffffffffffff0000ULL;
470             break;
471         case 0x2: // 512k
472             mask = 0xfffffffffff80000ULL;
473             break;
474         case 0x3: // 4M
475             mask = 0xffffffffffc00000ULL;
476                 break;
477         }
478         // ctx match, vaddr match?
479         if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
480             (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
481             // valid, access ok?
482             if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
483                 ((env->itlb_tte[i] & 0x4) && is_user)) {
484                 if (env->immuregs[3]) /* Fault status register */
485                     env->immuregs[3] = 2; /* overflow (not read before another fault) */
486                 env->immuregs[3] |= (is_user << 3) | 1;
487                 env->exception_index = TT_TFAULT;
488 #ifdef DEBUG_MMU
489                 printf("TFAULT at 0x%" PRIx64 "\n", address);
490 #endif
491                 return 1;
492             }
493             *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
494             *prot = PAGE_EXEC;
495             return 0;
496         }
497     }
498 #ifdef DEBUG_MMU
499     printf("TMISS at 0x%" PRIx64 "\n", address);
500 #endif
501     env->exception_index = TT_TMISS;
502     return 1;
503 }
504
505 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
506                                 int *prot, int *access_index,
507                                 target_ulong address, int rw, int mmu_idx)
508 {
509     int is_user = mmu_idx == MMU_USER_IDX;
510
511     if (rw == 2)
512         return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
513     else
514         return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
515 }
516
517 /* Perform address translation */
518 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
519                               int mmu_idx, int is_softmmu)
520 {
521     target_ulong virt_addr, vaddr;
522     target_phys_addr_t paddr;
523     int error_code = 0, prot, ret = 0, access_index;
524
525     error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
526     if (error_code == 0) {
527         virt_addr = address & TARGET_PAGE_MASK;
528         vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
529 #ifdef DEBUG_MMU
530         printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
531 #endif
532         ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
533         return ret;
534     }
535     // XXX
536     return 1;
537 }
538
539 #ifdef DEBUG_MMU
540 void dump_mmu(CPUState *env)
541 {
542     unsigned int i;
543     const char *mask;
544
545     printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", env->dmmuregs[1], env->dmmuregs[2]);
546     if ((env->lsu & DMMU_E) == 0) {
547         printf("DMMU disabled\n");
548     } else {
549         printf("DMMU dump:\n");
550         for (i = 0; i < 64; i++) {
551             switch ((env->dtlb_tte[i] >> 61) & 3) {
552             default:
553             case 0x0:
554                 mask = "  8k";
555                 break;
556             case 0x1:
557                 mask = " 64k";
558                 break;
559             case 0x2:
560                 mask = "512k";
561                 break;
562             case 0x3:
563                 mask = "  4M";
564                 break;
565             }
566             if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
567                 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
568                        env->dtlb_tag[i] & ~0x1fffULL,
569                        env->dtlb_tte[i] & 0x1ffffffe000ULL,
570                        mask,
571                        env->dtlb_tte[i] & 0x4? "priv": "user",
572                        env->dtlb_tte[i] & 0x2? "RW": "RO",
573                        env->dtlb_tte[i] & 0x40? "locked": "unlocked",
574                        env->dtlb_tag[i] & 0x1fffULL);
575             }
576         }
577     }
578     if ((env->lsu & IMMU_E) == 0) {
579         printf("IMMU disabled\n");
580     } else {
581         printf("IMMU dump:\n");
582         for (i = 0; i < 64; i++) {
583             switch ((env->itlb_tte[i] >> 61) & 3) {
584             default:
585             case 0x0:
586                 mask = "  8k";
587                 break;
588             case 0x1:
589                 mask = " 64k";
590                 break;
591             case 0x2:
592                 mask = "512k";
593                 break;
594             case 0x3:
595                 mask = "  4M";
596                 break;
597             }
598             if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
599                 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
600                        env->itlb_tag[i] & ~0x1fffULL,
601                        env->itlb_tte[i] & 0x1ffffffe000ULL,
602                        mask,
603                        env->itlb_tte[i] & 0x4? "priv": "user",
604                        env->itlb_tte[i] & 0x40? "locked": "unlocked",
605                        env->itlb_tag[i] & 0x1fffULL);
606             }
607         }
608     }
609 }
610 #endif /* DEBUG_MMU */
611
612 #endif /* TARGET_SPARC64 */
613 #endif /* !CONFIG_USER_ONLY */
614
615
616 #if defined(CONFIG_USER_ONLY)
617 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
618 {
619     return addr;
620 }
621
622 #else
623 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
624 {
625     target_phys_addr_t phys_addr;
626     int prot, access_index;
627
628     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
629                              MMU_KERNEL_IDX) != 0)
630         if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
631                                  0, MMU_KERNEL_IDX) != 0)
632             return -1;
633     if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
634         return -1;
635     return phys_addr;
636 }
637 #endif
638
639 void memcpy32(target_ulong *dst, const target_ulong *src)
640 {
641     dst[0] = src[0];
642     dst[1] = src[1];
643     dst[2] = src[2];
644     dst[3] = src[3];
645     dst[4] = src[4];
646     dst[5] = src[5];
647     dst[6] = src[6];
648     dst[7] = src[7];
649 }
650
651 void helper_flush(target_ulong addr)
652 {
653     addr &= ~7;
654     tb_invalidate_page_range(addr, addr + 8);
655 }
656
657 void cpu_reset(CPUSPARCState *env)
658 {
659     tlb_flush(env, 1);
660     env->cwp = 0;
661     env->wim = 1;
662     env->regwptr = env->regbase + (env->cwp * 16);
663 #if defined(CONFIG_USER_ONLY)
664     env->user_mode_only = 1;
665 #ifdef TARGET_SPARC64
666     env->cleanwin = NWINDOWS - 2;
667     env->cansave = NWINDOWS - 2;
668     env->pstate = PS_RMO | PS_PEF | PS_IE;
669     env->asi = 0x82; // Primary no-fault
670 #endif
671 #else
672     env->psret = 0;
673     env->psrs = 1;
674     env->psrps = 1;
675 #ifdef TARGET_SPARC64
676     env->pstate = PS_PRIV;
677     env->hpstate = HS_PRIV;
678     env->pc = 0x1fff0000000ULL;
679     env->tsptr = &env->ts[env->tl];
680 #else
681     env->pc = 0;
682     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
683     env->mmuregs[0] |= env->mmu_bm;
684 #endif
685     env->npc = env->pc + 4;
686 #endif
687 }
688
689 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
690 {
691     sparc_def_t def1, *def = &def1;
692
693     if (cpu_sparc_find_by_name(def, cpu_model) < 0)
694         return -1;
695
696     env->features = def->features;
697     env->cpu_model_str = cpu_model;
698     env->version = def->iu_version;
699     env->fsr = def->fpu_version;
700 #if !defined(TARGET_SPARC64)
701     env->mmu_bm = def->mmu_bm;
702     env->mmu_ctpr_mask = def->mmu_ctpr_mask;
703     env->mmu_cxr_mask = def->mmu_cxr_mask;
704     env->mmu_sfsr_mask = def->mmu_sfsr_mask;
705     env->mmu_trcr_mask = def->mmu_trcr_mask;
706     env->mmuregs[0] |= def->mmu_version;
707     cpu_sparc_set_id(env, 0);
708 #endif
709     return 0;
710 }
711
712 static void cpu_sparc_close(CPUSPARCState *env)
713 {
714     free(env);
715 }
716
717 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
718 {
719     CPUSPARCState *env;
720
721     env = qemu_mallocz(sizeof(CPUSPARCState));
722     if (!env)
723         return NULL;
724     cpu_exec_init(env);
725
726     gen_intermediate_code_init(env);
727
728     if (cpu_sparc_register(env, cpu_model) < 0) {
729         cpu_sparc_close(env);
730         return NULL;
731     }
732     cpu_reset(env);
733
734     return env;
735 }
736
737 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
738 {
739 #if !defined(TARGET_SPARC64)
740     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
741 #endif
742 }
743
744 static const sparc_def_t sparc_defs[] = {
745 #ifdef TARGET_SPARC64
746     {
747         .name = "Fujitsu Sparc64",
748         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
749                        | (MAXTL << 8) | (NWINDOWS - 1)),
750         .fpu_version = 0x00000000,
751         .mmu_version = 0,
752         .features = CPU_DEFAULT_FEATURES,
753     },
754     {
755         .name = "Fujitsu Sparc64 III",
756         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
757                        | (MAXTL << 8) | (NWINDOWS - 1)),
758         .fpu_version = 0x00000000,
759         .mmu_version = 0,
760         .features = CPU_DEFAULT_FEATURES,
761     },
762     {
763         .name = "Fujitsu Sparc64 IV",
764         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
765                        | (MAXTL << 8) | (NWINDOWS - 1)),
766         .fpu_version = 0x00000000,
767         .mmu_version = 0,
768         .features = CPU_DEFAULT_FEATURES,
769     },
770     {
771         .name = "Fujitsu Sparc64 V",
772         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
773                        | (MAXTL << 8) | (NWINDOWS - 1)),
774         .fpu_version = 0x00000000,
775         .mmu_version = 0,
776         .features = CPU_DEFAULT_FEATURES,
777     },
778     {
779         .name = "TI UltraSparc I",
780         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
781                        | (MAXTL << 8) | (NWINDOWS - 1)),
782         .fpu_version = 0x00000000,
783         .mmu_version = 0,
784         .features = CPU_DEFAULT_FEATURES,
785     },
786     {
787         .name = "TI UltraSparc II",
788         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
789                        | (MAXTL << 8) | (NWINDOWS - 1)),
790         .fpu_version = 0x00000000,
791         .mmu_version = 0,
792         .features = CPU_DEFAULT_FEATURES,
793     },
794     {
795         .name = "TI UltraSparc IIi",
796         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
797                        | (MAXTL << 8) | (NWINDOWS - 1)),
798         .fpu_version = 0x00000000,
799         .mmu_version = 0,
800         .features = CPU_DEFAULT_FEATURES,
801     },
802     {
803         .name = "TI UltraSparc IIe",
804         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
805                        | (MAXTL << 8) | (NWINDOWS - 1)),
806         .fpu_version = 0x00000000,
807         .mmu_version = 0,
808         .features = CPU_DEFAULT_FEATURES,
809     },
810     {
811         .name = "Sun UltraSparc III",
812         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
813                        | (MAXTL << 8) | (NWINDOWS - 1)),
814         .fpu_version = 0x00000000,
815         .mmu_version = 0,
816         .features = CPU_DEFAULT_FEATURES,
817     },
818     {
819         .name = "Sun UltraSparc III Cu",
820         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
821                        | (MAXTL << 8) | (NWINDOWS - 1)),
822         .fpu_version = 0x00000000,
823         .mmu_version = 0,
824         .features = CPU_DEFAULT_FEATURES,
825     },
826     {
827         .name = "Sun UltraSparc IIIi",
828         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
829                        | (MAXTL << 8) | (NWINDOWS - 1)),
830         .fpu_version = 0x00000000,
831         .mmu_version = 0,
832         .features = CPU_DEFAULT_FEATURES,
833     },
834     {
835         .name = "Sun UltraSparc IV",
836         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
837                        | (MAXTL << 8) | (NWINDOWS - 1)),
838         .fpu_version = 0x00000000,
839         .mmu_version = 0,
840         .features = CPU_DEFAULT_FEATURES,
841     },
842     {
843         .name = "Sun UltraSparc IV+",
844         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
845                        | (MAXTL << 8) | (NWINDOWS - 1)),
846         .fpu_version = 0x00000000,
847         .mmu_version = 0,
848         .features = CPU_DEFAULT_FEATURES,
849     },
850     {
851         .name = "Sun UltraSparc IIIi+",
852         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
853                        | (MAXTL << 8) | (NWINDOWS - 1)),
854         .fpu_version = 0x00000000,
855         .mmu_version = 0,
856         .features = CPU_DEFAULT_FEATURES,
857     },
858     {
859         .name = "NEC UltraSparc I",
860         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
861                        | (MAXTL << 8) | (NWINDOWS - 1)),
862         .fpu_version = 0x00000000,
863         .mmu_version = 0,
864         .features = CPU_DEFAULT_FEATURES,
865     },
866 #else
867     {
868         .name = "Fujitsu MB86900",
869         .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
870         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
871         .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
872         .mmu_bm = 0x00004000,
873         .mmu_ctpr_mask = 0x007ffff0,
874         .mmu_cxr_mask = 0x0000003f,
875         .mmu_sfsr_mask = 0xffffffff,
876         .mmu_trcr_mask = 0xffffffff,
877         .features = CPU_FEATURE_FLOAT,
878     },
879     {
880         .name = "Fujitsu MB86904",
881         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
882         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
883         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
884         .mmu_bm = 0x00004000,
885         .mmu_ctpr_mask = 0x00ffffc0,
886         .mmu_cxr_mask = 0x000000ff,
887         .mmu_sfsr_mask = 0x00016fff,
888         .mmu_trcr_mask = 0x00ffffff,
889         .features = CPU_DEFAULT_FEATURES,
890     },
891     {
892         .name = "Fujitsu MB86907",
893         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
894         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
895         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
896         .mmu_bm = 0x00004000,
897         .mmu_ctpr_mask = 0xffffffc0,
898         .mmu_cxr_mask = 0x000000ff,
899         .mmu_sfsr_mask = 0x00016fff,
900         .mmu_trcr_mask = 0xffffffff,
901         .features = CPU_DEFAULT_FEATURES,
902     },
903     {
904         .name = "LSI L64811",
905         .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
906         .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
907         .mmu_version = 0x10 << 24,
908         .mmu_bm = 0x00004000,
909         .mmu_ctpr_mask = 0x007ffff0,
910         .mmu_cxr_mask = 0x0000003f,
911         .mmu_sfsr_mask = 0xffffffff,
912         .mmu_trcr_mask = 0xffffffff,
913         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT,
914     },
915     {
916         .name = "Cypress CY7C601",
917         .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
918         .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
919         .mmu_version = 0x10 << 24,
920         .mmu_bm = 0x00004000,
921         .mmu_ctpr_mask = 0x007ffff0,
922         .mmu_cxr_mask = 0x0000003f,
923         .mmu_sfsr_mask = 0xffffffff,
924         .mmu_trcr_mask = 0xffffffff,
925         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT,
926     },
927     {
928         .name = "Cypress CY7C611",
929         .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
930         .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
931         .mmu_version = 0x10 << 24,
932         .mmu_bm = 0x00004000,
933         .mmu_ctpr_mask = 0x007ffff0,
934         .mmu_cxr_mask = 0x0000003f,
935         .mmu_sfsr_mask = 0xffffffff,
936         .mmu_trcr_mask = 0xffffffff,
937         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT,
938     },
939     {
940         .name = "TI SuperSparc II",
941         .iu_version = 0x40000000,
942         .fpu_version = 0 << 17,
943         .mmu_version = 0x04000000,
944         .mmu_bm = 0x00002000,
945         .mmu_ctpr_mask = 0xffffffc0,
946         .mmu_cxr_mask = 0x0000ffff,
947         .mmu_sfsr_mask = 0xffffffff,
948         .mmu_trcr_mask = 0xffffffff,
949         .features = CPU_DEFAULT_FEATURES,
950     },
951     {
952         .name = "TI MicroSparc I",
953         .iu_version = 0x41000000,
954         .fpu_version = 4 << 17,
955         .mmu_version = 0x41000000,
956         .mmu_bm = 0x00004000,
957         .mmu_ctpr_mask = 0x007ffff0,
958         .mmu_cxr_mask = 0x0000003f,
959         .mmu_sfsr_mask = 0x00016fff,
960         .mmu_trcr_mask = 0x0000003f,
961         .features = CPU_DEFAULT_FEATURES,
962     },
963     {
964         .name = "TI MicroSparc II",
965         .iu_version = 0x42000000,
966         .fpu_version = 4 << 17,
967         .mmu_version = 0x02000000,
968         .mmu_bm = 0x00004000,
969         .mmu_ctpr_mask = 0x00ffffc0,
970         .mmu_cxr_mask = 0x000000ff,
971         .mmu_sfsr_mask = 0x00016fff,
972         .mmu_trcr_mask = 0x00ffffff,
973         .features = CPU_DEFAULT_FEATURES,
974     },
975     {
976         .name = "TI MicroSparc IIep",
977         .iu_version = 0x42000000,
978         .fpu_version = 4 << 17,
979         .mmu_version = 0x04000000,
980         .mmu_bm = 0x00004000,
981         .mmu_ctpr_mask = 0x00ffffc0,
982         .mmu_cxr_mask = 0x000000ff,
983         .mmu_sfsr_mask = 0x00016bff,
984         .mmu_trcr_mask = 0x00ffffff,
985         .features = CPU_DEFAULT_FEATURES,
986     },
987     {
988         .name = "TI SuperSparc 51",
989         .iu_version = 0x43000000,
990         .fpu_version = 0 << 17,
991         .mmu_version = 0x04000000,
992         .mmu_bm = 0x00002000,
993         .mmu_ctpr_mask = 0xffffffc0,
994         .mmu_cxr_mask = 0x0000ffff,
995         .mmu_sfsr_mask = 0xffffffff,
996         .mmu_trcr_mask = 0xffffffff,
997         .features = CPU_DEFAULT_FEATURES,
998     },
999     {
1000         .name = "TI SuperSparc 61",
1001         .iu_version = 0x44000000,
1002         .fpu_version = 0 << 17,
1003         .mmu_version = 0x04000000,
1004         .mmu_bm = 0x00002000,
1005         .mmu_ctpr_mask = 0xffffffc0,
1006         .mmu_cxr_mask = 0x0000ffff,
1007         .mmu_sfsr_mask = 0xffffffff,
1008         .mmu_trcr_mask = 0xffffffff,
1009         .features = CPU_DEFAULT_FEATURES,
1010     },
1011     {
1012         .name = "Ross RT625",
1013         .iu_version = 0x1e000000,
1014         .fpu_version = 1 << 17,
1015         .mmu_version = 0x1e000000,
1016         .mmu_bm = 0x00004000,
1017         .mmu_ctpr_mask = 0x007ffff0,
1018         .mmu_cxr_mask = 0x0000003f,
1019         .mmu_sfsr_mask = 0xffffffff,
1020         .mmu_trcr_mask = 0xffffffff,
1021         .features = CPU_DEFAULT_FEATURES,
1022     },
1023     {
1024         .name = "Ross RT620",
1025         .iu_version = 0x1f000000,
1026         .fpu_version = 1 << 17,
1027         .mmu_version = 0x1f000000,
1028         .mmu_bm = 0x00004000,
1029         .mmu_ctpr_mask = 0x007ffff0,
1030         .mmu_cxr_mask = 0x0000003f,
1031         .mmu_sfsr_mask = 0xffffffff,
1032         .mmu_trcr_mask = 0xffffffff,
1033         .features = CPU_DEFAULT_FEATURES,
1034     },
1035     {
1036         .name = "BIT B5010",
1037         .iu_version = 0x20000000,
1038         .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1039         .mmu_version = 0x20000000,
1040         .mmu_bm = 0x00004000,
1041         .mmu_ctpr_mask = 0x007ffff0,
1042         .mmu_cxr_mask = 0x0000003f,
1043         .mmu_sfsr_mask = 0xffffffff,
1044         .mmu_trcr_mask = 0xffffffff,
1045         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT,
1046     },
1047     {
1048         .name = "Matsushita MN10501",
1049         .iu_version = 0x50000000,
1050         .fpu_version = 0 << 17,
1051         .mmu_version = 0x50000000,
1052         .mmu_bm = 0x00004000,
1053         .mmu_ctpr_mask = 0x007ffff0,
1054         .mmu_cxr_mask = 0x0000003f,
1055         .mmu_sfsr_mask = 0xffffffff,
1056         .mmu_trcr_mask = 0xffffffff,
1057         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT,
1058     },
1059     {
1060         .name = "Weitek W8601",
1061         .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1062         .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1063         .mmu_version = 0x10 << 24,
1064         .mmu_bm = 0x00004000,
1065         .mmu_ctpr_mask = 0x007ffff0,
1066         .mmu_cxr_mask = 0x0000003f,
1067         .mmu_sfsr_mask = 0xffffffff,
1068         .mmu_trcr_mask = 0xffffffff,
1069         .features = CPU_DEFAULT_FEATURES,
1070     },
1071     {
1072         .name = "LEON2",
1073         .iu_version = 0xf2000000,
1074         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1075         .mmu_version = 0xf2000000,
1076         .mmu_bm = 0x00004000,
1077         .mmu_ctpr_mask = 0x007ffff0,
1078         .mmu_cxr_mask = 0x0000003f,
1079         .mmu_sfsr_mask = 0xffffffff,
1080         .mmu_trcr_mask = 0xffffffff,
1081         .features = CPU_DEFAULT_FEATURES,
1082     },
1083     {
1084         .name = "LEON3",
1085         .iu_version = 0xf3000000,
1086         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1087         .mmu_version = 0xf3000000,
1088         .mmu_bm = 0x00004000,
1089         .mmu_ctpr_mask = 0x007ffff0,
1090         .mmu_cxr_mask = 0x0000003f,
1091         .mmu_sfsr_mask = 0xffffffff,
1092         .mmu_trcr_mask = 0xffffffff,
1093         .features = CPU_DEFAULT_FEATURES,
1094     },
1095 #endif
1096 };
1097
1098 static const char * const feature_name[] = {
1099     "float",
1100     "float128",
1101     "swap",
1102     "mul",
1103     "div",
1104     "flush",
1105     "fsqrt",
1106     "fmul",
1107     "vis1",
1108     "vis2",
1109 };
1110
1111 static void print_features(FILE *f,
1112                            int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1113                            uint32_t features, const char *prefix)
1114 {
1115     unsigned int i;
1116
1117     for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1118         if (feature_name[i] && (features & (1 << i))) {
1119             if (prefix)
1120                 (*cpu_fprintf)(f, "%s", prefix);
1121             (*cpu_fprintf)(f, "%s ", feature_name[i]);
1122         }
1123 }
1124
1125 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1126 {
1127     unsigned int i;
1128
1129     for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1130         if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1131             *features |= 1 << i;
1132             return;
1133         }
1134     fprintf(stderr, "CPU feature %s not found\n", flagname);
1135 }
1136
1137 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const unsigned char *cpu_model)
1138 {
1139     unsigned int i;
1140     const sparc_def_t *def = NULL;
1141     char *s = strdup(cpu_model);
1142     char *featurestr, *name = strtok(s, ",");
1143     uint32_t plus_features = 0;
1144     uint32_t minus_features = 0;
1145     long long iu_version;
1146     uint32_t fpu_version, mmu_version;
1147
1148     for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1149         if (strcasecmp(name, sparc_defs[i].name) == 0) {
1150             def = &sparc_defs[i];
1151         }
1152     }
1153     if (!def)
1154         goto error;
1155     memcpy(cpu_def, def, sizeof(*def));
1156
1157     featurestr = strtok(NULL, ",");
1158     while (featurestr) {
1159         char *val;
1160
1161         if (featurestr[0] == '+') {
1162             add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1163         } else if (featurestr[0] == '-') {
1164             add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1165         } else if ((val = strchr(featurestr, '='))) {
1166             *val = 0; val++;
1167             if (!strcmp(featurestr, "iu_version")) {
1168                 char *err;
1169
1170                 iu_version = strtoll(val, &err, 0);
1171                 if (!*val || *err) {
1172                     fprintf(stderr, "bad numerical value %s\n", val);
1173                     goto error;
1174                 }
1175                 cpu_def->iu_version = iu_version;
1176 #ifdef DEBUG_FEATURES
1177                 fprintf(stderr, "iu_version %llx\n", iu_version);
1178 #endif
1179             } else if (!strcmp(featurestr, "fpu_version")) {
1180                 char *err;
1181
1182                 fpu_version = strtol(val, &err, 0);
1183                 if (!*val || *err) {
1184                     fprintf(stderr, "bad numerical value %s\n", val);
1185                     goto error;
1186                 }
1187                 cpu_def->fpu_version = fpu_version;
1188 #ifdef DEBUG_FEATURES
1189                 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1190 #endif
1191             } else if (!strcmp(featurestr, "mmu_version")) {
1192                 char *err;
1193
1194                 mmu_version = strtol(val, &err, 0);
1195                 if (!*val || *err) {
1196                     fprintf(stderr, "bad numerical value %s\n", val);
1197                     goto error;
1198                 }
1199                 cpu_def->mmu_version = mmu_version;
1200 #ifdef DEBUG_FEATURES
1201                 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1202 #endif
1203             } else {
1204                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1205                 goto error;
1206             }
1207         } else {
1208             fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
1209             goto error;
1210         }
1211         featurestr = strtok(NULL, ",");
1212     }
1213     cpu_def->features |= plus_features;
1214     cpu_def->features &= ~minus_features;
1215 #ifdef DEBUG_FEATURES
1216     print_features(stderr, fprintf, cpu_def->features, NULL);
1217 #endif
1218     free(s);
1219     return 0;
1220
1221  error:
1222     free(s);
1223     return -1;
1224 }
1225
1226 void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1227 {
1228     unsigned int i;
1229
1230     for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1231         (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x ",
1232                        sparc_defs[i].name,
1233                        sparc_defs[i].iu_version,
1234                        sparc_defs[i].fpu_version,
1235                        sparc_defs[i].mmu_version);
1236         print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
1237         print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
1238         (*cpu_fprintf)(f, "\n");
1239     }
1240     (*cpu_fprintf)(f, "CPU feature flags (+/-): ");
1241     print_features(f, cpu_fprintf, -1, NULL);
1242     (*cpu_fprintf)(f, "\n");
1243     (*cpu_fprintf)(f, "Numerical features (=): iu_version fpu_version mmu_version\n");
1244 }
1245
1246 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1247
1248 void cpu_dump_state(CPUState *env, FILE *f,
1249                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1250                     int flags)
1251 {
1252     int i, x;
1253
1254     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
1255     cpu_fprintf(f, "General Registers:\n");
1256     for (i = 0; i < 4; i++)
1257         cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1258     cpu_fprintf(f, "\n");
1259     for (; i < 8; i++)
1260         cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1261     cpu_fprintf(f, "\nCurrent Register Window:\n");
1262     for (x = 0; x < 3; x++) {
1263         for (i = 0; i < 4; i++)
1264             cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1265                     (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1266                     env->regwptr[i + x * 8]);
1267         cpu_fprintf(f, "\n");
1268         for (; i < 8; i++)
1269             cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1270                     (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1271                     env->regwptr[i + x * 8]);
1272         cpu_fprintf(f, "\n");
1273     }
1274     cpu_fprintf(f, "\nFloating Point Registers:\n");
1275     for (i = 0; i < 32; i++) {
1276         if ((i & 3) == 0)
1277             cpu_fprintf(f, "%%f%02d:", i);
1278         cpu_fprintf(f, " %016lf", env->fpr[i]);
1279         if ((i & 3) == 3)
1280             cpu_fprintf(f, "\n");
1281     }
1282 #ifdef TARGET_SPARC64
1283     cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1284                 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1285     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
1286                 env->cansave, env->canrestore, env->otherwin, env->wstate,
1287                 env->cleanwin, NWINDOWS - 1 - env->cwp);
1288 #else
1289     cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
1290             GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1291             GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1292             env->psrs?'S':'-', env->psrps?'P':'-',
1293             env->psret?'E':'-', env->wim);
1294 #endif
1295     cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1296 }
1297
1298 #ifdef TARGET_SPARC64
1299 #if !defined(CONFIG_USER_ONLY)
1300 #include "qemu-common.h"
1301 #include "hw/irq.h"
1302 #include "qemu-timer.h"
1303 #endif
1304
1305 void helper_tick_set_count(void *opaque, uint64_t count)
1306 {
1307 #if !defined(CONFIG_USER_ONLY)
1308     ptimer_set_count(opaque, -count);
1309 #endif
1310 }
1311
1312 uint64_t helper_tick_get_count(void *opaque)
1313 {
1314 #if !defined(CONFIG_USER_ONLY)
1315     return -ptimer_get_count(opaque);
1316 #else
1317     return 0;
1318 #endif
1319 }
1320
1321 void helper_tick_set_limit(void *opaque, uint64_t limit)
1322 {
1323 #if !defined(CONFIG_USER_ONLY)
1324     ptimer_set_limit(opaque, -limit, 0);
1325 #endif
1326 }
1327 #endif