Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ 91736d37

History | View | Annotate | Download (45.1 kB)

1
/*
2
 *  sparc helpers
3
 *
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
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
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
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <signal.h>
26
#include <assert.h>
27

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "qemu-common.h"
31

    
32
//#define DEBUG_MMU
33
//#define DEBUG_FEATURES
34
//#define DEBUG_PCALL
35

    
36
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
37

    
38
/* Sparc MMU emulation */
39

    
40
/* thread support */
41

    
42
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
43

    
44
void cpu_lock(void)
45
{
46
    spin_lock(&global_cpu_lock);
47
}
48

    
49
void cpu_unlock(void)
50
{
51
    spin_unlock(&global_cpu_lock);
52
}
53

    
54
#if defined(CONFIG_USER_ONLY)
55

    
56
int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
57
                               int mmu_idx, int is_softmmu)
58
{
59
    if (rw & 2)
60
        env1->exception_index = TT_TFAULT;
61
    else
62
        env1->exception_index = TT_DFAULT;
63
    return 1;
64
}
65

    
66
#else
67

    
68
#ifndef TARGET_SPARC64
69
/*
70
 * Sparc V8 Reference MMU (SRMMU)
71
 */
72
static const int access_table[8][8] = {
73
    { 0, 0, 0, 0, 8, 0, 12, 12 },
74
    { 0, 0, 0, 0, 8, 0, 0, 0 },
75
    { 8, 8, 0, 0, 0, 8, 12, 12 },
76
    { 8, 8, 0, 0, 0, 8, 0, 0 },
77
    { 8, 0, 8, 0, 8, 8, 12, 12 },
78
    { 8, 0, 8, 0, 8, 0, 8, 0 },
79
    { 8, 8, 8, 0, 8, 8, 12, 12 },
80
    { 8, 8, 8, 0, 8, 8, 8, 0 }
81
};
82

    
83
static const int perm_table[2][8] = {
84
    {
85
        PAGE_READ,
86
        PAGE_READ | PAGE_WRITE,
87
        PAGE_READ | PAGE_EXEC,
88
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
89
        PAGE_EXEC,
90
        PAGE_READ | PAGE_WRITE,
91
        PAGE_READ | PAGE_EXEC,
92
        PAGE_READ | PAGE_WRITE | PAGE_EXEC
93
    },
94
    {
95
        PAGE_READ,
96
        PAGE_READ | PAGE_WRITE,
97
        PAGE_READ | PAGE_EXEC,
98
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
99
        PAGE_EXEC,
100
        PAGE_READ,
101
        0,
102
        0,
103
    }
104
};
105

    
106
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
107
                                int *prot, int *access_index,
108
                                target_ulong address, int rw, int mmu_idx)
109
{
110
    int access_perms = 0;
111
    target_phys_addr_t pde_ptr;
112
    uint32_t pde;
113
    target_ulong virt_addr;
114
    int error_code = 0, is_dirty, is_user;
115
    unsigned long page_offset;
116

    
117
    is_user = mmu_idx == MMU_USER_IDX;
118
    virt_addr = address & TARGET_PAGE_MASK;
119

    
120
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
121
        // Boot mode: instruction fetches are taken from PROM
122
        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
123
            *physical = env->prom_addr | (address & 0x7ffffULL);
124
            *prot = PAGE_READ | PAGE_EXEC;
125
            return 0;
126
        }
127
        *physical = address;
128
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
129
        return 0;
130
    }
131

    
132
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
133
    *physical = 0xffffffffffff0000ULL;
134

    
135
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
136
    /* Context base + context number */
137
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
138
    pde = ldl_phys(pde_ptr);
139

    
140
    /* Ctx pde */
141
    switch (pde & PTE_ENTRYTYPE_MASK) {
142
    default:
143
    case 0: /* Invalid */
144
        return 1 << 2;
145
    case 2: /* L0 PTE, maybe should not happen? */
146
    case 3: /* Reserved */
147
        return 4 << 2;
148
    case 1: /* L0 PDE */
149
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
150
        pde = ldl_phys(pde_ptr);
151

    
152
        switch (pde & PTE_ENTRYTYPE_MASK) {
153
        default:
154
        case 0: /* Invalid */
155
            return (1 << 8) | (1 << 2);
156
        case 3: /* Reserved */
157
            return (1 << 8) | (4 << 2);
158
        case 1: /* L1 PDE */
159
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
160
            pde = ldl_phys(pde_ptr);
161

    
162
            switch (pde & PTE_ENTRYTYPE_MASK) {
163
            default:
164
            case 0: /* Invalid */
165
                return (2 << 8) | (1 << 2);
166
            case 3: /* Reserved */
167
                return (2 << 8) | (4 << 2);
168
            case 1: /* L2 PDE */
169
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
170
                pde = ldl_phys(pde_ptr);
171

    
172
                switch (pde & PTE_ENTRYTYPE_MASK) {
173
                default:
174
                case 0: /* Invalid */
175
                    return (3 << 8) | (1 << 2);
176
                case 1: /* PDE, should not happen */
177
                case 3: /* Reserved */
178
                    return (3 << 8) | (4 << 2);
179
                case 2: /* L3 PTE */
180
                    virt_addr = address & TARGET_PAGE_MASK;
181
                    page_offset = (address & TARGET_PAGE_MASK) &
182
                        (TARGET_PAGE_SIZE - 1);
183
                }
184
                break;
185
            case 2: /* L2 PTE */
186
                virt_addr = address & ~0x3ffff;
187
                page_offset = address & 0x3ffff;
188
            }
189
            break;
190
        case 2: /* L1 PTE */
191
            virt_addr = address & ~0xffffff;
192
            page_offset = address & 0xffffff;
193
        }
194
    }
195

    
196
    /* update page modified and dirty bits */
197
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
198
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
199
        pde |= PG_ACCESSED_MASK;
200
        if (is_dirty)
201
            pde |= PG_MODIFIED_MASK;
202
        stl_phys_notdirty(pde_ptr, pde);
203
    }
204
    /* check access */
205
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
206
    error_code = access_table[*access_index][access_perms];
207
    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
208
        return error_code;
209

    
210
    /* the page can be put in the TLB */
