~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to target-sparc/helper.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-07 06:20:34 UTC
  • mfrom: (1.1.9 upstream)
  • mto: This revision was merged to the branch mainline in revision 7.
  • Revision ID: james.westby@ubuntu.com-20090307062034-i3pead4mw653v2el
Tags: 0.10.0-1
[ Aurelien Jarno ]
* New upstream release:
  - Fix fr-be keyboard mapping (closes: bug#514462).
  - Fix stat64 structure on ppc-linux-user (closes: bug#470231).
  - Add a chroot option (closes: bug#415996).
  - Add evdev support (closes: bug#513210).
  - Fix loop on symlinks in user mode (closes: bug#297572).
  - Bump depends on openbios-sparc.
  - Depends on openbios-ppc.
  - Update 12_signal_powerpc_support.patch.
  - Update 21_net_soopts.patch.
  - Drop 44_socklen_t_check.patch (merged upstream).
  - Drop 49_null_check.patch (merged upstream).
  - Update 64_ppc_asm_constraints.patch.
  - Drop security/CVE-2008-0928-fedora.patch (merged upstream).
  - Drop security/CVE-2007-5730.patch (merged upstream).
* patches/80_stable-branch.patch: add patches from stable branch:
  - Fix race condition between signal handler/execution loop (closes:
    bug#474386, bug#501731).
* debian/copyright: update.
* Compile and install .dtb files:
  - debian/control: build-depends on device-tree-compiler.
  - debian/patches/81_compile_dtb.patch: new patch from upstream.
  - debian/rules: compile and install bamboo.dtb and mpc8544.dtb.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
17
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
19
 */
20
20
#include <stdarg.h>
21
21
#include <stdlib.h>
27
27
 
28
28
#include "cpu.h"
29
29
#include "exec-all.h"
 
30
#include "qemu-common.h"
30
31
 
31
32
//#define DEBUG_MMU
 
33
//#define DEBUG_FEATURES
 
34
 
 
35
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
32
36
 
33
37
/* Sparc MMU emulation */
34
38
 
35
39
/* thread support */
36
40
 
37
 
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
 
41
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
38
42
 
39
43
void cpu_lock(void)
40
44
{
48
52
 
49
53
#if defined(CONFIG_USER_ONLY)
50
54
 
51
 
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
 
55
int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
52
56
                               int mmu_idx, int is_softmmu)
53
57
{
54
58
    if (rw & 2)
55
 
        env->exception_index = TT_TFAULT;
 
59
        env1->exception_index = TT_TFAULT;
56
60
    else
57
 
        env->exception_index = TT_DFAULT;
 
61
        env1->exception_index = TT_DFAULT;
58
62
    return 1;
59
63
}
60
64
 
65
69
 * Sparc V8 Reference MMU (SRMMU)
66
70
 */
67
71
static const int access_table[8][8] = {
68
 
    { 0, 0, 0, 0, 2, 0, 3, 3 },
69
 
    { 0, 0, 0, 0, 2, 0, 0, 0 },
70
 
    { 2, 2, 0, 0, 0, 2, 3, 3 },
71
 
    { 2, 2, 0, 0, 0, 2, 0, 0 },
72
 
    { 2, 0, 2, 0, 2, 2, 3, 3 },
73
 
    { 2, 0, 2, 0, 2, 0, 2, 0 },
74
 
    { 2, 2, 2, 0, 2, 2, 3, 3 },
75
 
    { 2, 2, 2, 0, 2, 2, 2, 0 }
 
72
    { 0, 0, 0, 0, 8, 0, 12, 12 },
 
73
    { 0, 0, 0, 0, 8, 0, 0, 0 },
 
74
    { 8, 8, 0, 0, 0, 8, 12, 12 },
 
75
    { 8, 8, 0, 0, 0, 8, 0, 0 },
 
76
    { 8, 0, 8, 0, 8, 8, 12, 12 },
 
77
    { 8, 0, 8, 0, 8, 0, 8, 0 },
 
78
    { 8, 8, 8, 0, 8, 8, 12, 12 },
 
79
    { 8, 8, 8, 0, 8, 8, 8, 0 }
76
80
};
77
81
 
78
82
static const int perm_table[2][8] = {
98
102
    }
99
103
};
100
104
 
101
 
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
102
 
                          int *access_index, target_ulong address, int rw,
103
 
                          int mmu_idx)
 
105
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 
106
                                int *prot, int *access_index,
 
107
                                target_ulong address, int rw, int mmu_idx)
104
108
{
105
109
    int access_perms = 0;
106
110
    target_phys_addr_t pde_ptr;
114
118
 
115
119
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
116
120
        // Boot mode: instruction fetches are taken from PROM
117
 
        if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
 
121
        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
118
122
            *physical = env->prom_addr | (address & 0x7ffffULL);
119
123
            *prot = PAGE_READ | PAGE_EXEC;
120
124
            return 0;
129
133
 
130
134
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
131
135
    /* Context base + context number */
132
 
    pde_ptr = ((env->mmuregs[1] & ~63)<< 4) + (env->mmuregs[2] << 2);
 
136
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
133
137
    pde = ldl_phys(pde_ptr);
134
138
 
135
139
    /* Ctx pde */
173
177
                    return (3 << 8) | (4 << 2);
174
178
                case 2: /* L3 PTE */
175
179
                    virt_addr = address & TARGET_PAGE_MASK;
176
 
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
 
180
                    page_offset = (address & TARGET_PAGE_MASK) &
 
181
                        (TARGET_PAGE_SIZE - 1);
177
182
                }
178
183
                break;
179
184
            case 2: /* L2 PTE */
223
228
    target_ulong vaddr;
224
229
    int error_code = 0, prot, ret = 0, access_index;
225
230
 
226
 
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
 
231
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
 
232
                                      address, rw, mmu_idx);
227
233
    if (error_code == 0) {
228
234
        vaddr = address & TARGET_PAGE_MASK;
229
235
        paddr &= TARGET_PAGE_MASK;
367
373
/*
368
374
 * UltraSparc IIi I/DMMUs
369
375
 */
370
 
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
371
 
                          int *access_index, target_ulong address, int rw,
372
 
                          int is_user)
 
376
static int get_physical_address_data(CPUState *env,
 
377
                                     target_phys_addr_t *physical, int *prot,
 
378
                                     target_ulong address, int rw, int is_user)
373
379
{
374
380
    target_ulong mask;
375
381
    unsigned int i;
396
402
            mask = 0xffffffffffc00000ULL;
397
403
            break;
398
404
        }
399
 
        // ctx match, vaddr match?
 
405
        // ctx match, vaddr match, valid?
400
406
        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
401
 
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
402
 
            // valid, access ok?
403
 
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
404
 
                ((env->dtlb_tte[i] & 0x4) && is_user) ||
 
407
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL) &&
 
408
            (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
 
409
            // access ok?
 
410
            if (((env->dtlb_tte[i] & 0x4) && is_user) ||
405
411
                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
406
412
                if (env->dmmuregs[3]) /* Fault status register */
407
 
                    env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
 
413
                    env->dmmuregs[3] = 2; /* overflow (not read before
 
414
                                             another fault) */
408
415
                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
409
416
                env->dmmuregs[4] = address; /* Fault address register */
410
417
                env->exception_index = TT_DFAULT;
413
420
#endif
414
421
                return 1;
415
422
            }
416
 
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
 
423
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
 
424
                (address & ~mask & 0x1fffffff000ULL);
417
425
            *prot = PAGE_READ;
418
426
            if (env->dtlb_tte[i] & 0x2)
419
427
                *prot |= PAGE_WRITE;
423
431
#ifdef DEBUG_MMU
424
432
    printf("DMISS at 0x%" PRIx64 "\n", address);
425
433
#endif
 
434
    env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
426
435
    env->exception_index = TT_DMISS;
427
436
    return 1;
428
437
}
429
438
 
430
 
static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
431
 
                          int *access_index, target_ulong address, int rw,
432
 
                          int is_user)
 
