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