~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to target-sparc/helper.c

  • Committer: pbrook
  • Date: 2006-10-22 00:18:54 UTC
  • Revision ID: git-v1:e6e5906b6e0a81718066ca43aef57515026c6624
ColdFire target.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2196 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  sparc helpers
3
 
 *
 
3
 * 
4
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5
5
 *
6
6
 * This library is free software; you can redistribute it and/or
27
27
 
28
28
#include "cpu.h"
29
29
#include "exec-all.h"
30
 
#include "qemu-common.h"
31
 
#include "helper.h"
32
30
 
33
31
//#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
 
};
51
 
 
52
 
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
53
32
 
54
33
/* Sparc MMU emulation */
55
34
 
67
46
    spin_unlock(&global_cpu_lock);
68
47
}
69
48
 
70
 
#if defined(CONFIG_USER_ONLY)
 
49
#if defined(CONFIG_USER_ONLY) 
71
50
 
72
 
int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
73
 
                               int mmu_idx, int is_softmmu)
 
51
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
 
52
                               int is_user, int is_softmmu)
74
53
{
75
54
    if (rw & 2)
76
 
        env1->exception_index = TT_TFAULT;
 
55
        env->exception_index = TT_TFAULT;
77
56
    else
78
 
        env1->exception_index = TT_DFAULT;
 
57
        env->exception_index = TT_DFAULT;
79
58
    return 1;
80
59
}
81
60
 
119
98
    }
120
99
};
121
100
 
122
 
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
123
 
                                int *prot, int *access_index,
124
 
                                target_ulong address, int rw, int mmu_idx)
 
101
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
 
102
                          int *access_index, target_ulong address, int rw,
 
103
                          int is_user)
125
104
{
126
105
    int access_perms = 0;
127
106
    target_phys_addr_t pde_ptr;
128
107
    uint32_t pde;
129
108
    target_ulong virt_addr;
130
 
    int error_code = 0, is_dirty, is_user;
 
109
    int error_code = 0, is_dirty;
131
110
    unsigned long page_offset;
132
111
 
133
 
    is_user = mmu_idx == MMU_USER_IDX;
134
112
    virt_addr = address & TARGET_PAGE_MASK;
135
 
 
136
113
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
137
 
        // Boot mode: instruction fetches are taken from PROM
138
 
        if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
139
 
            *physical = env->prom_addr | (address & 0x7ffffULL);
140
 
            *prot = PAGE_READ | PAGE_EXEC;
141
 
            return 0;
142
 
        }
143
 
        *physical = address;
 
114
        *physical = address;
144
115
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
145
116
        return 0;
146
117
    }
147
118
 
148
119
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
149
 
    *physical = 0xffffffffffff0000ULL;
 
120
    *physical = 0xfffff000;
150
121
 
151
122
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
152
123
    /* Context base + context number */
157
128
    switch (pde & PTE_ENTRYTYPE_MASK) {
158
129
    default:
159
130
    case 0: /* Invalid */
160
 
        return 1 << 2;
 
131
        return 1 << 2;
161
132
    case 2: /* L0 PTE, maybe should not happen? */
162
133
    case 3: /* Reserved */
163
134
        return 4 << 2;
164
135
    case 1: /* L0 PDE */
165
 
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
 
136
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
166
137
        pde = ldl_phys(pde_ptr);
167
138
 
168
 
        switch (pde & PTE_ENTRYTYPE_MASK) {
169
 
        default:
170
 
        case 0: /* Invalid */
171
 
            return (1 << 8) | (1 << 2);
172
 
        case 3: /* Reserved */
173
 
            return (1 << 8) | (4 << 2);
174
 
        case 1: /* L1 PDE */
175
 
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
 
139
        switch (pde & PTE_ENTRYTYPE_MASK) {
 
140
        default:
 
141
        case 0: /* Invalid */
 
142
            return (1 << 8) | (1 << 2);
 
143
        case 3: /* Reserved */
 
144
            return (1 << 8) | (4 << 2);
 
145
        case 1: /* L1 PDE */
 
146
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
176
147
            pde = ldl_phys(pde_ptr);
177
148
 
178
 
            switch (pde & PTE_ENTRYTYPE_MASK) {
179
 
            default:
180
 
            case 0: /* Invalid */
181
 
                return (2 << 8) | (1 << 2);
182
 
            case 3: /* Reserved */
183
 
                return (2 << 8) | (4 << 2);
184
 
            case 1: /* L2 PDE */
185
 
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
 
149
            switch (pde & PTE_ENTRYTYPE_MASK) {
 
150
            default:
 
151
            case 0: /* Invalid */
 
152
                return (2 << 8) | (1 << 2);
 
153
            case 3: /* Reserved */
 
154
                return (2 << 8) | (4 << 2);
 
155
            case 1: /* L2 PDE */
 
156
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
186
157
                pde = ldl_phys(pde_ptr);
187
158
 
188
 
                switch (pde & PTE_ENTRYTYPE_MASK) {
189
 
                default:
190
 
                case 0: /* Invalid */
191
 
                    return (3 << 8) | (1 << 2);
192
 
                case 1: /* PDE, should not happen */
193
 
                case 3: /* Reserved */
194
 
                    return (3 << 8) | (4 << 2);
195
 
                case 2: /* L3 PTE */
196
 
                    virt_addr = address & TARGET_PAGE_MASK;
197
 
                    page_offset = (address & TARGET_PAGE_MASK) &
198
 
                        (TARGET_PAGE_SIZE - 1);
199
 
                }
200
 
                break;
201
 
            case 2: /* L2 PTE */
202
 
                virt_addr = address & ~0x3ffff;
203
 
                page_offset = address & 0x3ffff;
204
 
            }
205
 
            break;
206
 
        case 2: /* L1 PTE */
207
 
            virt_addr = address & ~0xffffff;
208
 
            page_offset = address & 0xffffff;
209
 
        }
 
159
                switch (pde & PTE_ENTRYTYPE_MASK) {
 
160
                default:
 
161
                case 0: /* Invalid */
 
162
                    return (3 << 8) | (1 << 2);
 
163
                case 1: /* PDE, should not happen */
 
164
                case 3: /* Reserved */
 
165
                    return (3 << 8) | (4 << 2);
 
166
                case 2: /* L3 PTE */
 
167
                    virt_addr = address & TARGET_PAGE_MASK;
 
168
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
 
169
                }
 
170
                break;
 
171
            case 2: /* L2 PTE */
 
172
                virt_addr = address & ~0x3ffff;
 
173
                page_offset = address & 0x3ffff;
 
174
            }
 
175
            break;
 
176
        case 2: /* L1 PTE */
 
177
            virt_addr = address & ~0xffffff;
 
178
            page_offset = address & 0xffffff;
 
179
        }
210
180
    }
211
181
 
212
182
    /* update page modified and dirty bits */
213
183
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
214
184
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
215
 
        pde |= PG_ACCESSED_MASK;
216
 
        if (is_dirty)
217
 
            pde |= PG_MODIFIED_MASK;
 
185
        pde |= PG_ACCESSED_MASK;
 
186
        if (is_dirty)
 
187
            pde |= PG_MODIFIED_MASK;
218
188
        stl_phys_notdirty(pde_ptr, pde);
219
189
    }
220
190
    /* check access */
221
191
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
222
192
    error_code = access_table[*access_index][access_perms];
223
193
    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
224
 
        return error_code;
 
194
        return error_code;
225
195
 
226
196
    /* the page can be put in the TLB */
227
197
    *prot = perm_table[is_user][access_perms];
233
203
 
234
204
    /* Even if large ptes, we map only one 4KB page in the cache to
235
205
       avoid filling it too fast */
236
 
    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
 
206
    *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
237
207
    return error_code;
238
208
}
239
209
 
240
210
/* Perform address translation */
241
211
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
242
 
                              int mmu_idx, int is_softmmu)
 
212
                              int is_user, int is_softmmu)
243
213
{
244
214
    target_phys_addr_t paddr;
245
 
    target_ulong vaddr;
 
215
    unsigned long vaddr;
246
216
    int error_code = 0, prot, ret = 0, access_index;
247
217
 
248
 
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
249
 
                                      address, rw, mmu_idx);
 
218
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
250
219
    if (error_code == 0) {
251
 
        vaddr = address & TARGET_PAGE_MASK;
252
 
        paddr &= TARGET_PAGE_MASK;
 
220
        vaddr = address & TARGET_PAGE_MASK;
 
221
        paddr &= TARGET_PAGE_MASK;
253
222
#ifdef DEBUG_MMU
254
 
        printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
255
 
               TARGET_FMT_lx "\n", address, paddr, vaddr);
 
223
        printf("Translate at 0x%lx -> 0x%lx, vaddr 0x%lx\n", (long)address, (long)paddr, (long)vaddr);
256
224
#endif
257
 
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
258
 
        return ret;
 