439
static int get_physical_address_code(CPUState *env,
 
440
                                     target_phys_addr_t *physical, int *prot,
 
441
                                     target_ulong address, int is_user)
433
442
{
434
443
    target_ulong mask;
435
444
    unsigned int i;
456
465
            mask = 0xffffffffffc00000ULL;
457
466
                break;
458
467
        }
459
 
        // ctx match, vaddr match?
 
468
        // ctx match, vaddr match, valid?
460
469
        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
461
 
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
462
 
            // valid, access ok?
463
 
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
464
 
                ((env->itlb_tte[i] & 0x4) && is_user)) {
 
470
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL) &&
 
471
            (env->itlb_tte[i] & 0x8000000000000000ULL)) {
 
472
            // access ok?
 
473
            if ((env->itlb_tte[i] & 0x4) && is_user) {
465
474
                if (env->immuregs[3]) /* Fault status register */
466
 
                    env->immuregs[3] = 2; /* overflow (not read before another fault) */
 
475
                    env->immuregs[3] = 2; /* overflow (not read before
 
476
                                             another fault) */
467
477
                env->immuregs[3] |= (is_user << 3) | 1;
468
478
                env->exception_index = TT_TFAULT;
469
479
#ifdef DEBUG_MMU
471
481
#endif
472
482
                return 1;
473
483
            }
474
 
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
 
484
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
 
485
                (address & ~mask & 0x1fffffff000ULL);
475
486
            *prot = PAGE_EXEC;
476
487
            return 0;
477
488
        }
479
490
#ifdef DEBUG_MMU
480
491
    printf("TMISS at 0x%" PRIx64 "\n", address);
481
492
#endif
 
493
    env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
482
494
    env->exception_index = TT_TMISS;
483
495
    return 1;
484
496
}
485
497
 
486
 
int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
487
 
                          int *access_index, target_ulong address, int rw,
488
 
                          int mmu_idx)
 
498
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 
499
                                int *prot, int *access_index,
 
500
                                target_ulong address, int rw, int mmu_idx)
489
501
{
490
502
    int is_user = mmu_idx == MMU_USER_IDX;
491
503
 
492
504
    if (rw == 2)
493
 
        return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
 
505
        return get_physical_address_code(env, physical, prot, address,
 
506
                                         is_user);
494
507
    else
495
 
        return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
 
508
        return get_physical_address_data(env, physical, prot, address, rw,
 
509
                                         is_user);
496
510
}
497
511
 
498
512
/* Perform address translation */
503
517
    target_phys_addr_t paddr;
504
518
    int error_code = 0, prot, ret = 0, access_index;
505
519
 
506
 
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
 
520
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
 
521
                                      address, rw, mmu_idx);
507
522
    if (error_code == 0) {
508
523
        virt_addr = address & TARGET_PAGE_MASK;
509
 
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
 
524
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
 
525
                             (TARGET_PAGE_SIZE - 1));
510
526
#ifdef DEBUG_MMU
511
 
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
 
527
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
 
528
               "\n", address, paddr, vaddr);
512
529
#endif
513
530
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
514
531
        return ret;
523
540
    unsigned int i;
524
541
    const char *mask;
525
542
 
526
 
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", env->dmmuregs[1], env->dmmuregs[2]);
 
543
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
 
544
           env->dmmuregs[1], env->dmmuregs[2]);
527
545
    if ((env->lsu & DMMU_E) == 0) {
528
546
        printf("DMMU disabled\n");
529
547
    } else {
545
563
                break;
546
564
            }
547
565
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
548
 
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
 
566
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
 
567
                       ", %s, %s, %s, %s, ctx %" PRId64 "\n",
549
568
                       env->dtlb_tag[i] & ~0x1fffULL,
550
569
                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
551
570
                       mask,
577
596
                break;
578
597
            }
579
598
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
580
 
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
 
599
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
 
