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