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