]> git.proxmox.com Git - qemu.git/blame - target-sparc/helper.c
Update version and changelog for release
[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,
2a90358f
BS
391 target_phys_addr_t *physical,
392 int is_nucleus)
536ba015
IK
393{
394 uint64_t mask;
395
6e8e7d4c 396 switch ((tlb->tte >> 61) & 3) {
536ba015
IK
397 default:
398 case 0x0: // 8k
399 mask = 0xffffffffffffe000ULL;
400 break;
401 case 0x1: // 64k
402 mask = 0xffffffffffff0000ULL;
403 break;
404 case 0x2: // 512k
405 mask = 0xfffffffffff80000ULL;
406 break;
407 case 0x3: // 4M
408 mask = 0xffffffffffc00000ULL;
409 break;
410 }
411
412 // valid, context match, virtual address match?
f707726e 413 if (TTE_IS_VALID(tlb->tte) &&
2a90358f
BS
414 ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
415 || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
416 && compare_masked(address, tlb->tag, mask))
536ba015
IK
417 {
418 // decode physical address
6e8e7d4c 419 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
536ba015
IK
420 return 1;
421 }
422
423 return 0;
424}
425
77f193da 426static int get_physical_address_data(CPUState *env,
c227f099 427 target_phys_addr_t *physical, int *prot,
22548760 428 target_ulong address, int rw, int is_user)
3475187d 429{
3475187d 430 unsigned int i;
536ba015 431 uint64_t context;
2a90358f 432 int is_nucleus;
3475187d
FB
433
434 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
e8807b14 435 *physical = ultrasparc_truncate_physical(address);
0f8a249a 436 *prot = PAGE_READ | PAGE_WRITE;
3475187d
FB
437 return 0;
438 }
439
6e8e7d4c 440 context = env->dmmu.mmu_primary_context & 0x1fff;
2a90358f 441 is_nucleus = env->tl > 0;
536ba015 442
3475187d 443 for (i = 0; i < 64; i++) {
afdf8109 444 // ctx match, vaddr match, valid?
6e8e7d4c 445 if (ultrasparc_tag_match(&env->dtlb[i],
2a90358f
BS
446 address, context, physical,
447 is_nucleus)) {
afdf8109 448 // access ok?
6e8e7d4c
IK
449 if (((env->dtlb[i].tte & 0x4) && is_user) ||
450 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
451 uint8_t fault_type = 0;
452
453 if ((env->dtlb[i].tte & 0x4) && is_user) {
454 fault_type |= 1; /* privilege violation */
455 }
456
457 if (env->dmmu.sfsr & 1) /* Fault status register */
458 env->dmmu.sfsr = 2; /* overflow (not read before
77f193da 459 another fault) */
6e8e7d4c
IK
460
461 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
462
463 env->dmmu.sfsr |= (fault_type << 7);
464
465 env->dmmu.sfar = address; /* Fault address register */
0f8a249a 466 env->exception_index = TT_DFAULT;
83469015 467#ifdef DEBUG_MMU
0f8a249a 468 printf("DFAULT at 0x%" PRIx64 "\n", address);
83469015 469#endif
0f8a249a
BS
470 return 1;
471 }
0f8a249a 472 *prot = PAGE_READ;
6e8e7d4c 473 if (env->dtlb[i].tte & 0x2)
0f8a249a 474 *prot |= PAGE_WRITE;
f707726e 475 TTE_SET_USED(env->dtlb[i].tte);
0f8a249a
BS
476 return 0;
477 }
3475187d 478 }
83469015 479#ifdef DEBUG_MMU
26a76461 480 printf("DMISS at 0x%" PRIx64 "\n", address);
83469015 481#endif
6e8e7d4c 482 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
83469015 483 env->exception_index = TT_DMISS;
3475187d
FB
484 return 1;
485}
486
77f193da 487static int get_physical_address_code(CPUState *env,
c227f099 488 target_phys_addr_t *physical, int *prot,
22548760 489 target_ulong address, int is_user)
3475187d 490{
3475187d 491 unsigned int i;
536ba015 492 uint64_t context;
2a90358f 493 int is_nucleus;
3475187d 494
e8807b14
IK
495 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
496 /* IMMU disabled */
497 *physical = ultrasparc_truncate_physical(address);
0f8a249a 498 *prot = PAGE_EXEC;
3475187d
FB
499 return 0;
500 }
83469015 501
6e8e7d4c 502 context = env->dmmu.mmu_primary_context & 0x1fff;
2a90358f 503 is_nucleus = env->tl > 0;
536ba015 504
3475187d 505 for (i = 0; i < 64; i++) {
afdf8109 506 // ctx match, vaddr match, valid?
6e8e7d4c 507 if (ultrasparc_tag_match(&env->itlb[i],
2a90358f
BS
508 address, context, physical,
509 is_nucleus)) {
afdf8109 510 // access ok?
6e8e7d4c
IK
511 if ((env->itlb[i].tte & 0x4) && is_user) {
512 if (env->immu.sfsr) /* Fault status register */
513 env->immu.sfsr = 2; /* overflow (not read before
77f193da 514 another fault) */
6e8e7d4c 515 env->immu.sfsr |= (is_user << 3) | 1;
0f8a249a 516 env->exception_index = TT_TFAULT;
83469015 517#ifdef DEBUG_MMU
0f8a249a 518 printf("TFAULT at 0x%" PRIx64 "\n", address);
83469015 519#endif
0f8a249a
BS
520 return 1;
521 }
0f8a249a 522 *prot = PAGE_EXEC;
f707726e 523 TTE_SET_USED(env->itlb[i].tte);
0f8a249a
BS
524 return 0;
525 }
3475187d 526 }
83469015 527#ifdef DEBUG_MMU
26a76461 528 printf("TMISS at 0x%" PRIx64 "\n", address);
83469015 529#endif
7ab463cb 530 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
6e8e7d4c 531 env->immu.tag_access = (address & ~0x1fffULL) | context;
83469015 532 env->exception_index = TT_TMISS;
3475187d
FB
533 return 1;
534}
535
c227f099 536static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
c48fcb47
BS
537 int *prot, int *access_index,
538 target_ulong address, int rw, int mmu_idx)
3475187d 539{
6ebbf390
JM
540 int is_user = mmu_idx == MMU_USER_IDX;
541
3475187d 542 if (rw == 2)
22548760
BS
543 return get_physical_address_code(env, physical, prot, address,
544 is_user);
3475187d 545 else
22548760
BS
546 return get_physical_address_data(env, physical, prot, address, rw,
547 is_user);
3475187d
FB
548}
549
550/* Perform address translation */
551int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 552 int mmu_idx, int is_softmmu)
3475187d 553{
83469015 554 target_ulong virt_addr, vaddr;
c227f099 555 target_phys_addr_t paddr;
3475187d
FB
556 int error_code = 0, prot, ret = 0, access_index;
557
77f193da
BS
558 error_code = get_physical_address(env, &paddr, &prot, &access_index,
559 address, rw, mmu_idx);
3475187d 560 if (error_code == 0) {
0f8a249a 561 virt_addr = address & TARGET_PAGE_MASK;
77f193da
BS
562 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
563 (TARGET_PAGE_SIZE - 1));
83469015 564#ifdef DEBUG_MMU
77f193da
BS
565 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
566 "\n", address, paddr, vaddr);
83469015 567#endif
6ebbf390 568 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
0f8a249a 569 return ret;
3475187d
FB
570 }
571 // XXX
572 return 1;
573}
574
83469015
FB
575#ifdef DEBUG_MMU
576void dump_mmu(CPUState *env)
577{
578 unsigned int i;
579 const char *mask;
580
77f193da 581 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
6e8e7d4c 582 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
83469015 583 if ((env->lsu & DMMU_E) == 0) {
0f8a249a 584 printf("DMMU disabled\n");
83469015 585 } else {
0f8a249a
BS
586 printf("DMMU dump:\n");
587 for (i = 0; i < 64; i++) {
31a68d57 588 switch ((env->dtlb[i].tte >> 61) & 3) {
0f8a249a
BS
589 default:
590 case 0x0:
591 mask = " 8k";
592 break;
593 case 0x1:
594 mask = " 64k";
595 break;
596 case 0x2:
597 mask = "512k";
598 break;
599 case 0x3:
600 mask = " 4M";
601 break;
602 }
31a68d57
BS
603 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
604 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
2a90358f 605 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
6e8e7d4c 606 i,
31a68d57
BS
607 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
608 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
0f8a249a 609 mask,
31a68d57
BS
610 env->dtlb[i].tte & 0x4? "priv": "user",
611 env->dtlb[i].tte & 0x2? "RW": "RO",
612 env->dtlb[i].tte & 0x40? "locked": "unlocked",
2a90358f
BS
613 env->dtlb[i].tag & (uint64_t)0x1fffULL,
614 TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
0f8a249a
BS
615 }
616 }
83469015
FB
617 }
618 if ((env->lsu & IMMU_E) == 0) {
0f8a249a 619 printf("IMMU disabled\n");
83469015 620 } else {
0f8a249a
BS
621 printf("IMMU dump:\n");
622 for (i = 0; i < 64; i++) {
31a68d57 623 switch ((env->itlb[i].tte >> 61) & 3) {
0f8a249a
BS
624 default:
625 case 0x0:
626 mask = " 8k";
627 break;
628 case 0x1:
629 mask = " 64k";
630 break;
631 case 0x2:
632 mask = "512k";
633 break;
634 case 0x3:
635 mask = " 4M";
636 break;
637 }
31a68d57
BS
638 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
639 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
2a90358f 640 ", %s, %s, %s, ctx %" PRId64 " %s\n",
6e8e7d4c
IK
641 i,
642 env->itlb[i].tag & (uint64_t)~0x1fffULL,
31a68d57 643 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
0f8a249a 644 mask,
31a68d57
BS
645 env->itlb[i].tte & 0x4? "priv": "user",
646 env->itlb[i].tte & 0x40? "locked": "unlocked",
2a90358f
BS
647 env->itlb[i].tag & (uint64_t)0x1fffULL,
648 TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
0f8a249a
BS
649 }
650 }
83469015
FB
651 }
652}
24741ef3
FB
653#endif /* DEBUG_MMU */
654
655#endif /* TARGET_SPARC64 */
656#endif /* !CONFIG_USER_ONLY */
657
c48fcb47
BS
658
659#if defined(CONFIG_USER_ONLY)
c227f099 660target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
c48fcb47
BS
661{
662 return addr;
663}
664
665#else
c227f099 666target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
c48fcb47 667{
c227f099 668 target_phys_addr_t phys_addr;
c48fcb47
BS
669 int prot, access_index;
670
671 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
672 MMU_KERNEL_IDX) != 0)
673 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
674 0, MMU_KERNEL_IDX) != 0)
675 return -1;
676 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
677 return -1;
678 return phys_addr;
679}
680#endif
681
c48fcb47
BS
682void cpu_reset(CPUSPARCState *env)
683{
eca1bdf4
AL
684 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
685 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
686 log_cpu_state(env, 0);
687 }
688
c48fcb47
BS
689 tlb_flush(env, 1);
690 env->cwp = 0;
5210977a 691#ifndef TARGET_SPARC64
c48fcb47 692 env->wim = 1;
5210977a 693#endif
c48fcb47 694 env->regwptr = env->regbase + (env->cwp * 16);
6b743278 695 CC_OP = CC_OP_FLAGS;
c48fcb47 696#if defined(CONFIG_USER_ONLY)
c48fcb47 697#ifdef TARGET_SPARC64
1a14026e
BS
698 env->cleanwin = env->nwindows - 2;
699 env->cansave = env->nwindows - 2;
c48fcb47
BS
700 env->pstate = PS_RMO | PS_PEF | PS_IE;
701 env->asi = 0x82; // Primary no-fault
702#endif
703#else
5210977a 704#if !defined(TARGET_SPARC64)
c48fcb47 705 env->psret = 0;
5210977a 706#endif
c48fcb47
BS
707 env->psrs = 1;
708 env->psrps = 1;
709#ifdef TARGET_SPARC64
8194f35a 710 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
c48fcb47 711 env->hpstate = HS_PRIV;
8194f35a
IK
712 env->tl = env->maxtl;
713 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
415fc906 714 env->lsu = 0;
c48fcb47 715#else
c48fcb47 716 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
5578ceab 717 env->mmuregs[0] |= env->def->mmu_bm;
c48fcb47 718#endif
e87231d4 719 env->pc = 0;
c48fcb47
BS
720 env->npc = env->pc + 4;
721#endif
722}
723
64a88d5d 724static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
c48fcb47 725{
64a88d5d 726 sparc_def_t def1, *def = &def1;
c48fcb47 727
64a88d5d
BS
728 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
729 return -1;
c48fcb47 730
5578ceab
BS
731 env->def = qemu_mallocz(sizeof(*def));
732 memcpy(env->def, def, sizeof(*def));
733#if defined(CONFIG_USER_ONLY)
734 if ((env->def->features & CPU_FEATURE_FLOAT))
735 env->def->features |= CPU_FEATURE_FLOAT128;
736#endif
c48fcb47
BS
737 env->cpu_model_str = cpu_model;
738 env->version = def->iu_version;
739 env->fsr = def->fpu_version;
1a14026e 740 env->nwindows = def->nwindows;
c48fcb47 741#if !defined(TARGET_SPARC64)
c48fcb47
BS
742 env->mmuregs[0] |= def->mmu_version;
743 cpu_sparc_set_id(env, 0);
963262de 744 env->mxccregs[7] |= def->mxcc_version;
1a14026e 745#else
fb79ceb9 746 env->mmu_version = def->mmu_version;
c19148bd
BS
747 env->maxtl = def->maxtl;
748 env->version |= def->maxtl << 8;
1a14026e 749 env->version |= def->nwindows - 1;
c48fcb47 750#endif
64a88d5d
BS
751 return 0;
752}
753
754static void cpu_sparc_close(CPUSPARCState *env)
755{
5578ceab 756 free(env->def);
64a88d5d
BS
757 free(env);
758}
759
760CPUSPARCState *cpu_sparc_init(const char *cpu_model)
761{
762 CPUSPARCState *env;
763
764 env = qemu_mallocz(sizeof(CPUSPARCState));
64a88d5d 765 cpu_exec_init(env);
c48fcb47
BS
766
767 gen_intermediate_code_init(env);
768
64a88d5d
BS
769 if (cpu_sparc_register(env, cpu_model) < 0) {
770 cpu_sparc_close(env);
771 return NULL;
772 }
0bf46a40 773 qemu_init_vcpu(env);
c48fcb47
BS
774
775 return env;
776}
777
778void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
779{
780#if !defined(TARGET_SPARC64)
781 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
782#endif
783}
784
785static const sparc_def_t sparc_defs[] = {
786#ifdef TARGET_SPARC64
787 {
788 .name = "Fujitsu Sparc64",
c19148bd 789 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
c48fcb47 790 .fpu_version = 0x00000000,
fb79ceb9 791 .mmu_version = mmu_us_12,
1a14026e 792 .nwindows = 4,
c19148bd 793 .maxtl = 4,
64a88d5d 794 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
795 },
796 {
797 .name = "Fujitsu Sparc64 III",
c19148bd 798 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
c48fcb47 799 .fpu_version = 0x00000000,
fb79ceb9 800 .mmu_version = mmu_us_12,
1a14026e 801 .nwindows = 5,
c19148bd 802 .maxtl = 4,
64a88d5d 803 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
804 },
805 {
806 .name = "Fujitsu Sparc64 IV",
c19148bd 807 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
c48fcb47 808 .fpu_version = 0x00000000,
fb79ceb9 809 .mmu_version = mmu_us_12,
1a14026e 810 .nwindows = 8,
c19148bd 811 .maxtl = 5,
64a88d5d 812 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
813 },
814 {
815 .name = "Fujitsu Sparc64 V",
c19148bd 816 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
c48fcb47 817 .fpu_version = 0x00000000,
fb79ceb9 818 .mmu_version = mmu_us_12,
1a14026e 819 .nwindows = 8,
c19148bd 820 .maxtl = 5,
64a88d5d 821 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
822 },
823 {
824 .name = "TI UltraSparc I",
c19148bd 825 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 826 .fpu_version = 0x00000000,
fb79ceb9 827 .mmu_version = mmu_us_12,
1a14026e 828 .nwindows = 8,
c19148bd 829 .maxtl = 5,
64a88d5d 830 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
831 },
832 {
833 .name = "TI UltraSparc II",
c19148bd 834 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
c48fcb47 835 .fpu_version = 0x00000000,
fb79ceb9 836 .mmu_version = mmu_us_12,
1a14026e 837 .nwindows = 8,
c19148bd 838 .maxtl = 5,
64a88d5d 839 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
840 },
841 {
842 .name = "TI UltraSparc IIi",
c19148bd 843 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
c48fcb47 844 .fpu_version = 0x00000000,
fb79ceb9 845 .mmu_version = mmu_us_12,
1a14026e 846 .nwindows = 8,
c19148bd 847 .maxtl = 5,
64a88d5d 848 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
849 },
850 {
851 .name = "TI UltraSparc IIe",
c19148bd 852 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
c48fcb47 853 .fpu_version = 0x00000000,
fb79ceb9 854 .mmu_version = mmu_us_12,
1a14026e 855 .nwindows = 8,
c19148bd 856 .maxtl = 5,
64a88d5d 857 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
858 },
859 {
860 .name = "Sun UltraSparc III",
c19148bd 861 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
c48fcb47 862 .fpu_version = 0x00000000,
fb79ceb9 863 .mmu_version = mmu_us_12,
1a14026e 864 .nwindows = 8,
c19148bd 865 .maxtl = 5,
64a88d5d 866 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
867 },
868 {
869 .name = "Sun UltraSparc III Cu",
c19148bd 870 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
c48fcb47 871 .fpu_version = 0x00000000,
fb79ceb9 872 .mmu_version = mmu_us_3,
1a14026e 873 .nwindows = 8,
c19148bd 874 .maxtl = 5,
64a88d5d 875 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
876 },
877 {
878 .name = "Sun UltraSparc IIIi",
c19148bd 879 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
c48fcb47 880 .fpu_version = 0x00000000,
fb79ceb9 881 .mmu_version = mmu_us_12,
1a14026e 882 .nwindows = 8,
c19148bd 883 .maxtl = 5,
64a88d5d 884 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
885 },
886 {
887 .name = "Sun UltraSparc IV",
c19148bd 888 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
c48fcb47 889 .fpu_version = 0x00000000,
fb79ceb9 890 .mmu_version = mmu_us_4,
1a14026e 891 .nwindows = 8,
c19148bd 892 .maxtl = 5,
64a88d5d 893 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
894 },
895 {
896 .name = "Sun UltraSparc IV+",
c19148bd 897 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
c48fcb47 898 .fpu_version = 0x00000000,
fb79ceb9 899 .mmu_version = mmu_us_12,
1a14026e 900 .nwindows = 8,
c19148bd 901 .maxtl = 5,
fb79ceb9 902 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
c48fcb47
BS
903 },
904 {
905 .name = "Sun UltraSparc IIIi+",
c19148bd 906 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
c48fcb47 907 .fpu_version = 0x00000000,
fb79ceb9 908 .mmu_version = mmu_us_3,
1a14026e 909 .nwindows = 8,
c19148bd 910 .maxtl = 5,
64a88d5d 911 .features = CPU_DEFAULT_FEATURES,
c48fcb47 912 },
c7ba218d
BS
913 {
914 .name = "Sun UltraSparc T1",
915 // defined in sparc_ifu_fdp.v and ctu.h
c19148bd 916 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
917 .fpu_version = 0x00000000,
918 .mmu_version = mmu_sun4v,
919 .nwindows = 8,
c19148bd 920 .maxtl = 6,
c7ba218d
BS
921 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
922 | CPU_FEATURE_GL,
923 },
924 {
925 .name = "Sun UltraSparc T2",
926 // defined in tlu_asi_ctl.v and n2_revid_cust.v
c19148bd 927 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
928 .fpu_version = 0x00000000,
929 .mmu_version = mmu_sun4v,
930 .nwindows = 8,
c19148bd 931 .maxtl = 6,
c7ba218d
BS
932 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
933 | CPU_FEATURE_GL,
934 },
c48fcb47
BS
935 {
936 .name = "NEC UltraSparc I",
c19148bd 937 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 938 .fpu_version = 0x00000000,
fb79ceb9 939 .mmu_version = mmu_us_12,
1a14026e 940 .nwindows = 8,
c19148bd 941 .maxtl = 5,
64a88d5d 942 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
943 },
944#else
945 {
946 .name = "Fujitsu MB86900",
947 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
948 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
949 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
950 .mmu_bm = 0x00004000,
951 .mmu_ctpr_mask = 0x007ffff0,
952 .mmu_cxr_mask = 0x0000003f,
953 .mmu_sfsr_mask = 0xffffffff,
954 .mmu_trcr_mask = 0xffffffff,
1a14026e 955 .nwindows = 7,
e30b4678 956 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
c48fcb47
BS
957 },
958 {
959 .name = "Fujitsu MB86904",
960 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
961 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
962 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
963 .mmu_bm = 0x00004000,
964 .mmu_ctpr_mask = 0x00ffffc0,
965 .mmu_cxr_mask = 0x000000ff,
966 .mmu_sfsr_mask = 0x00016fff,
967 .mmu_trcr_mask = 0x00ffffff,
1a14026e 968 .nwindows = 8,
64a88d5d 969 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
970 },
971 {
972 .name = "Fujitsu MB86907",
973 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
974 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
975 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
976 .mmu_bm = 0x00004000,
977 .mmu_ctpr_mask = 0xffffffc0,
978 .mmu_cxr_mask = 0x000000ff,
979 .mmu_sfsr_mask = 0x00016fff,
980 .mmu_trcr_mask = 0xffffffff,
1a14026e 981 .nwindows = 8,
64a88d5d 982 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
983 },
984 {
985 .name = "LSI L64811",
986 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
987 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
988 .mmu_version = 0x10 << 24,
989 .mmu_bm = 0x00004000,
990 .mmu_ctpr_mask = 0x007ffff0,
991 .mmu_cxr_mask = 0x0000003f,
992 .mmu_sfsr_mask = 0xffffffff,
993 .mmu_trcr_mask = 0xffffffff,
1a14026e 994 .nwindows = 8,
e30b4678
BS
995 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
996 CPU_FEATURE_FSMULD,
c48fcb47
BS
997 },
998 {
999 .name = "Cypress CY7C601",
1000 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1001 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1002 .mmu_version = 0x10 << 24,
1003 .mmu_bm = 0x00004000,
1004 .mmu_ctpr_mask = 0x007ffff0,
1005 .mmu_cxr_mask = 0x0000003f,
1006 .mmu_sfsr_mask = 0xffffffff,
1007 .mmu_trcr_mask = 0xffffffff,
1a14026e 1008 .nwindows = 8,
e30b4678
BS
1009 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1010 CPU_FEATURE_FSMULD,
c48fcb47
BS
1011 },
1012 {
1013 .name = "Cypress CY7C611",
1014 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1015 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1016 .mmu_version = 0x10 << 24,
1017 .mmu_bm = 0x00004000,
1018 .mmu_ctpr_mask = 0x007ffff0,
1019 .mmu_cxr_mask = 0x0000003f,
1020 .mmu_sfsr_mask = 0xffffffff,
1021 .mmu_trcr_mask = 0xffffffff,
1a14026e 1022 .nwindows = 8,
e30b4678
BS
1023 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1024 CPU_FEATURE_FSMULD,
c48fcb47 1025 },
c48fcb47
BS
1026 {
1027 .name = "TI MicroSparc I",
1028 .iu_version = 0x41000000,
1029 .fpu_version = 4 << 17,
1030 .mmu_version = 0x41000000,
1031 .mmu_bm = 0x00004000,
1032 .mmu_ctpr_mask = 0x007ffff0,
1033 .mmu_cxr_mask = 0x0000003f,
1034 .mmu_sfsr_mask = 0x00016fff,
1035 .mmu_trcr_mask = 0x0000003f,
1a14026e 1036 .nwindows = 7,
e30b4678
BS
1037 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1038 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1039 CPU_FEATURE_FMUL,
c48fcb47
BS
1040 },
1041 {
1042 .name = "TI MicroSparc II",
1043 .iu_version = 0x42000000,
1044 .fpu_version = 4 << 17,
1045 .mmu_version = 0x02000000,
1046 .mmu_bm = 0x00004000,
1047 .mmu_ctpr_mask = 0x00ffffc0,
1048 .mmu_cxr_mask = 0x000000ff,
1049 .mmu_sfsr_mask = 0x00016fff,
1050 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1051 .nwindows = 8,
64a88d5d 1052 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1053 },
1054 {
1055 .name = "TI MicroSparc IIep",
1056 .iu_version = 0x42000000,
1057 .fpu_version = 4 << 17,
1058 .mmu_version = 0x04000000,
1059 .mmu_bm = 0x00004000,
1060 .mmu_ctpr_mask = 0x00ffffc0,
1061 .mmu_cxr_mask = 0x000000ff,
1062 .mmu_sfsr_mask = 0x00016bff,
1063 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1064 .nwindows = 8,
64a88d5d 1065 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1066 },
b5154bde
BS
1067 {
1068 .name = "TI SuperSparc 40", // STP1020NPGA
963262de 1069 .iu_version = 0x41000000, // SuperSPARC 2.x
b5154bde 1070 .fpu_version = 0 << 17,
963262de 1071 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
b5154bde
BS
1072 .mmu_bm = 0x00002000,
1073 .mmu_ctpr_mask = 0xffffffc0,
1074 .mmu_cxr_mask = 0x0000ffff,
1075 .mmu_sfsr_mask = 0xffffffff,
1076 .mmu_trcr_mask = 0xffffffff,
1a14026e 1077 .nwindows = 8,
b5154bde
BS
1078 .features = CPU_DEFAULT_FEATURES,
1079 },
1080 {
1081 .name = "TI SuperSparc 50", // STP1020PGA
963262de 1082 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1083 .fpu_version = 0 << 17,
963262de 1084 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1085 .mmu_bm = 0x00002000,
1086 .mmu_ctpr_mask = 0xffffffc0,
1087 .mmu_cxr_mask = 0x0000ffff,
1088 .mmu_sfsr_mask = 0xffffffff,
1089 .mmu_trcr_mask = 0xffffffff,
1a14026e 1090 .nwindows = 8,
b5154bde
BS
1091 .features = CPU_DEFAULT_FEATURES,
1092 },
c48fcb47
BS
1093 {
1094 .name = "TI SuperSparc 51",
963262de 1095 .iu_version = 0x40000000, // SuperSPARC 3.x
c48fcb47 1096 .fpu_version = 0 << 17,
963262de 1097 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
c48fcb47
BS
1098 .mmu_bm = 0x00002000,
1099 .mmu_ctpr_mask = 0xffffffc0,
1100 .mmu_cxr_mask = 0x0000ffff,
1101 .mmu_sfsr_mask = 0xffffffff,
1102 .mmu_trcr_mask = 0xffffffff,
963262de 1103 .mxcc_version = 0x00000104,
1a14026e 1104 .nwindows = 8,
64a88d5d 1105 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1106 },
b5154bde
BS
1107 {
1108 .name = "TI SuperSparc 60", // STP1020APGA
963262de 1109 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1110 .fpu_version = 0 << 17,
963262de 1111 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1112 .mmu_bm = 0x00002000,
1113 .mmu_ctpr_mask = 0xffffffc0,
1114 .mmu_cxr_mask = 0x0000ffff,
1115 .mmu_sfsr_mask = 0xffffffff,
1116 .mmu_trcr_mask = 0xffffffff,
1a14026e 1117 .nwindows = 8,
b5154bde
BS
1118 .features = CPU_DEFAULT_FEATURES,
1119 },
c48fcb47
BS
1120 {
1121 .name = "TI SuperSparc 61",
963262de 1122 .iu_version = 0x44000000, // SuperSPARC 3.x
c48fcb47 1123 .fpu_version = 0 << 17,
963262de
BS
1124 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1125 .mmu_bm = 0x00002000,
1126 .mmu_ctpr_mask = 0xffffffc0,
1127 .mmu_cxr_mask = 0x0000ffff,
1128 .mmu_sfsr_mask = 0xffffffff,
1129 .mmu_trcr_mask = 0xffffffff,
1130 .mxcc_version = 0x00000104,
1131 .nwindows = 8,
1132 .features = CPU_DEFAULT_FEATURES,
1133 },
1134 {
1135 .name = "TI SuperSparc II",
1136 .iu_version = 0x40000000, // SuperSPARC II 1.x
1137 .fpu_version = 0 << 17,
1138 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
c48fcb47
BS
1139 .mmu_bm = 0x00002000,
1140 .mmu_ctpr_mask = 0xffffffc0,
1141 .mmu_cxr_mask = 0x0000ffff,
1142 .mmu_sfsr_mask = 0xffffffff,
1143 .mmu_trcr_mask = 0xffffffff,
963262de 1144 .mxcc_version = 0x00000104,
1a14026e 1145 .nwindows = 8,
64a88d5d 1146 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1147 },
1148 {
1149 .name = "Ross RT625",
1150 .iu_version = 0x1e000000,
1151 .fpu_version = 1 << 17,
1152 .mmu_version = 0x1e000000,
1153 .mmu_bm = 0x00004000,
1154 .mmu_ctpr_mask = 0x007ffff0,
1155 .mmu_cxr_mask = 0x0000003f,
1156 .mmu_sfsr_mask = 0xffffffff,
1157 .mmu_trcr_mask = 0xffffffff,
1a14026e 1158 .nwindows = 8,
64a88d5d 1159 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1160 },
1161 {
1162 .name = "Ross RT620",
1163 .iu_version = 0x1f000000,
1164 .fpu_version = 1 << 17,
1165 .mmu_version = 0x1f000000,
1166 .mmu_bm = 0x00004000,
1167 .mmu_ctpr_mask = 0x007ffff0,
1168 .mmu_cxr_mask = 0x0000003f,
1169 .mmu_sfsr_mask = 0xffffffff,
1170 .mmu_trcr_mask = 0xffffffff,
1a14026e 1171 .nwindows = 8,
64a88d5d 1172 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1173 },
1174 {
1175 .name = "BIT B5010",
1176 .iu_version = 0x20000000,
1177 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1178 .mmu_version = 0x20000000,
1179 .mmu_bm = 0x00004000,
1180 .mmu_ctpr_mask = 0x007ffff0,
1181 .mmu_cxr_mask = 0x0000003f,
1182 .mmu_sfsr_mask = 0xffffffff,
1183 .mmu_trcr_mask = 0xffffffff,
1a14026e 1184 .nwindows = 8,
e30b4678
BS
1185 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1186 CPU_FEATURE_FSMULD,
c48fcb47
BS
1187 },
1188 {
1189 .name = "Matsushita MN10501",
1190 .iu_version = 0x50000000,
1191 .fpu_version = 0 << 17,
1192 .mmu_version = 0x50000000,
1193 .mmu_bm = 0x00004000,
1194 .mmu_ctpr_mask = 0x007ffff0,
1195 .mmu_cxr_mask = 0x0000003f,
1196 .mmu_sfsr_mask = 0xffffffff,
1197 .mmu_trcr_mask = 0xffffffff,
1a14026e 1198 .nwindows = 8,
e30b4678
BS
1199 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1200 CPU_FEATURE_FSMULD,
c48fcb47
BS
1201 },
1202 {
1203 .name = "Weitek W8601",
1204 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1205 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1206 .mmu_version = 0x10 << 24,
1207 .mmu_bm = 0x00004000,
1208 .mmu_ctpr_mask = 0x007ffff0,
1209 .mmu_cxr_mask = 0x0000003f,
1210 .mmu_sfsr_mask = 0xffffffff,
1211 .mmu_trcr_mask = 0xffffffff,
1a14026e 1212 .nwindows = 8,
64a88d5d 1213 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1214 },
1215 {
1216 .name = "LEON2",
1217 .iu_version = 0xf2000000,
1218 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1219 .mmu_version = 0xf2000000,
1220 .mmu_bm = 0x00004000,
1221 .mmu_ctpr_mask = 0x007ffff0,
1222 .mmu_cxr_mask = 0x0000003f,
1223 .mmu_sfsr_mask = 0xffffffff,
1224 .mmu_trcr_mask = 0xffffffff,
1a14026e 1225 .nwindows = 8,
64a88d5d 1226 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1227 },
1228 {
1229 .name = "LEON3",
1230 .iu_version = 0xf3000000,
1231 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1232 .mmu_version = 0xf3000000,
1233 .mmu_bm = 0x00004000,
1234 .mmu_ctpr_mask = 0x007ffff0,
1235 .mmu_cxr_mask = 0x0000003f,
1236 .mmu_sfsr_mask = 0xffffffff,
1237 .mmu_trcr_mask = 0xffffffff,
1a14026e 1238 .nwindows = 8,
64a88d5d 1239 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1240 },
1241#endif
1242};
1243
64a88d5d
BS
1244static const char * const feature_name[] = {
1245 "float",
1246 "float128",
1247 "swap",
1248 "mul",
1249 "div",
1250 "flush",
1251 "fsqrt",
1252 "fmul",
1253 "vis1",
1254 "vis2",
e30b4678 1255 "fsmuld",
fb79ceb9
BS
1256 "hypv",
1257 "cmt",
1258 "gl",
64a88d5d
BS
1259};
1260
1261static void print_features(FILE *f,
1262 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1263 uint32_t features, const char *prefix)
c48fcb47
BS
1264{
1265 unsigned int i;
1266
64a88d5d
BS
1267 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1268 if (feature_name[i] && (features & (1 << i))) {
1269 if (prefix)
1270 (*cpu_fprintf)(f, "%s", prefix);
1271 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1272 }
1273}
1274
1275static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1276{
1277 unsigned int i;
1278
1279 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1280 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1281 *features |= 1 << i;
1282 return;
1283 }
1284 fprintf(stderr, "CPU feature %s not found\n", flagname);
1285}
1286
22548760 1287static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
64a88d5d
BS
1288{
1289 unsigned int i;
1290 const sparc_def_t *def = NULL;
1291 char *s = strdup(cpu_model);
1292 char *featurestr, *name = strtok(s, ",");
1293 uint32_t plus_features = 0;
1294 uint32_t minus_features = 0;
1295 long long iu_version;
1a14026e 1296 uint32_t fpu_version, mmu_version, nwindows;
64a88d5d 1297
b1503cda 1298 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
c48fcb47 1299 if (strcasecmp(name, sparc_defs[i].name) == 0) {
64a88d5d 1300 def = &sparc_defs[i];
c48fcb47
BS
1301 }
1302 }
64a88d5d
BS
1303 if (!def)
1304 goto error;
1305 memcpy(cpu_def, def, sizeof(*def));
1306
1307 featurestr = strtok(NULL, ",");
1308 while (featurestr) {
1309 char *val;
1310
1311 if (featurestr[0] == '+') {
1312 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1313 } else if (featurestr[0] == '-') {
1314 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1315 } else if ((val = strchr(featurestr, '='))) {
1316 *val = 0; val++;
1317 if (!strcmp(featurestr, "iu_version")) {
1318 char *err;
1319
1320 iu_version = strtoll(val, &err, 0);
1321 if (!*val || *err) {
1322 fprintf(stderr, "bad numerical value %s\n", val);
1323 goto error;
1324 }
1325 cpu_def->iu_version = iu_version;
1326#ifdef DEBUG_FEATURES
1327 fprintf(stderr, "iu_version %llx\n", iu_version);
1328#endif
1329 } else if (!strcmp(featurestr, "fpu_version")) {
1330 char *err;
1331
1332 fpu_version = strtol(val, &err, 0);
1333 if (!*val || *err) {
1334 fprintf(stderr, "bad numerical value %s\n", val);
1335 goto error;
1336 }
1337 cpu_def->fpu_version = fpu_version;
1338#ifdef DEBUG_FEATURES
0bf9e31a 1339 fprintf(stderr, "fpu_version %x\n", fpu_version);
64a88d5d
BS
1340#endif
1341 } else if (!strcmp(featurestr, "mmu_version")) {
1342 char *err;
1343
1344 mmu_version = strtol(val, &err, 0);
1345 if (!*val || *err) {
1346 fprintf(stderr, "bad numerical value %s\n", val);
1347 goto error;
1348 }
1349 cpu_def->mmu_version = mmu_version;
1350#ifdef DEBUG_FEATURES
0bf9e31a 1351 fprintf(stderr, "mmu_version %x\n", mmu_version);
1a14026e
BS
1352#endif
1353 } else if (!strcmp(featurestr, "nwindows")) {
1354 char *err;
1355
1356 nwindows = strtol(val, &err, 0);
1357 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1358 nwindows < MIN_NWINDOWS) {
1359 fprintf(stderr, "bad numerical value %s\n", val);
1360 goto error;
1361 }
1362 cpu_def->nwindows = nwindows;
1363#ifdef DEBUG_FEATURES
1364 fprintf(stderr, "nwindows %d\n", nwindows);
64a88d5d
BS
1365#endif
1366 } else {
1367 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1368 goto error;
1369 }
1370 } else {
77f193da
BS
1371 fprintf(stderr, "feature string `%s' not in format "
1372 "(+feature|-feature|feature=xyz)\n", featurestr);
64a88d5d
BS
1373 goto error;
1374 }
1375 featurestr = strtok(NULL, ",");
1376 }
1377 cpu_def->features |= plus_features;
1378 cpu_def->features &= ~minus_features;
1379#ifdef DEBUG_FEATURES
1380 print_features(stderr, fprintf, cpu_def->features, NULL);
1381#endif
1382 free(s);
1383 return 0;
1384
1385 error:
1386 free(s);
1387 return -1;
c48fcb47
BS
1388}
1389
77f193da 1390void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
c48fcb47
BS
1391{
1392 unsigned int i;
1393
b1503cda 1394 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1a14026e 1395 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
c48fcb47
BS
1396 sparc_defs[i].name,
1397 sparc_defs[i].iu_version,
1398 sparc_defs[i].fpu_version,
1a14026e
BS
1399 sparc_defs[i].mmu_version,
1400 sparc_defs[i].nwindows);
77f193da
BS
1401 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1402 ~sparc_defs[i].features, "-");
1403 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1404 sparc_defs[i].features, "+");
64a88d5d 1405 (*cpu_fprintf)(f, "\n");
c48fcb47 1406 }
f76981b1
BS
1407 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1408 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
64a88d5d 1409 (*cpu_fprintf)(f, "\n");
f76981b1
BS
1410 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1411 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1412 (*cpu_fprintf)(f, "\n");
1413 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1414 "fpu_version mmu_version nwindows\n");
c48fcb47
BS
1415}
1416
c48fcb47
BS
1417void cpu_dump_state(CPUState *env, FILE *f,
1418 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1419 int flags)
1420{
1421 int i, x;
1422
77f193da
BS
1423 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1424 env->npc);
c48fcb47
BS
1425 cpu_fprintf(f, "General Registers:\n");
1426 for (i = 0; i < 4; i++)
1427 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1428 cpu_fprintf(f, "\n");
1429 for (; i < 8; i++)
1430 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1431 cpu_fprintf(f, "\nCurrent Register Window:\n");
1432 for (x = 0; x < 3; x++) {
1433 for (i = 0; i < 4; i++)
1434 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1435 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1436 env->regwptr[i + x * 8]);
1437 cpu_fprintf(f, "\n");
1438 for (; i < 8; i++)
1439 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1440 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1441 env->regwptr[i + x * 8]);
1442 cpu_fprintf(f, "\n");
1443 }
1444 cpu_fprintf(f, "\nFloating Point Registers:\n");
1445 for (i = 0; i < 32; i++) {
1446 if ((i & 3) == 0)
1447 cpu_fprintf(f, "%%f%02d:", i);
a37ee56c 1448 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
c48fcb47
BS
1449 if ((i & 3) == 3)
1450 cpu_fprintf(f, "\n");
1451 }
1452#ifdef TARGET_SPARC64
1453 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1454 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
77f193da
BS
1455 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1456 "cleanwin %d cwp %d\n",
c48fcb47 1457 env->cansave, env->canrestore, env->otherwin, env->wstate,
1a14026e 1458 env->cleanwin, env->nwindows - 1 - env->cwp);
c48fcb47 1459#else
d78f3995
BS
1460
1461#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1462
77f193da
BS
1463 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1464 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1465 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1466 env->psrs?'S':'-', env->psrps?'P':'-',
1467 env->psret?'E':'-', env->wim);
c48fcb47 1468#endif
3a3b925d 1469 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
c48fcb47 1470}