Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ ff21f70a

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