600
                       ", %s, %s, %s, ctx %" PRId64 "\n",
581
601
                       env->itlb_tag[i] & ~0x1fffULL,
582
602
                       env->itlb_tte[i] & 0x1ffffffe000ULL,
583
603
                       mask,
593
613
#endif /* TARGET_SPARC64 */
594
614
#endif /* !CONFIG_USER_ONLY */
595
615
 
596
 
void memcpy32(target_ulong *dst, const target_ulong *src)
597
 
{
598
 
    dst[0] = src[0];
599
 
    dst[1] = src[1];
600
 
    dst[2] = src[2];
601
 
    dst[3] = src[3];
602
 
    dst[4] = src[4];
603
 
    dst[5] = src[5];
604
 
    dst[6] = src[6];
605
 
    dst[7] = src[7];
606
 
}
607
 
 
608
 
#ifdef TARGET_SPARC64
609
 
#if !defined(CONFIG_USER_ONLY)
610
 
#include "qemu-common.h"
611
 
#include "hw/irq.h"
612
 
#include "qemu-timer.h"
613
 
#endif
614
 
 
615
 
void do_tick_set_count(void *opaque, uint64_t count)
616
 
{
617
 
#if !defined(CONFIG_USER_ONLY)
618
 
    ptimer_set_count(opaque, -count);
619
 
#endif
620
 
}
621
 
 
622
 
uint64_t do_tick_get_count(void *opaque)
623
 
{
624
 
#if !defined(CONFIG_USER_ONLY)
625
 
    return -ptimer_get_count(opaque);
626
 
#else
627
 
    return 0;
628
 
#endif
629
 
}
630
 
 
631
 
void do_tick_set_limit(void *opaque, uint64_t limit)
632
 
{
633
 
#if !defined(CONFIG_USER_ONLY)
634
 
    ptimer_set_limit(opaque, -limit, 0);
635
 
#endif
636
 
}
637
 
#endif
 
616
 
 
617
#if defined(CONFIG_USER_ONLY)
 
618
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 
619
{
 
620
    return addr;
 
621
}
 
622
 
 
623
#else
 
624
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 
625
{
 
626
    target_phys_addr_t phys_addr;
 
627
    int prot, access_index;
 
628
 
 
629
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
 
630
                             MMU_KERNEL_IDX) != 0)
 
631
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
 
632
                                 0, MMU_KERNEL_IDX) != 0)
 
633
            return -1;
 
634
    if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
 
635
        return -1;
 
636
    return phys_addr;
 
637
}
 
638
#endif
 
639
 
 
640
void cpu_reset(CPUSPARCState *env)
 
641
{
 
642
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
 
643
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
 
644
        log_cpu_state(env, 0);
 
645
    }
 
646
 
 
647
    tlb_flush(env, 1);
 
648
    env->cwp = 0;
 
649
    env->wim = 1;
 
650
    env->regwptr = env->regbase + (env->cwp * 16);
 
651
#if defined(CONFIG_USER_ONLY)
 
652
#ifdef TARGET_SPARC64
 
653
    env->cleanwin = env->nwindows - 2;
 
654
    env->cansave = env->nwindows - 2;
 
655
    env->pstate = PS_RMO | PS_PEF | PS_IE;
 
656
    env->asi = 0x82; // Primary no-fault
 
657
#endif
 
658
#else
 
659
    env->psret = 0;
 
660
    env->psrs = 1;
 
661
    env->psrps = 1;
 
662
#ifdef TARGET_SPARC64
 
663
    env->pstate = PS_PRIV;
 
664
    env->hpstate = HS_PRIV;
 
665
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
 
666
    env->lsu = 0;
 
667
#else
 
668
    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
 
669
    env->mmuregs[0] |= env->def->mmu_bm;
 
670
#endif
 
671
    env->pc = 0;
 
672
    env->npc = env->pc + 4;
 
673
#endif
 
674
}
 
675
 
 
676
static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
 
677
{
 
678
    sparc_def_t def1, *def = &def1;
 
679
 
 
680
    if (cpu_sparc_find_by_name(def, cpu_model) < 0)
 
681
        return -1;
 
682
 
 
683
    env->def = qemu_mallocz(sizeof(*def));
 
684
    memcpy(env->def, def, sizeof(*def));
 
685
#if defined(CONFIG_USER_ONLY)
 
686
    if ((env->def->features & CPU_FEATURE_FLOAT))
 
687
        env->def->features |= CPU_FEATURE_FLOAT128;
 
688
#endif
 
689
    env->cpu_model_str = cpu_model;
 
690
    env->version = def->iu_version;
 
691
    env->fsr = def->fpu_version;
 
692
    env->nwindows = def->nwindows;
 
693
#if !defined(TARGET_SPARC64)
 
694
    env->mmuregs[0] |= def->mmu_version;
 
695
    cpu_sparc_set_id(env, 0);
 
696
    env->mxccregs[7] |= def->mxcc_version;
 
697
#else
 
698
    env->mmu_version = def->mmu_version;
 
699
    env->maxtl = def->maxtl;
 
700
    env->version |= def->maxtl << 8;
 
701
    env->version |= def->nwindows - 1;
 
702
#endif
 
703
    return 0;
 
704
}
 
705
 
 
706
static void cpu_sparc_close(CPUSPARCState *env)
 
707
{
 
708
    free(env->def);
 
709
    free(env);
 
710
}
 
711
 
 
712
CPUSPARCState *cpu_sparc_init(const char *cpu_model)
 
713
{
 
714
    CPUSPARCState *env;
 
715
 
 
716
    env = qemu_mallocz(sizeof(CPUSPARCState));
 
717
    cpu_exec_init(env);
 
718
 
 
719
    gen_intermediate_code_init(env);
 
720
 
 
721
    if (cpu_sparc_register(env, cpu_model) < 0) {
 
722
        cpu_sparc_close(env);
 
723
        return NULL;
 
724
    }
 
725
    cpu_reset(env);
 
726
 
 
727
    return env;
 
728
}
 
