Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ 95f9397c

History | View | Annotate | Download (52.9 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
#include "helper.h"
32

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

    
37
typedef struct sparc_def_t sparc_def_t;
38

    
39
struct sparc_def_t {
40
    const char *name;
41
    target_ulong iu_version;
42
    uint32_t fpu_version;
43
    uint32_t mmu_version;
44
    uint32_t mmu_bm;
45
    uint32_t mmu_ctpr_mask;
46
    uint32_t mmu_cxr_mask;
47
    uint32_t mmu_sfsr_mask;
48
    uint32_t mmu_trcr_mask;
49
    uint32_t features;
50
    uint32_t nwindows;
51
    uint32_t maxtl;
52
};
53

    
54
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
55

    
56
/* Sparc MMU emulation */
57

    
58
/* thread support */
59

    
60
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
61

    
62
void cpu_lock(void)
63
{
64
    spin_lock(&global_cpu_lock);
65
}
66

    
67
void cpu_unlock(void)
68
{
69
    spin_unlock(&global_cpu_lock);
70
}
71

    
72
#if defined(CONFIG_USER_ONLY)
73

    
74
int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
75
                               int mmu_idx, int is_softmmu)
76
{
77
    if (rw & 2)
78
        env1->exception_index = TT_TFAULT;
79
    else
80
        env1->exception_index = TT_DFAULT;
81
    return 1;
82
}
83

    
84
#else
85

    
86
#ifndef TARGET_SPARC64
87
/*
88
 * Sparc V8 Reference MMU (SRMMU)
89
 */
90
static const int access_table[8][8] = {
91
    { 0, 0, 0, 0, 8, 0, 12, 12 },
92
    { 0, 0, 0, 0, 8, 0, 0, 0 },
93
    { 8, 8, 0, 0, 0, 8, 12, 12 },
94
    { 8, 8, 0, 0, 0, 8, 0, 0 },
95
    { 8, 0, 8, 0, 8, 8, 12, 12 },
96
    { 8, 0, 8, 0, 8, 0, 8, 0 },
97
    { 8, 8, 8, 0, 8, 8, 12, 12 },
98
    { 8, 8, 8, 0, 8, 8, 8, 0 }
99
};
100

    
101
static const int perm_table[2][8] = {
102
    {
103
        PAGE_READ,
104
        PAGE_READ | PAGE_WRITE,
105
        PAGE_READ | PAGE_EXEC,
106
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
107
        PAGE_EXEC,
108
        PAGE_READ | PAGE_WRITE,
109
        PAGE_READ | PAGE_EXEC,
110
        PAGE_READ | PAGE_WRITE | PAGE_EXEC
111
    },
112
    {
113
        PAGE_READ,
114
        PAGE_READ | PAGE_WRITE,
115
        PAGE_READ | PAGE_EXEC,
116
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
117
        PAGE_EXEC,
118
        PAGE_READ,
119
        0,
120
        0,
121
    }
122
};
123

    
124
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
125
                                int *prot, int *access_index,
126
                                target_ulong address, int rw, int mmu_idx)
127
{
128
    int access_perms = 0;
129
    target_phys_addr_t pde_ptr;
130
    uint32_t pde;
131
    target_ulong virt_addr;
132
    int error_code = 0, is_dirty, is_user;
133
    unsigned long page_offset;
134

    
135
    is_user = mmu_idx == MMU_USER_IDX;
136
    virt_addr = address & TARGET_PAGE_MASK;
137

    
138
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
139
        // Boot mode: instruction fetches are taken from PROM
140
        if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
141
            *physical = env->prom_addr | (address & 0x7ffffULL);
142
            *prot = PAGE_READ | PAGE_EXEC;
143
            return 0;
144
        }
145
        *physical = address;
146
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
147
        return 0;
148
    }
149

    
150
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
151
    *physical = 0xffffffffffff0000ULL;
152

    
153
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
154
    /* Context base + context number */
155
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
156
    pde = ldl_phys(pde_ptr);
157

    
158
    /* Ctx pde */
159
    switch (pde & PTE_ENTRYTYPE_MASK) {
160
    default:
161
    case 0: /* Invalid */
162
        return 1 << 2;
163
    case 2: /* L0 PTE, maybe should not happen? */
164
    case 3: /* Reserved */
165
        return 4 << 2;
166
    case 1: /* L0 PDE */
167
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
168
        pde = ldl_phys(pde_ptr);
169

    
170
        switch (pde & PTE_ENTRYTYPE_MASK) {
171
        default:
172
        case 0: /* Invalid */
173
            return (1 << 8) | (1 << 2);
174
        case 3: /* Reserved */
175
            return (1 << 8) | (4 << 2);
176
        case 1: /* L1 PDE */
177
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
178
            pde = ldl_phys(pde_ptr);
179

    
180
            switch (pde & PTE_ENTRYTYPE_MASK) {
181
            default:
182
            case 0: /* Invalid */
183
                return (2 << 8) | (1 << 2);
184
            case 3: /* Reserved */
185
                return (2 << 8) | (4 << 2);
186
            case 1: /* L2 PDE */
187
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
188
                pde = ldl_phys(pde_ptr);
189

    
190
                switch (pde & PTE_ENTRYTYPE_MASK) {
191
                default:
192
                case 0: /* Invalid */
193
                    return (3 << 8) | (1 << 2);
194
                case 1: /* PDE, should not happen */
195
                case 3: /* Reserved */
196
                    return (3 << 8) | (4 << 2);
197
                case 2: /* L3 PTE */
198
                    virt_addr = address & TARGET_PAGE_MASK;
199
                    page_offset = (address & TARGET_PAGE_MASK) &
200
                        (TARGET_PAGE_SIZE - 1);
201
                }
202
                break;
203
            case 2: /* L2 PTE */
204
                virt_addr = address & ~0x3ffff;
205
                page_offset = address & 0x3ffff;
206
            }
207
            break;
208
        case 2: /* L1 PTE */
209
            virt_addr = address & ~0xffffff;
210
            page_offset = address & 0xffffff;
211
        }
212
    }
213

    
214
    /* update page modified and dirty bits */
215
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
216
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
217
        pde |= PG_ACCESSED_MASK;
218
        if (is_dirty)
219
            pde |= PG_MODIFIED_MASK;
220
        stl_phys_notdirty(pde_ptr, pde);
221
    }
222
    /* check access */
223
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
224
    error_code = access_table[*access_index][access_perms];
225
    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
226
        return error_code;
227

    
228
    /* the page can be put in the TLB */
229
    *prot = perm_table[is_user][access_perms];
230
    if (!(pde & PG_MODIFIED_MASK)) {
231
        /* only set write access if already dirty... otherwise wait
232
           for dirty access */
233
        *prot &= ~PAGE_WRITE;
234
    }
235

    
236
    /* Even if large ptes, we map only one 4KB page in the cache to
237
       avoid filling it too fast */
238
    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
239
    return error_code;
240
}
241

    
242
/* Perform address translation */
243
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
244
                              int mmu_idx, int is_softmmu)
245
{
246
    target_phys_addr_t paddr;
247
    target_ulong vaddr;
248
    int error_code = 0, prot, ret = 0, access_index;
249

    
250
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
251
                                      address, rw, mmu_idx);
252
    if (error_code == 0) {
253
        vaddr = address & TARGET_PAGE_MASK;
254
        paddr &= TARGET_PAGE_MASK;
255
#ifdef DEBUG_MMU
256
        printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
257
               TARGET_FMT_lx "\n", address, paddr, vaddr);
