xref: /qemu/target/m68k/cpu.c (revision 8835ed32)
1 /*
2  * QEMU Motorola 68k CPU
3  *
4  * Copyright (c) 2012 SUSE LINUX Products GmbH
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see
18  * <http://www.gnu.org/licenses/lgpl-2.1.html>
19  */
20 
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "cpu.h"
24 #include "migration/vmstate.h"
25 #include "fpu/softfloat.h"
26 
27 static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
28 {
29     M68kCPU *cpu = M68K_CPU(cs);
30 
31     cpu->env.pc = value;
32 }
33 
34 static vaddr m68k_cpu_get_pc(CPUState *cs)
35 {
36     M68kCPU *cpu = M68K_CPU(cs);
37 
38     return cpu->env.pc;
39 }
40 
41 static void m68k_restore_state_to_opc(CPUState *cs,
42                                       const TranslationBlock *tb,
43                                       const uint64_t *data)
44 {
45     M68kCPU *cpu = M68K_CPU(cs);
46     int cc_op = data[1];
47 
48     cpu->env.pc = data[0];
49     if (cc_op != CC_OP_DYNAMIC) {
50         cpu->env.cc_op = cc_op;
51     }
52 }
53 
54 static bool m68k_cpu_has_work(CPUState *cs)
55 {
56     return cs->interrupt_request & CPU_INTERRUPT_HARD;
57 }
58 
59 static void m68k_set_feature(CPUM68KState *env, int feature)
60 {
61     env->features |= BIT_ULL(feature);
62 }
63 
64 static void m68k_unset_feature(CPUM68KState *env, int feature)
65 {
66     env->features &= ~BIT_ULL(feature);
67 }
68 
69 static void m68k_cpu_reset_hold(Object *obj)
70 {
71     CPUState *s = CPU(obj);
72     M68kCPU *cpu = M68K_CPU(s);
73     M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
74     CPUM68KState *env = &cpu->env;
75     floatx80 nan = floatx80_default_nan(NULL);
76     int i;
77 
78     if (mcc->parent_phases.hold) {
79         mcc->parent_phases.hold(obj);
80     }
81 
82     memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
83 #ifdef CONFIG_USER_ONLY
84     cpu_m68k_set_sr(env, 0);
85 #else
86     cpu_m68k_set_sr(env, SR_S | SR_I);
87 #endif
88     for (i = 0; i < 8; i++) {
89         env->fregs[i].d = nan;
90     }
91     cpu_m68k_set_fpcr(env, 0);
92     env->fpsr = 0;
93 
94     /* TODO: We should set PC from the interrupt vector.  */
95     env->pc = 0;
96 }
97 
98 static void m68k_cpu_disas_set_info(CPUState *s, disassemble_info *info)
99 {
100     info->print_insn = print_insn_m68k;
101     info->mach = 0;
102 }
103 
104 /* CPU models */
105 
106 static ObjectClass *m68k_cpu_class_by_name(const char *cpu_model)
107 {
108     ObjectClass *oc;
109     char *typename;
110 
111     typename = g_strdup_printf(M68K_CPU_TYPE_NAME("%s"), cpu_model);
112     oc = object_class_by_name(typename);
113     g_free(typename);
114 
115     return oc;
116 }
117 
118 static void m5206_cpu_initfn(Object *obj)
119 {
120     M68kCPU *cpu = M68K_CPU(obj);
121     CPUM68KState *env = &cpu->env;
122 
123     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
124     m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV);
125 }
126 
127 /* Base feature set, including isns. for m68k family */
128 static void m68000_cpu_initfn(Object *obj)
129 {
130     M68kCPU *cpu = M68K_CPU(obj);
131     CPUM68KState *env = &cpu->env;
132 
133     m68k_set_feature(env, M68K_FEATURE_M68K);
134     m68k_set_feature(env, M68K_FEATURE_USP);
135     m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
136     m68k_set_feature(env, M68K_FEATURE_MOVEP);
137 }
138 
139 /*
140  * Adds BKPT, MOVE-from-SR *now priv instr, and MOVEC, MOVES, RTD
141  */
142 static void m68010_cpu_initfn(Object *obj)
143 {
144     M68kCPU *cpu = M68K_CPU(obj);
145     CPUM68KState *env = &cpu->env;
146 
147     m68000_cpu_initfn(obj);
148     m68k_set_feature(env, M68K_FEATURE_M68010);
149     m68k_set_feature(env, M68K_FEATURE_RTD);
150     m68k_set_feature(env, M68K_FEATURE_BKPT);
151     m68k_set_feature(env, M68K_FEATURE_MOVEC);
152     m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV);
153 }
154 
155 /*
156  * Adds BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, CAS, CAS2,
157  *      CHK2, CMP2, DIVSL, DIVUL, EXTB, PACK, TRAPcc, UNPK.
158  *
159  * 68020/30 only:
160  *      CALLM, cpBcc, cpDBcc, cpGEN, cpRESTORE, cpSAVE, cpScc, cpTRAPcc
161  */
162 static void m68020_cpu_initfn(Object *obj)
163 {
164     M68kCPU *cpu = M68K_CPU(obj);
165     CPUM68KState *env = &cpu->env;
166 
167     m68010_cpu_initfn(obj);
168     m68k_unset_feature(env, M68K_FEATURE_M68010);
169     m68k_set_feature(env, M68K_FEATURE_M68020);
170     m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
171     m68k_set_feature(env, M68K_FEATURE_BRAL);
172     m68k_set_feature(env, M68K_FEATURE_BCCL);
173     m68k_set_feature(env, M68K_FEATURE_BITFIELD);
174     m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
175     m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
176     m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
177     m68k_set_feature(env, M68K_FEATURE_FPU);
178     m68k_set_feature(env, M68K_FEATURE_CAS);
179     m68k_set_feature(env, M68K_FEATURE_CHK2);
180     m68k_set_feature(env, M68K_FEATURE_MSP);
181     m68k_set_feature(env, M68K_FEATURE_UNALIGNED_DATA);
182     m68k_set_feature(env, M68K_FEATURE_TRAPCC);
183 }
184 
185 /*
186  * Adds: PFLUSH (*5)
187  * 68030 Only: PFLUSHA (*5), PLOAD (*5), PMOVE
188  * 68030/40 Only: PTEST
189  *
190  * NOTES:
191  *  5. Not valid on MC68EC030
192  */
193 static void m68030_cpu_initfn(Object *obj)
194 {
195     M68kCPU *cpu = M68K_CPU(obj);
196     CPUM68KState *env = &cpu->env;
197 
198     m68020_cpu_initfn(obj);
199     m68k_unset_feature(env, M68K_FEATURE_M68020);
200     m68k_set_feature(env, M68K_FEATURE_M68030);
201 }
202 
203 /*
204  * Adds: CINV, CPUSH
205  * Adds all with Note *2: FABS, FSABS, FDABS, FADD, FSADD, FDADD, FBcc, FCMP,
206  *                        FDBcc, FDIV, FSDIV, FDDIV, FMOVE, FSMOVE, FDMOVE,
207  *                        FMOVEM, FMUL, FSMUL, FDMUL, FNEG, FSNEG, FDNEG, FNOP,
208  *                        FRESTORE, FSAVE, FScc, FSQRT, FSSQRT, FDSQRT, FSUB,
209  *                        FSSUB, FDSUB, FTRAPcc, FTST
210  *
211  * Adds with Notes *2, and *3: FACOS, FASIN, FATAN, FATANH, FCOS, FCOSH, FETOX,
212  *                             FETOXM, FGETEXP, FGETMAN, FINT, FINTRZ, FLOG10,
213  *                             FLOG2, FLOGN, FLOGNP1, FMOD, FMOVECR, FREM,
214  *                             FSCALE, FSGLDIV, FSGLMUL, FSIN, FSINCOS, FSINH,
215  *                             FTAN, FTANH, FTENTOX, FTWOTOX
216  * NOTES:
217  * 2. Not applicable to the MC68EC040, MC68LC040, MC68EC060, and MC68LC060.
218  * 3. These are software-supported instructions on the MC68040 and MC68060.
219  */
220 static void m68040_cpu_initfn(Object *obj)
221 {
222     M68kCPU *cpu = M68K_CPU(obj);
223     CPUM68KState *env = &cpu->env;
224 
225     m68030_cpu_initfn(obj);
226     m68k_unset_feature(env, M68K_FEATURE_M68030);
227     m68k_set_feature(env, M68K_FEATURE_M68040);
228 }
229 
230 /*
231  * Adds: PLPA
232  * Adds all with Note *2: CAS, CAS2, MULS, MULU, CHK2, CMP2, DIVS, DIVU
233  * All Fxxxx instructions are as per m68040 with exception to; FMOVEM NOTE3
234  *
235  * Does NOT implement MOVEP
236  *
237  * NOTES:
238  * 2. Not applicable to the MC68EC040, MC68LC040, MC68EC060, and MC68LC060.
239  * 3. These are software-supported instructions on the MC68040 and MC68060.
240  */
241 static void m68060_cpu_initfn(Object *obj)
242 {
243     M68kCPU *cpu = M68K_CPU(obj);
244     CPUM68KState *env = &cpu->env;
245 
246     m68040_cpu_initfn(obj);
247     m68k_unset_feature(env, M68K_FEATURE_M68040);
248     m68k_set_feature(env, M68K_FEATURE_M68060);
249     m68k_unset_feature(env, M68K_FEATURE_MOVEP);
250 
251     /* Implemented as a software feature */
252     m68k_unset_feature(env, M68K_FEATURE_QUAD_MULDIV);
253 }
254 
255 static void m5208_cpu_initfn(Object *obj)
256 {
257     M68kCPU *cpu = M68K_CPU(obj);
258     CPUM68KState *env = &cpu->env;
259 
260     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
261     m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
262     m68k_set_feature(env, M68K_FEATURE_BRAL);
263     m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
264     m68k_set_feature(env, M68K_FEATURE_USP);
265     m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV);
266 }
267 
268 static void cfv4e_cpu_initfn(Object *obj)
269 {
270     M68kCPU *cpu = M68K_CPU(obj);
271     CPUM68KState *env = &cpu->env;
272 
273     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
274     m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
275     m68k_set_feature(env, M68K_FEATURE_BRAL);
276     m68k_set_feature(env, M68K_FEATURE_CF_FPU);
277     m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
278     m68k_set_feature(env, M68K_FEATURE_USP);
279     m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV);
280 }
281 
282 static void any_cpu_initfn(Object *obj)
283 {
284     M68kCPU *cpu = M68K_CPU(obj);
285     CPUM68KState *env = &cpu->env;
286 
287     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
288     m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
289     m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
290     m68k_set_feature(env, M68K_FEATURE_BRAL);
291     m68k_set_feature(env, M68K_FEATURE_CF_FPU);
292     /*
293      * MAC and EMAC are mututally exclusive, so pick EMAC.
294      * It's mostly backwards compatible.
295      */
296     m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
297     m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
298     m68k_set_feature(env, M68K_FEATURE_USP);
299     m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
300     m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
301     m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV);
302 }
303 
304 static void m68k_cpu_realizefn(DeviceState *dev, Error **errp)
305 {
306     CPUState *cs = CPU(dev);
307     M68kCPU *cpu = M68K_CPU(dev);
308     M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev);
309     Error *local_err = NULL;
310 
311     register_m68k_insns(&cpu->env);
312 
313     cpu_exec_realizefn(cs, &local_err);
314     if (local_err != NULL) {
315         error_propagate(errp, local_err);
316         return;
317     }
318 
319     m68k_cpu_init_gdb(cpu);
320 
321     cpu_reset(cs);
322     qemu_init_vcpu(cs);
323 
324     mcc->parent_realize(dev, errp);
325 }
326 
327 #if !defined(CONFIG_USER_ONLY)
328 static bool fpu_needed(void *opaque)
329 {
330     M68kCPU *s = opaque;
331 
332     return m68k_feature(&s->env, M68K_FEATURE_CF_FPU) ||
333            m68k_feature(&s->env, M68K_FEATURE_FPU);
334 }
335 
336 typedef struct m68k_FPReg_tmp {
337     FPReg *parent;
338     uint64_t tmp_mant;
339     uint16_t tmp_exp;
340 } m68k_FPReg_tmp;
341 
342 static void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
343 {
344     CPU_LDoubleU temp;
345 
346     temp.d = f;
347     *pmant = temp.l.lower;
348     *pexp = temp.l.upper;
349 }
350 
351 static floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
352 {
353     CPU_LDoubleU temp;
354 
355     temp.l.upper = upper;
356     temp.l.lower = mant;
357     return temp.d;
358 }
359 
360 static int freg_pre_save(void *opaque)
361 {
362     m68k_FPReg_tmp *tmp = opaque;
363 
364     cpu_get_fp80(&tmp->tmp_mant, &tmp->tmp_exp, tmp->parent->d);
365 
366     return 0;
367 }
368 
369 static int freg_post_load(void *opaque, int version)
370 {
371     m68k_FPReg_tmp *tmp = opaque;
372 
373     tmp->parent->d = cpu_set_fp80(tmp->tmp_mant, tmp->tmp_exp);
374 
375     return 0;
376 }
377 
378 static const VMStateDescription vmstate_freg_tmp = {
379     .name = "freg_tmp",
380     .post_load = freg_post_load,
381     .pre_save  = freg_pre_save,
382     .fields = (const VMStateField[]) {
383         VMSTATE_UINT64(tmp_mant, m68k_FPReg_tmp),
384         VMSTATE_UINT16(tmp_exp, m68k_FPReg_tmp),
385         VMSTATE_END_OF_LIST()
386     }
387 };
388 
389 static const VMStateDescription vmstate_freg = {
390     .name = "freg",
391     .fields = (const VMStateField[]) {
392         VMSTATE_WITH_TMP(FPReg, m68k_FPReg_tmp, vmstate_freg_tmp),
393         VMSTATE_END_OF_LIST()
394     }
395 };
396 
397 static int fpu_post_load(void *opaque, int version)
398 {
399     M68kCPU *s = opaque;
400 
401     cpu_m68k_restore_fp_status(&s->env);
402 
403     return 0;
404 }
405 
406 const VMStateDescription vmmstate_fpu = {
407     .name = "cpu/fpu",
408     .version_id = 1,
409     .minimum_version_id = 1,
410     .needed = fpu_needed,
411     .post_load = fpu_post_load,
412     .fields = (const VMStateField[]) {
413         VMSTATE_UINT32(env.fpcr, M68kCPU),
414         VMSTATE_UINT32(env.fpsr, M68kCPU),
415         VMSTATE_STRUCT_ARRAY(env.fregs, M68kCPU, 8, 0, vmstate_freg, FPReg),
416         VMSTATE_STRUCT(env.fp_result, M68kCPU, 0, vmstate_freg, FPReg),
417         VMSTATE_END_OF_LIST()
418     }
419 };
420 
421 static bool cf_spregs_needed(void *opaque)
422 {
423     M68kCPU *s = opaque;
424 
425     return m68k_feature(&s->env, M68K_FEATURE_CF_ISA_A);
426 }
427 
428 const VMStateDescription vmstate_cf_spregs = {
429     .name = "cpu/cf_spregs",
430     .version_id = 1,
431     .minimum_version_id = 1,
432     .needed = cf_spregs_needed,
433     .fields = (const VMStateField[]) {
434         VMSTATE_UINT64_ARRAY(env.macc, M68kCPU, 4),
435         VMSTATE_UINT32(env.macsr, M68kCPU),
436         VMSTATE_UINT32(env.mac_mask, M68kCPU),
437         VMSTATE_UINT32(env.rambar0, M68kCPU),
438         VMSTATE_UINT32(env.mbar, M68kCPU),
439         VMSTATE_END_OF_LIST()
440     }
441 };
442 
443 static bool cpu_68040_mmu_needed(void *opaque)
444 {
445     M68kCPU *s = opaque;
446 
447     return m68k_feature(&s->env, M68K_FEATURE_M68040);
448 }
449 
450 const VMStateDescription vmstate_68040_mmu = {
451     .name = "cpu/68040_mmu",
452     .version_id = 1,
453     .minimum_version_id = 1,
454     .needed = cpu_68040_mmu_needed,
455     .fields = (const VMStateField[]) {
456         VMSTATE_UINT32(env.mmu.ar, M68kCPU),
457         VMSTATE_UINT32(env.mmu.ssw, M68kCPU),
458         VMSTATE_UINT16(env.mmu.tcr, M68kCPU),
459         VMSTATE_UINT32(env.mmu.urp, M68kCPU),
460         VMSTATE_UINT32(env.mmu.srp, M68kCPU),
461         VMSTATE_BOOL(env.mmu.fault, M68kCPU),
462         VMSTATE_UINT32_ARRAY(env.mmu.ttr, M68kCPU, 4),
463         VMSTATE_UINT32(env.mmu.mmusr, M68kCPU),
464         VMSTATE_END_OF_LIST()
465     }
466 };
467 
468 static bool cpu_68040_spregs_needed(void *opaque)
469 {
470     M68kCPU *s = opaque;
471 
472     return m68k_feature(&s->env, M68K_FEATURE_M68040);
473 }
474 
475 const VMStateDescription vmstate_68040_spregs = {
476     .name = "cpu/68040_spregs",
477     .version_id = 1,
478     .minimum_version_id = 1,
479     .needed = cpu_68040_spregs_needed,
480     .fields = (const VMStateField[]) {
481         VMSTATE_UINT32(env.vbr, M68kCPU),
482         VMSTATE_UINT32(env.cacr, M68kCPU),
483         VMSTATE_UINT32(env.sfc, M68kCPU),
484         VMSTATE_UINT32(env.dfc, M68kCPU),
485         VMSTATE_END_OF_LIST()
486     }
487 };
488 
489 static const VMStateDescription vmstate_m68k_cpu = {
490     .name = "cpu",
491     .version_id = 1,
492     .minimum_version_id = 1,
493     .fields = (const VMStateField[]) {
494         VMSTATE_UINT32_ARRAY(env.dregs, M68kCPU, 8),
495         VMSTATE_UINT32_ARRAY(env.aregs, M68kCPU, 8),
496         VMSTATE_UINT32(env.pc, M68kCPU),
497         VMSTATE_UINT32(env.sr, M68kCPU),
498         VMSTATE_INT32(env.current_sp, M68kCPU),
499         VMSTATE_UINT32_ARRAY(env.sp, M68kCPU, 3),
500         VMSTATE_UINT32(env.cc_op, M68kCPU),
501         VMSTATE_UINT32(env.cc_x, M68kCPU),
502         VMSTATE_UINT32(env.cc_n, M68kCPU),
503         VMSTATE_UINT32(env.cc_v, M68kCPU),
504         VMSTATE_UINT32(env.cc_c, M68kCPU),
505         VMSTATE_UINT32(env.cc_z, M68kCPU),
506         VMSTATE_INT32(env.pending_vector, M68kCPU),
507         VMSTATE_INT32(env.pending_level, M68kCPU),
508         VMSTATE_END_OF_LIST()
509     },
510     .subsections = (const VMStateDescription * const []) {
511         &vmmstate_fpu,
512         &vmstate_cf_spregs,
513         &vmstate_68040_mmu,
514         &vmstate_68040_spregs,
515         NULL
516     },
517 };
518 
519 #include "hw/core/sysemu-cpu-ops.h"
520 
521 static const struct SysemuCPUOps m68k_sysemu_ops = {
522     .get_phys_page_debug = m68k_cpu_get_phys_page_debug,
523 };
524 #endif /* !CONFIG_USER_ONLY */
525 
526 #include "hw/core/tcg-cpu-ops.h"
527 
528 static const struct TCGCPUOps m68k_tcg_ops = {
529     .initialize = m68k_tcg_init,
530     .restore_state_to_opc = m68k_restore_state_to_opc,
531 
532 #ifndef CONFIG_USER_ONLY
533     .tlb_fill = m68k_cpu_tlb_fill,
534     .cpu_exec_interrupt = m68k_cpu_exec_interrupt,
535     .do_interrupt = m68k_cpu_do_interrupt,
536     .do_transaction_failed = m68k_cpu_transaction_failed,
537 #endif /* !CONFIG_USER_ONLY */
538 };
539 
540 static void m68k_cpu_class_init(ObjectClass *c, void *data)
541 {
542     M68kCPUClass *mcc = M68K_CPU_CLASS(c);
543     CPUClass *cc = CPU_CLASS(c);
544     DeviceClass *dc = DEVICE_CLASS(c);
545     ResettableClass *rc = RESETTABLE_CLASS(c);
546 
547     device_class_set_parent_realize(dc, m68k_cpu_realizefn,
548                                     &mcc->parent_realize);
549     resettable_class_set_parent_phases(rc, NULL, m68k_cpu_reset_hold, NULL,
550                                        &mcc->parent_phases);
551 
552     cc->class_by_name = m68k_cpu_class_by_name;
553     cc->has_work = m68k_cpu_has_work;
554     cc->dump_state = m68k_cpu_dump_state;
555     cc->set_pc = m68k_cpu_set_pc;
556     cc->get_pc = m68k_cpu_get_pc;
557     cc->gdb_read_register = m68k_cpu_gdb_read_register;
558     cc->gdb_write_register = m68k_cpu_gdb_write_register;
559 #if !defined(CONFIG_USER_ONLY)
560     dc->vmsd = &vmstate_m68k_cpu;
561     cc->sysemu_ops = &m68k_sysemu_ops;
562 #endif
563     cc->disas_set_info = m68k_cpu_disas_set_info;
564 
565     cc->gdb_num_core_regs = 18;
566     cc->tcg_ops = &m68k_tcg_ops;
567 }
568 
569 static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data)
570 {
571     CPUClass *cc = CPU_CLASS(c);
572 
573     cc->gdb_core_xml_file = "cf-core.xml";
574 }
575 
576 #define DEFINE_M68K_CPU_TYPE_CF(model)               \
577     {                                                \
578         .name = M68K_CPU_TYPE_NAME(#model),          \
579         .instance_init = model##_cpu_initfn,         \
580         .parent = TYPE_M68K_CPU,                     \
581         .class_init = m68k_cpu_class_init_cf_core    \
582     }
583 
584 static void m68k_cpu_class_init_m68k_core(ObjectClass *c, void *data)
585 {
586     CPUClass *cc = CPU_CLASS(c);
587 
588     cc->gdb_core_xml_file = "m68k-core.xml";
589 }
590 
591 #define DEFINE_M68K_CPU_TYPE_M68K(model)             \
592     {                                                \
593         .name = M68K_CPU_TYPE_NAME(#model),          \
594         .instance_init = model##_cpu_initfn,         \
595         .parent = TYPE_M68K_CPU,                     \
596         .class_init = m68k_cpu_class_init_m68k_core  \
597     }
598 
599 static const TypeInfo m68k_cpus_type_infos[] = {
600     { /* base class should be registered first */
601         .name = TYPE_M68K_CPU,
602         .parent = TYPE_CPU,
603         .instance_size = sizeof(M68kCPU),
604         .instance_align = __alignof(M68kCPU),
605         .abstract = true,
606         .class_size = sizeof(M68kCPUClass),
607         .class_init = m68k_cpu_class_init,
608     },
609     DEFINE_M68K_CPU_TYPE_M68K(m68000),
610     DEFINE_M68K_CPU_TYPE_M68K(m68010),
611     DEFINE_M68K_CPU_TYPE_M68K(m68020),
612     DEFINE_M68K_CPU_TYPE_M68K(m68030),
613     DEFINE_M68K_CPU_TYPE_M68K(m68040),
614     DEFINE_M68K_CPU_TYPE_M68K(m68060),
615     DEFINE_M68K_CPU_TYPE_CF(m5206),
616     DEFINE_M68K_CPU_TYPE_CF(m5208),
617     DEFINE_M68K_CPU_TYPE_CF(cfv4e),
618     DEFINE_M68K_CPU_TYPE_CF(any),
619 };
620 
621 DEFINE_TYPES(m68k_cpus_type_infos)
622