729
 
 
730
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
 
731
{
 
732
#if !defined(TARGET_SPARC64)
 
733
    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
 
734
#endif
 
735
}
 
736
 
 
737
static const sparc_def_t sparc_defs[] = {
 
738
#ifdef TARGET_SPARC64
 
739
    {
 
740
        .name = "Fujitsu Sparc64",
 
741
        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
 
742
        .fpu_version = 0x00000000,
 
743
        .mmu_version = mmu_us_12,
 
744
        .nwindows = 4,
 
745
        .maxtl = 4,
 
746
        .features = CPU_DEFAULT_FEATURES,
 
747
    },
 
748
    {
 
749
        .name = "Fujitsu Sparc64 III",
 
750
        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
 
751
        .fpu_version = 0x00000000,
 
752
        .mmu_version = mmu_us_12,
 
753
        .nwindows = 5,
 
754
        .maxtl = 4,
 
755
        .features = CPU_DEFAULT_FEATURES,
 
756
    },
 
757
    {
 
758
        .name = "Fujitsu Sparc64 IV",
 
759
        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
 
760
        .fpu_version = 0x00000000,
 
761
        .mmu_version = mmu_us_12,
 
762
        .nwindows = 8,
 
763
        .maxtl = 5,
 
764
        .features = CPU_DEFAULT_FEATURES,
 
765
    },
 
766
    {
 
767
        .name = "Fujitsu Sparc64 V",
 
768
        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
 
769
        .fpu_version = 0x00000000,
 
770
        .mmu_version = mmu_us_12,
 
771
        .nwindows = 8,
 
772
        .maxtl = 5,
 
773
        .features = CPU_DEFAULT_FEATURES,
 
774
    },
 
775
    {
 
776
        .name = "TI UltraSparc I",
 
777
        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
 
778
        .fpu_version = 0x00000000,
 
779
        .mmu_version = mmu_us_12,
 
780
        .nwindows = 8,
 
781
        .maxtl = 5,
 
782
        .features = CPU_DEFAULT_FEATURES,
 
783
    },
 
784
    {
 
785
        .name = "TI UltraSparc II",
 
786
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
 
787
        .fpu_version = 0x00000000,
 
788
        .mmu_version = mmu_us_12,
 
789
        .nwindows = 8,
 
790
        .maxtl = 5,
 
791
        .features = CPU_DEFAULT_FEATURES,
 
792
    },
 
793
    {
 
794
        .name = "TI UltraSparc IIi",
 
795
        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
 
796
        .fpu_version = 0x00000000,
 
797
        .mmu_version = mmu_us_12,
 
798
        .nwindows = 8,
 
799
        .maxtl = 5,
 
800
        .features = CPU_DEFAULT_FEATURES,
 
801
    },
 
802
    {
 
803
        .name = "TI UltraSparc IIe",
 
804
        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
 
805
        .fpu_version = 0x00000000,
 
806
        .mmu_version = mmu_us_12,
 
807
        .nwindows = 8,
 
808
        .maxtl = 5,
 
809
        .features = CPU_DEFAULT_FEATURES,
 
810
    },
 
811
    {
 
812
        .name = "Sun UltraSparc III",
 
813
        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
 
814
        .fpu_version = 0x00000000,
 
815
        .mmu_version = mmu_us_12,
 
816
        .nwindows = 8,
 
817
        .maxtl = 5,
 
818
        .features = CPU_DEFAULT_FEATURES,
 
819
    },
 
820
    {
 
821
        .name = "Sun UltraSparc III Cu",
 
822
        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
 
823
        .fpu_version = 0x00000000,
 
824
        .mmu_version = mmu_us_3,
 
825
        .nwindows = 8,
 
826
        .maxtl = 5,
 
827
        .features = CPU_DEFAULT_FEATURES,
 
828
    },
 
829
    {
 
830
        .name = "Sun UltraSparc IIIi",
 
831
        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
 
832
        .fpu_version = 0x00000000,
 
833
        .mmu_version = mmu_us_12,
 
834
        .nwindows = 8,
 
835
        .maxtl = 5,
 
836
        .features = CPU_DEFAULT_FEATURES,
 
837
    },
 
838
    {
 
839
        .name = "Sun UltraSparc IV",
 
840
        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
 
841
        .fpu_version = 0x00000000,
 
842
        .mmu_version = mmu_us_4,
 
843
        .nwindows = 8,
 
844
        .maxtl = 5,
 
845
        .features = CPU_DEFAULT_FEATURES,
 
846
    },
 
847
    {
 
848
        .name = "Sun UltraSparc IV+",
 
849
        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
 
850
        .fpu_version = 0x00000000,
 
851
        .mmu_version = mmu_us_12,
 
852
        .nwindows = 8,
 
853
        .maxtl = 5,
 
854
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
 
855
    },
 
856
    {
 
857
        .name = "Sun UltraSparc IIIi+",
 
858
        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
 
859
        .fpu_version = 0x00000000,
 
860
        .mmu_version = mmu_us_3,
 
861
        .nwindows = 8,
 
862
        .maxtl = 5,
 
863
        .features = CPU_DEFAULT_FEATURES,
 
864
    },
 
865
    {
 
866
        .name = "Sun UltraSparc T1",
 
867
        // defined in sparc_ifu_fdp.v and ctu.h
 
868
        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
 
869
        .fpu_version = 0x00000000,
 
870
        .mmu_version = mmu_sun4v,
 
871
        .nwindows = 8,
 
872
        .maxtl = 6,
 
873
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
 
874
        | CPU_FEATURE_GL,
 
875
    },
 
876
    {
 
877
        .name = "Sun UltraSparc T2",
 
878
        // defined in tlu_asi_ctl.v and n2_revid_cust.v
 
879
        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
 
880
        .fpu_version = 0x00000000,
 
881
        .mmu_version = mmu_sun4v,
 
882
        .nwindows = 8,
 
883
        .maxtl = 6,
 
884
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
 
885
        | CPU_FEATURE_GL,
 
886
    },
 
887
    {
 
888
        .name = "NEC UltraSparc I",
 
889
        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
 
890
        .fpu_version = 0x00000000,
 
891
        .mmu_version = mmu_us_12,
 
892
        .nwindows = 8,
 
893
        .maxtl = 5,
 
894
        .features = CPU_DEFAULT_FEATURES,
 
895
    },
 
896
#else
 
897
    {
 
898
        .name = "Fujitsu MB86900",
 
899
        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
 
900
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 
901
        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
 
902
        .mmu_bm = 0x00004000,
 
903
        .mmu_ctpr_mask = 0x007ffff0,
 
904
        .mmu_cxr_mask = 0x0000003f,
 
905
        .mmu_sfsr_mask = 0xffffffff,
 
906
        .mmu_trcr_mask = 0xffffffff,
 
907
        .nwindows = 7,
 
908
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
 
909
    },
 
910
    {
 
911
        .name = "Fujitsu MB86904",
 
912
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
 
913
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 
914
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
 
915
        .mmu_bm = 0x00004000,
 
916
        .mmu_ctpr_mask = 0x00ffffc0,
 
917
        .mmu_cxr_mask = 0x000000ff,
 
918
        .mmu_sfsr_mask = 0x00016fff,
 
919
        .mmu_trcr_mask = 0x00ffffff,
 
920
        .nwindows = 8,
 
921
        .features = CPU_DEFAULT_FEATURES,
 
922
    },
 
923
    {
 
924
        .name = "Fujitsu MB86907",
 
925
        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
 
926
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 
927
        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
 
928
        .mmu_bm = 0x00004000,
 
929
        .mmu_ctpr_mask = 0xffffffc0,
 
930
        .mmu_cxr_mask = 0x000000ff,
 
931
        .mmu_sfsr_mask = 0x00016fff,
 
932
        .mmu_trcr_mask = 0xffffffff,
 
933
        .nwindows = 8,
 
934
        .features = CPU_DEFAULT_FEATURES,
 
935
    },
 
936
    {
 
937
        .name = "LSI L64811",
 
938
        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
 
939
        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
 
940
        .mmu_version = 0x10 << 24,
 
941
        .mmu_bm = 0x00004000,
 
942
        .mmu_ctpr_mask = 0x007ffff0,
 
943
        .mmu_cxr_mask = 0x0000003f,
 
944
        .mmu_sfsr_mask = 0xffffffff,
 
945
        .mmu_trcr_mask = 0xffffffff,
 
946
        .nwindows = 8,
 
947
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
 
948
        CPU_FEATURE_FSMULD,
 
949
    },
 
950
    {
 
951
        .name = "Cypress CY7C601",
 
952
        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
 
953
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
 
954
        .mmu_version = 0x10 << 24,
 
955
        .mmu_bm = 0x00004000,
 
956
        .mmu_ctpr_mask = 0x007ffff0,
 
957
        .mmu_cxr_mask = 0x0000003f,
 
958
        .mmu_sfsr_mask = 0xffffffff,
 
959
        .mmu_trcr_mask = 0xffffffff,
 
960
        .nwindows = 8,
 
961
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
 
962
        CPU_FEATURE_FSMULD,
 
963
    },
 
964
    {
 
965
        .name = "Cypress CY7C611",
 
966
        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
 
967
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
 
968
        .mmu_version = 0x10 << 24,
 
969
        .mmu_bm = 0x00004000,
 
970
        .mmu_ctpr_mask = 0x007ffff0,
 
971
        .mmu_cxr_mask = 0x0000003f,
 
972
        .mmu_sfsr_mask = 0xffffffff,
 
973
        .mmu_trcr_mask = 0xffffffff,
 
974
        .nwindows = 8,
 
975
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
 
976
        CPU_FEATURE_FSMULD,
 
977
    },
 
978
    {
 
979
        .name = "TI MicroSparc I",
 
980
        .iu_version = 0x41000000,
 
981
        .fpu_version = 4 << 17,
 
982
        .mmu_version = 0x41000000,
 
983
        .mmu_bm = 0x00004000,
 
984
        .mmu_ctpr_mask = 0x007ffff0,
 
985
        .mmu_cxr_mask = 0x0000003f,
 
986
        .mmu_sfsr_mask = 0x00016fff,
 
987
        .mmu_trcr_mask = 0x0000003f,
 
988
        .nwindows = 7,
 
989
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
 
990
        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
 
991
        CPU_FEATURE_FMUL,
 
992
    },
 
993
    {
 
994
        .name = "TI MicroSparc II",
 
995
        .iu_version = 0x42000000,
 
996
        .fpu_version = 4 << 17,
 
997
        .mmu_version = 0x02000000,
 
998
        .mmu_bm = 0x00004000,
 
999
        .mmu_ctpr_mask = 0x00ffffc0,
 
1000
        .mmu_cxr_mask = 0x000000ff,
 
1001
        .mmu_sfsr_mask = 0x00016fff,
 
1002
        .mmu_trcr_mask = 0x00ffffff,
 
1003
        .nwindows = 8,
 
1004
        .features = CPU_DEFAULT_FEATURES,
 
1005
    },
 
1006
    {
 
1007
        .name = "TI MicroSparc IIep",
 
1008
        .iu_version = 0x42000000,
 
1009
        .fpu_version = 4 << 17,
 
1010
        .mmu_version = 0x04000000,
 
1011
        .mmu_bm = 0x00004000,
 
1012
        .mmu_ctpr_mask = 0x00ffffc0,
 
1013
        .mmu_cxr_mask = 0x000000ff,
 
1014
        .mmu_sfsr_mask = 0x00016bff,
 
1015
        .mmu_trcr_mask = 0x00ffffff,
 
1016
        .nwindows = 8,
 
1017
        .features = CPU_DEFAULT_FEATURES,
 
1018
    },
 
1019
    {
 
1020
        .name = "TI SuperSparc 40", // STP1020NPGA
 
1021
        .iu_version = 0x41000000, // SuperSPARC 2.x
 
1022
        .fpu_version = 0 << 17,
 
1023
        .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
 
1024
        .mmu_bm = 0x00002000,
 
1025
        .mmu_ctpr_mask = 0xffffffc0,
 
1026
        .mmu_cxr_mask = 0x0000ffff,
 
1027
        .mmu_sfsr_mask = 0xffffffff,
 
1028
        .mmu_trcr_mask = 0xffffffff,
 
1029
        .nwindows = 8,
 
1030
        .features = CPU_DEFAULT_FEATURES,
 
1031
    },
 
1032
    {
 
1033
        .name = "TI SuperSparc 50", // STP1020PGA
 
1034
        .iu_version = 0x40000000, // SuperSPARC 3.x
 
1035
        .fpu_version = 0 << 17,
 
1036
        .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
 
1037
        .mmu_bm = 0x00002000,
 
1038
        .mmu_ctpr_mask = 0xffffffc0,
 
1039
        .mmu_cxr_mask = 0x0000ffff,
 
1040
        .mmu_sfsr_mask = 0xffffffff,
 
1041
        .mmu_trcr_mask = 0xffffffff,
 
1042
        .nwindows = 8,
 
1043
        .features = CPU_DEFAULT_FEATURES,
 
1044
    },
 
1045
    {
 
1046
        .name = "TI SuperSparc 51",
 
1047
        .iu_version = 0x40000000, // SuperSPARC 3.x
 
1048
        .fpu_version = 0 << 17,
 
1049
        .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
 
1050
        .mmu_bm = 0x00002000,
 
1051
        .mmu_ctpr_mask = 0xffffffc0,
 
1052
        .mmu_cxr_mask = 0x0000ffff,
 
1053
        .mmu_sfsr_mask = 0xffffffff,
 
1054
        .mmu_trcr_mask = 0xffffffff,
 
1055
        .mxcc_version = 0x00000104,
 
1056
        .nwindows = 8,
 
1057
        .features = CPU_DEFAULT_FEATURES,
 
1058
    },
 
1059
    {
 
1060
        .name = "TI SuperSparc 60", // STP1020APGA
 
1061
        .iu_version = 0x40000000, // SuperSPARC 3.x
 
1062
        .fpu_version = 0 << 17,
 
1063
        .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
 
1064
        .mmu_bm = 0x00002000,
 
1065
        .mmu_ctpr_mask = 0xffffffc0,
 
1066
        .mmu_cxr_mask = 0x0000ffff,
 
1067
        .mmu_sfsr_mask = 0xffffffff,
 
1068
        .mmu_trcr_mask = 0xffffffff,
 
1069
        .nwindows = 8,
 
1070
        .features = CPU_DEFAULT_FEATURES,
 
1071
    },
 
1072
    {
 
1073
        .name = "TI SuperSparc 61",
 
1074
        .iu_version = 0x44000000, // SuperSPARC 3.x
 
1075
        .fpu_version = 0 << 17,
 
1076
        .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
 
1077
        .mmu_bm = 0x00002000,
 
1078
        .mmu_ctpr_mask = 0xffffffc0,
 
1079
        .mmu_cxr_mask = 0x0000ffff,
 
1080
        .mmu_sfsr_mask = 0xffffffff,
 
1081
        .mmu_trcr_mask = 0xffffffff,
 
1082
        .mxcc_version = 0x00000104,
 
1083
        .nwindows = 8,
 
1084
        .features = CPU_DEFAULT_FEATURES,
 
1085
    },
 
1086
    {
 
1087
        .name = "TI SuperSparc II",
 
1088
        .iu_version = 0x40000000, // SuperSPARC II 1.x
 
1089
        .fpu_version = 0 << 17,
 
1090
        .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
 
1091
        .mmu_bm = 0x00002000,
 
1092
        .mmu_ctpr_mask = 0xffffffc0,
 
1093
        .mmu_cxr_mask = 0x0000ffff,
 
1094
        .mmu_sfsr_mask = 0xffffffff,
 
1095
        .mmu_trcr_mask = 0xffffffff,
 
1096
        .mxcc_version = 0x00000104,
 
1097
        .nwindows = 8,
 
1098
        .features = CPU_DEFAULT_FEATURES,
 
1099
    },
 
1100
    {
 
1101
        .name = "Ross RT625",
 
1102
        .iu_version = 0x1e000000,
 
1103
        .fpu_version = 1 << 17,
 
1104
        .mmu_version = 0x1e000000,
 
1105
        .mmu_bm = 0x00004000,
 
1106
        .mmu_ctpr_mask = 0x007ffff0,
 
1107
        .mmu_cxr_mask = 0x0000003f,
 
1108
        .mmu_sfsr_mask = 0xffffffff,
 
1109
        .mmu_trcr_mask = 0xffffffff,
 
1110
        .nwindows = 8,
 
1111
        .features = CPU_DEFAULT_FEATURES,
 
1112
    },
 
1113
    {
 
1114
        .name = "Ross RT620",
 
1115
        .iu_version = 0x1f000000,
 
1116
        .fpu_version = 1 << 17,
 
1117
        .mmu_version = 0x1f000000,
 
1118
        .mmu_bm = 0x00004000,
 
1119
        .mmu_ctpr_mask = 0x007ffff0,
 
1120
        .mmu_cxr_mask = 0x0000003f,
 
1121
        .mmu_sfsr_mask = 0xffffffff,
 
1122
        .mmu_trcr_mask = 0xffffffff,
 
1123
        .nwindows = 8,
 
1124
        .features = CPU_DEFAULT_FEATURES,
 
1125
    },
 
1126
    {
 
1127
        .name = "BIT B5010",
 
1128
        .iu_version = 0x20000000,
 
1129
        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
 
1130
        .mmu_version = 0x20000000,
 
1131
        .mmu_bm = 0x00004000,
 
1132
        .mmu_ctpr_mask = 0x007ffff0,
 
1133
        .mmu_cxr_mask = 0x0000003f,
 
1134
        .mmu_sfsr_mask = 0xffffffff,
 
1135
        .mmu_trcr_mask = 0xffffffff,
 
1136
        .nwindows = 8,
 
1137
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
 
1138
        CPU_FEATURE_FSMULD,
 
1139
    },
 
1140
    {
 
1141
        .name = "Matsushita MN10501",
 
1142
        .iu_version = 0x50000000,
 
1143
        .fpu_version = 0 << 17,
 
1144
        .mmu_version = 0x50000000,
 
1145
        .mmu_bm = 0x00004000,
 
1146
        .mmu_ctpr_mask = 0x007ffff0,
 
1147
        .mmu_cxr_mask = 0x0000003f,
 
1148
        .mmu_sfsr_mask = 0xffffffff,
 
1149
        .mmu_trcr_mask = 0xffffffff,
 
1150
        .nwindows = 8,
 
1151
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
 
1152
        CPU_FEATURE_FSMULD,
 
1153
    },
 
1154
    {
 
1155
        .name = "Weitek W8601",
 
1156
        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
 
1157
        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
 
1158
        .mmu_version = 0x10 << 24,
 
1159
        .mmu_bm = 0x00004000,
 
1160
        .mmu_ctpr_mask = 0x007ffff0,
 
1161
        .mmu_cxr_mask = 0x0000003f,
 
1162
        .mmu_sfsr_mask = 0xffffffff,
 
1163
        .mmu_trcr_mask = 0xffffffff,
 
1164
        .nwindows = 8,
 
1165
        .features = CPU_DEFAULT_FEATURES,
 
1166
    },
 
1167
    {
 
1168
        .name = "LEON2",
 
1169
        .iu_version = 0xf2000000,
 
1170
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 
1171
        .mmu_version = 0xf2000000,
 
1172
        .mmu_bm = 0x00004000,
 
1173
        .mmu_ctpr_mask = 0x007ffff0,
 
1174
        .mmu_cxr_mask = 0x0000003f,
 
1175
        .mmu_sfsr_mask = 0xffffffff,
 
1176
        .mmu_trcr_mask = 0xffffffff,
 
1177
        .nwindows = 8,
 
1178
        .features = CPU_DEFAULT_FEATURES,
 
1179
    },
 
1180
    {
 
1181
        .name = "LEON3",
 
1182
        .iu_version = 0xf3000000,
 
1183
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 
1184
        .mmu_version = 0xf3000000,
 
1185
        .mmu_bm = 0x00004000,
 
1186
        .mmu_ctpr_mask = 0x007ffff0,
 
1187
        .mmu_cxr_mask = 0x0000003f,
 
1188
        .mmu_sfsr_mask = 0xffffffff,
 
1189
        .mmu_trcr_mask = 0xffffffff,
 
1190
        .nwindows = 8,
 
1191
        .features = CPU_DEFAULT_FEATURES,
 
1192
    },
 
1193
#endif
 
1194
};
 
