xref: /qemu/target/sparc/cpu.c (revision 12a6c15ef31c98ecefa63e91ac36955383038384)
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"
23db5d39f7SAndreas Färber #include "qemu/error-report.h"
2463c91552SPaolo Bonzini #include "exec/exec-all.h"
25ab3b491fSBlue Swirl 
26ab3b491fSBlue Swirl //#define DEBUG_FEATURES
27ab3b491fSBlue Swirl 
28ab7ab3d7SAndreas Färber /* CPUClass::reset() */
29ab7ab3d7SAndreas Färber static void sparc_cpu_reset(CPUState *s)
30ab7ab3d7SAndreas Färber {
31ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(s);
32ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
33ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
34ab7ab3d7SAndreas Färber 
35ab7ab3d7SAndreas Färber     scc->parent_reset(s);
36ab7ab3d7SAndreas Färber 
371f5c00cfSAlex Bennée     memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
38ab3b491fSBlue Swirl     env->cwp = 0;
39ab3b491fSBlue Swirl #ifndef TARGET_SPARC64
40ab3b491fSBlue Swirl     env->wim = 1;
41ab3b491fSBlue Swirl #endif
42ab3b491fSBlue Swirl     env->regwptr = env->regbase + (env->cwp * 16);
43ab3b491fSBlue Swirl     CC_OP = CC_OP_FLAGS;
44ab3b491fSBlue Swirl #if defined(CONFIG_USER_ONLY)
45ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
46ab3b491fSBlue Swirl     env->cleanwin = env->nwindows - 2;
47ab3b491fSBlue Swirl     env->cansave = env->nwindows - 2;
48ab3b491fSBlue Swirl     env->pstate = PS_RMO | PS_PEF | PS_IE;
49ab3b491fSBlue Swirl     env->asi = 0x82; /* Primary no-fault */
50ab3b491fSBlue Swirl #endif
51ab3b491fSBlue Swirl #else
52ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
53ab3b491fSBlue Swirl     env->psret = 0;
54ab3b491fSBlue Swirl     env->psrs = 1;
55ab3b491fSBlue Swirl     env->psrps = 1;
56ab3b491fSBlue Swirl #endif
57ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
58cbc3a6a4SArtyom Tarasenko     env->pstate = PS_PRIV | PS_RED | PS_PEF;
59cbc3a6a4SArtyom Tarasenko     if (!cpu_has_hypervisor(env)) {
60cbc3a6a4SArtyom Tarasenko         env->pstate |= PS_AG;
61cbc3a6a4SArtyom Tarasenko     }
62ab3b491fSBlue Swirl     env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
63ab3b491fSBlue Swirl     env->tl = env->maxtl;
64cbc3a6a4SArtyom Tarasenko     env->gl = 2;
65ab3b491fSBlue Swirl     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
66ab3b491fSBlue Swirl     env->lsu = 0;
67ab3b491fSBlue Swirl #else
68ab3b491fSBlue Swirl     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
69ab3b491fSBlue Swirl     env->mmuregs[0] |= env->def->mmu_bm;
70ab3b491fSBlue Swirl #endif
71ab3b491fSBlue Swirl     env->pc = 0;
72ab3b491fSBlue Swirl     env->npc = env->pc + 4;
73ab3b491fSBlue Swirl #endif
74ab3b491fSBlue Swirl     env->cache_control = 0;
75ab3b491fSBlue Swirl }
76ab3b491fSBlue Swirl 
7787afe467SRichard Henderson static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
7887afe467SRichard Henderson {
7987afe467SRichard Henderson     if (interrupt_request & CPU_INTERRUPT_HARD) {
8087afe467SRichard Henderson         SPARCCPU *cpu = SPARC_CPU(cs);
8187afe467SRichard Henderson         CPUSPARCState *env = &cpu->env;
8287afe467SRichard Henderson 
8387afe467SRichard Henderson         if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
8487afe467SRichard Henderson             int pil = env->interrupt_index & 0xf;
8587afe467SRichard Henderson             int type = env->interrupt_index & 0xf0;
8687afe467SRichard Henderson 
8787afe467SRichard Henderson             if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
8887afe467SRichard Henderson                 cs->exception_index = env->interrupt_index;
8987afe467SRichard Henderson                 sparc_cpu_do_interrupt(cs);
9087afe467SRichard Henderson                 return true;
9187afe467SRichard Henderson             }
9287afe467SRichard Henderson         }
9387afe467SRichard Henderson     }
9487afe467SRichard Henderson     return false;
9587afe467SRichard Henderson }
9687afe467SRichard Henderson 
97df0900ebSPeter Crosthwaite static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
98df0900ebSPeter Crosthwaite {
99df0900ebSPeter Crosthwaite     info->print_insn = print_insn_sparc;
100df0900ebSPeter Crosthwaite #ifdef TARGET_SPARC64
101df0900ebSPeter Crosthwaite     info->mach = bfd_mach_sparc_v9b;
102df0900ebSPeter Crosthwaite #endif
103df0900ebSPeter Crosthwaite }
104df0900ebSPeter Crosthwaite 
105fb02d56eSIgor Mammedov static void sparc_cpu_parse_features(CPUState *cs, char *features,
106fb02d56eSIgor Mammedov                                      Error **errp);
107fb02d56eSIgor Mammedov 
108433ac7a9SAndreas Färber static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
109ab3b491fSBlue Swirl {
110433ac7a9SAndreas Färber     CPUSPARCState *env = &cpu->env;
111433ac7a9SAndreas Färber     char *s = g_strdup(cpu_model);
112*12a6c15eSIgor Mammedov     char *featurestr = strtok(s, ",");
113433ac7a9SAndreas Färber     Error *err = NULL;
114ab3b491fSBlue Swirl 
115433ac7a9SAndreas Färber     featurestr = strtok(NULL, ",");
116fb02d56eSIgor Mammedov     sparc_cpu_parse_features(CPU(cpu), featurestr, &err);
117433ac7a9SAndreas Färber     g_free(s);
118433ac7a9SAndreas Färber     if (err) {
119565f65d2SMarkus Armbruster         error_report_err(err);
120433ac7a9SAndreas Färber         return -1;
121433ac7a9SAndreas Färber     }
122433ac7a9SAndreas Färber 
123*12a6c15eSIgor Mammedov     env->version = env->def->iu_version;
124*12a6c15eSIgor Mammedov     env->fsr = env->def->fpu_version;
125*12a6c15eSIgor Mammedov     env->nwindows = env->def->nwindows;
126ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
127*12a6c15eSIgor Mammedov     env->mmuregs[0] |= env->def->mmu_version;
128ab3b491fSBlue Swirl     cpu_sparc_set_id(env, 0);
129*12a6c15eSIgor Mammedov     env->mxccregs[7] |= env->def->mxcc_version;
130ab3b491fSBlue Swirl #else
131*12a6c15eSIgor Mammedov     env->mmu_version = env->def->mmu_version;
132*12a6c15eSIgor Mammedov     env->maxtl = env->def->maxtl;
133*12a6c15eSIgor Mammedov     env->version |= env->def->maxtl << 8;
134*12a6c15eSIgor Mammedov     env->version |= env->def->nwindows - 1;
135ab3b491fSBlue Swirl #endif
136ab3b491fSBlue Swirl     return 0;
137ab3b491fSBlue Swirl }
138ab3b491fSBlue Swirl 
139e59be77aSAndreas Färber SPARCCPU *cpu_sparc_init(const char *cpu_model)
140ab3b491fSBlue Swirl {
141ab7ab3d7SAndreas Färber     SPARCCPU *cpu;
142*12a6c15eSIgor Mammedov     ObjectClass *oc;
143*12a6c15eSIgor Mammedov     char *str, *name;
144ab3b491fSBlue Swirl 
145*12a6c15eSIgor Mammedov     str = g_strdup(cpu_model);
146*12a6c15eSIgor Mammedov     name = strtok(str, ",");
147*12a6c15eSIgor Mammedov     oc = cpu_class_by_name(TYPE_SPARC_CPU, name);
148*12a6c15eSIgor Mammedov     g_free(str);
149*12a6c15eSIgor Mammedov     if (oc == NULL) {
150*12a6c15eSIgor Mammedov         return NULL;
151*12a6c15eSIgor Mammedov     }
152*12a6c15eSIgor Mammedov 
153*12a6c15eSIgor Mammedov     cpu = SPARC_CPU(object_new(object_class_get_name(oc)));
154ab3b491fSBlue Swirl 
155433ac7a9SAndreas Färber     if (cpu_sparc_register(cpu, cpu_model) < 0) {
1565c099537SPaolo Bonzini         object_unref(OBJECT(cpu));
157ab3b491fSBlue Swirl         return NULL;
158ab3b491fSBlue Swirl     }
159b6e91ebfSAndreas Färber 
160b6e91ebfSAndreas Färber     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
161ab3b491fSBlue Swirl 
162e59be77aSAndreas Färber     return cpu;
163ab3b491fSBlue Swirl }
164ab3b491fSBlue Swirl 
165ab3b491fSBlue Swirl void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
166ab3b491fSBlue Swirl {
167ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
168ab3b491fSBlue Swirl     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
169ab3b491fSBlue Swirl #endif
170ab3b491fSBlue Swirl }
171ab3b491fSBlue Swirl 
172ab3b491fSBlue Swirl static const sparc_def_t sparc_defs[] = {
173ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
174ab3b491fSBlue Swirl     {
175ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64",
176ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
177ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
178ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
179ab3b491fSBlue Swirl         .nwindows = 4,
180ab3b491fSBlue Swirl         .maxtl = 4,
181ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
182ab3b491fSBlue Swirl     },
183ab3b491fSBlue Swirl     {
184ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 III",
185ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
186ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
187ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
188ab3b491fSBlue Swirl         .nwindows = 5,
189ab3b491fSBlue Swirl         .maxtl = 4,
190ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
191ab3b491fSBlue Swirl     },
192ab3b491fSBlue Swirl     {
193ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 IV",
194ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
195ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
196ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
197ab3b491fSBlue Swirl         .nwindows = 8,
198ab3b491fSBlue Swirl         .maxtl = 5,
199ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
200ab3b491fSBlue Swirl     },
201ab3b491fSBlue Swirl     {
202ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 V",
203ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
204ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
205ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
206ab3b491fSBlue Swirl         .nwindows = 8,
207ab3b491fSBlue Swirl         .maxtl = 5,
208ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
209ab3b491fSBlue Swirl     },
210ab3b491fSBlue Swirl     {
211ab3b491fSBlue Swirl         .name = "TI UltraSparc I",
212ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
213ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
214ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
215ab3b491fSBlue Swirl         .nwindows = 8,
216ab3b491fSBlue Swirl         .maxtl = 5,
217ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
218ab3b491fSBlue Swirl     },
219ab3b491fSBlue Swirl     {
220ab3b491fSBlue Swirl         .name = "TI UltraSparc II",
221ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
222ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
223ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
224ab3b491fSBlue Swirl         .nwindows = 8,
225ab3b491fSBlue Swirl         .maxtl = 5,
226ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
227ab3b491fSBlue Swirl     },
228ab3b491fSBlue Swirl     {
229ab3b491fSBlue Swirl         .name = "TI UltraSparc IIi",
230ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
231ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
232ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
233ab3b491fSBlue Swirl         .nwindows = 8,
234ab3b491fSBlue Swirl         .maxtl = 5,
235ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
236ab3b491fSBlue Swirl     },
237ab3b491fSBlue Swirl     {
238ab3b491fSBlue Swirl         .name = "TI UltraSparc IIe",
239ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
240ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
241ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
242ab3b491fSBlue Swirl         .nwindows = 8,
243ab3b491fSBlue Swirl         .maxtl = 5,
244ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
245ab3b491fSBlue Swirl     },
246ab3b491fSBlue Swirl     {
247ab3b491fSBlue Swirl         .name = "Sun UltraSparc III",
248ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
249ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
250ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
251ab3b491fSBlue Swirl         .nwindows = 8,
252ab3b491fSBlue Swirl         .maxtl = 5,
253ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
254ab3b491fSBlue Swirl     },
255ab3b491fSBlue Swirl     {
256ab3b491fSBlue Swirl         .name = "Sun UltraSparc III Cu",
257ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
258ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
259ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
260ab3b491fSBlue Swirl         .nwindows = 8,
261ab3b491fSBlue Swirl         .maxtl = 5,
262ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
263ab3b491fSBlue Swirl     },
264ab3b491fSBlue Swirl     {
265ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi",
266ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
267ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
268ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
269ab3b491fSBlue Swirl         .nwindows = 8,
270ab3b491fSBlue Swirl         .maxtl = 5,
271ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
272ab3b491fSBlue Swirl     },
273ab3b491fSBlue Swirl     {
274ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV",
275ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
276ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
277ab3b491fSBlue Swirl         .mmu_version = mmu_us_4,
278ab3b491fSBlue Swirl         .nwindows = 8,
279ab3b491fSBlue Swirl         .maxtl = 5,
280ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
281ab3b491fSBlue Swirl     },
282ab3b491fSBlue Swirl     {
283ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV+",
284ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
285ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
286ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
287ab3b491fSBlue Swirl         .nwindows = 8,
288ab3b491fSBlue Swirl         .maxtl = 5,
289ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
290ab3b491fSBlue Swirl     },
291ab3b491fSBlue Swirl     {
292ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi+",
293ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
294ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
295ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
296ab3b491fSBlue Swirl         .nwindows = 8,
297ab3b491fSBlue Swirl         .maxtl = 5,
298ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
299ab3b491fSBlue Swirl     },
300ab3b491fSBlue Swirl     {
301ab3b491fSBlue Swirl         .name = "Sun UltraSparc T1",
302ab3b491fSBlue Swirl         /* defined in sparc_ifu_fdp.v and ctu.h */
303ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
304ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
305ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
306ab3b491fSBlue Swirl         .nwindows = 8,
307ab3b491fSBlue Swirl         .maxtl = 6,
308ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
309ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
310ab3b491fSBlue Swirl     },
311ab3b491fSBlue Swirl     {
312ab3b491fSBlue Swirl         .name = "Sun UltraSparc T2",
313ab3b491fSBlue Swirl         /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
314ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
315ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
316ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
317ab3b491fSBlue Swirl         .nwindows = 8,
318ab3b491fSBlue Swirl         .maxtl = 6,
319ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
320ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
321ab3b491fSBlue Swirl     },
322ab3b491fSBlue Swirl     {
323ab3b491fSBlue Swirl         .name = "NEC UltraSparc I",
324ab3b491fSBlue Swirl         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
325ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
326ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
327ab3b491fSBlue Swirl         .nwindows = 8,
328ab3b491fSBlue Swirl         .maxtl = 5,
329ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
330ab3b491fSBlue Swirl     },
331ab3b491fSBlue Swirl #else
332ab3b491fSBlue Swirl     {
333ab3b491fSBlue Swirl         .name = "Fujitsu MB86904",
334ab3b491fSBlue Swirl         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
335ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
336ab3b491fSBlue Swirl         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
337ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
338ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
339ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
340ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
341ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
342ab3b491fSBlue Swirl         .nwindows = 8,
343ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
344ab3b491fSBlue Swirl     },
345ab3b491fSBlue Swirl     {
346ab3b491fSBlue Swirl         .name = "Fujitsu MB86907",
347ab3b491fSBlue Swirl         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
348ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
349ab3b491fSBlue Swirl         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
350ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
351ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
352ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
353ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
354ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
355ab3b491fSBlue Swirl         .nwindows = 8,
356ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
357ab3b491fSBlue Swirl     },
358ab3b491fSBlue Swirl     {
359ab3b491fSBlue Swirl         .name = "TI MicroSparc I",
360ab3b491fSBlue Swirl         .iu_version = 0x41000000,
361ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
362ab3b491fSBlue Swirl         .mmu_version = 0x41000000,
363ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
364ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
365ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
366ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
367ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x0000003f,
368ab3b491fSBlue Swirl         .nwindows = 7,
369ab3b491fSBlue Swirl         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
370ab3b491fSBlue Swirl         CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
371ab3b491fSBlue Swirl         CPU_FEATURE_FMUL,
372ab3b491fSBlue Swirl     },
373ab3b491fSBlue Swirl     {
374ab3b491fSBlue Swirl         .name = "TI MicroSparc II",
375ab3b491fSBlue Swirl         .iu_version = 0x42000000,
376ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
377ab3b491fSBlue Swirl         .mmu_version = 0x02000000,
378ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
379ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
380ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
381ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
382ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
383ab3b491fSBlue Swirl         .nwindows = 8,
384ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
385ab3b491fSBlue Swirl     },
386ab3b491fSBlue Swirl     {
387ab3b491fSBlue Swirl         .name = "TI MicroSparc IIep",
388ab3b491fSBlue Swirl         .iu_version = 0x42000000,
389ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
390ab3b491fSBlue Swirl         .mmu_version = 0x04000000,
391ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
392ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
393ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
394ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016bff,
395ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
396ab3b491fSBlue Swirl         .nwindows = 8,
397ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
398ab3b491fSBlue Swirl     },
399ab3b491fSBlue Swirl     {
400ab3b491fSBlue Swirl         .name = "TI SuperSparc 40", /* STP1020NPGA */
401ab3b491fSBlue Swirl         .iu_version = 0x41000000, /* SuperSPARC 2.x */
402ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
403ab3b491fSBlue Swirl         .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
404ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
405ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
406ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
407ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
408ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
409ab3b491fSBlue Swirl         .nwindows = 8,
410ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
411ab3b491fSBlue Swirl     },
412ab3b491fSBlue Swirl     {
413ab3b491fSBlue Swirl         .name = "TI SuperSparc 50", /* STP1020PGA */
414ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
415ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
416ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
417ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
418ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
419ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
420ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
421ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
422ab3b491fSBlue Swirl         .nwindows = 8,
423ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
424ab3b491fSBlue Swirl     },
425ab3b491fSBlue Swirl     {
426ab3b491fSBlue Swirl         .name = "TI SuperSparc 51",
427ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
428ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
429ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
430ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
431ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
432ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
433ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
434ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
435ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
436ab3b491fSBlue Swirl         .nwindows = 8,
437ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
438ab3b491fSBlue Swirl     },
439ab3b491fSBlue Swirl     {
440ab3b491fSBlue Swirl         .name = "TI SuperSparc 60", /* STP1020APGA */
441ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
442ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
443ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
444ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
445ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
446ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
447ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
448ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
449ab3b491fSBlue Swirl         .nwindows = 8,
450ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
451ab3b491fSBlue Swirl     },
452ab3b491fSBlue Swirl     {
453ab3b491fSBlue Swirl         .name = "TI SuperSparc 61",
454ab3b491fSBlue Swirl         .iu_version = 0x44000000, /* SuperSPARC 3.x */
455ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
456ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
457ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
458ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
459ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
460ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
461ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
462ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
463ab3b491fSBlue Swirl         .nwindows = 8,
464ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
465ab3b491fSBlue Swirl     },
466ab3b491fSBlue Swirl     {
467ab3b491fSBlue Swirl         .name = "TI SuperSparc II",
468ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC II 1.x */
469ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
470ab3b491fSBlue Swirl         .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
471ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
472ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
473ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
474ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
475ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
476ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
477ab3b491fSBlue Swirl         .nwindows = 8,
478ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
479ab3b491fSBlue Swirl     },
480ab3b491fSBlue Swirl     {
481ab3b491fSBlue Swirl         .name = "LEON2",
482ab3b491fSBlue Swirl         .iu_version = 0xf2000000,
483ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
484ab3b491fSBlue Swirl         .mmu_version = 0xf2000000,
485ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
486ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
487ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
488ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
489ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
490ab3b491fSBlue Swirl         .nwindows = 8,
491ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
492ab3b491fSBlue Swirl     },
493ab3b491fSBlue Swirl     {
494ab3b491fSBlue Swirl         .name = "LEON3",
495ab3b491fSBlue Swirl         .iu_version = 0xf3000000,
496ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
497ab3b491fSBlue Swirl         .mmu_version = 0xf3000000,
498ab3b491fSBlue Swirl         .mmu_bm = 0x00000000,
4997a0a9c2cSRonald Hecht         .mmu_ctpr_mask = 0xfffffffc,
5007a0a9c2cSRonald Hecht         .mmu_cxr_mask = 0x000000ff,
501ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
502ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
503ab3b491fSBlue Swirl         .nwindows = 8,
504ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
50516c358e9SSebastian Huber         CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
50616c358e9SSebastian Huber         CPU_FEATURE_CASA,
507ab3b491fSBlue Swirl     },
508ab3b491fSBlue Swirl #endif
509ab3b491fSBlue Swirl };
510ab3b491fSBlue Swirl 
511ab3b491fSBlue Swirl static const char * const feature_name[] = {
512ab3b491fSBlue Swirl     "float",
513ab3b491fSBlue Swirl     "float128",
514ab3b491fSBlue Swirl     "swap",
515ab3b491fSBlue Swirl     "mul",
516ab3b491fSBlue Swirl     "div",
517ab3b491fSBlue Swirl     "flush",
518ab3b491fSBlue Swirl     "fsqrt",
519ab3b491fSBlue Swirl     "fmul",
520ab3b491fSBlue Swirl     "vis1",
521ab3b491fSBlue Swirl     "vis2",
522ab3b491fSBlue Swirl     "fsmuld",
523ab3b491fSBlue Swirl     "hypv",
524ab3b491fSBlue Swirl     "cmt",
525ab3b491fSBlue Swirl     "gl",
526ab3b491fSBlue Swirl };
527ab3b491fSBlue Swirl 
528ab3b491fSBlue Swirl static void print_features(FILE *f, fprintf_function cpu_fprintf,
529ab3b491fSBlue Swirl                            uint32_t features, const char *prefix)
530ab3b491fSBlue Swirl {
531ab3b491fSBlue Swirl     unsigned int i;
532ab3b491fSBlue Swirl 
533ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
534ab3b491fSBlue Swirl         if (feature_name[i] && (features & (1 << i))) {
535ab3b491fSBlue Swirl             if (prefix) {
536ab3b491fSBlue Swirl                 (*cpu_fprintf)(f, "%s", prefix);
537ab3b491fSBlue Swirl             }
538ab3b491fSBlue Swirl             (*cpu_fprintf)(f, "%s ", feature_name[i]);
539ab3b491fSBlue Swirl         }
540ab3b491fSBlue Swirl     }
541ab3b491fSBlue Swirl }
542ab3b491fSBlue Swirl 
543ab3b491fSBlue Swirl static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
544ab3b491fSBlue Swirl {
545ab3b491fSBlue Swirl     unsigned int i;
546ab3b491fSBlue Swirl 
547ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
548ab3b491fSBlue Swirl         if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
549ab3b491fSBlue Swirl             *features |= 1 << i;
550ab3b491fSBlue Swirl             return;
551ab3b491fSBlue Swirl         }
552ab3b491fSBlue Swirl     }
553db5d39f7SAndreas Färber     error_report("CPU feature %s not found", flagname);
554ab3b491fSBlue Swirl }
555ab3b491fSBlue Swirl 
556433ac7a9SAndreas Färber static void sparc_cpu_parse_features(CPUState *cs, char *features,
557433ac7a9SAndreas Färber                                      Error **errp)
558433ac7a9SAndreas Färber {
559433ac7a9SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
560433ac7a9SAndreas Färber     sparc_def_t *cpu_def = cpu->env.def;
561433ac7a9SAndreas Färber     char *featurestr;
562433ac7a9SAndreas Färber     uint32_t plus_features = 0;
563433ac7a9SAndreas Färber     uint32_t minus_features = 0;
564433ac7a9SAndreas Färber     uint64_t iu_version;
565433ac7a9SAndreas Färber     uint32_t fpu_version, mmu_version, nwindows;
566433ac7a9SAndreas Färber 
567433ac7a9SAndreas Färber     featurestr = features ? strtok(features, ",") : NULL;
568ab3b491fSBlue Swirl     while (featurestr) {
569ab3b491fSBlue Swirl         char *val;
570ab3b491fSBlue Swirl 
571ab3b491fSBlue Swirl         if (featurestr[0] == '+') {
572ab3b491fSBlue Swirl             add_flagname_to_bitmaps(featurestr + 1, &plus_features);
573ab3b491fSBlue Swirl         } else if (featurestr[0] == '-') {
574ab3b491fSBlue Swirl             add_flagname_to_bitmaps(featurestr + 1, &minus_features);
575ab3b491fSBlue Swirl         } else if ((val = strchr(featurestr, '='))) {
576ab3b491fSBlue Swirl             *val = 0; val++;
577ab3b491fSBlue Swirl             if (!strcmp(featurestr, "iu_version")) {
578ab3b491fSBlue Swirl                 char *err;
579ab3b491fSBlue Swirl 
580ab3b491fSBlue Swirl                 iu_version = strtoll(val, &err, 0);
581ab3b491fSBlue Swirl                 if (!*val || *err) {
582433ac7a9SAndreas Färber                     error_setg(errp, "bad numerical value %s", val);
583433ac7a9SAndreas Färber                     return;
584ab3b491fSBlue Swirl                 }
585ab3b491fSBlue Swirl                 cpu_def->iu_version = iu_version;
586ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
587ab3b491fSBlue Swirl                 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
588ab3b491fSBlue Swirl #endif
589ab3b491fSBlue Swirl             } else if (!strcmp(featurestr, "fpu_version")) {
590ab3b491fSBlue Swirl                 char *err;
591ab3b491fSBlue Swirl 
592ab3b491fSBlue Swirl                 fpu_version = strtol(val, &err, 0);
593ab3b491fSBlue Swirl                 if (!*val || *err) {
594433ac7a9SAndreas Färber                     error_setg(errp, "bad numerical value %s", val);
595433ac7a9SAndreas Färber                     return;
596ab3b491fSBlue Swirl                 }
597ab3b491fSBlue Swirl                 cpu_def->fpu_version = fpu_version;
598ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
599ab3b491fSBlue Swirl                 fprintf(stderr, "fpu_version %x\n", fpu_version);
600ab3b491fSBlue Swirl #endif
601ab3b491fSBlue Swirl             } else if (!strcmp(featurestr, "mmu_version")) {
602ab3b491fSBlue Swirl                 char *err;
603ab3b491fSBlue Swirl 
604ab3b491fSBlue Swirl                 mmu_version = strtol(val, &err, 0);
605ab3b491fSBlue Swirl                 if (!*val || *err) {
606433ac7a9SAndreas Färber                     error_setg(errp, "bad numerical value %s", val);
607433ac7a9SAndreas Färber                     return;
608ab3b491fSBlue Swirl                 }
609ab3b491fSBlue Swirl                 cpu_def->mmu_version = mmu_version;
610ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
611ab3b491fSBlue Swirl                 fprintf(stderr, "mmu_version %x\n", mmu_version);
612ab3b491fSBlue Swirl #endif
613ab3b491fSBlue Swirl             } else if (!strcmp(featurestr, "nwindows")) {
614ab3b491fSBlue Swirl                 char *err;
615ab3b491fSBlue Swirl 
616ab3b491fSBlue Swirl                 nwindows = strtol(val, &err, 0);
617ab3b491fSBlue Swirl                 if (!*val || *err || nwindows > MAX_NWINDOWS ||
618ab3b491fSBlue Swirl                     nwindows < MIN_NWINDOWS) {
619433ac7a9SAndreas Färber                     error_setg(errp, "bad numerical value %s", val);
620433ac7a9SAndreas Färber                     return;
621ab3b491fSBlue Swirl                 }
622ab3b491fSBlue Swirl                 cpu_def->nwindows = nwindows;
623ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
624ab3b491fSBlue Swirl                 fprintf(stderr, "nwindows %d\n", nwindows);
625ab3b491fSBlue Swirl #endif
626ab3b491fSBlue Swirl             } else {
627433ac7a9SAndreas Färber                 error_setg(errp, "unrecognized feature %s", featurestr);
628433ac7a9SAndreas Färber                 return;
629ab3b491fSBlue Swirl             }
630ab3b491fSBlue Swirl         } else {
631433ac7a9SAndreas Färber             error_setg(errp, "feature string `%s' not in format "
632db5d39f7SAndreas Färber                              "(+feature|-feature|feature=xyz)", featurestr);
633433ac7a9SAndreas Färber             return;
634ab3b491fSBlue Swirl         }
635ab3b491fSBlue Swirl         featurestr = strtok(NULL, ",");
636ab3b491fSBlue Swirl     }
637ab3b491fSBlue Swirl     cpu_def->features |= plus_features;
638ab3b491fSBlue Swirl     cpu_def->features &= ~minus_features;
639ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
640ab3b491fSBlue Swirl     print_features(stderr, fprintf, cpu_def->features, NULL);
641ab3b491fSBlue Swirl #endif
642ab3b491fSBlue Swirl }
643ab3b491fSBlue Swirl 
644ab3b491fSBlue Swirl void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
645ab3b491fSBlue Swirl {
646ab3b491fSBlue Swirl     unsigned int i;
647ab3b491fSBlue Swirl 
648ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
649ab3b491fSBlue Swirl         (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
650ab3b491fSBlue Swirl                        " FPU %08x MMU %08x NWINS %d ",
651ab3b491fSBlue Swirl                        sparc_defs[i].name,
652ab3b491fSBlue Swirl                        sparc_defs[i].iu_version,
653ab3b491fSBlue Swirl                        sparc_defs[i].fpu_version,
654ab3b491fSBlue Swirl                        sparc_defs[i].mmu_version,
655ab3b491fSBlue Swirl                        sparc_defs[i].nwindows);
656ab3b491fSBlue Swirl         print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
657ab3b491fSBlue Swirl                        ~sparc_defs[i].features, "-");
658ab3b491fSBlue Swirl         print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
659ab3b491fSBlue Swirl                        sparc_defs[i].features, "+");
660ab3b491fSBlue Swirl         (*cpu_fprintf)(f, "\n");
661ab3b491fSBlue Swirl     }
662ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
663ab3b491fSBlue Swirl     print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
664ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "\n");
665ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
666ab3b491fSBlue Swirl     print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
667ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "\n");
668ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
669ab3b491fSBlue Swirl                    "fpu_version mmu_version nwindows\n");
670ab3b491fSBlue Swirl }
671ab3b491fSBlue Swirl 
672ab3b491fSBlue Swirl static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
673ab3b491fSBlue Swirl                          uint32_t cc)
674ab3b491fSBlue Swirl {
675ab3b491fSBlue Swirl     cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
676ab3b491fSBlue Swirl                 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
677ab3b491fSBlue Swirl                 cc & PSR_CARRY ? 'C' : '-');
678ab3b491fSBlue Swirl }
679ab3b491fSBlue Swirl 
680ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
681ab3b491fSBlue Swirl #define REGS_PER_LINE 4
682ab3b491fSBlue Swirl #else
683ab3b491fSBlue Swirl #define REGS_PER_LINE 8
684ab3b491fSBlue Swirl #endif
685ab3b491fSBlue Swirl 
686878096eeSAndreas Färber void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
687ab3b491fSBlue Swirl                           int flags)
688ab3b491fSBlue Swirl {
689878096eeSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
690878096eeSAndreas Färber     CPUSPARCState *env = &cpu->env;
691ab3b491fSBlue Swirl     int i, x;
692ab3b491fSBlue Swirl 
693ab3b491fSBlue Swirl     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
694ab3b491fSBlue Swirl                 env->npc);
695ab3b491fSBlue Swirl 
696ab3b491fSBlue Swirl     for (i = 0; i < 8; i++) {
697ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == 0) {
698ab3b491fSBlue Swirl             cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
699ab3b491fSBlue Swirl         }
700ab3b491fSBlue Swirl         cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
701ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
702ab3b491fSBlue Swirl             cpu_fprintf(f, "\n");
703ab3b491fSBlue Swirl         }
704ab3b491fSBlue Swirl     }
705ab3b491fSBlue Swirl     for (x = 0; x < 3; x++) {
706ab3b491fSBlue Swirl         for (i = 0; i < 8; i++) {
707ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == 0) {
708ab3b491fSBlue Swirl                 cpu_fprintf(f, "%%%c%d-%d: ",
709ab3b491fSBlue Swirl                             x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
710ab3b491fSBlue Swirl                             i, i + REGS_PER_LINE - 1);
711ab3b491fSBlue Swirl             }
712ab3b491fSBlue Swirl             cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
713ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
714ab3b491fSBlue Swirl                 cpu_fprintf(f, "\n");
715ab3b491fSBlue Swirl             }
716ab3b491fSBlue Swirl         }
717ab3b491fSBlue Swirl     }
71876a23ca0SRichard Henderson 
71930038fd8SRichard Henderson     for (i = 0; i < TARGET_DPREGS; i++) {
720ab3b491fSBlue Swirl         if ((i & 3) == 0) {
72130038fd8SRichard Henderson             cpu_fprintf(f, "%%f%02d: ", i * 2);
722ab3b491fSBlue Swirl         }
72330038fd8SRichard Henderson         cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
724ab3b491fSBlue Swirl         if ((i & 3) == 3) {
725ab3b491fSBlue Swirl             cpu_fprintf(f, "\n");
726ab3b491fSBlue Swirl         }
727ab3b491fSBlue Swirl     }
728ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
729ab3b491fSBlue Swirl     cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
730ab3b491fSBlue Swirl                 (unsigned)cpu_get_ccr(env));
731ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
732ab3b491fSBlue Swirl     cpu_fprintf(f, " xcc: ");
733ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
734cbc3a6a4SArtyom Tarasenko     cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
735cbc3a6a4SArtyom Tarasenko                 env->psrpil, env->gl);
736cbc3a6a4SArtyom Tarasenko     cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
737cbc3a6a4SArtyom Tarasenko                 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
738ab3b491fSBlue Swirl     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
739ab3b491fSBlue Swirl                 "cleanwin: %d cwp: %d\n",
740ab3b491fSBlue Swirl                 env->cansave, env->canrestore, env->otherwin, env->wstate,
741ab3b491fSBlue Swirl                 env->cleanwin, env->nwindows - 1 - env->cwp);
742ab3b491fSBlue Swirl     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
743ab3b491fSBlue Swirl                 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
744cbc3a6a4SArtyom Tarasenko 
745ab3b491fSBlue Swirl #else
746ab3b491fSBlue Swirl     cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
747ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
748ab3b491fSBlue Swirl     cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
749ab3b491fSBlue Swirl                 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
750ab3b491fSBlue Swirl                 env->wim);
751ab3b491fSBlue Swirl     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
752ab3b491fSBlue Swirl                 env->fsr, env->y);
753ab3b491fSBlue Swirl #endif
75476a23ca0SRichard Henderson     cpu_fprintf(f, "\n");
755ab3b491fSBlue Swirl }
756ab7ab3d7SAndreas Färber 
757f45748f1SAndreas Färber static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
758f45748f1SAndreas Färber {
759f45748f1SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
760f45748f1SAndreas Färber 
761f45748f1SAndreas Färber     cpu->env.pc = value;
762f45748f1SAndreas Färber     cpu->env.npc = value + 4;
763f45748f1SAndreas Färber }
764f45748f1SAndreas Färber 
765bdf7ae5bSAndreas Färber static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
766bdf7ae5bSAndreas Färber {
767bdf7ae5bSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
768bdf7ae5bSAndreas Färber 
769bdf7ae5bSAndreas Färber     cpu->env.pc = tb->pc;
770bdf7ae5bSAndreas Färber     cpu->env.npc = tb->cs_base;
771bdf7ae5bSAndreas Färber }
772bdf7ae5bSAndreas Färber 
7738c2e1b00SAndreas Färber static bool sparc_cpu_has_work(CPUState *cs)
7748c2e1b00SAndreas Färber {
7758c2e1b00SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
7768c2e1b00SAndreas Färber     CPUSPARCState *env = &cpu->env;
7778c2e1b00SAndreas Färber 
7788c2e1b00SAndreas Färber     return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
7798c2e1b00SAndreas Färber            cpu_interrupts_enabled(env);
7808c2e1b00SAndreas Färber }
7818c2e1b00SAndreas Färber 
782*12a6c15eSIgor Mammedov static char *sparc_cpu_type_name(const char *cpu_model)
783*12a6c15eSIgor Mammedov {
784*12a6c15eSIgor Mammedov     char *name = g_strdup_printf("%s-" TYPE_SPARC_CPU, cpu_model);
785*12a6c15eSIgor Mammedov     char *s = name;
786*12a6c15eSIgor Mammedov 
787*12a6c15eSIgor Mammedov     /* SPARC cpu model names happen to have whitespaces,
788*12a6c15eSIgor Mammedov      * as type names shouldn't have spaces replace them with '-'
789*12a6c15eSIgor Mammedov      */
790*12a6c15eSIgor Mammedov     while ((s = strchr(s, ' '))) {
791*12a6c15eSIgor Mammedov         *s = '-';
792*12a6c15eSIgor Mammedov     }
793*12a6c15eSIgor Mammedov 
794*12a6c15eSIgor Mammedov     return name;
795*12a6c15eSIgor Mammedov }
796*12a6c15eSIgor Mammedov 
797*12a6c15eSIgor Mammedov static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
798*12a6c15eSIgor Mammedov {
799*12a6c15eSIgor Mammedov     ObjectClass *oc;
800*12a6c15eSIgor Mammedov     char *typename;
801*12a6c15eSIgor Mammedov 
802*12a6c15eSIgor Mammedov     if (cpu_model == NULL) {
803*12a6c15eSIgor Mammedov         return NULL;
804*12a6c15eSIgor Mammedov     }
805*12a6c15eSIgor Mammedov 
806*12a6c15eSIgor Mammedov     typename = sparc_cpu_type_name(cpu_model);
807*12a6c15eSIgor Mammedov     oc = object_class_by_name(typename);
808*12a6c15eSIgor Mammedov     g_free(typename);
809*12a6c15eSIgor Mammedov     return oc;
810*12a6c15eSIgor Mammedov }
811*12a6c15eSIgor Mammedov 
812b6e91ebfSAndreas Färber static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
813b6e91ebfSAndreas Färber {
814ce5b1bbfSLaurent Vivier     CPUState *cs = CPU(dev);
815b6e91ebfSAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
816ce5b1bbfSLaurent Vivier     Error *local_err = NULL;
817247bf011SAndreas Färber #if defined(CONFIG_USER_ONLY)
818247bf011SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(dev);
819247bf011SAndreas Färber     CPUSPARCState *env = &cpu->env;
820247bf011SAndreas Färber 
821247bf011SAndreas Färber     if ((env->def->features & CPU_FEATURE_FLOAT)) {
822247bf011SAndreas Färber         env->def->features |= CPU_FEATURE_FLOAT128;
823247bf011SAndreas Färber     }
824247bf011SAndreas Färber #endif
825b6e91ebfSAndreas Färber 
826ce5b1bbfSLaurent Vivier     cpu_exec_realizefn(cs, &local_err);
827ce5b1bbfSLaurent Vivier     if (local_err != NULL) {
828ce5b1bbfSLaurent Vivier         error_propagate(errp, local_err);
829ce5b1bbfSLaurent Vivier         return;
830ce5b1bbfSLaurent Vivier     }
831ce5b1bbfSLaurent Vivier 
832ce5b1bbfSLaurent Vivier     qemu_init_vcpu(cs);
83314a10fc3SAndreas Färber 
834b6e91ebfSAndreas Färber     scc->parent_realize(dev, errp);
835b6e91ebfSAndreas Färber }
836b6e91ebfSAndreas Färber 
837ab7ab3d7SAndreas Färber static void sparc_cpu_initfn(Object *obj)
838ab7ab3d7SAndreas Färber {
839c05efcb1SAndreas Färber     CPUState *cs = CPU(obj);
840ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(obj);
841*12a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
842ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
843ab7ab3d7SAndreas Färber 
844c05efcb1SAndreas Färber     cs->env_ptr = env;
8455266d20aSAndreas Färber 
8465266d20aSAndreas Färber     if (tcg_enabled()) {
8475266d20aSAndreas Färber         gen_intermediate_code_init(env);
8485266d20aSAndreas Färber     }
849*12a6c15eSIgor Mammedov 
850*12a6c15eSIgor Mammedov     env->def = g_memdup(scc->cpu_def, sizeof(*scc->cpu_def));
851ab7ab3d7SAndreas Färber }
852ab7ab3d7SAndreas Färber 
853ab7ab3d7SAndreas Färber static void sparc_cpu_uninitfn(Object *obj)
854ab7ab3d7SAndreas Färber {
855ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(obj);
856ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
857ab7ab3d7SAndreas Färber 
858ab7ab3d7SAndreas Färber     g_free(env->def);
859ab7ab3d7SAndreas Färber }
860ab7ab3d7SAndreas Färber 
861ab7ab3d7SAndreas Färber static void sparc_cpu_class_init(ObjectClass *oc, void *data)
862ab7ab3d7SAndreas Färber {
863ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
864ab7ab3d7SAndreas Färber     CPUClass *cc = CPU_CLASS(oc);
865b6e91ebfSAndreas Färber     DeviceClass *dc = DEVICE_CLASS(oc);
866b6e91ebfSAndreas Färber 
867b6e91ebfSAndreas Färber     scc->parent_realize = dc->realize;
868b6e91ebfSAndreas Färber     dc->realize = sparc_cpu_realizefn;
869ab7ab3d7SAndreas Färber 
870ab7ab3d7SAndreas Färber     scc->parent_reset = cc->reset;
871ab7ab3d7SAndreas Färber     cc->reset = sparc_cpu_reset;
87297a8ea5aSAndreas Färber 
873*12a6c15eSIgor Mammedov     cc->class_by_name = sparc_cpu_class_by_name;
8748c2e1b00SAndreas Färber     cc->has_work = sparc_cpu_has_work;
87597a8ea5aSAndreas Färber     cc->do_interrupt = sparc_cpu_do_interrupt;
87687afe467SRichard Henderson     cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
877878096eeSAndreas Färber     cc->dump_state = sparc_cpu_dump_state;
878f3659eeeSAndreas Färber #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
879f3659eeeSAndreas Färber     cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
880f3659eeeSAndreas Färber #endif
881f45748f1SAndreas Färber     cc->set_pc = sparc_cpu_set_pc;
882bdf7ae5bSAndreas Färber     cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
8835b50e790SAndreas Färber     cc->gdb_read_register = sparc_cpu_gdb_read_register;
8845b50e790SAndreas Färber     cc->gdb_write_register = sparc_cpu_gdb_write_register;
8857510454eSAndreas Färber #ifdef CONFIG_USER_ONLY
8867510454eSAndreas Färber     cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
8877510454eSAndreas Färber #else
88800b941e5SAndreas Färber     cc->do_unassigned_access = sparc_cpu_unassigned_access;
88993e22326SPaolo Bonzini     cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
89000b941e5SAndreas Färber     cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
891df32c8d4SJuan Quintela     cc->vmsd = &vmstate_sparc_cpu;
89200b941e5SAndreas Färber #endif
893df0900ebSPeter Crosthwaite     cc->disas_set_info = cpu_sparc_disas_set_info;
894a0e372f0SAndreas Färber 
895a0e372f0SAndreas Färber #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
896a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 86;
897a0e372f0SAndreas Färber #else
898a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 72;
899a0e372f0SAndreas Färber #endif
900ab7ab3d7SAndreas Färber }
901ab7ab3d7SAndreas Färber 
902ab7ab3d7SAndreas Färber static const TypeInfo sparc_cpu_type_info = {
903ab7ab3d7SAndreas Färber     .name = TYPE_SPARC_CPU,
904ab7ab3d7SAndreas Färber     .parent = TYPE_CPU,
905ab7ab3d7SAndreas Färber     .instance_size = sizeof(SPARCCPU),
906ab7ab3d7SAndreas Färber     .instance_init = sparc_cpu_initfn,
907ab7ab3d7SAndreas Färber     .instance_finalize = sparc_cpu_uninitfn,
908*12a6c15eSIgor Mammedov     .abstract = true,
909ab7ab3d7SAndreas Färber     .class_size = sizeof(SPARCCPUClass),
910ab7ab3d7SAndreas Färber     .class_init = sparc_cpu_class_init,
911ab7ab3d7SAndreas Färber };
912ab7ab3d7SAndreas Färber 
913*12a6c15eSIgor Mammedov static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
914*12a6c15eSIgor Mammedov {
915*12a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
916*12a6c15eSIgor Mammedov     scc->cpu_def = data;
917*12a6c15eSIgor Mammedov }
918*12a6c15eSIgor Mammedov 
919*12a6c15eSIgor Mammedov static void sparc_register_cpudef_type(const struct sparc_def_t *def)
920*12a6c15eSIgor Mammedov {
921*12a6c15eSIgor Mammedov     char *typename = sparc_cpu_type_name(def->name);
922*12a6c15eSIgor Mammedov     TypeInfo ti = {
923*12a6c15eSIgor Mammedov         .name = typename,
924*12a6c15eSIgor Mammedov         .parent = TYPE_SPARC_CPU,
925*12a6c15eSIgor Mammedov         .class_init = sparc_cpu_cpudef_class_init,
926*12a6c15eSIgor Mammedov         .class_data = (void *)def,
927*12a6c15eSIgor Mammedov     };
928*12a6c15eSIgor Mammedov 
929*12a6c15eSIgor Mammedov     type_register(&ti);
930*12a6c15eSIgor Mammedov     g_free(typename);
931*12a6c15eSIgor Mammedov }
932*12a6c15eSIgor Mammedov 
933ab7ab3d7SAndreas Färber static void sparc_cpu_register_types(void)
934ab7ab3d7SAndreas Färber {
935*12a6c15eSIgor Mammedov     int i;
936*12a6c15eSIgor Mammedov 
937ab7ab3d7SAndreas Färber     type_register_static(&sparc_cpu_type_info);
938*12a6c15eSIgor Mammedov     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
939*12a6c15eSIgor Mammedov         sparc_register_cpudef_type(&sparc_defs[i]);
940*12a6c15eSIgor Mammedov     }
941ab7ab3d7SAndreas Färber }
942ab7ab3d7SAndreas Färber 
943ab7ab3d7SAndreas Färber type_init(sparc_cpu_register_types)
944