225
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
 
226
        return ret;
259
227
    }
260
228
 
261
229
    if (env->mmuregs[3]) /* Fault status register */
262
 
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
 
230
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
263
231
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
264
232
    env->mmuregs[4] = address; /* Fault address register */
265
233
 
268
236
        // permissions. If no mapping is available, redirect accesses to
269
237
        // neverland. Fake/overridden mappings will be flushed when
270
238
        // switching to normal mode.
271
 
        vaddr = address & TARGET_PAGE_MASK;
 
239
        vaddr = address & TARGET_PAGE_MASK;
272
240
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
273
 
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
274
 
        return ret;
 
241
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
 
242
        return ret;
275
243
    } else {
276
244
        if (rw & 2)
277
245
            env->exception_index = TT_TFAULT;
287
255
    uint32_t pde;
288
256
 
289
257
    /* Context base + context number */
290
 
    pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
291
 
        (env->mmuregs[2] << 2);
 
258
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
292
259
    pde = ldl_phys(pde_ptr);
293
260
 
294
261
    switch (pde & PTE_ENTRYTYPE_MASK) {
296
263
    case 0: /* Invalid */
297
264
    case 2: /* PTE, maybe should not happen? */
298
265
    case 3: /* Reserved */
299
 
        return 0;
 
266
        return 0;
300
267
    case 1: /* L1 PDE */
301
 
        if (mmulev == 3)
302
 
            return pde;
303
 
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
 
268
        if (mmulev == 3)
 
269
            return pde;
 
270
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
304
271
        pde = ldl_phys(pde_ptr);
305
272
 
306
 
        switch (pde & PTE_ENTRYTYPE_MASK) {
307
 
        default:
308
 
        case 0: /* Invalid */
309
 
        case 3: /* Reserved */
310
 
            return 0;
311
 
        case 2: /* L1 PTE */
312
 
            return pde;
313
 
        case 1: /* L2 PDE */
314
 
            if (mmulev == 2)
315
 
                return pde;
316
 
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
 
273
        switch (pde & PTE_ENTRYTYPE_MASK) {
 
274
        default:
 
275
        case 0: /* Invalid */
 
276
        case 3: /* Reserved */
 
277
            return 0;
 
278
        case 2: /* L1 PTE */
 
279
            return pde;
 
280
        case 1: /* L2 PDE */
 
281
            if (mmulev == 2)
 
282
                return pde;
 
283
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
317
284
            pde = ldl_phys(pde_ptr);
318
285
 
319
 
            switch (pde & PTE_ENTRYTYPE_MASK) {
320
 
            default:
321
 
            case 0: /* Invalid */
322
 
            case 3: /* Reserved */
323
 
                return 0;
324
 
            case 2: /* L2 PTE */
325
 
                return pde;
326
 
            case 1: /* L3 PDE */
327
 
                if (mmulev == 1)
328
 
                    return pde;
329
 
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
 
286
            switch (pde & PTE_ENTRYTYPE_MASK) {
 
287
            default:
 
288
            case 0: /* Invalid */
 
289
            case 3: /* Reserved */
 
290
                return 0;
 
291
            case 2: /* L2 PTE */
 
292
                return pde;
 
293
            case 1: /* L3 PDE */
 
294
                if (mmulev == 1)
 
295
                    return pde;
 
296
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
330
297
                pde = ldl_phys(pde_ptr);
331
298
 
332
 
                switch (pde & PTE_ENTRYTYPE_MASK) {
333
 
                default:
334
 
                case 0: /* Invalid */
335
 
                case 1: /* PDE, should not happen */
336
 
                case 3: /* Reserved */
337
 
                    return 0;
338
 
                case 2: /* L3 PTE */
339
 
                    return pde;
340
 
                }
341
 
            }
342
 
        }
 
299
                switch (pde & PTE_ENTRYTYPE_MASK) {
 
300
                default:
 
301
                case 0: /* Invalid */
 
302
                case 1: /* PDE, should not happen */
 
303
                case 3: /* Reserved */
 
304
                    return 0;
 
305
                case 2: /* L3 PTE */
 
306
                    return pde;
 
307
                }
 
308
            }
 
309
        }
343
310
    }
344
311
    return 0;
345
312
}
347
314
#ifdef DEBUG_MMU
348
315
void dump_mmu(CPUState *env)
349
316
{
350
 
    target_ulong va, va1, va2;
351
 
    unsigned int n, m, o;
352
 
    target_phys_addr_t pde_ptr, pa;
 
317
     target_ulong va, va1, va2;
 
318
     unsigned int n, m, o;
 
319
     target_phys_addr_t pde_ptr, pa;
353
320
    uint32_t pde;
354
321
 
355
322
    printf("MMU dump:\n");
356
323
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
357
324
    pde = ldl_phys(pde_ptr);
358
 
    printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
359
 
           (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
 
325
    printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
360
326
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
361
 
        pde = mmu_probe(env, va, 2);
362
 
        if (pde) {
363
 
            pa = cpu_get_phys_page_debug(env, va);
364
 
            printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
365
 
                   " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
366
 
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
367
 
                pde = mmu_probe(env, va1, 1);
368
 
                if (pde) {
369
 
                    pa = cpu_get_phys_page_debug(env, va1);
370
 
                    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
371
 
                           " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
372
 
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
373
 
                        pde = mmu_probe(env, va2, 0);
374
 
                        if (pde) {
375
 
                            pa = cpu_get_phys_page_debug(env, va2);
376
 
                            printf("  VA: " TARGET_FMT_lx ", PA: "
377
 
                                   TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
378
 
                                   va2, pa, pde);
379
 
                        }
380
 
                    }
381
 
                }
382
 
            }
383
 
        }
 
327
        pde_ptr = mmu_probe(env, va, 2);
 
328
        if (pde_ptr) {
 
329
            pa = cpu_get_phys_page_debug(env, va);
 
330
            printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr);
 
331
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
 
332
                pde_ptr = mmu_probe(env, va1, 1);
 
333
                if (pde_ptr) {
 
334
                    pa = cpu_get_phys_page_debug(env, va1);
 
335
                    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr);
 
336
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
 
337
                        pde_ptr = mmu_probe(env, va2, 0);
 
338
                        if (pde_ptr) {
 
339
                            pa = cpu_get_phys_page_debug(env, va2);
 
340
                            printf("  VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr);
 
341
                        }
 
342
                    }
 
343
                }
 
344
            }
 
345
        }
384
346
    }
385
347
    printf("MMU dump ends\n");
386
348
}
390
352
/*
391
353
 * UltraSparc IIi I/DMMUs
392
354
 */
393
 
static int get_physical_address_data(CPUState *env,
394
 
                                     target_phys_addr_t *physical, int *prot,
395
 
                                     target_ulong address, int rw, int is_user)
 
355
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
 
356
                          int *access_index, target_ulong address, int rw,
 
357
                          int is_user)
396
358
{
397
359
    target_ulong mask;
398
360
    unsigned int i;
399
361
 
400
362
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
401
 
        *physical = address;
402
 
        *prot = PAGE_READ | PAGE_WRITE;
 
363
        *physical = address;
 
364
        *prot = PAGE_READ | PAGE_WRITE;
403
365
        return 0;
404
366
    }
405
367
 
406
368
    for (i = 0; i < 64; i++) {
407
 
        switch ((env->dtlb_tte[i] >> 61) & 3) {
408
 
        default:
409
 
        case 0x0: // 8k
410
 
            mask = 0xffffffffffffe000ULL;
411
 
            break;
412
 
        case 0x1: // 64k
413
 
            mask = 0xffffffffffff0000ULL;
414
 
            break;
415
 
        case 0x2: // 512k
416
 
            mask = 0xfffffffffff80000ULL;
417
 
            break;
418
 
        case 0x3: // 4M
419
 
            mask = 0xffffffffffc00000ULL;
420
 
            break;
421
 
        }
422
 
        // ctx match, vaddr match?
423
 
        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
424
 
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
425
 
            // valid, access ok?
426
 
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
427
 
                ((env->dtlb_tte[i] & 0x4) && is_user) ||
428
 
                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
429
 
                if (env->dmmuregs[3]) /* Fault status register */
430
 
                    env->dmmuregs[3] = 2; /* overflow (not read before
431
 
                                             another fault) */
432
 
                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
433
 
                env->dmmuregs[4] = address; /* Fault address register */
434
 
                env->exception_index = TT_DFAULT;
 
369
        switch ((env->dtlb_tte[i] >> 61) & 3) {
 
370
        default:
 
371
        case 0x0: // 8k
 
372
            mask = 0xffffffffffffe000ULL;
 
373
            break;
 
374
        case 0x1: // 64k
 
375
            mask = 0xffffffffffff0000ULL;
 
376
            break;
 
377
        case 0x2: // 512k
 
378
            mask = 0xfffffffffff80000ULL;
 
379
            break;
 
380
        case 0x3: // 4M
 
381
            mask = 0xffffffffffc00000ULL;
 
382
            break;
 
383
        }
 
384
        // ctx match, vaddr match?
 
385
        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
 
386
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
 
387
            // valid, access ok?
 
388
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
 
389
                ((env->dtlb_tte[i] & 0x4) && is_user) ||
 
390
                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
 
391
                if (env->dmmuregs[3]) /* Fault status register */
 
392
                    env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
 
393
                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
 
394
                env->dmmuregs[4] = address; /* Fault address register */
 
395
                env->exception_index = TT_DFAULT;
435
396
#ifdef DEBUG_MMU
436
 
                printf("DFAULT at 0x%" PRIx64 "\n", address);
 
397
                printf("DFAULT at 0x%" PRIx64 "\n", address);
437
398
#endif
438
 
                return 1;
439
 
            }
