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