1195
 
 
1196
static const char * const feature_name[] = {
 
1197
    "float",
 
1198
    "float128",
 
1199
    "swap",
 
1200
    "mul",
 
1201
    "div",
 
1202
    "flush",
 
1203
    "fsqrt",
 
1204
    "fmul",
 
1205
    "vis1",
 
1206
    "vis2",
 
1207
    "fsmuld",
 
1208
    "hypv",
 
1209
    "cmt",
 
1210
    "gl",
 
1211
};
 
1212
 
 
1213
static void print_features(FILE *f,
 
1214
                           int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
 
1215
                           uint32_t features, const char *prefix)
 
1216
{
 
1217
    unsigned int i;
 
1218
 
 
1219
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
 
1220
        if (feature_name[i] && (features & (1 << i))) {
 
1221
            if (prefix)
 
1222
                (*cpu_fprintf)(f, "%s", prefix);
 
1223
            (*cpu_fprintf)(f, "%s ", feature_name[i]);
 
1224
        }
 
1225
}
 
1226
 
 
1227
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
 
1228
{
 
1229
    unsigned int i;
 
1230
 
 
1231
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
 
1232
        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
 
1233
            *features |= 1 << i;
 
1234
            return;
 
1235
        }
 
1236
    fprintf(stderr, "CPU feature %s not found\n", flagname);
 
