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