qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

cpu.c (18071B)


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