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