211
    *prot = perm_table[is_user][access_perms];
212
    if (!(pde & PG_MODIFIED_MASK)) {
213
        /* only set write access if already dirty... otherwise wait
214
           for dirty access */
215
        *prot &= ~PAGE_WRITE;
216
    }
217

    
218
    /* Even if large ptes, we map only one 4KB page in the cache to
219
       avoid filling it too fast */
220
    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
221
    return error_code;
222
}
223

    
224
/* Perform address translation */
225
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
226
                              int mmu_idx, int is_softmmu)
227
{
228
    target_phys_addr_t paddr;
229
    target_ulong vaddr;
230
    int error_code = 0, prot, ret = 0, access_index;
231

    
232
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
233
                                      address, rw, mmu_idx);
234
    if (error_code == 0) {
235
        vaddr = address & TARGET_PAGE_MASK;
236
        paddr &= TARGET_PAGE_MASK;
237
#ifdef DEBUG_MMU
238
        printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
239
               TARGET_FMT_lx "\n", address, paddr, vaddr);
240
#endif
241
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
242
        return ret;
243
    }
244

    
245
    if (env->mmuregs[3]) /* Fault status register */
246
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
247
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
248
    env->mmuregs[4] = address; /* Fault address register */
249

    
250
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
251
        // No fault mode: if a mapping is available, just override
252
        // permissions. If no mapping is available, redirect accesses to
253
        // neverland. Fake/overridden mappings will be flushed when
254
        // switching to normal mode.
255
        vaddr = address & TARGET_PAGE_MASK;
256
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
257
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
258
        return ret;
259
    } else {
260
        if (rw & 2)
261
            env->exception_index = TT_TFAULT;
262
        else
263
            env->exception_index = TT_DFAULT;
264
        return 1;
265
    }
266
}
267

    
268
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
269
{
270
    target_phys_addr_t pde_ptr;
271
    uint32_t pde;
272

    
273
    /* Context base + context number */
274
    pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
275
        (env->mmuregs[2] << 2);
276
    pde = ldl_phys(pde_ptr);
277

    
278
    switch (pde & PTE_ENTRYTYPE_MASK) {
279
    default:
280
    case 0: /* Invalid */
281
    case 2: /* PTE, maybe should not happen? */
282
    case 3: /* Reserved */
283
        return 0;
284
    case 1: /* L1 PDE */
285
        if (mmulev == 3)
286
            return pde;
287
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
288
        pde = ldl_phys(pde_ptr);
289

    
290
        switch (pde & PTE_ENTRYTYPE_MASK) {
291
        default:
292
        case 0: /* Invalid */
293
        case 3: /* Reserved */
294
            return 0;
295
        case 2: /* L1 PTE */
296
            return pde;
297
        case 1: /* L2 PDE */
298
            if (mmulev == 2)
299
                return pde;
300
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
301
            pde = ldl_phys(pde_ptr);
302

    
303
            switch (pde & PTE_ENTRYTYPE_MASK) {
304
            default:
305
            case 0: /* Invalid */
306
            case 3: /* Reserved */
307
                return 0;
308
            case 2: /* L2 PTE */
309
                return pde;
310
            case 1: /* L3 PDE */
311
                if (mmulev == 1)
312
                    return pde;
313
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
314
                pde = ldl_phys(pde_ptr);
315

    
316
                switch (pde & PTE_ENTRYTYPE_MASK) {
317
                default:
318
                case 0: /* Invalid */
319
                case 1: /* PDE, should not happen */
320
                case 3: /* Reserved */
321
                    return 0;
322
                case 2: /* L3 PTE */
323
                    return pde;
324
                }
325
            }
326
        }
327
    }
328
    return 0;
329
}
330

    
331
#ifdef DEBUG_MMU
332
void dump_mmu(CPUState *env)
333
{
334
    target_ulong va, va1, va2;
335
    unsigned int n, m, o;
336
    target_phys_addr_t pde_ptr, pa;
337
    uint32_t pde;
338

    
339
    printf("MMU dump:\n");
340
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
341
    pde = ldl_phys(pde_ptr);
342
    printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
343
           (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
344
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
345
        pde = mmu_probe(env, va, 2);
346
        if (pde) {
347
            pa = cpu_get_phys_page_debug(env, va);
348
            printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
349
                   " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
350
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
351
                pde = mmu_probe(env, va1, 1);
352
                if (pde) {
353
                    pa = cpu_get_phys_page_debug(env, va1);
354
                    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
355
                           " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
356
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
357
                        pde = mmu_probe(env, va2, 0);
358
                        if (pde) {
359
                            pa = cpu_get_phys_page_debug(env, va2);
360
                            printf("  VA: " TARGET_FMT_lx ", PA: "
361
                                   TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
362
                                   va2, pa, pde);
363
                        }
364
                    }
365
                }
366
            }
367
        }
368
    }
369
    printf("MMU dump ends\n");
370
}
371
#endif /* DEBUG_MMU */
372

    
373
#else /* !TARGET_SPARC64 */
374
/*
375
 * UltraSparc IIi I/DMMUs
376
 */
377
static int get_physical_address_data(CPUState *env,
378
                                     target_phys_addr_t *physical, int *prot,
379
                                     target_ulong address, int rw, int is_user)
380
{
381
    target_ulong mask;
382
    unsigned int i;
383

    
384
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
385
        *physical = address;
386
        *prot = PAGE_READ | PAGE_WRITE;
387
        return 0;
388
    }
389

    
390
    for (i = 0; i < 64; i++) {
391
        switch ((env->dtlb_tte[i] >> 61) & 3) {
392
        default:
393
        case 0x0: // 8k
394
            mask = 0xffffffffffffe000ULL;
395
            break;
396
        case 0x1: // 64k
397
            mask = 0xffffffffffff0000ULL;
398
            break;
399
        case 0x2: // 512k
400
            mask = 0xfffffffffff80000ULL;
401
            break;
402
        case 0x3: // 4M
403
            mask = 0xffffffffffc00000ULL;
404
            break;
405
        }
406
        // ctx match, vaddr match?
407
        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
408
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
409
            // valid, access ok?
410
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
411
                ((env->dtlb_tte[i] & 0x4) && is_user) ||
412
                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
413
                if (env->dmmuregs[3]) /* Fault status register */
414
                    env->dmmuregs[3] = 2; /* overflow (not read before
415
                                             another fault) */
416
                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
417
                env->dmmuregs[4] = address; /* Fault address register */
418
                env->exception_index = TT_DFAULT;
419
#ifdef DEBUG_MMU
420
                printf("DFAULT at 0x%" PRIx64 "\n", address);
421
#endif
422
                return 1;
423
            }
