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