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