424
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
425
                (address & ~mask & 0x1fffffff000ULL);
426
            *prot = PAGE_READ;
427
            if (env->dtlb_tte[i] & 0x2)
428
                *prot |= PAGE_WRITE;
429
            return 0;
430
        }
431
    }
432
#ifdef DEBUG_MMU
433
    printf("DMISS at 0x%" PRIx64 "\n", address);
434
#endif
435
    env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
436
    env->exception_index = TT_DMISS;
437
    return 1;
438
}
439

    
440
static int get_physical_address_code(CPUState *env,
441
                                     target_phys_addr_t *physical, int *prot,
442
                                     target_ulong address, int is_user)
443
{
444
    target_ulong mask;
445
    unsigned int i;
446

    
447
    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
448
        *physical = address;
449
        *prot = PAGE_EXEC;
450
        return 0;
451
    }
452

    
453
    for (i = 0; i < 64; i++) {
454
        switch ((env->itlb_tte[i] >> 61) & 3) {
455
        default:
456
        case 0x0: // 8k
457
            mask = 0xffffffffffffe000ULL;
458
            break;
459
        case 0x1: // 64k
460
            mask = 0xffffffffffff0000ULL;
461
            break;
462
        case 0x2: // 512k
463
            mask = 0xfffffffffff80000ULL;
464
            break;
465
        case 0x3: // 4M
466
            mask = 0xffffffffffc00000ULL;
467
                break;
468
        }
469
        // ctx match, vaddr match?
470
        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
471
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
472
            // valid, access ok?
473
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
474
                ((env->itlb_tte[i] & 0x4) && is_user)) {
475
                if (env->immuregs[3]) /* Fault status register */
476
                    env->immuregs[3] = 2; /* overflow (not read before
477
                                             another fault) */
478
                env->immuregs[3] |= (is_user << 3) | 1;
479
                env->exception_index = TT_TFAULT;
480
#ifdef DEBUG_MMU
481
                printf("TFAULT at 0x%" PRIx64 "\n", address);
482
#endif
483
                return 1;
484
            }
485
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
486
                (address & ~mask & 0x1fffffff000ULL);
487
            *prot = PAGE_EXEC;
488
            return 0;
489
        }
490
    }
491
#ifdef DEBUG_MMU
492
    printf("TMISS at 0x%" PRIx64 "\n", address);
493
#endif
494
    env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
495
    env->exception_index = TT_TMISS;
496
    return 1;
497
}
498

    
499
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
500
                                int *prot, int *access_index,
501
                                target_ulong address, int rw, int mmu_idx)
502
{
503
    int is_user = mmu_idx == MMU_USER_IDX;
504

    
505
    if (rw == 2)
506
        return get_physical_address_code(env, physical, prot, address,
507
                                         is_user);
508
    else
509
        return get_physical_address_data(env, physical, prot, address, rw,
510
                                         is_user);
511
}
512

    
513
/* Perform address translation */
514
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
515
                              int mmu_idx, int is_softmmu)
516
{
517
    target_ulong virt_addr, vaddr;
518
    target_phys_addr_t paddr;
519
    int error_code = 0, prot, ret = 0, access_index;
520

    
521
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
522
                                      address, rw, mmu_idx);
523
    if (error_code == 0) {
524
        virt_addr = address & TARGET_PAGE_MASK;
525
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
526
                             (TARGET_PAGE_SIZE - 1));
527
#ifdef DEBUG_MMU
528
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
529
               "\n", address, paddr, vaddr);
530
#endif
531
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
532
        return ret;
533
    }
534
    // XXX
535
    return 1;
536
}
537

    
538
#ifdef DEBUG_MMU
539
void dump_mmu(CPUState *env)
540
{
541
    unsigned int i;
542
    const char *mask;
543

    
544
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
545
           env->dmmuregs[1], env->dmmuregs[2]);
546
    if ((env->lsu & DMMU_E) == 0) {
547
        printf("DMMU disabled\n");
548
    } else {
549
        printf("DMMU dump:\n");
550
        for (i = 0; i < 64; i++) {
551
            switch ((env->dtlb_tte[i] >> 61) & 3) {
552
            default:
553
            case 0x0:
554
                mask = "  8k";
555
                break;
556
            case 0x1:
557
                mask = " 64k";
558
                break;
559
            case 0x2:
560
                mask = "512k";
561
                break;
562
            case 0x3:
563
                mask = "  4M";
564
                break;
565
            }
566
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
567
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
568
                       ", %s, %s, %s, %s, ctx %" PRId64 "\n",
569
                       env->dtlb_tag[i] & ~0x1fffULL,
570
                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
571
                       mask,
572
                       env->dtlb_tte[i] & 0x4? "priv": "user",
573
                       env->dtlb_tte[i] & 0x2? "RW": "RO",
574
                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
575
                       env->dtlb_tag[i] & 0x1fffULL);
576
            }
577
        }
578
    }
579
    if ((env->lsu & IMMU_E) == 0) {
580
        printf("IMMU disabled\n");
581
    } else {
582
        printf("IMMU dump:\n");
583
        for (i = 0; i < 64; i++) {
584
            switch ((env->itlb_tte[i] >> 61) & 3) {
585
            default:
586
            case 0x0:
587
                mask = "  8k";
588
                break;
589
            case 0x1:
590
                mask = " 64k";
591
                break;
592
            case 0x2:
593
                mask = "512k";
594
                break;
595
            case 0x3:
596
                mask = "  4M";
597
                break;
598
            }
599
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
600
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
601
                       ", %s, %s, %s, ctx %" PRId64 "\n",
602
                       env->itlb_tag[i] & ~0x1fffULL,
603
                       env->itlb_tte[i] & 0x1ffffffe000ULL,
604
                       mask,
605
                       env->itlb_tte[i] & 0x4? "priv": "user",
606
                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
607
                       env->itlb_tag[i] & 0x1fffULL);
608
            }
