Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ a88790a1

History | View | Annotate | Download (49.1 kB)

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