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