609
        }
610
    }
611
}
612
#endif /* DEBUG_MMU */
613

    
614
#endif /* TARGET_SPARC64 */
615
#endif /* !CONFIG_USER_ONLY */
616

    
617

    
618
#if defined(CONFIG_USER_ONLY)
619
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
620
{
621
    return addr;
622
}
623

    
624
#else
625
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
626
{
627
    target_phys_addr_t phys_addr;
628
    int prot, access_index;
629

    
630
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
631
                             MMU_KERNEL_IDX) != 0)
632
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
633
                                 0, MMU_KERNEL_IDX) != 0)
634
            return -1;
635
    if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
636
        return -1;
637
    return phys_addr;
638
}
639
#endif
640

    
641
void cpu_reset(CPUSPARCState *env)
642
{
643
    tlb_flush(env, 1);
644
    env->cwp = 0;
645
    env->wim = 1;
646
    env->regwptr = env->regbase + (env->cwp * 16);
647
#if defined(CONFIG_USER_ONLY)
648
    env->user_mode_only = 1;
649
#ifdef TARGET_SPARC64
650
    env->cleanwin = env->nwindows - 2;
651
    env->cansave = env->nwindows - 2;
652
    env->pstate = PS_RMO | PS_PEF | PS_IE;
653
    env->asi = 0x82; // Primary no-fault
654
#endif
655
#else
656
    env->psret = 0;
657
    env->psrs = 1;
658
    env->psrps = 1;
659
#ifdef TARGET_SPARC64
660
    env->pstate = PS_PRIV;
661
    env->hpstate = HS_PRIV;
662
    env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset
663
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
664
#else
665
    env->pc = 0;
666
    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
667
    env->mmuregs[0] |= env->def->mmu_bm;
668
#endif
669
    env->npc = env->pc + 4;
670
#endif
671
}
672

    
673
static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
674
{
675
    sparc_def_t def1, *def = &def1;
676

    
677
    if (cpu_sparc_find_by_name(def, cpu_model) < 0)
678
        return -1;
679

    
680
    env->def = qemu_mallocz(sizeof(*def));
681
    memcpy(env->def, def, sizeof(*def));
682
#if defined(CONFIG_USER_ONLY)
683
    if ((env->def->features & CPU_FEATURE_FLOAT))
684
        env->def->features |= CPU_FEATURE_FLOAT128;
685
#endif
686
    env->cpu_model_str = cpu_model;
687
    env->version = def->iu_version;
688
    env->fsr = def->fpu_version;
689
    env->nwindows = def->nwindows;
690
#if !defined(TARGET_SPARC64)
691
    env->mmuregs[0] |= def->mmu_version;
692
    cpu_sparc_set_id(env, 0);
693
#else
694
    env->mmu_version = def->mmu_version;
695
    env->maxtl = def->maxtl;
696
    env->version |= def->maxtl << 8;
697
    env->version |= def->nwindows - 1;
698
#endif
699
    return 0;
700
}
701

    
702
static void cpu_sparc_close(CPUSPARCState *env)
703
{
704
    free(env->def);
705
    free(env);
706
}
707

    
708
CPUSPARCState *cpu_sparc_init(const char *cpu_model)
709
{
710
    CPUSPARCState *env;
711

    
712
    env = qemu_mallocz(sizeof(CPUSPARCState));
713
    if (!env)
714
        return NULL;
715
    cpu_exec_init(env);
716

    
717
    gen_intermediate_code_init(env);
718

    
719
    if (cpu_sparc_register(env, cpu_model) < 0) {
720
        cpu_sparc_close(env);
721
        return NULL;
722
    }
723
    cpu_reset(env);
724

    
725
    return env;
726
}
727

    
728
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
729
{
730
#if !defined(TARGET_SPARC64)
731
    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
732
#endif
733
}
734

    
735
static const sparc_def_t sparc_defs[] = {
736
#ifdef TARGET_SPARC64
737
    {
738
        .name = "Fujitsu Sparc64",
739
        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
740
        .fpu_version = 0x00000000,
741
        .mmu_version = mmu_us_12,
742
        .nwindows = 4,
743
        .maxtl = 4,
744
        .features = CPU_DEFAULT_FEATURES,
745
    },
746
    {
747
        .name = "Fujitsu Sparc64 III",
748
        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
749
        .fpu_version = 0x00000000,
750
        .mmu_version = mmu_us_12,
751
        .nwindows = 5,
752
        .maxtl = 4,
753
        .features = CPU_DEFAULT_FEATURES,
754
    },
755
    {
756
        .name = "Fujitsu Sparc64 IV",
757
        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
758
        .fpu_version = 0x00000000,
759
        .mmu_version = mmu_us_12,
760
        .nwindows = 8,
761
        .maxtl = 5,
762
        .features = CPU_DEFAULT_FEATURES,
763
    },
764
    {
765
        .name = "Fujitsu Sparc64 V",
766
        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
767
        .fpu_version = 0x00000000,
768
        .mmu_version = mmu_us_12,
769
        .nwindows = 8,
770
        .maxtl = 5,
771
        .features = CPU_DEFAULT_FEATURES,
772
    },
773
    {
774
        .name = "TI UltraSparc I",
775
        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
776
        .fpu_version = 0x00000000,
777
        .mmu_version = mmu_us_12,
778
        .nwindows = 8,
779
        .maxtl = 5,
780
        .features = CPU_DEFAULT_FEATURES,
781
    },
782
    {
783
        .name = "TI UltraSparc II",
784
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
785
        .fpu_version = 0x00000000,
786
        .mmu_version = mmu_us_12,
787
        .nwindows = 8,
788
        .maxtl = 5,
789
        .features = CPU_DEFAULT_FEATURES,
790
    },
791
    {
792
        .name = "TI UltraSparc IIi",
793
        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
794
        .fpu_version = 0x00000000,
795
        .mmu_version = mmu_us_12,
796
        .nwindows = 8,
797
        .maxtl = 5,
798
        .features = CPU_DEFAULT_FEATURES,
799
    },
800
    {
801
        .name = "TI UltraSparc IIe",
802
        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
803
        .fpu_version = 0x00000000,
804
        .mmu_version = mmu_us_12,
805
        .nwindows = 8,
806
        .maxtl = 5,
807
        .features = CPU_DEFAULT_FEATURES,
808
    },
809
    {
810
        .name = "Sun UltraSparc III",
811
        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
812
        .fpu_version = 0x00000000,
813
        .mmu_version = mmu_us_12,
814
        .nwindows = 8,
815
        .maxtl = 5,
816
        .features = CPU_DEFAULT_FEATURES,
817
    },
818
    {
819
        .name = "Sun UltraSparc III Cu",
820
        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
821
        .fpu_version = 0x00000000,
822
        .mmu_version = mmu_us_3,
823
        .nwindows = 8,
824
        .maxtl = 5,
825
        .features = CPU_DEFAULT_FEATURES,
826
    },
827
    {
828
        .name = "Sun UltraSparc IIIi",
829
        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
830
        .fpu_version = 0x00000000,
831
        .mmu_version = mmu_us_12,
832
        .nwindows = 8,
833
        .maxtl = 5,
834
        .features = CPU_DEFAULT_FEATURES,
835
    },
836
    {
837
        .name = "Sun UltraSparc IV",
838
        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
839
        .fpu_version = 0x00000000,
840
        .mmu_version = mmu_us_4,
841
        .nwindows = 8,
842
        .maxtl = 5,
843
        .features = CPU_DEFAULT_FEATURES,
844
    },
845
    {
846
        .name = "Sun UltraSparc IV+",
847
        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
848
        .fpu_version = 0x00000000,
849
        .mmu_version = mmu_us_12,
850
        .nwindows = 8,
851
        .maxtl = 5,
852
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
853
    },
854
    {
855
        .name = "Sun UltraSparc IIIi+",
856
        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
857
        .fpu_version = 0x00000000,
858
        .mmu_version = mmu_us_3,
859
        .nwindows = 8,
860
        .maxtl = 5,
861
        .features = CPU_DEFAULT_FEATURES,
862
    },
863
    {
864
        .name = "Sun UltraSparc T1",
865
        // defined in sparc_ifu_fdp.v and ctu.h
866
        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
867
        .fpu_version = 0x00000000,
868
        .mmu_version = mmu_sun4v,
869
        .nwindows = 8,
870
        .maxtl = 6,
871
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
872
        | CPU_FEATURE_GL,
873
    },
874
    {
875
        .name = "Sun UltraSparc T2",
876
        // defined in tlu_asi_ctl.v and n2_revid_cust.v
877
        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
878
        .fpu_version = 0x00000000,
879
        .mmu_version = mmu_sun4v,
880
        .nwindows = 8,
881
        .maxtl = 6,
882
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
883
        | CPU_FEATURE_GL,
884
    },
885
    {
886
        .name = "NEC UltraSparc I",
887
        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
888
        .fpu_version = 0x00000000,
889
        .mmu_version = mmu_us_12,
890
        .nwindows = 8,
891
        .maxtl = 5,
892
        .features = CPU_DEFAULT_FEATURES,
893
    },
894
#else
895
    {
896
        .name = "Fujitsu MB86900",
897
        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
898
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
899
        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
900
        .mmu_bm = 0x00004000,
901
        .mmu_ctpr_mask = 0x007ffff0,
902
        .mmu_cxr_mask = 0x0000003f,
903
        .mmu_sfsr_mask = 0xffffffff,
904
        .mmu_trcr_mask = 0xffffffff,
905
        .nwindows = 7,
906
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
907
    },
908
    {
909
        .name = "Fujitsu MB86904",
910
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
911
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
912
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
913
        .mmu_bm = 0x00004000,
914
        .mmu_ctpr_mask = 0x00ffffc0,
915
        .mmu_cxr_mask = 0x000000ff,
916
        .mmu_sfsr_mask = 0x00016fff,
917
        .mmu_trcr_mask = 0x00ffffff,
918
        .nwindows = 8,
919
        .features = CPU_DEFAULT_FEATURES,
920
    },
921
    {
922
        .name = "Fujitsu MB86907",
923
        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
924
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
925
        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
926
        .mmu_bm = 0x00004000,
927
        .mmu_ctpr_mask = 0xffffffc0,
928
        .mmu_cxr_mask = 0x000000ff,
929
        .mmu_sfsr_mask = 0x00016fff,
930
        .mmu_trcr_mask = 0xffffffff,
931
        .nwindows = 8,
932
        .features = CPU_DEFAULT_FEATURES,
933
    },
934
    {
935
        .name = "LSI L64811",
936
        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
937
        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
938
        .mmu_version = 0x10 << 24,
939
        .mmu_bm = 0x00004000,
940
        .mmu_ctpr_mask = 0x007ffff0,
941
        .mmu_cxr_mask = 0x0000003f,
942
        .mmu_sfsr_mask = 0xffffffff,
943
        .mmu_trcr_mask = 0xffffffff,
944
        .nwindows = 8,
945
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
946
        CPU_FEATURE_FSMULD,
947
    },
948
    {
949
        .name = "Cypress CY7C601",
950
        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
951
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
952
        .mmu_version = 0x10 << 24,
953
        .mmu_bm = 0x00004000,
954
        .mmu_ctpr_mask = 0x007ffff0,
955
        .mmu_cxr_mask = 0x0000003f,
956
        .mmu_sfsr_mask = 0xffffffff,
957
        .mmu_trcr_mask = 0xffffffff,
958
        .nwindows = 8,
959
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
960
        CPU_FEATURE_FSMULD,
961
    },
962
    {
963
        .name = "Cypress CY7C611",
964
        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
965
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
966
        .mmu_version = 0x10 << 24,
967
        .mmu_bm = 0x00004000,
968
        .mmu_ctpr_mask = 0x007ffff0,
969
        .mmu_cxr_mask = 0x0000003f,
970
        .mmu_sfsr_mask = 0xffffffff,
971
        .mmu_trcr_mask = 0xffffffff,
972
        .nwindows = 8,
973
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
974
        CPU_FEATURE_FSMULD,
975
    },
976
    {
977
        .name = "TI SuperSparc II",
978
        .iu_version = 0x40000000,
979
        .fpu_version = 0 << 17,
980
        .mmu_version = 0x04000000,
981
        .mmu_bm = 0x00002000,
982
        .mmu_ctpr_mask = 0xffffffc0,
983
        .mmu_cxr_mask = 0x0000ffff,
984
        .mmu_sfsr_mask = 0xffffffff,
985
        .mmu_trcr_mask = 0xffffffff,
986
        .nwindows = 8,
987
        .features = CPU_DEFAULT_FEATURES,
988
    },
989
    {
990
        .name = "TI MicroSparc I",
991
        .iu_version = 0x41000000,
992
        .fpu_version = 4 << 17,
993
        .mmu_version = 0x41000000,
994
        .mmu_bm = 0x00004000,
995
        .mmu_ctpr_mask = 0x007ffff0,
996
        .mmu_cxr_mask = 0x0000003f,
997
        .mmu_sfsr_mask = 0x00016fff,
998
        .mmu_trcr_mask = 0x0000003f,
999
        .nwindows = 7,
1000
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1001
        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1002
        CPU_FEATURE_FMUL,
1003
    },
1004
    {
1005
        .name = "TI MicroSparc II",
1006
        .iu_version = 0x42000000,
1007
        .fpu_version = 4 << 17,
1008
        .mmu_version = 0x02000000,
1009
        .mmu_bm = 0x00004000,
1010
        .mmu_ctpr_mask = 0x00ffffc0,
1011
        .mmu_cxr_mask = 0x000000ff,
1012
        .mmu_sfsr_mask = 0x00016fff,
1013
        .mmu_trcr_mask = 0x00ffffff,
1014
        .nwindows = 8,
1015
        .features = CPU_DEFAULT_FEATURES,
1016
    },
1017
    {
1018
        .name = "TI MicroSparc IIep",
1019
        .iu_version = 0x42000000,
1020
        .fpu_version = 4 << 17,
1021
        .mmu_version = 0x04000000,
1022
        .mmu_bm = 0x00004000,
1023
        .mmu_ctpr_mask = 0x00ffffc0,
1024
        .mmu_cxr_mask = 0x000000ff,
1025
        .mmu_sfsr_mask = 0x00016bff,
1026
        .mmu_trcr_mask = 0x00ffffff,
1027
        .nwindows = 8,
1028
        .features = CPU_DEFAULT_FEATURES,
1029
    },
1030
    {
1031
        .name = "TI SuperSparc 40", // STP1020NPGA
1032
        .iu_version = 0x41000000,
1033
        .fpu_version = 0 << 17,
1034
        .mmu_version = 0x00000000,
1035
        .mmu_bm = 0x00002000,
1036
        .mmu_ctpr_mask = 0xffffffc0,
1037
        .mmu_cxr_mask = 0x0000ffff,
1038
        .mmu_sfsr_mask = 0xffffffff,
1039
        .mmu_trcr_mask = 0xffffffff,
1040
        .nwindows = 8,
1041
        .features = CPU_DEFAULT_FEATURES,
1042
    },
1043
    {
1044
        .name = "TI SuperSparc 50", // STP1020PGA
1045
        .iu_version = 0x40000000,
1046
        .fpu_version = 0 << 17,
1047
        .mmu_version = 0x04000000,
1048
        .mmu_bm = 0x00002000,
1049
        .mmu_ctpr_mask = 0xffffffc0,
1050
        .mmu_cxr_mask = 0x0000ffff,
1051
        .mmu_sfsr_mask = 0xffffffff,
1052
        .mmu_trcr_mask = 0xffffffff,
1053
        .nwindows = 8,
1054
        .features = CPU_DEFAULT_FEATURES,
1055
    },
1056
    {
1057
        .name = "TI SuperSparc 51",
1058
        .iu_version = 0x43000000,
1059
        .fpu_version = 0 << 17,
1060
        .mmu_version = 0x04000000,
1061
        .mmu_bm = 0x00002000,
1062
        .mmu_ctpr_mask = 0xffffffc0,
1063
        .mmu_cxr_mask = 0x0000ffff,
1064
        .mmu_sfsr_mask = 0xffffffff,
1065
        .mmu_trcr_mask = 0xffffffff,
1066
        .nwindows = 8,
1067
        .features = CPU_DEFAULT_FEATURES,
1068
    },
1069
    {
1070
        .name = "TI SuperSparc 60", // STP1020APGA
1071
        .iu_version = 0x40000000,
1072
        .fpu_version = 0 << 17,
1073
        .mmu_version = 0x03000000,
1074
        .mmu_bm = 0x00002000,
1075
        .mmu_ctpr_mask = 0xffffffc0,
1076
        .mmu_cxr_mask = 0x0000ffff,
1077
        .mmu_sfsr_mask = 0xffffffff,
1078
        .mmu_trcr_mask = 0xffffffff,
1079
        .nwindows = 8,
1080
        .features = CPU_DEFAULT_FEATURES,
1081
    },
1082
    {
1083
        .name = "TI SuperSparc 61",
1084
        .iu_version = 0x44000000,
1085
        .fpu_version = 0 << 17,
1086
        .mmu_version = 0x04000000,
1087
        .mmu_bm = 0x00002000,
1088
        .mmu_ctpr_mask = 0xffffffc0,
1089
        .mmu_cxr_mask = 0x0000ffff,
1090
        .mmu_sfsr_mask = 0xffffffff,
1091
        .mmu_trcr_mask = 0xffffffff,
1092
        .nwindows = 8,
1093
        .features = CPU_DEFAULT_FEATURES,
1094
    },
1095
    {
1096
        .name = "Ross RT625",
1097
        .iu_version = 0x1e000000,
1098
        .fpu_version = 1 << 17,
1099
        .mmu_version = 0x1e000000,
1100
        .mmu_bm = 0x00004000,
1101
        .mmu_ctpr_mask = 0x007ffff0,
1102
        .mmu_cxr_mask = 0x0000003f,
1103
        .mmu_sfsr_mask = 0xffffffff,
1104
        .mmu_trcr_mask = 0xffffffff,
1105
        .nwindows = 8,
1106
        .features = CPU_DEFAULT_FEATURES,
1107
    },
1108
    {
1109
        .name = "Ross RT620",
1110
        .iu_version = 0x1f000000,
1111
        .fpu_version = 1 << 17,
1112
        .mmu_version = 0x1f000000,
1113
        .mmu_bm = 0x00004000,
1114
        .mmu_ctpr_mask = 0x007ffff0,
1115
        .mmu_cxr_mask = 0x0000003f,
1116
        .mmu_sfsr_mask = 0xffffffff,
1117
        .mmu_trcr_mask = 0xffffffff,
1118
        .nwindows = 8,
1119
        .features = CPU_DEFAULT_FEATURES,
1120
    },
1121
    {
1122
        .name = "BIT B5010",
1123
        .iu_version = 0x20000000,
1124
        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1125
        .mmu_version = 0x20000000,
1126
        .mmu_bm = 0x00004000,
1127
        .mmu_ctpr_mask = 0x007ffff0,
1128
        .mmu_cxr_mask = 0x0000003f,
1129
        .mmu_sfsr_mask = 0xffffffff,
1130
        .mmu_trcr_mask = 0xffffffff,
1131
        .nwindows = 8,
1132
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1133
        CPU_FEATURE_FSMULD,
1134
    },
1135
    {
1136
        .name = "Matsushita MN10501",
1137
        .iu_version = 0x50000000,
1138
        .fpu_version = 0 << 17,
1139
        .mmu_version = 0x50000000,
1140
        .mmu_bm = 0x00004000,
1141
        .mmu_ctpr_mask = 0x007ffff0,
1142
        .mmu_cxr_mask = 0x0000003f,
1143
        .mmu_sfsr_mask = 0xffffffff,
1144
        .mmu_trcr_mask = 0xffffffff,
1145
        .nwindows = 8,
1146
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1147
        CPU_FEATURE_FSMULD,
1148
    },
1149
    {
1150
        .name = "Weitek W8601",
1151
        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1152
        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1153
        .mmu_version = 0x10 << 24,
1154
        .mmu_bm = 0x00004000,
1155
        .mmu_ctpr_mask = 0x007ffff0,
1156
        .mmu_cxr_mask = 0x0000003f,
1157
        .mmu_sfsr_mask = 0xffffffff,
1158
        .mmu_trcr_mask = 0xffffffff,
1159
        .nwindows = 8,
1160
        .features = CPU_DEFAULT_FEATURES,
1161
    },
1162
    {
1163
        .name = "LEON2",
1164
        .iu_version = 0xf2000000,
1165
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1166
        .mmu_version = 0xf2000000,
1167
        .mmu_bm = 0x00004000,
1168
        .mmu_ctpr_mask = 0x007ffff0,
1169
        .mmu_cxr_mask = 0x0000003f,
1170
        .mmu_sfsr_mask = 0xffffffff,
1171
        .mmu_trcr_mask = 0xffffffff,
1172
        .nwindows = 8,
1173
        .features = CPU_DEFAULT_FEATURES,
1174
    },
1175
    {
1176
        .name = "LEON3",
1177
        .iu_version = 0xf3000000,
1178
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1179
        .mmu_version = 0xf3000000,
1180
        .mmu_bm = 0x00004000,
1181
        .mmu_ctpr_mask = 0x007ffff0,
1182
        .mmu_cxr_mask = 0x0000003f,
1183
        .mmu_sfsr_mask = 0xffffffff,
1184
        .mmu_trcr_mask = 0xffffffff,
1185
        .nwindows = 8,
1186
        .features = CPU_DEFAULT_FEATURES,
1187
    },
1188
#endif
1189
};
1190

    
1191
static const char * const feature_name[] = {
1192
    "float",
1193
    "float128",
1194
    "swap",
1195
    "mul",
1196
    "div",
1197
    "flush",
1198
    "fsqrt",
1199
    "fmul",
1200
    "vis1",
1201
    "vis2",
1202
    "fsmuld",
1203
    "hypv",
1204
    "cmt",
1205
    "gl",
1206
};
1207

    
1208
static void print_features(FILE *f,
1209
                           int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1210
                           uint32_t features, const char *prefix)
