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