]> git.proxmox.com Git - mirror_qemu.git/blame - target-sparc/helper.c
vnc: add missing target for vnc-encodings-*.o
[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
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
IK
497 env->dmmu.sfar = address; /* Fault address register */
498 return 1;
0f8a249a 499 }
3475187d 500 }
b8e9fc06
IK
501
502 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
503 address, context);
504
6e8e7d4c 505 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
83469015 506 env->exception_index = TT_DMISS;
3475187d
FB
507 return 1;
508}
509
77f193da 510static int get_physical_address_code(CPUState *env,
c227f099 511 target_phys_addr_t *physical, int *prot,
2065061e 512 target_ulong address, int mmu_idx)
3475187d 513{
3475187d 514 unsigned int i;
536ba015 515 uint64_t context;
3475187d 516
2065061e
IK
517 int is_user = (mmu_idx == MMU_USER_IDX ||
518 mmu_idx == MMU_USER_SECONDARY_IDX);
519
e8807b14
IK
520 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
521 /* IMMU disabled */
522 *physical = ultrasparc_truncate_physical(address);
0f8a249a 523 *prot = PAGE_EXEC;
3475187d
FB
524 return 0;
525 }
83469015 526
299b520c 527 if (env->tl == 0) {
2065061e 528 /* PRIMARY context */
299b520c
IK
529 context = env->dmmu.mmu_primary_context & 0x1fff;
530 } else {
2065061e 531 /* NUCLEUS context */
299b520c
IK
532 context = 0;
533 }
536ba015 534
3475187d 535 for (i = 0; i < 64; i++) {
afdf8109 536 // ctx match, vaddr match, valid?
6e8e7d4c 537 if (ultrasparc_tag_match(&env->itlb[i],
299b520c 538 address, context, physical)) {
afdf8109 539 // access ok?
6e8e7d4c
IK
540 if ((env->itlb[i].tte & 0x4) && is_user) {
541 if (env->immu.sfsr) /* Fault status register */
542 env->immu.sfsr = 2; /* overflow (not read before
77f193da 543 another fault) */
6e8e7d4c 544 env->immu.sfsr |= (is_user << 3) | 1;
0f8a249a 545 env->exception_index = TT_TFAULT;
b8e9fc06
IK
546
547 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
548 address, context);
549
0f8a249a
BS
550 return 1;
551 }
0f8a249a 552 *prot = PAGE_EXEC;
f707726e 553 TTE_SET_USED(env->itlb[i].tte);
0f8a249a
BS
554 return 0;
555 }
3475187d 556 }
b8e9fc06
IK
557
558 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
559 address, context);
560
7ab463cb 561 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
6e8e7d4c 562 env->immu.tag_access = (address & ~0x1fffULL) | context;
83469015 563 env->exception_index = TT_TMISS;
3475187d
FB
564 return 1;
565}
566
c227f099 567static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
c48fcb47 568 int *prot, int *access_index,
d4c430a8
PB
569 target_ulong address, int rw, int mmu_idx,
570 target_ulong *page_size)
3475187d 571{
d4c430a8
PB
572 /* ??? We treat everything as a small page, then explicitly flush
573 everything when an entry is evicted. */
574 *page_size = TARGET_PAGE_SIZE;
9fd1ae3a
IK
575
576#if defined (DEBUG_MMU)
577 /* safety net to catch wrong softmmu index use from dynamic code */
578 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
579 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
580 " primary context=%" PRIx64
581 " secondary context=%" PRIx64
582 " address=%" PRIx64
583 "\n",
584 (rw == 2 ? "CODE" : "DATA"),
585 env->tl, mmu_idx,
586 env->dmmu.mmu_primary_context,
587 env->dmmu.mmu_secondary_context,
588 address);
589 }
590#endif
591
3475187d 592 if (rw == 2)
22548760 593 return get_physical_address_code(env, physical, prot, address,
2065061e 594 mmu_idx);
3475187d 595 else
22548760 596 return get_physical_address_data(env, physical, prot, address, rw,
2065061e 597 mmu_idx);
3475187d
FB
598}
599
600/* Perform address translation */
601int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 602 int mmu_idx, int is_softmmu)
3475187d 603{
83469015 604 target_ulong virt_addr, vaddr;
c227f099 605 target_phys_addr_t paddr;
d4c430a8
PB
606 target_ulong page_size;
607 int error_code = 0, prot, access_index;
3475187d 608
77f193da 609 error_code = get_physical_address(env, &paddr, &prot, &access_index,
d4c430a8 610 address, rw, mmu_idx, &page_size);
3475187d 611 if (error_code == 0) {
0f8a249a 612 virt_addr = address & TARGET_PAGE_MASK;
77f193da
BS
613 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
614 (TARGET_PAGE_SIZE - 1));
b8e9fc06
IK
615
616 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
617 " vaddr %" PRIx64
618 " mmu_idx=%d"
619 " tl=%d"
620 " primary context=%" PRIx64
621 " secondary context=%" PRIx64
622 "\n",
623 address, paddr, vaddr, mmu_idx, env->tl,
624 env->dmmu.mmu_primary_context,
625 env->dmmu.mmu_secondary_context);
626
d4c430a8
PB
627 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
628 return 0;
3475187d
FB
629 }
630 // XXX
631 return 1;
632}
633
83469015
FB
634#ifdef DEBUG_MMU
635void dump_mmu(CPUState *env)
636{
637 unsigned int i;
638 const char *mask;
639
77f193da 640 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
6e8e7d4c 641 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
83469015 642 if ((env->lsu & DMMU_E) == 0) {
0f8a249a 643 printf("DMMU disabled\n");
83469015 644 } else {
0f8a249a
BS
645 printf("DMMU dump:\n");
646 for (i = 0; i < 64; i++) {
31a68d57 647 switch ((env->dtlb[i].tte >> 61) & 3) {
0f8a249a
BS
648 default:
649 case 0x0:
650 mask = " 8k";
651 break;
652 case 0x1:
653 mask = " 64k";
654 break;
655 case 0x2:
656 mask = "512k";
657 break;
658 case 0x3:
659 mask = " 4M";
660 break;
661 }
31a68d57
BS
662 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
663 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
2a90358f 664 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
6e8e7d4c 665 i,
31a68d57
BS
666 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
667 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
0f8a249a 668 mask,
31a68d57
BS
669 env->dtlb[i].tte & 0x4? "priv": "user",
670 env->dtlb[i].tte & 0x2? "RW": "RO",
671 env->dtlb[i].tte & 0x40? "locked": "unlocked",
2a90358f 672 env->dtlb[i].tag & (uint64_t)0x1fffULL,
e2129586 673 TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
0f8a249a
BS
674 }
675 }
83469015
FB
676 }
677 if ((env->lsu & IMMU_E) == 0) {
0f8a249a 678 printf("IMMU disabled\n");
83469015 679 } else {
0f8a249a
BS
680 printf("IMMU dump:\n");
681 for (i = 0; i < 64; i++) {
31a68d57 682 switch ((env->itlb[i].tte >> 61) & 3) {
0f8a249a
BS
683 default:
684 case 0x0:
685 mask = " 8k";
686 break;
687 case 0x1:
688 mask = " 64k";
689 break;
690 case 0x2:
691 mask = "512k";
692 break;
693 case 0x3:
694 mask = " 4M";
695 break;
696 }
31a68d57
BS
697 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
698 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
2a90358f 699 ", %s, %s, %s, ctx %" PRId64 " %s\n",
6e8e7d4c
IK
700 i,
701 env->itlb[i].tag & (uint64_t)~0x1fffULL,
31a68d57 702 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
0f8a249a 703 mask,
31a68d57
BS
704 env->itlb[i].tte & 0x4? "priv": "user",
705 env->itlb[i].tte & 0x40? "locked": "unlocked",
2a90358f 706 env->itlb[i].tag & (uint64_t)0x1fffULL,
e2129586 707 TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
0f8a249a
BS
708 }
709 }
83469015
FB
710 }
711}
24741ef3
FB
712#endif /* DEBUG_MMU */
713
714#endif /* TARGET_SPARC64 */
715#endif /* !CONFIG_USER_ONLY */
716
c48fcb47 717
4fcc562b 718#if !defined(CONFIG_USER_ONLY)
2065061e
IK
719target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
720 int mmu_idx)
c48fcb47 721{
c227f099 722 target_phys_addr_t phys_addr;
d4c430a8 723 target_ulong page_size;
c48fcb47
BS
724 int prot, access_index;
725
726 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
2065061e 727 mmu_idx, &page_size) != 0)
c48fcb47 728 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
2065061e 729 0, mmu_idx, &page_size) != 0)
c48fcb47
BS
730 return -1;
731 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
732 return -1;
733 return phys_addr;
734}
2065061e
IK
735
736target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
737{
9fd1ae3a 738 return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
2065061e 739}
c48fcb47
BS
740#endif
741
c48fcb47
BS
742void cpu_reset(CPUSPARCState *env)
743{
eca1bdf4
AL
744 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
745 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
746 log_cpu_state(env, 0);
747 }
748
c48fcb47
BS
749 tlb_flush(env, 1);
750 env->cwp = 0;
5210977a 751#ifndef TARGET_SPARC64
c48fcb47 752 env->wim = 1;
5210977a 753#endif
c48fcb47 754 env->regwptr = env->regbase + (env->cwp * 16);
6b743278 755 CC_OP = CC_OP_FLAGS;
c48fcb47 756#if defined(CONFIG_USER_ONLY)
c48fcb47 757#ifdef TARGET_SPARC64
1a14026e
BS
758 env->cleanwin = env->nwindows - 2;
759 env->cansave = env->nwindows - 2;
c48fcb47
BS
760 env->pstate = PS_RMO | PS_PEF | PS_IE;
761 env->asi = 0x82; // Primary no-fault
762#endif
763#else
5210977a 764#if !defined(TARGET_SPARC64)
c48fcb47
BS
765 env->psret = 0;
766 env->psrs = 1;
767 env->psrps = 1;
2aae2b8e 768#endif
c48fcb47 769#ifdef TARGET_SPARC64
8194f35a 770 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
2aae2b8e 771 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
8194f35a
IK
772 env->tl = env->maxtl;
773 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
415fc906 774 env->lsu = 0;
c48fcb47 775#else
c48fcb47 776 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
5578ceab 777 env->mmuregs[0] |= env->def->mmu_bm;
c48fcb47 778#endif
e87231d4 779 env->pc = 0;
c48fcb47
BS
780 env->npc = env->pc + 4;
781#endif
782}
783
64a88d5d 784static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
c48fcb47 785{
64a88d5d 786 sparc_def_t def1, *def = &def1;
c48fcb47 787
64a88d5d
BS
788 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
789 return -1;
c48fcb47 790
5578ceab
BS
791 env->def = qemu_mallocz(sizeof(*def));
792 memcpy(env->def, def, sizeof(*def));
793#if defined(CONFIG_USER_ONLY)
794 if ((env->def->features & CPU_FEATURE_FLOAT))
795 env->def->features |= CPU_FEATURE_FLOAT128;
796#endif
c48fcb47
BS
797 env->cpu_model_str = cpu_model;
798 env->version = def->iu_version;
799 env->fsr = def->fpu_version;
1a14026e 800 env->nwindows = def->nwindows;
c48fcb47 801#if !defined(TARGET_SPARC64)
c48fcb47
BS
802 env->mmuregs[0] |= def->mmu_version;
803 cpu_sparc_set_id(env, 0);
963262de 804 env->mxccregs[7] |= def->mxcc_version;
1a14026e 805#else
fb79ceb9 806 env->mmu_version = def->mmu_version;
c19148bd
BS
807 env->maxtl = def->maxtl;
808 env->version |= def->maxtl << 8;
1a14026e 809 env->version |= def->nwindows - 1;
c48fcb47 810#endif
64a88d5d
BS
811 return 0;
812}
813
814static void cpu_sparc_close(CPUSPARCState *env)
815{
5578ceab 816 free(env->def);
64a88d5d
BS
817 free(env);
818}
819
820CPUSPARCState *cpu_sparc_init(const char *cpu_model)
821{
822 CPUSPARCState *env;
823
824 env = qemu_mallocz(sizeof(CPUSPARCState));
64a88d5d 825 cpu_exec_init(env);
c48fcb47
BS
826
827 gen_intermediate_code_init(env);
828
64a88d5d
BS
829 if (cpu_sparc_register(env, cpu_model) < 0) {
830 cpu_sparc_close(env);
831 return NULL;
832 }
0bf46a40 833 qemu_init_vcpu(env);
c48fcb47
BS
834
835 return env;
836}
837
838void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
839{
840#if !defined(TARGET_SPARC64)
841 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
842#endif
843}
844
845static const sparc_def_t sparc_defs[] = {
846#ifdef TARGET_SPARC64
847 {
848 .name = "Fujitsu Sparc64",
c19148bd 849 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
c48fcb47 850 .fpu_version = 0x00000000,
fb79ceb9 851 .mmu_version = mmu_us_12,
1a14026e 852 .nwindows = 4,
c19148bd 853 .maxtl = 4,
64a88d5d 854 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
855 },
856 {
857 .name = "Fujitsu Sparc64 III",
c19148bd 858 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
c48fcb47 859 .fpu_version = 0x00000000,
fb79ceb9 860 .mmu_version = mmu_us_12,
1a14026e 861 .nwindows = 5,
c19148bd 862 .maxtl = 4,
64a88d5d 863 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
864 },
865 {
866 .name = "Fujitsu Sparc64 IV",
c19148bd 867 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
c48fcb47 868 .fpu_version = 0x00000000,
fb79ceb9 869 .mmu_version = mmu_us_12,
1a14026e 870 .nwindows = 8,
c19148bd 871 .maxtl = 5,
64a88d5d 872 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
873 },
874 {
875 .name = "Fujitsu Sparc64 V",
c19148bd 876 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
c48fcb47 877 .fpu_version = 0x00000000,
fb79ceb9 878 .mmu_version = mmu_us_12,
1a14026e 879 .nwindows = 8,
c19148bd 880 .maxtl = 5,
64a88d5d 881 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
882 },
883 {
884 .name = "TI UltraSparc I",
c19148bd 885 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 886 .fpu_version = 0x00000000,
fb79ceb9 887 .mmu_version = mmu_us_12,
1a14026e 888 .nwindows = 8,
c19148bd 889 .maxtl = 5,
64a88d5d 890 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
891 },
892 {
893 .name = "TI UltraSparc II",
c19148bd 894 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
c48fcb47 895 .fpu_version = 0x00000000,
fb79ceb9 896 .mmu_version = mmu_us_12,
1a14026e 897 .nwindows = 8,
c19148bd 898 .maxtl = 5,
64a88d5d 899 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
900 },
901 {
902 .name = "TI UltraSparc IIi",
c19148bd 903 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
c48fcb47 904 .fpu_version = 0x00000000,
fb79ceb9 905 .mmu_version = mmu_us_12,
1a14026e 906 .nwindows = 8,
c19148bd 907 .maxtl = 5,
64a88d5d 908 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
909 },
910 {
911 .name = "TI UltraSparc IIe",
c19148bd 912 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
c48fcb47 913 .fpu_version = 0x00000000,
fb79ceb9 914 .mmu_version = mmu_us_12,
1a14026e 915 .nwindows = 8,
c19148bd 916 .maxtl = 5,
64a88d5d 917 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
918 },
919 {
920 .name = "Sun UltraSparc III",
c19148bd 921 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
c48fcb47 922 .fpu_version = 0x00000000,
fb79ceb9 923 .mmu_version = mmu_us_12,
1a14026e 924 .nwindows = 8,
c19148bd 925 .maxtl = 5,
64a88d5d 926 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
927 },
928 {
929 .name = "Sun UltraSparc III Cu",
c19148bd 930 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
c48fcb47 931 .fpu_version = 0x00000000,
fb79ceb9 932 .mmu_version = mmu_us_3,
1a14026e 933 .nwindows = 8,
c19148bd 934 .maxtl = 5,
64a88d5d 935 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
936 },
937 {
938 .name = "Sun UltraSparc IIIi",
c19148bd 939 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
c48fcb47 940 .fpu_version = 0x00000000,
fb79ceb9 941 .mmu_version = mmu_us_12,
1a14026e 942 .nwindows = 8,
c19148bd 943 .maxtl = 5,
64a88d5d 944 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
945 },
946 {
947 .name = "Sun UltraSparc IV",
c19148bd 948 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
c48fcb47 949 .fpu_version = 0x00000000,
fb79ceb9 950 .mmu_version = mmu_us_4,
1a14026e 951 .nwindows = 8,
c19148bd 952 .maxtl = 5,
64a88d5d 953 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
954 },
955 {
956 .name = "Sun UltraSparc IV+",
c19148bd 957 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
c48fcb47 958 .fpu_version = 0x00000000,
fb79ceb9 959 .mmu_version = mmu_us_12,
1a14026e 960 .nwindows = 8,
c19148bd 961 .maxtl = 5,
fb79ceb9 962 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
c48fcb47
BS
963 },
964 {
965 .name = "Sun UltraSparc IIIi+",
c19148bd 966 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
c48fcb47 967 .fpu_version = 0x00000000,
fb79ceb9 968 .mmu_version = mmu_us_3,
1a14026e 969 .nwindows = 8,
c19148bd 970 .maxtl = 5,
64a88d5d 971 .features = CPU_DEFAULT_FEATURES,
c48fcb47 972 },
c7ba218d
BS
973 {
974 .name = "Sun UltraSparc T1",
975 // defined in sparc_ifu_fdp.v and ctu.h
c19148bd 976 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
977 .fpu_version = 0x00000000,
978 .mmu_version = mmu_sun4v,
979 .nwindows = 8,
c19148bd 980 .maxtl = 6,
c7ba218d
BS
981 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
982 | CPU_FEATURE_GL,
983 },
984 {
985 .name = "Sun UltraSparc T2",
986 // defined in tlu_asi_ctl.v and n2_revid_cust.v
c19148bd 987 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
988 .fpu_version = 0x00000000,
989 .mmu_version = mmu_sun4v,
990 .nwindows = 8,
c19148bd 991 .maxtl = 6,
c7ba218d
BS
992 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
993 | CPU_FEATURE_GL,
994 },
c48fcb47
BS
995 {
996 .name = "NEC UltraSparc I",
c19148bd 997 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 998 .fpu_version = 0x00000000,
fb79ceb9 999 .mmu_version = mmu_us_12,
1a14026e 1000 .nwindows = 8,
c19148bd 1001 .maxtl = 5,
64a88d5d 1002 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1003 },
1004#else
1005 {
1006 .name = "Fujitsu MB86900",
1007 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1008 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1009 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1010 .mmu_bm = 0x00004000,
1011 .mmu_ctpr_mask = 0x007ffff0,
1012 .mmu_cxr_mask = 0x0000003f,
1013 .mmu_sfsr_mask = 0xffffffff,
1014 .mmu_trcr_mask = 0xffffffff,
1a14026e 1015 .nwindows = 7,
e30b4678 1016 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
c48fcb47
BS
1017 },
1018 {
1019 .name = "Fujitsu MB86904",
1020 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1021 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1022 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1023 .mmu_bm = 0x00004000,
1024 .mmu_ctpr_mask = 0x00ffffc0,
1025 .mmu_cxr_mask = 0x000000ff,
1026 .mmu_sfsr_mask = 0x00016fff,
1027 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1028 .nwindows = 8,
64a88d5d 1029 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1030 },
1031 {
1032 .name = "Fujitsu MB86907",
1033 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1034 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1035 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1036 .mmu_bm = 0x00004000,
1037 .mmu_ctpr_mask = 0xffffffc0,
1038 .mmu_cxr_mask = 0x000000ff,
1039 .mmu_sfsr_mask = 0x00016fff,
1040 .mmu_trcr_mask = 0xffffffff,
1a14026e 1041 .nwindows = 8,
64a88d5d 1042 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1043 },
1044 {
1045 .name = "LSI L64811",
1046 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1047 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1048 .mmu_version = 0x10 << 24,
1049 .mmu_bm = 0x00004000,
1050 .mmu_ctpr_mask = 0x007ffff0,
1051 .mmu_cxr_mask = 0x0000003f,
1052 .mmu_sfsr_mask = 0xffffffff,
1053 .mmu_trcr_mask = 0xffffffff,
1a14026e 1054 .nwindows = 8,
e30b4678
BS
1055 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1056 CPU_FEATURE_FSMULD,
c48fcb47
BS
1057 },
1058 {
1059 .name = "Cypress CY7C601",
1060 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1061 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1062 .mmu_version = 0x10 << 24,
1063 .mmu_bm = 0x00004000,
1064 .mmu_ctpr_mask = 0x007ffff0,
1065 .mmu_cxr_mask = 0x0000003f,
1066 .mmu_sfsr_mask = 0xffffffff,
1067 .mmu_trcr_mask = 0xffffffff,
1a14026e 1068 .nwindows = 8,
e30b4678
BS
1069 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1070 CPU_FEATURE_FSMULD,
c48fcb47
BS
1071 },
1072 {
1073 .name = "Cypress CY7C611",
1074 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1075 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1076 .mmu_version = 0x10 << 24,
1077 .mmu_bm = 0x00004000,
1078 .mmu_ctpr_mask = 0x007ffff0,
1079 .mmu_cxr_mask = 0x0000003f,
1080 .mmu_sfsr_mask = 0xffffffff,
1081 .mmu_trcr_mask = 0xffffffff,
1a14026e 1082 .nwindows = 8,
e30b4678
BS
1083 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1084 CPU_FEATURE_FSMULD,
c48fcb47 1085 },
c48fcb47
BS
1086 {
1087 .name = "TI MicroSparc I",
1088 .iu_version = 0x41000000,
1089 .fpu_version = 4 << 17,
1090 .mmu_version = 0x41000000,
1091 .mmu_bm = 0x00004000,
1092 .mmu_ctpr_mask = 0x007ffff0,
1093 .mmu_cxr_mask = 0x0000003f,
1094 .mmu_sfsr_mask = 0x00016fff,
1095 .mmu_trcr_mask = 0x0000003f,
1a14026e 1096 .nwindows = 7,
e30b4678
BS
1097 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1098 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1099 CPU_FEATURE_FMUL,
c48fcb47
BS
1100 },
1101 {
1102 .name = "TI MicroSparc II",
1103 .iu_version = 0x42000000,
1104 .fpu_version = 4 << 17,
1105 .mmu_version = 0x02000000,
1106 .mmu_bm = 0x00004000,
1107 .mmu_ctpr_mask = 0x00ffffc0,
1108 .mmu_cxr_mask = 0x000000ff,
1109 .mmu_sfsr_mask = 0x00016fff,
1110 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1111 .nwindows = 8,
64a88d5d 1112 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1113 },
1114 {
1115 .name = "TI MicroSparc IIep",
1116 .iu_version = 0x42000000,
1117 .fpu_version = 4 << 17,
1118 .mmu_version = 0x04000000,
1119 .mmu_bm = 0x00004000,
1120 .mmu_ctpr_mask = 0x00ffffc0,
1121 .mmu_cxr_mask = 0x000000ff,
1122 .mmu_sfsr_mask = 0x00016bff,
1123 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1124 .nwindows = 8,
64a88d5d 1125 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1126 },
b5154bde
BS
1127 {
1128 .name = "TI SuperSparc 40", // STP1020NPGA
963262de 1129 .iu_version = 0x41000000, // SuperSPARC 2.x
b5154bde 1130 .fpu_version = 0 << 17,
963262de 1131 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
b5154bde
BS
1132 .mmu_bm = 0x00002000,
1133 .mmu_ctpr_mask = 0xffffffc0,
1134 .mmu_cxr_mask = 0x0000ffff,
1135 .mmu_sfsr_mask = 0xffffffff,
1136 .mmu_trcr_mask = 0xffffffff,
1a14026e 1137 .nwindows = 8,
b5154bde
BS
1138 .features = CPU_DEFAULT_FEATURES,
1139 },
1140 {
1141 .name = "TI SuperSparc 50", // STP1020PGA
963262de 1142 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1143 .fpu_version = 0 << 17,
963262de 1144 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1145 .mmu_bm = 0x00002000,
1146 .mmu_ctpr_mask = 0xffffffc0,
1147 .mmu_cxr_mask = 0x0000ffff,
1148 .mmu_sfsr_mask = 0xffffffff,
1149 .mmu_trcr_mask = 0xffffffff,
1a14026e 1150 .nwindows = 8,
b5154bde
BS
1151 .features = CPU_DEFAULT_FEATURES,
1152 },
c48fcb47
BS
1153 {
1154 .name = "TI SuperSparc 51",
963262de 1155 .iu_version = 0x40000000, // SuperSPARC 3.x
c48fcb47 1156 .fpu_version = 0 << 17,
963262de 1157 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
c48fcb47
BS
1158 .mmu_bm = 0x00002000,
1159 .mmu_ctpr_mask = 0xffffffc0,
1160 .mmu_cxr_mask = 0x0000ffff,
1161 .mmu_sfsr_mask = 0xffffffff,
1162 .mmu_trcr_mask = 0xffffffff,
963262de 1163 .mxcc_version = 0x00000104,
1a14026e 1164 .nwindows = 8,
64a88d5d 1165 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1166 },
b5154bde
BS
1167 {
1168 .name = "TI SuperSparc 60", // STP1020APGA
963262de 1169 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1170 .fpu_version = 0 << 17,
963262de 1171 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1172 .mmu_bm = 0x00002000,
1173 .mmu_ctpr_mask = 0xffffffc0,
1174 .mmu_cxr_mask = 0x0000ffff,
1175 .mmu_sfsr_mask = 0xffffffff,
1176 .mmu_trcr_mask = 0xffffffff,
1a14026e 1177 .nwindows = 8,
b5154bde
BS
1178 .features = CPU_DEFAULT_FEATURES,
1179 },
c48fcb47
BS
1180 {
1181 .name = "TI SuperSparc 61",
963262de 1182 .iu_version = 0x44000000, // SuperSPARC 3.x
c48fcb47 1183 .fpu_version = 0 << 17,
963262de
BS
1184 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1185 .mmu_bm = 0x00002000,
1186 .mmu_ctpr_mask = 0xffffffc0,
1187 .mmu_cxr_mask = 0x0000ffff,
1188 .mmu_sfsr_mask = 0xffffffff,
1189 .mmu_trcr_mask = 0xffffffff,
1190 .mxcc_version = 0x00000104,
1191 .nwindows = 8,
1192 .features = CPU_DEFAULT_FEATURES,
1193 },
1194 {
1195 .name = "TI SuperSparc II",
1196 .iu_version = 0x40000000, // SuperSPARC II 1.x
1197 .fpu_version = 0 << 17,
1198 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
c48fcb47
BS
1199 .mmu_bm = 0x00002000,
1200 .mmu_ctpr_mask = 0xffffffc0,
1201 .mmu_cxr_mask = 0x0000ffff,
1202 .mmu_sfsr_mask = 0xffffffff,
1203 .mmu_trcr_mask = 0xffffffff,
963262de 1204 .mxcc_version = 0x00000104,
1a14026e 1205 .nwindows = 8,
64a88d5d 1206 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1207 },
1208 {
1209 .name = "Ross RT625",
1210 .iu_version = 0x1e000000,
1211 .fpu_version = 1 << 17,
1212 .mmu_version = 0x1e000000,
1213 .mmu_bm = 0x00004000,
1214 .mmu_ctpr_mask = 0x007ffff0,
1215 .mmu_cxr_mask = 0x0000003f,
1216 .mmu_sfsr_mask = 0xffffffff,
1217 .mmu_trcr_mask = 0xffffffff,
1a14026e 1218 .nwindows = 8,
64a88d5d 1219 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1220 },
1221 {
1222 .name = "Ross RT620",
1223 .iu_version = 0x1f000000,
1224 .fpu_version = 1 << 17,
1225 .mmu_version = 0x1f000000,
1226 .mmu_bm = 0x00004000,
1227 .mmu_ctpr_mask = 0x007ffff0,
1228 .mmu_cxr_mask = 0x0000003f,
1229 .mmu_sfsr_mask = 0xffffffff,
1230 .mmu_trcr_mask = 0xffffffff,
1a14026e 1231 .nwindows = 8,
64a88d5d 1232 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1233 },
1234 {
1235 .name = "BIT B5010",
1236 .iu_version = 0x20000000,
1237 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1238 .mmu_version = 0x20000000,
1239 .mmu_bm = 0x00004000,
1240 .mmu_ctpr_mask = 0x007ffff0,
1241 .mmu_cxr_mask = 0x0000003f,
1242 .mmu_sfsr_mask = 0xffffffff,
1243 .mmu_trcr_mask = 0xffffffff,
1a14026e 1244 .nwindows = 8,
e30b4678
BS
1245 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1246 CPU_FEATURE_FSMULD,
c48fcb47
BS
1247 },
1248 {
1249 .name = "Matsushita MN10501",
1250 .iu_version = 0x50000000,
1251 .fpu_version = 0 << 17,
1252 .mmu_version = 0x50000000,
1253 .mmu_bm = 0x00004000,
1254 .mmu_ctpr_mask = 0x007ffff0,
1255 .mmu_cxr_mask = 0x0000003f,
1256 .mmu_sfsr_mask = 0xffffffff,
1257 .mmu_trcr_mask = 0xffffffff,
1a14026e 1258 .nwindows = 8,
e30b4678
BS
1259 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1260 CPU_FEATURE_FSMULD,
c48fcb47
BS
1261 },
1262 {
1263 .name = "Weitek W8601",
1264 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1265 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1266 .mmu_version = 0x10 << 24,
1267 .mmu_bm = 0x00004000,
1268 .mmu_ctpr_mask = 0x007ffff0,
1269 .mmu_cxr_mask = 0x0000003f,
1270 .mmu_sfsr_mask = 0xffffffff,
1271 .mmu_trcr_mask = 0xffffffff,
1a14026e 1272 .nwindows = 8,
64a88d5d 1273 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1274 },
1275 {
1276 .name = "LEON2",
1277 .iu_version = 0xf2000000,
1278 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1279 .mmu_version = 0xf2000000,
1280 .mmu_bm = 0x00004000,
1281 .mmu_ctpr_mask = 0x007ffff0,
1282 .mmu_cxr_mask = 0x0000003f,
1283 .mmu_sfsr_mask = 0xffffffff,
1284 .mmu_trcr_mask = 0xffffffff,
1a14026e 1285 .nwindows = 8,
64a88d5d 1286 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1287 },
1288 {
1289 .name = "LEON3",
1290 .iu_version = 0xf3000000,
1291 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1292 .mmu_version = 0xf3000000,
1293 .mmu_bm = 0x00004000,
1294 .mmu_ctpr_mask = 0x007ffff0,
1295 .mmu_cxr_mask = 0x0000003f,
1296 .mmu_sfsr_mask = 0xffffffff,
1297 .mmu_trcr_mask = 0xffffffff,
1a14026e 1298 .nwindows = 8,
64a88d5d 1299 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1300 },
1301#endif
1302};
1303
64a88d5d
BS
1304static const char * const feature_name[] = {
1305 "float",
1306 "float128",
1307 "swap",
1308 "mul",
1309 "div",
1310 "flush",
1311 "fsqrt",
1312 "fmul",
1313 "vis1",
1314 "vis2",
e30b4678 1315 "fsmuld",
fb79ceb9
BS
1316 "hypv",
1317 "cmt",
1318 "gl",
64a88d5d
BS
1319};
1320
1321static void print_features(FILE *f,
1322 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1323 uint32_t features, const char *prefix)
c48fcb47
BS
1324{
1325 unsigned int i;
1326
64a88d5d
BS
1327 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1328 if (feature_name[i] && (features & (1 << i))) {
1329 if (prefix)
1330 (*cpu_fprintf)(f, "%s", prefix);
1331 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1332 }
1333}
1334
1335static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1336{
1337 unsigned int i;
1338
1339 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1340 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1341 *features |= 1 << i;
1342 return;
1343 }
1344 fprintf(stderr, "CPU feature %s not found\n", flagname);
1345}
1346
22548760 1347static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
64a88d5d
BS
1348{
1349 unsigned int i;
1350 const sparc_def_t *def = NULL;
1351 char *s = strdup(cpu_model);
1352 char *featurestr, *name = strtok(s, ",");
1353 uint32_t plus_features = 0;
1354 uint32_t minus_features = 0;
0bfcd599 1355 uint64_t iu_version;
1a14026e 1356 uint32_t fpu_version, mmu_version, nwindows;
64a88d5d 1357
b1503cda 1358 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
c48fcb47 1359 if (strcasecmp(name, sparc_defs[i].name) == 0) {
64a88d5d 1360 def = &sparc_defs[i];
c48fcb47
BS
1361 }
1362 }
64a88d5d
BS
1363 if (!def)
1364 goto error;
1365 memcpy(cpu_def, def, sizeof(*def));
1366
1367 featurestr = strtok(NULL, ",");
1368 while (featurestr) {
1369 char *val;
1370
1371 if (featurestr[0] == '+') {
1372 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1373 } else if (featurestr[0] == '-') {
1374 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1375 } else if ((val = strchr(featurestr, '='))) {
1376 *val = 0; val++;
1377 if (!strcmp(featurestr, "iu_version")) {
1378 char *err;
1379
1380 iu_version = strtoll(val, &err, 0);
1381 if (!*val || *err) {
1382 fprintf(stderr, "bad numerical value %s\n", val);
1383 goto error;
1384 }
1385 cpu_def->iu_version = iu_version;
1386#ifdef DEBUG_FEATURES
0bfcd599 1387 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
64a88d5d
BS
1388#endif
1389 } else if (!strcmp(featurestr, "fpu_version")) {
1390 char *err;
1391
1392 fpu_version = strtol(val, &err, 0);
1393 if (!*val || *err) {
1394 fprintf(stderr, "bad numerical value %s\n", val);
1395 goto error;
1396 }
1397 cpu_def->fpu_version = fpu_version;
1398#ifdef DEBUG_FEATURES
0bf9e31a 1399 fprintf(stderr, "fpu_version %x\n", fpu_version);
64a88d5d
BS
1400#endif
1401 } else if (!strcmp(featurestr, "mmu_version")) {
1402 char *err;
1403
1404 mmu_version = strtol(val, &err, 0);
1405 if (!*val || *err) {
1406 fprintf(stderr, "bad numerical value %s\n", val);
1407 goto error;
1408 }
1409 cpu_def->mmu_version = mmu_version;
1410#ifdef DEBUG_FEATURES
0bf9e31a 1411 fprintf(stderr, "mmu_version %x\n", mmu_version);
1a14026e
BS
1412#endif
1413 } else if (!strcmp(featurestr, "nwindows")) {
1414 char *err;
1415
1416 nwindows = strtol(val, &err, 0);
1417 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1418 nwindows < MIN_NWINDOWS) {
1419 fprintf(stderr, "bad numerical value %s\n", val);
1420 goto error;
1421 }
1422 cpu_def->nwindows = nwindows;
1423#ifdef DEBUG_FEATURES
1424 fprintf(stderr, "nwindows %d\n", nwindows);
64a88d5d
BS
1425#endif
1426 } else {
1427 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1428 goto error;
1429 }
1430 } else {
77f193da
BS
1431 fprintf(stderr, "feature string `%s' not in format "
1432 "(+feature|-feature|feature=xyz)\n", featurestr);
64a88d5d
BS
1433 goto error;
1434 }
1435 featurestr = strtok(NULL, ",");
1436 }
1437 cpu_def->features |= plus_features;
1438 cpu_def->features &= ~minus_features;
1439#ifdef DEBUG_FEATURES
1440 print_features(stderr, fprintf, cpu_def->features, NULL);
1441#endif
1442 free(s);
1443 return 0;
1444
1445 error:
1446 free(s);
1447 return -1;
c48fcb47
BS
1448}
1449
77f193da 1450void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
c48fcb47
BS
1451{
1452 unsigned int i;
1453
b1503cda 1454 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1a14026e 1455 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
c48fcb47
BS
1456 sparc_defs[i].name,
1457 sparc_defs[i].iu_version,
1458 sparc_defs[i].fpu_version,
1a14026e
BS
1459 sparc_defs[i].mmu_version,
1460 sparc_defs[i].nwindows);
77f193da
BS
1461 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1462 ~sparc_defs[i].features, "-");
1463 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1464 sparc_defs[i].features, "+");
64a88d5d 1465 (*cpu_fprintf)(f, "\n");
c48fcb47 1466 }
f76981b1
BS
1467 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1468 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
64a88d5d 1469 (*cpu_fprintf)(f, "\n");
f76981b1
BS
1470 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1471 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1472 (*cpu_fprintf)(f, "\n");
1473 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1474 "fpu_version mmu_version nwindows\n");
c48fcb47
BS
1475}
1476
43bb98bf
BS
1477static void cpu_print_cc(FILE *f,
1478 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1479 uint32_t cc)
1480{
1481 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1482 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1483 cc & PSR_CARRY? 'C' : '-');
1484}
1485
1486#ifdef TARGET_SPARC64
1487#define REGS_PER_LINE 4
1488#else
1489#define REGS_PER_LINE 8
1490#endif
1491
c48fcb47
BS
1492void cpu_dump_state(CPUState *env, FILE *f,
1493 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1494 int flags)
1495{
1496 int i, x;
1497
77f193da
BS
1498 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1499 env->npc);
c48fcb47 1500 cpu_fprintf(f, "General Registers:\n");
43bb98bf
BS
1501
1502 for (i = 0; i < 8; i++) {
1503 if (i % REGS_PER_LINE == 0) {
1504 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1505 }
1506 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1507 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1508 cpu_fprintf(f, "\n");
1509 }
1510 }
c48fcb47
BS
1511 cpu_fprintf(f, "\nCurrent Register Window:\n");
1512 for (x = 0; x < 3; x++) {
43bb98bf
BS
1513 for (i = 0; i < 8; i++) {
1514 if (i % REGS_PER_LINE == 0) {
1515 cpu_fprintf(f, "%%%c%d-%d: ",
1516 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1517 i, i + REGS_PER_LINE - 1);
1518 }
1519 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1520 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1521 cpu_fprintf(f, "\n");
1522 }
1523 }
c48fcb47
BS
1524 }
1525 cpu_fprintf(f, "\nFloating Point Registers:\n");
43bb98bf 1526 for (i = 0; i < TARGET_FPREGS; i++) {
c48fcb47
BS
1527 if ((i & 3) == 0)
1528 cpu_fprintf(f, "%%f%02d:", i);
a37ee56c 1529 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
c48fcb47
BS
1530 if ((i & 3) == 3)
1531 cpu_fprintf(f, "\n");
1532 }
1533#ifdef TARGET_SPARC64
43bb98bf 1534 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
113c6106 1535 (unsigned)cpu_get_ccr(env));
5a834bb4 1536 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
43bb98bf 1537 cpu_fprintf(f, " xcc: ");
5a834bb4 1538 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
43bb98bf
BS
1539 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1540 env->psrpil);
1541 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1542 "cleanwin: %d cwp: %d\n",
c48fcb47 1543 env->cansave, env->canrestore, env->otherwin, env->wstate,
1a14026e 1544 env->cleanwin, env->nwindows - 1 - env->cwp);
43bb98bf
BS
1545 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1546 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
c48fcb47 1547#else
5a834bb4
BS
1548 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1549 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
43bb98bf
BS
1550 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1551 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1552 env->wim);
1553 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1554 env->fsr, env->y);
c48fcb47 1555#endif
c48fcb47 1556}