440
 
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
441
 
                (address & ~mask & 0x1fffffff000ULL);
442
 
            *prot = PAGE_READ;
443
 
            if (env->dtlb_tte[i] & 0x2)
444
 
                *prot |= PAGE_WRITE;
445
 
            return 0;
446
 
        }
 
399
                return 1;
 
400
            }
 
401
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
 
402
            *prot = PAGE_READ;
 
403
            if (env->dtlb_tte[i] & 0x2)
 
404
                *prot |= PAGE_WRITE;
 
405
            return 0;
 
406
        }
447
407
    }
448
408
#ifdef DEBUG_MMU
449
409
    printf("DMISS at 0x%" PRIx64 "\n", address);
452
412
    return 1;
453
413
}
454
414
 
455
 
static int get_physical_address_code(CPUState *env,
456
 
                                     target_phys_addr_t *physical, int *prot,
457
 
                                     target_ulong address, int is_user)
 
415
static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
 
416
                          int *access_index, target_ulong address, int rw,
 
417
                          int is_user)
458
418
{
459
419
    target_ulong mask;
460
420
    unsigned int i;
461
421
 
462
422
    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
463
 
        *physical = address;
464
 
        *prot = PAGE_EXEC;
 
423
        *physical = address;
 
424
        *prot = PAGE_EXEC;
465
425
        return 0;
466
426
    }
467
427
 
468
428
    for (i = 0; i < 64; i++) {
469
 
        switch ((env->itlb_tte[i] >> 61) & 3) {
470
 
        default:
471
 
        case 0x0: // 8k
472
 
            mask = 0xffffffffffffe000ULL;
473
 
            break;
474
 
        case 0x1: // 64k
475
 
            mask = 0xffffffffffff0000ULL;
476
 
            break;
477
 
        case 0x2: // 512k
478
 
            mask = 0xfffffffffff80000ULL;
479
 
            break;
480
 
        case 0x3: // 4M
481
 
            mask = 0xffffffffffc00000ULL;
482
 
                break;
483
 
        }
484
 
        // ctx match, vaddr match?
485
 
        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
486
 
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
487
 
            // valid, access ok?
488
 
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
489
 
                ((env->itlb_tte[i] & 0x4) && is_user)) {
490
 
                if (env->immuregs[3]) /* Fault status register */
491
 
                    env->immuregs[3] = 2; /* overflow (not read before
492
 
                                             another fault) */
493
 
                env->immuregs[3] |= (is_user << 3) | 1;
494
 
                env->exception_index = TT_TFAULT;
 
429
        switch ((env->itlb_tte[i] >> 61) & 3) {
 
430
        default:
 
431
        case 0x0: // 8k
 
432
            mask = 0xffffffffffffe000ULL;
 
433
            break;
 
434
        case 0x1: // 64k
 
435
            mask = 0xffffffffffff0000ULL;
 
436
            break;
 
437
        case 0x2: // 512k
 
438
            mask = 0xfffffffffff80000ULL;
 
439
            break;
 
440
        case 0x3: // 4M
 
441
            mask = 0xffffffffffc00000ULL;
 
442
                break;
 
443
        }
 
444
        // ctx match, vaddr match?
 
445
        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
 
446
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
 
447
            // valid, access ok?
 
448
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
 
449
                ((env->itlb_tte[i] & 0x4) && is_user)) {
 
450
                if (env->immuregs[3]) /* Fault status register */
 
451
                    env->immuregs[3] = 2; /* overflow (not read before another fault) */
 
452
                env->immuregs[3] |= (is_user << 3) | 1;
 
453
                env->exception_index = TT_TFAULT;
495
454
#ifdef DEBUG_MMU
496
 
                printf("TFAULT at 0x%" PRIx64 "\n", address);
 
455
                printf("TFAULT at 0x%" PRIx64 "\n", address);
497
456
#endif
498
 
                return 1;
499
 
            }
500
 
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
501
 
                (address & ~mask & 0x1fffffff000ULL);
502
 
            *prot = PAGE_EXEC;
503
 
            return 0;
504
 
        }
 
457
                return 1;
 
458
            }
 
459
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
 
460
            *prot = PAGE_EXEC;
 
461
            return 0;
 
462
        }
505
463
    }
506
464
#ifdef DEBUG_MMU
507
465
    printf("TMISS at 0x%" PRIx64 "\n", address);
510
468
    return 1;
511
469
}
512
470
 
513
 
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
514
 
                                int *prot, int *access_index,
515
 
                                target_ulong address, int rw, int mmu_idx)
 
471
int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
 
472
                          int *access_index, target_ulong address, int rw,
 
473
                          int is_user)
516
474
{
517
 
    int is_user = mmu_idx == MMU_USER_IDX;
518
 
 
519
475
    if (rw == 2)
520
 
        return get_physical_address_code(env, physical, prot, address,
521
 
                                         is_user);
 
476
        return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
522
477
    else
523
 
        return get_physical_address_data(env, physical, prot, address, rw,
524
 
                                         is_user);
 
478
        return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
525
479
}
526
480
 
527
481
/* Perform address translation */
528
482
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
529
 
                              int mmu_idx, int is_softmmu)
 
483
                              int is_user, int is_softmmu)
530
484
{
531
485
    target_ulong virt_addr, vaddr;
532
486
    target_phys_addr_t paddr;
533
487
    int error_code = 0, prot, ret = 0, access_index;
534
488
 
535
 
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
536
 
                                      address, rw, mmu_idx);
 
489
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
537
490
    if (error_code == 0) {
538
 
        virt_addr = address & TARGET_PAGE_MASK;
539
 
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
540
 
                             (TARGET_PAGE_SIZE - 1));
 
491
        virt_addr = address & TARGET_PAGE_MASK;
 
492
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
541
493
#ifdef DEBUG_MMU
542
 
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
543
 
               "\n", address, paddr, vaddr);
 
494
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
544
495
#endif
545
 
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
546
 
        return ret;
 
496
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
 
497
        return ret;
547
498
    }
548
499
    // XXX
549
500
    return 1;
555
506
    unsigned int i;
556
507
    const char *mask;
557
508
 
558
 
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
559
 
           env->dmmuregs[1], env->dmmuregs[2]);
 
509
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", env->dmmuregs[1], env->dmmuregs[2]);
560
510
    if ((env->lsu & DMMU_E) == 0) {
561
 
        printf("DMMU disabled\n");
 
511
        printf("DMMU disabled\n");
562
512
    } else {
563
 
        printf("DMMU dump:\n");
564
 
        for (i = 0; i < 64; i++) {
565
 
            switch ((env->dtlb_tte[i] >> 61) & 3) {
566
 
            default:
567
 
            case 0x0:
568
 
                mask = "  8k";
569
 
                break;
570
 
            case 0x1:
571
 
                mask = " 64k";
572
 
                break;
573
 
            case 0x2:
574
 
                mask = "512k";
575
 
                break;
576
 
            case 0x3:
577
 
                mask = "  4M";
578
 
                break;
579
 
            }
580
 
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
581
 
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
582
 
                       ", %s, %s, %s, %s, ctx %" PRId64 "\n",
583
 
                       env->dtlb_tag[i] & ~0x1fffULL,
584
 
                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
585
 
                       mask,
586
 
                       env->dtlb_tte[i] & 0x4? "priv": "user",
587
 
                       env->dtlb_tte[i] & 0x2? "RW": "RO",
588
 
                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
589
 
                       env->dtlb_tag[i] & 0x1fffULL);
590
 
            }
591
 
        }
 
513
        printf("DMMU dump:\n");
 
