]> git.proxmox.com Git - qemu.git/blame - target-sparc/helper.c
Use glib memory allocation and free functions
[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,
97b348e7 45 int mmu_idx)
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,
97b348e7 215 int mmu_idx)
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;
d1afc48b
TS
448 } else if (rw == 4) {
449 sfsr |= SFSR_NF_BIT;
ccc76c24
TS
450 }
451
3475187d 452 for (i = 0; i < 64; i++) {
afdf8109 453 // ctx match, vaddr match, valid?
b8e9fc06 454 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
d1afc48b 455 int do_fault = 0;
b8e9fc06 456
afdf8109 457 // access ok?
d1afc48b 458 /* multiple bits in SFSR.FT may be set on TT_DFAULT */
06e12b65 459 if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
d1afc48b 460 do_fault = 1;
ccc76c24 461 sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
6e8e7d4c 462
b8e9fc06
IK
463 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
464 " mmu_idx=%d tl=%d\n",
465 address, context, mmu_idx, env->tl);
d1afc48b
TS
466 }
467 if (rw == 4) {
468 if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) {
469 do_fault = 1;
470 sfsr |= SFSR_FT_NF_E_BIT;
471 }
472 } else {
473 if (TTE_IS_NFO(env->dtlb[i].tte)) {
474 do_fault = 1;
475 sfsr |= SFSR_FT_NFO_BIT;
476 }
477 }
478
479 if (do_fault) {
480 /* faults above are reported with TT_DFAULT. */
481 env->exception_index = TT_DFAULT;
06e12b65 482 } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
d1afc48b 483 do_fault = 1;
b8e9fc06 484 env->exception_index = TT_DPROT;
6e8e7d4c 485
b8e9fc06
IK
486 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
487 " mmu_idx=%d tl=%d\n",
488 address, context, mmu_idx, env->tl);
d1afc48b
TS
489 }
490
491 if (!do_fault) {
b8e9fc06 492 *prot = PAGE_READ;
06e12b65 493 if (TTE_IS_W_OK(env->dtlb[i].tte)) {
b8e9fc06 494 *prot |= PAGE_WRITE;
06e12b65 495 }
b8e9fc06
IK
496
497 TTE_SET_USED(env->dtlb[i].tte);
498
499 return 0;
500 }
501
ccc76c24
TS
502 if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
503 sfsr |= SFSR_OW_BIT; /* overflow (not read before
504 another fault) */
505 }
6e8e7d4c 506
ccc76c24
TS
507 if (env->pstate & PS_PRIV) {
508 sfsr |= SFSR_PR_BIT;
509 }
6e8e7d4c 510
ccc76c24
TS
511 /* FIXME: ASI field in SFSR must be set */
512 env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
6e8e7d4c 513
b8e9fc06 514 env->dmmu.sfar = address; /* Fault address register */
9168b3a5
IK
515
516 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
517
b8e9fc06 518 return 1;
0f8a249a 519 }
3475187d 520 }
b8e9fc06
IK
521
522 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
523 address, context);
524
ccc76c24
TS
525 /*
526 * On MMU misses:
527 * - UltraSPARC IIi: SFSR and SFAR unmodified
528 * - JPS1: SFAR updated and some fields of SFSR updated
529 */
6e8e7d4c 530 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
83469015 531 env->exception_index = TT_DMISS;
3475187d
FB
532 return 1;
533}
534
77f193da 535static int get_physical_address_code(CPUState *env,
c227f099 536 target_phys_addr_t *physical, int *prot,
2065061e 537 target_ulong address, int mmu_idx)
3475187d 538{
3475187d 539 unsigned int i;
536ba015 540 uint64_t context;
3475187d 541
2065061e
IK
542 int is_user = (mmu_idx == MMU_USER_IDX ||
543 mmu_idx == MMU_USER_SECONDARY_IDX);
544
e8807b14
IK
545 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
546 /* IMMU disabled */
547 *physical = ultrasparc_truncate_physical(address);
0f8a249a 548 *prot = PAGE_EXEC;
3475187d
FB
549 return 0;
550 }
83469015 551
299b520c 552 if (env->tl == 0) {
2065061e 553 /* PRIMARY context */
299b520c
IK
554 context = env->dmmu.mmu_primary_context & 0x1fff;
555 } else {
2065061e 556 /* NUCLEUS context */
299b520c
IK
557 context = 0;
558 }
536ba015 559
3475187d 560 for (i = 0; i < 64; i++) {
afdf8109 561 // ctx match, vaddr match, valid?
6e8e7d4c 562 if (ultrasparc_tag_match(&env->itlb[i],
299b520c 563 address, context, physical)) {
afdf8109 564 // access ok?
06e12b65 565 if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
ccc76c24
TS
566 /* Fault status register */
567 if (env->immu.sfsr & SFSR_VALID_BIT) {
568 env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
569 another fault) */
570 } else {
571 env->immu.sfsr = 0;
572 }
573 if (env->pstate & PS_PRIV) {
574 env->immu.sfsr |= SFSR_PR_BIT;
575 }
576 if (env->tl > 0) {
577 env->immu.sfsr |= SFSR_CT_NUCLEUS;
578 }
579
580 /* FIXME: ASI field in SFSR must be set */
581 env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
0f8a249a 582 env->exception_index = TT_TFAULT;
b8e9fc06 583
9168b3a5
IK
584 env->immu.tag_access = (address & ~0x1fffULL) | context;
585
b8e9fc06
IK
586 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
587 address, context);
588
0f8a249a
BS
589 return 1;
590 }
0f8a249a 591 *prot = PAGE_EXEC;
f707726e 592 TTE_SET_USED(env->itlb[i].tte);
0f8a249a
BS
593 return 0;
594 }
3475187d 595 }
b8e9fc06
IK
596
597 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
598 address, context);
599
7ab463cb 600 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
6e8e7d4c 601 env->immu.tag_access = (address & ~0x1fffULL) | context;
83469015 602 env->exception_index = TT_TMISS;
3475187d
FB
603 return 1;
604}
605
c227f099 606static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
c48fcb47 607 int *prot, int *access_index,
d4c430a8
PB
608 target_ulong address, int rw, int mmu_idx,
609 target_ulong *page_size)
3475187d 610{
d4c430a8
PB
611 /* ??? We treat everything as a small page, then explicitly flush
612 everything when an entry is evicted. */
613 *page_size = TARGET_PAGE_SIZE;
9fd1ae3a
IK
614
615#if defined (DEBUG_MMU)
616 /* safety net to catch wrong softmmu index use from dynamic code */
617 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
618 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
619 " primary context=%" PRIx64
620 " secondary context=%" PRIx64
621 " address=%" PRIx64
622 "\n",
623 (rw == 2 ? "CODE" : "DATA"),
624 env->tl, mmu_idx,
625 env->dmmu.mmu_primary_context,
626 env->dmmu.mmu_secondary_context,
627 address);
628 }
629#endif
630
3475187d 631 if (rw == 2)
22548760 632 return get_physical_address_code(env, physical, prot, address,
2065061e 633 mmu_idx);
3475187d 634 else
22548760 635 return get_physical_address_data(env, physical, prot, address, rw,
2065061e 636 mmu_idx);
3475187d
FB
637}
638
639/* Perform address translation */
640int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
97b348e7 641 int mmu_idx)
3475187d 642{
83469015 643 target_ulong virt_addr, vaddr;
c227f099 644 target_phys_addr_t paddr;
d4c430a8
PB
645 target_ulong page_size;
646 int error_code = 0, prot, access_index;
3475187d 647
77f193da 648 error_code = get_physical_address(env, &paddr, &prot, &access_index,
d4c430a8 649 address, rw, mmu_idx, &page_size);
3475187d 650 if (error_code == 0) {
0f8a249a 651 virt_addr = address & TARGET_PAGE_MASK;
77f193da
BS
652 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
653 (TARGET_PAGE_SIZE - 1));
b8e9fc06
IK
654
655 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
656 " vaddr %" PRIx64
657 " mmu_idx=%d"
658 " tl=%d"
659 " primary context=%" PRIx64
660 " secondary context=%" PRIx64
661 "\n",
662 address, paddr, vaddr, mmu_idx, env->tl,
663 env->dmmu.mmu_primary_context,
664 env->dmmu.mmu_secondary_context);
665
d4c430a8
PB
666 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
667 return 0;
3475187d
FB
668 }
669 // XXX
670 return 1;
671}
672
d41160a3 673void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
83469015
FB
674{
675 unsigned int i;
676 const char *mask;
677
d41160a3
BS
678 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
679 PRId64 "\n",
680 env->dmmu.mmu_primary_context,
681 env->dmmu.mmu_secondary_context);
83469015 682 if ((env->lsu & DMMU_E) == 0) {
d41160a3 683 (*cpu_fprintf)(f, "DMMU disabled\n");
83469015 684 } else {
d41160a3 685 (*cpu_fprintf)(f, "DMMU dump\n");
0f8a249a 686 for (i = 0; i < 64; i++) {
06e12b65 687 switch (TTE_PGSIZE(env->dtlb[i].tte)) {
0f8a249a
BS
688 default:
689 case 0x0:
690 mask = " 8k";
691 break;
692 case 0x1:
693 mask = " 64k";
694 break;
695 case 0x2:
696 mask = "512k";
697 break;
698 case 0x3:
699 mask = " 4M";
700 break;
701 }
06e12b65 702 if (TTE_IS_VALID(env->dtlb[i].tte)) {
3b8b030a 703 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
d41160a3
BS
704 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
705 i,
706 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
06e12b65 707 TTE_PA(env->dtlb[i].tte),
d41160a3 708 mask,
06e12b65
TS
709 TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
710 TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
711 TTE_IS_LOCKED(env->dtlb[i].tte) ?
712 "locked" : "unlocked",
d41160a3
BS
713 env->dtlb[i].tag & (uint64_t)0x1fffULL,
714 TTE_IS_GLOBAL(env->dtlb[i].tte)?
715 "global" : "local");
0f8a249a
BS
716 }
717 }
83469015
FB
718 }
719 if ((env->lsu & IMMU_E) == 0) {
d41160a3 720 (*cpu_fprintf)(f, "IMMU disabled\n");
83469015 721 } else {
d41160a3 722 (*cpu_fprintf)(f, "IMMU dump\n");
0f8a249a 723 for (i = 0; i < 64; i++) {
06e12b65 724 switch (TTE_PGSIZE(env->itlb[i].tte)) {
0f8a249a
BS
725 default:
726 case 0x0:
727 mask = " 8k";
728 break;
729 case 0x1:
730 mask = " 64k";
731 break;
732 case 0x2:
733 mask = "512k";
734 break;
735 case 0x3:
736 mask = " 4M";
737 break;
738 }
06e12b65 739 if (TTE_IS_VALID(env->itlb[i].tte)) {
3b8b030a 740 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
d41160a3
BS
741 ", %s, %s, %s, ctx %" PRId64 " %s\n",
742 i,
743 env->itlb[i].tag & (uint64_t)~0x1fffULL,
06e12b65 744 TTE_PA(env->itlb[i].tte),
d41160a3 745 mask,
06e12b65
TS
746 TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
747 TTE_IS_LOCKED(env->itlb[i].tte) ?
748 "locked" : "unlocked",
d41160a3
BS
749 env->itlb[i].tag & (uint64_t)0x1fffULL,
750 TTE_IS_GLOBAL(env->itlb[i].tte)?
751 "global" : "local");
0f8a249a
BS
752 }
753 }
83469015
FB
754 }
755}
24741ef3
FB
756
757#endif /* TARGET_SPARC64 */
758#endif /* !CONFIG_USER_ONLY */
759
c48fcb47 760
4fcc562b 761#if !defined(CONFIG_USER_ONLY)
321365ab
TS
762static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
763 target_ulong addr, int rw, int mmu_idx)
764{
765 target_ulong page_size;
766 int prot, access_index;
767
768 return get_physical_address(env, phys, &prot, &access_index, addr, rw,
769 mmu_idx, &page_size);
770}
771
b64b6436 772#if defined(TARGET_SPARC64)
2065061e
IK
773target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
774 int mmu_idx)
c48fcb47 775{
c227f099 776 target_phys_addr_t phys_addr;
c48fcb47 777
d1afc48b 778 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) {
c48fcb47 779 return -1;
103dcbe5 780 }
c48fcb47
BS
781 return phys_addr;
782}
b64b6436 783#endif
2065061e
IK
784
785target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
786{
b64b6436
TS
787 target_phys_addr_t phys_addr;
788 int mmu_idx = cpu_mmu_index(env);
789
790 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
791 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
792 return -1;
793 }
794 }
795 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) {
796 return -1;
797 }
798 return phys_addr;
2065061e 799}
c48fcb47
BS
800#endif
801
e67768d0
BS
802#ifdef TARGET_SPARC64
803#ifdef DEBUG_PCALL
804static const char * const excp_names[0x80] = {
805 [TT_TFAULT] = "Instruction Access Fault",
806 [TT_TMISS] = "Instruction Access MMU Miss",
807 [TT_CODE_ACCESS] = "Instruction Access Error",
808 [TT_ILL_INSN] = "Illegal Instruction",
809 [TT_PRIV_INSN] = "Privileged Instruction",
810 [TT_NFPU_INSN] = "FPU Disabled",
811 [TT_FP_EXCP] = "FPU Exception",
812 [TT_TOVF] = "Tag Overflow",
813 [TT_CLRWIN] = "Clean Windows",
814 [TT_DIV_ZERO] = "Division By Zero",
815 [TT_DFAULT] = "Data Access Fault",
816 [TT_DMISS] = "Data Access MMU Miss",
817 [TT_DATA_ACCESS] = "Data Access Error",
818 [TT_DPROT] = "Data Protection Error",
819 [TT_UNALIGNED] = "Unaligned Memory Access",
820 [TT_PRIV_ACT] = "Privileged Action",
821 [TT_EXTINT | 0x1] = "External Interrupt 1",
822 [TT_EXTINT | 0x2] = "External Interrupt 2",
823 [TT_EXTINT | 0x3] = "External Interrupt 3",
824 [TT_EXTINT | 0x4] = "External Interrupt 4",
825 [TT_EXTINT | 0x5] = "External Interrupt 5",
826 [TT_EXTINT | 0x6] = "External Interrupt 6",
827 [TT_EXTINT | 0x7] = "External Interrupt 7",
828 [TT_EXTINT | 0x8] = "External Interrupt 8",
829 [TT_EXTINT | 0x9] = "External Interrupt 9",
830 [TT_EXTINT | 0xa] = "External Interrupt 10",
831 [TT_EXTINT | 0xb] = "External Interrupt 11",
832 [TT_EXTINT | 0xc] = "External Interrupt 12",
833 [TT_EXTINT | 0xd] = "External Interrupt 13",
834 [TT_EXTINT | 0xe] = "External Interrupt 14",
835 [TT_EXTINT | 0xf] = "External Interrupt 15",
836};
837#endif
838
839void do_interrupt(CPUState *env)
840{
841 int intno = env->exception_index;
842 trap_state *tsptr;
843
844#ifdef DEBUG_PCALL
845 if (qemu_loglevel_mask(CPU_LOG_INT)) {
846 static int count;
847 const char *name;
848
849 if (intno < 0 || intno >= 0x180) {
850 name = "Unknown";
851 } else if (intno >= 0x100) {
852 name = "Trap Instruction";
853 } else if (intno >= 0xc0) {
854 name = "Window Fill";
855 } else if (intno >= 0x80) {
856 name = "Window Spill";
857 } else {
858 name = excp_names[intno];
859 if (!name) {
860 name = "Unknown";
861 }
862 }
863
864 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
865 " SP=%016" PRIx64 "\n",
866 count, name, intno,
867 env->pc,
868 env->npc, env->regwptr[6]);
869 log_cpu_state(env, 0);
870#if 0
871 {
872 int i;
873 uint8_t *ptr;
874
875 qemu_log(" code=");
876 ptr = (uint8_t *)env->pc;
877 for (i = 0; i < 16; i++) {
878 qemu_log(" %02x", ldub(ptr + i));
879 }
880 qemu_log("\n");
881 }
882#endif
883 count++;
884 }
885#endif
886#if !defined(CONFIG_USER_ONLY)
887 if (env->tl >= env->maxtl) {
888 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
889 " Error state", env->exception_index, env->tl, env->maxtl);
890 return;
891 }
892#endif
893 if (env->tl < env->maxtl - 1) {
894 env->tl++;
895 } else {
896 env->pstate |= PS_RED;
897 if (env->tl < env->maxtl) {
898 env->tl++;
899 }
900 }
901 tsptr = cpu_tsptr(env);
902
903 tsptr->tstate = (cpu_get_ccr(env) << 32) |
904 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
905 cpu_get_cwp64(env);
906 tsptr->tpc = env->pc;
907 tsptr->tnpc = env->npc;
908 tsptr->tt = intno;
909
910 switch (intno) {
911 case TT_IVEC:
912 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
913 break;
914 case TT_TFAULT:
915 case TT_DFAULT:
916 case TT_TMISS ... TT_TMISS + 3:
917 case TT_DMISS ... TT_DMISS + 3:
918 case TT_DPROT ... TT_DPROT + 3:
919 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
920 break;
921 default:
922 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
923 break;
924 }
925
926 if (intno == TT_CLRWIN) {
927 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
928 } else if ((intno & 0x1c0) == TT_SPILL) {
929 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
930 } else if ((intno & 0x1c0) == TT_FILL) {
931 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
932 }
933 env->tbr &= ~0x7fffULL;
934 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
935 env->pc = env->tbr;
936 env->npc = env->pc + 4;
937 env->exception_index = -1;
938}
939#else
940#ifdef DEBUG_PCALL
941static const char * const excp_names[0x80] = {
942 [TT_TFAULT] = "Instruction Access Fault",
943 [TT_ILL_INSN] = "Illegal Instruction",
944 [TT_PRIV_INSN] = "Privileged Instruction",
945 [TT_NFPU_INSN] = "FPU Disabled",
946 [TT_WIN_OVF] = "Window Overflow",
947 [TT_WIN_UNF] = "Window Underflow",
948 [TT_UNALIGNED] = "Unaligned Memory Access",
949 [TT_FP_EXCP] = "FPU Exception",
950 [TT_DFAULT] = "Data Access Fault",
951 [TT_TOVF] = "Tag Overflow",
952 [TT_EXTINT | 0x1] = "External Interrupt 1",
953 [TT_EXTINT | 0x2] = "External Interrupt 2",
954 [TT_EXTINT | 0x3] = "External Interrupt 3",
955 [TT_EXTINT | 0x4] = "External Interrupt 4",
956 [TT_EXTINT | 0x5] = "External Interrupt 5",
957 [TT_EXTINT | 0x6] = "External Interrupt 6",
958 [TT_EXTINT | 0x7] = "External Interrupt 7",
959 [TT_EXTINT | 0x8] = "External Interrupt 8",
960 [TT_EXTINT | 0x9] = "External Interrupt 9",
961 [TT_EXTINT | 0xa] = "External Interrupt 10",
962 [TT_EXTINT | 0xb] = "External Interrupt 11",
963 [TT_EXTINT | 0xc] = "External Interrupt 12",
964 [TT_EXTINT | 0xd] = "External Interrupt 13",
965 [TT_EXTINT | 0xe] = "External Interrupt 14",
966 [TT_EXTINT | 0xf] = "External Interrupt 15",
967 [TT_TOVF] = "Tag Overflow",
968 [TT_CODE_ACCESS] = "Instruction Access Error",
969 [TT_DATA_ACCESS] = "Data Access Error",
970 [TT_DIV_ZERO] = "Division By Zero",
971 [TT_NCP_INSN] = "Coprocessor Disabled",
972};
973#endif
974
975void do_interrupt(CPUState *env)
976{
977 int cwp, intno = env->exception_index;
978
979#ifdef DEBUG_PCALL
980 if (qemu_loglevel_mask(CPU_LOG_INT)) {
981 static int count;
982 const char *name;
983
984 if (intno < 0 || intno >= 0x100) {
985 name = "Unknown";
986 } else if (intno >= 0x80) {
987 name = "Trap Instruction";
988 } else {
989 name = excp_names[intno];
990 if (!name) {
991 name = "Unknown";
992 }
993 }
994
995 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
996 count, name, intno,
997 env->pc,
998 env->npc, env->regwptr[6]);
999 log_cpu_state(env, 0);
1000#if 0
1001 {
1002 int i;
1003 uint8_t *ptr;
1004
1005 qemu_log(" code=");
1006 ptr = (uint8_t *)env->pc;
1007 for (i = 0; i < 16; i++) {
1008 qemu_log(" %02x", ldub(ptr + i));
1009 }
1010 qemu_log("\n");
1011 }
1012#endif
1013 count++;
1014 }
1015#endif
1016#if !defined(CONFIG_USER_ONLY)
1017 if (env->psret == 0) {
1018 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
1019 env->exception_index);
1020 return;
1021 }
1022#endif
1023 env->psret = 0;
1024 cwp = cpu_cwp_dec(env, env->cwp - 1);
1025 cpu_set_cwp(env, cwp);
1026 env->regwptr[9] = env->pc;
1027 env->regwptr[10] = env->npc;
1028 env->psrps = env->psrs;
1029 env->psrs = 1;
1030 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1031 env->pc = env->tbr;
1032 env->npc = env->pc + 4;
1033 env->exception_index = -1;
1034
1035#if !defined(CONFIG_USER_ONLY)
1036 /* IRQ acknowledgment */
1037 if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
1038 env->qemu_irq_ack(env->irq_manager, intno);
1039 }
1040#endif
1041}
1042#endif
1043
c48fcb47
BS
1044void cpu_reset(CPUSPARCState *env)
1045{
eca1bdf4
AL
1046 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1047 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1048 log_cpu_state(env, 0);
1049 }
1050
c48fcb47
BS
1051 tlb_flush(env, 1);
1052 env->cwp = 0;
5210977a 1053#ifndef TARGET_SPARC64
c48fcb47 1054 env->wim = 1;
5210977a 1055#endif
c48fcb47 1056 env->regwptr = env->regbase + (env->cwp * 16);
6b743278 1057 CC_OP = CC_OP_FLAGS;
c48fcb47 1058#if defined(CONFIG_USER_ONLY)
c48fcb47 1059#ifdef TARGET_SPARC64
1a14026e
BS
1060 env->cleanwin = env->nwindows - 2;
1061 env->cansave = env->nwindows - 2;
c48fcb47
BS
1062 env->pstate = PS_RMO | PS_PEF | PS_IE;
1063 env->asi = 0x82; // Primary no-fault
1064#endif
1065#else
5210977a 1066#if !defined(TARGET_SPARC64)
c48fcb47
BS
1067 env->psret = 0;
1068 env->psrs = 1;
1069 env->psrps = 1;
2aae2b8e 1070#endif
c48fcb47 1071#ifdef TARGET_SPARC64
8194f35a 1072 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
2aae2b8e 1073 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
8194f35a
IK
1074 env->tl = env->maxtl;
1075 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
415fc906 1076 env->lsu = 0;
c48fcb47 1077#else
c48fcb47 1078 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
5578ceab 1079 env->mmuregs[0] |= env->def->mmu_bm;
c48fcb47 1080#endif
e87231d4 1081 env->pc = 0;
c48fcb47
BS
1082 env->npc = env->pc + 4;
1083#endif
b04d9890 1084 env->cache_control = 0;
c48fcb47
BS
1085}
1086
64a88d5d 1087static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
c48fcb47 1088{
64a88d5d 1089 sparc_def_t def1, *def = &def1;
c48fcb47 1090
64a88d5d
BS
1091 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
1092 return -1;
c48fcb47 1093
7267c094 1094 env->def = g_malloc0(sizeof(*def));
5578ceab
BS
1095 memcpy(env->def, def, sizeof(*def));
1096#if defined(CONFIG_USER_ONLY)
1097 if ((env->def->features & CPU_FEATURE_FLOAT))
1098 env->def->features |= CPU_FEATURE_FLOAT128;
1099#endif
c48fcb47
BS
1100 env->cpu_model_str = cpu_model;
1101 env->version = def->iu_version;
1102 env->fsr = def->fpu_version;
1a14026e 1103 env->nwindows = def->nwindows;
c48fcb47 1104#if !defined(TARGET_SPARC64)
c48fcb47
BS
1105 env->mmuregs[0] |= def->mmu_version;
1106 cpu_sparc_set_id(env, 0);
963262de 1107 env->mxccregs[7] |= def->mxcc_version;
1a14026e 1108#else
fb79ceb9 1109 env->mmu_version = def->mmu_version;
c19148bd
BS
1110 env->maxtl = def->maxtl;
1111 env->version |= def->maxtl << 8;
1a14026e 1112 env->version |= def->nwindows - 1;
c48fcb47 1113#endif
64a88d5d
BS
1114 return 0;
1115}
1116
1117static void cpu_sparc_close(CPUSPARCState *env)
1118{
5578ceab 1119 free(env->def);
64a88d5d
BS
1120 free(env);
1121}
1122
1123CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1124{
1125 CPUSPARCState *env;
1126
7267c094 1127 env = g_malloc0(sizeof(CPUSPARCState));
64a88d5d 1128 cpu_exec_init(env);
c48fcb47
BS
1129
1130 gen_intermediate_code_init(env);
1131
64a88d5d
BS
1132 if (cpu_sparc_register(env, cpu_model) < 0) {
1133 cpu_sparc_close(env);
1134 return NULL;
1135 }
0bf46a40 1136 qemu_init_vcpu(env);
c48fcb47
BS
1137
1138 return env;
1139}
1140
1141void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
1142{
1143#if !defined(TARGET_SPARC64)
1144 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
1145#endif
1146}
1147
1148static const sparc_def_t sparc_defs[] = {
1149#ifdef TARGET_SPARC64
1150 {
1151 .name = "Fujitsu Sparc64",
c19148bd 1152 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
c48fcb47 1153 .fpu_version = 0x00000000,
fb79ceb9 1154 .mmu_version = mmu_us_12,
1a14026e 1155 .nwindows = 4,
c19148bd 1156 .maxtl = 4,
64a88d5d 1157 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1158 },
1159 {
1160 .name = "Fujitsu Sparc64 III",
c19148bd 1161 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
c48fcb47 1162 .fpu_version = 0x00000000,
fb79ceb9 1163 .mmu_version = mmu_us_12,
1a14026e 1164 .nwindows = 5,
c19148bd 1165 .maxtl = 4,
64a88d5d 1166 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1167 },
1168 {
1169 .name = "Fujitsu Sparc64 IV",
c19148bd 1170 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
c48fcb47 1171 .fpu_version = 0x00000000,
fb79ceb9 1172 .mmu_version = mmu_us_12,
1a14026e 1173 .nwindows = 8,
c19148bd 1174 .maxtl = 5,
64a88d5d 1175 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1176 },
1177 {
1178 .name = "Fujitsu Sparc64 V",
c19148bd 1179 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
c48fcb47 1180 .fpu_version = 0x00000000,
fb79ceb9 1181 .mmu_version = mmu_us_12,
1a14026e 1182 .nwindows = 8,
c19148bd 1183 .maxtl = 5,
64a88d5d 1184 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1185 },
1186 {
1187 .name = "TI UltraSparc I",
c19148bd 1188 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 1189 .fpu_version = 0x00000000,
fb79ceb9 1190 .mmu_version = mmu_us_12,
1a14026e 1191 .nwindows = 8,
c19148bd 1192 .maxtl = 5,
64a88d5d 1193 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1194 },
1195 {
1196 .name = "TI UltraSparc II",
c19148bd 1197 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
c48fcb47 1198 .fpu_version = 0x00000000,
fb79ceb9 1199 .mmu_version = mmu_us_12,
1a14026e 1200 .nwindows = 8,
c19148bd 1201 .maxtl = 5,
64a88d5d 1202 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1203 },
1204 {
1205 .name = "TI UltraSparc IIi",
c19148bd 1206 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
c48fcb47 1207 .fpu_version = 0x00000000,
fb79ceb9 1208 .mmu_version = mmu_us_12,
1a14026e 1209 .nwindows = 8,
c19148bd 1210 .maxtl = 5,
64a88d5d 1211 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1212 },
1213 {
1214 .name = "TI UltraSparc IIe",
c19148bd 1215 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
c48fcb47 1216 .fpu_version = 0x00000000,
fb79ceb9 1217 .mmu_version = mmu_us_12,
1a14026e 1218 .nwindows = 8,
c19148bd 1219 .maxtl = 5,
64a88d5d 1220 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1221 },
1222 {
1223 .name = "Sun UltraSparc III",
c19148bd 1224 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
c48fcb47 1225 .fpu_version = 0x00000000,
fb79ceb9 1226 .mmu_version = mmu_us_12,
1a14026e 1227 .nwindows = 8,
c19148bd 1228 .maxtl = 5,
64a88d5d 1229 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1230 },
1231 {
1232 .name = "Sun UltraSparc III Cu",
c19148bd 1233 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
c48fcb47 1234 .fpu_version = 0x00000000,
fb79ceb9 1235 .mmu_version = mmu_us_3,
1a14026e 1236 .nwindows = 8,
c19148bd 1237 .maxtl = 5,
64a88d5d 1238 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1239 },
1240 {
1241 .name = "Sun UltraSparc IIIi",
c19148bd 1242 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
c48fcb47 1243 .fpu_version = 0x00000000,
fb79ceb9 1244 .mmu_version = mmu_us_12,
1a14026e 1245 .nwindows = 8,
c19148bd 1246 .maxtl = 5,
64a88d5d 1247 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1248 },
1249 {
1250 .name = "Sun UltraSparc IV",
c19148bd 1251 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
c48fcb47 1252 .fpu_version = 0x00000000,
fb79ceb9 1253 .mmu_version = mmu_us_4,
1a14026e 1254 .nwindows = 8,
c19148bd 1255 .maxtl = 5,
64a88d5d 1256 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1257 },
1258 {
1259 .name = "Sun UltraSparc IV+",
c19148bd 1260 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
c48fcb47 1261 .fpu_version = 0x00000000,
fb79ceb9 1262 .mmu_version = mmu_us_12,
1a14026e 1263 .nwindows = 8,
c19148bd 1264 .maxtl = 5,
fb79ceb9 1265 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
c48fcb47
BS
1266 },
1267 {
1268 .name = "Sun UltraSparc IIIi+",
c19148bd 1269 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
c48fcb47 1270 .fpu_version = 0x00000000,
fb79ceb9 1271 .mmu_version = mmu_us_3,
1a14026e 1272 .nwindows = 8,
c19148bd 1273 .maxtl = 5,
64a88d5d 1274 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1275 },
c7ba218d
BS
1276 {
1277 .name = "Sun UltraSparc T1",
1278 // defined in sparc_ifu_fdp.v and ctu.h
c19148bd 1279 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
1280 .fpu_version = 0x00000000,
1281 .mmu_version = mmu_sun4v,
1282 .nwindows = 8,
c19148bd 1283 .maxtl = 6,
c7ba218d
BS
1284 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1285 | CPU_FEATURE_GL,
1286 },
1287 {
1288 .name = "Sun UltraSparc T2",
1289 // defined in tlu_asi_ctl.v and n2_revid_cust.v
c19148bd 1290 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
1291 .fpu_version = 0x00000000,
1292 .mmu_version = mmu_sun4v,
1293 .nwindows = 8,
c19148bd 1294 .maxtl = 6,
c7ba218d
BS
1295 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1296 | CPU_FEATURE_GL,
1297 },
c48fcb47
BS
1298 {
1299 .name = "NEC UltraSparc I",
c19148bd 1300 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 1301 .fpu_version = 0x00000000,
fb79ceb9 1302 .mmu_version = mmu_us_12,
1a14026e 1303 .nwindows = 8,
c19148bd 1304 .maxtl = 5,
64a88d5d 1305 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1306 },
1307#else
1308 {
1309 .name = "Fujitsu MB86900",
1310 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1311 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1312 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1313 .mmu_bm = 0x00004000,
1314 .mmu_ctpr_mask = 0x007ffff0,
1315 .mmu_cxr_mask = 0x0000003f,
1316 .mmu_sfsr_mask = 0xffffffff,
1317 .mmu_trcr_mask = 0xffffffff,
1a14026e 1318 .nwindows = 7,
e30b4678 1319 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
c48fcb47
BS
1320 },
1321 {
1322 .name = "Fujitsu MB86904",
1323 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1324 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1325 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1326 .mmu_bm = 0x00004000,
1327 .mmu_ctpr_mask = 0x00ffffc0,
1328 .mmu_cxr_mask = 0x000000ff,
1329 .mmu_sfsr_mask = 0x00016fff,
1330 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1331 .nwindows = 8,
64a88d5d 1332 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1333 },
1334 {
1335 .name = "Fujitsu MB86907",
1336 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1337 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1338 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1339 .mmu_bm = 0x00004000,
1340 .mmu_ctpr_mask = 0xffffffc0,
1341 .mmu_cxr_mask = 0x000000ff,
1342 .mmu_sfsr_mask = 0x00016fff,
1343 .mmu_trcr_mask = 0xffffffff,
1a14026e 1344 .nwindows = 8,
64a88d5d 1345 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1346 },
1347 {
1348 .name = "LSI L64811",
1349 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1350 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1351 .mmu_version = 0x10 << 24,
1352 .mmu_bm = 0x00004000,
1353 .mmu_ctpr_mask = 0x007ffff0,
1354 .mmu_cxr_mask = 0x0000003f,
1355 .mmu_sfsr_mask = 0xffffffff,
1356 .mmu_trcr_mask = 0xffffffff,
1a14026e 1357 .nwindows = 8,
e30b4678
BS
1358 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1359 CPU_FEATURE_FSMULD,
c48fcb47
BS
1360 },
1361 {
1362 .name = "Cypress CY7C601",
1363 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1364 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1365 .mmu_version = 0x10 << 24,
1366 .mmu_bm = 0x00004000,
1367 .mmu_ctpr_mask = 0x007ffff0,
1368 .mmu_cxr_mask = 0x0000003f,
1369 .mmu_sfsr_mask = 0xffffffff,
1370 .mmu_trcr_mask = 0xffffffff,
1a14026e 1371 .nwindows = 8,
e30b4678
BS
1372 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1373 CPU_FEATURE_FSMULD,
c48fcb47
BS
1374 },
1375 {
1376 .name = "Cypress CY7C611",
1377 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1378 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1379 .mmu_version = 0x10 << 24,
1380 .mmu_bm = 0x00004000,
1381 .mmu_ctpr_mask = 0x007ffff0,
1382 .mmu_cxr_mask = 0x0000003f,
1383 .mmu_sfsr_mask = 0xffffffff,
1384 .mmu_trcr_mask = 0xffffffff,
1a14026e 1385 .nwindows = 8,
e30b4678
BS
1386 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1387 CPU_FEATURE_FSMULD,
c48fcb47 1388 },
c48fcb47
BS
1389 {
1390 .name = "TI MicroSparc I",
1391 .iu_version = 0x41000000,
1392 .fpu_version = 4 << 17,
1393 .mmu_version = 0x41000000,
1394 .mmu_bm = 0x00004000,
1395 .mmu_ctpr_mask = 0x007ffff0,
1396 .mmu_cxr_mask = 0x0000003f,
1397 .mmu_sfsr_mask = 0x00016fff,
1398 .mmu_trcr_mask = 0x0000003f,
1a14026e 1399 .nwindows = 7,
e30b4678
BS
1400 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1401 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1402 CPU_FEATURE_FMUL,
c48fcb47
BS
1403 },
1404 {
1405 .name = "TI MicroSparc II",
1406 .iu_version = 0x42000000,
1407 .fpu_version = 4 << 17,
1408 .mmu_version = 0x02000000,
1409 .mmu_bm = 0x00004000,
1410 .mmu_ctpr_mask = 0x00ffffc0,
1411 .mmu_cxr_mask = 0x000000ff,
1412 .mmu_sfsr_mask = 0x00016fff,
1413 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1414 .nwindows = 8,
64a88d5d 1415 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1416 },
1417 {
1418 .name = "TI MicroSparc IIep",
1419 .iu_version = 0x42000000,
1420 .fpu_version = 4 << 17,
1421 .mmu_version = 0x04000000,
1422 .mmu_bm = 0x00004000,
1423 .mmu_ctpr_mask = 0x00ffffc0,
1424 .mmu_cxr_mask = 0x000000ff,
1425 .mmu_sfsr_mask = 0x00016bff,
1426 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1427 .nwindows = 8,
64a88d5d 1428 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1429 },
b5154bde
BS
1430 {
1431 .name = "TI SuperSparc 40", // STP1020NPGA
963262de 1432 .iu_version = 0x41000000, // SuperSPARC 2.x
b5154bde 1433 .fpu_version = 0 << 17,
963262de 1434 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
b5154bde
BS
1435 .mmu_bm = 0x00002000,
1436 .mmu_ctpr_mask = 0xffffffc0,
1437 .mmu_cxr_mask = 0x0000ffff,
1438 .mmu_sfsr_mask = 0xffffffff,
1439 .mmu_trcr_mask = 0xffffffff,
1a14026e 1440 .nwindows = 8,
b5154bde
BS
1441 .features = CPU_DEFAULT_FEATURES,
1442 },
1443 {
1444 .name = "TI SuperSparc 50", // STP1020PGA
963262de 1445 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1446 .fpu_version = 0 << 17,
963262de 1447 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1448 .mmu_bm = 0x00002000,
1449 .mmu_ctpr_mask = 0xffffffc0,
1450 .mmu_cxr_mask = 0x0000ffff,
1451 .mmu_sfsr_mask = 0xffffffff,
1452 .mmu_trcr_mask = 0xffffffff,
1a14026e 1453 .nwindows = 8,
b5154bde
BS
1454 .features = CPU_DEFAULT_FEATURES,
1455 },
c48fcb47
BS
1456 {
1457 .name = "TI SuperSparc 51",
963262de 1458 .iu_version = 0x40000000, // SuperSPARC 3.x
c48fcb47 1459 .fpu_version = 0 << 17,
963262de 1460 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
c48fcb47
BS
1461 .mmu_bm = 0x00002000,
1462 .mmu_ctpr_mask = 0xffffffc0,
1463 .mmu_cxr_mask = 0x0000ffff,
1464 .mmu_sfsr_mask = 0xffffffff,
1465 .mmu_trcr_mask = 0xffffffff,
963262de 1466 .mxcc_version = 0x00000104,
1a14026e 1467 .nwindows = 8,
64a88d5d 1468 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1469 },
b5154bde
BS
1470 {
1471 .name = "TI SuperSparc 60", // STP1020APGA
963262de 1472 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1473 .fpu_version = 0 << 17,
963262de 1474 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1475 .mmu_bm = 0x00002000,
1476 .mmu_ctpr_mask = 0xffffffc0,
1477 .mmu_cxr_mask = 0x0000ffff,
1478 .mmu_sfsr_mask = 0xffffffff,
1479 .mmu_trcr_mask = 0xffffffff,
1a14026e 1480 .nwindows = 8,
b5154bde
BS
1481 .features = CPU_DEFAULT_FEATURES,
1482 },
c48fcb47
BS
1483 {
1484 .name = "TI SuperSparc 61",
963262de 1485 .iu_version = 0x44000000, // SuperSPARC 3.x
c48fcb47 1486 .fpu_version = 0 << 17,
963262de
BS
1487 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1488 .mmu_bm = 0x00002000,
1489 .mmu_ctpr_mask = 0xffffffc0,
1490 .mmu_cxr_mask = 0x0000ffff,
1491 .mmu_sfsr_mask = 0xffffffff,
1492 .mmu_trcr_mask = 0xffffffff,
1493 .mxcc_version = 0x00000104,
1494 .nwindows = 8,
1495 .features = CPU_DEFAULT_FEATURES,
1496 },
1497 {
1498 .name = "TI SuperSparc II",
1499 .iu_version = 0x40000000, // SuperSPARC II 1.x
1500 .fpu_version = 0 << 17,
1501 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
c48fcb47
BS
1502 .mmu_bm = 0x00002000,
1503 .mmu_ctpr_mask = 0xffffffc0,
1504 .mmu_cxr_mask = 0x0000ffff,
1505 .mmu_sfsr_mask = 0xffffffff,
1506 .mmu_trcr_mask = 0xffffffff,
963262de 1507 .mxcc_version = 0x00000104,
1a14026e 1508 .nwindows = 8,
64a88d5d 1509 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1510 },
1511 {
1512 .name = "Ross RT625",
1513 .iu_version = 0x1e000000,
1514 .fpu_version = 1 << 17,
1515 .mmu_version = 0x1e000000,
1516 .mmu_bm = 0x00004000,
1517 .mmu_ctpr_mask = 0x007ffff0,
1518 .mmu_cxr_mask = 0x0000003f,
1519 .mmu_sfsr_mask = 0xffffffff,
1520 .mmu_trcr_mask = 0xffffffff,
1a14026e 1521 .nwindows = 8,
64a88d5d 1522 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1523 },
1524 {
1525 .name = "Ross RT620",
1526 .iu_version = 0x1f000000,
1527 .fpu_version = 1 << 17,
1528 .mmu_version = 0x1f000000,
1529 .mmu_bm = 0x00004000,
1530 .mmu_ctpr_mask = 0x007ffff0,
1531 .mmu_cxr_mask = 0x0000003f,
1532 .mmu_sfsr_mask = 0xffffffff,
1533 .mmu_trcr_mask = 0xffffffff,
1a14026e 1534 .nwindows = 8,
64a88d5d 1535 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1536 },
1537 {
1538 .name = "BIT B5010",
1539 .iu_version = 0x20000000,
1540 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1541 .mmu_version = 0x20000000,
1542 .mmu_bm = 0x00004000,
1543 .mmu_ctpr_mask = 0x007ffff0,
1544 .mmu_cxr_mask = 0x0000003f,
1545 .mmu_sfsr_mask = 0xffffffff,
1546 .mmu_trcr_mask = 0xffffffff,
1a14026e 1547 .nwindows = 8,
e30b4678
BS
1548 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1549 CPU_FEATURE_FSMULD,
c48fcb47
BS
1550 },
1551 {
1552 .name = "Matsushita MN10501",
1553 .iu_version = 0x50000000,
1554 .fpu_version = 0 << 17,
1555 .mmu_version = 0x50000000,
1556 .mmu_bm = 0x00004000,
1557 .mmu_ctpr_mask = 0x007ffff0,
1558 .mmu_cxr_mask = 0x0000003f,
1559 .mmu_sfsr_mask = 0xffffffff,
1560 .mmu_trcr_mask = 0xffffffff,
1a14026e 1561 .nwindows = 8,
e30b4678
BS
1562 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1563 CPU_FEATURE_FSMULD,
c48fcb47
BS
1564 },
1565 {
1566 .name = "Weitek W8601",
1567 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1568 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1569 .mmu_version = 0x10 << 24,
1570 .mmu_bm = 0x00004000,
1571 .mmu_ctpr_mask = 0x007ffff0,
1572 .mmu_cxr_mask = 0x0000003f,
1573 .mmu_sfsr_mask = 0xffffffff,
1574 .mmu_trcr_mask = 0xffffffff,
1a14026e 1575 .nwindows = 8,
64a88d5d 1576 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1577 },
1578 {
1579 .name = "LEON2",
1580 .iu_version = 0xf2000000,
1581 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1582 .mmu_version = 0xf2000000,
1583 .mmu_bm = 0x00004000,
1584 .mmu_ctpr_mask = 0x007ffff0,
1585 .mmu_cxr_mask = 0x0000003f,
1586 .mmu_sfsr_mask = 0xffffffff,
1587 .mmu_trcr_mask = 0xffffffff,
1a14026e 1588 .nwindows = 8,
b04d9890 1589 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
c48fcb47
BS
1590 },
1591 {
1592 .name = "LEON3",
1593 .iu_version = 0xf3000000,
1594 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1595 .mmu_version = 0xf3000000,
b04d9890 1596 .mmu_bm = 0x00000000,
c48fcb47
BS
1597 .mmu_ctpr_mask = 0x007ffff0,
1598 .mmu_cxr_mask = 0x0000003f,
1599 .mmu_sfsr_mask = 0xffffffff,
1600 .mmu_trcr_mask = 0xffffffff,
1a14026e 1601 .nwindows = 8,
4a2ba232 1602 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
60f356e8 1603 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
c48fcb47
BS
1604 },
1605#endif
1606};
1607
64a88d5d
BS
1608static const char * const feature_name[] = {
1609 "float",
1610 "float128",
1611 "swap",
1612 "mul",
1613 "div",
1614 "flush",
1615 "fsqrt",
1616 "fmul",
1617 "vis1",
1618 "vis2",
e30b4678 1619 "fsmuld",
fb79ceb9
BS
1620 "hypv",
1621 "cmt",
1622 "gl",
64a88d5d
BS
1623};
1624
9a78eead 1625static void print_features(FILE *f, fprintf_function cpu_fprintf,
64a88d5d 1626 uint32_t features, const char *prefix)
c48fcb47
BS
1627{
1628 unsigned int i;
1629
64a88d5d
BS
1630 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1631 if (feature_name[i] && (features & (1 << i))) {
1632 if (prefix)
1633 (*cpu_fprintf)(f, "%s", prefix);
1634 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1635 }
1636}
1637
1638static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1639{
1640 unsigned int i;
1641
1642 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1643 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1644 *features |= 1 << i;
1645 return;
1646 }
1647 fprintf(stderr, "CPU feature %s not found\n", flagname);
1648}
1649
22548760 1650static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
64a88d5d
BS
1651{
1652 unsigned int i;
1653 const sparc_def_t *def = NULL;
1654 char *s = strdup(cpu_model);
1655 char *featurestr, *name = strtok(s, ",");
1656 uint32_t plus_features = 0;
1657 uint32_t minus_features = 0;
0bfcd599 1658 uint64_t iu_version;
1a14026e 1659 uint32_t fpu_version, mmu_version, nwindows;
64a88d5d 1660
b1503cda 1661 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
c48fcb47 1662 if (strcasecmp(name, sparc_defs[i].name) == 0) {
64a88d5d 1663 def = &sparc_defs[i];
c48fcb47
BS
1664 }
1665 }
64a88d5d
BS
1666 if (!def)
1667 goto error;
1668 memcpy(cpu_def, def, sizeof(*def));
1669
1670 featurestr = strtok(NULL, ",");
1671 while (featurestr) {
1672 char *val;
1673
1674 if (featurestr[0] == '+') {
1675 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1676 } else if (featurestr[0] == '-') {
1677 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1678 } else if ((val = strchr(featurestr, '='))) {
1679 *val = 0; val++;
1680 if (!strcmp(featurestr, "iu_version")) {
1681 char *err;
1682
1683 iu_version = strtoll(val, &err, 0);
1684 if (!*val || *err) {
1685 fprintf(stderr, "bad numerical value %s\n", val);
1686 goto error;
1687 }
1688 cpu_def->iu_version = iu_version;
1689#ifdef DEBUG_FEATURES
0bfcd599 1690 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
64a88d5d
BS
1691#endif
1692 } else if (!strcmp(featurestr, "fpu_version")) {
1693 char *err;
1694
1695 fpu_version = strtol(val, &err, 0);
1696 if (!*val || *err) {
1697 fprintf(stderr, "bad numerical value %s\n", val);
1698 goto error;
1699 }
1700 cpu_def->fpu_version = fpu_version;
1701#ifdef DEBUG_FEATURES
0bf9e31a 1702 fprintf(stderr, "fpu_version %x\n", fpu_version);
64a88d5d
BS
1703#endif
1704 } else if (!strcmp(featurestr, "mmu_version")) {
1705 char *err;
1706
1707 mmu_version = strtol(val, &err, 0);
1708 if (!*val || *err) {
1709 fprintf(stderr, "bad numerical value %s\n", val);
1710 goto error;
1711 }
1712 cpu_def->mmu_version = mmu_version;
1713#ifdef DEBUG_FEATURES
0bf9e31a 1714 fprintf(stderr, "mmu_version %x\n", mmu_version);
1a14026e
BS
1715#endif
1716 } else if (!strcmp(featurestr, "nwindows")) {
1717 char *err;
1718
1719 nwindows = strtol(val, &err, 0);
1720 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1721 nwindows < MIN_NWINDOWS) {
1722 fprintf(stderr, "bad numerical value %s\n", val);
1723 goto error;
1724 }
1725 cpu_def->nwindows = nwindows;
1726#ifdef DEBUG_FEATURES
1727 fprintf(stderr, "nwindows %d\n", nwindows);
64a88d5d
BS
1728#endif
1729 } else {
1730 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1731 goto error;
1732 }
1733 } else {
77f193da
BS
1734 fprintf(stderr, "feature string `%s' not in format "
1735 "(+feature|-feature|feature=xyz)\n", featurestr);
64a88d5d
BS
1736 goto error;
1737 }
1738 featurestr = strtok(NULL, ",");
1739 }
1740 cpu_def->features |= plus_features;
1741 cpu_def->features &= ~minus_features;
1742#ifdef DEBUG_FEATURES
1743 print_features(stderr, fprintf, cpu_def->features, NULL);
1744#endif
1745 free(s);
1746 return 0;
1747
1748 error:
1749 free(s);
1750 return -1;
c48fcb47
BS
1751}
1752
9a78eead 1753void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
c48fcb47
BS
1754{
1755 unsigned int i;
1756
b1503cda 1757 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1a14026e 1758 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
c48fcb47
BS
1759 sparc_defs[i].name,
1760 sparc_defs[i].iu_version,
1761 sparc_defs[i].fpu_version,
1a14026e
BS
1762 sparc_defs[i].mmu_version,
1763 sparc_defs[i].nwindows);
77f193da
BS
1764 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1765 ~sparc_defs[i].features, "-");
1766 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1767 sparc_defs[i].features, "+");
64a88d5d 1768 (*cpu_fprintf)(f, "\n");
c48fcb47 1769 }
f76981b1
BS
1770 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1771 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
64a88d5d 1772 (*cpu_fprintf)(f, "\n");
f76981b1
BS
1773 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1774 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1775 (*cpu_fprintf)(f, "\n");
1776 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1777 "fpu_version mmu_version nwindows\n");
c48fcb47
BS
1778}
1779
9a78eead 1780static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
43bb98bf
BS
1781 uint32_t cc)
1782{
1783 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1784 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1785 cc & PSR_CARRY? 'C' : '-');
1786}
1787
1788#ifdef TARGET_SPARC64
1789#define REGS_PER_LINE 4
1790#else
1791#define REGS_PER_LINE 8
1792#endif
1793
9a78eead 1794void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
c48fcb47
BS
1795 int flags)
1796{
1797 int i, x;
1798
77f193da
BS
1799 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1800 env->npc);
c48fcb47 1801 cpu_fprintf(f, "General Registers:\n");
43bb98bf
BS
1802
1803 for (i = 0; i < 8; i++) {
1804 if (i % REGS_PER_LINE == 0) {
1805 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1806 }
1807 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1808 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1809 cpu_fprintf(f, "\n");
1810 }
1811 }
c48fcb47
BS
1812 cpu_fprintf(f, "\nCurrent Register Window:\n");
1813 for (x = 0; x < 3; x++) {
43bb98bf
BS
1814 for (i = 0; i < 8; i++) {
1815 if (i % REGS_PER_LINE == 0) {
1816 cpu_fprintf(f, "%%%c%d-%d: ",
1817 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1818 i, i + REGS_PER_LINE - 1);
1819 }
1820 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1821 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1822 cpu_fprintf(f, "\n");
1823 }
1824 }
c48fcb47
BS
1825 }
1826 cpu_fprintf(f, "\nFloating Point Registers:\n");
43bb98bf 1827 for (i = 0; i < TARGET_FPREGS; i++) {
c48fcb47
BS
1828 if ((i & 3) == 0)
1829 cpu_fprintf(f, "%%f%02d:", i);
a37ee56c 1830 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
c48fcb47
BS
1831 if ((i & 3) == 3)
1832 cpu_fprintf(f, "\n");
1833 }
1834#ifdef TARGET_SPARC64
43bb98bf 1835 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
113c6106 1836 (unsigned)cpu_get_ccr(env));
5a834bb4 1837 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
43bb98bf 1838 cpu_fprintf(f, " xcc: ");
5a834bb4 1839 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
43bb98bf
BS
1840 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1841 env->psrpil);
1842 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1843 "cleanwin: %d cwp: %d\n",
c48fcb47 1844 env->cansave, env->canrestore, env->otherwin, env->wstate,
1a14026e 1845 env->cleanwin, env->nwindows - 1 - env->cwp);
43bb98bf
BS
1846 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1847 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
c48fcb47 1848#else
5a834bb4
BS
1849 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1850 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
43bb98bf
BS
1851 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1852 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1853 env->wim);
1854 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1855 env->fsr, env->y);
c48fcb47 1856#endif
c48fcb47 1857}