xref: /qemu/target/sparc/cpu.c (revision 700549620b3ee15924f19b9eb79961655ce671c5)
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"
25de05005bSIgor Mammedov #include "hw/qdev-properties.h"
26de05005bSIgor Mammedov #include "qapi/visitor.h"
27ab3b491fSBlue Swirl 
28ab3b491fSBlue Swirl //#define DEBUG_FEATURES
29ab3b491fSBlue Swirl 
30ab7ab3d7SAndreas Färber /* CPUClass::reset() */
31ab7ab3d7SAndreas Färber static void sparc_cpu_reset(CPUState *s)
32ab7ab3d7SAndreas Färber {
33ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(s);
34ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
35ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
36ab7ab3d7SAndreas Färber 
37ab7ab3d7SAndreas Färber     scc->parent_reset(s);
38ab7ab3d7SAndreas Färber 
391f5c00cfSAlex Bennée     memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
40ab3b491fSBlue Swirl     env->cwp = 0;
41ab3b491fSBlue Swirl #ifndef TARGET_SPARC64
42ab3b491fSBlue Swirl     env->wim = 1;
43ab3b491fSBlue Swirl #endif
44ab3b491fSBlue Swirl     env->regwptr = env->regbase + (env->cwp * 16);
45ab3b491fSBlue Swirl     CC_OP = CC_OP_FLAGS;
46ab3b491fSBlue Swirl #if defined(CONFIG_USER_ONLY)
47ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
48ab3b491fSBlue Swirl     env->cleanwin = env->nwindows - 2;
49ab3b491fSBlue Swirl     env->cansave = env->nwindows - 2;
50ab3b491fSBlue Swirl     env->pstate = PS_RMO | PS_PEF | PS_IE;
51ab3b491fSBlue Swirl     env->asi = 0x82; /* Primary no-fault */
52ab3b491fSBlue Swirl #endif
53ab3b491fSBlue Swirl #else
54ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
55ab3b491fSBlue Swirl     env->psret = 0;
56ab3b491fSBlue Swirl     env->psrs = 1;
57ab3b491fSBlue Swirl     env->psrps = 1;
58ab3b491fSBlue Swirl #endif
59ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
60cbc3a6a4SArtyom Tarasenko     env->pstate = PS_PRIV | PS_RED | PS_PEF;
61cbc3a6a4SArtyom Tarasenko     if (!cpu_has_hypervisor(env)) {
62cbc3a6a4SArtyom Tarasenko         env->pstate |= PS_AG;
63cbc3a6a4SArtyom Tarasenko     }
64ab3b491fSBlue Swirl     env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
65ab3b491fSBlue Swirl     env->tl = env->maxtl;
66cbc3a6a4SArtyom Tarasenko     env->gl = 2;
67ab3b491fSBlue Swirl     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
68ab3b491fSBlue Swirl     env->lsu = 0;
69ab3b491fSBlue Swirl #else
70ab3b491fSBlue Swirl     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
71576e1c4cSIgor Mammedov     env->mmuregs[0] |= env->def.mmu_bm;
72ab3b491fSBlue Swirl #endif
73ab3b491fSBlue Swirl     env->pc = 0;
74ab3b491fSBlue Swirl     env->npc = env->pc + 4;
75ab3b491fSBlue Swirl #endif
76ab3b491fSBlue Swirl     env->cache_control = 0;
77ab3b491fSBlue Swirl }
78ab3b491fSBlue Swirl 
7987afe467SRichard Henderson static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
8087afe467SRichard Henderson {
8187afe467SRichard Henderson     if (interrupt_request & CPU_INTERRUPT_HARD) {
8287afe467SRichard Henderson         SPARCCPU *cpu = SPARC_CPU(cs);
8387afe467SRichard Henderson         CPUSPARCState *env = &cpu->env;
8487afe467SRichard Henderson 
8587afe467SRichard Henderson         if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
8687afe467SRichard Henderson             int pil = env->interrupt_index & 0xf;
8787afe467SRichard Henderson             int type = env->interrupt_index & 0xf0;
8887afe467SRichard Henderson 
8987afe467SRichard Henderson             if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
9087afe467SRichard Henderson                 cs->exception_index = env->interrupt_index;
9187afe467SRichard Henderson                 sparc_cpu_do_interrupt(cs);
9287afe467SRichard Henderson                 return true;
9387afe467SRichard Henderson             }
9487afe467SRichard Henderson         }
9587afe467SRichard Henderson     }
9687afe467SRichard Henderson     return false;
9787afe467SRichard Henderson }
9887afe467SRichard Henderson 
99df0900ebSPeter Crosthwaite static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
100df0900ebSPeter Crosthwaite {
101df0900ebSPeter Crosthwaite     info->print_insn = print_insn_sparc;
102df0900ebSPeter Crosthwaite #ifdef TARGET_SPARC64
103df0900ebSPeter Crosthwaite     info->mach = bfd_mach_sparc_v9b;
104df0900ebSPeter Crosthwaite #endif
105df0900ebSPeter Crosthwaite }
106df0900ebSPeter Crosthwaite 
107fb02d56eSIgor Mammedov static void sparc_cpu_parse_features(CPUState *cs, char *features,
108fb02d56eSIgor Mammedov                                      Error **errp);
109fb02d56eSIgor Mammedov 
110433ac7a9SAndreas Färber static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
111ab3b491fSBlue Swirl {
112433ac7a9SAndreas Färber     char *s = g_strdup(cpu_model);
11312a6c15eSIgor Mammedov     char *featurestr = strtok(s, ",");
114433ac7a9SAndreas Färber     Error *err = NULL;
115ab3b491fSBlue Swirl 
116433ac7a9SAndreas Färber     featurestr = strtok(NULL, ",");
117fb02d56eSIgor Mammedov     sparc_cpu_parse_features(CPU(cpu), featurestr, &err);
118433ac7a9SAndreas Färber     g_free(s);
119433ac7a9SAndreas Färber     if (err) {
120565f65d2SMarkus Armbruster         error_report_err(err);
121433ac7a9SAndreas Färber         return -1;
122433ac7a9SAndreas Färber     }
123433ac7a9SAndreas Färber 
124ab3b491fSBlue Swirl     return 0;
125ab3b491fSBlue Swirl }
126ab3b491fSBlue Swirl 
127e59be77aSAndreas Färber SPARCCPU *cpu_sparc_init(const char *cpu_model)
128ab3b491fSBlue Swirl {
129ab7ab3d7SAndreas Färber     SPARCCPU *cpu;
13012a6c15eSIgor Mammedov     ObjectClass *oc;
13112a6c15eSIgor Mammedov     char *str, *name;
132ab3b491fSBlue Swirl 
13312a6c15eSIgor Mammedov     str = g_strdup(cpu_model);
13412a6c15eSIgor Mammedov     name = strtok(str, ",");
13512a6c15eSIgor Mammedov     oc = cpu_class_by_name(TYPE_SPARC_CPU, name);
13612a6c15eSIgor Mammedov     g_free(str);
13712a6c15eSIgor Mammedov     if (oc == NULL) {
13812a6c15eSIgor Mammedov         return NULL;
13912a6c15eSIgor Mammedov     }
14012a6c15eSIgor Mammedov 
14112a6c15eSIgor Mammedov     cpu = SPARC_CPU(object_new(object_class_get_name(oc)));
142ab3b491fSBlue Swirl 
143433ac7a9SAndreas Färber     if (cpu_sparc_register(cpu, cpu_model) < 0) {
1445c099537SPaolo Bonzini         object_unref(OBJECT(cpu));
145ab3b491fSBlue Swirl         return NULL;
146ab3b491fSBlue Swirl     }
147b6e91ebfSAndreas Färber 
148b6e91ebfSAndreas Färber     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
149ab3b491fSBlue Swirl 
150e59be77aSAndreas Färber     return cpu;
151ab3b491fSBlue Swirl }
152ab3b491fSBlue Swirl 
153ab3b491fSBlue Swirl void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
154ab3b491fSBlue Swirl {
155ab3b491fSBlue Swirl #if !defined(TARGET_SPARC64)
156ab3b491fSBlue Swirl     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
157ab3b491fSBlue Swirl #endif
158ab3b491fSBlue Swirl }
159ab3b491fSBlue Swirl 
160ab3b491fSBlue Swirl static const sparc_def_t sparc_defs[] = {
161ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
162ab3b491fSBlue Swirl     {
163ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64",
164ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
165ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
166ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
167ab3b491fSBlue Swirl         .nwindows = 4,
168ab3b491fSBlue Swirl         .maxtl = 4,
169ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
170ab3b491fSBlue Swirl     },
171ab3b491fSBlue Swirl     {
172ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 III",
173ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
174ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
175ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
176ab3b491fSBlue Swirl         .nwindows = 5,
177ab3b491fSBlue Swirl         .maxtl = 4,
178ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
179ab3b491fSBlue Swirl     },
180ab3b491fSBlue Swirl     {
181ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 IV",
182ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
183ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
184ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
185ab3b491fSBlue Swirl         .nwindows = 8,
186ab3b491fSBlue Swirl         .maxtl = 5,
187ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
188ab3b491fSBlue Swirl     },
189ab3b491fSBlue Swirl     {
190ab3b491fSBlue Swirl         .name = "Fujitsu Sparc64 V",
191ab3b491fSBlue Swirl         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
192ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
193ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
194ab3b491fSBlue Swirl         .nwindows = 8,
195ab3b491fSBlue Swirl         .maxtl = 5,
196ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
197ab3b491fSBlue Swirl     },
198ab3b491fSBlue Swirl     {
199ab3b491fSBlue Swirl         .name = "TI UltraSparc I",
200ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
201ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
202ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
203ab3b491fSBlue Swirl         .nwindows = 8,
204ab3b491fSBlue Swirl         .maxtl = 5,
205ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
206ab3b491fSBlue Swirl     },
207ab3b491fSBlue Swirl     {
208ab3b491fSBlue Swirl         .name = "TI UltraSparc II",
209ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
210ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
211ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
212ab3b491fSBlue Swirl         .nwindows = 8,
213ab3b491fSBlue Swirl         .maxtl = 5,
214ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
215ab3b491fSBlue Swirl     },
216ab3b491fSBlue Swirl     {
217ab3b491fSBlue Swirl         .name = "TI UltraSparc IIi",
218ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
219ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
220ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
221ab3b491fSBlue Swirl         .nwindows = 8,
222ab3b491fSBlue Swirl         .maxtl = 5,
223ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
224ab3b491fSBlue Swirl     },
225ab3b491fSBlue Swirl     {
226ab3b491fSBlue Swirl         .name = "TI UltraSparc IIe",
227ab3b491fSBlue Swirl         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
228ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
229ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
230ab3b491fSBlue Swirl         .nwindows = 8,
231ab3b491fSBlue Swirl         .maxtl = 5,
232ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
233ab3b491fSBlue Swirl     },
234ab3b491fSBlue Swirl     {
235ab3b491fSBlue Swirl         .name = "Sun UltraSparc III",
236ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
237ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
238ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
239ab3b491fSBlue Swirl         .nwindows = 8,
240ab3b491fSBlue Swirl         .maxtl = 5,
241ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
242ab3b491fSBlue Swirl     },
243ab3b491fSBlue Swirl     {
244ab3b491fSBlue Swirl         .name = "Sun UltraSparc III Cu",
245ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
246ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
247ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
248ab3b491fSBlue Swirl         .nwindows = 8,
249ab3b491fSBlue Swirl         .maxtl = 5,
250ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
251ab3b491fSBlue Swirl     },
252ab3b491fSBlue Swirl     {
253ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi",
254ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
255ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
256ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
257ab3b491fSBlue Swirl         .nwindows = 8,
258ab3b491fSBlue Swirl         .maxtl = 5,
259ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
260ab3b491fSBlue Swirl     },
261ab3b491fSBlue Swirl     {
262ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV",
263ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
264ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
265ab3b491fSBlue Swirl         .mmu_version = mmu_us_4,
266ab3b491fSBlue Swirl         .nwindows = 8,
267ab3b491fSBlue Swirl         .maxtl = 5,
268ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
269ab3b491fSBlue Swirl     },
270ab3b491fSBlue Swirl     {
271ab3b491fSBlue Swirl         .name = "Sun UltraSparc IV+",
272ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
273ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
274ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
275ab3b491fSBlue Swirl         .nwindows = 8,
276ab3b491fSBlue Swirl         .maxtl = 5,
277ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
278ab3b491fSBlue Swirl     },
279ab3b491fSBlue Swirl     {
280ab3b491fSBlue Swirl         .name = "Sun UltraSparc IIIi+",
281ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
282ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
283ab3b491fSBlue Swirl         .mmu_version = mmu_us_3,
284ab3b491fSBlue Swirl         .nwindows = 8,
285ab3b491fSBlue Swirl         .maxtl = 5,
286ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
287ab3b491fSBlue Swirl     },
288ab3b491fSBlue Swirl     {
289ab3b491fSBlue Swirl         .name = "Sun UltraSparc T1",
290ab3b491fSBlue Swirl         /* defined in sparc_ifu_fdp.v and ctu.h */
291ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
292ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
293ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
294ab3b491fSBlue Swirl         .nwindows = 8,
295ab3b491fSBlue Swirl         .maxtl = 6,
296ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
297ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
298ab3b491fSBlue Swirl     },
299ab3b491fSBlue Swirl     {
300ab3b491fSBlue Swirl         .name = "Sun UltraSparc T2",
301ab3b491fSBlue Swirl         /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
302ab3b491fSBlue Swirl         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
303ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
304ab3b491fSBlue Swirl         .mmu_version = mmu_sun4v,
305ab3b491fSBlue Swirl         .nwindows = 8,
306ab3b491fSBlue Swirl         .maxtl = 6,
307ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
308ab3b491fSBlue Swirl         | CPU_FEATURE_GL,
309ab3b491fSBlue Swirl     },
310ab3b491fSBlue Swirl     {
311ab3b491fSBlue Swirl         .name = "NEC UltraSparc I",
312ab3b491fSBlue Swirl         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
313ab3b491fSBlue Swirl         .fpu_version = 0x00000000,
314ab3b491fSBlue Swirl         .mmu_version = mmu_us_12,
315ab3b491fSBlue Swirl         .nwindows = 8,
316ab3b491fSBlue Swirl         .maxtl = 5,
317ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
318ab3b491fSBlue Swirl     },
319ab3b491fSBlue Swirl #else
320ab3b491fSBlue Swirl     {
321ab3b491fSBlue Swirl         .name = "Fujitsu MB86904",
322ab3b491fSBlue Swirl         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
323ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
324ab3b491fSBlue Swirl         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
325ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
326ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
327ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
328ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
329ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
330ab3b491fSBlue Swirl         .nwindows = 8,
331ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
332ab3b491fSBlue Swirl     },
333ab3b491fSBlue Swirl     {
334ab3b491fSBlue Swirl         .name = "Fujitsu MB86907",
335ab3b491fSBlue Swirl         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
336ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
337ab3b491fSBlue Swirl         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
338ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
339ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
340ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
341ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
342ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
343ab3b491fSBlue Swirl         .nwindows = 8,
344ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
345ab3b491fSBlue Swirl     },
346ab3b491fSBlue Swirl     {
347ab3b491fSBlue Swirl         .name = "TI MicroSparc I",
348ab3b491fSBlue Swirl         .iu_version = 0x41000000,
349ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
350ab3b491fSBlue Swirl         .mmu_version = 0x41000000,
351ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
352ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
353ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
354ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
355ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x0000003f,
356ab3b491fSBlue Swirl         .nwindows = 7,
357ab3b491fSBlue Swirl         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
358ab3b491fSBlue Swirl         CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
359ab3b491fSBlue Swirl         CPU_FEATURE_FMUL,
360ab3b491fSBlue Swirl     },
361ab3b491fSBlue Swirl     {
362ab3b491fSBlue Swirl         .name = "TI MicroSparc II",
363ab3b491fSBlue Swirl         .iu_version = 0x42000000,
364ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
365ab3b491fSBlue Swirl         .mmu_version = 0x02000000,
366ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
367ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
368ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
369ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016fff,
370ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
371ab3b491fSBlue Swirl         .nwindows = 8,
372ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
373ab3b491fSBlue Swirl     },
374ab3b491fSBlue Swirl     {
375ab3b491fSBlue Swirl         .name = "TI MicroSparc IIep",
376ab3b491fSBlue Swirl         .iu_version = 0x42000000,
377ab3b491fSBlue Swirl         .fpu_version = 4 << 17,
378ab3b491fSBlue Swirl         .mmu_version = 0x04000000,
379ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
380ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x00ffffc0,
381ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x000000ff,
382ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0x00016bff,
383ab3b491fSBlue Swirl         .mmu_trcr_mask = 0x00ffffff,
384ab3b491fSBlue Swirl         .nwindows = 8,
385ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
386ab3b491fSBlue Swirl     },
387ab3b491fSBlue Swirl     {
388ab3b491fSBlue Swirl         .name = "TI SuperSparc 40", /* STP1020NPGA */
389ab3b491fSBlue Swirl         .iu_version = 0x41000000, /* SuperSPARC 2.x */
390ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
391ab3b491fSBlue Swirl         .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
392ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
393ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
394ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
395ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
396ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
397ab3b491fSBlue Swirl         .nwindows = 8,
398ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
399ab3b491fSBlue Swirl     },
400ab3b491fSBlue Swirl     {
401ab3b491fSBlue Swirl         .name = "TI SuperSparc 50", /* STP1020PGA */
402ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
403ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
404ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
405ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
406ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
407ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
408ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
409ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
410ab3b491fSBlue Swirl         .nwindows = 8,
411ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
412ab3b491fSBlue Swirl     },
413ab3b491fSBlue Swirl     {
414ab3b491fSBlue Swirl         .name = "TI SuperSparc 51",
415ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
416ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
417ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
418ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
419ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
420ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
421ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
422ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
423ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
424ab3b491fSBlue Swirl         .nwindows = 8,
425ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
426ab3b491fSBlue Swirl     },
427ab3b491fSBlue Swirl     {
428ab3b491fSBlue Swirl         .name = "TI SuperSparc 60", /* STP1020APGA */
429ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC 3.x */
430ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
431ab3b491fSBlue Swirl         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
432ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
433ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
434ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
435ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
436ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
437ab3b491fSBlue Swirl         .nwindows = 8,
438ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
439ab3b491fSBlue Swirl     },
440ab3b491fSBlue Swirl     {
441ab3b491fSBlue Swirl         .name = "TI SuperSparc 61",
442ab3b491fSBlue Swirl         .iu_version = 0x44000000, /* SuperSPARC 3.x */
443ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
444ab3b491fSBlue Swirl         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
445ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
446ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
447ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
448ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
449ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
450ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
451ab3b491fSBlue Swirl         .nwindows = 8,
452ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
453ab3b491fSBlue Swirl     },
454ab3b491fSBlue Swirl     {
455ab3b491fSBlue Swirl         .name = "TI SuperSparc II",
456ab3b491fSBlue Swirl         .iu_version = 0x40000000, /* SuperSPARC II 1.x */
457ab3b491fSBlue Swirl         .fpu_version = 0 << 17,
458ab3b491fSBlue Swirl         .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
459ab3b491fSBlue Swirl         .mmu_bm = 0x00002000,
460ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0xffffffc0,
461ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000ffff,
462ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
463ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
464ab3b491fSBlue Swirl         .mxcc_version = 0x00000104,
465ab3b491fSBlue Swirl         .nwindows = 8,
466ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES,
467ab3b491fSBlue Swirl     },
468ab3b491fSBlue Swirl     {
469ab3b491fSBlue Swirl         .name = "LEON2",
470ab3b491fSBlue Swirl         .iu_version = 0xf2000000,
471ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
472ab3b491fSBlue Swirl         .mmu_version = 0xf2000000,
473ab3b491fSBlue Swirl         .mmu_bm = 0x00004000,
474ab3b491fSBlue Swirl         .mmu_ctpr_mask = 0x007ffff0,
475ab3b491fSBlue Swirl         .mmu_cxr_mask = 0x0000003f,
476ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
477ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
478ab3b491fSBlue Swirl         .nwindows = 8,
479ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
480ab3b491fSBlue Swirl     },
481ab3b491fSBlue Swirl     {
482ab3b491fSBlue Swirl         .name = "LEON3",
483ab3b491fSBlue Swirl         .iu_version = 0xf3000000,
484ab3b491fSBlue Swirl         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
485ab3b491fSBlue Swirl         .mmu_version = 0xf3000000,
486ab3b491fSBlue Swirl         .mmu_bm = 0x00000000,
4877a0a9c2cSRonald Hecht         .mmu_ctpr_mask = 0xfffffffc,
4887a0a9c2cSRonald Hecht         .mmu_cxr_mask = 0x000000ff,
489ab3b491fSBlue Swirl         .mmu_sfsr_mask = 0xffffffff,
490ab3b491fSBlue Swirl         .mmu_trcr_mask = 0xffffffff,
491ab3b491fSBlue Swirl         .nwindows = 8,
492ab3b491fSBlue Swirl         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
49316c358e9SSebastian Huber         CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
49416c358e9SSebastian Huber         CPU_FEATURE_CASA,
495ab3b491fSBlue Swirl     },
496ab3b491fSBlue Swirl #endif
497ab3b491fSBlue Swirl };
498ab3b491fSBlue Swirl 
499ab3b491fSBlue Swirl static const char * const feature_name[] = {
500ab3b491fSBlue Swirl     "float",
501ab3b491fSBlue Swirl     "float128",
502ab3b491fSBlue Swirl     "swap",
503ab3b491fSBlue Swirl     "mul",
504ab3b491fSBlue Swirl     "div",
505ab3b491fSBlue Swirl     "flush",
506ab3b491fSBlue Swirl     "fsqrt",
507ab3b491fSBlue Swirl     "fmul",
508ab3b491fSBlue Swirl     "vis1",
509ab3b491fSBlue Swirl     "vis2",
510ab3b491fSBlue Swirl     "fsmuld",
511ab3b491fSBlue Swirl     "hypv",
512ab3b491fSBlue Swirl     "cmt",
513ab3b491fSBlue Swirl     "gl",
514ab3b491fSBlue Swirl };
515ab3b491fSBlue Swirl 
516ab3b491fSBlue Swirl static void print_features(FILE *f, fprintf_function cpu_fprintf,
517ab3b491fSBlue Swirl                            uint32_t features, const char *prefix)
518ab3b491fSBlue Swirl {
519ab3b491fSBlue Swirl     unsigned int i;
520ab3b491fSBlue Swirl 
521ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
522ab3b491fSBlue Swirl         if (feature_name[i] && (features & (1 << i))) {
523ab3b491fSBlue Swirl             if (prefix) {
524ab3b491fSBlue Swirl                 (*cpu_fprintf)(f, "%s", prefix);
525ab3b491fSBlue Swirl             }
526ab3b491fSBlue Swirl             (*cpu_fprintf)(f, "%s ", feature_name[i]);
527ab3b491fSBlue Swirl         }
528ab3b491fSBlue Swirl     }
529ab3b491fSBlue Swirl }
530ab3b491fSBlue Swirl 
531ab3b491fSBlue Swirl static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
532ab3b491fSBlue Swirl {
533ab3b491fSBlue Swirl     unsigned int i;
534ab3b491fSBlue Swirl 
535ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
536ab3b491fSBlue Swirl         if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
537ab3b491fSBlue Swirl             *features |= 1 << i;
538ab3b491fSBlue Swirl             return;
539ab3b491fSBlue Swirl         }
540ab3b491fSBlue Swirl     }
541db5d39f7SAndreas Färber     error_report("CPU feature %s not found", flagname);
542ab3b491fSBlue Swirl }
543ab3b491fSBlue Swirl 
544433ac7a9SAndreas Färber static void sparc_cpu_parse_features(CPUState *cs, char *features,
545433ac7a9SAndreas Färber                                      Error **errp)
546433ac7a9SAndreas Färber {
547433ac7a9SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
548576e1c4cSIgor Mammedov     sparc_def_t *cpu_def = &cpu->env.def;
549433ac7a9SAndreas Färber     char *featurestr;
550433ac7a9SAndreas Färber     uint32_t plus_features = 0;
551433ac7a9SAndreas Färber     uint32_t minus_features = 0;
552433ac7a9SAndreas Färber     uint64_t iu_version;
553433ac7a9SAndreas Färber     uint32_t fpu_version, mmu_version, nwindows;
554433ac7a9SAndreas Färber 
555433ac7a9SAndreas Färber     featurestr = features ? strtok(features, ",") : NULL;
556ab3b491fSBlue Swirl     while (featurestr) {
557ab3b491fSBlue Swirl         char *val;
558ab3b491fSBlue Swirl 
559ab3b491fSBlue Swirl         if (featurestr[0] == '+') {
560ab3b491fSBlue Swirl             add_flagname_to_bitmaps(featurestr + 1, &plus_features);
561ab3b491fSBlue Swirl         } else if (featurestr[0] == '-') {
562ab3b491fSBlue Swirl             add_flagname_to_bitmaps(featurestr + 1, &minus_features);
563ab3b491fSBlue Swirl         } else if ((val = strchr(featurestr, '='))) {
564ab3b491fSBlue Swirl             *val = 0; val++;
565ab3b491fSBlue Swirl             if (!strcmp(featurestr, "iu_version")) {
566ab3b491fSBlue Swirl                 char *err;
567ab3b491fSBlue Swirl 
568ab3b491fSBlue Swirl                 iu_version = strtoll(val, &err, 0);
569ab3b491fSBlue Swirl                 if (!*val || *err) {
570433ac7a9SAndreas Färber                     error_setg(errp, "bad numerical value %s", val);
571433ac7a9SAndreas Färber                     return;
572ab3b491fSBlue Swirl                 }
573ab3b491fSBlue Swirl                 cpu_def->iu_version = iu_version;
574ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
575ab3b491fSBlue Swirl                 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
576ab3b491fSBlue Swirl #endif
577ab3b491fSBlue Swirl             } else if (!strcmp(featurestr, "fpu_version")) {
578ab3b491fSBlue Swirl                 char *err;
579ab3b491fSBlue Swirl 
580ab3b491fSBlue Swirl                 fpu_version = strtol(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->fpu_version = fpu_version;
586ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
587ab3b491fSBlue Swirl                 fprintf(stderr, "fpu_version %x\n", fpu_version);
588ab3b491fSBlue Swirl #endif
589ab3b491fSBlue Swirl             } else if (!strcmp(featurestr, "mmu_version")) {
590ab3b491fSBlue Swirl                 char *err;
591ab3b491fSBlue Swirl 
592ab3b491fSBlue Swirl                 mmu_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->mmu_version = mmu_version;
598ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
599ab3b491fSBlue Swirl                 fprintf(stderr, "mmu_version %x\n", mmu_version);
600ab3b491fSBlue Swirl #endif
601ab3b491fSBlue Swirl             } else if (!strcmp(featurestr, "nwindows")) {
602ab3b491fSBlue Swirl                 char *err;
603ab3b491fSBlue Swirl 
604ab3b491fSBlue Swirl                 nwindows = strtol(val, &err, 0);
605ab3b491fSBlue Swirl                 if (!*val || *err || nwindows > MAX_NWINDOWS ||
606ab3b491fSBlue Swirl                     nwindows < MIN_NWINDOWS) {
607433ac7a9SAndreas Färber                     error_setg(errp, "bad numerical value %s", val);
608433ac7a9SAndreas Färber                     return;
609ab3b491fSBlue Swirl                 }
610ab3b491fSBlue Swirl                 cpu_def->nwindows = nwindows;
611ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
612ab3b491fSBlue Swirl                 fprintf(stderr, "nwindows %d\n", nwindows);
613ab3b491fSBlue Swirl #endif
614ab3b491fSBlue Swirl             } else {
615433ac7a9SAndreas Färber                 error_setg(errp, "unrecognized feature %s", featurestr);
616433ac7a9SAndreas Färber                 return;
617ab3b491fSBlue Swirl             }
618ab3b491fSBlue Swirl         } else {
619433ac7a9SAndreas Färber             error_setg(errp, "feature string `%s' not in format "
620db5d39f7SAndreas Färber                              "(+feature|-feature|feature=xyz)", featurestr);
621433ac7a9SAndreas Färber             return;
622ab3b491fSBlue Swirl         }
623ab3b491fSBlue Swirl         featurestr = strtok(NULL, ",");
624ab3b491fSBlue Swirl     }
625ab3b491fSBlue Swirl     cpu_def->features |= plus_features;
626ab3b491fSBlue Swirl     cpu_def->features &= ~minus_features;
627ab3b491fSBlue Swirl #ifdef DEBUG_FEATURES
628ab3b491fSBlue Swirl     print_features(stderr, fprintf, cpu_def->features, NULL);
629ab3b491fSBlue Swirl #endif
630ab3b491fSBlue Swirl }
631ab3b491fSBlue Swirl 
632ab3b491fSBlue Swirl void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
633ab3b491fSBlue Swirl {
634ab3b491fSBlue Swirl     unsigned int i;
635ab3b491fSBlue Swirl 
636ab3b491fSBlue Swirl     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
637ab3b491fSBlue Swirl         (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
638ab3b491fSBlue Swirl                        " FPU %08x MMU %08x NWINS %d ",
639ab3b491fSBlue Swirl                        sparc_defs[i].name,
640ab3b491fSBlue Swirl                        sparc_defs[i].iu_version,
641ab3b491fSBlue Swirl                        sparc_defs[i].fpu_version,
642ab3b491fSBlue Swirl                        sparc_defs[i].mmu_version,
643ab3b491fSBlue Swirl                        sparc_defs[i].nwindows);
644ab3b491fSBlue Swirl         print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
645ab3b491fSBlue Swirl                        ~sparc_defs[i].features, "-");
646ab3b491fSBlue Swirl         print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
647ab3b491fSBlue Swirl                        sparc_defs[i].features, "+");
648ab3b491fSBlue Swirl         (*cpu_fprintf)(f, "\n");
649ab3b491fSBlue Swirl     }
650ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
651ab3b491fSBlue Swirl     print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
652ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "\n");
653ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
654ab3b491fSBlue Swirl     print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
655ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "\n");
656ab3b491fSBlue Swirl     (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
657ab3b491fSBlue Swirl                    "fpu_version mmu_version nwindows\n");
658ab3b491fSBlue Swirl }
659ab3b491fSBlue Swirl 
660ab3b491fSBlue Swirl static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
661ab3b491fSBlue Swirl                          uint32_t cc)
662ab3b491fSBlue Swirl {
663ab3b491fSBlue Swirl     cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
664ab3b491fSBlue Swirl                 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
665ab3b491fSBlue Swirl                 cc & PSR_CARRY ? 'C' : '-');
666ab3b491fSBlue Swirl }
667ab3b491fSBlue Swirl 
668ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
669ab3b491fSBlue Swirl #define REGS_PER_LINE 4
670ab3b491fSBlue Swirl #else
671ab3b491fSBlue Swirl #define REGS_PER_LINE 8
672ab3b491fSBlue Swirl #endif
673ab3b491fSBlue Swirl 
674878096eeSAndreas Färber void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
675ab3b491fSBlue Swirl                           int flags)
676ab3b491fSBlue Swirl {
677878096eeSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
678878096eeSAndreas Färber     CPUSPARCState *env = &cpu->env;
679ab3b491fSBlue Swirl     int i, x;
680ab3b491fSBlue Swirl 
681ab3b491fSBlue Swirl     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
682ab3b491fSBlue Swirl                 env->npc);
683ab3b491fSBlue Swirl 
684ab3b491fSBlue Swirl     for (i = 0; i < 8; i++) {
685ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == 0) {
686ab3b491fSBlue Swirl             cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
687ab3b491fSBlue Swirl         }
688ab3b491fSBlue Swirl         cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
689ab3b491fSBlue Swirl         if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
690ab3b491fSBlue Swirl             cpu_fprintf(f, "\n");
691ab3b491fSBlue Swirl         }
692ab3b491fSBlue Swirl     }
693ab3b491fSBlue Swirl     for (x = 0; x < 3; x++) {
694ab3b491fSBlue Swirl         for (i = 0; i < 8; i++) {
695ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == 0) {
696ab3b491fSBlue Swirl                 cpu_fprintf(f, "%%%c%d-%d: ",
697ab3b491fSBlue Swirl                             x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
698ab3b491fSBlue Swirl                             i, i + REGS_PER_LINE - 1);
699ab3b491fSBlue Swirl             }
700ab3b491fSBlue Swirl             cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
701ab3b491fSBlue Swirl             if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
702ab3b491fSBlue Swirl                 cpu_fprintf(f, "\n");
703ab3b491fSBlue Swirl             }
704ab3b491fSBlue Swirl         }
705ab3b491fSBlue Swirl     }
70676a23ca0SRichard Henderson 
70730038fd8SRichard Henderson     for (i = 0; i < TARGET_DPREGS; i++) {
708ab3b491fSBlue Swirl         if ((i & 3) == 0) {
70930038fd8SRichard Henderson             cpu_fprintf(f, "%%f%02d: ", i * 2);
710ab3b491fSBlue Swirl         }
71130038fd8SRichard Henderson         cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
712ab3b491fSBlue Swirl         if ((i & 3) == 3) {
713ab3b491fSBlue Swirl             cpu_fprintf(f, "\n");
714ab3b491fSBlue Swirl         }
715ab3b491fSBlue Swirl     }
716ab3b491fSBlue Swirl #ifdef TARGET_SPARC64
717ab3b491fSBlue Swirl     cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
718ab3b491fSBlue Swirl                 (unsigned)cpu_get_ccr(env));
719ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
720ab3b491fSBlue Swirl     cpu_fprintf(f, " xcc: ");
721ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
722cbc3a6a4SArtyom Tarasenko     cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
723cbc3a6a4SArtyom Tarasenko                 env->psrpil, env->gl);
724cbc3a6a4SArtyom Tarasenko     cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
725cbc3a6a4SArtyom Tarasenko                 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
726ab3b491fSBlue Swirl     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
727ab3b491fSBlue Swirl                 "cleanwin: %d cwp: %d\n",
728ab3b491fSBlue Swirl                 env->cansave, env->canrestore, env->otherwin, env->wstate,
729ab3b491fSBlue Swirl                 env->cleanwin, env->nwindows - 1 - env->cwp);
730ab3b491fSBlue Swirl     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
731ab3b491fSBlue Swirl                 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
732cbc3a6a4SArtyom Tarasenko 
733ab3b491fSBlue Swirl #else
734ab3b491fSBlue Swirl     cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
735ab3b491fSBlue Swirl     cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
736ab3b491fSBlue Swirl     cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
737ab3b491fSBlue Swirl                 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
738ab3b491fSBlue Swirl                 env->wim);
739ab3b491fSBlue Swirl     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
740ab3b491fSBlue Swirl                 env->fsr, env->y);
741ab3b491fSBlue Swirl #endif
74276a23ca0SRichard Henderson     cpu_fprintf(f, "\n");
743ab3b491fSBlue Swirl }
744ab7ab3d7SAndreas Färber 
745f45748f1SAndreas Färber static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
746f45748f1SAndreas Färber {
747f45748f1SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
748f45748f1SAndreas Färber 
749f45748f1SAndreas Färber     cpu->env.pc = value;
750f45748f1SAndreas Färber     cpu->env.npc = value + 4;
751f45748f1SAndreas Färber }
752f45748f1SAndreas Färber 
753bdf7ae5bSAndreas Färber static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
754bdf7ae5bSAndreas Färber {
755bdf7ae5bSAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
756bdf7ae5bSAndreas Färber 
757bdf7ae5bSAndreas Färber     cpu->env.pc = tb->pc;
758bdf7ae5bSAndreas Färber     cpu->env.npc = tb->cs_base;
759bdf7ae5bSAndreas Färber }
760bdf7ae5bSAndreas Färber 
7618c2e1b00SAndreas Färber static bool sparc_cpu_has_work(CPUState *cs)
7628c2e1b00SAndreas Färber {
7638c2e1b00SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(cs);
7648c2e1b00SAndreas Färber     CPUSPARCState *env = &cpu->env;
7658c2e1b00SAndreas Färber 
7668c2e1b00SAndreas Färber     return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
7678c2e1b00SAndreas Färber            cpu_interrupts_enabled(env);
7688c2e1b00SAndreas Färber }
7698c2e1b00SAndreas Färber 
77012a6c15eSIgor Mammedov static char *sparc_cpu_type_name(const char *cpu_model)
77112a6c15eSIgor Mammedov {
77212a6c15eSIgor Mammedov     char *name = g_strdup_printf("%s-" TYPE_SPARC_CPU, cpu_model);
77312a6c15eSIgor Mammedov     char *s = name;
77412a6c15eSIgor Mammedov 
77512a6c15eSIgor Mammedov     /* SPARC cpu model names happen to have whitespaces,
77612a6c15eSIgor Mammedov      * as type names shouldn't have spaces replace them with '-'
77712a6c15eSIgor Mammedov      */
77812a6c15eSIgor Mammedov     while ((s = strchr(s, ' '))) {
77912a6c15eSIgor Mammedov         *s = '-';
78012a6c15eSIgor Mammedov     }
78112a6c15eSIgor Mammedov 
78212a6c15eSIgor Mammedov     return name;
78312a6c15eSIgor Mammedov }
78412a6c15eSIgor Mammedov 
78512a6c15eSIgor Mammedov static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
78612a6c15eSIgor Mammedov {
78712a6c15eSIgor Mammedov     ObjectClass *oc;
78812a6c15eSIgor Mammedov     char *typename;
78912a6c15eSIgor Mammedov 
79012a6c15eSIgor Mammedov     if (cpu_model == NULL) {
79112a6c15eSIgor Mammedov         return NULL;
79212a6c15eSIgor Mammedov     }
79312a6c15eSIgor Mammedov 
79412a6c15eSIgor Mammedov     typename = sparc_cpu_type_name(cpu_model);
79512a6c15eSIgor Mammedov     oc = object_class_by_name(typename);
79612a6c15eSIgor Mammedov     g_free(typename);
79712a6c15eSIgor Mammedov     return oc;
79812a6c15eSIgor Mammedov }
79912a6c15eSIgor Mammedov 
800b6e91ebfSAndreas Färber static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
801b6e91ebfSAndreas Färber {
802ce5b1bbfSLaurent Vivier     CPUState *cs = CPU(dev);
803b6e91ebfSAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
804ce5b1bbfSLaurent Vivier     Error *local_err = NULL;
805247bf011SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(dev);
806247bf011SAndreas Färber     CPUSPARCState *env = &cpu->env;
807247bf011SAndreas Färber 
808*70054962SIgor Mammedov #if defined(CONFIG_USER_ONLY)
809576e1c4cSIgor Mammedov     if ((env->def.features & CPU_FEATURE_FLOAT)) {
810576e1c4cSIgor Mammedov         env->def.features |= CPU_FEATURE_FLOAT128;
811247bf011SAndreas Färber     }
812247bf011SAndreas Färber #endif
813b6e91ebfSAndreas Färber 
814*70054962SIgor Mammedov     env->version = env->def.iu_version;
815*70054962SIgor Mammedov     env->fsr = env->def.fpu_version;
816*70054962SIgor Mammedov     env->nwindows = env->def.nwindows;
817*70054962SIgor Mammedov #if !defined(TARGET_SPARC64)
818*70054962SIgor Mammedov     env->mmuregs[0] |= env->def.mmu_version;
819*70054962SIgor Mammedov     cpu_sparc_set_id(env, 0);
820*70054962SIgor Mammedov     env->mxccregs[7] |= env->def.mxcc_version;
821*70054962SIgor Mammedov #else
822*70054962SIgor Mammedov     env->mmu_version = env->def.mmu_version;
823*70054962SIgor Mammedov     env->maxtl = env->def.maxtl;
824*70054962SIgor Mammedov     env->version |= env->def.maxtl << 8;
825*70054962SIgor Mammedov     env->version |= env->def.nwindows - 1;
826*70054962SIgor Mammedov #endif
827*70054962SIgor Mammedov 
828ce5b1bbfSLaurent Vivier     cpu_exec_realizefn(cs, &local_err);
829ce5b1bbfSLaurent Vivier     if (local_err != NULL) {
830ce5b1bbfSLaurent Vivier         error_propagate(errp, local_err);
831ce5b1bbfSLaurent Vivier         return;
832ce5b1bbfSLaurent Vivier     }
833ce5b1bbfSLaurent Vivier 
834ce5b1bbfSLaurent Vivier     qemu_init_vcpu(cs);
83514a10fc3SAndreas Färber 
836b6e91ebfSAndreas Färber     scc->parent_realize(dev, errp);
837b6e91ebfSAndreas Färber }
838b6e91ebfSAndreas Färber 
839ab7ab3d7SAndreas Färber static void sparc_cpu_initfn(Object *obj)
840ab7ab3d7SAndreas Färber {
841c05efcb1SAndreas Färber     CPUState *cs = CPU(obj);
842ab7ab3d7SAndreas Färber     SPARCCPU *cpu = SPARC_CPU(obj);
84312a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
844ab7ab3d7SAndreas Färber     CPUSPARCState *env = &cpu->env;
845ab7ab3d7SAndreas Färber 
846c05efcb1SAndreas Färber     cs->env_ptr = env;
8475266d20aSAndreas Färber 
8485266d20aSAndreas Färber     if (tcg_enabled()) {
8495266d20aSAndreas Färber         gen_intermediate_code_init(env);
8505266d20aSAndreas Färber     }
85112a6c15eSIgor Mammedov 
852576e1c4cSIgor Mammedov     if (scc->cpu_def) {
853576e1c4cSIgor Mammedov         env->def = *scc->cpu_def;
854ab7ab3d7SAndreas Färber     }
855ab7ab3d7SAndreas Färber }
856ab7ab3d7SAndreas Färber 
857de05005bSIgor Mammedov static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
858de05005bSIgor Mammedov                                void *opaque, Error **errp)
859de05005bSIgor Mammedov {
860de05005bSIgor Mammedov     SPARCCPU *cpu = SPARC_CPU(obj);
861de05005bSIgor Mammedov     int64_t value = cpu->env.def.nwindows;
862de05005bSIgor Mammedov 
863de05005bSIgor Mammedov     visit_type_int(v, name, &value, errp);
864de05005bSIgor Mammedov }
865de05005bSIgor Mammedov 
866de05005bSIgor Mammedov static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
867de05005bSIgor Mammedov                                void *opaque, Error **errp)
868de05005bSIgor Mammedov {
869de05005bSIgor Mammedov     const int64_t min = MIN_NWINDOWS;
870de05005bSIgor Mammedov     const int64_t max = MAX_NWINDOWS;
871de05005bSIgor Mammedov     SPARCCPU *cpu = SPARC_CPU(obj);
872de05005bSIgor Mammedov     Error *err = NULL;
873de05005bSIgor Mammedov     int64_t value;
874de05005bSIgor Mammedov 
875de05005bSIgor Mammedov     visit_type_int(v, name, &value, &err);
876de05005bSIgor Mammedov     if (err) {
877de05005bSIgor Mammedov         error_propagate(errp, err);
878de05005bSIgor Mammedov         return;
879de05005bSIgor Mammedov     }
880de05005bSIgor Mammedov 
881de05005bSIgor Mammedov     if (value < min || value > max) {
882de05005bSIgor Mammedov         error_setg(errp, "Property %s.%s doesn't take value %" PRId64
883de05005bSIgor Mammedov                    " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
884de05005bSIgor Mammedov                    object_get_typename(obj), name ? name : "null",
885de05005bSIgor Mammedov                    value, min, max);
886de05005bSIgor Mammedov         return;
887de05005bSIgor Mammedov     }
888de05005bSIgor Mammedov     cpu->env.def.nwindows = value;
889de05005bSIgor Mammedov }
890de05005bSIgor Mammedov 
891de05005bSIgor Mammedov static PropertyInfo qdev_prop_nwindows = {
892de05005bSIgor Mammedov     .name  = "int",
893de05005bSIgor Mammedov     .get   = sparc_get_nwindows,
894de05005bSIgor Mammedov     .set   = sparc_set_nwindows,
895de05005bSIgor Mammedov };
896de05005bSIgor Mammedov 
897de05005bSIgor Mammedov static Property sparc_cpu_properties[] = {
898de05005bSIgor Mammedov     DEFINE_PROP_BIT("float",    SPARCCPU, env.def.features, 0, false),
899de05005bSIgor Mammedov     DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
900de05005bSIgor Mammedov     DEFINE_PROP_BIT("swap",     SPARCCPU, env.def.features, 2, false),
901de05005bSIgor Mammedov     DEFINE_PROP_BIT("mul",      SPARCCPU, env.def.features, 3, false),
902de05005bSIgor Mammedov     DEFINE_PROP_BIT("div",      SPARCCPU, env.def.features, 4, false),
903de05005bSIgor Mammedov     DEFINE_PROP_BIT("flush",    SPARCCPU, env.def.features, 5, false),
904de05005bSIgor Mammedov     DEFINE_PROP_BIT("fsqrt",    SPARCCPU, env.def.features, 6, false),
905de05005bSIgor Mammedov     DEFINE_PROP_BIT("fmul",     SPARCCPU, env.def.features, 7, false),
906de05005bSIgor Mammedov     DEFINE_PROP_BIT("vis1",     SPARCCPU, env.def.features, 8, false),
907de05005bSIgor Mammedov     DEFINE_PROP_BIT("vis2",     SPARCCPU, env.def.features, 9, false),
908de05005bSIgor Mammedov     DEFINE_PROP_BIT("fsmuld",   SPARCCPU, env.def.features, 10, false),
909de05005bSIgor Mammedov     DEFINE_PROP_BIT("hypv",     SPARCCPU, env.def.features, 11, false),
910de05005bSIgor Mammedov     DEFINE_PROP_BIT("cmt",      SPARCCPU, env.def.features, 12, false),
911de05005bSIgor Mammedov     DEFINE_PROP_BIT("gl",       SPARCCPU, env.def.features, 13, false),
912de05005bSIgor Mammedov     DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
913de05005bSIgor Mammedov                          qdev_prop_uint64, target_ulong),
914de05005bSIgor Mammedov     DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
915de05005bSIgor Mammedov     DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
916de05005bSIgor Mammedov     { .name  = "nwindows", .info  = &qdev_prop_nwindows },
917de05005bSIgor Mammedov     DEFINE_PROP_END_OF_LIST()
918de05005bSIgor Mammedov };
919de05005bSIgor Mammedov 
920ab7ab3d7SAndreas Färber static void sparc_cpu_class_init(ObjectClass *oc, void *data)
921ab7ab3d7SAndreas Färber {
922ab7ab3d7SAndreas Färber     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
923ab7ab3d7SAndreas Färber     CPUClass *cc = CPU_CLASS(oc);
924b6e91ebfSAndreas Färber     DeviceClass *dc = DEVICE_CLASS(oc);
925b6e91ebfSAndreas Färber 
926b6e91ebfSAndreas Färber     scc->parent_realize = dc->realize;
927b6e91ebfSAndreas Färber     dc->realize = sparc_cpu_realizefn;
928de05005bSIgor Mammedov     dc->props = sparc_cpu_properties;
929ab7ab3d7SAndreas Färber 
930ab7ab3d7SAndreas Färber     scc->parent_reset = cc->reset;
931ab7ab3d7SAndreas Färber     cc->reset = sparc_cpu_reset;
93297a8ea5aSAndreas Färber 
93312a6c15eSIgor Mammedov     cc->class_by_name = sparc_cpu_class_by_name;
9348c2e1b00SAndreas Färber     cc->has_work = sparc_cpu_has_work;
93597a8ea5aSAndreas Färber     cc->do_interrupt = sparc_cpu_do_interrupt;
93687afe467SRichard Henderson     cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
937878096eeSAndreas Färber     cc->dump_state = sparc_cpu_dump_state;
938f3659eeeSAndreas Färber #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
939f3659eeeSAndreas Färber     cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
940f3659eeeSAndreas Färber #endif
941f45748f1SAndreas Färber     cc->set_pc = sparc_cpu_set_pc;
942bdf7ae5bSAndreas Färber     cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
9435b50e790SAndreas Färber     cc->gdb_read_register = sparc_cpu_gdb_read_register;
9445b50e790SAndreas Färber     cc->gdb_write_register = sparc_cpu_gdb_write_register;
9457510454eSAndreas Färber #ifdef CONFIG_USER_ONLY
9467510454eSAndreas Färber     cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
9477510454eSAndreas Färber #else
94800b941e5SAndreas Färber     cc->do_unassigned_access = sparc_cpu_unassigned_access;
94993e22326SPaolo Bonzini     cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
95000b941e5SAndreas Färber     cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
951df32c8d4SJuan Quintela     cc->vmsd = &vmstate_sparc_cpu;
95200b941e5SAndreas Färber #endif
953df0900ebSPeter Crosthwaite     cc->disas_set_info = cpu_sparc_disas_set_info;
954a0e372f0SAndreas Färber 
955a0e372f0SAndreas Färber #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
956a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 86;
957a0e372f0SAndreas Färber #else
958a0e372f0SAndreas Färber     cc->gdb_num_core_regs = 72;
959a0e372f0SAndreas Färber #endif
960ab7ab3d7SAndreas Färber }
961ab7ab3d7SAndreas Färber 
962ab7ab3d7SAndreas Färber static const TypeInfo sparc_cpu_type_info = {
963ab7ab3d7SAndreas Färber     .name = TYPE_SPARC_CPU,
964ab7ab3d7SAndreas Färber     .parent = TYPE_CPU,
965ab7ab3d7SAndreas Färber     .instance_size = sizeof(SPARCCPU),
966ab7ab3d7SAndreas Färber     .instance_init = sparc_cpu_initfn,
96712a6c15eSIgor Mammedov     .abstract = true,
968ab7ab3d7SAndreas Färber     .class_size = sizeof(SPARCCPUClass),
969ab7ab3d7SAndreas Färber     .class_init = sparc_cpu_class_init,
970ab7ab3d7SAndreas Färber };
971ab7ab3d7SAndreas Färber 
97212a6c15eSIgor Mammedov static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
97312a6c15eSIgor Mammedov {
97412a6c15eSIgor Mammedov     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
97512a6c15eSIgor Mammedov     scc->cpu_def = data;
97612a6c15eSIgor Mammedov }
97712a6c15eSIgor Mammedov 
97812a6c15eSIgor Mammedov static void sparc_register_cpudef_type(const struct sparc_def_t *def)
97912a6c15eSIgor Mammedov {
98012a6c15eSIgor Mammedov     char *typename = sparc_cpu_type_name(def->name);
98112a6c15eSIgor Mammedov     TypeInfo ti = {
98212a6c15eSIgor Mammedov         .name = typename,
98312a6c15eSIgor Mammedov         .parent = TYPE_SPARC_CPU,
98412a6c15eSIgor Mammedov         .class_init = sparc_cpu_cpudef_class_init,
98512a6c15eSIgor Mammedov         .class_data = (void *)def,
98612a6c15eSIgor Mammedov     };
98712a6c15eSIgor Mammedov 
98812a6c15eSIgor Mammedov     type_register(&ti);
98912a6c15eSIgor Mammedov     g_free(typename);
99012a6c15eSIgor Mammedov }
99112a6c15eSIgor Mammedov 
992ab7ab3d7SAndreas Färber static void sparc_cpu_register_types(void)
993ab7ab3d7SAndreas Färber {
99412a6c15eSIgor Mammedov     int i;
99512a6c15eSIgor Mammedov 
996ab7ab3d7SAndreas Färber     type_register_static(&sparc_cpu_type_info);
99712a6c15eSIgor Mammedov     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
99812a6c15eSIgor Mammedov         sparc_register_cpudef_type(&sparc_defs[i]);
99912a6c15eSIgor Mammedov     }
1000ab7ab3d7SAndreas Färber }
1001ab7ab3d7SAndreas Färber 
1002ab7ab3d7SAndreas Färber type_init(sparc_cpu_register_types)
1003