514
        for (i = 0; i < 64; i++) {
 
515
            switch ((env->dtlb_tte[i] >> 61) & 3) {
 
516
            default:
 
517
            case 0x0:
 
518
                mask = "  8k";
 
519
                break;
 
520
            case 0x1:
 
521
                mask = " 64k";
 
522
                break;
 
523
            case 0x2:
 
524
                mask = "512k";
 
525
                break;
 
526
            case 0x3:
 
527
                mask = "  4M";
 
528
                break;
 
529
            }
 
530
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
 
531
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
 
532
                       env->dtlb_tag[i] & ~0x1fffULL,
 
533
                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
 
534
                       mask,
 
535
                       env->dtlb_tte[i] & 0x4? "priv": "user",
 
536
                       env->dtlb_tte[i] & 0x2? "RW": "RO",
 
537
                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
 
538
                       env->dtlb_tag[i] & 0x1fffULL);
 
539
            }
 
540
        }
592
541
    }
593
542
    if ((env->lsu & IMMU_E) == 0) {
594
 
        printf("IMMU disabled\n");
 
543
        printf("IMMU disabled\n");
595
544
    } else {
596
 
        printf("IMMU dump:\n");
597
 
        for (i = 0; i < 64; i++) {
598
 
            switch ((env->itlb_tte[i] >> 61) & 3) {
599
 
            default:
600
 
            case 0x0:
601
 
                mask = "  8k";
602
 
                break;
603
 
            case 0x1:
604
 
                mask = " 64k";
605
 
                break;
606
 
            case 0x2:
607
 
                mask = "512k";
608
 
                break;
609
 
            case 0x3:
610
 
                mask = "  4M";
611
 
                break;
612
 
            }
613
 
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
614
 
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
615
 
                       ", %s, %s, %s, ctx %" PRId64 "\n",
616
 
                       env->itlb_tag[i] & ~0x1fffULL,
617
 
                       env->itlb_tte[i] & 0x1ffffffe000ULL,
618
 
                       mask,
619
 
                       env->itlb_tte[i] & 0x4? "priv": "user",
620
 
                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
621
 
                       env->itlb_tag[i] & 0x1fffULL);
622
 
            }
623
 
        }
 
545
        printf("IMMU dump:\n");
 
546
        for (i = 0; i < 64; i++) {
 
547
            switch ((env->itlb_tte[i] >> 61) & 3) {
 
548
            default:
 
549
            case 0x0:
 
550
                mask = "  8k";
 
551
                break;
 
552
            case 0x1:
 
553
                mask = " 64k";
 
554
                break;
 
555
            case 0x2:
 
556
                mask = "512k";
 
557
                break;
 
558
            case 0x3:
 
559
                mask = "  4M";
 
560
                break;
 
561
            }
 
562
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
 
563
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
 
564
                       env->itlb_tag[i] & ~0x1fffULL,
 
565
                       env->itlb_tte[i] & 0x1ffffffe000ULL,
 
566
                       mask,
 
567
                       env->itlb_tte[i] & 0x4? "priv": "user",
 
568
                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
 
569
                       env->itlb_tag[i] & 0x1fffULL);
 
570
            }
 
571
        }
624
572
    }
625
573
}
626
574
#endif /* DEBUG_MMU */
628
576
#endif /* TARGET_SPARC64 */
629
577
#endif /* !CONFIG_USER_ONLY */
630
578
 
631
 
 
632
 
#if defined(CONFIG_USER_ONLY)
633
 
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
634
 
{
635
 
    return addr;
636
 
}
637
 
 
638
 
#else
639
 
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
640
 
{
641
 
    target_phys_addr_t phys_addr;
642
 
    int prot, access_index;
643
 
 
644
 
    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
645
 
                             MMU_KERNEL_IDX) != 0)
646
 
        if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
647
 
                                 0, MMU_KERNEL_IDX) != 0)
648
 
            return -1;
649
 
    if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
650
 
        return -1;
651
 
    return phys_addr;
652
 
}
653
 
#endif
654
 
 
655
 
#ifdef TARGET_SPARC64
656
 
#ifdef DEBUG_PCALL
657
 
static const char * const excp_names[0x50] = {
658
 
    [TT_TFAULT] = "Instruction Access Fault",
659
 
    [TT_TMISS] = "Instruction Access MMU Miss",
660
 
    [TT_CODE_ACCESS] = "Instruction Access Error",
661
 
    [TT_ILL_INSN] = "Illegal Instruction",
662
 
    [TT_PRIV_INSN] = "Privileged Instruction",
663
 
    [TT_NFPU_INSN] = "FPU Disabled",
664
 
    [TT_FP_EXCP] = "FPU Exception",
665
 
    [TT_TOVF] = "Tag Overflow",
666
 
    [TT_CLRWIN] = "Clean Windows",
667
 
    [TT_DIV_ZERO] = "Division By Zero",
668
 
    [TT_DFAULT] = "Data Access Fault",
669
 
    [TT_DMISS] = "Data Access MMU Miss",
670
 
    [TT_DATA_ACCESS] = "Data Access Error",
671
 
    [TT_DPROT] = "Data Protection Error",
672
 
    [TT_UNALIGNED] = "Unaligned Memory Access",
673
 
    [TT_PRIV_ACT] = "Privileged Action",
674
 
    [TT_EXTINT | 0x1] = "External Interrupt 1",
675
 
    [TT_EXTINT | 0x2] = "External Interrupt 2",
676
 
    [TT_EXTINT | 0x3] = "External Interrupt 3",
677
 
    [TT_EXTINT | 0x4] = "External Interrupt 4",
678
 
    [TT_EXTINT | 0x5] = "External Interrupt 5",
679
 
    [TT_EXTINT | 0x6] = "External Interrupt 6",
680
 
    [TT_EXTINT | 0x7] = "External Interrupt 7",
681
 
    [TT_EXTINT | 0x8] = "External Interrupt 8",
682
 
    [TT_EXTINT | 0x9] = "External Interrupt 9",
683
 
    [TT_EXTINT | 0xa] = "External Interrupt 10",
684
 
    [TT_EXTINT | 0xb] = "External Interrupt 11",
685
 
    [TT_EXTINT | 0xc] = "External Interrupt 12",
686
 
    [TT_EXTINT | 0xd] = "External Interrupt 13",
687
 
    [TT_EXTINT | 0xe] = "External Interrupt 14",
688
 
    [TT_EXTINT | 0xf] = "External Interrupt 15",
689
 
};
690
 
#endif
691
 
 
692
 
void do_interrupt(CPUState *env)
693
 
{
694
 
    int intno = env->exception_index;
695
 
 
696
 
#ifdef DEBUG_PCALL
697
 
    if (loglevel & CPU_LOG_INT) {
698
 
        static int count;
699
 
        const char *name;
700
 
 
701
 
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
702
 
            name = "Unknown";
703
 
        else if (intno >= 0x100)
704
 
            name = "Trap Instruction";
705
 
        else if (intno >= 0xc0)
706
 
            name = "Window Fill";
707
 
        else if (intno >= 0x80)
708
 
            name = "Window Spill";
709
 
        else {
710
 
            name = excp_names[intno];
711
 
            if (!name)
712
 
                name = "Unknown";
713
 
        }
714
 
 
715
 
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
716
 
                " SP=%016" PRIx64 "\n",
717
 
                count, name, intno,
718
 
                env->pc,
719
 
                env->npc, env->regwptr[6]);
720
 
        cpu_dump_state(env, logfile, fprintf, 0);
721
 
#if 0
722
 
        {
723
 
            int i;
724
 
            uint8_t *ptr;
725
 
 
726
 
            fprintf(logfile, "       code=");
727
 
            ptr = (uint8_t *)env->pc;
728
 
            for(i = 0; i < 16; i++) {
729
 
                fprintf(logfile, " %02x", ldub(ptr + i));
730
 
            }
731
 
            fprintf(logfile, "\n");
732
 
        }
733
 
#endif
734
 
        count++;
735
 
    }
736
 
#endif
737
 
#if !defined(CONFIG_USER_ONLY)
738
 
    if (env->tl == MAXTL) {
739
 
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state",
740
 
                  env->exception_index);
741
 
        return;
742
 
    }
743
 
#endif
744
 
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
745
 
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
746
 
        GET_CWP64(env);
747
 
    env->tsptr->tpc = env->pc;
748
 
    env->tsptr->tnpc = env->npc;
749
 
    env->tsptr->tt = intno;
750
 
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
751
 
 
752
 
    if (intno == TT_CLRWIN)
753
 
        cpu_set_cwp(env, (env->cwp - 1) & (NWINDOWS - 1));
754
 
    else if ((intno & 0x1c0) == TT_SPILL)
755
 
        cpu_set_cwp(env, (env->cwp - env->cansave - 2) & (NWINDOWS - 1));
756
 
    else if ((intno & 0x1c0) == TT_FILL)
757
 
        cpu_set_cwp(env, (env->cwp + 1) & (NWINDOWS - 1));
758
 
    env->tbr &= ~0x7fffULL;
