cpu.c 21 KB

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