258
#endif
259
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
260
        return ret;
261
    }
262

    
263
    if (env->mmuregs[3]) /* Fault status register */
264
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
265
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
266
    env->mmuregs[4] = address; /* Fault address register */
267

    
268
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
269
        // No fault mode: if a mapping is available, just override
270
        // permissions. If no mapping is available, redirect accesses to
271
        // neverland. Fake/overridden mappings will be flushed when
272
        // switching to normal mode.
273
        vaddr = address & TARGET_PAGE_MASK;
274
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
275
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
276
        return ret;
277
    } else {
278
        if (rw & 2)
279
            env->exception_index = TT_TFAULT;
280
        else
281
            env->exception_index = TT_DFAULT;
282
        return 1;
283
    }
284
}
285

    
286
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
287
{
288
    target_phys_addr_t pde_ptr;
289
    uint32_t pde;
290

    
291
    /* Context base + context number */
292
    pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
293
        (env->mmuregs[2] << 2);
294
    pde = ldl_phys(pde_ptr);
295

    
296
    switch (pde & PTE_ENTRYTYPE_MASK) {
297
    default:
298
    case 0: /* Invalid */
299
    case 2: /* PTE, maybe should not happen? */
300
    case 3: /* Reserved */
301
        return 0;
302
    case 1: /* L1 PDE */
303
        if (mmulev == 3)
304
            return pde;
305
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
306
        pde = ldl_phys(pde_ptr);
307

    
308
        switch (pde & PTE_ENTRYTYPE_MASK) {
309
        default:
310
        case 0: /* Invalid */
311
        case 3: /* Reserved */
312
            return 0;
313
        case 2: /* L1 PTE */
314
            return pde;
315
        case 1: /* L2 PDE */
316
            if (mmulev == 2)
317
                return pde;
318
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
319
            pde = ldl_phys(pde_ptr);
320

    
321
            switch (pde & PTE_ENTRYTYPE_MASK) {
322
            default:
323
            case 0: /* Invalid */
324
            case 3: /* Reserved */
325
                return 0;
326
            case 2: /* L2 PTE */
327
                return pde;
328
            case 1: /* L3 PDE */
329
                if (mmulev == 1)
330
                    return pde;
331
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
332
                pde = ldl_phys(pde_ptr);
333

    
334
                switch (pde & PTE_ENTRYTYPE_MASK) {
335
                default:
336
                case 0: /* Invalid */
337
                case 1: /* PDE, should not happen */
338
                case 3: /* Reserved */
339
                    return 0;
340
                case 2: /* L3 PTE */
341
                    return pde;
342
                }
343
            }
344
        }
345
    }
346
    return 0;
347
}
348

    
349
#ifdef DEBUG_MMU
350
void dump_mmu(CPUState *env)
351
{
352
    target_ulong va, va1, va2;
353
    unsigned int n, m, o;
354
    target_phys_addr_t pde_ptr, pa;
355
    uint32_t pde;
356

    
357
    printf("MMU dump:\n");
358
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
359
    pde = ldl_phys(pde_ptr);
360
    printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
361
           (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
362
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
363
        pde = mmu_probe(env, va, 2);
364
        if (pde) {
365
            pa = cpu_get_phys_page_debug(env, va);
366
            printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
367
                   " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
368
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
369
                pde = mmu_probe(env, va1, 1);
370
                if (pde) {
371
                    pa = cpu_get_phys_page_debug(env, va1);
372
                    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
373
                           " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
374
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
375
                        pde = mmu_probe(env, va2, 0);
376
                        if (pde) {
377
                            pa = cpu_get_phys_page_debug(env, va2);
378
                            printf("  VA: " TARGET_FMT_lx ", PA: "
379
                                   TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
380
                                   va2, pa, pde);
381
                        }
382
                    }
383
                }
384
            }
385
        }
386
    }
387
    printf("MMU dump ends\n");
388
}
389
#endif /* DEBUG_MMU */
390

    
391
#else /* !TARGET_SPARC64 */
392
/*
393
 * UltraSparc IIi I/DMMUs
394
 */
395
static int get_physical_address_data(CPUState *env,
396
                                     target_phys_addr_t *physical, int *prot,
397
                                     target_ulong address, int rw, int is_user)
398
{
399
    target_ulong mask;
400
    unsigned int i;
401

    
402
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
403
        *physical = address;
404
        *prot = PAGE_READ | PAGE_WRITE;
405
        return 0;
406
    }
407

    
408
    for (i = 0; i < 64; i++) {
409
        switch ((env->dtlb_tte[i] >> 61) & 3) {
410
        default:
411
        case 0x0: // 8k
412
            mask = 0xffffffffffffe000ULL;
413
            break;
414
        case 0x1: // 64k
415
            mask = 0xffffffffffff0000ULL;
416
            break;
417
        case 0x2: // 512k
418
            mask = 0xfffffffffff80000ULL;
419
            break;
420
        case 0x3: // 4M
421
            mask = 0xffffffffffc00000ULL;
422
            break;
423
        }
424
        // ctx match, vaddr match?
425
        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
426
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
427
            // valid, access ok?
428
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
429
                ((env->dtlb_tte[i] & 0x4) && is_user) ||
430
                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
431
                if (env->dmmuregs[3]) /* Fault status register */
432
                    env->dmmuregs[3] = 2; /* overflow (not read before
433
                                             another fault) */
434
                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
435
                env->dmmuregs[4] = address; /* Fault address register */
436
                env->exception_index = TT_DFAULT;
437
#ifdef DEBUG_MMU
438
                printf("DFAULT at 0x%" PRIx64 "\n", address);
439
#endif
440
                return 1;
441
            }
442
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
443
                (address & ~mask & 0x1fffffff000ULL);
444
            *prot = PAGE_READ;
445
            if (env->dtlb_tte[i] & 0x2)
446
                *prot |= PAGE_WRITE;
447
            return 0;
448
        }
449
    }
450
#ifdef DEBUG_MMU
451
    printf("DMISS at 0x%" PRIx64 "\n", address);
452
#endif
453
    env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
454
    env->exception_index = TT_DMISS;
455
    return 1;
456
}
457

    
458
static int get_physical_address_code(CPUState *env,
459
                                     target_phys_addr_t *physical, int *prot,
460
                                     target_ulong address, int is_user)
461
{
462
    target_ulong mask;
463
    unsigned int i;
464

    
465
    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
466
        *physical = address;
467
        *prot = PAGE_EXEC;
468
        return 0;
469
    }
470

    
471
    for (i = 0; i < 64; i++) {
472
        switch ((env->itlb_tte[i] >> 61) & 3) {
473
        default:
474
        case 0x0: // 8k
475
            mask = 0xffffffffffffe000ULL;
476
            break;
477
        case 0x1: // 64k
478
            mask = 0xffffffffffff0000ULL;
479
            break;
480
        case 0x2: // 512k
481
            mask = 0xfffffffffff80000ULL;
482
            break;
483
        case 0x3: // 4M
484
            mask = 0xffffffffffc00000ULL;
485
                break;
486
        }
487
        // ctx match, vaddr match?
488
        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
489
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
490
            // valid, access ok?
491
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
492
                ((env->itlb_tte[i] & 0x4) && is_user)) {
493
                if (env->immuregs[3]) /* Fault status register */
494
                    env->immuregs[3] = 2; /* overflow (not read before
495
                                             another fault) */
496
                env->immuregs[3] |= (is_user << 3) | 1;
497
                env->exception_index = TT_TFAULT;
498
#ifdef DEBUG_MMU
499
                printf("TFAULT at 0x%" PRIx64 "\n", address);
500
#endif
501
                return 1;
502
            }
