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