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