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