Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ 44e4c0ba

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