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