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