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