xref: /qemu/target/sparc/cpu.c (revision ca4d5d862df43630381647552725eaf1099033b8)
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
95650b549SChetan Pant  * version 2.1 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"
230b8fa32fSMarkus Armbruster #include "qemu/module.h"
240442428aSMarkus Armbruster #include "qemu/qemu-print.h"
2563c91552SPaolo Bonzini #include "exec/exec-all.h"
26de05005bSIgor Mammedov #include "hw/qdev-properties.h"
27de05005bSIgor Mammedov #include "qapi/visitor.h"
28c4bf3a92SAnton Johansson #include "tcg/tcg.h"
29ab3b491fSBlue Swirl 
30ab3b491fSBlue Swirl //#define DEBUG_FEATURES
31ab3b491fSBlue Swirl 
323b4fff1bSPeter Maydell static void sparc_cpu_reset_hold(Object *obj)
33ab7ab3d7SAndreas Färber {
343b4fff1bSPeter Maydell     CPUState *s = CPU(obj);
35ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(s);
36ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
37ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
38ab7ab3d7SAndreas Färber 
393b4fff1bSPeter Maydell     if (scc->parent_phases.hold) {
403b4fff1bSPeter Maydell         scc->parent_phases.hold(obj);
413b4fff1bSPeter Maydell     }
42ab7ab3d7SAndreas Färber 
431f5c00cfSAlex Bennée     memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
44ab3b491fSBlue Swirl     env->cwp = 0;
45ab3b491fSBlue Swirl #ifndef TARGET_SPARC64
46ab3b491fSBlue Swirl     env->wim = 1;
47ab3b491fSBlue Swirl #endif
48ab3b491fSBlue Swirl     env->regwptr = env->regbase + (env->cwp * 16);
49ab3b491fSBlue Swirl     CC_OP = CC_OP_FLAGS;
50ab3b491fSBlue Swirl #if defined(CONFIG_USER_ONLY)
51ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
52ab3b491fSBlue Swirl     env->cleanwin = env->nwindows - 2;
53ab3b491fSBlue Swirl     env->cansave = env->nwindows - 2;
54ab3b491fSBlue Swirl     env->pstate = PS_RMO | PS_PEF | PS_IE;
55ab3b491fSBlue Swirl     env->asi = 0x82; /* Primary no-fault */
56ab3b491fSBlue Swirl #endif
57ab3b491fSBlue Swirl #else
58ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
59ab3b491fSBlue Swirl     env->psret = 0;
60ab3b491fSBlue Swirl     env->psrs = 1;
61ab3b491fSBlue Swirl     env->psrps = 1;
62ab3b491fSBlue Swirl #endif
63ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
64cbc3a6a4SArtyom Tarasenko     env->pstate = PS_PRIV | PS_RED | PS_PEF;
65cbc3a6a4SArtyom Tarasenko     if (!cpu_has_hypervisor(env)) {
66cbc3a6a4SArtyom Tarasenko         env->pstate |= PS_AG;
67cbc3a6a4SArtyom Tarasenko     }
68ab3b491fSBlue Swirl     env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
69ab3b491fSBlue Swirl     env->tl = env->maxtl;
70cbc3a6a4SArtyom Tarasenko     env->gl = 2;
71ab3b491fSBlue Swirl     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
72ab3b491fSBlue Swirl     env->lsu = 0;
73ab3b491fSBlue Swirl #else
74ab3b491fSBlue Swirl     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
75576e1c4cSIgor Mammedov     env->mmuregs[0] |= env->def.mmu_bm;
76ab3b491fSBlue Swirl #endif
77ab3b491fSBlue Swirl     env->pc = 0;
78ab3b491fSBlue Swirl     env->npc = env->pc + 4;
79ab3b491fSBlue Swirl #endif
80ab3b491fSBlue Swirl     env->cache_control = 0;
81ab3b491fSBlue Swirl }
82ab3b491fSBlue Swirl 
83798ac8b5SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
8487afe467SRichard Henderson static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
8587afe467SRichard Henderson {
8687afe467SRichard Henderson     if (interrupt_request & CPU_INTERRUPT_HARD) {
8787afe467SRichard Henderson         SPARCCPU *cpu = SPARC_CPU(cs);
8887afe467SRichard Henderson         CPUSPARCState *env = &cpu->env;
8987afe467SRichard Henderson 
9087afe467SRichard Henderson         if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
9187afe467SRichard Henderson             int pil = env->interrupt_index & 0xf;
9287afe467SRichard Henderson             int type = env->interrupt_index & 0xf0;
9387afe467SRichard Henderson 
9487afe467SRichard Henderson             if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
9587afe467SRichard Henderson                 cs->exception_index = env->interrupt_index;
9687afe467SRichard Henderson                 sparc_cpu_do_interrupt(cs);
9787afe467SRichard Henderson                 return true;
9887afe467SRichard Henderson             }
9987afe467SRichard Henderson         }
10087afe467SRichard Henderson     }
10187afe467SRichard Henderson     return false;
10287afe467SRichard Henderson }
103798ac8b5SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
10487afe467SRichard Henderson 
105df0900ebSPeter Crosthwaite static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
106df0900ebSPeter Crosthwaite {
107df0900ebSPeter Crosthwaite     info->print_insn = print_insn_sparc;
108df0900ebSPeter Crosthwaite #ifdef TARGET_SPARC64
109df0900ebSPeter Crosthwaite     info->mach = bfd_mach_sparc_v9b;
110df0900ebSPeter Crosthwaite #endif
111df0900ebSPeter Crosthwaite }
112df0900ebSPeter Crosthwaite 
113d1853231SIgor Mammedov static void
114d1853231SIgor Mammedov cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
115ab3b491fSBlue Swirl {
116d1853231SIgor Mammedov     GlobalProperty *prop = g_new0(typeof(*prop), 1);
117d1853231SIgor Mammedov     prop->driver = typename;
118d1853231SIgor Mammedov     prop->property = g_strdup(name);
119d1853231SIgor Mammedov     prop->value = g_strdup(val);
120d1853231SIgor Mammedov     qdev_prop_register_global(prop);
121433ac7a9SAndreas Färber }
122433ac7a9SAndreas Färber 
123d1853231SIgor Mammedov /* Parse "+feature,-feature,feature=foo" CPU feature string */
124d1853231SIgor Mammedov static void sparc_cpu_parse_features(const char *typename, char *features,
125d1853231SIgor Mammedov                                      Error **errp)
126d1853231SIgor Mammedov {
127d1853231SIgor Mammedov     GList *l, *plus_features = NULL, *minus_features = NULL;
128d1853231SIgor Mammedov     char *featurestr; /* Single 'key=value" string being parsed */
129d1853231SIgor Mammedov     static bool cpu_globals_initialized;
130d1853231SIgor Mammedov 
131d1853231SIgor Mammedov     if (cpu_globals_initialized) {
132d1853231SIgor Mammedov         return;
133d1853231SIgor Mammedov     }
134d1853231SIgor Mammedov     cpu_globals_initialized = true;
135d1853231SIgor Mammedov 
136d1853231SIgor Mammedov     if (!features) {
137d1853231SIgor Mammedov         return;
138d1853231SIgor Mammedov     }
139d1853231SIgor Mammedov 
140d1853231SIgor Mammedov     for (featurestr = strtok(features, ",");
141d1853231SIgor Mammedov          featurestr;
142d1853231SIgor Mammedov          featurestr = strtok(NULL, ",")) {
143d1853231SIgor Mammedov         const char *name;
144d1853231SIgor Mammedov         const char *val = NULL;
145d1853231SIgor Mammedov         char *eq = NULL;
146d1853231SIgor Mammedov 
147d1853231SIgor Mammedov         /* Compatibility syntax: */
148d1853231SIgor Mammedov         if (featurestr[0] == '+') {
149d1853231SIgor Mammedov             plus_features = g_list_append(plus_features,
150d1853231SIgor Mammedov                                           g_strdup(featurestr + 1));
151d1853231SIgor Mammedov             continue;
152d1853231SIgor Mammedov         } else if (featurestr[0] == '-') {
153d1853231SIgor Mammedov             minus_features = g_list_append(minus_features,
154d1853231SIgor Mammedov                                            g_strdup(featurestr + 1));
155d1853231SIgor Mammedov             continue;
156d1853231SIgor Mammedov         }
157d1853231SIgor Mammedov 
158d1853231SIgor Mammedov         eq = strchr(featurestr, '=');
159d1853231SIgor Mammedov         name = featurestr;
160d1853231SIgor Mammedov         if (eq) {
161d1853231SIgor Mammedov             *eq++ = 0;
162d1853231SIgor Mammedov             val = eq;
163d1853231SIgor Mammedov 
164d1853231SIgor Mammedov             /*
165d1853231SIgor Mammedov              * Temporarily, only +feat/-feat will be supported
166d1853231SIgor Mammedov              * for boolean properties until we remove the
167d1853231SIgor Mammedov              * minus-overrides-plus semantics and just follow
168d1853231SIgor Mammedov              * the order options appear on the command-line.
169d1853231SIgor Mammedov              *
170d1853231SIgor Mammedov              * TODO: warn if user is relying on minus-override-plus semantics
171d1853231SIgor Mammedov              * TODO: remove minus-override-plus semantics after
172d1853231SIgor Mammedov              *       warning for a few releases
173d1853231SIgor Mammedov              */
174d1853231SIgor Mammedov             if (!strcasecmp(val, "on") ||
175d1853231SIgor Mammedov                 !strcasecmp(val, "off") ||
176d1853231SIgor Mammedov                 !strcasecmp(val, "true") ||
177d1853231SIgor Mammedov                 !strcasecmp(val, "false")) {
178d1853231SIgor Mammedov                 error_setg(errp, "Boolean properties in format %s=%s"
179d1853231SIgor Mammedov                                  " are not supported", name, val);
180d1853231SIgor Mammedov                 return;
181d1853231SIgor Mammedov             }
182d1853231SIgor Mammedov         } else {
183d1853231SIgor Mammedov             error_setg(errp, "Unsupported property format: %s", name);
184d1853231SIgor Mammedov             return;
185d1853231SIgor Mammedov         }
186d1853231SIgor Mammedov         cpu_add_feat_as_prop(typename, name, val);
187d1853231SIgor Mammedov     }
188d1853231SIgor Mammedov 
189d1853231SIgor Mammedov     for (l = plus_features; l; l = l->next) {
190d1853231SIgor Mammedov         const char *name = l->data;
191d1853231SIgor Mammedov         cpu_add_feat_as_prop(typename, name, "on");
192d1853231SIgor Mammedov     }
193d1853231SIgor Mammedov     g_list_free_full(plus_features, g_free);
194d1853231SIgor Mammedov 
195d1853231SIgor Mammedov     for (l = minus_features; l; l = l->next) {
196d1853231SIgor Mammedov         const char *name = l->data;
197d1853231SIgor Mammedov         cpu_add_feat_as_prop(typename, name, "off");
198d1853231SIgor Mammedov     }
199d1853231SIgor Mammedov     g_list_free_full(minus_features, g_free);
200ab3b491fSBlue Swirl }
201ab3b491fSBlue Swirl 
202ab3b491fSBlue Swirl void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
203ab3b491fSBlue Swirl {
204ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
205ab3b491fSBlue Swirl     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
206ab3b491fSBlue Swirl #endif
207ab3b491fSBlue Swirl }
208ab3b491fSBlue Swirl 
209ab3b491fSBlue Swirl static const sparc_def_t sparc_defs[] = {
210ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
211ab3b491fSBlue Swirl     {
212ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64",
213ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
214ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
215ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
216ab3b491fSBlue Swirl         .nwindows = 4,
217ab3b491fSBlue Swirl         .maxtl = 4,
218ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
219ab3b491fSBlue Swirl     },
220ab3b491fSBlue Swirl     {
221ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 III",
222ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
223ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
224ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
225ab3b491fSBlue Swirl         .nwindows = 5,
226ab3b491fSBlue Swirl         .maxtl = 4,
227ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
228ab3b491fSBlue Swirl     },
229ab3b491fSBlue Swirl     {
230ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 IV",
231ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
232ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
233ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
234ab3b491fSBlue Swirl         .nwindows = 8,
235ab3b491fSBlue Swirl         .maxtl = 5,
236ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
237ab3b491fSBlue Swirl     },
238ab3b491fSBlue Swirl     {
239ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 V",
240ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
241ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
242ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
243ab3b491fSBlue Swirl         .nwindows = 8,
244ab3b491fSBlue Swirl         .maxtl = 5,
245ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
246ab3b491fSBlue Swirl     },
247ab3b491fSBlue Swirl     {
248ab3b491fSBlue Swirl         .name = "TI UltraSparc I",
249ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
250ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
251ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
252ab3b491fSBlue Swirl         .nwindows = 8,
253ab3b491fSBlue Swirl         .maxtl = 5,
254ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
255ab3b491fSBlue Swirl     },
256ab3b491fSBlue Swirl     {
257ab3b491fSBlue Swirl         .name = "TI UltraSparc II",
258ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
259ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
260ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
261ab3b491fSBlue Swirl         .nwindows = 8,
262ab3b491fSBlue Swirl         .maxtl = 5,
263ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
264ab3b491fSBlue Swirl     },
265ab3b491fSBlue Swirl     {
266ab3b491fSBlue Swirl         .name = "TI UltraSparc IIi",
267ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
268ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
269ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
270ab3b491fSBlue Swirl         .nwindows = 8,
271ab3b491fSBlue Swirl         .maxtl = 5,
272ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
273ab3b491fSBlue Swirl     },
274ab3b491fSBlue Swirl     {
275ab3b491fSBlue Swirl         .name = "TI UltraSparc IIe",
276ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
277ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
278ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
279ab3b491fSBlue Swirl         .nwindows = 8,
280ab3b491fSBlue Swirl         .maxtl = 5,
281ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
282ab3b491fSBlue Swirl     },
283ab3b491fSBlue Swirl     {
284ab3b491fSBlue Swirl         .name = "Sun UltraSparc III",
285ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
286ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
287ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
288ab3b491fSBlue Swirl         .nwindows = 8,
289ab3b491fSBlue Swirl         .maxtl = 5,
290ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
291ab3b491fSBlue Swirl     },
292ab3b491fSBlue Swirl     {
293ab3b491fSBlue Swirl         .name = "Sun UltraSparc III Cu",
294ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
295ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
296ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
297ab3b491fSBlue Swirl         .nwindows = 8,
298ab3b491fSBlue Swirl         .maxtl = 5,
299ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
300ab3b491fSBlue Swirl     },
301ab3b491fSBlue Swirl     {
302ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi",
303ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
304ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
305ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
306ab3b491fSBlue Swirl         .nwindows = 8,
307ab3b491fSBlue Swirl         .maxtl = 5,
308ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
309ab3b491fSBlue Swirl     },
310ab3b491fSBlue Swirl     {
311ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV",
312ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
313ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
314ab3b491fSBlue Swirl         .mmu_version = mmu_us_4,
315ab3b491fSBlue Swirl         .nwindows = 8,
316ab3b491fSBlue Swirl         .maxtl = 5,
317ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
318ab3b491fSBlue Swirl     },
319ab3b491fSBlue Swirl     {
320ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV+",
321ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
322ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
323ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
324ab3b491fSBlue Swirl         .nwindows = 8,
325ab3b491fSBlue Swirl         .maxtl = 5,
326ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
327ab3b491fSBlue Swirl     },
328ab3b491fSBlue Swirl     {
329ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi+",
330ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
331ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
332ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
333ab3b491fSBlue Swirl         .nwindows = 8,
334ab3b491fSBlue Swirl         .maxtl = 5,
335ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
336ab3b491fSBlue Swirl     },
337ab3b491fSBlue Swirl     {
338ab3b491fSBlue Swirl         .name = "Sun UltraSparc T1",
339ab3b491fSBlue Swirl         /* defined in sparc_ifu_fdp.v and ctu.h */
340ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
341ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
342ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
343ab3b491fSBlue Swirl         .nwindows = 8,
344ab3b491fSBlue Swirl         .maxtl = 6,
345ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
346ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
347ab3b491fSBlue Swirl     },
348ab3b491fSBlue Swirl     {
349ab3b491fSBlue Swirl         .name = "Sun UltraSparc T2",
350ab3b491fSBlue Swirl         /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
351ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
352ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
353ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
354ab3b491fSBlue Swirl         .nwindows = 8,
355ab3b491fSBlue Swirl         .maxtl = 6,
356ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
357ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
358ab3b491fSBlue Swirl     },
359ab3b491fSBlue Swirl     {
360ab3b491fSBlue Swirl         .name = "NEC UltraSparc I",
361ab3b491fSBlue Swirl         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
362ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
363ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
364ab3b491fSBlue Swirl         .nwindows = 8,
365ab3b491fSBlue Swirl         .maxtl = 5,
366ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
367ab3b491fSBlue Swirl     },
368ab3b491fSBlue Swirl #else
369ab3b491fSBlue Swirl     {
370ab3b491fSBlue Swirl         .name = "Fujitsu MB86904",
371ab3b491fSBlue Swirl         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
372ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
373ab3b491fSBlue Swirl         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
374ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
375ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
376ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
377ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
378ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
379ab3b491fSBlue Swirl         .nwindows = 8,
380ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
381ab3b491fSBlue Swirl     },
382ab3b491fSBlue Swirl     {
383ab3b491fSBlue Swirl         .name = "Fujitsu MB86907",
384ab3b491fSBlue Swirl         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
385ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
386ab3b491fSBlue Swirl         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
387ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
388ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
389ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
390ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
391ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
392ab3b491fSBlue Swirl         .nwindows = 8,
393ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
394ab3b491fSBlue Swirl     },
395ab3b491fSBlue Swirl     {
396ab3b491fSBlue Swirl         .name = "TI MicroSparc I",
397ab3b491fSBlue Swirl         .iu_version = 0x41000000,
398ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
399ab3b491fSBlue Swirl         .mmu_version = 0x41000000,
400ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
401ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
402ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
403ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
404ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x0000003f,
405ab3b491fSBlue Swirl         .nwindows = 7,
406ab3b491fSBlue Swirl         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
407ab3b491fSBlue Swirl         CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
408ab3b491fSBlue Swirl         CPU_FEATURE_FMUL,
409ab3b491fSBlue Swirl     },
410ab3b491fSBlue Swirl     {
411ab3b491fSBlue Swirl         .name = "TI MicroSparc II",
412ab3b491fSBlue Swirl         .iu_version = 0x42000000,
413ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
414ab3b491fSBlue Swirl         .mmu_version = 0x02000000,
415ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
416ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
417ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
418ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
419ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
420ab3b491fSBlue Swirl         .nwindows = 8,
421ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
422ab3b491fSBlue Swirl     },
423ab3b491fSBlue Swirl     {
424ab3b491fSBlue Swirl         .name = "TI MicroSparc IIep",
425ab3b491fSBlue Swirl         .iu_version = 0x42000000,
426ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
427ab3b491fSBlue Swirl         .mmu_version = 0x04000000,
428ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
429ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
430ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
431ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016bff,
432ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
433ab3b491fSBlue Swirl         .nwindows = 8,
434ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
435ab3b491fSBlue Swirl     },
436ab3b491fSBlue Swirl     {
437ab3b491fSBlue Swirl         .name = "TI SuperSparc 40", /* STP1020NPGA */
438ab3b491fSBlue Swirl         .iu_version = 0x41000000, /* SuperSPARC 2.x */
439ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
440ab3b491fSBlue Swirl         .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
441ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
442ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
443ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
444ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
445ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
446ab3b491fSBlue Swirl         .nwindows = 8,
447ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
448ab3b491fSBlue Swirl     },
449ab3b491fSBlue Swirl     {
450ab3b491fSBlue Swirl         .name = "TI SuperSparc 50", /* STP1020PGA */
451ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
452ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
453ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
454ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
455ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
456ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
457ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
458ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
459ab3b491fSBlue Swirl         .nwindows = 8,
460ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
461ab3b491fSBlue Swirl     },
462ab3b491fSBlue Swirl     {
463ab3b491fSBlue Swirl         .name = "TI SuperSparc 51",
464ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
465ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
466ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
467ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
468ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
469ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
470ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
471ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
472ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
473ab3b491fSBlue Swirl         .nwindows = 8,
474ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
475ab3b491fSBlue Swirl     },
476ab3b491fSBlue Swirl     {
477ab3b491fSBlue Swirl         .name = "TI SuperSparc 60", /* STP1020APGA */
478ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
479ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
480ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
481ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
482ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
483ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
484ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
485ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
486ab3b491fSBlue Swirl         .nwindows = 8,
487ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
488ab3b491fSBlue Swirl     },
489ab3b491fSBlue Swirl     {
490ab3b491fSBlue Swirl         .name = "TI SuperSparc 61",
491ab3b491fSBlue Swirl         .iu_version = 0x44000000, /* SuperSPARC 3.x */
492ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
493ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
494ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
495ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
496ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
497ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
498ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
499ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
500ab3b491fSBlue Swirl         .nwindows = 8,
501ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
502ab3b491fSBlue Swirl     },
503ab3b491fSBlue Swirl     {
504ab3b491fSBlue Swirl         .name = "TI SuperSparc II",
505ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC II 1.x */
506ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
507ab3b491fSBlue Swirl         .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
508ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
509ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
510ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
511ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
512ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
513ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
514ab3b491fSBlue Swirl         .nwindows = 8,
515ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
516ab3b491fSBlue Swirl     },
517ab3b491fSBlue Swirl     {
518ab3b491fSBlue Swirl         .name = "LEON2",
519ab3b491fSBlue Swirl         .iu_version = 0xf2000000,
520ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
521ab3b491fSBlue Swirl         .mmu_version = 0xf2000000,
522ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
523ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
524ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
525ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
526ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
527ab3b491fSBlue Swirl         .nwindows = 8,
528ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
529ab3b491fSBlue Swirl     },
530ab3b491fSBlue Swirl     {
531ab3b491fSBlue Swirl         .name = "LEON3",
532ab3b491fSBlue Swirl         .iu_version = 0xf3000000,
533ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
534ab3b491fSBlue Swirl         .mmu_version = 0xf3000000,
535ab3b491fSBlue Swirl         .mmu_bm = 0x00000000,
5367a0a9c2cSRonald Hecht         .mmu_ctpr_mask = 0xfffffffc,
5377a0a9c2cSRonald Hecht         .mmu_cxr_mask = 0x000000ff,
538ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
539ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
540ab3b491fSBlue Swirl         .nwindows = 8,
541ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
54216c358e9SSebastian Huber         CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
54316c358e9SSebastian Huber         CPU_FEATURE_CASA,
544ab3b491fSBlue Swirl     },
545ab3b491fSBlue Swirl #endif
546ab3b491fSBlue Swirl };
547ab3b491fSBlue Swirl 
548ab3b491fSBlue Swirl static const char * const feature_name[] = {
549ab3b491fSBlue Swirl     "float",
550ab3b491fSBlue Swirl     "float128",
551ab3b491fSBlue Swirl     "swap",
552ab3b491fSBlue Swirl     "mul",
553ab3b491fSBlue Swirl     "div",
554ab3b491fSBlue Swirl     "flush",
555ab3b491fSBlue Swirl     "fsqrt",
556ab3b491fSBlue Swirl     "fmul",
557ab3b491fSBlue Swirl     "vis1",
558ab3b491fSBlue Swirl     "vis2",
559ab3b491fSBlue Swirl     "fsmuld",
560ab3b491fSBlue Swirl     "hypv",
561ab3b491fSBlue Swirl     "cmt",
562ab3b491fSBlue Swirl     "gl",
563ab3b491fSBlue Swirl };
564ab3b491fSBlue Swirl 
5650442428aSMarkus Armbruster static void print_features(uint32_t features, const char *prefix)
566ab3b491fSBlue Swirl {
567ab3b491fSBlue Swirl     unsigned int i;
568ab3b491fSBlue Swirl 
569ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
570ab3b491fSBlue Swirl         if (feature_name[i] && (features & (1 << i))) {
571ab3b491fSBlue Swirl             if (prefix) {
5720442428aSMarkus Armbruster                 qemu_printf("%s", prefix);
573ab3b491fSBlue Swirl             }
5740442428aSMarkus Armbruster             qemu_printf("%s ", feature_name[i]);
575ab3b491fSBlue Swirl         }
576ab3b491fSBlue Swirl     }
577ab3b491fSBlue Swirl }
578ab3b491fSBlue Swirl 
5790442428aSMarkus Armbruster void sparc_cpu_list(void)
580ab3b491fSBlue Swirl {
581ab3b491fSBlue Swirl     unsigned int i;
582ab3b491fSBlue Swirl 
583ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
5840442428aSMarkus Armbruster         qemu_printf("Sparc %16s IU " TARGET_FMT_lx
585ab3b491fSBlue Swirl                     " FPU %08x MMU %08x NWINS %d ",
586ab3b491fSBlue Swirl                     sparc_defs[i].name,
587ab3b491fSBlue Swirl                     sparc_defs[i].iu_version,
588ab3b491fSBlue Swirl                     sparc_defs[i].fpu_version,
589ab3b491fSBlue Swirl                     sparc_defs[i].mmu_version,
590ab3b491fSBlue Swirl                     sparc_defs[i].nwindows);
5910442428aSMarkus Armbruster         print_features(CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
5920442428aSMarkus Armbruster         print_features(~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
5930442428aSMarkus Armbruster         qemu_printf("\n");
594ab3b491fSBlue Swirl     }
5950442428aSMarkus Armbruster     qemu_printf("Default CPU feature flags (use '-' to remove): ");
5960442428aSMarkus Armbruster     print_features(CPU_DEFAULT_FEATURES, NULL);
5970442428aSMarkus Armbruster     qemu_printf("\n");
5980442428aSMarkus Armbruster     qemu_printf("Available CPU feature flags (use '+' to add): ");
5990442428aSMarkus Armbruster     print_features(~CPU_DEFAULT_FEATURES, NULL);
6000442428aSMarkus Armbruster     qemu_printf("\n");
6010442428aSMarkus Armbruster     qemu_printf("Numerical features (use '=' to set): iu_version "
602ab3b491fSBlue Swirl                 "fpu_version mmu_version nwindows\n");
603ab3b491fSBlue Swirl }
604ab3b491fSBlue Swirl 
60590c84c56SMarkus Armbruster static void cpu_print_cc(FILE *f, uint32_t cc)
606ab3b491fSBlue Swirl {
60790c84c56SMarkus Armbruster     qemu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
608ab3b491fSBlue Swirl                  cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
609ab3b491fSBlue Swirl                  cc & PSR_CARRY ? 'C' : '-');
610ab3b491fSBlue Swirl }
611ab3b491fSBlue Swirl 
612ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
613ab3b491fSBlue Swirl #define REGS_PER_LINE 4
614ab3b491fSBlue Swirl #else
615ab3b491fSBlue Swirl #define REGS_PER_LINE 8
616ab3b491fSBlue Swirl #endif
617ab3b491fSBlue Swirl 
6189ac200acSPhilippe Mathieu-Daudé static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
619ab3b491fSBlue Swirl {
620878096eeSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
621878096eeSAndreas Färber     CPUSPARCState *env = &cpu->env;
622ab3b491fSBlue Swirl     int i, x;
623ab3b491fSBlue Swirl 
62490c84c56SMarkus Armbruster     qemu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
625ab3b491fSBlue Swirl                  env->npc);
626ab3b491fSBlue Swirl 
627ab3b491fSBlue Swirl     for (i = 0; i < 8; i++) {
628ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == 0) {
62990c84c56SMarkus Armbruster             qemu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
630ab3b491fSBlue Swirl         }
63190c84c56SMarkus Armbruster         qemu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
632ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
63390c84c56SMarkus Armbruster             qemu_fprintf(f, "\n");
634ab3b491fSBlue Swirl         }
635ab3b491fSBlue Swirl     }
636ab3b491fSBlue Swirl     for (x = 0; x < 3; x++) {
637ab3b491fSBlue Swirl         for (i = 0; i < 8; i++) {
638ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == 0) {
63990c84c56SMarkus Armbruster                 qemu_fprintf(f, "%%%c%d-%d: ",
640ab3b491fSBlue Swirl                              x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
641ab3b491fSBlue Swirl                              i, i + REGS_PER_LINE - 1);
642ab3b491fSBlue Swirl             }
64390c84c56SMarkus Armbruster             qemu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
644ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
64590c84c56SMarkus Armbruster                 qemu_fprintf(f, "\n");
646ab3b491fSBlue Swirl             }
647ab3b491fSBlue Swirl         }
648ab3b491fSBlue Swirl     }
64976a23ca0SRichard Henderson 
650d13c394cSRichard Henderson     if (flags & CPU_DUMP_FPU) {
65130038fd8SRichard Henderson         for (i = 0; i < TARGET_DPREGS; i++) {
652ab3b491fSBlue Swirl             if ((i & 3) == 0) {
65390c84c56SMarkus Armbruster                 qemu_fprintf(f, "%%f%02d: ", i * 2);
654ab3b491fSBlue Swirl             }
65590c84c56SMarkus Armbruster             qemu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
656ab3b491fSBlue Swirl             if ((i & 3) == 3) {
65790c84c56SMarkus Armbruster                 qemu_fprintf(f, "\n");
658ab3b491fSBlue Swirl             }
659ab3b491fSBlue Swirl         }
660d13c394cSRichard Henderson     }
661d13c394cSRichard Henderson 
662ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
66390c84c56SMarkus Armbruster     qemu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
664ab3b491fSBlue Swirl                  (unsigned)cpu_get_ccr(env));
66590c84c56SMarkus Armbruster     cpu_print_cc(f, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
66690c84c56SMarkus Armbruster     qemu_fprintf(f, " xcc: ");
66790c84c56SMarkus Armbruster     cpu_print_cc(f, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
66890c84c56SMarkus Armbruster     qemu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
669cbc3a6a4SArtyom Tarasenko                  env->psrpil, env->gl);
67090c84c56SMarkus Armbruster     qemu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
671cbc3a6a4SArtyom Tarasenko                  TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
67290c84c56SMarkus Armbruster     qemu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
673ab3b491fSBlue Swirl                  "cleanwin: %d cwp: %d\n",
674ab3b491fSBlue Swirl                  env->cansave, env->canrestore, env->otherwin, env->wstate,
675ab3b491fSBlue Swirl                  env->cleanwin, env->nwindows - 1 - env->cwp);
676*ca4d5d86SPeter Maydell     qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: %016x\n",
677*ca4d5d86SPeter Maydell                  env->fsr, env->y, env->fprs);
678cbc3a6a4SArtyom Tarasenko 
679ab3b491fSBlue Swirl #else
68090c84c56SMarkus Armbruster     qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
68190c84c56SMarkus Armbruster     cpu_print_cc(f, cpu_get_psr(env));
68290c84c56SMarkus Armbruster     qemu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
683ab3b491fSBlue Swirl                  env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
684ab3b491fSBlue Swirl                  env->wim);
68590c84c56SMarkus Armbruster     qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
686ab3b491fSBlue Swirl                  env->fsr, env->y);
687ab3b491fSBlue Swirl #endif
68890c84c56SMarkus Armbruster     qemu_fprintf(f, "\n");
689ab3b491fSBlue Swirl }
690ab7ab3d7SAndreas Färber 
691f45748f1SAndreas Färber static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
692f45748f1SAndreas Färber {
693f45748f1SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
694f45748f1SAndreas Färber 
695f45748f1SAndreas Färber     cpu->env.pc = value;
696f45748f1SAndreas Färber     cpu->env.npc = value + 4;
697f45748f1SAndreas Färber }
698f45748f1SAndreas Färber 
699e4fdf9dfSRichard Henderson static vaddr sparc_cpu_get_pc(CPUState *cs)
700e4fdf9dfSRichard Henderson {
701e4fdf9dfSRichard Henderson     SPARCCPU *cpu = SPARC_CPU(cs);
702e4fdf9dfSRichard Henderson 
703e4fdf9dfSRichard Henderson     return cpu->env.pc;
704e4fdf9dfSRichard Henderson }
705e4fdf9dfSRichard Henderson 
70604a37d4cSRichard Henderson static void sparc_cpu_synchronize_from_tb(CPUState *cs,
70704a37d4cSRichard Henderson                                           const TranslationBlock *tb)
708bdf7ae5bSAndreas Färber {
709bdf7ae5bSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
710bdf7ae5bSAndreas Färber 
711c4bf3a92SAnton Johansson     tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
712c4bf3a92SAnton Johansson     cpu->env.pc = tb->pc;
713bdf7ae5bSAndreas Färber     cpu->env.npc = tb->cs_base;
714bdf7ae5bSAndreas Färber }
715bdf7ae5bSAndreas Färber 
7168c2e1b00SAndreas Färber static bool sparc_cpu_has_work(CPUState *cs)
7178c2e1b00SAndreas Färber {
7188c2e1b00SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
7198c2e1b00SAndreas Färber     CPUSPARCState *env = &cpu->env;
7208c2e1b00SAndreas Färber 
7218c2e1b00SAndreas Färber     return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
7228c2e1b00SAndreas Färber            cpu_interrupts_enabled(env);
7238c2e1b00SAndreas Färber }
7248c2e1b00SAndreas Färber 
72512a6c15eSIgor Mammedov static char *sparc_cpu_type_name(const char *cpu_model)
72612a6c15eSIgor Mammedov {
7271d4bfc54SIgor Mammedov     char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
72812a6c15eSIgor Mammedov     char *s = name;
72912a6c15eSIgor Mammedov 
73012a6c15eSIgor Mammedov     /* SPARC cpu model names happen to have whitespaces,
73112a6c15eSIgor Mammedov      * as type names shouldn't have spaces replace them with '-'
73212a6c15eSIgor Mammedov      */
73312a6c15eSIgor Mammedov     while ((s = strchr(s, ' '))) {
73412a6c15eSIgor Mammedov         *s = '-';
73512a6c15eSIgor Mammedov     }
73612a6c15eSIgor Mammedov 
73712a6c15eSIgor Mammedov     return name;
73812a6c15eSIgor Mammedov }
73912a6c15eSIgor Mammedov 
74012a6c15eSIgor Mammedov static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
74112a6c15eSIgor Mammedov {
74212a6c15eSIgor Mammedov     ObjectClass *oc;
74312a6c15eSIgor Mammedov     char *typename;
74412a6c15eSIgor Mammedov 
74512a6c15eSIgor Mammedov     typename = sparc_cpu_type_name(cpu_model);
74612a6c15eSIgor Mammedov     oc = object_class_by_name(typename);
74712a6c15eSIgor Mammedov     g_free(typename);
74812a6c15eSIgor Mammedov     return oc;
74912a6c15eSIgor Mammedov }
75012a6c15eSIgor Mammedov 
751b6e91ebfSAndreas Färber static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
752b6e91ebfSAndreas Färber {
753ce5b1bbfSLaurent Vivier     CPUState *cs = CPU(dev);
754b6e91ebfSAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
755ce5b1bbfSLaurent Vivier     Error *local_err = NULL;
756247bf011SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(dev);
757247bf011SAndreas Färber     CPUSPARCState *env = &cpu->env;
758247bf011SAndreas Färber 
75970054962SIgor Mammedov #if defined(CONFIG_USER_ONLY)
760576e1c4cSIgor Mammedov     if ((env->def.features & CPU_FEATURE_FLOAT)) {
761576e1c4cSIgor Mammedov         env->def.features |= CPU_FEATURE_FLOAT128;
762247bf011SAndreas Färber     }
763247bf011SAndreas Färber #endif
764b6e91ebfSAndreas Färber 
76570054962SIgor Mammedov     env->version = env->def.iu_version;
76670054962SIgor Mammedov     env->fsr = env->def.fpu_version;
76770054962SIgor Mammedov     env->nwindows = env->def.nwindows;
76870054962SIgor Mammedov #if !defined(TARGET_SPARC64)
76970054962SIgor Mammedov     env->mmuregs[0] |= env->def.mmu_version;
77070054962SIgor Mammedov     cpu_sparc_set_id(env, 0);
77170054962SIgor Mammedov     env->mxccregs[7] |= env->def.mxcc_version;
77270054962SIgor Mammedov #else
77370054962SIgor Mammedov     env->mmu_version = env->def.mmu_version;
77470054962SIgor Mammedov     env->maxtl = env->def.maxtl;
77570054962SIgor Mammedov     env->version |= env->def.maxtl << 8;
77670054962SIgor Mammedov     env->version |= env->def.nwindows - 1;
77770054962SIgor Mammedov #endif
77870054962SIgor Mammedov 
779ce5b1bbfSLaurent Vivier     cpu_exec_realizefn(cs, &local_err);
780ce5b1bbfSLaurent Vivier     if (local_err != NULL) {
781ce5b1bbfSLaurent Vivier         error_propagate(errp, local_err);
782ce5b1bbfSLaurent Vivier         return;
783ce5b1bbfSLaurent Vivier     }
784ce5b1bbfSLaurent Vivier 
785ce5b1bbfSLaurent Vivier     qemu_init_vcpu(cs);
78614a10fc3SAndreas Färber 
787b6e91ebfSAndreas Färber     scc->parent_realize(dev, errp);
788b6e91ebfSAndreas Färber }
789b6e91ebfSAndreas Färber 
790ab7ab3d7SAndreas Färber static void sparc_cpu_initfn(Object *obj)
791ab7ab3d7SAndreas Färber {
792ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(obj);
79312a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
794ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
795ab7ab3d7SAndreas Färber 
7967506ed90SRichard Henderson     cpu_set_cpustate_pointers(cpu);
7975266d20aSAndreas Färber 
798576e1c4cSIgor Mammedov     if (scc->cpu_def) {
799576e1c4cSIgor Mammedov         env->def = *scc->cpu_def;
800ab7ab3d7SAndreas Färber     }
801ab7ab3d7SAndreas Färber }
802ab7ab3d7SAndreas Färber 
803de05005bSIgor Mammedov static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
804de05005bSIgor Mammedov                                void *opaque, Error **errp)
805de05005bSIgor Mammedov {
806de05005bSIgor Mammedov     SPARCCPU *cpu = SPARC_CPU(obj);
807de05005bSIgor Mammedov     int64_t value = cpu->env.def.nwindows;
808de05005bSIgor Mammedov 
809de05005bSIgor Mammedov     visit_type_int(v, name, &value, errp);
810de05005bSIgor Mammedov }
811de05005bSIgor Mammedov 
812de05005bSIgor Mammedov static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
813de05005bSIgor Mammedov                                void *opaque, Error **errp)
814de05005bSIgor Mammedov {
815de05005bSIgor Mammedov     const int64_t min = MIN_NWINDOWS;
816de05005bSIgor Mammedov     const int64_t max = MAX_NWINDOWS;
817de05005bSIgor Mammedov     SPARCCPU *cpu = SPARC_CPU(obj);
818de05005bSIgor Mammedov     int64_t value;
819de05005bSIgor Mammedov 
820668f62ecSMarkus Armbruster     if (!visit_type_int(v, name, &value, errp)) {
821de05005bSIgor Mammedov         return;
822de05005bSIgor Mammedov     }
823de05005bSIgor Mammedov 
824de05005bSIgor Mammedov     if (value < min || value > max) {
825de05005bSIgor Mammedov         error_setg(errp, "Property %s.%s doesn't take value %" PRId64
826de05005bSIgor Mammedov                    " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
827de05005bSIgor Mammedov                    object_get_typename(obj), name ? name : "null",
828de05005bSIgor Mammedov                    value, min, max);
829de05005bSIgor Mammedov         return;
830de05005bSIgor Mammedov     }
831de05005bSIgor Mammedov     cpu->env.def.nwindows = value;
832de05005bSIgor Mammedov }
833de05005bSIgor Mammedov 
834de05005bSIgor Mammedov static PropertyInfo qdev_prop_nwindows = {
835de05005bSIgor Mammedov     .name  = "int",
836de05005bSIgor Mammedov     .get   = sparc_get_nwindows,
837de05005bSIgor Mammedov     .set   = sparc_set_nwindows,
838de05005bSIgor Mammedov };
839de05005bSIgor Mammedov 
840de05005bSIgor Mammedov static Property sparc_cpu_properties[] = {
841de05005bSIgor Mammedov     DEFINE_PROP_BIT("float",    SPARCCPU, env.def.features, 0, false),
842de05005bSIgor Mammedov     DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
843de05005bSIgor Mammedov     DEFINE_PROP_BIT("swap",     SPARCCPU, env.def.features, 2, false),
844de05005bSIgor Mammedov     DEFINE_PROP_BIT("mul",      SPARCCPU, env.def.features, 3, false),
845de05005bSIgor Mammedov     DEFINE_PROP_BIT("div",      SPARCCPU, env.def.features, 4, false),
846de05005bSIgor Mammedov     DEFINE_PROP_BIT("flush",    SPARCCPU, env.def.features, 5, false),
847de05005bSIgor Mammedov     DEFINE_PROP_BIT("fsqrt",    SPARCCPU, env.def.features, 6, false),
848de05005bSIgor Mammedov     DEFINE_PROP_BIT("fmul",     SPARCCPU, env.def.features, 7, false),
849de05005bSIgor Mammedov     DEFINE_PROP_BIT("vis1",     SPARCCPU, env.def.features, 8, false),
850de05005bSIgor Mammedov     DEFINE_PROP_BIT("vis2",     SPARCCPU, env.def.features, 9, false),
851de05005bSIgor Mammedov     DEFINE_PROP_BIT("fsmuld",   SPARCCPU, env.def.features, 10, false),
852de05005bSIgor Mammedov     DEFINE_PROP_BIT("hypv",     SPARCCPU, env.def.features, 11, false),
853de05005bSIgor Mammedov     DEFINE_PROP_BIT("cmt",      SPARCCPU, env.def.features, 12, false),
854de05005bSIgor Mammedov     DEFINE_PROP_BIT("gl",       SPARCCPU, env.def.features, 13, false),
855de05005bSIgor Mammedov     DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
856de05005bSIgor Mammedov                          qdev_prop_uint64, target_ulong),
857de05005bSIgor Mammedov     DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
858de05005bSIgor Mammedov     DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
85943b6ab4cSEduardo Habkost     DEFINE_PROP("nwindows", SPARCCPU, env.def.nwindows,
86043b6ab4cSEduardo Habkost                 qdev_prop_nwindows, uint32_t),
861de05005bSIgor Mammedov     DEFINE_PROP_END_OF_LIST()
862de05005bSIgor Mammedov };
863de05005bSIgor Mammedov 
8648b80bd28SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
8658b80bd28SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
8668b80bd28SPhilippe Mathieu-Daudé 
8678b80bd28SPhilippe Mathieu-Daudé static const struct SysemuCPUOps sparc_sysemu_ops = {
86808928c6dSPhilippe Mathieu-Daudé     .get_phys_page_debug = sparc_cpu_get_phys_page_debug,
869feece4d0SPhilippe Mathieu-Daudé     .legacy_vmsd = &vmstate_sparc_cpu,
8708b80bd28SPhilippe Mathieu-Daudé };
8718b80bd28SPhilippe Mathieu-Daudé #endif
8728b80bd28SPhilippe Mathieu-Daudé 
87378271684SClaudio Fontana #ifdef CONFIG_TCG
87478271684SClaudio Fontana #include "hw/core/tcg-cpu-ops.h"
87578271684SClaudio Fontana 
87611906557SRichard Henderson static const struct TCGCPUOps sparc_tcg_ops = {
87778271684SClaudio Fontana     .initialize = sparc_tcg_init,
87878271684SClaudio Fontana     .synchronize_from_tb = sparc_cpu_synchronize_from_tb,
879f36aaa53SRichard Henderson     .restore_state_to_opc = sparc_restore_state_to_opc,
88078271684SClaudio Fontana 
88178271684SClaudio Fontana #ifndef CONFIG_USER_ONLY
882caac44a5SRichard Henderson     .tlb_fill = sparc_cpu_tlb_fill,
883798ac8b5SPhilippe Mathieu-Daudé     .cpu_exec_interrupt = sparc_cpu_exec_interrupt,
88478271684SClaudio Fontana     .do_interrupt = sparc_cpu_do_interrupt,
88578271684SClaudio Fontana     .do_transaction_failed = sparc_cpu_do_transaction_failed,
88678271684SClaudio Fontana     .do_unaligned_access = sparc_cpu_do_unaligned_access,
88778271684SClaudio Fontana #endif /* !CONFIG_USER_ONLY */
88878271684SClaudio Fontana };
88978271684SClaudio Fontana #endif /* CONFIG_TCG */
89078271684SClaudio Fontana 
891ab7ab3d7SAndreas Färber static void sparc_cpu_class_init(ObjectClass *oc, void *data)
892ab7ab3d7SAndreas Färber {
893ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
894ab7ab3d7SAndreas Färber     CPUClass *cc = CPU_CLASS(oc);
895b6e91ebfSAndreas Färber     DeviceClass *dc = DEVICE_CLASS(oc);
8963b4fff1bSPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(oc);
897b6e91ebfSAndreas Färber 
898bf853881SPhilippe Mathieu-Daudé     device_class_set_parent_realize(dc, sparc_cpu_realizefn,
899bf853881SPhilippe Mathieu-Daudé                                     &scc->parent_realize);
9004f67d30bSMarc-André Lureau     device_class_set_props(dc, sparc_cpu_properties);
901ab7ab3d7SAndreas Färber 
9023b4fff1bSPeter Maydell     resettable_class_set_parent_phases(rc, NULL, sparc_cpu_reset_hold, NULL,
9033b4fff1bSPeter Maydell                                        &scc->parent_phases);
90497a8ea5aSAndreas Färber 
90512a6c15eSIgor Mammedov     cc->class_by_name = sparc_cpu_class_by_name;
906d1853231SIgor Mammedov     cc->parse_features = sparc_cpu_parse_features;
9078c2e1b00SAndreas Färber     cc->has_work = sparc_cpu_has_work;
908878096eeSAndreas Färber     cc->dump_state = sparc_cpu_dump_state;
909f3659eeeSAndreas Färber #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
910f3659eeeSAndreas Färber     cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
911f3659eeeSAndreas Färber #endif
912f45748f1SAndreas Färber     cc->set_pc = sparc_cpu_set_pc;
913e4fdf9dfSRichard Henderson     cc->get_pc = sparc_cpu_get_pc;
9145b50e790SAndreas Färber     cc->gdb_read_register = sparc_cpu_gdb_read_register;
9155b50e790SAndreas Färber     cc->gdb_write_register = sparc_cpu_gdb_write_register;
916e84942f2SRichard Henderson #ifndef CONFIG_USER_ONLY
9178b80bd28SPhilippe Mathieu-Daudé     cc->sysemu_ops = &sparc_sysemu_ops;
91800b941e5SAndreas Färber #endif
919df0900ebSPeter Crosthwaite     cc->disas_set_info = cpu_sparc_disas_set_info;
920a0e372f0SAndreas Färber 
921a0e372f0SAndreas Färber #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
922a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 86;
923a0e372f0SAndreas Färber #else
924a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 72;
925a0e372f0SAndreas Färber #endif
92678271684SClaudio Fontana     cc->tcg_ops = &sparc_tcg_ops;
927ab7ab3d7SAndreas Färber }
928ab7ab3d7SAndreas Färber 
929ab7ab3d7SAndreas Färber static const TypeInfo sparc_cpu_type_info = {
930ab7ab3d7SAndreas Färber     .name = TYPE_SPARC_CPU,
931ab7ab3d7SAndreas Färber     .parent = TYPE_CPU,
932ab7ab3d7SAndreas Färber     .instance_size = sizeof(SPARCCPU),
933ab7ab3d7SAndreas Färber     .instance_init = sparc_cpu_initfn,
93412a6c15eSIgor Mammedov     .abstract = true,
935ab7ab3d7SAndreas Färber     .class_size = sizeof(SPARCCPUClass),
936ab7ab3d7SAndreas Färber     .class_init = sparc_cpu_class_init,
937ab7ab3d7SAndreas Färber };
938ab7ab3d7SAndreas Färber 
93912a6c15eSIgor Mammedov static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
94012a6c15eSIgor Mammedov {
94112a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
94212a6c15eSIgor Mammedov     scc->cpu_def = data;
94312a6c15eSIgor Mammedov }
94412a6c15eSIgor Mammedov 
94512a6c15eSIgor Mammedov static void sparc_register_cpudef_type(const struct sparc_def_t *def)
94612a6c15eSIgor Mammedov {
94712a6c15eSIgor Mammedov     char *typename = sparc_cpu_type_name(def->name);
94812a6c15eSIgor Mammedov     TypeInfo ti = {
94912a6c15eSIgor Mammedov         .name = typename,
95012a6c15eSIgor Mammedov         .parent = TYPE_SPARC_CPU,
95112a6c15eSIgor Mammedov         .class_init = sparc_cpu_cpudef_class_init,
95212a6c15eSIgor Mammedov         .class_data = (void *)def,
95312a6c15eSIgor Mammedov     };
95412a6c15eSIgor Mammedov 
95512a6c15eSIgor Mammedov     type_register(&ti);
95612a6c15eSIgor Mammedov     g_free(typename);
95712a6c15eSIgor Mammedov }
95812a6c15eSIgor Mammedov 
959ab7ab3d7SAndreas Färber static void sparc_cpu_register_types(void)
960ab7ab3d7SAndreas Färber {
96112a6c15eSIgor Mammedov     int i;
96212a6c15eSIgor Mammedov 
963ab7ab3d7SAndreas Färber     type_register_static(&sparc_cpu_type_info);
96412a6c15eSIgor Mammedov     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
96512a6c15eSIgor Mammedov         sparc_register_cpudef_type(&sparc_defs[i]);
96612a6c15eSIgor Mammedov     }
967ab7ab3d7SAndreas Färber }
968ab7ab3d7SAndreas Färber 
969ab7ab3d7SAndreas Färber type_init(sparc_cpu_register_types)
970