1237
}
 
1238
 
 
1239
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
 
1240
{
 
1241
    unsigned int i;
 
1242
    const sparc_def_t *def = NULL;
 
1243
    char *s = strdup(cpu_model);
 
1244
    char *featurestr, *name = strtok(s, ",");
 
1245
    uint32_t plus_features = 0;
 
1246
    uint32_t minus_features = 0;
 
1247
    long long iu_version;
 
1248
    uint32_t fpu_version, mmu_version, nwindows;
 
1249
 
 
1250
    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
 
1251
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
 
1252
            def = &sparc_defs[i];
 
1253
        }
 
1254
    }
 
1255
    if (!def)
 
1256
        goto error;
 
1257
    memcpy(cpu_def, def, sizeof(*def));
 
1258
 
 
1259
    featurestr = strtok(NULL, ",");
 
1260
    while (featurestr) {
 
1261
        char *val;
 
1262
 
 
1263
        if (featurestr[0] == '+') {
 
1264
            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
 
1265
        } else if (featurestr[0] == '-') {
 
1266
            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
 
1267
        } else if ((val = strchr(featurestr, '='))) {
 
1268
            *val = 0; val++;
 
1269
            if (!strcmp(featurestr, "iu_version")) {
 
1270
                char *err;
 
1271
 
 
1272
                iu_version = strtoll(val, &err, 0);
 
1273
                if (!*val || *err) {
 
1274
                    fprintf(stderr, "bad numerical value %s\n", val);
 
1275
                    goto error;
 
1276
                }
 
1277
                cpu_def->iu_version = iu_version;
 
1278
#ifdef DEBUG_FEATURES
 
1279
                fprintf(stderr, "iu_version %llx\n", iu_version);
 
1280
#endif
 
1281
            } else if (!strcmp(featurestr, "fpu_version")) {
 
1282
                char *err;
 
1283
 
 
1284
                fpu_version = strtol(val, &err, 0);
 
1285
                if (!*val || *err) {
 
1286
                    fprintf(stderr, "bad numerical value %s\n", val);
 
1287
                    goto error;
 
1288
                }
 
1289
                cpu_def->fpu_version = fpu_version;
 
1290
#ifdef DEBUG_FEATURES
 
1291
                fprintf(stderr, "fpu_version %llx\n", fpu_version);
 
1292
#endif
 
1293
            } else if (!strcmp(featurestr, "mmu_version")) {
 
1294
                char *err;
 
1295
 
 
1296
                mmu_version = strtol(val, &err, 0);
 
1297
                if (!*val || *err) {
 
1298
                    fprintf(stderr, "bad numerical value %s\n", val);
 
1299
                    goto error;
 
1300
                }
 
1301
                cpu_def->mmu_version = mmu_version;
 
1302
#ifdef DEBUG_FEATURES
 
1303
                fprintf(stderr, "mmu_version %llx\n", mmu_version);
 
1304
#endif
 
1305
            } else if (!strcmp(featurestr, "nwindows")) {
 
1306
                char *err;
 
1307
 
 
1308
                nwindows = strtol(val, &err, 0);
 
1309
                if (!*val || *err || nwindows > MAX_NWINDOWS ||
 
1310
                    nwindows < MIN_NWINDOWS) {
 
1311
                    fprintf(stderr, "bad numerical value %s\n", val);
 
1312
                    goto error;
 
1313
                }
 
1314
                cpu_def->nwindows = nwindows;
 
1315
#ifdef DEBUG_FEATURES
 
1316
                fprintf(stderr, "nwindows %d\n", nwindows);
 
1317
#endif
 
1318
            } else {
 
1319
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
 
1320
                goto error;
 
1321
            }
 
1322
        } else {
 
1323
            fprintf(stderr, "feature string `%s' not in format "
 
1324
                    "(+feature|-feature|feature=xyz)\n", featurestr);
 
1325
            goto error;
 
1326
        }
 
1327
        featurestr = strtok(NULL, ",");
 
1328
    }
 
