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