503
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
504
                (address & ~mask & 0x1fffffff000ULL);
505
            *prot = PAGE_EXEC;
506
            return 0;
507
        }
508
    }
509
#ifdef DEBUG_MMU
510
    printf("TMISS at 0x%" PRIx64 "\n", address);
511
#endif
512
    env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
513
    env->exception_index = TT_TMISS;
514
    return 1;
515
}
516

    
517
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
518
                                int *prot, int *access_index,
519
                                target_ulong address, int rw, int mmu_idx)
520
{
521
    int is_user = mmu_idx == MMU_USER_IDX;
522

    
523
    if (rw == 2)
524
        return get_physical_address_code(env, physical, prot, address,
525
                                         is_user);
526
    else
527
        return get_physical_address_data(env, physical, prot, address, rw,
528
                                         is_user);
529
}
530

    
531
/* Perform address translation */
532
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
533
                              int mmu_idx, int is_softmmu)
534
{
535
    target_ulong virt_addr, vaddr;
536
    target_phys_addr_t paddr;
537
    int error_code = 0, prot, ret = 0, access_index;
538

    
539
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
540
                                      address, rw, mmu_idx);
541
    if (error_code == 0) {
542
        virt_addr = address & TARGET_PAGE_MASK;
543
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
544
                             (TARGET_PAGE_SIZE - 1));
545
#ifdef DEBUG_MMU
546
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
547
               "\n", address, paddr, vaddr);
548
#endif
549
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
550
        return ret;
551
    }
552
    // XXX
553
    return 1;
554
}
555

    
556
#ifdef DEBUG_MMU
557
void dump_mmu(CPUState *env)
558
{
559
    unsigned int i;
560
    const char *mask;
561

    
562
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
563
           env->dmmuregs[1], env->dmmuregs[2]);
564
    if ((env->lsu & DMMU_E) == 0) {
565
        printf("DMMU disabled\n");
566
    } else {
567
        printf("DMMU dump:\n");
568
        for (i = 0; i < 64; i++) {
569
            switch ((env->dtlb_tte[i] >> 61) & 3) {
570
            default:
571
            case 0x0:
572
                mask = "  8k";
573
                break;
574
            case 0x1:
575
                mask = " 64k";
576
                break;
577
            case 0x2:
578
                mask = "512k";
579
                break;
580
            case 0x3:
581
                mask = "  4M";
582
                break;
583
            }
584
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
585
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
586
                       ", %s, %s, %s, %s, ctx %" PRId64 "\n",
587
                       env->dtlb_tag[i] & ~0x1fffULL,
588
                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
589
                       mask,
590
                       env->dtlb_tte[i] & 0x4? "priv": "user",
591
                       env->dtlb_tte[i] & 0x2? "RW": "RO",
592
                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
593
                       env->dtlb_tag[i] & 0x1fffULL);
594
            }
595
        }
596
    }
597
    if ((env->lsu & IMMU_E) == 0) {
598
        printf("IMMU disabled\n");
599
    } else {
600
        printf("IMMU dump:\n");
601
        for (i = 0; i < 64; i++) {
602
            switch ((env->itlb_tte[i] >> 61) & 3) {
603
            default:
604
            case 0x0:
605
                mask = "  8k";
606
                break;
607
            case 0x1:
608
                mask = " 64k";
609
                break;
610
            case 0x2:
611
                mask = "512k";
612
                break;
613
            case 0x3:
614
                mask = "  4M";
615
                break;
616
            }
617
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
618
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
619
                       ", %s, %s, %s, ctx %" PRId64 "\n",
620
                       env->itlb_tag[i] & ~0x1fffULL,
621
                       env->itlb_tte[i] & 0x1ffffffe000ULL,
622
                       mask,
623
                       env->itlb_tte[i] & 0x4? "priv": "user",
624
                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
625
                       env->itlb_tag[i] & 0x1fffULL);
626
            }
627
        }
628
    }
629
}
630
#endif /* DEBUG_MMU */
631

    
632
#endif /* TARGET_SPARC64 */
633
#endif /* !CONFIG_USER_ONLY */
634

    
635

    
636
#if defined(CONFIG_USER_ONLY)
637
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
638
{
639
    return addr;
640
}
641

    
642
#else
643
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
644
{
645
    target_phys_addr_t phys_addr;
646
    int prot, access_index;
647

    
648
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
649
                             MMU_KERNEL_IDX) != 0)
650
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
651
                                 0, MMU_KERNEL_IDX) != 0)
652
            return -1;
653
    if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
654
        return -1;
655
    return phys_addr;
656
}
657
#endif
658

    
659
#ifdef TARGET_SPARC64
660
#ifdef DEBUG_PCALL
661
static const char * const excp_names[0x80] = {
662
    [TT_TFAULT] = "Instruction Access Fault",
663
    [TT_TMISS] = "Instruction Access MMU Miss",
664
    [TT_CODE_ACCESS] = "Instruction Access Error",
665
    [TT_ILL_INSN] = "Illegal Instruction",
666
    [TT_PRIV_INSN] = "Privileged Instruction",
667
    [TT_NFPU_INSN] = "FPU Disabled",
668
    [TT_FP_EXCP] = "FPU Exception",
669
    [TT_TOVF] = "Tag Overflow",
670
    [TT_CLRWIN] = "Clean Windows",
671
    [TT_DIV_ZERO] = "Division By Zero",
672
    [TT_DFAULT] = "Data Access Fault",
673
    [TT_DMISS] = "Data Access MMU Miss",
674
    [TT_DATA_ACCESS] = "Data Access Error",
675
    [TT_DPROT] = "Data Protection Error",
676
    [TT_UNALIGNED] = "Unaligned Memory Access",
677
    [TT_PRIV_ACT] = "Privileged Action",
678
    [TT_EXTINT | 0x1] = "External Interrupt 1",
679
    [TT_EXTINT | 0x2] = "External Interrupt 2",
680
    [TT_EXTINT | 0x3] = "External Interrupt 3",
681
    [TT_EXTINT | 0x4] = "External Interrupt 4",
682
    [TT_EXTINT | 0x5] = "External Interrupt 5",
683
    [TT_EXTINT | 0x6] = "External Interrupt 6",
684
    [TT_EXTINT | 0x7] = "External Interrupt 7",
685
    [TT_EXTINT | 0x8] = "External Interrupt 8",
686
    [TT_EXTINT | 0x9] = "External Interrupt 9",
687
    [TT_EXTINT | 0xa] = "External Interrupt 10",
688
    [TT_EXTINT | 0xb] = "External Interrupt 11",
689
    [TT_EXTINT | 0xc] = "External Interrupt 12",
690
    [TT_EXTINT | 0xd] = "External Interrupt 13",
691
    [TT_EXTINT | 0xe] = "External Interrupt 14",
692
    [TT_EXTINT | 0xf] = "External Interrupt 15",
693
};
694
#endif
695

    
696
void do_interrupt(CPUState *env)
697
{
698
    int intno = env->exception_index;
699

    
700
#ifdef DEBUG_PCALL
701
    if (loglevel & CPU_LOG_INT) {
702
        static int count;
703
        const char *name;
704

    
705
        if (intno < 0 || intno >= 0x180)
706
            name = "Unknown";
707
        else if (intno >= 0x100)
708
            name = "Trap Instruction";
709
        else if (intno >= 0xc0)
710
            name = "Window Fill";
711
        else if (intno >= 0x80)
712
            name = "Window Spill";
713
        else {
714
            name = excp_names[intno];
715
            if (!name)
716
                name = "Unknown";
717
        }
718

    
719
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
720
                " SP=%016" PRIx64 "\n",
721
                count, name, intno,
722
                env->pc,
723
                env->npc, env->regwptr[6]);
724
        cpu_dump_state(env, logfile, fprintf, 0);
725
#if 0
726
        {
727
            int i;
728
            uint8_t *ptr;
729

730
            fprintf(logfile, "       code=");
731
            ptr = (uint8_t *)env->pc;
732
            for(i = 0; i < 16; i++) {
733
                fprintf(logfile, " %02x", ldub(ptr + i));
734
            }
735
            fprintf(logfile, "\n");
736
        }
737
#endif
738
        count++;
739
    }
