cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

cpu.c (17350B)


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