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