]> git.proxmox.com Git - qemu.git/blame - target-sparc/helper.c
SPARC64: split cpu_get_phys_page_debug() from cpu_get_phys_page_nofault()
[qemu.git] / target-sparc / helper.c
CommitLineData
e8af50a3
FB
1/*
2 * sparc helpers
5fafdf24 3 *
83469015 4 * Copyright (c) 2003-2005 Fabrice Bellard
e8af50a3
FB
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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
e8af50a3 18 */
ee5bbe38
FB
19#include <stdarg.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <inttypes.h>
ee5bbe38
FB
24
25#include "cpu.h"
ca10f867 26#include "qemu-common.h"
e8af50a3 27
e80cfcfc 28//#define DEBUG_MMU
64a88d5d 29//#define DEBUG_FEATURES
e8af50a3 30
b8e9fc06
IK
31#ifdef DEBUG_MMU
32#define DPRINTF_MMU(fmt, ...) \
33 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
34#else
35#define DPRINTF_MMU(fmt, ...) do {} while (0)
36#endif
37
22548760 38static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
c48fcb47 39
e8af50a3 40/* Sparc MMU emulation */
e8af50a3 41
5fafdf24 42#if defined(CONFIG_USER_ONLY)
9d893301 43
22548760 44int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
6ebbf390 45 int mmu_idx, int is_softmmu)
9d893301 46{
878d3096 47 if (rw & 2)
22548760 48 env1->exception_index = TT_TFAULT;
878d3096 49 else
22548760 50 env1->exception_index = TT_DFAULT;
9d893301
FB
51 return 1;
52}
53
54#else
e8af50a3 55
3475187d 56#ifndef TARGET_SPARC64
83469015
FB
57/*
58 * Sparc V8 Reference MMU (SRMMU)
59 */
e8af50a3 60static const int access_table[8][8] = {
a764a566
BS
61 { 0, 0, 0, 0, 8, 0, 12, 12 },
62 { 0, 0, 0, 0, 8, 0, 0, 0 },
63 { 8, 8, 0, 0, 0, 8, 12, 12 },
64 { 8, 8, 0, 0, 0, 8, 0, 0 },
65 { 8, 0, 8, 0, 8, 8, 12, 12 },
66 { 8, 0, 8, 0, 8, 0, 8, 0 },
67 { 8, 8, 8, 0, 8, 8, 12, 12 },
68 { 8, 8, 8, 0, 8, 8, 8, 0 }
e8af50a3
FB
69};
70
227671c9
FB
71static const int perm_table[2][8] = {
72 {
73 PAGE_READ,
74 PAGE_READ | PAGE_WRITE,
75 PAGE_READ | PAGE_EXEC,
76 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
77 PAGE_EXEC,
78 PAGE_READ | PAGE_WRITE,
79 PAGE_READ | PAGE_EXEC,
80 PAGE_READ | PAGE_WRITE | PAGE_EXEC
81 },
82 {
83 PAGE_READ,
84 PAGE_READ | PAGE_WRITE,
85 PAGE_READ | PAGE_EXEC,
86 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
87 PAGE_EXEC,
88 PAGE_READ,
89 0,
90 0,
91 }
e8af50a3
FB
92};
93
c227f099 94static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
c48fcb47 95 int *prot, int *access_index,
d4c430a8
PB
96 target_ulong address, int rw, int mmu_idx,
97 target_ulong *page_size)
e8af50a3 98{
e80cfcfc 99 int access_perms = 0;
c227f099 100 target_phys_addr_t pde_ptr;
af7bf89b 101 uint32_t pde;
6ebbf390 102 int error_code = 0, is_dirty, is_user;
e80cfcfc 103 unsigned long page_offset;
e8af50a3 104
6ebbf390 105 is_user = mmu_idx == MMU_USER_IDX;
40ce0a9a 106
e8af50a3 107 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
d4c430a8 108 *page_size = TARGET_PAGE_SIZE;
40ce0a9a 109 // Boot mode: instruction fetches are taken from PROM
5578ceab 110 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
58a770f3 111 *physical = env->prom_addr | (address & 0x7ffffULL);
40ce0a9a
BS
112 *prot = PAGE_READ | PAGE_EXEC;
113 return 0;
114 }
0f8a249a 115 *physical = address;
227671c9 116 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
e80cfcfc 117 return 0;
e8af50a3
FB
118 }
119
7483750d 120 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
5dcb6b91 121 *physical = 0xffffffffffff0000ULL;
7483750d 122
e8af50a3
FB
123 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
124 /* Context base + context number */
3deaeab7 125 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
49be8030 126 pde = ldl_phys(pde_ptr);
e8af50a3
FB
127
128 /* Ctx pde */
129 switch (pde & PTE_ENTRYTYPE_MASK) {
e80cfcfc 130 default:
e8af50a3 131 case 0: /* Invalid */
0f8a249a 132 return 1 << 2;
e80cfcfc 133 case 2: /* L0 PTE, maybe should not happen? */
e8af50a3 134 case 3: /* Reserved */
7483750d 135 return 4 << 2;
e80cfcfc 136 case 1: /* L0 PDE */
0f8a249a 137 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
49be8030 138 pde = ldl_phys(pde_ptr);
e8af50a3 139
0f8a249a
BS
140 switch (pde & PTE_ENTRYTYPE_MASK) {
141 default:
142 case 0: /* Invalid */
143 return (1 << 8) | (1 << 2);
144 case 3: /* Reserved */
145 return (1 << 8) | (4 << 2);
146 case 1: /* L1 PDE */
147 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
49be8030 148 pde = ldl_phys(pde_ptr);
e8af50a3 149
0f8a249a
BS
150 switch (pde & PTE_ENTRYTYPE_MASK) {
151 default:
152 case 0: /* Invalid */
153 return (2 << 8) | (1 << 2);
154 case 3: /* Reserved */
155 return (2 << 8) | (4 << 2);
156 case 1: /* L2 PDE */
157 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
49be8030 158 pde = ldl_phys(pde_ptr);
e8af50a3 159
0f8a249a
BS
160 switch (pde & PTE_ENTRYTYPE_MASK) {
161 default:
162 case 0: /* Invalid */
163 return (3 << 8) | (1 << 2);
164 case 1: /* PDE, should not happen */
165 case 3: /* Reserved */
166 return (3 << 8) | (4 << 2);
167 case 2: /* L3 PTE */
77f193da
BS
168 page_offset = (address & TARGET_PAGE_MASK) &
169 (TARGET_PAGE_SIZE - 1);
0f8a249a 170 }
d4c430a8 171 *page_size = TARGET_PAGE_SIZE;
0f8a249a
BS
172 break;
173 case 2: /* L2 PTE */
0f8a249a 174 page_offset = address & 0x3ffff;
d4c430a8 175 *page_size = 0x40000;
0f8a249a
BS
176 }
177 break;
178 case 2: /* L1 PTE */
0f8a249a 179 page_offset = address & 0xffffff;
d4c430a8 180 *page_size = 0x1000000;
0f8a249a 181 }
e8af50a3
FB
182 }
183
698235aa
AT
184 /* check access */
185 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
186 error_code = access_table[*access_index][access_perms];
187 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
188 return error_code;
189
e8af50a3 190 /* update page modified and dirty bits */
b769d8fe 191 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
e8af50a3 192 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
0f8a249a
BS
193 pde |= PG_ACCESSED_MASK;
194 if (is_dirty)
195 pde |= PG_MODIFIED_MASK;
49be8030 196 stl_phys_notdirty(pde_ptr, pde);
e8af50a3 197 }
e8af50a3
FB
198
199 /* the page can be put in the TLB */
227671c9
FB
200 *prot = perm_table[is_user][access_perms];
201 if (!(pde & PG_MODIFIED_MASK)) {
e8af50a3
FB
202 /* only set write access if already dirty... otherwise wait
203 for dirty access */
227671c9 204 *prot &= ~PAGE_WRITE;
e8af50a3
FB
205 }
206
207 /* Even if large ptes, we map only one 4KB page in the cache to
208 avoid filling it too fast */
c227f099 209 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
6f7e9aec 210 return error_code;
e80cfcfc
FB
211}
212
213/* Perform address translation */
af7bf89b 214int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 215 int mmu_idx, int is_softmmu)
e80cfcfc 216{
c227f099 217 target_phys_addr_t paddr;
5dcb6b91 218 target_ulong vaddr;
d4c430a8
PB
219 target_ulong page_size;
220 int error_code = 0, prot, access_index;
e8af50a3 221
77f193da 222 error_code = get_physical_address(env, &paddr, &prot, &access_index,
d4c430a8 223 address, rw, mmu_idx, &page_size);
e80cfcfc 224 if (error_code == 0) {
0f8a249a
BS
225 vaddr = address & TARGET_PAGE_MASK;
226 paddr &= TARGET_PAGE_MASK;
9e61bde5 227#ifdef DEBUG_MMU
0f8a249a 228 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
5dcb6b91 229 TARGET_FMT_lx "\n", address, paddr, vaddr);
9e61bde5 230#endif
d4c430a8
PB
231 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
232 return 0;
e80cfcfc 233 }
e8af50a3 234
e8af50a3 235 if (env->mmuregs[3]) /* Fault status register */
0f8a249a 236 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
7483750d 237 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
e8af50a3
FB
238 env->mmuregs[4] = address; /* Fault address register */
239
878d3096 240 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
6f7e9aec
FB
241 // No fault mode: if a mapping is available, just override
242 // permissions. If no mapping is available, redirect accesses to
243 // neverland. Fake/overridden mappings will be flushed when
244 // switching to normal mode.
0f8a249a 245 vaddr = address & TARGET_PAGE_MASK;
227671c9 246 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
d4c430a8
PB
247 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
248 return 0;
7483750d
FB
249 } else {
250 if (rw & 2)
251 env->exception_index = TT_TFAULT;
252 else
253 env->exception_index = TT_DFAULT;
254 return 1;
878d3096 255 }
e8af50a3 256}
24741ef3
FB
257
258target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
259{
c227f099 260 target_phys_addr_t pde_ptr;
24741ef3
FB
261 uint32_t pde;
262
263 /* Context base + context number */
c227f099 264 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
5dcb6b91 265 (env->mmuregs[2] << 2);
24741ef3
FB
266 pde = ldl_phys(pde_ptr);
267
268 switch (pde & PTE_ENTRYTYPE_MASK) {
269 default:
270 case 0: /* Invalid */
271 case 2: /* PTE, maybe should not happen? */
272 case 3: /* Reserved */
0f8a249a 273 return 0;
24741ef3 274 case 1: /* L1 PDE */
0f8a249a
BS
275 if (mmulev == 3)
276 return pde;
277 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
24741ef3
FB
278 pde = ldl_phys(pde_ptr);
279
0f8a249a
BS
280 switch (pde & PTE_ENTRYTYPE_MASK) {
281 default:
282 case 0: /* Invalid */
283 case 3: /* Reserved */
284 return 0;
285 case 2: /* L1 PTE */
286 return pde;
287 case 1: /* L2 PDE */
288 if (mmulev == 2)
289 return pde;
290 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
24741ef3
FB
291 pde = ldl_phys(pde_ptr);
292
0f8a249a
BS
293 switch (pde & PTE_ENTRYTYPE_MASK) {
294 default:
295 case 0: /* Invalid */
296 case 3: /* Reserved */
297 return 0;
298 case 2: /* L2 PTE */
299 return pde;
300 case 1: /* L3 PDE */
301 if (mmulev == 1)
302 return pde;
303 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
24741ef3
FB
304 pde = ldl_phys(pde_ptr);
305
0f8a249a
BS
306 switch (pde & PTE_ENTRYTYPE_MASK) {
307 default:
308 case 0: /* Invalid */
309 case 1: /* PDE, should not happen */
310 case 3: /* Reserved */
311 return 0;
312 case 2: /* L3 PTE */
313 return pde;
314 }
315 }
316 }
24741ef3
FB
317 }
318 return 0;
319}
320
d41160a3 321void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
24741ef3 322{
5dcb6b91
BS
323 target_ulong va, va1, va2;
324 unsigned int n, m, o;
c227f099 325 target_phys_addr_t pde_ptr, pa;
24741ef3
FB
326 uint32_t pde;
327
24741ef3
FB
328 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
329 pde = ldl_phys(pde_ptr);
d41160a3
BS
330 (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
331 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
24741ef3 332 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
0f8a249a
BS
333 pde = mmu_probe(env, va, 2);
334 if (pde) {
335 pa = cpu_get_phys_page_debug(env, va);
d41160a3
BS
336 (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
337 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
0f8a249a
BS
338 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
339 pde = mmu_probe(env, va1, 1);
340 if (pde) {
341 pa = cpu_get_phys_page_debug(env, va1);
d41160a3
BS
342 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
343 TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
344 va1, pa, pde);
0f8a249a
BS
345 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
346 pde = mmu_probe(env, va2, 0);
347 if (pde) {
348 pa = cpu_get_phys_page_debug(env, va2);
d41160a3
BS
349 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
350 TARGET_FMT_plx " PTE: "
351 TARGET_FMT_lx "\n",
352 va2, pa, pde);
0f8a249a
BS
353 }
354 }
355 }
356 }
357 }
24741ef3 358 }
24741ef3 359}
24741ef3
FB
360
361#else /* !TARGET_SPARC64 */
e8807b14
IK
362
363// 41 bit physical address space
c227f099 364static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
e8807b14
IK
365{
366 return x & 0x1ffffffffffULL;
367}
368
83469015
FB
369/*
370 * UltraSparc IIi I/DMMUs
371 */
536ba015 372
536ba015
IK
373// Returns true if TTE tag is valid and matches virtual address value in context
374// requires virtual address mask value calculated from TTE entry size
6e8e7d4c 375static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
536ba015 376 uint64_t address, uint64_t context,
299b520c 377 target_phys_addr_t *physical)
536ba015
IK
378{
379 uint64_t mask;
380
06e12b65 381 switch (TTE_PGSIZE(tlb->tte)) {
536ba015
IK
382 default:
383 case 0x0: // 8k
384 mask = 0xffffffffffffe000ULL;
385 break;
386 case 0x1: // 64k
387 mask = 0xffffffffffff0000ULL;
388 break;
389 case 0x2: // 512k
390 mask = 0xfffffffffff80000ULL;
391 break;
392 case 0x3: // 4M
393 mask = 0xffffffffffc00000ULL;
394 break;
395 }
396
397 // valid, context match, virtual address match?
f707726e 398 if (TTE_IS_VALID(tlb->tte) &&
299b520c 399 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
2a90358f 400 && compare_masked(address, tlb->tag, mask))
536ba015
IK
401 {
402 // decode physical address
6e8e7d4c 403 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
536ba015
IK
404 return 1;
405 }
406
407 return 0;
408}
409
77f193da 410static int get_physical_address_data(CPUState *env,
c227f099 411 target_phys_addr_t *physical, int *prot,
2065061e 412 target_ulong address, int rw, int mmu_idx)
3475187d 413{
3475187d 414 unsigned int i;
536ba015 415 uint64_t context;
ccc76c24 416 uint64_t sfsr = 0;
3475187d 417
2065061e
IK
418 int is_user = (mmu_idx == MMU_USER_IDX ||
419 mmu_idx == MMU_USER_SECONDARY_IDX);
420
3475187d 421 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
e8807b14 422 *physical = ultrasparc_truncate_physical(address);
0f8a249a 423 *prot = PAGE_READ | PAGE_WRITE;
3475187d
FB
424 return 0;
425 }
426
2065061e
IK
427 switch(mmu_idx) {
428 case MMU_USER_IDX:
429 case MMU_KERNEL_IDX:
299b520c 430 context = env->dmmu.mmu_primary_context & 0x1fff;
ccc76c24 431 sfsr |= SFSR_CT_PRIMARY;
2065061e
IK
432 break;
433 case MMU_USER_SECONDARY_IDX:
434 case MMU_KERNEL_SECONDARY_IDX:
435 context = env->dmmu.mmu_secondary_context & 0x1fff;
ccc76c24 436 sfsr |= SFSR_CT_SECONDARY;
2065061e
IK
437 break;
438 case MMU_NUCLEUS_IDX:
ccc76c24
TS
439 sfsr |= SFSR_CT_NUCLEUS;
440 /* FALLTHRU */
44505216 441 default:
299b520c 442 context = 0;
2065061e 443 break;
299b520c 444 }
536ba015 445
ccc76c24
TS
446 if (rw == 1) {
447 sfsr |= SFSR_WRITE_BIT;
448 }
449
3475187d 450 for (i = 0; i < 64; i++) {
afdf8109 451 // ctx match, vaddr match, valid?
b8e9fc06
IK
452 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
453
afdf8109 454 // access ok?
06e12b65 455 if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
ccc76c24 456 sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
b8e9fc06 457 env->exception_index = TT_DFAULT;
6e8e7d4c 458
b8e9fc06
IK
459 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
460 " mmu_idx=%d tl=%d\n",
461 address, context, mmu_idx, env->tl);
06e12b65 462 } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
b8e9fc06 463 env->exception_index = TT_DPROT;
6e8e7d4c 464
b8e9fc06
IK
465 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
466 " mmu_idx=%d tl=%d\n",
467 address, context, mmu_idx, env->tl);
468 } else {
469 *prot = PAGE_READ;
06e12b65 470 if (TTE_IS_W_OK(env->dtlb[i].tte)) {
b8e9fc06 471 *prot |= PAGE_WRITE;
06e12b65 472 }
b8e9fc06
IK
473
474 TTE_SET_USED(env->dtlb[i].tte);
475
476 return 0;
477 }
478
ccc76c24
TS
479 if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
480 sfsr |= SFSR_OW_BIT; /* overflow (not read before
481 another fault) */
482 }
6e8e7d4c 483
ccc76c24
TS
484 if (env->pstate & PS_PRIV) {
485 sfsr |= SFSR_PR_BIT;
486 }
6e8e7d4c 487
ccc76c24
TS
488 /* FIXME: ASI field in SFSR must be set */
489 env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
6e8e7d4c 490
b8e9fc06 491 env->dmmu.sfar = address; /* Fault address register */
9168b3a5
IK
492
493 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
494
b8e9fc06 495 return 1;
0f8a249a 496 }
3475187d 497 }
b8e9fc06
IK
498
499 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
500 address, context);
501
ccc76c24
TS
502 /*
503 * On MMU misses:
504 * - UltraSPARC IIi: SFSR and SFAR unmodified
505 * - JPS1: SFAR updated and some fields of SFSR updated
506 */
6e8e7d4c 507 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
83469015 508 env->exception_index = TT_DMISS;
3475187d
FB
509 return 1;
510}
511
77f193da 512static int get_physical_address_code(CPUState *env,
c227f099 513 target_phys_addr_t *physical, int *prot,
2065061e 514 target_ulong address, int mmu_idx)
3475187d 515{
3475187d 516 unsigned int i;
536ba015 517 uint64_t context;
3475187d 518
2065061e
IK
519 int is_user = (mmu_idx == MMU_USER_IDX ||
520 mmu_idx == MMU_USER_SECONDARY_IDX);
521
e8807b14
IK
522 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
523 /* IMMU disabled */
524 *physical = ultrasparc_truncate_physical(address);
0f8a249a 525 *prot = PAGE_EXEC;
3475187d
FB
526 return 0;
527 }
83469015 528
299b520c 529 if (env->tl == 0) {
2065061e 530 /* PRIMARY context */
299b520c
IK
531 context = env->dmmu.mmu_primary_context & 0x1fff;
532 } else {
2065061e 533 /* NUCLEUS context */
299b520c
IK
534 context = 0;
535 }
536ba015 536
3475187d 537 for (i = 0; i < 64; i++) {
afdf8109 538 // ctx match, vaddr match, valid?
6e8e7d4c 539 if (ultrasparc_tag_match(&env->itlb[i],
299b520c 540 address, context, physical)) {
afdf8109 541 // access ok?
06e12b65 542 if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
ccc76c24
TS
543 /* Fault status register */
544 if (env->immu.sfsr & SFSR_VALID_BIT) {
545 env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
546 another fault) */
547 } else {
548 env->immu.sfsr = 0;
549 }
550 if (env->pstate & PS_PRIV) {
551 env->immu.sfsr |= SFSR_PR_BIT;
552 }
553 if (env->tl > 0) {
554 env->immu.sfsr |= SFSR_CT_NUCLEUS;
555 }
556
557 /* FIXME: ASI field in SFSR must be set */
558 env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
0f8a249a 559 env->exception_index = TT_TFAULT;
b8e9fc06 560
9168b3a5
IK
561 env->immu.tag_access = (address & ~0x1fffULL) | context;
562
b8e9fc06
IK
563 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
564 address, context);
565
0f8a249a
BS
566 return 1;
567 }
0f8a249a 568 *prot = PAGE_EXEC;
f707726e 569 TTE_SET_USED(env->itlb[i].tte);
0f8a249a
BS
570 return 0;
571 }
3475187d 572 }
b8e9fc06
IK
573
574 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
575 address, context);
576
7ab463cb 577 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
6e8e7d4c 578 env->immu.tag_access = (address & ~0x1fffULL) | context;
83469015 579 env->exception_index = TT_TMISS;
3475187d
FB
580 return 1;
581}
582
c227f099 583static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
c48fcb47 584 int *prot, int *access_index,
d4c430a8
PB
585 target_ulong address, int rw, int mmu_idx,
586 target_ulong *page_size)
3475187d 587{
d4c430a8
PB
588 /* ??? We treat everything as a small page, then explicitly flush
589 everything when an entry is evicted. */
590 *page_size = TARGET_PAGE_SIZE;
9fd1ae3a
IK
591
592#if defined (DEBUG_MMU)
593 /* safety net to catch wrong softmmu index use from dynamic code */
594 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
595 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
596 " primary context=%" PRIx64
597 " secondary context=%" PRIx64
598 " address=%" PRIx64
599 "\n",
600 (rw == 2 ? "CODE" : "DATA"),
601 env->tl, mmu_idx,
602 env->dmmu.mmu_primary_context,
603 env->dmmu.mmu_secondary_context,
604 address);
605 }
606#endif
607
3475187d 608 if (rw == 2)
22548760 609 return get_physical_address_code(env, physical, prot, address,
2065061e 610 mmu_idx);
3475187d 611 else
22548760 612 return get_physical_address_data(env, physical, prot, address, rw,
2065061e 613 mmu_idx);
3475187d
FB
614}
615
616/* Perform address translation */
617int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 618 int mmu_idx, int is_softmmu)
3475187d 619{
83469015 620 target_ulong virt_addr, vaddr;
c227f099 621 target_phys_addr_t paddr;
d4c430a8
PB
622 target_ulong page_size;
623 int error_code = 0, prot, access_index;
3475187d 624
77f193da 625 error_code = get_physical_address(env, &paddr, &prot, &access_index,
d4c430a8 626 address, rw, mmu_idx, &page_size);
3475187d 627 if (error_code == 0) {
0f8a249a 628 virt_addr = address & TARGET_PAGE_MASK;
77f193da
BS
629 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
630 (TARGET_PAGE_SIZE - 1));
b8e9fc06
IK
631
632 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
633 " vaddr %" PRIx64
634 " mmu_idx=%d"
635 " tl=%d"
636 " primary context=%" PRIx64
637 " secondary context=%" PRIx64
638 "\n",
639 address, paddr, vaddr, mmu_idx, env->tl,
640 env->dmmu.mmu_primary_context,
641 env->dmmu.mmu_secondary_context);
642
d4c430a8
PB
643 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
644 return 0;
3475187d
FB
645 }
646 // XXX
647 return 1;
648}
649
d41160a3 650void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
83469015
FB
651{
652 unsigned int i;
653 const char *mask;
654
d41160a3
BS
655 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
656 PRId64 "\n",
657 env->dmmu.mmu_primary_context,
658 env->dmmu.mmu_secondary_context);
83469015 659 if ((env->lsu & DMMU_E) == 0) {
d41160a3 660 (*cpu_fprintf)(f, "DMMU disabled\n");
83469015 661 } else {
d41160a3 662 (*cpu_fprintf)(f, "DMMU dump\n");
0f8a249a 663 for (i = 0; i < 64; i++) {
06e12b65 664 switch (TTE_PGSIZE(env->dtlb[i].tte)) {
0f8a249a
BS
665 default:
666 case 0x0:
667 mask = " 8k";
668 break;
669 case 0x1:
670 mask = " 64k";
671 break;
672 case 0x2:
673 mask = "512k";
674 break;
675 case 0x3:
676 mask = " 4M";
677 break;
678 }
06e12b65 679 if (TTE_IS_VALID(env->dtlb[i].tte)) {
d41160a3
BS
680 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
681 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
682 i,
683 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
06e12b65 684 TTE_PA(env->dtlb[i].tte),
d41160a3 685 mask,
06e12b65
TS
686 TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
687 TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
688 TTE_IS_LOCKED(env->dtlb[i].tte) ?
689 "locked" : "unlocked",
d41160a3
BS
690 env->dtlb[i].tag & (uint64_t)0x1fffULL,
691 TTE_IS_GLOBAL(env->dtlb[i].tte)?
692 "global" : "local");
0f8a249a
BS
693 }
694 }
83469015
FB
695 }
696 if ((env->lsu & IMMU_E) == 0) {
d41160a3 697 (*cpu_fprintf)(f, "IMMU disabled\n");
83469015 698 } else {
d41160a3 699 (*cpu_fprintf)(f, "IMMU dump\n");
0f8a249a 700 for (i = 0; i < 64; i++) {
06e12b65 701 switch (TTE_PGSIZE(env->itlb[i].tte)) {
0f8a249a
BS
702 default:
703 case 0x0:
704 mask = " 8k";
705 break;
706 case 0x1:
707 mask = " 64k";
708 break;
709 case 0x2:
710 mask = "512k";
711 break;
712 case 0x3:
713 mask = " 4M";
714 break;
715 }
06e12b65 716 if (TTE_IS_VALID(env->itlb[i].tte)) {
d41160a3
BS
717 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
718 ", %s, %s, %s, ctx %" PRId64 " %s\n",
719 i,
720 env->itlb[i].tag & (uint64_t)~0x1fffULL,
06e12b65 721 TTE_PA(env->itlb[i].tte),
d41160a3 722 mask,
06e12b65
TS
723 TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
724 TTE_IS_LOCKED(env->itlb[i].tte) ?
725 "locked" : "unlocked",
d41160a3
BS
726 env->itlb[i].tag & (uint64_t)0x1fffULL,
727 TTE_IS_GLOBAL(env->itlb[i].tte)?
728 "global" : "local");
0f8a249a
BS
729 }
730 }
83469015
FB
731 }
732}
24741ef3
FB
733
734#endif /* TARGET_SPARC64 */
735#endif /* !CONFIG_USER_ONLY */
736
c48fcb47 737
4fcc562b 738#if !defined(CONFIG_USER_ONLY)
321365ab
TS
739static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
740 target_ulong addr, int rw, int mmu_idx)
741{
742 target_ulong page_size;
743 int prot, access_index;
744
745 return get_physical_address(env, phys, &prot, &access_index, addr, rw,
746 mmu_idx, &page_size);
747}
748
b64b6436 749#if defined(TARGET_SPARC64)
2065061e
IK
750target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
751 int mmu_idx)
c48fcb47 752{
c227f099 753 target_phys_addr_t phys_addr;
c48fcb47 754
321365ab
TS
755 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
756 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
c48fcb47 757 return -1;
321365ab
TS
758 }
759 }
c48fcb47
BS
760 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
761 return -1;
762 return phys_addr;
763}
b64b6436 764#endif
2065061e
IK
765
766target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
767{
b64b6436
TS
768 target_phys_addr_t phys_addr;
769 int mmu_idx = cpu_mmu_index(env);
770
771 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
772 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
773 return -1;
774 }
775 }
776 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) {
777 return -1;
778 }
779 return phys_addr;
2065061e 780}
c48fcb47
BS
781#endif
782
e67768d0
BS
783#ifdef TARGET_SPARC64
784#ifdef DEBUG_PCALL
785static const char * const excp_names[0x80] = {
786 [TT_TFAULT] = "Instruction Access Fault",
787 [TT_TMISS] = "Instruction Access MMU Miss",
788 [TT_CODE_ACCESS] = "Instruction Access Error",
789 [TT_ILL_INSN] = "Illegal Instruction",
790 [TT_PRIV_INSN] = "Privileged Instruction",
791 [TT_NFPU_INSN] = "FPU Disabled",
792 [TT_FP_EXCP] = "FPU Exception",
793 [TT_TOVF] = "Tag Overflow",
794 [TT_CLRWIN] = "Clean Windows",
795 [TT_DIV_ZERO] = "Division By Zero",
796 [TT_DFAULT] = "Data Access Fault",
797 [TT_DMISS] = "Data Access MMU Miss",
798 [TT_DATA_ACCESS] = "Data Access Error",
799 [TT_DPROT] = "Data Protection Error",
800 [TT_UNALIGNED] = "Unaligned Memory Access",
801 [TT_PRIV_ACT] = "Privileged Action",
802 [TT_EXTINT | 0x1] = "External Interrupt 1",
803 [TT_EXTINT | 0x2] = "External Interrupt 2",
804 [TT_EXTINT | 0x3] = "External Interrupt 3",
805 [TT_EXTINT | 0x4] = "External Interrupt 4",
806 [TT_EXTINT | 0x5] = "External Interrupt 5",
807 [TT_EXTINT | 0x6] = "External Interrupt 6",
808 [TT_EXTINT | 0x7] = "External Interrupt 7",
809 [TT_EXTINT | 0x8] = "External Interrupt 8",
810 [TT_EXTINT | 0x9] = "External Interrupt 9",
811 [TT_EXTINT | 0xa] = "External Interrupt 10",
812 [TT_EXTINT | 0xb] = "External Interrupt 11",
813 [TT_EXTINT | 0xc] = "External Interrupt 12",
814 [TT_EXTINT | 0xd] = "External Interrupt 13",
815 [TT_EXTINT | 0xe] = "External Interrupt 14",
816 [TT_EXTINT | 0xf] = "External Interrupt 15",
817};
818#endif
819
820void do_interrupt(CPUState *env)
821{
822 int intno = env->exception_index;
823 trap_state *tsptr;
824
825#ifdef DEBUG_PCALL
826 if (qemu_loglevel_mask(CPU_LOG_INT)) {
827 static int count;
828 const char *name;
829
830 if (intno < 0 || intno >= 0x180) {
831 name = "Unknown";
832 } else if (intno >= 0x100) {
833 name = "Trap Instruction";
834 } else if (intno >= 0xc0) {
835 name = "Window Fill";
836 } else if (intno >= 0x80) {
837 name = "Window Spill";
838 } else {
839 name = excp_names[intno];
840 if (!name) {
841 name = "Unknown";
842 }
843 }
844
845 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
846 " SP=%016" PRIx64 "\n",
847 count, name, intno,
848 env->pc,
849 env->npc, env->regwptr[6]);
850 log_cpu_state(env, 0);
851#if 0
852 {
853 int i;
854 uint8_t *ptr;
855
856 qemu_log(" code=");
857 ptr = (uint8_t *)env->pc;
858 for (i = 0; i < 16; i++) {
859 qemu_log(" %02x", ldub(ptr + i));
860 }
861 qemu_log("\n");
862 }
863#endif
864 count++;
865 }
866#endif
867#if !defined(CONFIG_USER_ONLY)
868 if (env->tl >= env->maxtl) {
869 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
870 " Error state", env->exception_index, env->tl, env->maxtl);
871 return;
872 }
873#endif
874 if (env->tl < env->maxtl - 1) {
875 env->tl++;
876 } else {
877 env->pstate |= PS_RED;
878 if (env->tl < env->maxtl) {
879 env->tl++;
880 }
881 }
882 tsptr = cpu_tsptr(env);
883
884 tsptr->tstate = (cpu_get_ccr(env) << 32) |
885 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
886 cpu_get_cwp64(env);
887 tsptr->tpc = env->pc;
888 tsptr->tnpc = env->npc;
889 tsptr->tt = intno;
890
891 switch (intno) {
892 case TT_IVEC:
893 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
894 break;
895 case TT_TFAULT:
896 case TT_DFAULT:
897 case TT_TMISS ... TT_TMISS + 3:
898 case TT_DMISS ... TT_DMISS + 3:
899 case TT_DPROT ... TT_DPROT + 3:
900 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
901 break;
902 default:
903 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
904 break;
905 }
906
907 if (intno == TT_CLRWIN) {
908 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
909 } else if ((intno & 0x1c0) == TT_SPILL) {
910 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
911 } else if ((intno & 0x1c0) == TT_FILL) {
912 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
913 }
914 env->tbr &= ~0x7fffULL;
915 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
916 env->pc = env->tbr;
917 env->npc = env->pc + 4;
918 env->exception_index = -1;
919}
920#else
921#ifdef DEBUG_PCALL
922static const char * const excp_names[0x80] = {
923 [TT_TFAULT] = "Instruction Access Fault",
924 [TT_ILL_INSN] = "Illegal Instruction",
925 [TT_PRIV_INSN] = "Privileged Instruction",
926 [TT_NFPU_INSN] = "FPU Disabled",
927 [TT_WIN_OVF] = "Window Overflow",
928 [TT_WIN_UNF] = "Window Underflow",
929 [TT_UNALIGNED] = "Unaligned Memory Access",
930 [TT_FP_EXCP] = "FPU Exception",
931 [TT_DFAULT] = "Data Access Fault",
932 [TT_TOVF] = "Tag Overflow",
933 [TT_EXTINT | 0x1] = "External Interrupt 1",
934 [TT_EXTINT | 0x2] = "External Interrupt 2",
935 [TT_EXTINT | 0x3] = "External Interrupt 3",
936 [TT_EXTINT | 0x4] = "External Interrupt 4",
937 [TT_EXTINT | 0x5] = "External Interrupt 5",
938 [TT_EXTINT | 0x6] = "External Interrupt 6",
939 [TT_EXTINT | 0x7] = "External Interrupt 7",
940 [TT_EXTINT | 0x8] = "External Interrupt 8",
941 [TT_EXTINT | 0x9] = "External Interrupt 9",
942 [TT_EXTINT | 0xa] = "External Interrupt 10",
943 [TT_EXTINT | 0xb] = "External Interrupt 11",
944 [TT_EXTINT | 0xc] = "External Interrupt 12",
945 [TT_EXTINT | 0xd] = "External Interrupt 13",
946 [TT_EXTINT | 0xe] = "External Interrupt 14",
947 [TT_EXTINT | 0xf] = "External Interrupt 15",
948 [TT_TOVF] = "Tag Overflow",
949 [TT_CODE_ACCESS] = "Instruction Access Error",
950 [TT_DATA_ACCESS] = "Data Access Error",
951 [TT_DIV_ZERO] = "Division By Zero",
952 [TT_NCP_INSN] = "Coprocessor Disabled",
953};
954#endif
955
956void do_interrupt(CPUState *env)
957{
958 int cwp, intno = env->exception_index;
959
960#ifdef DEBUG_PCALL
961 if (qemu_loglevel_mask(CPU_LOG_INT)) {
962 static int count;
963 const char *name;
964
965 if (intno < 0 || intno >= 0x100) {
966 name = "Unknown";
967 } else if (intno >= 0x80) {
968 name = "Trap Instruction";
969 } else {
970 name = excp_names[intno];
971 if (!name) {
972 name = "Unknown";
973 }
974 }
975
976 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
977 count, name, intno,
978 env->pc,
979 env->npc, env->regwptr[6]);
980 log_cpu_state(env, 0);
981#if 0
982 {
983 int i;
984 uint8_t *ptr;
985
986 qemu_log(" code=");
987 ptr = (uint8_t *)env->pc;
988 for (i = 0; i < 16; i++) {
989 qemu_log(" %02x", ldub(ptr + i));
990 }
991 qemu_log("\n");
992 }
993#endif
994 count++;
995 }
996#endif
997#if !defined(CONFIG_USER_ONLY)
998 if (env->psret == 0) {
999 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
1000 env->exception_index);
1001 return;
1002 }
1003#endif
1004 env->psret = 0;
1005 cwp = cpu_cwp_dec(env, env->cwp - 1);
1006 cpu_set_cwp(env, cwp);
1007 env->regwptr[9] = env->pc;
1008 env->regwptr[10] = env->npc;
1009 env->psrps = env->psrs;
1010 env->psrs = 1;
1011 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1012 env->pc = env->tbr;
1013 env->npc = env->pc + 4;
1014 env->exception_index = -1;
1015
1016#if !defined(CONFIG_USER_ONLY)
1017 /* IRQ acknowledgment */
1018 if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
1019 env->qemu_irq_ack(env->irq_manager, intno);
1020 }
1021#endif
1022}
1023#endif
1024
c48fcb47
BS
1025void cpu_reset(CPUSPARCState *env)
1026{
eca1bdf4
AL
1027 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1028 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1029 log_cpu_state(env, 0);
1030 }
1031
c48fcb47
BS
1032 tlb_flush(env, 1);
1033 env->cwp = 0;
5210977a 1034#ifndef TARGET_SPARC64
c48fcb47 1035 env->wim = 1;
5210977a 1036#endif
c48fcb47 1037 env->regwptr = env->regbase + (env->cwp * 16);
6b743278 1038 CC_OP = CC_OP_FLAGS;
c48fcb47 1039#if defined(CONFIG_USER_ONLY)
c48fcb47 1040#ifdef TARGET_SPARC64
1a14026e
BS
1041 env->cleanwin = env->nwindows - 2;
1042 env->cansave = env->nwindows - 2;
c48fcb47
BS
1043 env->pstate = PS_RMO | PS_PEF | PS_IE;
1044 env->asi = 0x82; // Primary no-fault
1045#endif
1046#else
5210977a 1047#if !defined(TARGET_SPARC64)
c48fcb47
BS
1048 env->psret = 0;
1049 env->psrs = 1;
1050 env->psrps = 1;
2aae2b8e 1051#endif
c48fcb47 1052#ifdef TARGET_SPARC64
8194f35a 1053 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
2aae2b8e 1054 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
8194f35a
IK
1055 env->tl = env->maxtl;
1056 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
415fc906 1057 env->lsu = 0;
c48fcb47 1058#else
c48fcb47 1059 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
5578ceab 1060 env->mmuregs[0] |= env->def->mmu_bm;
c48fcb47 1061#endif
e87231d4 1062 env->pc = 0;
c48fcb47
BS
1063 env->npc = env->pc + 4;
1064#endif
b04d9890 1065 env->cache_control = 0;
c48fcb47
BS
1066}
1067
64a88d5d 1068static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
c48fcb47 1069{
64a88d5d 1070 sparc_def_t def1, *def = &def1;
c48fcb47 1071
64a88d5d
BS
1072 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
1073 return -1;
c48fcb47 1074
5578ceab
BS
1075 env->def = qemu_mallocz(sizeof(*def));
1076 memcpy(env->def, def, sizeof(*def));
1077#if defined(CONFIG_USER_ONLY)
1078 if ((env->def->features & CPU_FEATURE_FLOAT))
1079 env->def->features |= CPU_FEATURE_FLOAT128;
1080#endif
c48fcb47
BS
1081 env->cpu_model_str = cpu_model;
1082 env->version = def->iu_version;
1083 env->fsr = def->fpu_version;
1a14026e 1084 env->nwindows = def->nwindows;
c48fcb47 1085#if !defined(TARGET_SPARC64)
c48fcb47
BS
1086 env->mmuregs[0] |= def->mmu_version;
1087 cpu_sparc_set_id(env, 0);
963262de 1088 env->mxccregs[7] |= def->mxcc_version;
1a14026e 1089#else
fb79ceb9 1090 env->mmu_version = def->mmu_version;
c19148bd
BS
1091 env->maxtl = def->maxtl;
1092 env->version |= def->maxtl << 8;
1a14026e 1093 env->version |= def->nwindows - 1;
c48fcb47 1094#endif
64a88d5d
BS
1095 return 0;
1096}
1097
1098static void cpu_sparc_close(CPUSPARCState *env)
1099{
5578ceab 1100 free(env->def);
64a88d5d
BS
1101 free(env);
1102}
1103
1104CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1105{
1106 CPUSPARCState *env;
1107
1108 env = qemu_mallocz(sizeof(CPUSPARCState));
64a88d5d 1109 cpu_exec_init(env);
c48fcb47
BS
1110
1111 gen_intermediate_code_init(env);
1112
64a88d5d
BS
1113 if (cpu_sparc_register(env, cpu_model) < 0) {
1114 cpu_sparc_close(env);
1115 return NULL;
1116 }
0bf46a40 1117 qemu_init_vcpu(env);
c48fcb47
BS
1118
1119 return env;
1120}
1121
1122void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
1123{
1124#if !defined(TARGET_SPARC64)
1125 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
1126#endif
1127}
1128
1129static const sparc_def_t sparc_defs[] = {
1130#ifdef TARGET_SPARC64
1131 {
1132 .name = "Fujitsu Sparc64",
c19148bd 1133 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
c48fcb47 1134 .fpu_version = 0x00000000,
fb79ceb9 1135 .mmu_version = mmu_us_12,
1a14026e 1136 .nwindows = 4,
c19148bd 1137 .maxtl = 4,
64a88d5d 1138 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1139 },
1140 {
1141 .name = "Fujitsu Sparc64 III",
c19148bd 1142 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
c48fcb47 1143 .fpu_version = 0x00000000,
fb79ceb9 1144 .mmu_version = mmu_us_12,
1a14026e 1145 .nwindows = 5,
c19148bd 1146 .maxtl = 4,
64a88d5d 1147 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1148 },
1149 {
1150 .name = "Fujitsu Sparc64 IV",
c19148bd 1151 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
c48fcb47 1152 .fpu_version = 0x00000000,
fb79ceb9 1153 .mmu_version = mmu_us_12,
1a14026e 1154 .nwindows = 8,
c19148bd 1155 .maxtl = 5,
64a88d5d 1156 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1157 },
1158 {
1159 .name = "Fujitsu Sparc64 V",
c19148bd 1160 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
c48fcb47 1161 .fpu_version = 0x00000000,
fb79ceb9 1162 .mmu_version = mmu_us_12,
1a14026e 1163 .nwindows = 8,
c19148bd 1164 .maxtl = 5,
64a88d5d 1165 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1166 },
1167 {
1168 .name = "TI UltraSparc I",
c19148bd 1169 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 1170 .fpu_version = 0x00000000,
fb79ceb9 1171 .mmu_version = mmu_us_12,
1a14026e 1172 .nwindows = 8,
c19148bd 1173 .maxtl = 5,
64a88d5d 1174 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1175 },
1176 {
1177 .name = "TI UltraSparc II",
c19148bd 1178 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
c48fcb47 1179 .fpu_version = 0x00000000,
fb79ceb9 1180 .mmu_version = mmu_us_12,
1a14026e 1181 .nwindows = 8,
c19148bd 1182 .maxtl = 5,
64a88d5d 1183 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1184 },
1185 {
1186 .name = "TI UltraSparc IIi",
c19148bd 1187 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
c48fcb47 1188 .fpu_version = 0x00000000,
fb79ceb9 1189 .mmu_version = mmu_us_12,
1a14026e 1190 .nwindows = 8,
c19148bd 1191 .maxtl = 5,
64a88d5d 1192 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1193 },
1194 {
1195 .name = "TI UltraSparc IIe",
c19148bd 1196 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
c48fcb47 1197 .fpu_version = 0x00000000,
fb79ceb9 1198 .mmu_version = mmu_us_12,
1a14026e 1199 .nwindows = 8,
c19148bd 1200 .maxtl = 5,
64a88d5d 1201 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1202 },
1203 {
1204 .name = "Sun UltraSparc III",
c19148bd 1205 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
c48fcb47 1206 .fpu_version = 0x00000000,
fb79ceb9 1207 .mmu_version = mmu_us_12,
1a14026e 1208 .nwindows = 8,
c19148bd 1209 .maxtl = 5,
64a88d5d 1210 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1211 },
1212 {
1213 .name = "Sun UltraSparc III Cu",
c19148bd 1214 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
c48fcb47 1215 .fpu_version = 0x00000000,
fb79ceb9 1216 .mmu_version = mmu_us_3,
1a14026e 1217 .nwindows = 8,
c19148bd 1218 .maxtl = 5,
64a88d5d 1219 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1220 },
1221 {
1222 .name = "Sun UltraSparc IIIi",
c19148bd 1223 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
c48fcb47 1224 .fpu_version = 0x00000000,
fb79ceb9 1225 .mmu_version = mmu_us_12,
1a14026e 1226 .nwindows = 8,
c19148bd 1227 .maxtl = 5,
64a88d5d 1228 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1229 },
1230 {
1231 .name = "Sun UltraSparc IV",
c19148bd 1232 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
c48fcb47 1233 .fpu_version = 0x00000000,
fb79ceb9 1234 .mmu_version = mmu_us_4,
1a14026e 1235 .nwindows = 8,
c19148bd 1236 .maxtl = 5,
64a88d5d 1237 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1238 },
1239 {
1240 .name = "Sun UltraSparc IV+",
c19148bd 1241 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
c48fcb47 1242 .fpu_version = 0x00000000,
fb79ceb9 1243 .mmu_version = mmu_us_12,
1a14026e 1244 .nwindows = 8,
c19148bd 1245 .maxtl = 5,
fb79ceb9 1246 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
c48fcb47
BS
1247 },
1248 {
1249 .name = "Sun UltraSparc IIIi+",
c19148bd 1250 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
c48fcb47 1251 .fpu_version = 0x00000000,
fb79ceb9 1252 .mmu_version = mmu_us_3,
1a14026e 1253 .nwindows = 8,
c19148bd 1254 .maxtl = 5,
64a88d5d 1255 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1256 },
c7ba218d
BS
1257 {
1258 .name = "Sun UltraSparc T1",
1259 // defined in sparc_ifu_fdp.v and ctu.h
c19148bd 1260 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
1261 .fpu_version = 0x00000000,
1262 .mmu_version = mmu_sun4v,
1263 .nwindows = 8,
c19148bd 1264 .maxtl = 6,
c7ba218d
BS
1265 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1266 | CPU_FEATURE_GL,
1267 },
1268 {
1269 .name = "Sun UltraSparc T2",
1270 // defined in tlu_asi_ctl.v and n2_revid_cust.v
c19148bd 1271 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
1272 .fpu_version = 0x00000000,
1273 .mmu_version = mmu_sun4v,
1274 .nwindows = 8,
c19148bd 1275 .maxtl = 6,
c7ba218d
BS
1276 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1277 | CPU_FEATURE_GL,
1278 },
c48fcb47
BS
1279 {
1280 .name = "NEC UltraSparc I",
c19148bd 1281 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 1282 .fpu_version = 0x00000000,
fb79ceb9 1283 .mmu_version = mmu_us_12,
1a14026e 1284 .nwindows = 8,
c19148bd 1285 .maxtl = 5,
64a88d5d 1286 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1287 },
1288#else
1289 {
1290 .name = "Fujitsu MB86900",
1291 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1292 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1293 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1294 .mmu_bm = 0x00004000,
1295 .mmu_ctpr_mask = 0x007ffff0,
1296 .mmu_cxr_mask = 0x0000003f,
1297 .mmu_sfsr_mask = 0xffffffff,
1298 .mmu_trcr_mask = 0xffffffff,
1a14026e 1299 .nwindows = 7,
e30b4678 1300 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
c48fcb47
BS
1301 },
1302 {
1303 .name = "Fujitsu MB86904",
1304 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1305 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1306 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1307 .mmu_bm = 0x00004000,
1308 .mmu_ctpr_mask = 0x00ffffc0,
1309 .mmu_cxr_mask = 0x000000ff,
1310 .mmu_sfsr_mask = 0x00016fff,
1311 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1312 .nwindows = 8,
64a88d5d 1313 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1314 },
1315 {
1316 .name = "Fujitsu MB86907",
1317 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1318 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1319 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1320 .mmu_bm = 0x00004000,
1321 .mmu_ctpr_mask = 0xffffffc0,
1322 .mmu_cxr_mask = 0x000000ff,
1323 .mmu_sfsr_mask = 0x00016fff,
1324 .mmu_trcr_mask = 0xffffffff,
1a14026e 1325 .nwindows = 8,
64a88d5d 1326 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1327 },
1328 {
1329 .name = "LSI L64811",
1330 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1331 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1332 .mmu_version = 0x10 << 24,
1333 .mmu_bm = 0x00004000,
1334 .mmu_ctpr_mask = 0x007ffff0,
1335 .mmu_cxr_mask = 0x0000003f,
1336 .mmu_sfsr_mask = 0xffffffff,
1337 .mmu_trcr_mask = 0xffffffff,
1a14026e 1338 .nwindows = 8,
e30b4678
BS
1339 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1340 CPU_FEATURE_FSMULD,
c48fcb47
BS
1341 },
1342 {
1343 .name = "Cypress CY7C601",
1344 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1345 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1346 .mmu_version = 0x10 << 24,
1347 .mmu_bm = 0x00004000,
1348 .mmu_ctpr_mask = 0x007ffff0,
1349 .mmu_cxr_mask = 0x0000003f,
1350 .mmu_sfsr_mask = 0xffffffff,
1351 .mmu_trcr_mask = 0xffffffff,
1a14026e 1352 .nwindows = 8,
e30b4678
BS
1353 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1354 CPU_FEATURE_FSMULD,
c48fcb47
BS
1355 },
1356 {
1357 .name = "Cypress CY7C611",
1358 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1359 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1360 .mmu_version = 0x10 << 24,
1361 .mmu_bm = 0x00004000,
1362 .mmu_ctpr_mask = 0x007ffff0,
1363 .mmu_cxr_mask = 0x0000003f,
1364 .mmu_sfsr_mask = 0xffffffff,
1365 .mmu_trcr_mask = 0xffffffff,
1a14026e 1366 .nwindows = 8,
e30b4678
BS
1367 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1368 CPU_FEATURE_FSMULD,
c48fcb47 1369 },
c48fcb47
BS
1370 {
1371 .name = "TI MicroSparc I",
1372 .iu_version = 0x41000000,
1373 .fpu_version = 4 << 17,
1374 .mmu_version = 0x41000000,
1375 .mmu_bm = 0x00004000,
1376 .mmu_ctpr_mask = 0x007ffff0,
1377 .mmu_cxr_mask = 0x0000003f,
1378 .mmu_sfsr_mask = 0x00016fff,
1379 .mmu_trcr_mask = 0x0000003f,
1a14026e 1380 .nwindows = 7,
e30b4678
BS
1381 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1382 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1383 CPU_FEATURE_FMUL,
c48fcb47
BS
1384 },
1385 {
1386 .name = "TI MicroSparc II",
1387 .iu_version = 0x42000000,
1388 .fpu_version = 4 << 17,
1389 .mmu_version = 0x02000000,
1390 .mmu_bm = 0x00004000,
1391 .mmu_ctpr_mask = 0x00ffffc0,
1392 .mmu_cxr_mask = 0x000000ff,
1393 .mmu_sfsr_mask = 0x00016fff,
1394 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1395 .nwindows = 8,
64a88d5d 1396 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1397 },
1398 {
1399 .name = "TI MicroSparc IIep",
1400 .iu_version = 0x42000000,
1401 .fpu_version = 4 << 17,
1402 .mmu_version = 0x04000000,
1403 .mmu_bm = 0x00004000,
1404 .mmu_ctpr_mask = 0x00ffffc0,
1405 .mmu_cxr_mask = 0x000000ff,
1406 .mmu_sfsr_mask = 0x00016bff,
1407 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1408 .nwindows = 8,
64a88d5d 1409 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1410 },
b5154bde
BS
1411 {
1412 .name = "TI SuperSparc 40", // STP1020NPGA
963262de 1413 .iu_version = 0x41000000, // SuperSPARC 2.x
b5154bde 1414 .fpu_version = 0 << 17,
963262de 1415 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
b5154bde
BS
1416 .mmu_bm = 0x00002000,
1417 .mmu_ctpr_mask = 0xffffffc0,
1418 .mmu_cxr_mask = 0x0000ffff,
1419 .mmu_sfsr_mask = 0xffffffff,
1420 .mmu_trcr_mask = 0xffffffff,
1a14026e 1421 .nwindows = 8,
b5154bde
BS
1422 .features = CPU_DEFAULT_FEATURES,
1423 },
1424 {
1425 .name = "TI SuperSparc 50", // STP1020PGA
963262de 1426 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1427 .fpu_version = 0 << 17,
963262de 1428 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1429 .mmu_bm = 0x00002000,
1430 .mmu_ctpr_mask = 0xffffffc0,
1431 .mmu_cxr_mask = 0x0000ffff,
1432 .mmu_sfsr_mask = 0xffffffff,
1433 .mmu_trcr_mask = 0xffffffff,
1a14026e 1434 .nwindows = 8,
b5154bde
BS
1435 .features = CPU_DEFAULT_FEATURES,
1436 },
c48fcb47
BS
1437 {
1438 .name = "TI SuperSparc 51",
963262de 1439 .iu_version = 0x40000000, // SuperSPARC 3.x
c48fcb47 1440 .fpu_version = 0 << 17,
963262de 1441 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
c48fcb47
BS
1442 .mmu_bm = 0x00002000,
1443 .mmu_ctpr_mask = 0xffffffc0,
1444 .mmu_cxr_mask = 0x0000ffff,
1445 .mmu_sfsr_mask = 0xffffffff,
1446 .mmu_trcr_mask = 0xffffffff,
963262de 1447 .mxcc_version = 0x00000104,
1a14026e 1448 .nwindows = 8,
64a88d5d 1449 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1450 },
b5154bde
BS
1451 {
1452 .name = "TI SuperSparc 60", // STP1020APGA
963262de 1453 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1454 .fpu_version = 0 << 17,
963262de 1455 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1456 .mmu_bm = 0x00002000,
1457 .mmu_ctpr_mask = 0xffffffc0,
1458 .mmu_cxr_mask = 0x0000ffff,
1459 .mmu_sfsr_mask = 0xffffffff,
1460 .mmu_trcr_mask = 0xffffffff,
1a14026e 1461 .nwindows = 8,
b5154bde
BS
1462 .features = CPU_DEFAULT_FEATURES,
1463 },
c48fcb47
BS
1464 {
1465 .name = "TI SuperSparc 61",
963262de 1466 .iu_version = 0x44000000, // SuperSPARC 3.x
c48fcb47 1467 .fpu_version = 0 << 17,
963262de
BS
1468 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1469 .mmu_bm = 0x00002000,
1470 .mmu_ctpr_mask = 0xffffffc0,
1471 .mmu_cxr_mask = 0x0000ffff,
1472 .mmu_sfsr_mask = 0xffffffff,
1473 .mmu_trcr_mask = 0xffffffff,
1474 .mxcc_version = 0x00000104,
1475 .nwindows = 8,
1476 .features = CPU_DEFAULT_FEATURES,
1477 },
1478 {
1479 .name = "TI SuperSparc II",
1480 .iu_version = 0x40000000, // SuperSPARC II 1.x
1481 .fpu_version = 0 << 17,
1482 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
c48fcb47
BS
1483 .mmu_bm = 0x00002000,
1484 .mmu_ctpr_mask = 0xffffffc0,
1485 .mmu_cxr_mask = 0x0000ffff,
1486 .mmu_sfsr_mask = 0xffffffff,
1487 .mmu_trcr_mask = 0xffffffff,
963262de 1488 .mxcc_version = 0x00000104,
1a14026e 1489 .nwindows = 8,
64a88d5d 1490 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1491 },
1492 {
1493 .name = "Ross RT625",
1494 .iu_version = 0x1e000000,
1495 .fpu_version = 1 << 17,
1496 .mmu_version = 0x1e000000,
1497 .mmu_bm = 0x00004000,
1498 .mmu_ctpr_mask = 0x007ffff0,
1499 .mmu_cxr_mask = 0x0000003f,
1500 .mmu_sfsr_mask = 0xffffffff,
1501 .mmu_trcr_mask = 0xffffffff,
1a14026e 1502 .nwindows = 8,
64a88d5d 1503 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1504 },
1505 {
1506 .name = "Ross RT620",
1507 .iu_version = 0x1f000000,
1508 .fpu_version = 1 << 17,
1509 .mmu_version = 0x1f000000,
1510 .mmu_bm = 0x00004000,
1511 .mmu_ctpr_mask = 0x007ffff0,
1512 .mmu_cxr_mask = 0x0000003f,
1513 .mmu_sfsr_mask = 0xffffffff,
1514 .mmu_trcr_mask = 0xffffffff,
1a14026e 1515 .nwindows = 8,
64a88d5d 1516 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1517 },
1518 {
1519 .name = "BIT B5010",
1520 .iu_version = 0x20000000,
1521 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1522 .mmu_version = 0x20000000,
1523 .mmu_bm = 0x00004000,
1524 .mmu_ctpr_mask = 0x007ffff0,
1525 .mmu_cxr_mask = 0x0000003f,
1526 .mmu_sfsr_mask = 0xffffffff,
1527 .mmu_trcr_mask = 0xffffffff,
1a14026e 1528 .nwindows = 8,
e30b4678
BS
1529 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1530 CPU_FEATURE_FSMULD,
c48fcb47
BS
1531 },
1532 {
1533 .name = "Matsushita MN10501",
1534 .iu_version = 0x50000000,
1535 .fpu_version = 0 << 17,
1536 .mmu_version = 0x50000000,
1537 .mmu_bm = 0x00004000,
1538 .mmu_ctpr_mask = 0x007ffff0,
1539 .mmu_cxr_mask = 0x0000003f,
1540 .mmu_sfsr_mask = 0xffffffff,
1541 .mmu_trcr_mask = 0xffffffff,
1a14026e 1542 .nwindows = 8,
e30b4678
BS
1543 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1544 CPU_FEATURE_FSMULD,
c48fcb47
BS
1545 },
1546 {
1547 .name = "Weitek W8601",
1548 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1549 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1550 .mmu_version = 0x10 << 24,
1551 .mmu_bm = 0x00004000,
1552 .mmu_ctpr_mask = 0x007ffff0,
1553 .mmu_cxr_mask = 0x0000003f,
1554 .mmu_sfsr_mask = 0xffffffff,
1555 .mmu_trcr_mask = 0xffffffff,
1a14026e 1556 .nwindows = 8,
64a88d5d 1557 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1558 },
1559 {
1560 .name = "LEON2",
1561 .iu_version = 0xf2000000,
1562 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1563 .mmu_version = 0xf2000000,
1564 .mmu_bm = 0x00004000,
1565 .mmu_ctpr_mask = 0x007ffff0,
1566 .mmu_cxr_mask = 0x0000003f,
1567 .mmu_sfsr_mask = 0xffffffff,
1568 .mmu_trcr_mask = 0xffffffff,
1a14026e 1569 .nwindows = 8,
b04d9890 1570 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
c48fcb47
BS
1571 },
1572 {
1573 .name = "LEON3",
1574 .iu_version = 0xf3000000,
1575 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1576 .mmu_version = 0xf3000000,
b04d9890 1577 .mmu_bm = 0x00000000,
c48fcb47
BS
1578 .mmu_ctpr_mask = 0x007ffff0,
1579 .mmu_cxr_mask = 0x0000003f,
1580 .mmu_sfsr_mask = 0xffffffff,
1581 .mmu_trcr_mask = 0xffffffff,
1a14026e 1582 .nwindows = 8,
4a2ba232 1583 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
60f356e8 1584 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
c48fcb47
BS
1585 },
1586#endif
1587};
1588
64a88d5d
BS
1589static const char * const feature_name[] = {
1590 "float",
1591 "float128",
1592 "swap",
1593 "mul",
1594 "div",
1595 "flush",
1596 "fsqrt",
1597 "fmul",
1598 "vis1",
1599 "vis2",
e30b4678 1600 "fsmuld",
fb79ceb9
BS
1601 "hypv",
1602 "cmt",
1603 "gl",
64a88d5d
BS
1604};
1605
9a78eead 1606static void print_features(FILE *f, fprintf_function cpu_fprintf,
64a88d5d 1607 uint32_t features, const char *prefix)
c48fcb47
BS
1608{
1609 unsigned int i;
1610
64a88d5d
BS
1611 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1612 if (feature_name[i] && (features & (1 << i))) {
1613 if (prefix)
1614 (*cpu_fprintf)(f, "%s", prefix);
1615 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1616 }
1617}
1618
1619static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1620{
1621 unsigned int i;
1622
1623 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1624 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1625 *features |= 1 << i;
1626 return;
1627 }
1628 fprintf(stderr, "CPU feature %s not found\n", flagname);
1629}
1630
22548760 1631static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
64a88d5d
BS
1632{
1633 unsigned int i;
1634 const sparc_def_t *def = NULL;
1635 char *s = strdup(cpu_model);
1636 char *featurestr, *name = strtok(s, ",");
1637 uint32_t plus_features = 0;
1638 uint32_t minus_features = 0;
0bfcd599 1639 uint64_t iu_version;
1a14026e 1640 uint32_t fpu_version, mmu_version, nwindows;
64a88d5d 1641
b1503cda 1642 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
c48fcb47 1643 if (strcasecmp(name, sparc_defs[i].name) == 0) {
64a88d5d 1644 def = &sparc_defs[i];
c48fcb47
BS
1645 }
1646 }
64a88d5d
BS
1647 if (!def)
1648 goto error;
1649 memcpy(cpu_def, def, sizeof(*def));
1650
1651 featurestr = strtok(NULL, ",");
1652 while (featurestr) {
1653 char *val;
1654
1655 if (featurestr[0] == '+') {
1656 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1657 } else if (featurestr[0] == '-') {
1658 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1659 } else if ((val = strchr(featurestr, '='))) {
1660 *val = 0; val++;
1661 if (!strcmp(featurestr, "iu_version")) {
1662 char *err;
1663
1664 iu_version = strtoll(val, &err, 0);
1665 if (!*val || *err) {
1666 fprintf(stderr, "bad numerical value %s\n", val);
1667 goto error;
1668 }
1669 cpu_def->iu_version = iu_version;
1670#ifdef DEBUG_FEATURES
0bfcd599 1671 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
64a88d5d
BS
1672#endif
1673 } else if (!strcmp(featurestr, "fpu_version")) {
1674 char *err;
1675
1676 fpu_version = strtol(val, &err, 0);
1677 if (!*val || *err) {
1678 fprintf(stderr, "bad numerical value %s\n", val);
1679 goto error;
1680 }
1681 cpu_def->fpu_version = fpu_version;
1682#ifdef DEBUG_FEATURES
0bf9e31a 1683 fprintf(stderr, "fpu_version %x\n", fpu_version);
64a88d5d
BS
1684#endif
1685 } else if (!strcmp(featurestr, "mmu_version")) {
1686 char *err;
1687
1688 mmu_version = strtol(val, &err, 0);
1689 if (!*val || *err) {
1690 fprintf(stderr, "bad numerical value %s\n", val);
1691 goto error;
1692 }
1693 cpu_def->mmu_version = mmu_version;
1694#ifdef DEBUG_FEATURES
0bf9e31a 1695 fprintf(stderr, "mmu_version %x\n", mmu_version);
1a14026e
BS
1696#endif
1697 } else if (!strcmp(featurestr, "nwindows")) {
1698 char *err;
1699
1700 nwindows = strtol(val, &err, 0);
1701 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1702 nwindows < MIN_NWINDOWS) {
1703 fprintf(stderr, "bad numerical value %s\n", val);
1704 goto error;
1705 }
1706 cpu_def->nwindows = nwindows;
1707#ifdef DEBUG_FEATURES
1708 fprintf(stderr, "nwindows %d\n", nwindows);
64a88d5d
BS
1709#endif
1710 } else {
1711 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1712 goto error;
1713 }
1714 } else {
77f193da
BS
1715 fprintf(stderr, "feature string `%s' not in format "
1716 "(+feature|-feature|feature=xyz)\n", featurestr);
64a88d5d
BS
1717 goto error;
1718 }
1719 featurestr = strtok(NULL, ",");
1720 }
1721 cpu_def->features |= plus_features;
1722 cpu_def->features &= ~minus_features;
1723#ifdef DEBUG_FEATURES
1724 print_features(stderr, fprintf, cpu_def->features, NULL);
1725#endif
1726 free(s);
1727 return 0;
1728
1729 error:
1730 free(s);
1731 return -1;
c48fcb47
BS
1732}
1733
9a78eead 1734void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
c48fcb47
BS
1735{
1736 unsigned int i;
1737
b1503cda 1738 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1a14026e 1739 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
c48fcb47
BS
1740 sparc_defs[i].name,
1741 sparc_defs[i].iu_version,
1742 sparc_defs[i].fpu_version,
1a14026e
BS
1743 sparc_defs[i].mmu_version,
1744 sparc_defs[i].nwindows);
77f193da
BS
1745 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1746 ~sparc_defs[i].features, "-");
1747 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1748 sparc_defs[i].features, "+");
64a88d5d 1749 (*cpu_fprintf)(f, "\n");
c48fcb47 1750 }
f76981b1
BS
1751 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1752 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
64a88d5d 1753 (*cpu_fprintf)(f, "\n");
f76981b1
BS
1754 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1755 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1756 (*cpu_fprintf)(f, "\n");
1757 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1758 "fpu_version mmu_version nwindows\n");
c48fcb47
BS
1759}
1760
9a78eead 1761static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
43bb98bf
BS
1762 uint32_t cc)
1763{
1764 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1765 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1766 cc & PSR_CARRY? 'C' : '-');
1767}
1768
1769#ifdef TARGET_SPARC64
1770#define REGS_PER_LINE 4
1771#else
1772#define REGS_PER_LINE 8
1773#endif
1774
9a78eead 1775void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
c48fcb47
BS
1776 int flags)
1777{
1778 int i, x;
1779
77f193da
BS
1780 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1781 env->npc);
c48fcb47 1782 cpu_fprintf(f, "General Registers:\n");
43bb98bf
BS
1783
1784 for (i = 0; i < 8; i++) {
1785 if (i % REGS_PER_LINE == 0) {
1786 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1787 }
1788 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1789 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1790 cpu_fprintf(f, "\n");
1791 }
1792 }
c48fcb47
BS
1793 cpu_fprintf(f, "\nCurrent Register Window:\n");
1794 for (x = 0; x < 3; x++) {
43bb98bf
BS
1795 for (i = 0; i < 8; i++) {
1796 if (i % REGS_PER_LINE == 0) {
1797 cpu_fprintf(f, "%%%c%d-%d: ",
1798 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1799 i, i + REGS_PER_LINE - 1);
1800 }
1801 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1802 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1803 cpu_fprintf(f, "\n");
1804 }
1805 }
c48fcb47
BS
1806 }
1807 cpu_fprintf(f, "\nFloating Point Registers:\n");
43bb98bf 1808 for (i = 0; i < TARGET_FPREGS; i++) {
c48fcb47
BS
1809 if ((i & 3) == 0)
1810 cpu_fprintf(f, "%%f%02d:", i);
a37ee56c 1811 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
c48fcb47
BS
1812 if ((i & 3) == 3)
1813 cpu_fprintf(f, "\n");
1814 }
1815#ifdef TARGET_SPARC64
43bb98bf 1816 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
113c6106 1817 (unsigned)cpu_get_ccr(env));
5a834bb4 1818 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
43bb98bf 1819 cpu_fprintf(f, " xcc: ");
5a834bb4 1820 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
43bb98bf
BS
1821 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1822 env->psrpil);
1823 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1824 "cleanwin: %d cwp: %d\n",
c48fcb47 1825 env->cansave, env->canrestore, env->otherwin, env->wstate,
1a14026e 1826 env->cleanwin, env->nwindows - 1 - env->cwp);
43bb98bf
BS
1827 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1828 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
c48fcb47 1829#else
5a834bb4
BS
1830 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1831 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
43bb98bf
BS
1832 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1833 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1834 env->wim);
1835 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1836 env->fsr, env->y);
c48fcb47 1837#endif
c48fcb47 1838}