759
 
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
760
 
    if (env->tl < MAXTL - 1) {
761
 
        env->tl++;
762
 
    } else {
763
 
        env->pstate |= PS_RED;
764
 
        if (env->tl != MAXTL)
765
 
            env->tl++;
766
 
    }
767
 
    env->tsptr = &env->ts[env->tl];
768
 
    env->pc = env->tbr;
769
 
    env->npc = env->pc + 4;
770
 
    env->exception_index = 0;
771
 
}
772
 
#else
773
 
#ifdef DEBUG_PCALL
774
 
static const char * const excp_names[0x80] = {
775
 
    [TT_TFAULT] = "Instruction Access Fault",
776
 
    [TT_ILL_INSN] = "Illegal Instruction",
777
 
    [TT_PRIV_INSN] = "Privileged Instruction",
778
 
    [TT_NFPU_INSN] = "FPU Disabled",
779
 
    [TT_WIN_OVF] = "Window Overflow",
780
 
    [TT_WIN_UNF] = "Window Underflow",
781
 
    [TT_UNALIGNED] = "Unaligned Memory Access",
782
 
    [TT_FP_EXCP] = "FPU Exception",
783
 
    [TT_DFAULT] = "Data Access Fault",
784
 
    [TT_TOVF] = "Tag Overflow",
785
 
    [TT_EXTINT | 0x1] = "External Interrupt 1",
786
 
    [TT_EXTINT | 0x2] = "External Interrupt 2",
787
 
    [TT_EXTINT | 0x3] = "External Interrupt 3",
788
 
    [TT_EXTINT | 0x4] = "External Interrupt 4",
789
 
    [TT_EXTINT | 0x5] = "External Interrupt 5",
790
 
    [TT_EXTINT | 0x6] = "External Interrupt 6",
791
 
    [TT_EXTINT | 0x7] = "External Interrupt 7",
792
 
    [TT_EXTINT | 0x8] = "External Interrupt 8",
793
 
    [TT_EXTINT | 0x9] = "External Interrupt 9",
794
 
    [TT_EXTINT | 0xa] = "External Interrupt 10",
795
 
    [TT_EXTINT | 0xb] = "External Interrupt 11",
796
 
    [TT_EXTINT | 0xc] = "External Interrupt 12",
797
 
    [TT_EXTINT | 0xd] = "External Interrupt 13",
798
 
    [TT_EXTINT | 0xe] = "External Interrupt 14",
799
 
    [TT_EXTINT | 0xf] = "External Interrupt 15",
800
 
    [TT_TOVF] = "Tag Overflow",
801
 
    [TT_CODE_ACCESS] = "Instruction Access Error",
802
 
    [TT_DATA_ACCESS] = "Data Access Error",
803
 
    [TT_DIV_ZERO] = "Division By Zero",
804
 
    [TT_NCP_INSN] = "Coprocessor Disabled",
805
 
};
806
 
#endif
807
 
 
808
 
void do_interrupt(CPUState *env)
809
 
{
810
 
    int cwp, intno = env->exception_index;
811
 
 
812
 
#ifdef DEBUG_PCALL
813
 
    if (loglevel & CPU_LOG_INT) {
814
 
        static int count;
815
 
        const char *name;
816
 
 
817
 
        if (intno < 0 || intno >= 0x100)
818
 
            name = "Unknown";
819
 
        else if (intno >= 0x80)
820
 
            name = "Trap Instruction";
821
 
        else {
822
 
            name = excp_names[intno];
823
 
            if (!name)
824
 
                name = "Unknown";
825
 
        }
826
 
 
827
 
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
828
 
                count, name, intno,
829
 
                env->pc,
830
 
                env->npc, env->regwptr[6]);
831
 
        cpu_dump_state(env, logfile, fprintf, 0);
832
 
#if 0
833
 
        {
834
 
            int i;
835
 
            uint8_t *ptr;
836
 
 
837
 
            fprintf(logfile, "       code=");
838
 
            ptr = (uint8_t *)env->pc;
839
 
            for(i = 0; i < 16; i++) {
840
 
                fprintf(logfile, " %02x", ldub(ptr + i));
841
 
            }
842
 
            fprintf(logfile, "\n");
843
 
        }
844
 
#endif
845
 
        count++;
846
 
    }
847
 
#endif
848
 
#if !defined(CONFIG_USER_ONLY)
849
 
    if (env->psret == 0) {
850
 
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
851
 
                  env->exception_index);
852
 
        return;
853
 
    }
854
 
#endif
855
 
    env->psret = 0;
856
 
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
857
 
    cpu_set_cwp(env, cwp);
858
 
    env->regwptr[9] = env->pc;
859
 
    env->regwptr[10] = env->npc;
860
 
    env->psrps = env->psrs;
861
 
    env->psrs = 1;
862
 
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
863
 
    env->pc = env->tbr;
864
 
    env->npc = env->pc + 4;
865
 
    env->exception_index = 0;
866
 
}
867
 
#endif
868
 
 
869
579
void memcpy32(target_ulong *dst, const target_ulong *src)
870
580
{
871
581
    dst[0] = src[0];
877
587
    dst[6] = src[6];
878
588
    dst[7] = src[7];
879
589
}
880
 
 
881
 
void cpu_reset(CPUSPARCState *env)
882
 
{
883
 
    tlb_flush(env, 1);
884
 
    env->cwp = 0;
885
 
    env->wim = 1;
886
 
    env->regwptr = env->regbase + (env->cwp * 16);
887
 
#if defined(CONFIG_USER_ONLY)
888
 
    env->user_mode_only = 1;
889
 
#ifdef TARGET_SPARC64
890
 
    env->cleanwin = NWINDOWS - 2;
891
 
    env->cansave = NWINDOWS - 2;
892
 
    env->pstate = PS_RMO | PS_PEF | PS_IE;
893
 
    env->asi = 0x82; // Primary no-fault
894
 
#endif
895
 
#else
896
 
    env->psret = 0;
897
 
    env->psrs = 1;
898
 
    env->psrps = 1;
899
 
#ifdef TARGET_SPARC64
900
 
    env->pstate = PS_PRIV;
901
 
    env->hpstate = HS_PRIV;
902
 
    env->pc = 0x1fff0000000ULL;
903
 
    env->tsptr = &env->ts[env->tl];
904
 
#else
905
 
    env->pc = 0;
906
 
    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
907
 
    env->mmuregs[0] |= env->mmu_bm;
908
 
#endif
909
 
    env->npc = env->pc + 4;
910
 
#endif
911
 
}
912
 
 
913
 
static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
914
 
{
915
 
    sparc_def_t def1, *def = &def1;
916
 
 
917
 
    if (cpu_sparc_find_by_name(def, cpu_model) < 0)
918
 
        return -1;
919
 
 
920
 
    env->features = def->features;
921
 
    env->cpu_model_str = cpu_model;
922
 
    env->version = def->iu_version;
923
 
    env->fsr = def->fpu_version;
924
 
#if !defined(TARGET_SPARC64)
925
 
    env->mmu_bm = def->mmu_bm;
926
 
    env->mmu_ctpr_mask = def->mmu_ctpr_mask;
927
 
    env->mmu_cxr_mask = def->mmu_cxr_mask;
928
 
    env->mmu_sfsr_mask = def->mmu_sfsr_mask;
929
 
    env->mmu_trcr_mask = def->mmu_trcr_mask;
930
 
    env->mmuregs[0] |= def->mmu_version;
931
 
    cpu_sparc_set_id(env, 0);
932
 
#endif
933
 
    return 0;
934
 
}
935
 
 
936
 
static void cpu_sparc_close(CPUSPARCState *env)
937
 
{
938
 
    free(env);
939
 
}
940
 
 
941
 
CPUSPARCState *cpu_sparc_init(const char *cpu_model)
942
 
{
943
 
    CPUSPARCState *env;
944
 
 
945
 
    env = qemu_mallocz(sizeof(CPUSPARCState));
946
 
    if (!env)
947
 
        return NULL;
948
 
    cpu_exec_init(env);
949
 
 
950
 
    gen_intermediate_code_init(env);
951
 
 
952
 
    if (cpu_sparc_register(env, cpu_model) < 0) {
953
 
        cpu_sparc_close(env);
954
 
        return NULL;
955
 
    }
956
 
    cpu_reset(env);
957
 
 
958
 
    return env;
959
 
}
960
 
 
961
 
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
962
 
{
963
 
#if !defined(TARGET_SPARC64)
964
 
    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
965
 
#endif
966
 
}
967
 
 
968
 
