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