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