1211
{
1212
    unsigned int i;
1213

    
1214
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1215
        if (feature_name[i] && (features & (1 << i))) {
1216
            if (prefix)
1217
                (*cpu_fprintf)(f, "%s", prefix);
1218
            (*cpu_fprintf)(f, "%s ", feature_name[i]);
1219
        }
1220
}
1221

    
1222
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1223
{
1224
    unsigned int i;
1225

    
1226
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1227
        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1228
            *features |= 1 << i;
1229
            return;
1230
        }
1231
    fprintf(stderr, "CPU feature %s not found\n", flagname);
1232
}
1233

    
1234
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1235
{
1236
    unsigned int i;
1237
    const sparc_def_t *def = NULL;
1238
    char *s = strdup(cpu_model);
1239
    char *featurestr, *name = strtok(s, ",");
1240
    uint32_t plus_features = 0;
1241
    uint32_t minus_features = 0;
1242
    long long iu_version;
1243
    uint32_t fpu_version, mmu_version, nwindows;
1244

    
1245
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1246
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
1247
            def = &sparc_defs[i];
1248
        }
1249
    }
1250
    if (!def)
1251
        goto error;
1252
    memcpy(cpu_def, def, sizeof(*def));
1253

    
1254
    featurestr = strtok(NULL, ",");
