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