static const sparc_def_t sparc_defs[] = {
969
 
#ifdef TARGET_SPARC64
970
 
    {
971
 
        .name = "Fujitsu Sparc64",
972
 
        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
973
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
974
 
        .fpu_version = 0x00000000,
975
 
        .mmu_version = 0,
976
 
        .features = CPU_DEFAULT_FEATURES,
977
 
    },
978
 
    {
979
 
        .name = "Fujitsu Sparc64 III",
980
 
        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
981
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
982
 
        .fpu_version = 0x00000000,
983
 
        .mmu_version = 0,
984
 
        .features = CPU_DEFAULT_FEATURES,
985
 
    },
986
 
    {
987
 
        .name = "Fujitsu Sparc64 IV",
988
 
        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
989
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
990
 
        .fpu_version = 0x00000000,
991
 
        .mmu_version = 0,
992
 
        .features = CPU_DEFAULT_FEATURES,
993
 
    },
994
 
    {
995
 
        .name = "Fujitsu Sparc64 V",
996
 
        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
997
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
998
 
        .fpu_version = 0x00000000,
999
 
        .mmu_version = 0,
1000
 
        .features = CPU_DEFAULT_FEATURES,
1001
 
    },
1002
 
    {
1003
 
        .name = "TI UltraSparc I",
1004
 
        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
1005
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1006
 
        .fpu_version = 0x00000000,
1007
 
        .mmu_version = 0,
1008
 
        .features = CPU_DEFAULT_FEATURES,
1009
 
    },
1010
 
    {
1011
 
        .name = "TI UltraSparc II",
1012
 
        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
1013
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1014
 
        .fpu_version = 0x00000000,
1015
 
        .mmu_version = 0,
1016
 
        .features = CPU_DEFAULT_FEATURES,
1017
 
    },
1018
 
    {
1019
 
        .name = "TI UltraSparc IIi",
1020
 
        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
1021
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1022
 
        .fpu_version = 0x00000000,
1023
 
        .mmu_version = 0,
1024
 
        .features = CPU_DEFAULT_FEATURES,
1025
 
    },
1026
 
    {
1027
 
        .name = "TI UltraSparc IIe",
1028
 
        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
1029
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1030
 
        .fpu_version = 0x00000000,
1031
 
        .mmu_version = 0,
1032
 
        .features = CPU_DEFAULT_FEATURES,
1033
 
    },
1034
 
    {
1035
 
        .name = "Sun UltraSparc III",
1036
 
        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
1037
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1038
 
        .fpu_version = 0x00000000,
1039
 
        .mmu_version = 0,
1040
 
        .features = CPU_DEFAULT_FEATURES,
1041
 
    },
1042
 
    {
1043
 
        .name = "Sun UltraSparc III Cu",
1044
 
        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
1045
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1046
 
        .fpu_version = 0x00000000,
1047
 
        .mmu_version = 0,
1048
 
        .features = CPU_DEFAULT_FEATURES,
1049
 
    },
1050
 
    {
1051
 
        .name = "Sun UltraSparc IIIi",
1052
 
        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
1053
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1054
 
        .fpu_version = 0x00000000,
1055
 
        .mmu_version = 0,
1056
 
        .features = CPU_DEFAULT_FEATURES,
1057
 
    },
1058
 
    {
1059
 
        .name = "Sun UltraSparc IV",
1060
 
        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
1061
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1062
 
        .fpu_version = 0x00000000,
1063
 
        .mmu_version = 0,
1064
 
        .features = CPU_DEFAULT_FEATURES,
1065
 
    },
1066
 
    {
1067
 
        .name = "Sun UltraSparc IV+",
1068
 
        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
1069
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1070
 
        .fpu_version = 0x00000000,
1071
 
        .mmu_version = 0,
1072
 
        .features = CPU_DEFAULT_FEATURES,
1073
 
    },
1074
 
    {
1075
 
        .name = "Sun UltraSparc IIIi+",
1076
 
        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
1077
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1078
 
        .fpu_version = 0x00000000,
1079
 
        .mmu_version = 0,
1080
 
        .features = CPU_DEFAULT_FEATURES,
1081
 
    },
1082
 
    {
1083
 
        .name = "NEC UltraSparc I",
1084
 
        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
1085
 
                       | (MAXTL << 8) | (NWINDOWS - 1)),
1086
 
        .fpu_version = 0x00000000,
1087
 
        .mmu_version = 0,
1088
 
        .features = CPU_DEFAULT_FEATURES,
1089
 
    },
1090
 
#else
1091
 
    {
1092
 
        .name = "Fujitsu MB86900",
1093
 
        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1094
 
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1095
 
        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1096
 
        .mmu_bm = 0x00004000,
1097
 
        .mmu_ctpr_mask = 0x007ffff0,
1098
 
        .mmu_cxr_mask = 0x0000003f,
1099
 
        .mmu_sfsr_mask = 0xffffffff,
1100
 
        .mmu_trcr_mask = 0xffffffff,
1101
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1102
 
    },
1103
 
    {
1104
 
        .name = "Fujitsu MB86904",
1105
 
        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1106
 
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1107
 
        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1108
 
        .mmu_bm = 0x00004000,
1109
 
        .mmu_ctpr_mask = 0x00ffffc0,
1110
 
        .mmu_cxr_mask = 0x000000ff,
1111
 
        .mmu_sfsr_mask = 0x00016fff,
1112
 
        .mmu_trcr_mask = 0x00ffffff,
1113
 
        .features = CPU_DEFAULT_FEATURES,
1114
 
    },
1115
 
    {
1116
 
        .name = "Fujitsu MB86907",
1117
 
        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1118
 
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1119
 
        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1120
 
        .mmu_bm = 0x00004000,
1121
 
        .mmu_ctpr_mask = 0xffffffc0,
1122
 
        .mmu_cxr_mask = 0x000000ff,
1123
 
        .mmu_sfsr_mask = 0x00016fff,
1124
 
        .mmu_trcr_mask = 0xffffffff,
1125
 
        .features = CPU_DEFAULT_FEATURES,
1126
 
    },
1127
 
    {
1128
 
        .name = "LSI L64811",
1129
 
        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1130
 
        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1131
 
        .mmu_version = 0x10 << 24,
1132
 
        .mmu_bm = 0x00004000,
1133
 
        .mmu_ctpr_mask = 0x007ffff0,
1134
 
        .mmu_cxr_mask = 0x0000003f,
1135
 
        .mmu_sfsr_mask = 0xffffffff,
1136
 
        .mmu_trcr_mask = 0xffffffff,
1137
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1138
 
        CPU_FEATURE_FSMULD,
1139
 
    },
1140
 
    {
1141
 
        .name = "Cypress CY7C601",
1142
 
        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1143
 
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1144
 
        .mmu_version = 0x10 << 24,
1145
 
        .mmu_bm = 0x00004000,
1146
 
        .mmu_ctpr_mask = 0x007ffff0,
1147
 
        .mmu_cxr_mask = 0x0000003f,
1148
 
        .mmu_sfsr_mask = 0xffffffff,
1149
 
        .mmu_trcr_mask = 0xffffffff,
1150
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1151
 
        CPU_FEATURE_FSMULD,
1152
 
    },
1153
 
    {
1154
 
        .name = "Cypress CY7C611",
1155
 
        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1156
 
        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1157
 
        .mmu_version = 0x10 << 24,
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
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1164
 
        CPU_FEATURE_FSMULD,
1165
 
    },
1166
 
    {
1167
 
        .name = "TI SuperSparc II",
1168
 
        .iu_version = 0x40000000,
1169
 
        .fpu_version = 0 << 17,
1170
 
        .mmu_version = 0x04000000,
1171
 
        .mmu_bm = 0x00002000,
1172
 
        .mmu_ctpr_mask = 0xffffffc0,
1173
 
        .mmu_cxr_mask = 0x0000ffff,
1174
 
        .mmu_sfsr_mask = 0xffffffff,
1175
 
        .mmu_trcr_mask = 0xffffffff,
1176
 
        .features = CPU_DEFAULT_FEATURES,
1177
 
    },
1178
 
    {
1179
 
        .name = "TI MicroSparc I",
1180
 
        .iu_version = 0x41000000,
1181
 
        .fpu_version = 4 << 17,
1182
 
        .mmu_version = 0x41000000,
1183
 
        .mmu_bm = 0x00004000,
1184
 
        .mmu_ctpr_mask = 0x007ffff0,
1185
 
        .mmu_cxr_mask = 0x0000003f,
1186
 
        .mmu_sfsr_mask = 0x00016fff,
1187
 
        .mmu_trcr_mask = 0x0000003f,
1188
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1189
 
        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1190
 
        CPU_FEATURE_FMUL,
1191
 
    },
1192
 
    {
1193
 
        .name = "TI MicroSparc II",
1194
 
        .iu_version = 0x42000000,
1195
 
        .fpu_version = 4 << 17,
1196
 
        .mmu_version = 0x02000000,
1197
 
        .mmu_bm = 0x00004000,
1198
 
        .mmu_ctpr_mask = 0x00ffffc0,
1199
 
        .mmu_cxr_mask = 0x000000ff,
1200
 
        .mmu_sfsr_mask = 0x00016fff,
1201
 
        .mmu_trcr_mask = 0x00ffffff,
1202
 
        .features = CPU_DEFAULT_FEATURES,
1203
 
    },