1255
    while (featurestr) {
1256
        char *val;
1257

    
1258
        if (featurestr[0] == '+') {
1259
            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1260
        } else if (featurestr[0] == '-') {
1261
            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1262
        } else if ((val = strchr(featurestr, '='))) {
1263
            *val = 0; val++;
1264
            if (!strcmp(featurestr, "iu_version")) {
1265
                char *err;
1266

    
1267
                iu_version = strtoll(val, &err, 0);
1268
                if (!*val || *err) {
1269
                    fprintf(stderr, "bad numerical value %s\n", val);
1270
                    goto error;
1271
                }
1272
                cpu_def->iu_version = iu_version;
1273
#ifdef DEBUG_FEATURES
1274
                fprintf(stderr, "iu_version %llx\n", iu_version);
1275
#endif
1276
            } else if (!strcmp(featurestr, "fpu_version")) {
1277
                char *err;
1278

    
1279
                fpu_version = strtol(val, &err, 0);
1280
                if (!*val || *err) {
1281
                    fprintf(stderr, "bad numerical value %s\n", val);
1282
                    goto error;
1283
                }
1284
                cpu_def->fpu_version = fpu_version;
1285
#ifdef DEBUG_FEATURES
1286
                fprintf(stderr, "fpu_version %llx\n", fpu_version);
1287
#endif
1288
            } else if (!strcmp(featurestr, "mmu_version")) {
1289
                char *err;
1290

    
1291
                mmu_version = strtol(val, &err, 0);
1292
                if (!*val || *err) {
1293
                    fprintf(stderr, "bad numerical value %s\n", val);
1294
                    goto error;
1295
                }
1296
                cpu_def->mmu_version = mmu_version;
1297
#ifdef DEBUG_FEATURES
1298
                fprintf(stderr, "mmu_version %llx\n", mmu_version);
1299
#endif
1300
            } else if (!strcmp(featurestr, "nwindows")) {
1301
                char *err;
1302

    
1303
                nwindows = strtol(val, &err, 0);
1304
                if (!*val || *err || nwindows > MAX_NWINDOWS ||
1305
                    nwindows < MIN_NWINDOWS) {
1306
                    fprintf(stderr, "bad numerical value %s\n", val);
1307
                    goto error;
1308
                }
1309
                cpu_def->nwindows = nwindows;
1310
#ifdef DEBUG_FEATURES
1311
                fprintf(stderr, "nwindows %d\n", nwindows);
1312
#endif
1313
            } else {
1314
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
1315
                goto error;
1316
            }
1317
        } else {
1318
            fprintf(stderr, "feature string `%s' not in format "
1319
                    "(+feature|-feature|feature=xyz)\n", featurestr);
1320
            goto error;
1321
        }
1322
        featurestr = strtok(NULL, ",");
1323
    }
