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