740
#endif
741
#if !defined(CONFIG_USER_ONLY)
742
    if (env->tl >= env->maxtl) {
743
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
744
                  " Error state", env->exception_index, env->tl, env->maxtl);
745
        return;
746
    }
747
#endif
748
    if (env->tl < env->maxtl - 1) {
749
        env->tl++;
750
    } else {
751
        env->pstate |= PS_RED;
752
        if (env->tl < env->maxtl)
753
            env->tl++;
754
    }
755
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
756
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
757
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
758
        GET_CWP64(env);
759
    env->tsptr->tpc = env->pc;
760
    env->tsptr->tnpc = env->npc;
761
    env->tsptr->tt = intno;
762
    if (!(env->features & CPU_FEATURE_GL)) {
763
        switch (intno) {
764
        case TT_IVEC:
765
            change_pstate(PS_PEF | PS_PRIV | PS_IG);
766
            break;
767
        case TT_TFAULT:
768
        case TT_TMISS:
769
        case TT_DFAULT:
770
        case TT_DMISS:
771
        case TT_DPROT:
772
            change_pstate(PS_PEF | PS_PRIV | PS_MG);
773
            break;
774
        default:
775
            change_pstate(PS_PEF | PS_PRIV | PS_AG);
776
            break;
777
        }
778
    }
779
    if (intno == TT_CLRWIN)
780
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
781
    else if ((intno & 0x1c0) == TT_SPILL)
782
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
783
    else if ((intno & 0x1c0) == TT_FILL)
784
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
785
    env->tbr &= ~0x7fffULL;
786
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
787
    env->pc = env->tbr;
788
    env->npc = env->pc + 4;
789
    env->exception_index = 0;
790
}
791
#else
792
#ifdef DEBUG_PCALL
793
static const char * const excp_names[0x80] = {
794
    [TT_TFAULT] = "Instruction Access Fault",
795
    [TT_ILL_INSN] = "Illegal Instruction",
796
    [TT_PRIV_INSN] = "Privileged Instruction",
797
    [TT_NFPU_INSN] = "FPU Disabled",
798
    [TT_WIN_OVF] = "Window Overflow",
799
    [TT_WIN_UNF] = "Window Underflow",
800
    [TT_UNALIGNED] = "Unaligned Memory Access",
801
    [TT_FP_EXCP] = "FPU Exception",
802
    [TT_DFAULT] = "Data Access Fault",
803
    [TT_TOVF] = "Tag Overflow",
804
    [TT_EXTINT | 0x1] = "External Interrupt 1",
805
    [TT_EXTINT | 0x2] = "External Interrupt 2",
806
    [TT_EXTINT | 0x3] = "External Interrupt 3",
807
    [TT_EXTINT | 0x4] = "External Interrupt 4",
808
    [TT_EXTINT | 0x5] = "External Interrupt 5",
809
    [TT_EXTINT | 0x6] = "External Interrupt 6",
810
    [TT_EXTINT | 0x7] = "External Interrupt 7",
811
    [TT_EXTINT | 0x8] = "External Interrupt 8",
812
    [TT_EXTINT | 0x9] = "External Interrupt 9",
813
    [TT_EXTINT | 0xa] = "External Interrupt 10",
814
    [TT_EXTINT | 0xb] = "External Interrupt 11",
815
    [TT_EXTINT | 0xc] = "External Interrupt 12",
816
    [TT_EXTINT | 0xd] = "External Interrupt 13",
817
    [TT_EXTINT | 0xe] = "External Interrupt 14",
818
    [TT_EXTINT | 0xf] = "External Interrupt 15",
819
    [TT_TOVF] = "Tag Overflow",
820
    [TT_CODE_ACCESS] = "Instruction Access Error",
821
    [TT_DATA_ACCESS] = "Data Access Error",
822
    [TT_DIV_ZERO] = "Division By Zero",
823
    [TT_NCP_INSN] = "Coprocessor Disabled",
824
};
825
#endif
826

    
827
void do_interrupt(CPUState *env)
828
{
829
    int cwp, intno = env->exception_index;
830

    
831
#ifdef DEBUG_PCALL
832
    if (loglevel & CPU_LOG_INT) {
833
        static int count;
834
        const char *name;
835

    
836
        if (intno < 0 || intno >= 0x100)
837
            name = "Unknown";
838
        else if (intno >= 0x80)
839
            name = "Trap Instruction";
840
        else {
841
            name = excp_names[intno];
842
            if (!name)
843
                name = "Unknown";
844
        }
845

    
846
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
847
                count, name, intno,
848
                env->pc,
849
                env->npc, env->regwptr[6]);
850
        cpu_dump_state(env, logfile, fprintf, 0);
851
#if 0
852
        {
853
            int i;
854
            uint8_t *ptr;
855

856
            fprintf(logfile, "       code=");
857
            ptr = (uint8_t *)env->pc;
858
            for(i = 0; i < 16; i++) {
859
                fprintf(logfile, " %02x", ldub(ptr + i));
860
            }
861
            fprintf(logfile, "\n");
862
        }
863
#endif
864
        count++;
865
    }
866
#endif
867
#if !defined(CONFIG_USER_ONLY)
868
    if (env->psret == 0) {
869
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
870
                  env->exception_index);
871
        return;
872
    }
873
#endif
874
    env->psret = 0;
875
    cwp = cpu_cwp_dec(env, env->cwp - 1);
876
    cpu_set_cwp(env, cwp);
877
    env->regwptr[9] = env->pc;
878
    env->regwptr[10] = env->npc;
879
    env->psrps = env->psrs;
880
    env->psrs = 1;
881
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
882
    env->pc = env->tbr;
883
    env->npc = env->pc + 4;
884
    env->exception_index = 0;
