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