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