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