1204
 
    {
1205
 
        .name = "TI MicroSparc IIep",
1206
 
        .iu_version = 0x42000000,
1207
 
        .fpu_version = 4 << 17,
1208
 
        .mmu_version = 0x04000000,
1209
 
        .mmu_bm = 0x00004000,
1210
 
        .mmu_ctpr_mask = 0x00ffffc0,
1211
 
        .mmu_cxr_mask = 0x000000ff,
1212
 
        .mmu_sfsr_mask = 0x00016bff,
1213
 
        .mmu_trcr_mask = 0x00ffffff,
1214
 
        .features = CPU_DEFAULT_FEATURES,
1215
 
    },
1216
 
    {
1217
 
        .name = "TI SuperSparc 40", // STP1020NPGA
1218
 
        .iu_version = 0x41000000,
1219
 
        .fpu_version = 0 << 17,
1220
 
        .mmu_version = 0x00000000,
1221
 
        .mmu_bm = 0x00002000,
1222
 
        .mmu_ctpr_mask = 0xffffffc0,
1223
 
        .mmu_cxr_mask = 0x0000ffff,
1224
 
        .mmu_sfsr_mask = 0xffffffff,
1225
 
        .mmu_trcr_mask = 0xffffffff,
1226
 
        .features = CPU_DEFAULT_FEATURES,
1227
 
    },
1228
 
    {
1229
 
        .name = "TI SuperSparc 50", // STP1020PGA
1230
 
        .iu_version = 0x40000000,
1231
 
        .fpu_version = 0 << 17,
1232
 
        .mmu_version = 0x04000000,
1233
 
        .mmu_bm = 0x00002000,
1234
 
        .mmu_ctpr_mask = 0xffffffc0,
1235
 
        .mmu_cxr_mask = 0x0000ffff,
1236
 
        .mmu_sfsr_mask = 0xffffffff,
1237
 
        .mmu_trcr_mask = 0xffffffff,
1238
 
        .features = CPU_DEFAULT_FEATURES,
1239
 
    },
1240
 
    {
1241
 
        .name = "TI SuperSparc 51",
1242
 
        .iu_version = 0x43000000,
1243
 
        .fpu_version = 0 << 17,
1244
 
        .mmu_version = 0x04000000,
1245
 
        .mmu_bm = 0x00002000,
1246
 
        .mmu_ctpr_mask = 0xffffffc0,
1247
 
        .mmu_cxr_mask = 0x0000ffff,
1248
 
        .mmu_sfsr_mask = 0xffffffff,
1249
 
        .mmu_trcr_mask = 0xffffffff,
1250
 
        .features = CPU_DEFAULT_FEATURES,
1251
 
    },
1252
 
    {
1253
 
        .name = "TI SuperSparc 60", // STP1020APGA
1254
 
        .iu_version = 0x40000000,
1255
 
        .fpu_version = 0 << 17,
1256
 
        .mmu_version = 0x03000000,
1257
 
        .mmu_bm = 0x00002000,
1258
 
        .mmu_ctpr_mask = 0xffffffc0,
1259
 
        .mmu_cxr_mask = 0x0000ffff,
1260
 
        .mmu_sfsr_mask = 0xffffffff,
1261
 
        .mmu_trcr_mask = 0xffffffff,
1262
 
        .features = CPU_DEFAULT_FEATURES,
1263
 
    },
1264
 
    {
1265
 
        .name = "TI SuperSparc 61",
1266
 
        .iu_version = 0x44000000,
1267
 
        .fpu_version = 0 << 17,
1268
 
        .mmu_version = 0x04000000,
1269
 
        .mmu_bm = 0x00002000,
1270
 
        .mmu_ctpr_mask = 0xffffffc0,
1271
 
        .mmu_cxr_mask = 0x0000ffff,
1272
 
        .mmu_sfsr_mask = 0xffffffff,
1273
 
        .mmu_trcr_mask = 0xffffffff,
1274
 
        .features = CPU_DEFAULT_FEATURES,
1275
 
    },
1276
 
    {
1277
 
        .name = "Ross RT625",
1278
 
        .iu_version = 0x1e000000,
1279
 
        .fpu_version = 1 << 17,
1280
 
        .mmu_version = 0x1e000000,
1281
 
        .mmu_bm = 0x00004000,
1282
 
        .mmu_ctpr_mask = 0x007ffff0,
1283
 
        .mmu_cxr_mask = 0x0000003f,
1284
 
        .mmu_sfsr_mask = 0xffffffff,
1285
 
        .mmu_trcr_mask = 0xffffffff,
1286
 
        .features = CPU_DEFAULT_FEATURES,
1287
 
    },
1288
 
    {
1289
 
        .name = "Ross RT620",
1290
 
        .iu_version = 0x1f000000,
1291
 
        .fpu_version = 1 << 17,
1292
 
        .mmu_version = 0x1f000000,
1293
 
        .mmu_bm = 0x00004000,
1294
 
        .mmu_ctpr_mask = 0x007ffff0,
1295
 
        .mmu_cxr_mask = 0x0000003f,
1296
 
        .mmu_sfsr_mask = 0xffffffff,
1297
 
        .mmu_trcr_mask = 0xffffffff,
1298
 
        .features = CPU_DEFAULT_FEATURES,
1299
 
    },
1300
 
    {
1301
 
        .name = "BIT B5010",
1302
 
        .iu_version = 0x20000000,
1303
 
        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1304
 
        .mmu_version = 0x20000000,
1305
 
        .mmu_bm = 0x00004000,
1306
 
        .mmu_ctpr_mask = 0x007ffff0,
1307
 
        .mmu_cxr_mask = 0x0000003f,
1308
 
        .mmu_sfsr_mask = 0xffffffff,
1309
 
        .mmu_trcr_mask = 0xffffffff,
1310
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1311
 
        CPU_FEATURE_FSMULD,
1312
 
    },
1313
 
    {
1314
 
        .name = "Matsushita MN10501",
1315
 
        .iu_version = 0x50000000,
1316
 
        .fpu_version = 0 << 17,
1317
 
        .mmu_version = 0x50000000,
1318
 
        .mmu_bm = 0x00004000,
1319
 
        .mmu_ctpr_mask = 0x007ffff0,
1320
 
        .mmu_cxr_mask = 0x0000003f,
1321
 
        .mmu_sfsr_mask = 0xffffffff,
1322
 
        .mmu_trcr_mask = 0xffffffff,
1323
 
        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1324
 
        CPU_FEATURE_FSMULD,
1325
 
    },
1326
 
    {
1327
 
        .name = "Weitek W8601",
1328
 
        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1329
 
        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1330
 
        .mmu_version = 0x10 << 24,
1331
 
        .mmu_bm = 0x00004000,
1332
 
        .mmu_ctpr_mask = 0x007ffff0,
1333
 
        .mmu_cxr_mask = 0x0000003f,
1334
 
        .mmu_sfsr_mask = 0xffffffff,
1335
 
        .mmu_trcr_mask = 0xffffffff,
1336
 
        .features = CPU_DEFAULT_FEATURES,
1337
 
    },
1338
 
    {
1339
 
        .name = "LEON2",
1340
 
        .iu_version = 0xf2000000,
1341
 
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1342
 
        .mmu_version = 0xf2000000,
1343
 
        .mmu_bm = 0x00004000,
1344
 
        .mmu_ctpr_mask = 0x007ffff0,
1345
 
        .mmu_cxr_mask = 0x0000003f,
1346
 
        .mmu_sfsr_mask = 0xffffffff,
1347
 
        .mmu_trcr_mask = 0xffffffff,
1348
 
        .features = CPU_DEFAULT_FEATURES,
1349
 
    },
1350
 
    {
1351
 
        .name = "LEON3",
1352
 
        .iu_version = 0xf3000000,
1353
 
        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1354
 
        .mmu_version = 0xf3000000,
1355
 
        .mmu_bm = 0x00004000,
1356
 
        .mmu_ctpr_mask = 0x007ffff0,
1357
 
        .mmu_cxr_mask = 0x0000003f,
1358
 
        .mmu_sfsr_mask = 0xffffffff,
1359
 
        .mmu_trcr_mask = 0xffffffff,
1360
 
        .features = CPU_DEFAULT_FEATURES,
1361
 
    },
1362
 
#endif
1363
 
};
1364
 
 
1365
 
static const char * const feature_name[] = {
1366
 
    "float",
1367
 
    "float128",
1368
 
    "swap",
1369
 
    "mul",
1370
 
    "div",
1371
 
    "flush",
1372
 
    "fsqrt",
1373
 
    "fmul",
1374
 
    "vis1",
1375
 
    "vis2",
1376
 
    "fsmuld",
1377
 
};
1378
 
 
1379
 