885
}
886
#endif
887

    
888
void memcpy32(target_ulong *dst, const target_ulong *src)
889
{
890
    dst[0] = src[0];
891
    dst[1] = src[1];
892
    dst[2] = src[2];
893
    dst[3] = src[3];
894
    dst[4] = src[4];
895
    dst[5] = src[5];
896
    dst[6] = src[6];
897
    dst[7] = src[7];
898
}
899

    
900
void cpu_reset(CPUSPARCState *env)
901
{
902
    tlb_flush(env, 1);
903
    env->cwp = 0;
904
    env->wim = 1;
905
    env->regwptr = env->regbase + (env->cwp * 16);
906
#if defined(CONFIG_USER_ONLY)
907
    env->user_mode_only = 1;
908
#ifdef TARGET_SPARC64
909
    env->cleanwin = env->nwindows - 2;
910
    env->cansave = env->nwindows - 2;
911
    env->pstate = PS_RMO | PS_PEF | PS_IE;
912
    env->asi = 0x82; // Primary no-fault
913
#endif
914
#else
915
    env->psret = 0;
916
    env->psrs = 1;
917
    env->psrps = 1;
918
#ifdef TARGET_SPARC64
919
    env->pstate = PS_PRIV;
920
    env->hpstate = HS_PRIV;
921
    env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset
922
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
923
#else
924
    env->pc = 0;
925
    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
926
    env->mmuregs[0] |= env->mmu_bm;
927
#endif
928
    env->npc = env->pc + 4;
929
#endif
930
}
931

    
932
static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
933
{
934
    sparc_def_t def1, *def = &def1;
935

    
936
    if (cpu_sparc_find_by_name(def, cpu_model) < 0)
937
        return -1;
938

    
939
    env->features = def->features;
940
    env->cpu_model_str = cpu_model;
941
    env->version = def->iu_version;
942
    env->fsr = def->fpu_version;
943
    env->nwindows = def->nwindows;
944
#if !defined(TARGET_SPARC64)
945
    env->mmu_bm = def->mmu_bm;
946
    env->mmu_ctpr_mask = def->mmu_ctpr_mask;
947
    env->mmu_cxr_mask = def->mmu_cxr_mask;
948
    env->mmu_sfsr_mask = def->mmu_sfsr_mask;
949
    env->mmu_trcr_mask = def->mmu_trcr_mask;
950
    env->mmuregs[0] |= def->mmu_version;
951
    cpu_sparc_set_id(env, 0);
952
#else
953
    env->mmu_version = def->mmu_version;
954
    env->maxtl = def->maxtl;
955
    env->version |= def->maxtl << 8;
956
    env->version |= def->nwindows - 1;
957
#endif
958
    return 0;
959
}
960

    
961
static void cpu_sparc_close(CPUSPARCState *env)
962
{
963
    free(env);
964
}
965

    
966
CPUSPARCState *cpu_sparc_init(const char *cpu_model)
967
{
968
    CPUSPARCState *env;
969

    
970
    env = qemu_mallocz(sizeof(CPUSPARCState));
971
    if (!env)
972
        return NULL;
973
    cpu_exec_init(env);
974

    
975
    gen_intermediate_code_init(env);
976

    
977
    if (cpu_sparc_register(env, cpu_model) < 0) {
978
        cpu_sparc_close(env);
979
        return NULL;
980
    }
981
    cpu_reset(env);
982

    
983
    return env;
984
}
985

    
986
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
987
{
988
#if !defined(TARGET_SPARC64)
989
    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
990
#endif
991
}
992

    
993
static const sparc_def_t sparc_defs[] = {
994
#ifdef TARGET_SPARC64
995
    {
996
        .name = "Fujitsu Sparc64",
997
        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
998
        .fpu_version = 0x00000000,
999
        .mmu_version = mmu_us_12,
1000
        .nwindows = 4,
1001
        .maxtl = 4,
1002
        .features = CPU_DEFAULT_FEATURES,
1003
    },
1004
    {
1005
        .name = "Fujitsu Sparc64 III",
1006
        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
1007
        .fpu_version = 0x00000000,
1008
        .mmu_version = mmu_us_12,
1009
        .nwindows = 5,
1010
        .maxtl = 4,
1011
        .features = CPU_DEFAULT_FEATURES,
1012
    },
1013
    {
1014
        .name = "Fujitsu Sparc64 IV",
1015
        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
1016
        .fpu_version = 0x00000000,
1017
        .mmu_version = mmu_us_12,
1018
        .nwindows = 8,
1019
        .maxtl = 5,
1020
        .features = CPU_DEFAULT_FEATURES,
1021
    },
1022
    {
1023
        .name = "Fujitsu Sparc64 V",
1024
        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
1025
        .fpu_version = 0x00000000,
1026
        .mmu_version = mmu_us_12,
1027
        .nwindows = 8,
1028
        .maxtl = 5,
1029
        .features = CPU_DEFAULT_FEATURES,
1030
    },
1031
    {
1032
        .name = "TI UltraSparc I",
1033
        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1034
        .fpu_version = 0x00000000,
1035
        .mmu_version = mmu_us_12,
1036
        .nwindows = 8,
1037
        .maxtl = 5,
1038
        .features = CPU_DEFAULT_FEATURES,
1039
    },
1040
    {
1041
        .name = "TI UltraSparc II",
1042
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
1043
        .fpu_version = 0x00000000,
1044
        .mmu_version = mmu_us_12,
1045
        .nwindows = 8,
1046
        .maxtl = 5,
1047
        .features = CPU_DEFAULT_FEATURES,
1048
    },
1049
    {
1050
        .name = "TI UltraSparc IIi",
1051
        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
1052
        .fpu_version = 0x00000000,
1053
        .mmu_version = mmu_us_12,
1054
        .nwindows = 8,
1055
        .maxtl = 5,
1056
        .features = CPU_DEFAULT_FEATURES,
1057
    },
1058
    {
1059
        .name = "TI UltraSparc IIe",
1060
        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
1061
        .fpu_version = 0x00000000,
1062
        .mmu_version = mmu_us_12,
1063
        .nwindows = 8,
1064
        .maxtl = 5,
1065
        .features = CPU_DEFAULT_FEATURES,
1066
    },
1067
    {
1068
        .name = "Sun UltraSparc III",
1069
        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
1070
        .fpu_version = 0x00000000,
1071
        .mmu_version = mmu_us_12,
1072
        .nwindows = 8,
1073
        .maxtl = 5,
1074
        .features = CPU_DEFAULT_FEATURES,
1075
    },
1076
    {
1077
        .name = "Sun UltraSparc III Cu",
1078
        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
1079
        .fpu_version = 0x00000000,
1080
        .mmu_version = mmu_us_3,
1081
        .nwindows = 8,
1082
        .maxtl = 5,
1083
        .features = CPU_DEFAULT_FEATURES,
1084
    },
1085
    {
1086
        .name = "Sun UltraSparc IIIi",
1087
        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
1088
        .fpu_version = 0x00000000,
1089
        .mmu_version = mmu_us_12,
1090
        .nwindows = 8,
1091
        .maxtl = 5,
1092
        .features = CPU_DEFAULT_FEATURES,
1093
    },
1094
    {
1095
        .name = "Sun UltraSparc IV",
1096
        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
1097
        .fpu_version = 0x00000000,
1098
        .mmu_version = mmu_us_4,
1099
        .nwindows = 8,
1100
        .maxtl = 5,
1101
        .features = CPU_DEFAULT_FEATURES,
1102
    },
1103
    {
1104
        .name = "Sun UltraSparc IV+",
1105
        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
1106
        .fpu_version = 0x00000000,
1107
        .mmu_version = mmu_us_12,
1108
        .nwindows = 8,
1109
        .maxtl = 5,
1110
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1111
    },
1112
    {
1113
        .name = "Sun UltraSparc IIIi+",
1114
        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
1115
        .fpu_version = 0x00000000,
1116
        .mmu_version = mmu_us_3,
1117
        .nwindows = 8,
1118
        .maxtl = 5,
1119
        .features = CPU_DEFAULT_FEATURES,
1120
    },
1121
    {
1122
        .name = "Sun UltraSparc T1",
1123
        // defined in sparc_ifu_fdp.v and ctu.h
1124
        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
1125
        .fpu_version = 0x00000000,
1126
        .mmu_version = mmu_sun4v,
1127
        .nwindows = 8,
1128
        .maxtl = 6,
1129
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1130
        | CPU_FEATURE_GL,
1131
    },
1132
    {
1133
        .name = "Sun UltraSparc T2",
1134
        // defined in tlu_asi_ctl.v and n2_revid_cust.v
1135
        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
1136
        .fpu_version = 0x00000000,
1137
        .mmu_version = mmu_sun4v,
1138
        .nwindows = 8,
1139
        .maxtl = 6,
1140
        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1141
        | CPU_FEATURE_GL,
1142
    },
1143
    {
1144
        .name = "NEC UltraSparc I",
1145
        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1146
        .fpu_version = 0x00000000,
1147
        .mmu_version = mmu_us_12,
1148
        .nwindows = 8,
1149
        .maxtl = 5,
1150
        .features = CPU_DEFAULT_FEATURES,
1151
    },
1152
#else
1153
    {
1154
        .name = "Fujitsu MB86900",
1155
        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1156
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1157
        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1158
        .mmu_bm = 0x00004000,
1159
        .mmu_ctpr_mask = 0x007ffff0,
1160
        .mmu_cxr_mask = 0x0000003f,
1161
        .mmu_sfsr_mask = 0xffffffff,
1162
        .mmu_trcr_mask = 0xffffffff,
1163
        .nwindows = 7,
1164
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1165
    },
1166
    {
1167
        .name = "Fujitsu MB86904",
1168
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1169
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1170
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1171
        .mmu_bm = 0x00004000,
1172
        .mmu_ctpr_mask = 0x00ffffc0,
1173
        .mmu_cxr_mask = 0x000000ff,
1174
        .mmu_sfsr_mask = 0x00016fff,
1175
        .mmu_trcr_mask = 0x00ffffff,
1176
        .nwindows = 8,
1177
        .features = CPU_DEFAULT_FEATURES,
1178
    },
1179
    {
1180
        .name = "Fujitsu MB86907",
1181
        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1182
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1183
        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1184
        .mmu_bm = 0x00004000,
1185
        .mmu_ctpr_mask = 0xffffffc0,
1186
        .mmu_cxr_mask = 0x000000ff,
1187
        .mmu_sfsr_mask = 0x00016fff,
1188
        .mmu_trcr_mask = 0xffffffff,
1189
        .nwindows = 8,
1190
        .features = CPU_DEFAULT_FEATURES,
1191
    },
1192
    {
1193
        .name = "LSI L64811",
1194
        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1195
        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1196
        .mmu_version = 0x10 << 24,
1197
        .mmu_bm = 0x00004000,
1198
        .mmu_ctpr_mask = 0x007ffff0,
1199
        .mmu_cxr_mask = 0x0000003f,
1200
        .mmu_sfsr_mask = 0xffffffff,
1201
        .mmu_trcr_mask = 0xffffffff,
1202
        .nwindows = 8,
1203
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1204
        CPU_FEATURE_FSMULD,
1205
    },
1206
    {
1207
        .name = "Cypress CY7C601",
1208
        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1209
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1210
        .mmu_version = 0x10 << 24,
1211
        .mmu_bm = 0x00004000,
1212
        .mmu_ctpr_mask = 0x007ffff0,
1213
        .mmu_cxr_mask = 0x0000003f,
1214
        .mmu_sfsr_mask = 0xffffffff,
1215
        .mmu_trcr_mask = 0xffffffff,
1216
        .nwindows = 8,
1217
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1218
        CPU_FEATURE_FSMULD,
1219
    },
1220
    {
1221
        .name = "Cypress CY7C611",
1222
        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1223
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1224
        .mmu_version = 0x10 << 24,
1225
        .mmu_bm = 0x00004000,
1226
        .mmu_ctpr_mask = 0x007ffff0,
1227
        .mmu_cxr_mask = 0x0000003f,
1228
        .mmu_sfsr_mask = 0xffffffff,
1229
        .mmu_trcr_mask = 0xffffffff,
1230
        .nwindows = 8,
1231
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1232
        CPU_FEATURE_FSMULD,
1233
    },
1234
    {
1235
        .name = "TI SuperSparc II",
1236
        .iu_version = 0x40000000,
1237
        .fpu_version = 0 << 17,
1238
        .mmu_version = 0x04000000,
1239
        .mmu_bm = 0x00002000,
1240
        .mmu_ctpr_mask = 0xffffffc0,
1241
        .mmu_cxr_mask = 0x0000ffff,
1242
        .mmu_sfsr_mask = 0xffffffff,
1243
        .mmu_trcr_mask = 0xffffffff,
1244
        .nwindows = 8,
1245
        .features = CPU_DEFAULT_FEATURES,
1246
    },
1247
    {
1248
        .name = "TI MicroSparc I",
1249
        .iu_version = 0x41000000,
1250
        .fpu_version = 4 << 17,
1251
        .mmu_version = 0x41000000,
1252
        .mmu_bm = 0x00004000,
1253
        .mmu_ctpr_mask = 0x007ffff0,
1254
        .mmu_cxr_mask = 0x0000003f,
1255
        .mmu_sfsr_mask = 0x00016fff,
1256
        .mmu_trcr_mask = 0x0000003f,
1257
        .nwindows = 7,
1258
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1259
        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1260
        CPU_FEATURE_FMUL,
1261
    },
1262
    {
1263
        .name = "TI MicroSparc II",
1264
        .iu_version = 0x42000000,
1265
        .fpu_version = 4 << 17,
1266
        .mmu_version = 0x02000000,
1267
        .mmu_bm = 0x00004000,
1268
        .mmu_ctpr_mask = 0x00ffffc0,
1269
        .mmu_cxr_mask = 0x000000ff,
1270
        .mmu_sfsr_mask = 0x00016fff,
1271
        .mmu_trcr_mask = 0x00ffffff,
1272
        .nwindows = 8,
1273
        .features = CPU_DEFAULT_FEATURES,
1274
    },
1275
    {
1276
        .name = "TI MicroSparc IIep",
1277
        .iu_version = 0x42000000,
1278
        .fpu_version = 4 << 17,
1279
        .mmu_version = 0x04000000,
1280
        .mmu_bm = 0x00004000,
1281
        .mmu_ctpr_mask = 0x00ffffc0,
1282
        .mmu_cxr_mask = 0x000000ff,
1283
        .mmu_sfsr_mask = 0x00016bff,
1284
        .mmu_trcr_mask = 0x00ffffff,
1285
        .nwindows = 8,
1286
        .features = CPU_DEFAULT_FEATURES,
1287
    },
1288
    {
1289
        .name = "TI SuperSparc 40", // STP1020NPGA
1290
        .iu_version = 0x41000000,
1291
        .fpu_version = 0 << 17,
1292
        .mmu_version = 0x00000000,
1293
        .mmu_bm = 0x00002000,
1294
        .mmu_ctpr_mask = 0xffffffc0,
1295
        .mmu_cxr_mask = 0x0000ffff,
1296
        .mmu_sfsr_mask = 0xffffffff,
1297
        .mmu_trcr_mask = 0xffffffff,
1298
        .nwindows = 8,
1299
        .features = CPU_DEFAULT_FEATURES,
1300
    },
1301
    {
1302
        .name = "TI SuperSparc 50", // STP1020PGA
1303
        .iu_version = 0x40000000,
1304
        .fpu_version = 0 << 17,
1305
        .mmu_version = 0x04000000,
1306
        .mmu_bm = 0x00002000,
1307
        .mmu_ctpr_mask = 0xffffffc0,
1308
        .mmu_cxr_mask = 0x0000ffff,
1309
        .mmu_sfsr_mask = 0xffffffff,
1310
        .mmu_trcr_mask = 0xffffffff,
1311
        .nwindows = 8,
1312
        .features = CPU_DEFAULT_FEATURES,
1313
    },
1314
    {
1315
        .name = "TI SuperSparc 51",
1316
        .iu_version = 0x43000000,
1317
        .fpu_version = 0 << 17,
1318
        .mmu_version = 0x04000000,
1319
        .mmu_bm = 0x00002000,
1320
        .mmu_ctpr_mask = 0xffffffc0,
1321
        .mmu_cxr_mask = 0x0000ffff,
1322
        .mmu_sfsr_mask = 0xffffffff,
1323
        .mmu_trcr_mask = 0xffffffff,
1324
        .nwindows = 8,
1325
        .features = CPU_DEFAULT_FEATURES,
1326
    },
1327
    {
1328
        .name = "TI SuperSparc 60", // STP1020APGA
1329
        .iu_version = 0x40000000,
1330
        .fpu_version = 0 << 17,
1331
        .mmu_version = 0x03000000,
1332
        .mmu_bm = 0x00002000,
1333
        .mmu_ctpr_mask = 0xffffffc0,
1334
        .mmu_cxr_mask = 0x0000ffff,
1335
        .mmu_sfsr_mask = 0xffffffff,
1336
        .mmu_trcr_mask = 0xffffffff,
1337
        .nwindows = 8,
1338
        .features = CPU_DEFAULT_FEATURES,
1339
    },
1340
    {
1341
        .name = "TI SuperSparc 61",
1342
        .iu_version = 0x44000000,
1343
        .fpu_version = 0 << 17,
1344
        .mmu_version = 0x04000000,
1345
        .mmu_bm = 0x00002000,
1346
        .mmu_ctpr_mask = 0xffffffc0,
1347
        .mmu_cxr_mask = 0x0000ffff,
1348
        .mmu_sfsr_mask = 0xffffffff,
1349
        .mmu_trcr_mask = 0xffffffff,
1350
        .nwindows = 8,
1351
        .features = CPU_DEFAULT_FEATURES,
1352
    },
1353
    {
1354
        .name = "Ross RT625",
1355
        .iu_version = 0x1e000000,
1356
        .fpu_version = 1 << 17,
1357
        .mmu_version = 0x1e000000,
1358
        .mmu_bm = 0x00004000,
1359
        .mmu_ctpr_mask = 0x007ffff0,
1360
        .mmu_cxr_mask = 0x0000003f,
1361
        .mmu_sfsr_mask = 0xffffffff,
1362
        .mmu_trcr_mask = 0xffffffff,
1363
        .nwindows = 8,
1364
        .features = CPU_DEFAULT_FEATURES,
1365
    },
1366
    {
1367
        .name = "Ross RT620",
1368
        .iu_version = 0x1f000000,
1369
        .fpu_version = 1 << 17,
1370
        .mmu_version = 0x1f000000,
1371
        .mmu_bm = 0x00004000,
1372
        .mmu_ctpr_mask = 0x007ffff0,
1373
        .mmu_cxr_mask = 0x0000003f,
1374
        .mmu_sfsr_mask = 0xffffffff,
1375
        .mmu_trcr_mask = 0xffffffff,
1376
        .nwindows = 8,
1377
        .features = CPU_DEFAULT_FEATURES,
1378
    },
1379
    {
1380
        .name = "BIT B5010",
1381
        .iu_version = 0x20000000,
1382
        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1383
        .mmu_version = 0x20000000,
1384
        .mmu_bm = 0x00004000,
1385
        .mmu_ctpr_mask = 0x007ffff0,
1386
        .mmu_cxr_mask = 0x0000003f,
1387
        .mmu_sfsr_mask = 0xffffffff,
1388
        .mmu_trcr_mask = 0xffffffff,
1389
        .nwindows = 8,
1390
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1391
        CPU_FEATURE_FSMULD,
1392
    },
1393
    {
1394
        .name = "Matsushita MN10501",
1395
        .iu_version = 0x50000000,
1396
        .fpu_version = 0 << 17,
1397
        .mmu_version = 0x50000000,
1398
        .mmu_bm = 0x00004000,
1399
        .mmu_ctpr_mask = 0x007ffff0,
1400
        .mmu_cxr_mask = 0x0000003f,
1401
        .mmu_sfsr_mask = 0xffffffff,
1402
        .mmu_trcr_mask = 0xffffffff,
1403
        .nwindows = 8,
1404
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1405
        CPU_FEATURE_FSMULD,
1406
    },
1407
    {
1408
        .name = "Weitek W8601",
1409
        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1410
        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1411
        .mmu_version = 0x10 << 24,
1412
        .mmu_bm = 0x00004000,
1413
        .mmu_ctpr_mask = 0x007ffff0,
1414
        .mmu_cxr_mask = 0x0000003f,
1415
        .mmu_sfsr_mask = 0xffffffff,
1416
        .mmu_trcr_mask = 0xffffffff,
1417
        .nwindows = 8,
1418
        .features = CPU_DEFAULT_FEATURES,
1419
    },
1420
    {
1421
        .name = "LEON2",
1422
        .iu_version = 0xf2000000,
1423
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1424
        .mmu_version = 0xf2000000,
1425
        .mmu_bm = 0x00004000,
1426
        .mmu_ctpr_mask = 0x007ffff0,
1427
        .mmu_cxr_mask = 0x0000003f,
1428
        .mmu_sfsr_mask = 0xffffffff,
1429
        .mmu_trcr_mask = 0xffffffff,
1430
        .nwindows = 8,
1431
        .features = CPU_DEFAULT_FEATURES,
1432
    },
1433
    {
1434
        .name = "LEON3",
1435
        .iu_version = 0xf3000000,
1436
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1437
        .mmu_version = 0xf3000000,
1438
        .mmu_bm = 0x00004000,
1439
        .mmu_ctpr_mask = 0x007ffff0,
1440
        .mmu_cxr_mask = 0x0000003f,
1441
        .mmu_sfsr_mask = 0xffffffff,
1442
        .mmu_trcr_mask = 0xffffffff,
1443
        .nwindows = 8,
1444
        .features = CPU_DEFAULT_FEATURES,
1445
    },
1446
#endif
1447
};
1448

    
1449
static const char * const feature_name[] = {
1450
    "float",
1451
    "float128",
1452
    "swap",
1453
    "mul",
1454
    "div",
1455
    "flush",
1456
    "fsqrt",
1457
    "fmul",
1458
    "vis1",
1459
    "vis2",
1460
    "fsmuld",
1461
    "hypv",
1462
    "cmt",
1463
    "gl",
1464
};
1465

    
1466
static void print_features(FILE *f,
1467
                           int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1468
                           uint32_t features, const char *prefix)
