]> git.proxmox.com Git - qemu.git/blame - target-sparc/helper.c
Merge remote branch 'qemu-kvm/uq/master' into staging
[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
b04d9890 773 env->cache_control = 0;
c48fcb47
BS
774}
775
64a88d5d 776static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
c48fcb47 777{
64a88d5d 778 sparc_def_t def1, *def = &def1;
c48fcb47 779
64a88d5d
BS
780 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
781 return -1;
c48fcb47 782
5578ceab
BS
783 env->def = qemu_mallocz(sizeof(*def));
784 memcpy(env->def, def, sizeof(*def));
785#if defined(CONFIG_USER_ONLY)
786 if ((env->def->features & CPU_FEATURE_FLOAT))
787 env->def->features |= CPU_FEATURE_FLOAT128;
788#endif
c48fcb47
BS
789 env->cpu_model_str = cpu_model;
790 env->version = def->iu_version;
791 env->fsr = def->fpu_version;
1a14026e 792 env->nwindows = def->nwindows;
c48fcb47 793#if !defined(TARGET_SPARC64)
c48fcb47
BS
794 env->mmuregs[0] |= def->mmu_version;
795 cpu_sparc_set_id(env, 0);
963262de 796 env->mxccregs[7] |= def->mxcc_version;
1a14026e 797#else
fb79ceb9 798 env->mmu_version = def->mmu_version;
c19148bd
BS
799 env->maxtl = def->maxtl;
800 env->version |= def->maxtl << 8;
1a14026e 801 env->version |= def->nwindows - 1;
c48fcb47 802#endif
64a88d5d
BS
803 return 0;
804}
805
806static void cpu_sparc_close(CPUSPARCState *env)
807{
5578ceab 808 free(env->def);
64a88d5d
BS
809 free(env);
810}
811
812CPUSPARCState *cpu_sparc_init(const char *cpu_model)
813{
814 CPUSPARCState *env;
815
816 env = qemu_mallocz(sizeof(CPUSPARCState));
64a88d5d 817 cpu_exec_init(env);
c48fcb47
BS
818
819 gen_intermediate_code_init(env);
820
64a88d5d
BS
821 if (cpu_sparc_register(env, cpu_model) < 0) {
822 cpu_sparc_close(env);
823 return NULL;
824 }
0bf46a40 825 qemu_init_vcpu(env);
c48fcb47
BS
826
827 return env;
828}
829
830void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
831{
832#if !defined(TARGET_SPARC64)
833 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
834#endif
835}
836
837static const sparc_def_t sparc_defs[] = {
838#ifdef TARGET_SPARC64
839 {
840 .name = "Fujitsu Sparc64",
c19148bd 841 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
c48fcb47 842 .fpu_version = 0x00000000,
fb79ceb9 843 .mmu_version = mmu_us_12,
1a14026e 844 .nwindows = 4,
c19148bd 845 .maxtl = 4,
64a88d5d 846 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
847 },
848 {
849 .name = "Fujitsu Sparc64 III",
c19148bd 850 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
c48fcb47 851 .fpu_version = 0x00000000,
fb79ceb9 852 .mmu_version = mmu_us_12,
1a14026e 853 .nwindows = 5,
c19148bd 854 .maxtl = 4,
64a88d5d 855 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
856 },
857 {
858 .name = "Fujitsu Sparc64 IV",
c19148bd 859 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
c48fcb47 860 .fpu_version = 0x00000000,
fb79ceb9 861 .mmu_version = mmu_us_12,
1a14026e 862 .nwindows = 8,
c19148bd 863 .maxtl = 5,
64a88d5d 864 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
865 },
866 {
867 .name = "Fujitsu Sparc64 V",
c19148bd 868 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
c48fcb47 869 .fpu_version = 0x00000000,
fb79ceb9 870 .mmu_version = mmu_us_12,
1a14026e 871 .nwindows = 8,
c19148bd 872 .maxtl = 5,
64a88d5d 873 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
874 },
875 {
876 .name = "TI UltraSparc I",
c19148bd 877 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 878 .fpu_version = 0x00000000,
fb79ceb9 879 .mmu_version = mmu_us_12,
1a14026e 880 .nwindows = 8,
c19148bd 881 .maxtl = 5,
64a88d5d 882 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
883 },
884 {
885 .name = "TI UltraSparc II",
c19148bd 886 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
c48fcb47 887 .fpu_version = 0x00000000,
fb79ceb9 888 .mmu_version = mmu_us_12,
1a14026e 889 .nwindows = 8,
c19148bd 890 .maxtl = 5,
64a88d5d 891 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
892 },
893 {
894 .name = "TI UltraSparc IIi",
c19148bd 895 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
c48fcb47 896 .fpu_version = 0x00000000,
fb79ceb9 897 .mmu_version = mmu_us_12,
1a14026e 898 .nwindows = 8,
c19148bd 899 .maxtl = 5,
64a88d5d 900 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
901 },
902 {
903 .name = "TI UltraSparc IIe",
c19148bd 904 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
c48fcb47 905 .fpu_version = 0x00000000,
fb79ceb9 906 .mmu_version = mmu_us_12,
1a14026e 907 .nwindows = 8,
c19148bd 908 .maxtl = 5,
64a88d5d 909 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
910 },
911 {
912 .name = "Sun UltraSparc III",
c19148bd 913 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
c48fcb47 914 .fpu_version = 0x00000000,
fb79ceb9 915 .mmu_version = mmu_us_12,
1a14026e 916 .nwindows = 8,
c19148bd 917 .maxtl = 5,
64a88d5d 918 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
919 },
920 {
921 .name = "Sun UltraSparc III Cu",
c19148bd 922 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
c48fcb47 923 .fpu_version = 0x00000000,
fb79ceb9 924 .mmu_version = mmu_us_3,
1a14026e 925 .nwindows = 8,
c19148bd 926 .maxtl = 5,
64a88d5d 927 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
928 },
929 {
930 .name = "Sun UltraSparc IIIi",
c19148bd 931 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
c48fcb47 932 .fpu_version = 0x00000000,
fb79ceb9 933 .mmu_version = mmu_us_12,
1a14026e 934 .nwindows = 8,
c19148bd 935 .maxtl = 5,
64a88d5d 936 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
937 },
938 {
939 .name = "Sun UltraSparc IV",
c19148bd 940 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
c48fcb47 941 .fpu_version = 0x00000000,
fb79ceb9 942 .mmu_version = mmu_us_4,
1a14026e 943 .nwindows = 8,
c19148bd 944 .maxtl = 5,
64a88d5d 945 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
946 },
947 {
948 .name = "Sun UltraSparc IV+",
c19148bd 949 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
c48fcb47 950 .fpu_version = 0x00000000,
fb79ceb9 951 .mmu_version = mmu_us_12,
1a14026e 952 .nwindows = 8,
c19148bd 953 .maxtl = 5,
fb79ceb9 954 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
c48fcb47
BS
955 },
956 {
957 .name = "Sun UltraSparc IIIi+",
c19148bd 958 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
c48fcb47 959 .fpu_version = 0x00000000,
fb79ceb9 960 .mmu_version = mmu_us_3,
1a14026e 961 .nwindows = 8,
c19148bd 962 .maxtl = 5,
64a88d5d 963 .features = CPU_DEFAULT_FEATURES,
c48fcb47 964 },
c7ba218d
BS
965 {
966 .name = "Sun UltraSparc T1",
967 // defined in sparc_ifu_fdp.v and ctu.h
c19148bd 968 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
969 .fpu_version = 0x00000000,
970 .mmu_version = mmu_sun4v,
971 .nwindows = 8,
c19148bd 972 .maxtl = 6,
c7ba218d
BS
973 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
974 | CPU_FEATURE_GL,
975 },
976 {
977 .name = "Sun UltraSparc T2",
978 // defined in tlu_asi_ctl.v and n2_revid_cust.v
c19148bd 979 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
c7ba218d
BS
980 .fpu_version = 0x00000000,
981 .mmu_version = mmu_sun4v,
982 .nwindows = 8,
c19148bd 983 .maxtl = 6,
c7ba218d
BS
984 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
985 | CPU_FEATURE_GL,
986 },
c48fcb47
BS
987 {
988 .name = "NEC UltraSparc I",
c19148bd 989 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
c48fcb47 990 .fpu_version = 0x00000000,
fb79ceb9 991 .mmu_version = mmu_us_12,
1a14026e 992 .nwindows = 8,
c19148bd 993 .maxtl = 5,
64a88d5d 994 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
995 },
996#else
997 {
998 .name = "Fujitsu MB86900",
999 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1000 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1001 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1002 .mmu_bm = 0x00004000,
1003 .mmu_ctpr_mask = 0x007ffff0,
1004 .mmu_cxr_mask = 0x0000003f,
1005 .mmu_sfsr_mask = 0xffffffff,
1006 .mmu_trcr_mask = 0xffffffff,
1a14026e 1007 .nwindows = 7,
e30b4678 1008 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
c48fcb47
BS
1009 },
1010 {
1011 .name = "Fujitsu MB86904",
1012 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1013 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1014 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1015 .mmu_bm = 0x00004000,
1016 .mmu_ctpr_mask = 0x00ffffc0,
1017 .mmu_cxr_mask = 0x000000ff,
1018 .mmu_sfsr_mask = 0x00016fff,
1019 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1020 .nwindows = 8,
64a88d5d 1021 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1022 },
1023 {
1024 .name = "Fujitsu MB86907",
1025 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1026 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1027 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1028 .mmu_bm = 0x00004000,
1029 .mmu_ctpr_mask = 0xffffffc0,
1030 .mmu_cxr_mask = 0x000000ff,
1031 .mmu_sfsr_mask = 0x00016fff,
1032 .mmu_trcr_mask = 0xffffffff,
1a14026e 1033 .nwindows = 8,
64a88d5d 1034 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1035 },
1036 {
1037 .name = "LSI L64811",
1038 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1039 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1040 .mmu_version = 0x10 << 24,
1041 .mmu_bm = 0x00004000,
1042 .mmu_ctpr_mask = 0x007ffff0,
1043 .mmu_cxr_mask = 0x0000003f,
1044 .mmu_sfsr_mask = 0xffffffff,
1045 .mmu_trcr_mask = 0xffffffff,
1a14026e 1046 .nwindows = 8,
e30b4678
BS
1047 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1048 CPU_FEATURE_FSMULD,
c48fcb47
BS
1049 },
1050 {
1051 .name = "Cypress CY7C601",
1052 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1053 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1054 .mmu_version = 0x10 << 24,
1055 .mmu_bm = 0x00004000,
1056 .mmu_ctpr_mask = 0x007ffff0,
1057 .mmu_cxr_mask = 0x0000003f,
1058 .mmu_sfsr_mask = 0xffffffff,
1059 .mmu_trcr_mask = 0xffffffff,
1a14026e 1060 .nwindows = 8,
e30b4678
BS
1061 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1062 CPU_FEATURE_FSMULD,
c48fcb47
BS
1063 },
1064 {
1065 .name = "Cypress CY7C611",
1066 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1067 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1068 .mmu_version = 0x10 << 24,
1069 .mmu_bm = 0x00004000,
1070 .mmu_ctpr_mask = 0x007ffff0,
1071 .mmu_cxr_mask = 0x0000003f,
1072 .mmu_sfsr_mask = 0xffffffff,
1073 .mmu_trcr_mask = 0xffffffff,
1a14026e 1074 .nwindows = 8,
e30b4678
BS
1075 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1076 CPU_FEATURE_FSMULD,
c48fcb47 1077 },
c48fcb47
BS
1078 {
1079 .name = "TI MicroSparc I",
1080 .iu_version = 0x41000000,
1081 .fpu_version = 4 << 17,
1082 .mmu_version = 0x41000000,
1083 .mmu_bm = 0x00004000,
1084 .mmu_ctpr_mask = 0x007ffff0,
1085 .mmu_cxr_mask = 0x0000003f,
1086 .mmu_sfsr_mask = 0x00016fff,
1087 .mmu_trcr_mask = 0x0000003f,
1a14026e 1088 .nwindows = 7,
e30b4678
BS
1089 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1090 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1091 CPU_FEATURE_FMUL,
c48fcb47
BS
1092 },
1093 {
1094 .name = "TI MicroSparc II",
1095 .iu_version = 0x42000000,
1096 .fpu_version = 4 << 17,
1097 .mmu_version = 0x02000000,
1098 .mmu_bm = 0x00004000,
1099 .mmu_ctpr_mask = 0x00ffffc0,
1100 .mmu_cxr_mask = 0x000000ff,
1101 .mmu_sfsr_mask = 0x00016fff,
1102 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1103 .nwindows = 8,
64a88d5d 1104 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1105 },
1106 {
1107 .name = "TI MicroSparc IIep",
1108 .iu_version = 0x42000000,
1109 .fpu_version = 4 << 17,
1110 .mmu_version = 0x04000000,
1111 .mmu_bm = 0x00004000,
1112 .mmu_ctpr_mask = 0x00ffffc0,
1113 .mmu_cxr_mask = 0x000000ff,
1114 .mmu_sfsr_mask = 0x00016bff,
1115 .mmu_trcr_mask = 0x00ffffff,
1a14026e 1116 .nwindows = 8,
64a88d5d 1117 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1118 },
b5154bde
BS
1119 {
1120 .name = "TI SuperSparc 40", // STP1020NPGA
963262de 1121 .iu_version = 0x41000000, // SuperSPARC 2.x
b5154bde 1122 .fpu_version = 0 << 17,
963262de 1123 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
b5154bde
BS
1124 .mmu_bm = 0x00002000,
1125 .mmu_ctpr_mask = 0xffffffc0,
1126 .mmu_cxr_mask = 0x0000ffff,
1127 .mmu_sfsr_mask = 0xffffffff,
1128 .mmu_trcr_mask = 0xffffffff,
1a14026e 1129 .nwindows = 8,
b5154bde
BS
1130 .features = CPU_DEFAULT_FEATURES,
1131 },
1132 {
1133 .name = "TI SuperSparc 50", // STP1020PGA
963262de 1134 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1135 .fpu_version = 0 << 17,
963262de 1136 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1137 .mmu_bm = 0x00002000,
1138 .mmu_ctpr_mask = 0xffffffc0,
1139 .mmu_cxr_mask = 0x0000ffff,
1140 .mmu_sfsr_mask = 0xffffffff,
1141 .mmu_trcr_mask = 0xffffffff,
1a14026e 1142 .nwindows = 8,
b5154bde
BS
1143 .features = CPU_DEFAULT_FEATURES,
1144 },
c48fcb47
BS
1145 {
1146 .name = "TI SuperSparc 51",
963262de 1147 .iu_version = 0x40000000, // SuperSPARC 3.x
c48fcb47 1148 .fpu_version = 0 << 17,
963262de 1149 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
c48fcb47
BS
1150 .mmu_bm = 0x00002000,
1151 .mmu_ctpr_mask = 0xffffffc0,
1152 .mmu_cxr_mask = 0x0000ffff,
1153 .mmu_sfsr_mask = 0xffffffff,
1154 .mmu_trcr_mask = 0xffffffff,
963262de 1155 .mxcc_version = 0x00000104,
1a14026e 1156 .nwindows = 8,
64a88d5d 1157 .features = CPU_DEFAULT_FEATURES,
c48fcb47 1158 },
b5154bde
BS
1159 {
1160 .name = "TI SuperSparc 60", // STP1020APGA
963262de 1161 .iu_version = 0x40000000, // SuperSPARC 3.x
b5154bde 1162 .fpu_version = 0 << 17,
963262de 1163 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
b5154bde
BS
1164 .mmu_bm = 0x00002000,
1165 .mmu_ctpr_mask = 0xffffffc0,
1166 .mmu_cxr_mask = 0x0000ffff,
1167 .mmu_sfsr_mask = 0xffffffff,
1168 .mmu_trcr_mask = 0xffffffff,
1a14026e 1169 .nwindows = 8,
b5154bde
BS
1170 .features = CPU_DEFAULT_FEATURES,
1171 },
c48fcb47
BS
1172 {
1173 .name = "TI SuperSparc 61",
963262de 1174 .iu_version = 0x44000000, // SuperSPARC 3.x
c48fcb47 1175 .fpu_version = 0 << 17,
963262de
BS
1176 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1177 .mmu_bm = 0x00002000,
1178 .mmu_ctpr_mask = 0xffffffc0,
1179 .mmu_cxr_mask = 0x0000ffff,
1180 .mmu_sfsr_mask = 0xffffffff,
1181 .mmu_trcr_mask = 0xffffffff,
1182 .mxcc_version = 0x00000104,
1183 .nwindows = 8,
1184 .features = CPU_DEFAULT_FEATURES,
1185 },
1186 {
1187 .name = "TI SuperSparc II",
1188 .iu_version = 0x40000000, // SuperSPARC II 1.x
1189 .fpu_version = 0 << 17,
1190 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
c48fcb47
BS
1191 .mmu_bm = 0x00002000,
1192 .mmu_ctpr_mask = 0xffffffc0,
1193 .mmu_cxr_mask = 0x0000ffff,
1194 .mmu_sfsr_mask = 0xffffffff,
1195 .mmu_trcr_mask = 0xffffffff,
963262de 1196 .mxcc_version = 0x00000104,
1a14026e 1197 .nwindows = 8,
64a88d5d 1198 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1199 },
1200 {
1201 .name = "Ross RT625",
1202 .iu_version = 0x1e000000,
1203 .fpu_version = 1 << 17,
1204 .mmu_version = 0x1e000000,
1205 .mmu_bm = 0x00004000,
1206 .mmu_ctpr_mask = 0x007ffff0,
1207 .mmu_cxr_mask = 0x0000003f,
1208 .mmu_sfsr_mask = 0xffffffff,
1209 .mmu_trcr_mask = 0xffffffff,
1a14026e 1210 .nwindows = 8,
64a88d5d 1211 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1212 },
1213 {
1214 .name = "Ross RT620",
1215 .iu_version = 0x1f000000,
1216 .fpu_version = 1 << 17,
1217 .mmu_version = 0x1f000000,
1218 .mmu_bm = 0x00004000,
1219 .mmu_ctpr_mask = 0x007ffff0,
1220 .mmu_cxr_mask = 0x0000003f,
1221 .mmu_sfsr_mask = 0xffffffff,
1222 .mmu_trcr_mask = 0xffffffff,
1a14026e 1223 .nwindows = 8,
64a88d5d 1224 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1225 },
1226 {
1227 .name = "BIT B5010",
1228 .iu_version = 0x20000000,
1229 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1230 .mmu_version = 0x20000000,
1231 .mmu_bm = 0x00004000,
1232 .mmu_ctpr_mask = 0x007ffff0,
1233 .mmu_cxr_mask = 0x0000003f,
1234 .mmu_sfsr_mask = 0xffffffff,
1235 .mmu_trcr_mask = 0xffffffff,
1a14026e 1236 .nwindows = 8,
e30b4678
BS
1237 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1238 CPU_FEATURE_FSMULD,
c48fcb47
BS
1239 },
1240 {
1241 .name = "Matsushita MN10501",
1242 .iu_version = 0x50000000,
1243 .fpu_version = 0 << 17,
1244 .mmu_version = 0x50000000,
1245 .mmu_bm = 0x00004000,
1246 .mmu_ctpr_mask = 0x007ffff0,
1247 .mmu_cxr_mask = 0x0000003f,
1248 .mmu_sfsr_mask = 0xffffffff,
1249 .mmu_trcr_mask = 0xffffffff,
1a14026e 1250 .nwindows = 8,
e30b4678
BS
1251 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1252 CPU_FEATURE_FSMULD,
c48fcb47
BS
1253 },
1254 {
1255 .name = "Weitek W8601",
1256 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1257 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1258 .mmu_version = 0x10 << 24,
1259 .mmu_bm = 0x00004000,
1260 .mmu_ctpr_mask = 0x007ffff0,
1261 .mmu_cxr_mask = 0x0000003f,
1262 .mmu_sfsr_mask = 0xffffffff,
1263 .mmu_trcr_mask = 0xffffffff,
1a14026e 1264 .nwindows = 8,
64a88d5d 1265 .features = CPU_DEFAULT_FEATURES,
c48fcb47
BS
1266 },
1267 {
1268 .name = "LEON2",
1269 .iu_version = 0xf2000000,
1270 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1271 .mmu_version = 0xf2000000,
1272 .mmu_bm = 0x00004000,
1273 .mmu_ctpr_mask = 0x007ffff0,
1274 .mmu_cxr_mask = 0x0000003f,
1275 .mmu_sfsr_mask = 0xffffffff,
1276 .mmu_trcr_mask = 0xffffffff,
1a14026e 1277 .nwindows = 8,
b04d9890 1278 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
c48fcb47
BS
1279 },
1280 {
1281 .name = "LEON3",
1282 .iu_version = 0xf3000000,
1283 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1284 .mmu_version = 0xf3000000,
b04d9890 1285 .mmu_bm = 0x00000000,
c48fcb47
BS
1286 .mmu_ctpr_mask = 0x007ffff0,
1287 .mmu_cxr_mask = 0x0000003f,
1288 .mmu_sfsr_mask = 0xffffffff,
1289 .mmu_trcr_mask = 0xffffffff,
1a14026e 1290 .nwindows = 8,
4a2ba232 1291 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
60f356e8 1292 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
c48fcb47
BS
1293 },
1294#endif
1295};
1296
64a88d5d
BS
1297static const char * const feature_name[] = {
1298 "float",
1299 "float128",
1300 "swap",
1301 "mul",
1302 "div",
1303 "flush",
1304 "fsqrt",
1305 "fmul",
1306 "vis1",
1307 "vis2",
e30b4678 1308 "fsmuld",
fb79ceb9
BS
1309 "hypv",
1310 "cmt",
1311 "gl",
64a88d5d
BS
1312};
1313
9a78eead 1314static void print_features(FILE *f, fprintf_function cpu_fprintf,
64a88d5d 1315 uint32_t features, const char *prefix)
c48fcb47
BS
1316{
1317 unsigned int i;
1318
64a88d5d
BS
1319 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1320 if (feature_name[i] && (features & (1 << i))) {
1321 if (prefix)
1322 (*cpu_fprintf)(f, "%s", prefix);
1323 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1324 }
1325}
1326
1327static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1328{
1329 unsigned int i;
1330
1331 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1332 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1333 *features |= 1 << i;
1334 return;
1335 }
1336 fprintf(stderr, "CPU feature %s not found\n", flagname);
1337}
1338
22548760 1339static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
64a88d5d
BS
1340{
1341 unsigned int i;
1342 const sparc_def_t *def = NULL;
1343 char *s = strdup(cpu_model);
1344 char *featurestr, *name = strtok(s, ",");
1345 uint32_t plus_features = 0;
1346 uint32_t minus_features = 0;
0bfcd599 1347 uint64_t iu_version;
1a14026e 1348 uint32_t fpu_version, mmu_version, nwindows;
64a88d5d 1349
b1503cda 1350 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
c48fcb47 1351 if (strcasecmp(name, sparc_defs[i].name) == 0) {
64a88d5d 1352 def = &sparc_defs[i];
c48fcb47
BS
1353 }
1354 }
64a88d5d
BS
1355 if (!def)
1356 goto error;
1357 memcpy(cpu_def, def, sizeof(*def));
1358
1359 featurestr = strtok(NULL, ",");
1360 while (featurestr) {
1361 char *val;
1362
1363 if (featurestr[0] == '+') {
1364 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1365 } else if (featurestr[0] == '-') {
1366 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1367 } else if ((val = strchr(featurestr, '='))) {
1368 *val = 0; val++;
1369 if (!strcmp(featurestr, "iu_version")) {
1370 char *err;
1371
1372 iu_version = strtoll(val, &err, 0);
1373 if (!*val || *err) {
1374 fprintf(stderr, "bad numerical value %s\n", val);
1375 goto error;
1376 }
1377 cpu_def->iu_version = iu_version;
1378#ifdef DEBUG_FEATURES
0bfcd599 1379 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
64a88d5d
BS
1380#endif
1381 } else if (!strcmp(featurestr, "fpu_version")) {
1382 char *err;
1383
1384 fpu_version = strtol(val, &err, 0);
1385 if (!*val || *err) {
1386 fprintf(stderr, "bad numerical value %s\n", val);
1387 goto error;
1388 }
1389 cpu_def->fpu_version = fpu_version;
1390#ifdef DEBUG_FEATURES
0bf9e31a 1391 fprintf(stderr, "fpu_version %x\n", fpu_version);
64a88d5d
BS
1392#endif
1393 } else if (!strcmp(featurestr, "mmu_version")) {
1394 char *err;
1395
1396 mmu_version = strtol(val, &err, 0);
1397 if (!*val || *err) {
1398 fprintf(stderr, "bad numerical value %s\n", val);
1399 goto error;
1400 }
1401 cpu_def->mmu_version = mmu_version;
1402#ifdef DEBUG_FEATURES
0bf9e31a 1403 fprintf(stderr, "mmu_version %x\n", mmu_version);
1a14026e
BS
1404#endif
1405 } else if (!strcmp(featurestr, "nwindows")) {
1406 char *err;
1407
1408 nwindows = strtol(val, &err, 0);
1409 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1410 nwindows < MIN_NWINDOWS) {
1411 fprintf(stderr, "bad numerical value %s\n", val);
1412 goto error;
1413 }
1414 cpu_def->nwindows = nwindows;
1415#ifdef DEBUG_FEATURES
1416 fprintf(stderr, "nwindows %d\n", nwindows);
64a88d5d
BS
1417#endif
1418 } else {
1419 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1420 goto error;
1421 }
1422 } else {
77f193da
BS
1423 fprintf(stderr, "feature string `%s' not in format "
1424 "(+feature|-feature|feature=xyz)\n", featurestr);
64a88d5d
BS
1425 goto error;
1426 }
1427 featurestr = strtok(NULL, ",");
1428 }
1429 cpu_def->features |= plus_features;
1430 cpu_def->features &= ~minus_features;
1431#ifdef DEBUG_FEATURES
1432 print_features(stderr, fprintf, cpu_def->features, NULL);
1433#endif
1434 free(s);
1435 return 0;
1436
1437 error:
1438 free(s);
1439 return -1;
c48fcb47
BS
1440}
1441
9a78eead 1442void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
c48fcb47
BS
1443{
1444 unsigned int i;
1445
b1503cda 1446 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1a14026e 1447 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
c48fcb47
BS
1448 sparc_defs[i].name,
1449 sparc_defs[i].iu_version,
1450 sparc_defs[i].fpu_version,
1a14026e
BS
1451 sparc_defs[i].mmu_version,
1452 sparc_defs[i].nwindows);
77f193da
BS
1453 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1454 ~sparc_defs[i].features, "-");
1455 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1456 sparc_defs[i].features, "+");
64a88d5d 1457 (*cpu_fprintf)(f, "\n");
c48fcb47 1458 }
f76981b1
BS
1459 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1460 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
64a88d5d 1461 (*cpu_fprintf)(f, "\n");
f76981b1
BS
1462 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1463 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1464 (*cpu_fprintf)(f, "\n");
1465 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1466 "fpu_version mmu_version nwindows\n");
c48fcb47
BS
1467}
1468
9a78eead 1469static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
43bb98bf
BS
1470 uint32_t cc)
1471{
1472 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1473 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1474 cc & PSR_CARRY? 'C' : '-');
1475}
1476
1477#ifdef TARGET_SPARC64
1478#define REGS_PER_LINE 4
1479#else
1480#define REGS_PER_LINE 8
1481#endif
1482
9a78eead 1483void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
c48fcb47
BS
1484 int flags)
1485{
1486 int i, x;
1487
77f193da
BS
1488 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1489 env->npc);
c48fcb47 1490 cpu_fprintf(f, "General Registers:\n");
43bb98bf
BS
1491
1492 for (i = 0; i < 8; i++) {
1493 if (i % REGS_PER_LINE == 0) {
1494 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1495 }
1496 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1497 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1498 cpu_fprintf(f, "\n");
1499 }
1500 }
c48fcb47
BS
1501 cpu_fprintf(f, "\nCurrent Register Window:\n");
1502 for (x = 0; x < 3; x++) {
43bb98bf
BS
1503 for (i = 0; i < 8; i++) {
1504 if (i % REGS_PER_LINE == 0) {
1505 cpu_fprintf(f, "%%%c%d-%d: ",
1506 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1507 i, i + REGS_PER_LINE - 1);
1508 }
1509 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1510 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1511 cpu_fprintf(f, "\n");
1512 }
1513 }
c48fcb47
BS
1514 }
1515 cpu_fprintf(f, "\nFloating Point Registers:\n");
43bb98bf 1516 for (i = 0; i < TARGET_FPREGS; i++) {
c48fcb47
BS
1517 if ((i & 3) == 0)
1518 cpu_fprintf(f, "%%f%02d:", i);
a37ee56c 1519 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
c48fcb47
BS
1520 if ((i & 3) == 3)
1521 cpu_fprintf(f, "\n");
1522 }
1523#ifdef TARGET_SPARC64
43bb98bf 1524 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
113c6106 1525 (unsigned)cpu_get_ccr(env));
5a834bb4 1526 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
43bb98bf 1527 cpu_fprintf(f, " xcc: ");
5a834bb4 1528 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
43bb98bf
BS
1529 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1530 env->psrpil);
1531 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1532 "cleanwin: %d cwp: %d\n",
c48fcb47 1533 env->cansave, env->canrestore, env->otherwin, env->wstate,
1a14026e 1534 env->cleanwin, env->nwindows - 1 - env->cwp);
43bb98bf
BS
1535 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1536 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
c48fcb47 1537#else
5a834bb4
BS
1538 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1539 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
43bb98bf
BS
1540 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1541 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1542 env->wim);
1543 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1544 env->fsr, env->y);
c48fcb47 1545#endif
c48fcb47 1546}