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