1469
{
1470
    unsigned int i;
1471

    
1472
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1473
        if (feature_name[i] && (features & (1 << i))) {
1474
            if (prefix)
1475
                (*cpu_fprintf)(f, "%s", prefix);
1476
            (*cpu_fprintf)(f, "%s ", feature_name[i]);
1477
        }
1478
}
1479

    
1480
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1481
{
1482
    unsigned int i;
1483

    
1484
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1485
        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1486
            *features |= 1 << i;
1487
            return;
1488
        }
1489
    fprintf(stderr, "CPU feature %s not found\n", flagname);
1490
}
1491

    
1492
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1493
{
1494
    unsigned int i;
1495
    const sparc_def_t *def = NULL;
1496
    char *s = strdup(cpu_model);
1497
    char *featurestr, *name = strtok(s, ",");
1498
    uint32_t plus_features = 0;
1499
    uint32_t minus_features = 0;
1500
    long long iu_version;
1501
    uint32_t fpu_version, mmu_version, nwindows;
1502

    
1503
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1504
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
1505
            def = &sparc_defs[i];
1506
        }
1507
    }
1508
    if (!def)
1509
        goto error;
1510
    memcpy(cpu_def, def, sizeof(*def));
1511

    
1512
    featurestr = strtok(NULL, ",");
