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