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