xref: /qemu/target/sparc/cpu.c (revision 0442428a8976b4f94e04d24b5db9eb1b678d82c4)
1ab3b491fSBlue Swirl /*
2ab3b491fSBlue Swirl  * Sparc CPU init helpers
3ab3b491fSBlue Swirl  *
4ab3b491fSBlue Swirl  *  Copyright (c) 2003-2005 Fabrice Bellard
5ab3b491fSBlue Swirl  *
6ab3b491fSBlue Swirl  * This library is free software; you can redistribute it and/or
7ab3b491fSBlue Swirl  * modify it under the terms of the GNU Lesser General Public
8ab3b491fSBlue Swirl  * License as published by the Free Software Foundation; either
9ab3b491fSBlue Swirl  * version 2 of the License, or (at your option) any later version.
10ab3b491fSBlue Swirl  *
11ab3b491fSBlue Swirl  * This library is distributed in the hope that it will be useful,
12ab3b491fSBlue Swirl  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ab3b491fSBlue Swirl  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ab3b491fSBlue Swirl  * Lesser General Public License for more details.
15ab3b491fSBlue Swirl  *
16ab3b491fSBlue Swirl  * You should have received a copy of the GNU Lesser General Public
17ab3b491fSBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18ab3b491fSBlue Swirl  */
19ab3b491fSBlue Swirl 
20db5ebe5fSPeter Maydell #include "qemu/osdep.h"
21da34e65cSMarkus Armbruster #include "qapi/error.h"
22ab3b491fSBlue Swirl #include "cpu.h"
23*0442428aSMarkus Armbruster #include "qemu/qemu-print.h"
2463c91552SPaolo Bonzini #include "exec/exec-all.h"
25de05005bSIgor Mammedov #include "hw/qdev-properties.h"
26de05005bSIgor Mammedov #include "qapi/visitor.h"
27ab3b491fSBlue Swirl 
28ab3b491fSBlue Swirl //#define DEBUG_FEATURES
29ab3b491fSBlue Swirl 
30ab7ab3d7SAndreas Färber /* CPUClass::reset() */
31ab7ab3d7SAndreas Färber static void sparc_cpu_reset(CPUState *s)
32ab7ab3d7SAndreas Färber {
33ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(s);
34ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
35ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
36ab7ab3d7SAndreas Färber 
37ab7ab3d7SAndreas Färber     scc->parent_reset(s);
38ab7ab3d7SAndreas Färber 
391f5c00cfSAlex Bennée     memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
40ab3b491fSBlue Swirl     env->cwp = 0;
41ab3b491fSBlue Swirl #ifndef TARGET_SPARC64
42ab3b491fSBlue Swirl     env->wim = 1;
43ab3b491fSBlue Swirl #endif
44ab3b491fSBlue Swirl     env->regwptr = env->regbase + (env->cwp * 16);
45ab3b491fSBlue Swirl     CC_OP = CC_OP_FLAGS;
46ab3b491fSBlue Swirl #if defined(CONFIG_USER_ONLY)
47ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
48ab3b491fSBlue Swirl     env->cleanwin = env->nwindows - 2;
49ab3b491fSBlue Swirl     env->cansave = env->nwindows - 2;
50ab3b491fSBlue Swirl     env->pstate = PS_RMO | PS_PEF | PS_IE;
51ab3b491fSBlue Swirl     env->asi = 0x82; /* Primary no-fault */
52ab3b491fSBlue Swirl #endif
53ab3b491fSBlue Swirl #else
54ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
55ab3b491fSBlue Swirl     env->psret = 0;
56ab3b491fSBlue Swirl     env->psrs = 1;
57ab3b491fSBlue Swirl     env->psrps = 1;
58ab3b491fSBlue Swirl #endif
59ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
60cbc3a6a4SArtyom Tarasenko     env->pstate = PS_PRIV | PS_RED | PS_PEF;
61cbc3a6a4SArtyom Tarasenko     if (!cpu_has_hypervisor(env)) {
62cbc3a6a4SArtyom Tarasenko         env->pstate |= PS_AG;
63cbc3a6a4SArtyom Tarasenko     }
64ab3b491fSBlue Swirl     env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
65ab3b491fSBlue Swirl     env->tl = env->maxtl;
66cbc3a6a4SArtyom Tarasenko     env->gl = 2;
67ab3b491fSBlue Swirl     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
68ab3b491fSBlue Swirl     env->lsu = 0;
69ab3b491fSBlue Swirl #else
70ab3b491fSBlue Swirl     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
71576e1c4cSIgor Mammedov     env->mmuregs[0] |= env->def.mmu_bm;
72ab3b491fSBlue Swirl #endif
73ab3b491fSBlue Swirl     env->pc = 0;
74ab3b491fSBlue Swirl     env->npc = env->pc + 4;
75ab3b491fSBlue Swirl #endif
76ab3b491fSBlue Swirl     env->cache_control = 0;
77ab3b491fSBlue Swirl }
78ab3b491fSBlue Swirl 
7987afe467SRichard Henderson static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
8087afe467SRichard Henderson {
8187afe467SRichard Henderson     if (interrupt_request & CPU_INTERRUPT_HARD) {
8287afe467SRichard Henderson         SPARCCPU *cpu = SPARC_CPU(cs);
8387afe467SRichard Henderson         CPUSPARCState *env = &cpu->env;
8487afe467SRichard Henderson 
8587afe467SRichard Henderson         if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
8687afe467SRichard Henderson             int pil = env->interrupt_index & 0xf;
8787afe467SRichard Henderson             int type = env->interrupt_index & 0xf0;
8887afe467SRichard Henderson 
8987afe467SRichard Henderson             if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
9087afe467SRichard Henderson                 cs->exception_index = env->interrupt_index;
9187afe467SRichard Henderson                 sparc_cpu_do_interrupt(cs);
9287afe467SRichard Henderson                 return true;
9387afe467SRichard Henderson             }
9487afe467SRichard Henderson         }
9587afe467SRichard Henderson     }
9687afe467SRichard Henderson     return false;
9787afe467SRichard Henderson }
9887afe467SRichard Henderson 
99df0900ebSPeter Crosthwaite static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
100df0900ebSPeter Crosthwaite {
101df0900ebSPeter Crosthwaite     info->print_insn = print_insn_sparc;
102df0900ebSPeter Crosthwaite #ifdef TARGET_SPARC64
103df0900ebSPeter Crosthwaite     info->mach = bfd_mach_sparc_v9b;
104df0900ebSPeter Crosthwaite #endif
105df0900ebSPeter Crosthwaite }
106df0900ebSPeter Crosthwaite 
107d1853231SIgor Mammedov static void
108d1853231SIgor Mammedov cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
109ab3b491fSBlue Swirl {
110d1853231SIgor Mammedov     GlobalProperty *prop = g_new0(typeof(*prop), 1);
111d1853231SIgor Mammedov     prop->driver = typename;
112d1853231SIgor Mammedov     prop->property = g_strdup(name);
113d1853231SIgor Mammedov     prop->value = g_strdup(val);
114d1853231SIgor Mammedov     qdev_prop_register_global(prop);
115433ac7a9SAndreas Färber }
116433ac7a9SAndreas Färber 
117d1853231SIgor Mammedov /* Parse "+feature,-feature,feature=foo" CPU feature string */
118d1853231SIgor Mammedov static void sparc_cpu_parse_features(const char *typename, char *features,
119d1853231SIgor Mammedov                                      Error **errp)
120d1853231SIgor Mammedov {
121d1853231SIgor Mammedov     GList *l, *plus_features = NULL, *minus_features = NULL;
122d1853231SIgor Mammedov     char *featurestr; /* Single 'key=value" string being parsed */
123d1853231SIgor Mammedov     static bool cpu_globals_initialized;
124d1853231SIgor Mammedov 
125d1853231SIgor Mammedov     if (cpu_globals_initialized) {
126d1853231SIgor Mammedov         return;
127d1853231SIgor Mammedov     }
128d1853231SIgor Mammedov     cpu_globals_initialized = true;
129d1853231SIgor Mammedov 
130d1853231SIgor Mammedov     if (!features) {
131d1853231SIgor Mammedov         return;
132d1853231SIgor Mammedov     }
133d1853231SIgor Mammedov 
134d1853231SIgor Mammedov     for (featurestr = strtok(features, ",");
135d1853231SIgor Mammedov          featurestr;
136d1853231SIgor Mammedov          featurestr = strtok(NULL, ",")) {
137d1853231SIgor Mammedov         const char *name;
138d1853231SIgor Mammedov         const char *val = NULL;
139d1853231SIgor Mammedov         char *eq = NULL;
140d1853231SIgor Mammedov 
141d1853231SIgor Mammedov         /* Compatibility syntax: */
142d1853231SIgor Mammedov         if (featurestr[0] == '+') {
143d1853231SIgor Mammedov             plus_features = g_list_append(plus_features,
144d1853231SIgor Mammedov                                           g_strdup(featurestr + 1));
145d1853231SIgor Mammedov             continue;
146d1853231SIgor Mammedov         } else if (featurestr[0] == '-') {
147d1853231SIgor Mammedov             minus_features = g_list_append(minus_features,
148d1853231SIgor Mammedov                                            g_strdup(featurestr + 1));
149d1853231SIgor Mammedov             continue;
150d1853231SIgor Mammedov         }
151d1853231SIgor Mammedov 
152d1853231SIgor Mammedov         eq = strchr(featurestr, '=');
153d1853231SIgor Mammedov         name = featurestr;
154d1853231SIgor Mammedov         if (eq) {
155d1853231SIgor Mammedov             *eq++ = 0;
156d1853231SIgor Mammedov             val = eq;
157d1853231SIgor Mammedov 
158d1853231SIgor Mammedov             /*
159d1853231SIgor Mammedov              * Temporarily, only +feat/-feat will be supported
160d1853231SIgor Mammedov              * for boolean properties until we remove the
161d1853231SIgor Mammedov              * minus-overrides-plus semantics and just follow
162d1853231SIgor Mammedov              * the order options appear on the command-line.
163d1853231SIgor Mammedov              *
164d1853231SIgor Mammedov              * TODO: warn if user is relying on minus-override-plus semantics
165d1853231SIgor Mammedov              * TODO: remove minus-override-plus semantics after
166d1853231SIgor Mammedov              *       warning for a few releases
167d1853231SIgor Mammedov              */
168d1853231SIgor Mammedov             if (!strcasecmp(val, "on") ||
169d1853231SIgor Mammedov                 !strcasecmp(val, "off") ||
170d1853231SIgor Mammedov                 !strcasecmp(val, "true") ||
171d1853231SIgor Mammedov                 !strcasecmp(val, "false")) {
172d1853231SIgor Mammedov                 error_setg(errp, "Boolean properties in format %s=%s"
173d1853231SIgor Mammedov                                  " are not supported", name, val);
174d1853231SIgor Mammedov                 return;
175d1853231SIgor Mammedov             }
176d1853231SIgor Mammedov         } else {
177d1853231SIgor Mammedov             error_setg(errp, "Unsupported property format: %s", name);
178d1853231SIgor Mammedov             return;
179d1853231SIgor Mammedov         }
180d1853231SIgor Mammedov         cpu_add_feat_as_prop(typename, name, val);
181d1853231SIgor Mammedov     }
182d1853231SIgor Mammedov 
183d1853231SIgor Mammedov     for (l = plus_features; l; l = l->next) {
184d1853231SIgor Mammedov         const char *name = l->data;
185d1853231SIgor Mammedov         cpu_add_feat_as_prop(typename, name, "on");
186d1853231SIgor Mammedov     }
187d1853231SIgor Mammedov     g_list_free_full(plus_features, g_free);
188d1853231SIgor Mammedov 
189d1853231SIgor Mammedov     for (l = minus_features; l; l = l->next) {
190d1853231SIgor Mammedov         const char *name = l->data;
191d1853231SIgor Mammedov         cpu_add_feat_as_prop(typename, name, "off");
192d1853231SIgor Mammedov     }
193d1853231SIgor Mammedov     g_list_free_full(minus_features, g_free);
194ab3b491fSBlue Swirl }
195ab3b491fSBlue Swirl 
196ab3b491fSBlue Swirl void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
197ab3b491fSBlue Swirl {
198ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
199ab3b491fSBlue Swirl     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
200ab3b491fSBlue Swirl #endif
201ab3b491fSBlue Swirl }
202ab3b491fSBlue Swirl 
203ab3b491fSBlue Swirl static const sparc_def_t sparc_defs[] = {
204ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
205ab3b491fSBlue Swirl     {
206ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64",
207ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
208ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
209ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
210ab3b491fSBlue Swirl         .nwindows = 4,
211ab3b491fSBlue Swirl         .maxtl = 4,
212ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
213ab3b491fSBlue Swirl     },
214ab3b491fSBlue Swirl     {
215ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 III",
216ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
217ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
218ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
219ab3b491fSBlue Swirl         .nwindows = 5,
220ab3b491fSBlue Swirl         .maxtl = 4,
221ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
222ab3b491fSBlue Swirl     },
223ab3b491fSBlue Swirl     {
224ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 IV",
225ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
226ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
227ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
228ab3b491fSBlue Swirl         .nwindows = 8,
229ab3b491fSBlue Swirl         .maxtl = 5,
230ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
231ab3b491fSBlue Swirl     },
232ab3b491fSBlue Swirl     {
233ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 V",
234ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
235ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
236ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
237ab3b491fSBlue Swirl         .nwindows = 8,
238ab3b491fSBlue Swirl         .maxtl = 5,
239ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
240ab3b491fSBlue Swirl     },
241ab3b491fSBlue Swirl     {
242ab3b491fSBlue Swirl         .name = "TI UltraSparc I",
243ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
244ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
245ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
246ab3b491fSBlue Swirl         .nwindows = 8,
247ab3b491fSBlue Swirl         .maxtl = 5,
248ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
249ab3b491fSBlue Swirl     },
250ab3b491fSBlue Swirl     {
251ab3b491fSBlue Swirl         .name = "TI UltraSparc II",
252ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
253ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
254ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
255ab3b491fSBlue Swirl         .nwindows = 8,
256ab3b491fSBlue Swirl         .maxtl = 5,
257ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
258ab3b491fSBlue Swirl     },
259ab3b491fSBlue Swirl     {
260ab3b491fSBlue Swirl         .name = "TI UltraSparc IIi",
261ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
262ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
263ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
264ab3b491fSBlue Swirl         .nwindows = 8,
265ab3b491fSBlue Swirl         .maxtl = 5,
266ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
267ab3b491fSBlue Swirl     },
268ab3b491fSBlue Swirl     {
269ab3b491fSBlue Swirl         .name = "TI UltraSparc IIe",
270ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
271ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
272ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
273ab3b491fSBlue Swirl         .nwindows = 8,
274ab3b491fSBlue Swirl         .maxtl = 5,
275ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
276ab3b491fSBlue Swirl     },
277ab3b491fSBlue Swirl     {
278ab3b491fSBlue Swirl         .name = "Sun UltraSparc III",
279ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
280ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
281ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
282ab3b491fSBlue Swirl         .nwindows = 8,
283ab3b491fSBlue Swirl         .maxtl = 5,
284ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
285ab3b491fSBlue Swirl     },
286ab3b491fSBlue Swirl     {
287ab3b491fSBlue Swirl         .name = "Sun UltraSparc III Cu",
288ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
289ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
290ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
291ab3b491fSBlue Swirl         .nwindows = 8,
292ab3b491fSBlue Swirl         .maxtl = 5,
293ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
294ab3b491fSBlue Swirl     },
295ab3b491fSBlue Swirl     {
296ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi",
297ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
298ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
299ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
300ab3b491fSBlue Swirl         .nwindows = 8,
301ab3b491fSBlue Swirl         .maxtl = 5,
302ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
303ab3b491fSBlue Swirl     },
304ab3b491fSBlue Swirl     {
305ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV",
306ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
307ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
308ab3b491fSBlue Swirl         .mmu_version = mmu_us_4,
309ab3b491fSBlue Swirl         .nwindows = 8,
310ab3b491fSBlue Swirl         .maxtl = 5,
311ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
312ab3b491fSBlue Swirl     },
313ab3b491fSBlue Swirl     {
314ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV+",
315ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
316ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
317ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
318ab3b491fSBlue Swirl         .nwindows = 8,
319ab3b491fSBlue Swirl         .maxtl = 5,
320ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
321ab3b491fSBlue Swirl     },
322ab3b491fSBlue Swirl     {
323ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi+",
324ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
325ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
326ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
327ab3b491fSBlue Swirl         .nwindows = 8,
328ab3b491fSBlue Swirl         .maxtl = 5,
329ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
330ab3b491fSBlue Swirl     },
331ab3b491fSBlue Swirl     {
332ab3b491fSBlue Swirl         .name = "Sun UltraSparc T1",
333ab3b491fSBlue Swirl         /* defined in sparc_ifu_fdp.v and ctu.h */
334ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
335ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
336ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
337ab3b491fSBlue Swirl         .nwindows = 8,
338ab3b491fSBlue Swirl         .maxtl = 6,
339ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
340ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
341ab3b491fSBlue Swirl     },
342ab3b491fSBlue Swirl     {
343ab3b491fSBlue Swirl         .name = "Sun UltraSparc T2",
344ab3b491fSBlue Swirl         /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
345ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
346ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
347ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
348ab3b491fSBlue Swirl         .nwindows = 8,
349ab3b491fSBlue Swirl         .maxtl = 6,
350ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
351ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
352ab3b491fSBlue Swirl     },
353ab3b491fSBlue Swirl     {
354ab3b491fSBlue Swirl         .name = "NEC UltraSparc I",
355ab3b491fSBlue Swirl         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
356ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
357ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
358ab3b491fSBlue Swirl         .nwindows = 8,
359ab3b491fSBlue Swirl         .maxtl = 5,
360ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
361ab3b491fSBlue Swirl     },
362ab3b491fSBlue Swirl #else
363ab3b491fSBlue Swirl     {
364ab3b491fSBlue Swirl         .name = "Fujitsu MB86904",
365ab3b491fSBlue Swirl         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
366ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
367ab3b491fSBlue Swirl         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
368ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
369ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
370ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
371ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
372ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
373ab3b491fSBlue Swirl         .nwindows = 8,
374ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
375ab3b491fSBlue Swirl     },
376ab3b491fSBlue Swirl     {
377ab3b491fSBlue Swirl         .name = "Fujitsu MB86907",
378ab3b491fSBlue Swirl         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
379ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
380ab3b491fSBlue Swirl         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
381ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
382ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
383ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
384ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
385ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
386ab3b491fSBlue Swirl         .nwindows = 8,
387ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
388ab3b491fSBlue Swirl     },
389ab3b491fSBlue Swirl     {
390ab3b491fSBlue Swirl         .name = "TI MicroSparc I",
391ab3b491fSBlue Swirl         .iu_version = 0x41000000,
392ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
393ab3b491fSBlue Swirl         .mmu_version = 0x41000000,
394ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
395ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
396ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
397ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
398ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x0000003f,
399ab3b491fSBlue Swirl         .nwindows = 7,
400ab3b491fSBlue Swirl         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
401ab3b491fSBlue Swirl         CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
402ab3b491fSBlue Swirl         CPU_FEATURE_FMUL,
403ab3b491fSBlue Swirl     },
404ab3b491fSBlue Swirl     {
405ab3b491fSBlue Swirl         .name = "TI MicroSparc II",
406ab3b491fSBlue Swirl         .iu_version = 0x42000000,
407ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
408ab3b491fSBlue Swirl         .mmu_version = 0x02000000,
409ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
410ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
411ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
412ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
413ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
414ab3b491fSBlue Swirl         .nwindows = 8,
415ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
416ab3b491fSBlue Swirl     },
417ab3b491fSBlue Swirl     {
418ab3b491fSBlue Swirl         .name = "TI MicroSparc IIep",
419ab3b491fSBlue Swirl         .iu_version = 0x42000000,
420ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
421ab3b491fSBlue Swirl         .mmu_version = 0x04000000,
422ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
423ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
424ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
425ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016bff,
426ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
427ab3b491fSBlue Swirl         .nwindows = 8,
428ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
429ab3b491fSBlue Swirl     },
430ab3b491fSBlue Swirl     {
431ab3b491fSBlue Swirl         .name = "TI SuperSparc 40", /* STP1020NPGA */
432ab3b491fSBlue Swirl         .iu_version = 0x41000000, /* SuperSPARC 2.x */
433ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
434ab3b491fSBlue Swirl         .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
435ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
436ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
437ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
438ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
439ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
440ab3b491fSBlue Swirl         .nwindows = 8,
441ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
442ab3b491fSBlue Swirl     },
443ab3b491fSBlue Swirl     {
444ab3b491fSBlue Swirl         .name = "TI SuperSparc 50", /* STP1020PGA */
445ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
446ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
447ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
448ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
449ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
450ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
451ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
452ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
453ab3b491fSBlue Swirl         .nwindows = 8,
454ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
455ab3b491fSBlue Swirl     },
456ab3b491fSBlue Swirl     {
457ab3b491fSBlue Swirl         .name = "TI SuperSparc 51",
458ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
459ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
460ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
461ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
462ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
463ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
464ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
465ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
466ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
467ab3b491fSBlue Swirl         .nwindows = 8,
468ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
469ab3b491fSBlue Swirl     },
470ab3b491fSBlue Swirl     {
471ab3b491fSBlue Swirl         .name = "TI SuperSparc 60", /* STP1020APGA */
472ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
473ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
474ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
475ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
476ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
477ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
478ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
479ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
480ab3b491fSBlue Swirl         .nwindows = 8,
481ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
482ab3b491fSBlue Swirl     },
483ab3b491fSBlue Swirl     {
484ab3b491fSBlue Swirl         .name = "TI SuperSparc 61",
485ab3b491fSBlue Swirl         .iu_version = 0x44000000, /* SuperSPARC 3.x */
486ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
487ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
488ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
489ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
490ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
491ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
492ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
493ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
494ab3b491fSBlue Swirl         .nwindows = 8,
495ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
496ab3b491fSBlue Swirl     },
497ab3b491fSBlue Swirl     {
498ab3b491fSBlue Swirl         .name = "TI SuperSparc II",
499ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC II 1.x */
500ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
501ab3b491fSBlue Swirl         .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
502ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
503ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
504ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
505ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
506ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
507ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
508ab3b491fSBlue Swirl         .nwindows = 8,
509ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
510ab3b491fSBlue Swirl     },
511ab3b491fSBlue Swirl     {
512ab3b491fSBlue Swirl         .name = "LEON2",
513ab3b491fSBlue Swirl         .iu_version = 0xf2000000,
514ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
515ab3b491fSBlue Swirl         .mmu_version = 0xf2000000,
516ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
517ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
518ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
519ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
520ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
521ab3b491fSBlue Swirl         .nwindows = 8,
522ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
523ab3b491fSBlue Swirl     },
524ab3b491fSBlue Swirl     {
525ab3b491fSBlue Swirl         .name = "LEON3",
526ab3b491fSBlue Swirl         .iu_version = 0xf3000000,
527ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
528ab3b491fSBlue Swirl         .mmu_version = 0xf3000000,
529ab3b491fSBlue Swirl         .mmu_bm = 0x00000000,
5307a0a9c2cSRonald Hecht         .mmu_ctpr_mask = 0xfffffffc,
5317a0a9c2cSRonald Hecht         .mmu_cxr_mask = 0x000000ff,
532ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
533ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
534ab3b491fSBlue Swirl         .nwindows = 8,
535ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
53616c358e9SSebastian Huber         CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
53716c358e9SSebastian Huber         CPU_FEATURE_CASA,
538ab3b491fSBlue Swirl     },
539ab3b491fSBlue Swirl #endif
540ab3b491fSBlue Swirl };
541ab3b491fSBlue Swirl 
542ab3b491fSBlue Swirl static const char * const feature_name[] = {
543ab3b491fSBlue Swirl     "float",
544ab3b491fSBlue Swirl     "float128",
545ab3b491fSBlue Swirl     "swap",
546ab3b491fSBlue Swirl     "mul",
547ab3b491fSBlue Swirl     "div",
548ab3b491fSBlue Swirl     "flush",
549ab3b491fSBlue Swirl     "fsqrt",
550ab3b491fSBlue Swirl     "fmul",
551ab3b491fSBlue Swirl     "vis1",
552ab3b491fSBlue Swirl     "vis2",
553ab3b491fSBlue Swirl     "fsmuld",
554ab3b491fSBlue Swirl     "hypv",
555ab3b491fSBlue Swirl     "cmt",
556ab3b491fSBlue Swirl     "gl",
557ab3b491fSBlue Swirl };
558ab3b491fSBlue Swirl 
559*0442428aSMarkus Armbruster static void print_features(uint32_t features, const char *prefix)
560ab3b491fSBlue Swirl {
561ab3b491fSBlue Swirl     unsigned int i;
562ab3b491fSBlue Swirl 
563ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
564ab3b491fSBlue Swirl         if (feature_name[i] && (features & (1 << i))) {
565ab3b491fSBlue Swirl             if (prefix) {
566*0442428aSMarkus Armbruster                 qemu_printf("%s", prefix);
567ab3b491fSBlue Swirl             }
568*0442428aSMarkus Armbruster             qemu_printf("%s ", feature_name[i]);
569ab3b491fSBlue Swirl         }
570ab3b491fSBlue Swirl     }
571ab3b491fSBlue Swirl }
572ab3b491fSBlue Swirl 
573*0442428aSMarkus Armbruster void sparc_cpu_list(void)
574ab3b491fSBlue Swirl {
575ab3b491fSBlue Swirl     unsigned int i;
576ab3b491fSBlue Swirl 
577ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
578*0442428aSMarkus Armbruster         qemu_printf("Sparc %16s IU " TARGET_FMT_lx
579ab3b491fSBlue Swirl                     " FPU %08x MMU %08x NWINS %d ",
580ab3b491fSBlue Swirl                     sparc_defs[i].name,
581ab3b491fSBlue Swirl                     sparc_defs[i].iu_version,
582ab3b491fSBlue Swirl                     sparc_defs[i].fpu_version,
583ab3b491fSBlue Swirl                     sparc_defs[i].mmu_version,
584ab3b491fSBlue Swirl                     sparc_defs[i].nwindows);
585*0442428aSMarkus Armbruster         print_features(CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
586*0442428aSMarkus Armbruster         print_features(~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
587*0442428aSMarkus Armbruster         qemu_printf("\n");
588ab3b491fSBlue Swirl     }
589*0442428aSMarkus Armbruster     qemu_printf("Default CPU feature flags (use '-' to remove): ");
590*0442428aSMarkus Armbruster     print_features(CPU_DEFAULT_FEATURES, NULL);
591*0442428aSMarkus Armbruster     qemu_printf("\n");
592*0442428aSMarkus Armbruster     qemu_printf("Available CPU feature flags (use '+' to add): ");
593*0442428aSMarkus Armbruster     print_features(~CPU_DEFAULT_FEATURES, NULL);
594*0442428aSMarkus Armbruster     qemu_printf("\n");
595*0442428aSMarkus Armbruster     qemu_printf("Numerical features (use '=' to set): iu_version "
596ab3b491fSBlue Swirl                 "fpu_version mmu_version nwindows\n");
597ab3b491fSBlue Swirl }
598ab3b491fSBlue Swirl 
599ab3b491fSBlue Swirl static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
600ab3b491fSBlue Swirl                          uint32_t cc)
601ab3b491fSBlue Swirl {
602ab3b491fSBlue Swirl     cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
603ab3b491fSBlue Swirl                 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
604ab3b491fSBlue Swirl                 cc & PSR_CARRY ? 'C' : '-');
605ab3b491fSBlue Swirl }
606ab3b491fSBlue Swirl 
607ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
608ab3b491fSBlue Swirl #define REGS_PER_LINE 4
609ab3b491fSBlue Swirl #else
610ab3b491fSBlue Swirl #define REGS_PER_LINE 8
611ab3b491fSBlue Swirl #endif
612ab3b491fSBlue Swirl 
613878096eeSAndreas Färber void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
614ab3b491fSBlue Swirl                           int flags)
615ab3b491fSBlue Swirl {
616878096eeSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
617878096eeSAndreas Färber     CPUSPARCState *env = &cpu->env;
618ab3b491fSBlue Swirl     int i, x;
619ab3b491fSBlue Swirl 
620ab3b491fSBlue Swirl     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
621ab3b491fSBlue Swirl                 env->npc);
622ab3b491fSBlue Swirl 
623ab3b491fSBlue Swirl     for (i = 0; i < 8; i++) {
624ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == 0) {
625ab3b491fSBlue Swirl             cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
626ab3b491fSBlue Swirl         }
627ab3b491fSBlue Swirl         cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
628ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
629ab3b491fSBlue Swirl             cpu_fprintf(f, "\n");
630ab3b491fSBlue Swirl         }
631ab3b491fSBlue Swirl     }
632ab3b491fSBlue Swirl     for (x = 0; x < 3; x++) {
633ab3b491fSBlue Swirl         for (i = 0; i < 8; i++) {
634ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == 0) {
635ab3b491fSBlue Swirl                 cpu_fprintf(f, "%%%c%d-%d: ",
636ab3b491fSBlue Swirl                             x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
637ab3b491fSBlue Swirl                             i, i + REGS_PER_LINE - 1);
638ab3b491fSBlue Swirl             }
639ab3b491fSBlue Swirl             cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
640ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
641ab3b491fSBlue Swirl                 cpu_fprintf(f, "\n");
642ab3b491fSBlue Swirl             }
643ab3b491fSBlue Swirl         }
644ab3b491fSBlue Swirl     }
64576a23ca0SRichard Henderson 
646d13c394cSRichard Henderson     if (flags & CPU_DUMP_FPU) {
64730038fd8SRichard Henderson         for (i = 0; i < TARGET_DPREGS; i++) {
648ab3b491fSBlue Swirl             if ((i & 3) == 0) {
64930038fd8SRichard Henderson                 cpu_fprintf(f, "%%f%02d: ", i * 2);
650ab3b491fSBlue Swirl             }
65130038fd8SRichard Henderson             cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
652ab3b491fSBlue Swirl             if ((i & 3) == 3) {
653ab3b491fSBlue Swirl                 cpu_fprintf(f, "\n");
654ab3b491fSBlue Swirl             }
655ab3b491fSBlue Swirl         }
656d13c394cSRichard Henderson     }
657d13c394cSRichard Henderson 
658ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
659ab3b491fSBlue Swirl     cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
660ab3b491fSBlue Swirl                 (unsigned)cpu_get_ccr(env));
661ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
662ab3b491fSBlue Swirl     cpu_fprintf(f, " xcc: ");
663ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
664cbc3a6a4SArtyom Tarasenko     cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
665cbc3a6a4SArtyom Tarasenko                 env->psrpil, env->gl);
666cbc3a6a4SArtyom Tarasenko     cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
667cbc3a6a4SArtyom Tarasenko                 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
668ab3b491fSBlue Swirl     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
669ab3b491fSBlue Swirl                 "cleanwin: %d cwp: %d\n",
670ab3b491fSBlue Swirl                 env->cansave, env->canrestore, env->otherwin, env->wstate,
671ab3b491fSBlue Swirl                 env->cleanwin, env->nwindows - 1 - env->cwp);
672ab3b491fSBlue Swirl     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
673ab3b491fSBlue Swirl                 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
674cbc3a6a4SArtyom Tarasenko 
675ab3b491fSBlue Swirl #else
676ab3b491fSBlue Swirl     cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
677ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
678ab3b491fSBlue Swirl     cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
679ab3b491fSBlue Swirl                 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
680ab3b491fSBlue Swirl                 env->wim);
681ab3b491fSBlue Swirl     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
682ab3b491fSBlue Swirl                 env->fsr, env->y);
683ab3b491fSBlue Swirl #endif
68476a23ca0SRichard Henderson     cpu_fprintf(f, "\n");
685ab3b491fSBlue Swirl }
686ab7ab3d7SAndreas Färber 
687f45748f1SAndreas Färber static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
688f45748f1SAndreas Färber {
689f45748f1SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
690f45748f1SAndreas Färber 
691f45748f1SAndreas Färber     cpu->env.pc = value;
692f45748f1SAndreas Färber     cpu->env.npc = value + 4;
693f45748f1SAndreas Färber }
694f45748f1SAndreas Färber 
695bdf7ae5bSAndreas Färber static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
696bdf7ae5bSAndreas Färber {
697bdf7ae5bSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
698bdf7ae5bSAndreas Färber 
699bdf7ae5bSAndreas Färber     cpu->env.pc = tb->pc;
700bdf7ae5bSAndreas Färber     cpu->env.npc = tb->cs_base;
701bdf7ae5bSAndreas Färber }
702bdf7ae5bSAndreas Färber 
7038c2e1b00SAndreas Färber static bool sparc_cpu_has_work(CPUState *cs)
7048c2e1b00SAndreas Färber {
7058c2e1b00SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
7068c2e1b00SAndreas Färber     CPUSPARCState *env = &cpu->env;
7078c2e1b00SAndreas Färber 
7088c2e1b00SAndreas Färber     return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
7098c2e1b00SAndreas Färber            cpu_interrupts_enabled(env);
7108c2e1b00SAndreas Färber }
7118c2e1b00SAndreas Färber 
71212a6c15eSIgor Mammedov static char *sparc_cpu_type_name(const char *cpu_model)
71312a6c15eSIgor Mammedov {
7141d4bfc54SIgor Mammedov     char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
71512a6c15eSIgor Mammedov     char *s = name;
71612a6c15eSIgor Mammedov 
71712a6c15eSIgor Mammedov     /* SPARC cpu model names happen to have whitespaces,
71812a6c15eSIgor Mammedov      * as type names shouldn't have spaces replace them with '-'
71912a6c15eSIgor Mammedov      */
72012a6c15eSIgor Mammedov     while ((s = strchr(s, ' '))) {
72112a6c15eSIgor Mammedov         *s = '-';
72212a6c15eSIgor Mammedov     }
72312a6c15eSIgor Mammedov 
72412a6c15eSIgor Mammedov     return name;
72512a6c15eSIgor Mammedov }
72612a6c15eSIgor Mammedov 
72712a6c15eSIgor Mammedov static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
72812a6c15eSIgor Mammedov {
72912a6c15eSIgor Mammedov     ObjectClass *oc;
73012a6c15eSIgor Mammedov     char *typename;
73112a6c15eSIgor Mammedov 
73212a6c15eSIgor Mammedov     typename = sparc_cpu_type_name(cpu_model);
73312a6c15eSIgor Mammedov     oc = object_class_by_name(typename);
73412a6c15eSIgor Mammedov     g_free(typename);
73512a6c15eSIgor Mammedov     return oc;
73612a6c15eSIgor Mammedov }
73712a6c15eSIgor Mammedov 
738b6e91ebfSAndreas Färber static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
739b6e91ebfSAndreas Färber {
740ce5b1bbfSLaurent Vivier     CPUState *cs = CPU(dev);
741b6e91ebfSAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
742ce5b1bbfSLaurent Vivier     Error *local_err = NULL;
743247bf011SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(dev);
744247bf011SAndreas Färber     CPUSPARCState *env = &cpu->env;
745247bf011SAndreas Färber 
74670054962SIgor Mammedov #if defined(CONFIG_USER_ONLY)
747576e1c4cSIgor Mammedov     if ((env->def.features & CPU_FEATURE_FLOAT)) {
748576e1c4cSIgor Mammedov         env->def.features |= CPU_FEATURE_FLOAT128;
749247bf011SAndreas Färber     }
750247bf011SAndreas Färber #endif
751b6e91ebfSAndreas Färber 
75270054962SIgor Mammedov     env->version = env->def.iu_version;
75370054962SIgor Mammedov     env->fsr = env->def.fpu_version;
75470054962SIgor Mammedov     env->nwindows = env->def.nwindows;
75570054962SIgor Mammedov #if !defined(TARGET_SPARC64)
75670054962SIgor Mammedov     env->mmuregs[0] |= env->def.mmu_version;
75770054962SIgor Mammedov     cpu_sparc_set_id(env, 0);
75870054962SIgor Mammedov     env->mxccregs[7] |= env->def.mxcc_version;
75970054962SIgor Mammedov #else
76070054962SIgor Mammedov     env->mmu_version = env->def.mmu_version;
76170054962SIgor Mammedov     env->maxtl = env->def.maxtl;
76270054962SIgor Mammedov     env->version |= env->def.maxtl << 8;
76370054962SIgor Mammedov     env->version |= env->def.nwindows - 1;
76470054962SIgor Mammedov #endif
76570054962SIgor Mammedov 
766ce5b1bbfSLaurent Vivier     cpu_exec_realizefn(cs, &local_err);
767ce5b1bbfSLaurent Vivier     if (local_err != NULL) {
768ce5b1bbfSLaurent Vivier         error_propagate(errp, local_err);
769ce5b1bbfSLaurent Vivier         return;
770ce5b1bbfSLaurent Vivier     }
771ce5b1bbfSLaurent Vivier 
772ce5b1bbfSLaurent Vivier     qemu_init_vcpu(cs);
77314a10fc3SAndreas Färber 
774b6e91ebfSAndreas Färber     scc->parent_realize(dev, errp);
775b6e91ebfSAndreas Färber }
776b6e91ebfSAndreas Färber 
777ab7ab3d7SAndreas Färber static void sparc_cpu_initfn(Object *obj)
778ab7ab3d7SAndreas Färber {
779c05efcb1SAndreas Färber     CPUState *cs = CPU(obj);
780ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(obj);
78112a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
782ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
783ab7ab3d7SAndreas Färber 
784c05efcb1SAndreas Färber     cs->env_ptr = env;
7855266d20aSAndreas Färber 
786576e1c4cSIgor Mammedov     if (scc->cpu_def) {
787576e1c4cSIgor Mammedov         env->def = *scc->cpu_def;
788ab7ab3d7SAndreas Färber     }
789ab7ab3d7SAndreas Färber }
790ab7ab3d7SAndreas Färber 
791de05005bSIgor Mammedov static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
792de05005bSIgor Mammedov                                void *opaque, Error **errp)
793de05005bSIgor Mammedov {
794de05005bSIgor Mammedov     SPARCCPU *cpu = SPARC_CPU(obj);
795de05005bSIgor Mammedov     int64_t value = cpu->env.def.nwindows;
796de05005bSIgor Mammedov 
797de05005bSIgor Mammedov     visit_type_int(v, name, &value, errp);
798de05005bSIgor Mammedov }
799de05005bSIgor Mammedov 
800de05005bSIgor Mammedov static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
801de05005bSIgor Mammedov                                void *opaque, Error **errp)
802de05005bSIgor Mammedov {
803de05005bSIgor Mammedov     const int64_t min = MIN_NWINDOWS;
804de05005bSIgor Mammedov     const int64_t max = MAX_NWINDOWS;
805de05005bSIgor Mammedov     SPARCCPU *cpu = SPARC_CPU(obj);
806de05005bSIgor Mammedov     Error *err = NULL;
807de05005bSIgor Mammedov     int64_t value;
808de05005bSIgor Mammedov 
809de05005bSIgor Mammedov     visit_type_int(v, name, &value, &err);
810de05005bSIgor Mammedov     if (err) {
811de05005bSIgor Mammedov         error_propagate(errp, err);
812de05005bSIgor Mammedov         return;
813de05005bSIgor Mammedov     }
814de05005bSIgor Mammedov 
815de05005bSIgor Mammedov     if (value < min || value > max) {
816de05005bSIgor Mammedov         error_setg(errp, "Property %s.%s doesn't take value %" PRId64
817de05005bSIgor Mammedov                    " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
818de05005bSIgor Mammedov                    object_get_typename(obj), name ? name : "null",
819de05005bSIgor Mammedov                    value, min, max);
820de05005bSIgor Mammedov         return;
821de05005bSIgor Mammedov     }
822de05005bSIgor Mammedov     cpu->env.def.nwindows = value;
823de05005bSIgor Mammedov }
824de05005bSIgor Mammedov 
825de05005bSIgor Mammedov static PropertyInfo qdev_prop_nwindows = {
826de05005bSIgor Mammedov     .name  = "int",
827de05005bSIgor Mammedov     .get   = sparc_get_nwindows,
828de05005bSIgor Mammedov     .set   = sparc_set_nwindows,
829de05005bSIgor Mammedov };
830de05005bSIgor Mammedov 
831de05005bSIgor Mammedov static Property sparc_cpu_properties[] = {
832de05005bSIgor Mammedov     DEFINE_PROP_BIT("float",    SPARCCPU, env.def.features, 0, false),
833de05005bSIgor Mammedov     DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
834de05005bSIgor Mammedov     DEFINE_PROP_BIT("swap",     SPARCCPU, env.def.features, 2, false),
835de05005bSIgor Mammedov     DEFINE_PROP_BIT("mul",      SPARCCPU, env.def.features, 3, false),
836de05005bSIgor Mammedov     DEFINE_PROP_BIT("div",      SPARCCPU, env.def.features, 4, false),
837de05005bSIgor Mammedov     DEFINE_PROP_BIT("flush",    SPARCCPU, env.def.features, 5, false),
838de05005bSIgor Mammedov     DEFINE_PROP_BIT("fsqrt",    SPARCCPU, env.def.features, 6, false),
839de05005bSIgor Mammedov     DEFINE_PROP_BIT("fmul",     SPARCCPU, env.def.features, 7, false),
840de05005bSIgor Mammedov     DEFINE_PROP_BIT("vis1",     SPARCCPU, env.def.features, 8, false),
841de05005bSIgor Mammedov     DEFINE_PROP_BIT("vis2",     SPARCCPU, env.def.features, 9, false),
842de05005bSIgor Mammedov     DEFINE_PROP_BIT("fsmuld",   SPARCCPU, env.def.features, 10, false),
843de05005bSIgor Mammedov     DEFINE_PROP_BIT("hypv",     SPARCCPU, env.def.features, 11, false),
844de05005bSIgor Mammedov     DEFINE_PROP_BIT("cmt",      SPARCCPU, env.def.features, 12, false),
845de05005bSIgor Mammedov     DEFINE_PROP_BIT("gl",       SPARCCPU, env.def.features, 13, false),
846de05005bSIgor Mammedov     DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
847de05005bSIgor Mammedov                          qdev_prop_uint64, target_ulong),
848de05005bSIgor Mammedov     DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
849de05005bSIgor Mammedov     DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
850de05005bSIgor Mammedov     { .name  = "nwindows", .info  = &qdev_prop_nwindows },
851de05005bSIgor Mammedov     DEFINE_PROP_END_OF_LIST()
852de05005bSIgor Mammedov };
853de05005bSIgor Mammedov 
854ab7ab3d7SAndreas Färber static void sparc_cpu_class_init(ObjectClass *oc, void *data)
855ab7ab3d7SAndreas Färber {
856ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
857ab7ab3d7SAndreas Färber     CPUClass *cc = CPU_CLASS(oc);
858b6e91ebfSAndreas Färber     DeviceClass *dc = DEVICE_CLASS(oc);
859b6e91ebfSAndreas Färber 
860bf853881SPhilippe Mathieu-Daudé     device_class_set_parent_realize(dc, sparc_cpu_realizefn,
861bf853881SPhilippe Mathieu-Daudé                                     &scc->parent_realize);
862de05005bSIgor Mammedov     dc->props = sparc_cpu_properties;
863ab7ab3d7SAndreas Färber 
864ab7ab3d7SAndreas Färber     scc->parent_reset = cc->reset;
865ab7ab3d7SAndreas Färber     cc->reset = sparc_cpu_reset;
86697a8ea5aSAndreas Färber 
86712a6c15eSIgor Mammedov     cc->class_by_name = sparc_cpu_class_by_name;
868d1853231SIgor Mammedov     cc->parse_features = sparc_cpu_parse_features;
8698c2e1b00SAndreas Färber     cc->has_work = sparc_cpu_has_work;
87097a8ea5aSAndreas Färber     cc->do_interrupt = sparc_cpu_do_interrupt;
87187afe467SRichard Henderson     cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
872878096eeSAndreas Färber     cc->dump_state = sparc_cpu_dump_state;
873f3659eeeSAndreas Färber #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
874f3659eeeSAndreas Färber     cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
875f3659eeeSAndreas Färber #endif
876f45748f1SAndreas Färber     cc->set_pc = sparc_cpu_set_pc;
877bdf7ae5bSAndreas Färber     cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
8785b50e790SAndreas Färber     cc->gdb_read_register = sparc_cpu_gdb_read_register;
8795b50e790SAndreas Färber     cc->gdb_write_register = sparc_cpu_gdb_write_register;
8807510454eSAndreas Färber #ifdef CONFIG_USER_ONLY
8817510454eSAndreas Färber     cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
8827510454eSAndreas Färber #else
88300b941e5SAndreas Färber     cc->do_unassigned_access = sparc_cpu_unassigned_access;
88493e22326SPaolo Bonzini     cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
88500b941e5SAndreas Färber     cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
886df32c8d4SJuan Quintela     cc->vmsd = &vmstate_sparc_cpu;
88700b941e5SAndreas Färber #endif
888df0900ebSPeter Crosthwaite     cc->disas_set_info = cpu_sparc_disas_set_info;
88955c3ceefSRichard Henderson     cc->tcg_initialize = sparc_tcg_init;
890a0e372f0SAndreas Färber 
891a0e372f0SAndreas Färber #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
892a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 86;
893a0e372f0SAndreas Färber #else
894a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 72;
895a0e372f0SAndreas Färber #endif
896ab7ab3d7SAndreas Färber }
897ab7ab3d7SAndreas Färber 
898ab7ab3d7SAndreas Färber static const TypeInfo sparc_cpu_type_info = {
899ab7ab3d7SAndreas Färber     .name = TYPE_SPARC_CPU,
900ab7ab3d7SAndreas Färber     .parent = TYPE_CPU,
901ab7ab3d7SAndreas Färber     .instance_size = sizeof(SPARCCPU),
902ab7ab3d7SAndreas Färber     .instance_init = sparc_cpu_initfn,
90312a6c15eSIgor Mammedov     .abstract = true,
904ab7ab3d7SAndreas Färber     .class_size = sizeof(SPARCCPUClass),
905ab7ab3d7SAndreas Färber     .class_init = sparc_cpu_class_init,
906ab7ab3d7SAndreas Färber };
907ab7ab3d7SAndreas Färber 
90812a6c15eSIgor Mammedov static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
90912a6c15eSIgor Mammedov {
91012a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
91112a6c15eSIgor Mammedov     scc->cpu_def = data;
91212a6c15eSIgor Mammedov }
91312a6c15eSIgor Mammedov 
91412a6c15eSIgor Mammedov static void sparc_register_cpudef_type(const struct sparc_def_t *def)
91512a6c15eSIgor Mammedov {
91612a6c15eSIgor Mammedov     char *typename = sparc_cpu_type_name(def->name);
91712a6c15eSIgor Mammedov     TypeInfo ti = {
91812a6c15eSIgor Mammedov         .name = typename,
91912a6c15eSIgor Mammedov         .parent = TYPE_SPARC_CPU,
92012a6c15eSIgor Mammedov         .class_init = sparc_cpu_cpudef_class_init,
92112a6c15eSIgor Mammedov         .class_data = (void *)def,
92212a6c15eSIgor Mammedov     };
92312a6c15eSIgor Mammedov 
92412a6c15eSIgor Mammedov     type_register(&ti);
92512a6c15eSIgor Mammedov     g_free(typename);
92612a6c15eSIgor Mammedov }
92712a6c15eSIgor Mammedov 
928ab7ab3d7SAndreas Färber static void sparc_cpu_register_types(void)
929ab7ab3d7SAndreas Färber {
93012a6c15eSIgor Mammedov     int i;
93112a6c15eSIgor Mammedov 
932ab7ab3d7SAndreas Färber     type_register_static(&sparc_cpu_type_info);
93312a6c15eSIgor Mammedov     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
93412a6c15eSIgor Mammedov         sparc_register_cpudef_type(&sparc_defs[i]);
93512a6c15eSIgor Mammedov     }
936ab7ab3d7SAndreas Färber }
937ab7ab3d7SAndreas Färber 
938ab7ab3d7SAndreas Färber type_init(sparc_cpu_register_types)
939