1329
    cpu_def->features |= plus_features;
 
1330
    cpu_def->features &= ~minus_features;
 
1331
#ifdef DEBUG_FEATURES
 
1332
    print_features(stderr, fprintf, cpu_def->features, NULL);
 
1333
#endif
 
1334
    free(s);
 
1335
    return 0;
 
1336
 
 
1337
 error:
 
1338
    free(s);
 
1339
    return -1;
 
1340
}
 
1341
 
 
1342
void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 
1343
{
 
1344
    unsigned int i;
 
1345
 
 
1346
    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
 
1347
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
 
1348
                       sparc_defs[i].name,
 
1349
                       sparc_defs[i].iu_version,
 
1350
                       sparc_defs[i].fpu_version,
 
1351
                       sparc_defs[i].mmu_version,
 
1352
                       sparc_defs[i].nwindows);
 
1353
        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
 
1354
                       ~sparc_defs[i].features, "-");
 
1355
        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
 
1356
                       sparc_defs[i].features, "+");
 
1357
        (*cpu_fprintf)(f, "\n");
 
1358
    }
 
1359
    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
 
1360
    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
 
1361
    (*cpu_fprintf)(f, "\n");
 
1362
    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
 
1363
    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
 
1364
    (*cpu_fprintf)(f, "\n");
 
