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