1324
    cpu_def->features |= plus_features;
1325
    cpu_def->features &= ~minus_features;
1326
#ifdef DEBUG_FEATURES
1327
    print_features(stderr, fprintf, cpu_def->features, NULL);
1328
#endif
1329
    free(s);
1330
    return 0;
1331

    
1332
 error:
1333
    free(s);
1334
    return -1;
1335
}
1336

    
1337
void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1338
{
1339
    unsigned int i;
1340

    
1341
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1342
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1343
                       sparc_defs[i].name,
1344
                       sparc_defs[i].iu_version,
1345
                       sparc_defs[i].fpu_version,
1346
                       sparc_defs[i].mmu_version,
1347
                       sparc_defs[i].nwindows);
1348
        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1349
                       ~sparc_defs[i].features, "-");
1350
        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1351
                       sparc_defs[i].features, "+");
1352
        (*cpu_fprintf)(f, "\n");
1353
    }
1354
    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1355
    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1356
    (*cpu_fprintf)(f, "\n");
1357
    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1358
    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1359
    (*cpu_fprintf)(f, "\n");
1360
    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1361
                   "fpu_version mmu_version nwindows\n");
1362
}
1363

    
1364
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1365

    
1366
void cpu_dump_state(CPUState *env, FILE *f,
1367
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1368
                    int flags)
