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