1513
    while (featurestr) {
1514
        char *val;
1515

    
1516
        if (featurestr[0] == '+') {
1517
            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1518
        } else if (featurestr[0] == '-') {
1519
            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1520
        } else if ((val = strchr(featurestr, '='))) {
1521
            *val = 0; val++;
1522
            if (!strcmp(featurestr, "iu_version")) {
1523
                char *err;
1524

    
1525
                iu_version = strtoll(val, &err, 0);
1526
                if (!*val || *err) {
1527
                    fprintf(stderr, "bad numerical value %s\n", val);
1528
                    goto error;
1529
                }
1530
                cpu_def->iu_version = iu_version;
1531
#ifdef DEBUG_FEATURES
1532
                fprintf(stderr, "iu_version %llx\n", iu_version);
1533
#endif
1534
            } else if (!strcmp(featurestr, "fpu_version")) {
1535
                char *err;
1536

    
1537
                fpu_version = strtol(val, &err, 0);
1538
                if (!*val || *err) {
1539
                    fprintf(stderr, "bad numerical value %s\n", val);
1540
                    goto error;
1541
                }
1542
                cpu_def->fpu_version = fpu_version;
1543
#ifdef DEBUG_FEATURES
1544
                fprintf(stderr, "fpu_version %llx\n", fpu_version);
1545
#endif
1546
            } else if (!strcmp(featurestr, "mmu_version")) {
1547
                char *err;
1548

    
1549
                mmu_version = strtol(val, &err, 0);
1550
                if (!*val || *err) {
1551
                    fprintf(stderr, "bad numerical value %s\n", val);
1552
                    goto error;
1553
                }
1554
                cpu_def->mmu_version = mmu_version;
1555
#ifdef DEBUG_FEATURES
1556
                fprintf(stderr, "mmu_version %llx\n", mmu_version);
1557
#endif
1558
            } else if (!strcmp(featurestr, "nwindows")) {
1559
                char *err;
1560

    
1561
                nwindows = strtol(val, &err, 0);
1562
                if (!*val || *err || nwindows > MAX_NWINDOWS ||
1563
                    nwindows < MIN_NWINDOWS) {
1564
                    fprintf(stderr, "bad numerical value %s\n", val);
1565
                    goto error;
1566
                }
1567
                cpu_def->nwindows = nwindows;
1568
#ifdef DEBUG_FEATURES
1569
                fprintf(stderr, "nwindows %d\n", nwindows);
1570
#endif
1571
            } else {
1572
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
1573
                goto error;
1574
            }
1575
        } else {
1576
            fprintf(stderr, "feature string `%s' not in format "
1577
                    "(+feature|-feature|feature=xyz)\n", featurestr);
1578
            goto error;
1579
        }
1580
        featurestr = strtok(NULL, ",");
1581
    }