1369
{
1370
    int i, x;
1371

    
1372
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
1373
                env->npc);
1374
    cpu_fprintf(f, "General Registers:\n");
1375
    for (i = 0; i < 4; i++)
1376
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1377
    cpu_fprintf(f, "\n");
1378
    for (; i < 8; i++)
1379
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1380
    cpu_fprintf(f, "\nCurrent Register Window:\n");
1381
    for (x = 0; x < 3; x++) {
1382
        for (i = 0; i < 4; i++)
1383
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1384
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1385
                    env->regwptr[i + x * 8]);
1386
        cpu_fprintf(f, "\n");
1387
        for (; i < 8; 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
    }
1393
    cpu_fprintf(f, "\nFloating Point Registers:\n");
1394
    for (i = 0; i < 32; i++) {
1395
        if ((i & 3) == 0)
1396
            cpu_fprintf(f, "%%f%02d:", i);
1397
        cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1398
        if ((i & 3) == 3)
1399
            cpu_fprintf(f, "\n");
1400
    }
1401
#ifdef TARGET_SPARC64
1402
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1403
                env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1404
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1405
                "cleanwin %d cwp %d\n",
1406
                env->cansave, env->canrestore, env->otherwin, env->wstate,
1407
                env->cleanwin, env->nwindows - 1 - env->cwp);
1408
#else
1409
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1410
                GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1411
                GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1412
                env->psrs?'S':'-', env->psrps?'P':'-',
1413
                env->psret?'E':'-', env->wim);
1414
#endif
1415
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1416
}
1417

    
1418
#ifdef TARGET_SPARC64
1419
#if !defined(CONFIG_USER_ONLY)
1420
#include "qemu-common.h"
1421
#include "hw/irq.h"
1422
#include "qemu-timer.h"
1423
#endif
1424

    
1425
void helper_tick_set_count(void *opaque, uint64_t count)
1426
{
1427
#if !defined(CONFIG_USER_ONLY)
1428
    ptimer_set_count(opaque, -count);
1429
#endif
1430
}
1431

    
1432
uint64_t helper_tick_get_count(void *opaque)
1433
{
1434
#if !defined(CONFIG_USER_ONLY)
1435
    return -ptimer_get_count(opaque);
1436
#else
1437
    return 0;
1438
#endif
1439
}
1440

    
1441
void helper_tick_set_limit(void *opaque, uint64_t limit)
1442
{
1443
#if !defined(CONFIG_USER_ONLY)
1444
    ptimer_set_limit(opaque, -limit, 0);
1445
#endif
1446
}
1447
#endif