1365
    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
 
1366
                   "fpu_version mmu_version nwindows\n");
 
1367
}
 
1368
 
 
1369
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
 
1370
 
 
1371
void cpu_dump_state(CPUState *env, FILE *f,
 
1372
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
 
1373
                    int flags)
 
1374
{
 
1375
    int i, x;
 
1376
 
 
1377
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
 
1378
                env->npc);
 
1379
    cpu_fprintf(f, "General Registers:\n");
 
1380
    for (i = 0; i < 4; i++)
 
1381
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
 
1382
    cpu_fprintf(f, "\n");
 
1383
    for (; i < 8; i++)
 
1384
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
 
1385
    cpu_fprintf(f, "\nCurrent Register Window:\n");
 
1386
    for (x = 0; x < 3; x++) {
 
1387
        for (i = 0; i < 4; i++)
 
1388
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
 
1389
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
 
1390
                    env->regwptr[i + x * 8]);
 
1391
        cpu_fprintf(f, "\n");
 
1392
        for (; i < 8; i++)
 
1393
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
 
1394
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
 
1395
                    env->regwptr[i + x * 8]);
 
1396
        cpu_fprintf(f, "\n");
 
1397
    }
 
1398
    cpu_fprintf(f, "\nFloating Point Registers:\n");
 
1399
    for (i = 0; i < 32; i++) {
 
1400
        if ((i & 3) == 0)
 
1401
            cpu_fprintf(f, "%%f%02d:", i);
 
1402
        cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
 
1403
        if ((i & 3) == 3)
 
1404
            cpu_fprintf(f, "\n");
 
1405
    }
 
1406
#ifdef TARGET_SPARC64
 
1407
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
 
1408
                env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
 
1409
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
 
1410
                "cleanwin %d cwp %d\n",
 
1411
                env->cansave, env->canrestore, env->otherwin, env->wstate,
 
1412
                env->cleanwin, env->nwindows - 1 - env->cwp);
 
1413
#else
 
1414
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
 
1415
                GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
 
1416
                GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
 
1417
                env->psrs?'S':'-', env->psrps?'P':'-',
 
1418
                env->psret?'E':'-', env->wim);
 
1419
#endif
 
1420
    cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
 
1421
}