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 bool m68k_cpu_has_work(CPUState *cs) 35 { 36 return cs->interrupt_request & CPU_INTERRUPT_HARD; 37 } 38 39 static void m68k_set_feature(CPUM68KState *env, int feature) 40 { 41 env->features |= (1u << feature); 42 } 43 44 static void m68k_cpu_reset(DeviceState *dev) 45 { 46 CPUState *s = CPU(dev); 47 M68kCPU *cpu = M68K_CPU(s); 48 M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu); 49 CPUM68KState *env = &cpu->env; 50 floatx80 nan = floatx80_default_nan(NULL); 51 int i; 52 53 mcc->parent_reset(dev); 54 55 memset(env, 0, offsetof(CPUM68KState, end_reset_fields)); 56 #ifdef CONFIG_SOFTMMU 57 cpu_m68k_set_sr(env, SR_S | SR_I); 58 #else 59 cpu_m68k_set_sr(env, 0); 60 #endif 61 for (i = 0; i < 8; i++) { 62 env->fregs[i].d = nan; 63 } 64 cpu_m68k_set_fpcr(env, 0); 65 env->fpsr = 0; 66 67 /* TODO: We should set PC from the interrupt vector. */ 68 env->pc = 0; 69 } 70 71 static void m68k_cpu_disas_set_info(CPUState *s, disassemble_info *info) 72 { 73 M68kCPU *cpu = M68K_CPU(s); 74 CPUM68KState *env = &cpu->env; 75 info->print_insn = print_insn_m68k; 76 if (m68k_feature(env, M68K_FEATURE_M68000)) { 77 info->mach = bfd_mach_m68040; 78 } 79 } 80 81 /* CPU models */ 82 83 static ObjectClass *m68k_cpu_class_by_name(const char *cpu_model) 84 { 85 ObjectClass *oc; 86 char *typename; 87 88 typename = g_strdup_printf(M68K_CPU_TYPE_NAME("%s"), cpu_model); 89 oc = object_class_by_name(typename); 90 g_free(typename); 91 if (oc != NULL && (object_class_dynamic_cast(oc, TYPE_M68K_CPU) == NULL || 92 object_class_is_abstract(oc))) { 93 return NULL; 94 } 95 return oc; 96 } 97 98 static void m5206_cpu_initfn(Object *obj) 99 { 100 M68kCPU *cpu = M68K_CPU(obj); 101 CPUM68KState *env = &cpu->env; 102 103 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 104 } 105 106 static void m68000_cpu_initfn(Object *obj) 107 { 108 M68kCPU *cpu = M68K_CPU(obj); 109 CPUM68KState *env = &cpu->env; 110 111 m68k_set_feature(env, M68K_FEATURE_M68000); 112 m68k_set_feature(env, M68K_FEATURE_USP); 113 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); 114 m68k_set_feature(env, M68K_FEATURE_MOVEP); 115 } 116 117 /* common features for 68020, 68030 and 68040 */ 118 static void m680x0_cpu_common(CPUM68KState *env) 119 { 120 m68k_set_feature(env, M68K_FEATURE_M68000); 121 m68k_set_feature(env, M68K_FEATURE_USP); 122 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); 123 m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV); 124 m68k_set_feature(env, M68K_FEATURE_BRAL); 125 m68k_set_feature(env, M68K_FEATURE_BCCL); 126 m68k_set_feature(env, M68K_FEATURE_BITFIELD); 127 m68k_set_feature(env, M68K_FEATURE_EXT_FULL); 128 m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); 129 m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); 130 m68k_set_feature(env, M68K_FEATURE_FPU); 131 m68k_set_feature(env, M68K_FEATURE_CAS); 132 m68k_set_feature(env, M68K_FEATURE_BKPT); 133 m68k_set_feature(env, M68K_FEATURE_RTD); 134 m68k_set_feature(env, M68K_FEATURE_CHK2); 135 m68k_set_feature(env, M68K_FEATURE_MOVEP); 136 } 137 138 static void m68020_cpu_initfn(Object *obj) 139 { 140 M68kCPU *cpu = M68K_CPU(obj); 141 CPUM68KState *env = &cpu->env; 142 143 m680x0_cpu_common(env); 144 m68k_set_feature(env, M68K_FEATURE_M68020); 145 } 146 147 static void m68030_cpu_initfn(Object *obj) 148 { 149 M68kCPU *cpu = M68K_CPU(obj); 150 CPUM68KState *env = &cpu->env; 151 152 m680x0_cpu_common(env); 153 m68k_set_feature(env, M68K_FEATURE_M68030); 154 } 155 156 static void m68040_cpu_initfn(Object *obj) 157 { 158 M68kCPU *cpu = M68K_CPU(obj); 159 CPUM68KState *env = &cpu->env; 160 161 m680x0_cpu_common(env); 162 m68k_set_feature(env, M68K_FEATURE_M68040); 163 } 164 165 static void m68060_cpu_initfn(Object *obj) 166 { 167 M68kCPU *cpu = M68K_CPU(obj); 168 CPUM68KState *env = &cpu->env; 169 170 m68k_set_feature(env, M68K_FEATURE_M68000); 171 m68k_set_feature(env, M68K_FEATURE_USP); 172 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); 173 m68k_set_feature(env, M68K_FEATURE_BRAL); 174 m68k_set_feature(env, M68K_FEATURE_BCCL); 175 m68k_set_feature(env, M68K_FEATURE_BITFIELD); 176 m68k_set_feature(env, M68K_FEATURE_EXT_FULL); 177 m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); 178 m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); 179 m68k_set_feature(env, M68K_FEATURE_FPU); 180 m68k_set_feature(env, M68K_FEATURE_CAS); 181 m68k_set_feature(env, M68K_FEATURE_BKPT); 182 m68k_set_feature(env, M68K_FEATURE_RTD); 183 m68k_set_feature(env, M68K_FEATURE_CHK2); 184 m68k_set_feature(env, M68K_FEATURE_M68060); 185 } 186 187 static void m5208_cpu_initfn(Object *obj) 188 { 189 M68kCPU *cpu = M68K_CPU(obj); 190 CPUM68KState *env = &cpu->env; 191 192 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 193 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); 194 m68k_set_feature(env, M68K_FEATURE_BRAL); 195 m68k_set_feature(env, M68K_FEATURE_CF_EMAC); 196 m68k_set_feature(env, M68K_FEATURE_USP); 197 } 198 199 static void cfv4e_cpu_initfn(Object *obj) 200 { 201 M68kCPU *cpu = M68K_CPU(obj); 202 CPUM68KState *env = &cpu->env; 203 204 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 205 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); 206 m68k_set_feature(env, M68K_FEATURE_BRAL); 207 m68k_set_feature(env, M68K_FEATURE_CF_FPU); 208 m68k_set_feature(env, M68K_FEATURE_CF_EMAC); 209 m68k_set_feature(env, M68K_FEATURE_USP); 210 } 211 212 static void any_cpu_initfn(Object *obj) 213 { 214 M68kCPU *cpu = M68K_CPU(obj); 215 CPUM68KState *env = &cpu->env; 216 217 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 218 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); 219 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); 220 m68k_set_feature(env, M68K_FEATURE_BRAL); 221 m68k_set_feature(env, M68K_FEATURE_CF_FPU); 222 /* 223 * MAC and EMAC are mututally exclusive, so pick EMAC. 224 * It's mostly backwards compatible. 225 */ 226 m68k_set_feature(env, M68K_FEATURE_CF_EMAC); 227 m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B); 228 m68k_set_feature(env, M68K_FEATURE_USP); 229 m68k_set_feature(env, M68K_FEATURE_EXT_FULL); 230 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); 231 } 232 233 static void m68k_cpu_realizefn(DeviceState *dev, Error **errp) 234 { 235 CPUState *cs = CPU(dev); 236 M68kCPU *cpu = M68K_CPU(dev); 237 M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev); 238 Error *local_err = NULL; 239 240 register_m68k_insns(&cpu->env); 241 242 cpu_exec_realizefn(cs, &local_err); 243 if (local_err != NULL) { 244 error_propagate(errp, local_err); 245 return; 246 } 247 248 m68k_cpu_init_gdb(cpu); 249 250 cpu_reset(cs); 251 qemu_init_vcpu(cs); 252 253 mcc->parent_realize(dev, errp); 254 } 255 256 static void m68k_cpu_initfn(Object *obj) 257 { 258 M68kCPU *cpu = M68K_CPU(obj); 259 260 cpu_set_cpustate_pointers(cpu); 261 } 262 263 #if defined(CONFIG_SOFTMMU) 264 static bool fpu_needed(void *opaque) 265 { 266 M68kCPU *s = opaque; 267 268 return m68k_feature(&s->env, M68K_FEATURE_CF_FPU) || 269 m68k_feature(&s->env, M68K_FEATURE_FPU); 270 } 271 272 typedef struct m68k_FPReg_tmp { 273 FPReg *parent; 274 uint64_t tmp_mant; 275 uint16_t tmp_exp; 276 } m68k_FPReg_tmp; 277 278 static void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f) 279 { 280 CPU_LDoubleU temp; 281 282 temp.d = f; 283 *pmant = temp.l.lower; 284 *pexp = temp.l.upper; 285 } 286 287 static floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper) 288 { 289 CPU_LDoubleU temp; 290 291 temp.l.upper = upper; 292 temp.l.lower = mant; 293 return temp.d; 294 } 295 296 static int freg_pre_save(void *opaque) 297 { 298 m68k_FPReg_tmp *tmp = opaque; 299 300 cpu_get_fp80(&tmp->tmp_mant, &tmp->tmp_exp, tmp->parent->d); 301 302 return 0; 303 } 304 305 static int freg_post_load(void *opaque, int version) 306 { 307 m68k_FPReg_tmp *tmp = opaque; 308 309 tmp->parent->d = cpu_set_fp80(tmp->tmp_mant, tmp->tmp_exp); 310 311 return 0; 312 } 313 314 static const VMStateDescription vmstate_freg_tmp = { 315 .name = "freg_tmp", 316 .post_load = freg_post_load, 317 .pre_save = freg_pre_save, 318 .fields = (VMStateField[]) { 319 VMSTATE_UINT64(tmp_mant, m68k_FPReg_tmp), 320 VMSTATE_UINT16(tmp_exp, m68k_FPReg_tmp), 321 VMSTATE_END_OF_LIST() 322 } 323 }; 324 325 static const VMStateDescription vmstate_freg = { 326 .name = "freg", 327 .fields = (VMStateField[]) { 328 VMSTATE_WITH_TMP(FPReg, m68k_FPReg_tmp, vmstate_freg_tmp), 329 VMSTATE_END_OF_LIST() 330 } 331 }; 332 333 static int fpu_post_load(void *opaque, int version) 334 { 335 M68kCPU *s = opaque; 336 337 cpu_m68k_restore_fp_status(&s->env); 338 339 return 0; 340 } 341 342 const VMStateDescription vmmstate_fpu = { 343 .name = "cpu/fpu", 344 .version_id = 1, 345 .minimum_version_id = 1, 346 .needed = fpu_needed, 347 .post_load = fpu_post_load, 348 .fields = (VMStateField[]) { 349 VMSTATE_UINT32(env.fpcr, M68kCPU), 350 VMSTATE_UINT32(env.fpsr, M68kCPU), 351 VMSTATE_STRUCT_ARRAY(env.fregs, M68kCPU, 8, 0, vmstate_freg, FPReg), 352 VMSTATE_STRUCT(env.fp_result, M68kCPU, 0, vmstate_freg, FPReg), 353 VMSTATE_END_OF_LIST() 354 } 355 }; 356 357 static bool cf_spregs_needed(void *opaque) 358 { 359 M68kCPU *s = opaque; 360 361 return m68k_feature(&s->env, M68K_FEATURE_CF_ISA_A); 362 } 363 364 const VMStateDescription vmstate_cf_spregs = { 365 .name = "cpu/cf_spregs", 366 .version_id = 1, 367 .minimum_version_id = 1, 368 .needed = cf_spregs_needed, 369 .fields = (VMStateField[]) { 370 VMSTATE_UINT64_ARRAY(env.macc, M68kCPU, 4), 371 VMSTATE_UINT32(env.macsr, M68kCPU), 372 VMSTATE_UINT32(env.mac_mask, M68kCPU), 373 VMSTATE_UINT32(env.rambar0, M68kCPU), 374 VMSTATE_UINT32(env.mbar, M68kCPU), 375 VMSTATE_END_OF_LIST() 376 } 377 }; 378 379 static bool cpu_68040_mmu_needed(void *opaque) 380 { 381 M68kCPU *s = opaque; 382 383 return m68k_feature(&s->env, M68K_FEATURE_M68040); 384 } 385 386 const VMStateDescription vmstate_68040_mmu = { 387 .name = "cpu/68040_mmu", 388 .version_id = 1, 389 .minimum_version_id = 1, 390 .needed = cpu_68040_mmu_needed, 391 .fields = (VMStateField[]) { 392 VMSTATE_UINT32(env.mmu.ar, M68kCPU), 393 VMSTATE_UINT32(env.mmu.ssw, M68kCPU), 394 VMSTATE_UINT16(env.mmu.tcr, M68kCPU), 395 VMSTATE_UINT32(env.mmu.urp, M68kCPU), 396 VMSTATE_UINT32(env.mmu.srp, M68kCPU), 397 VMSTATE_BOOL(env.mmu.fault, M68kCPU), 398 VMSTATE_UINT32_ARRAY(env.mmu.ttr, M68kCPU, 4), 399 VMSTATE_UINT32(env.mmu.mmusr, M68kCPU), 400 VMSTATE_END_OF_LIST() 401 } 402 }; 403 404 static bool cpu_68040_spregs_needed(void *opaque) 405 { 406 M68kCPU *s = opaque; 407 408 return m68k_feature(&s->env, M68K_FEATURE_M68040); 409 } 410 411 const VMStateDescription vmstate_68040_spregs = { 412 .name = "cpu/68040_spregs", 413 .version_id = 1, 414 .minimum_version_id = 1, 415 .needed = cpu_68040_spregs_needed, 416 .fields = (VMStateField[]) { 417 VMSTATE_UINT32(env.vbr, M68kCPU), 418 VMSTATE_UINT32(env.cacr, M68kCPU), 419 VMSTATE_UINT32(env.sfc, M68kCPU), 420 VMSTATE_UINT32(env.dfc, M68kCPU), 421 VMSTATE_END_OF_LIST() 422 } 423 }; 424 425 static const VMStateDescription vmstate_m68k_cpu = { 426 .name = "cpu", 427 .version_id = 1, 428 .minimum_version_id = 1, 429 .fields = (VMStateField[]) { 430 VMSTATE_UINT32_ARRAY(env.dregs, M68kCPU, 8), 431 VMSTATE_UINT32_ARRAY(env.aregs, M68kCPU, 8), 432 VMSTATE_UINT32(env.pc, M68kCPU), 433 VMSTATE_UINT32(env.sr, M68kCPU), 434 VMSTATE_INT32(env.current_sp, M68kCPU), 435 VMSTATE_UINT32_ARRAY(env.sp, M68kCPU, 3), 436 VMSTATE_UINT32(env.cc_op, M68kCPU), 437 VMSTATE_UINT32(env.cc_x, M68kCPU), 438 VMSTATE_UINT32(env.cc_n, M68kCPU), 439 VMSTATE_UINT32(env.cc_v, M68kCPU), 440 VMSTATE_UINT32(env.cc_c, M68kCPU), 441 VMSTATE_UINT32(env.cc_z, M68kCPU), 442 VMSTATE_INT32(env.pending_vector, M68kCPU), 443 VMSTATE_INT32(env.pending_level, M68kCPU), 444 VMSTATE_END_OF_LIST() 445 }, 446 .subsections = (const VMStateDescription * []) { 447 &vmmstate_fpu, 448 &vmstate_cf_spregs, 449 &vmstate_68040_mmu, 450 &vmstate_68040_spregs, 451 NULL 452 }, 453 }; 454 #endif 455 456 static void m68k_cpu_class_init(ObjectClass *c, void *data) 457 { 458 M68kCPUClass *mcc = M68K_CPU_CLASS(c); 459 CPUClass *cc = CPU_CLASS(c); 460 DeviceClass *dc = DEVICE_CLASS(c); 461 462 device_class_set_parent_realize(dc, m68k_cpu_realizefn, 463 &mcc->parent_realize); 464 device_class_set_parent_reset(dc, m68k_cpu_reset, &mcc->parent_reset); 465 466 cc->class_by_name = m68k_cpu_class_by_name; 467 cc->has_work = m68k_cpu_has_work; 468 cc->tcg_ops.do_interrupt = m68k_cpu_do_interrupt; 469 cc->tcg_ops.cpu_exec_interrupt = m68k_cpu_exec_interrupt; 470 cc->dump_state = m68k_cpu_dump_state; 471 cc->set_pc = m68k_cpu_set_pc; 472 cc->gdb_read_register = m68k_cpu_gdb_read_register; 473 cc->gdb_write_register = m68k_cpu_gdb_write_register; 474 cc->tcg_ops.tlb_fill = m68k_cpu_tlb_fill; 475 #if defined(CONFIG_SOFTMMU) 476 cc->tcg_ops.do_transaction_failed = m68k_cpu_transaction_failed; 477 cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug; 478 dc->vmsd = &vmstate_m68k_cpu; 479 #endif 480 cc->disas_set_info = m68k_cpu_disas_set_info; 481 cc->tcg_ops.initialize = m68k_tcg_init; 482 483 cc->gdb_num_core_regs = 18; 484 } 485 486 static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data) 487 { 488 CPUClass *cc = CPU_CLASS(c); 489 490 cc->gdb_core_xml_file = "cf-core.xml"; 491 } 492 493 #define DEFINE_M68K_CPU_TYPE_CF(model) \ 494 { \ 495 .name = M68K_CPU_TYPE_NAME(#model), \ 496 .instance_init = model##_cpu_initfn, \ 497 .parent = TYPE_M68K_CPU, \ 498 .class_init = m68k_cpu_class_init_cf_core \ 499 } 500 501 static void m68k_cpu_class_init_m68k_core(ObjectClass *c, void *data) 502 { 503 CPUClass *cc = CPU_CLASS(c); 504 505 cc->gdb_core_xml_file = "m68k-core.xml"; 506 } 507 508 #define DEFINE_M68K_CPU_TYPE_M68K(model) \ 509 { \ 510 .name = M68K_CPU_TYPE_NAME(#model), \ 511 .instance_init = model##_cpu_initfn, \ 512 .parent = TYPE_M68K_CPU, \ 513 .class_init = m68k_cpu_class_init_m68k_core \ 514 } 515 516 static const TypeInfo m68k_cpus_type_infos[] = { 517 { /* base class should be registered first */ 518 .name = TYPE_M68K_CPU, 519 .parent = TYPE_CPU, 520 .instance_size = sizeof(M68kCPU), 521 .instance_init = m68k_cpu_initfn, 522 .abstract = true, 523 .class_size = sizeof(M68kCPUClass), 524 .class_init = m68k_cpu_class_init, 525 }, 526 DEFINE_M68K_CPU_TYPE_M68K(m68000), 527 DEFINE_M68K_CPU_TYPE_M68K(m68020), 528 DEFINE_M68K_CPU_TYPE_M68K(m68030), 529 DEFINE_M68K_CPU_TYPE_M68K(m68040), 530 DEFINE_M68K_CPU_TYPE_M68K(m68060), 531 DEFINE_M68K_CPU_TYPE_CF(m5206), 532 DEFINE_M68K_CPU_TYPE_CF(m5208), 533 DEFINE_M68K_CPU_TYPE_CF(cfv4e), 534 DEFINE_M68K_CPU_TYPE_CF(any), 535 }; 536 537 DEFINE_TYPES(m68k_cpus_type_infos) 538