1582
    cpu_def->features |= plus_features;
1583
    cpu_def->features &= ~minus_features;
1584
#ifdef DEBUG_FEATURES
1585
    print_features(stderr, fprintf, cpu_def->features, NULL);
1586
#endif
1587
    free(s);
1588
    return 0;
1589

    
1590
 error:
1591
    free(s);
1592
    return -1;
1593
}
1594

    
1595
void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1596
{
1597
    unsigned int i;
1598

    
1599
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1600
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1601
                       sparc_defs[i].name,
1602
                       sparc_defs[i].iu_version,
1603
                       sparc_defs[i].fpu_version,
1604
                       sparc_defs[i].mmu_version,
1605
                       sparc_defs[i].nwindows);
1606
        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1607
                       ~sparc_defs[i].features, "-");
1608
        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1609
                       sparc_defs[i].features, "+");
1610
        (*cpu_fprintf)(f, "\n");
1611
    }
1612
    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1613
    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1614
    (*cpu_fprintf)(f, "\n");
1615
    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1616
    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1617
    (*cpu_fprintf)(f, "\n");
1618
    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1619
                   "fpu_version mmu_version nwindows\n");
1620
}
1621

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

    
1624
void cpu_dump_state(CPUState *env, FILE *f,
1625
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1626
                    int flags)
1627
{
1628
    int i, x;
1629

    
1630
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
1631
                env->npc);
1632
    cpu_fprintf(f, "General Registers:\n");
1633
    for (i = 0; i < 4; i++)
1634
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1635
    cpu_fprintf(f, "\n");
1636
    for (; i < 8; i++)
1637
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1638
    cpu_fprintf(f, "\nCurrent Register Window:\n");
1639
    for (x = 0; x < 3; x++) {
1640
        for (i = 0; i < 4; i++)
1641
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1642
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1643
                    env->regwptr[i + x * 8]);
1644
        cpu_fprintf(f, "\n");
1645
        for (; i < 8; i++)
1646
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1647
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1648
                    env->regwptr[i + x * 8]);
1649
        cpu_fprintf(f, "\n");
1650
    }
1651
    cpu_fprintf(f, "\nFloating Point Registers:\n");
1652
    for (i = 0; i < 32; i++) {
1653
        if ((i & 3) == 0)
1654
            cpu_fprintf(f, "%%f%02d:", i);
1655
        cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1656
        if ((i & 3) == 3)
1657
            cpu_fprintf(f, "\n");
1658
    }
1659
#ifdef TARGET_SPARC64
1660
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1661
                env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1662
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1663
                "cleanwin %d cwp %d\n",
1664
                env->cansave, env->canrestore, env->otherwin, env->wstate,
1665
                env->cleanwin, env->nwindows - 1 - env->cwp);
1666
#else
1667
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1668
                GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1669
                GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1670
                env->psrs?'S':'-', env->psrps?'P':'-',
1671
                env->psret?'E':'-', env->wim);
1672
#endif
1673
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1674
}
1675

    
1676
#ifdef TARGET_SPARC64
1677
#if !defined(CONFIG_USER_ONLY)
1678
#include "qemu-common.h"
1679
#include "hw/irq.h"
1680
#include "qemu-timer.h"
1681
#endif
1682

    
1683
void helper_tick_set_count(void *opaque, uint64_t count)
1684
{
1685
#if !defined(CONFIG_USER_ONLY)
1686
    ptimer_set_count(opaque, -count);
1687
#endif
1688
}
1689

    
1690
uint64_t helper_tick_get_count(void *opaque)
1691
{
1692
#if !defined(CONFIG_USER_ONLY)
1693
    return -ptimer_get_count(opaque);
1694
#else
1695
    return 0;
1696
#endif
1697
}
1698

    
1699
void helper_tick_set_limit(void *opaque, uint64_t limit)
1700
{
1701
#if !defined(CONFIG_USER_ONLY)
1702
    ptimer_set_limit(opaque, -limit, 0);
1703
#endif
1704
}
1705
#endif