static void print_features(FILE *f,
1380
 
                           int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1381
 
                           uint32_t features, const char *prefix)
1382
 
{
1383
 
    unsigned int i;
1384
 
 
1385
 
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1386
 
        if (feature_name[i] && (features & (1 << i))) {
1387
 
            if (prefix)
1388
 
                (*cpu_fprintf)(f, "%s", prefix);
1389
 
            (*cpu_fprintf)(f, "%s ", feature_name[i]);
1390
 
        }
1391
 
}
1392
 
 
1393
 
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1394
 
{
1395
 
    unsigned int i;
1396
 
 
1397
 
    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1398
 
        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1399
 
            *features |= 1 << i;
1400
 
            return;
1401
 
        }
1402
 
    fprintf(stderr, "CPU feature %s not found\n", flagname);
1403
 
}
1404
 
 
1405
 
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1406
 
{
1407
 
    unsigned int i;
1408
 
    const sparc_def_t *def = NULL;
1409
 
    char *s = strdup(cpu_model);
1410
 
    char *featurestr, *name = strtok(s, ",");
1411
 
    uint32_t plus_features = 0;
1412
 
    uint32_t minus_features = 0;
1413
 
    long long iu_version;
1414
 
    uint32_t fpu_version, mmu_version;
1415
 
 
1416
 
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1417
 
        if (strcasecmp(name, sparc_defs[i].name) == 0) {
1418
 
            def = &sparc_defs[i];
1419
 
        }
1420
 
    }
1421
 
    if (!def)
1422
 
        goto error;
1423
 
    memcpy(cpu_def, def, sizeof(*def));
1424
 
 
1425
 
    featurestr = strtok(NULL, ",");
1426
 
    while (featurestr) {
1427
 
        char *val;
1428
 
 
1429
 
        if (featurestr[0] == '+') {
1430
 
            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1431
 
        } else if (featurestr[0] == '-') {
1432
 
            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1433
 
        } else if ((val = strchr(featurestr, '='))) {
1434
 
            *val = 0; val++;
1435
 
            if (!strcmp(featurestr, "iu_version")) {
1436
 
                char *err;
1437
 
 
1438
 
                iu_version = strtoll(val, &err, 0);
1439
 
                if (!*val || *err) {
1440
 
                    fprintf(stderr, "bad numerical value %s\n", val);
1441
 
                    goto error;
1442
 
                }
1443
 
                cpu_def->iu_version = iu_version;
1444
 
#ifdef DEBUG_FEATURES
1445
 
                fprintf(stderr, "iu_version %llx\n", iu_version);
1446
 
#endif
1447
 
            } else if (!strcmp(featurestr, "fpu_version")) {
1448
 
                char *err;
1449
 
 
1450
 
                fpu_version = strtol(val, &err, 0);
1451
 
                if (!*val || *err) {
1452
 
                    fprintf(stderr, "bad numerical value %s\n", val);
1453
 
                    goto error;
1454
 
                }
1455
 
                cpu_def->fpu_version = fpu_version;
1456
 
#ifdef DEBUG_FEATURES
1457
 
                fprintf(stderr, "fpu_version %llx\n", fpu_version);
1458
 
#endif
1459
 
            } else if (!strcmp(featurestr, "mmu_version")) {
1460
 
                char *err;
1461
 
 
1462
 
                mmu_version = strtol(val, &err, 0);
1463
 
                if (!*val || *err) {
1464
 
                    fprintf(stderr, "bad numerical value %s\n", val);
1465
 
                    goto error;
1466
 
                }
1467
 
                cpu_def->mmu_version = mmu_version;
1468
 
#ifdef DEBUG_FEATURES
1469
 
                fprintf(stderr, "mmu_version %llx\n", mmu_version);
1470
 
#endif
1471
 
            } else {
1472
 
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
1473
 
                goto error;
1474
 
            }
1475
 
        } else {
1476
 
            fprintf(stderr, "feature string `%s' not in format "
1477
 
                    "(+feature|-feature|feature=xyz)\n", featurestr);
1478
 
            goto error;
1479
 
        }
1480
 
        featurestr = strtok(NULL, ",");
1481
 
    }
1482
 
    cpu_def->features |= plus_features;
1483
 
    cpu_def->features &= ~minus_features;
1484
 
#ifdef DEBUG_FEATURES
1485
 
    print_features(stderr, fprintf, cpu_def->features, NULL);
1486
 
#endif
1487
 
    free(s);
1488
 
    return 0;
1489
 
 
1490
 
 error:
1491
 
    free(s);
1492
 
    return -1;
1493
 
}
1494
 
 
1495
 
void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1496
 
{
1497
 
    unsigned int i;
1498
 
 
1499
 
    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1500
 
        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x ",
1501
 
                       sparc_defs[i].name,
1502
 
                       sparc_defs[i].iu_version,
1503
 
                       sparc_defs[i].fpu_version,
1504
 
                       sparc_defs[i].mmu_version);
1505
 
        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1506
 
                       ~sparc_defs[i].features, "-");
1507
 
        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1508
 
                       sparc_defs[i].features, "+");
1509
 
        (*cpu_fprintf)(f, "\n");
1510
 
    }
1511
 
    (*cpu_fprintf)(f, "CPU feature flags (+/-): ");
1512
 
    print_features(f, cpu_fprintf, -1, NULL);
1513
 
    (*cpu_fprintf)(f, "\n");
1514
 
    (*cpu_fprintf)(f, "Numerical features (=): iu_version fpu_version "
1515
 
                   "mmu_version\n");
1516
 
}
1517
 
 
1518
 
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1519
 
 
1520
 
void cpu_dump_state(CPUState *env, FILE *f,
1521
 
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1522
 
                    int flags)
1523
 
{
1524
 
    int i, x;
1525
 
 
1526
 
    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
1527
 
                env->npc);
1528
 
    cpu_fprintf(f, "General Registers:\n");
1529
 
    for (i = 0; i < 4; i++)
1530
 
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1531
 
    cpu_fprintf(f, "\n");
1532
 
    for (; i < 8; i++)
1533
 
        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1534
 
    cpu_fprintf(f, "\nCurrent Register Window:\n");
1535
 
    for (x = 0; x < 3; x++) {
1536
 
        for (i = 0; i < 4; i++)
1537
 
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1538
 
                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1539
 
                    env->regwptr[i + x * 8]);
1540
 
        cpu_fprintf(f, "\n");
1541
 
        for (; i < 8; i++)
1542
 
            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1543
 
                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1544
 
                    env->regwptr[i + x * 8]);
1545
 
        cpu_fprintf(f, "\n");
1546
 
    }
1547
 
    cpu_fprintf(f, "\nFloating Point Registers:\n");
1548
 
    for (i = 0; i < 32; i++) {
1549
 
        if ((i & 3) == 0)
1550
 
            cpu_fprintf(f, "%%f%02d:", i);
1551
 
        cpu_fprintf(f, " %016lf", env->fpr[i]);
1552
 
        if ((i & 3) == 3)
1553
 
            cpu_fprintf(f, "\n");
1554
 
    }
1555
 
#ifdef TARGET_SPARC64
1556
 
    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1557
 
                env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1558
 
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1559
 
                "cleanwin %d cwp %d\n",
1560
 
                env->cansave, env->canrestore, env->otherwin, env->wstate,
1561
 
                env->cleanwin, NWINDOWS - 1 - env->cwp);
1562
 
#else
1563
 
    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1564
 
                GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1565
 
                GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1566
 
                env->psrs?'S':'-', env->psrps?'P':'-',
1567
 
                env->psret?'E':'-', env->wim);
1568
 
#endif
1569
 
    cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1570
 
}
1571
 
 
1572
 
#ifdef TARGET_SPARC64
1573
 
#if !defined(CONFIG_USER_ONLY)
1574
 
#include "qemu-common.h"
1575
 
#include "hw/irq.h"
1576
 
#include "qemu-timer.h"
1577
 
#endif
1578
 
 
1579
 
void helper_tick_set_count(void *opaque, uint64_t count)
1580
 
{
1581
 
#if !defined(CONFIG_USER_ONLY)
1582
 
    ptimer_set_count(opaque, -count);
1583
 
#endif
1584
 
}
1585
 
 
1586
 
uint64_t helper_tick_get_count(void *opaque)
1587
 
{
1588
 
#if !defined(CONFIG_USER_ONLY)
1589
 
    return -ptimer_get_count(opaque);
1590
 
#else
1591
 
    return 0;
1592
 
#endif
1593
 
}
1594
 
 
1595
 
void helper_tick_set_limit(void *opaque, uint64_t limit)
1596
 
{
1597
 
#if !defined(CONFIG_USER_ONLY)
1598
 
    ptimer_set_limit(opaque, -limit, 0);
1599
 
#endif
1600
 
}
1601
 
#endif