1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * QEMU Motorola 68k CPU 3fcf5ef2aSThomas Huth * 4fcf5ef2aSThomas Huth * Copyright (c) 2012 SUSE LINUX Products GmbH 5fcf5ef2aSThomas Huth * 6fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 7fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 8fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 9fcf5ef2aSThomas Huth * version 2.1 of the License, or (at your option) any later version. 10fcf5ef2aSThomas Huth * 11fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14fcf5ef2aSThomas Huth * Lesser General Public License for more details. 15fcf5ef2aSThomas Huth * 16fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 17fcf5ef2aSThomas Huth * License along with this library; if not, see 18fcf5ef2aSThomas Huth * <http://www.gnu.org/licenses/lgpl-2.1.html> 19fcf5ef2aSThomas Huth */ 20fcf5ef2aSThomas Huth 21fcf5ef2aSThomas Huth #include "qemu/osdep.h" 22fcf5ef2aSThomas Huth #include "qapi/error.h" 23fcf5ef2aSThomas Huth #include "cpu.h" 24fcf5ef2aSThomas Huth #include "migration/vmstate.h" 2524f91e81SAlex Bennée #include "fpu/softfloat.h" 26fcf5ef2aSThomas Huth 27fcf5ef2aSThomas Huth static void m68k_cpu_set_pc(CPUState *cs, vaddr value) 28fcf5ef2aSThomas Huth { 29fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(cs); 30fcf5ef2aSThomas Huth 31fcf5ef2aSThomas Huth cpu->env.pc = value; 32fcf5ef2aSThomas Huth } 33fcf5ef2aSThomas Huth 34e4fdf9dfSRichard Henderson static vaddr m68k_cpu_get_pc(CPUState *cs) 35e4fdf9dfSRichard Henderson { 36e4fdf9dfSRichard Henderson M68kCPU *cpu = M68K_CPU(cs); 37e4fdf9dfSRichard Henderson 38e4fdf9dfSRichard Henderson return cpu->env.pc; 39e4fdf9dfSRichard Henderson } 40e4fdf9dfSRichard Henderson 41584fd342SRichard Henderson static void m68k_restore_state_to_opc(CPUState *cs, 42584fd342SRichard Henderson const TranslationBlock *tb, 43584fd342SRichard Henderson const uint64_t *data) 44584fd342SRichard Henderson { 45584fd342SRichard Henderson M68kCPU *cpu = M68K_CPU(cs); 46584fd342SRichard Henderson int cc_op = data[1]; 47584fd342SRichard Henderson 48584fd342SRichard Henderson cpu->env.pc = data[0]; 49584fd342SRichard Henderson if (cc_op != CC_OP_DYNAMIC) { 50584fd342SRichard Henderson cpu->env.cc_op = cc_op; 51584fd342SRichard Henderson } 52584fd342SRichard Henderson } 53584fd342SRichard Henderson 54fcf5ef2aSThomas Huth static bool m68k_cpu_has_work(CPUState *cs) 55fcf5ef2aSThomas Huth { 56fcf5ef2aSThomas Huth return cs->interrupt_request & CPU_INTERRUPT_HARD; 57fcf5ef2aSThomas Huth } 58fcf5ef2aSThomas Huth 59*a5a2d7f6SRichard Henderson static int m68k_cpu_mmu_index(CPUState *cs, bool ifetch) 60*a5a2d7f6SRichard Henderson { 61*a5a2d7f6SRichard Henderson return cpu_env(cs)->sr & SR_S ? MMU_KERNEL_IDX : MMU_USER_IDX; 62*a5a2d7f6SRichard Henderson } 63*a5a2d7f6SRichard Henderson 64fcf5ef2aSThomas Huth static void m68k_set_feature(CPUM68KState *env, int feature) 65fcf5ef2aSThomas Huth { 662dc7bf63SMark Cave-Ayland env->features |= BIT_ULL(feature); 67fcf5ef2aSThomas Huth } 68fcf5ef2aSThomas Huth 694ecce5fbSLucien Murray-Pitts static void m68k_unset_feature(CPUM68KState *env, int feature) 704ecce5fbSLucien Murray-Pitts { 712dc7bf63SMark Cave-Ayland env->features &= ~BIT_ULL(feature); 724ecce5fbSLucien Murray-Pitts } 734ecce5fbSLucien Murray-Pitts 74bf90b345SPeter Maydell static void m68k_cpu_reset_hold(Object *obj) 75fcf5ef2aSThomas Huth { 76bf90b345SPeter Maydell CPUState *s = CPU(obj); 77fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(s); 78fcf5ef2aSThomas Huth M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu); 79fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 80f83311e4SLaurent Vivier floatx80 nan = floatx80_default_nan(NULL); 81f4a6ce51SLaurent Vivier int i; 82fcf5ef2aSThomas Huth 83bf90b345SPeter Maydell if (mcc->parent_phases.hold) { 84bf90b345SPeter Maydell mcc->parent_phases.hold(obj); 85bf90b345SPeter Maydell } 86fcf5ef2aSThomas Huth 871f5c00cfSAlex Bennée memset(env, 0, offsetof(CPUM68KState, end_reset_fields)); 886a140586SPhilippe Mathieu-Daudé #ifdef CONFIG_USER_ONLY 896e22b28eSLaurent Vivier cpu_m68k_set_sr(env, 0); 906a140586SPhilippe Mathieu-Daudé #else 916a140586SPhilippe Mathieu-Daudé cpu_m68k_set_sr(env, SR_S | SR_I); 92fcf5ef2aSThomas Huth #endif 93f4a6ce51SLaurent Vivier for (i = 0; i < 8; i++) { 94f83311e4SLaurent Vivier env->fregs[i].d = nan; 95f4a6ce51SLaurent Vivier } 96ba624944SLaurent Vivier cpu_m68k_set_fpcr(env, 0); 97f4a6ce51SLaurent Vivier env->fpsr = 0; 98f4a6ce51SLaurent Vivier 99fcf5ef2aSThomas Huth /* TODO: We should set PC from the interrupt vector. */ 100fcf5ef2aSThomas Huth env->pc = 0; 101fcf5ef2aSThomas Huth } 102fcf5ef2aSThomas Huth 103fcf5ef2aSThomas Huth static void m68k_cpu_disas_set_info(CPUState *s, disassemble_info *info) 104fcf5ef2aSThomas Huth { 105fcf5ef2aSThomas Huth info->print_insn = print_insn_m68k; 10612629fcfSRichard Henderson info->mach = 0; 107fcf5ef2aSThomas Huth } 108fcf5ef2aSThomas Huth 109fcf5ef2aSThomas Huth /* CPU models */ 110fcf5ef2aSThomas Huth 111fcf5ef2aSThomas Huth static ObjectClass *m68k_cpu_class_by_name(const char *cpu_model) 112fcf5ef2aSThomas Huth { 113fcf5ef2aSThomas Huth ObjectClass *oc; 114fcf5ef2aSThomas Huth char *typename; 115fcf5ef2aSThomas Huth 116f61797bdSIgor Mammedov typename = g_strdup_printf(M68K_CPU_TYPE_NAME("%s"), cpu_model); 117fcf5ef2aSThomas Huth oc = object_class_by_name(typename); 118fcf5ef2aSThomas Huth g_free(typename); 119d5be19f5SPhilippe Mathieu-Daudé 120fcf5ef2aSThomas Huth return oc; 121fcf5ef2aSThomas Huth } 122fcf5ef2aSThomas Huth 123fcf5ef2aSThomas Huth static void m5206_cpu_initfn(Object *obj) 124fcf5ef2aSThomas Huth { 125fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(obj); 126fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 127fcf5ef2aSThomas Huth 128fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 129b342e56bSMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); 130fcf5ef2aSThomas Huth } 131fcf5ef2aSThomas Huth 132ee2fc6c6SLucien Murray-Pitts /* Base feature set, including isns. for m68k family */ 133fcf5ef2aSThomas Huth static void m68000_cpu_initfn(Object *obj) 134fcf5ef2aSThomas Huth { 135fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(obj); 136fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 137fcf5ef2aSThomas Huth 138aece90d8SMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_M68K); 139fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_USP); 140fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); 1411226e212SPavel Dovgalyuk m68k_set_feature(env, M68K_FEATURE_MOVEP); 142fcf5ef2aSThomas Huth } 143fcf5ef2aSThomas Huth 1444ecce5fbSLucien Murray-Pitts /* 1454ecce5fbSLucien Murray-Pitts * Adds BKPT, MOVE-from-SR *now priv instr, and MOVEC, MOVES, RTD 1464ecce5fbSLucien Murray-Pitts */ 1474ecce5fbSLucien Murray-Pitts static void m68010_cpu_initfn(Object *obj) 148fcf5ef2aSThomas Huth { 1494ecce5fbSLucien Murray-Pitts M68kCPU *cpu = M68K_CPU(obj); 1504ecce5fbSLucien Murray-Pitts CPUM68KState *env = &cpu->env; 1514ecce5fbSLucien Murray-Pitts 1524ecce5fbSLucien Murray-Pitts m68000_cpu_initfn(obj); 1534ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_M68010); 15418059c9eSLaurent Vivier m68k_set_feature(env, M68K_FEATURE_RTD); 1554ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_BKPT); 1568df0e6aeSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_MOVEC); 157b342e56bSMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); 158fcf5ef2aSThomas Huth } 15918b6102eSLaurent Vivier 160ee2fc6c6SLucien Murray-Pitts /* 161ee2fc6c6SLucien Murray-Pitts * Adds BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, CAS, CAS2, 162ee2fc6c6SLucien Murray-Pitts * CHK2, CMP2, DIVSL, DIVUL, EXTB, PACK, TRAPcc, UNPK. 163ee2fc6c6SLucien Murray-Pitts * 164ee2fc6c6SLucien Murray-Pitts * 68020/30 only: 165ee2fc6c6SLucien Murray-Pitts * CALLM, cpBcc, cpDBcc, cpGEN, cpRESTORE, cpSAVE, cpScc, cpTRAPcc 166ee2fc6c6SLucien Murray-Pitts */ 16718b6102eSLaurent Vivier static void m68020_cpu_initfn(Object *obj) 16818b6102eSLaurent Vivier { 16918b6102eSLaurent Vivier M68kCPU *cpu = M68K_CPU(obj); 17018b6102eSLaurent Vivier CPUM68KState *env = &cpu->env; 17118b6102eSLaurent Vivier 1724ecce5fbSLucien Murray-Pitts m68010_cpu_initfn(obj); 1734ecce5fbSLucien Murray-Pitts m68k_unset_feature(env, M68K_FEATURE_M68010); 17418b6102eSLaurent Vivier m68k_set_feature(env, M68K_FEATURE_M68020); 1754ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV); 1764ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_BRAL); 1774ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_BCCL); 1784ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_BITFIELD); 1794ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_EXT_FULL); 1804ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); 1814ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); 1824ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_FPU); 1834ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_CAS); 1844ecce5fbSLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_CHK2); 1857525a9b9SLucien Murray-Pitts m68k_set_feature(env, M68K_FEATURE_MSP); 186a9431a03SMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_UNALIGNED_DATA); 187aeeb90afSRichard Henderson m68k_set_feature(env, M68K_FEATURE_TRAPCC); 18818b6102eSLaurent Vivier } 18918b6102eSLaurent Vivier 190ee2fc6c6SLucien Murray-Pitts /* 191ee2fc6c6SLucien Murray-Pitts * Adds: PFLUSH (*5) 192ee2fc6c6SLucien Murray-Pitts * 68030 Only: PFLUSHA (*5), PLOAD (*5), PMOVE 193ee2fc6c6SLucien Murray-Pitts * 68030/40 Only: PTEST 194ee2fc6c6SLucien Murray-Pitts * 195ee2fc6c6SLucien Murray-Pitts * NOTES: 196ee2fc6c6SLucien Murray-Pitts * 5. Not valid on MC68EC030 197ee2fc6c6SLucien Murray-Pitts */ 19818b6102eSLaurent Vivier static void m68030_cpu_initfn(Object *obj) 19918b6102eSLaurent Vivier { 20018b6102eSLaurent Vivier M68kCPU *cpu = M68K_CPU(obj); 20118b6102eSLaurent Vivier CPUM68KState *env = &cpu->env; 20218b6102eSLaurent Vivier 2034ecce5fbSLucien Murray-Pitts m68020_cpu_initfn(obj); 2044ecce5fbSLucien Murray-Pitts m68k_unset_feature(env, M68K_FEATURE_M68020); 20518b6102eSLaurent Vivier m68k_set_feature(env, M68K_FEATURE_M68030); 20618b6102eSLaurent Vivier } 2079d4f0429SLaurent Vivier 208ee2fc6c6SLucien Murray-Pitts /* 209ee2fc6c6SLucien Murray-Pitts * Adds: CINV, CPUSH 210ee2fc6c6SLucien Murray-Pitts * Adds all with Note *2: FABS, FSABS, FDABS, FADD, FSADD, FDADD, FBcc, FCMP, 211ee2fc6c6SLucien Murray-Pitts * FDBcc, FDIV, FSDIV, FDDIV, FMOVE, FSMOVE, FDMOVE, 212ee2fc6c6SLucien Murray-Pitts * FMOVEM, FMUL, FSMUL, FDMUL, FNEG, FSNEG, FDNEG, FNOP, 213ee2fc6c6SLucien Murray-Pitts * FRESTORE, FSAVE, FScc, FSQRT, FSSQRT, FDSQRT, FSUB, 214ee2fc6c6SLucien Murray-Pitts * FSSUB, FDSUB, FTRAPcc, FTST 215ee2fc6c6SLucien Murray-Pitts * 216ee2fc6c6SLucien Murray-Pitts * Adds with Notes *2, and *3: FACOS, FASIN, FATAN, FATANH, FCOS, FCOSH, FETOX, 217ee2fc6c6SLucien Murray-Pitts * FETOXM, FGETEXP, FGETMAN, FINT, FINTRZ, FLOG10, 218ee2fc6c6SLucien Murray-Pitts * FLOG2, FLOGN, FLOGNP1, FMOD, FMOVECR, FREM, 219ee2fc6c6SLucien Murray-Pitts * FSCALE, FSGLDIV, FSGLMUL, FSIN, FSINCOS, FSINH, 220ee2fc6c6SLucien Murray-Pitts * FTAN, FTANH, FTENTOX, FTWOTOX 221ee2fc6c6SLucien Murray-Pitts * NOTES: 222ee2fc6c6SLucien Murray-Pitts * 2. Not applicable to the MC68EC040, MC68LC040, MC68EC060, and MC68LC060. 223ee2fc6c6SLucien Murray-Pitts * 3. These are software-supported instructions on the MC68040 and MC68060. 224ee2fc6c6SLucien Murray-Pitts */ 2259d4f0429SLaurent Vivier static void m68040_cpu_initfn(Object *obj) 2269d4f0429SLaurent Vivier { 2279d4f0429SLaurent Vivier M68kCPU *cpu = M68K_CPU(obj); 2289d4f0429SLaurent Vivier CPUM68KState *env = &cpu->env; 2299d4f0429SLaurent Vivier 2304ecce5fbSLucien Murray-Pitts m68030_cpu_initfn(obj); 2314ecce5fbSLucien Murray-Pitts m68k_unset_feature(env, M68K_FEATURE_M68030); 2329d4f0429SLaurent Vivier m68k_set_feature(env, M68K_FEATURE_M68040); 2339d4f0429SLaurent Vivier } 234fcf5ef2aSThomas Huth 235ee2fc6c6SLucien Murray-Pitts /* 236ee2fc6c6SLucien Murray-Pitts * Adds: PLPA 237ee2fc6c6SLucien Murray-Pitts * Adds all with Note *2: CAS, CAS2, MULS, MULU, CHK2, CMP2, DIVS, DIVU 238ee2fc6c6SLucien Murray-Pitts * All Fxxxx instructions are as per m68040 with exception to; FMOVEM NOTE3 239ee2fc6c6SLucien Murray-Pitts * 240ee2fc6c6SLucien Murray-Pitts * Does NOT implement MOVEP 241ee2fc6c6SLucien Murray-Pitts * 242ee2fc6c6SLucien Murray-Pitts * NOTES: 243ee2fc6c6SLucien Murray-Pitts * 2. Not applicable to the MC68EC040, MC68LC040, MC68EC060, and MC68LC060. 244ee2fc6c6SLucien Murray-Pitts * 3. These are software-supported instructions on the MC68040 and MC68060. 245ee2fc6c6SLucien Murray-Pitts */ 246fcf5ef2aSThomas Huth static void m68060_cpu_initfn(Object *obj) 247fcf5ef2aSThomas Huth { 248fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(obj); 249fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 250fcf5ef2aSThomas Huth 2514ecce5fbSLucien Murray-Pitts m68040_cpu_initfn(obj); 2524ecce5fbSLucien Murray-Pitts m68k_unset_feature(env, M68K_FEATURE_M68040); 25318b6102eSLaurent Vivier m68k_set_feature(env, M68K_FEATURE_M68060); 2544ecce5fbSLucien Murray-Pitts m68k_unset_feature(env, M68K_FEATURE_MOVEP); 2554ecce5fbSLucien Murray-Pitts 2564ecce5fbSLucien Murray-Pitts /* Implemented as a software feature */ 2574ecce5fbSLucien Murray-Pitts m68k_unset_feature(env, M68K_FEATURE_QUAD_MULDIV); 258fcf5ef2aSThomas Huth } 259fcf5ef2aSThomas Huth 260fcf5ef2aSThomas Huth static void m5208_cpu_initfn(Object *obj) 261fcf5ef2aSThomas Huth { 262fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(obj); 263fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 264fcf5ef2aSThomas Huth 265fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 266fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); 267fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_BRAL); 268fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_EMAC); 269fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_USP); 270b342e56bSMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); 271fcf5ef2aSThomas Huth } 272fcf5ef2aSThomas Huth 273fcf5ef2aSThomas Huth static void cfv4e_cpu_initfn(Object *obj) 274fcf5ef2aSThomas Huth { 275fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(obj); 276fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 277fcf5ef2aSThomas Huth 278fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 279fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); 280fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_BRAL); 281fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_FPU); 282fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_EMAC); 283fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_USP); 284b342e56bSMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); 285fcf5ef2aSThomas Huth } 286fcf5ef2aSThomas Huth 287fcf5ef2aSThomas Huth static void any_cpu_initfn(Object *obj) 288fcf5ef2aSThomas Huth { 289fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(obj); 290fcf5ef2aSThomas Huth CPUM68KState *env = &cpu->env; 291fcf5ef2aSThomas Huth 292fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); 293fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); 294fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); 295fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_BRAL); 296fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_FPU); 297808d77bcSLucien Murray-Pitts /* 298808d77bcSLucien Murray-Pitts * MAC and EMAC are mututally exclusive, so pick EMAC. 299808d77bcSLucien Murray-Pitts * It's mostly backwards compatible. 300808d77bcSLucien Murray-Pitts */ 301fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_EMAC); 302fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B); 303fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_USP); 304fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_EXT_FULL); 305fcf5ef2aSThomas Huth m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); 306b342e56bSMark Cave-Ayland m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); 307fcf5ef2aSThomas Huth } 308fcf5ef2aSThomas Huth 309fcf5ef2aSThomas Huth static void m68k_cpu_realizefn(DeviceState *dev, Error **errp) 310fcf5ef2aSThomas Huth { 311fcf5ef2aSThomas Huth CPUState *cs = CPU(dev); 312fcf5ef2aSThomas Huth M68kCPU *cpu = M68K_CPU(dev); 313fcf5ef2aSThomas Huth M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev); 314fcf5ef2aSThomas Huth Error *local_err = NULL; 315fcf5ef2aSThomas Huth 316f47cf4e3SIgor Mammedov register_m68k_insns(&cpu->env); 317f47cf4e3SIgor Mammedov 318fcf5ef2aSThomas Huth cpu_exec_realizefn(cs, &local_err); 319fcf5ef2aSThomas Huth if (local_err != NULL) { 320fcf5ef2aSThomas Huth error_propagate(errp, local_err); 321fcf5ef2aSThomas Huth return; 322fcf5ef2aSThomas Huth } 323fcf5ef2aSThomas Huth 324fcf5ef2aSThomas Huth m68k_cpu_init_gdb(cpu); 325fcf5ef2aSThomas Huth 326fcf5ef2aSThomas Huth cpu_reset(cs); 327fcf5ef2aSThomas Huth qemu_init_vcpu(cs); 328fcf5ef2aSThomas Huth 329fcf5ef2aSThomas Huth mcc->parent_realize(dev, errp); 330fcf5ef2aSThomas Huth } 331fcf5ef2aSThomas Huth 3326a140586SPhilippe Mathieu-Daudé #if !defined(CONFIG_USER_ONLY) 333d21f73c6SLaurent Vivier static bool fpu_needed(void *opaque) 334d21f73c6SLaurent Vivier { 335d21f73c6SLaurent Vivier M68kCPU *s = opaque; 336d21f73c6SLaurent Vivier 337d21f73c6SLaurent Vivier return m68k_feature(&s->env, M68K_FEATURE_CF_FPU) || 338d21f73c6SLaurent Vivier m68k_feature(&s->env, M68K_FEATURE_FPU); 339d21f73c6SLaurent Vivier } 340d21f73c6SLaurent Vivier 341d21f73c6SLaurent Vivier typedef struct m68k_FPReg_tmp { 342d21f73c6SLaurent Vivier FPReg *parent; 343d21f73c6SLaurent Vivier uint64_t tmp_mant; 344d21f73c6SLaurent Vivier uint16_t tmp_exp; 345d21f73c6SLaurent Vivier } m68k_FPReg_tmp; 346d21f73c6SLaurent Vivier 347d21f73c6SLaurent Vivier static void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f) 348d21f73c6SLaurent Vivier { 349d21f73c6SLaurent Vivier CPU_LDoubleU temp; 350d21f73c6SLaurent Vivier 351d21f73c6SLaurent Vivier temp.d = f; 352d21f73c6SLaurent Vivier *pmant = temp.l.lower; 353d21f73c6SLaurent Vivier *pexp = temp.l.upper; 354d21f73c6SLaurent Vivier } 355d21f73c6SLaurent Vivier 356d21f73c6SLaurent Vivier static floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper) 357d21f73c6SLaurent Vivier { 358d21f73c6SLaurent Vivier CPU_LDoubleU temp; 359d21f73c6SLaurent Vivier 360d21f73c6SLaurent Vivier temp.l.upper = upper; 361d21f73c6SLaurent Vivier temp.l.lower = mant; 362d21f73c6SLaurent Vivier return temp.d; 363d21f73c6SLaurent Vivier } 364d21f73c6SLaurent Vivier 365d21f73c6SLaurent Vivier static int freg_pre_save(void *opaque) 366d21f73c6SLaurent Vivier { 367d21f73c6SLaurent Vivier m68k_FPReg_tmp *tmp = opaque; 368d21f73c6SLaurent Vivier 369d21f73c6SLaurent Vivier cpu_get_fp80(&tmp->tmp_mant, &tmp->tmp_exp, tmp->parent->d); 370d21f73c6SLaurent Vivier 371d21f73c6SLaurent Vivier return 0; 372d21f73c6SLaurent Vivier } 373d21f73c6SLaurent Vivier 374d21f73c6SLaurent Vivier static int freg_post_load(void *opaque, int version) 375d21f73c6SLaurent Vivier { 376d21f73c6SLaurent Vivier m68k_FPReg_tmp *tmp = opaque; 377d21f73c6SLaurent Vivier 378d21f73c6SLaurent Vivier tmp->parent->d = cpu_set_fp80(tmp->tmp_mant, tmp->tmp_exp); 379d21f73c6SLaurent Vivier 380d21f73c6SLaurent Vivier return 0; 381d21f73c6SLaurent Vivier } 382d21f73c6SLaurent Vivier 383d21f73c6SLaurent Vivier static const VMStateDescription vmstate_freg_tmp = { 384d21f73c6SLaurent Vivier .name = "freg_tmp", 385d21f73c6SLaurent Vivier .post_load = freg_post_load, 386d21f73c6SLaurent Vivier .pre_save = freg_pre_save, 387f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 388d21f73c6SLaurent Vivier VMSTATE_UINT64(tmp_mant, m68k_FPReg_tmp), 389d21f73c6SLaurent Vivier VMSTATE_UINT16(tmp_exp, m68k_FPReg_tmp), 390d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 391d21f73c6SLaurent Vivier } 392d21f73c6SLaurent Vivier }; 393d21f73c6SLaurent Vivier 394d21f73c6SLaurent Vivier static const VMStateDescription vmstate_freg = { 395d21f73c6SLaurent Vivier .name = "freg", 396f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 397d21f73c6SLaurent Vivier VMSTATE_WITH_TMP(FPReg, m68k_FPReg_tmp, vmstate_freg_tmp), 398d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 399d21f73c6SLaurent Vivier } 400d21f73c6SLaurent Vivier }; 401d21f73c6SLaurent Vivier 402d21f73c6SLaurent Vivier static int fpu_post_load(void *opaque, int version) 403d21f73c6SLaurent Vivier { 404d21f73c6SLaurent Vivier M68kCPU *s = opaque; 405d21f73c6SLaurent Vivier 406d21f73c6SLaurent Vivier cpu_m68k_restore_fp_status(&s->env); 407d21f73c6SLaurent Vivier 408d21f73c6SLaurent Vivier return 0; 409d21f73c6SLaurent Vivier } 410d21f73c6SLaurent Vivier 411d21f73c6SLaurent Vivier const VMStateDescription vmmstate_fpu = { 412d21f73c6SLaurent Vivier .name = "cpu/fpu", 413d21f73c6SLaurent Vivier .version_id = 1, 414d21f73c6SLaurent Vivier .minimum_version_id = 1, 415d21f73c6SLaurent Vivier .needed = fpu_needed, 416d21f73c6SLaurent Vivier .post_load = fpu_post_load, 417f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 418d21f73c6SLaurent Vivier VMSTATE_UINT32(env.fpcr, M68kCPU), 419d21f73c6SLaurent Vivier VMSTATE_UINT32(env.fpsr, M68kCPU), 420d21f73c6SLaurent Vivier VMSTATE_STRUCT_ARRAY(env.fregs, M68kCPU, 8, 0, vmstate_freg, FPReg), 421d21f73c6SLaurent Vivier VMSTATE_STRUCT(env.fp_result, M68kCPU, 0, vmstate_freg, FPReg), 422d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 423d21f73c6SLaurent Vivier } 424d21f73c6SLaurent Vivier }; 425d21f73c6SLaurent Vivier 426d21f73c6SLaurent Vivier static bool cf_spregs_needed(void *opaque) 427d21f73c6SLaurent Vivier { 428d21f73c6SLaurent Vivier M68kCPU *s = opaque; 429d21f73c6SLaurent Vivier 430d21f73c6SLaurent Vivier return m68k_feature(&s->env, M68K_FEATURE_CF_ISA_A); 431d21f73c6SLaurent Vivier } 432d21f73c6SLaurent Vivier 433d21f73c6SLaurent Vivier const VMStateDescription vmstate_cf_spregs = { 434d21f73c6SLaurent Vivier .name = "cpu/cf_spregs", 435d21f73c6SLaurent Vivier .version_id = 1, 436d21f73c6SLaurent Vivier .minimum_version_id = 1, 437d21f73c6SLaurent Vivier .needed = cf_spregs_needed, 438f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 439d21f73c6SLaurent Vivier VMSTATE_UINT64_ARRAY(env.macc, M68kCPU, 4), 440d21f73c6SLaurent Vivier VMSTATE_UINT32(env.macsr, M68kCPU), 441d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mac_mask, M68kCPU), 442d21f73c6SLaurent Vivier VMSTATE_UINT32(env.rambar0, M68kCPU), 443d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mbar, M68kCPU), 444d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 445d21f73c6SLaurent Vivier } 446d21f73c6SLaurent Vivier }; 447d21f73c6SLaurent Vivier 448d21f73c6SLaurent Vivier static bool cpu_68040_mmu_needed(void *opaque) 449d21f73c6SLaurent Vivier { 450d21f73c6SLaurent Vivier M68kCPU *s = opaque; 451d21f73c6SLaurent Vivier 452d21f73c6SLaurent Vivier return m68k_feature(&s->env, M68K_FEATURE_M68040); 453d21f73c6SLaurent Vivier } 454d21f73c6SLaurent Vivier 455d21f73c6SLaurent Vivier const VMStateDescription vmstate_68040_mmu = { 456d21f73c6SLaurent Vivier .name = "cpu/68040_mmu", 457d21f73c6SLaurent Vivier .version_id = 1, 458d21f73c6SLaurent Vivier .minimum_version_id = 1, 459d21f73c6SLaurent Vivier .needed = cpu_68040_mmu_needed, 460f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 461d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mmu.ar, M68kCPU), 462d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mmu.ssw, M68kCPU), 463d21f73c6SLaurent Vivier VMSTATE_UINT16(env.mmu.tcr, M68kCPU), 464d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mmu.urp, M68kCPU), 465d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mmu.srp, M68kCPU), 466d21f73c6SLaurent Vivier VMSTATE_BOOL(env.mmu.fault, M68kCPU), 467d21f73c6SLaurent Vivier VMSTATE_UINT32_ARRAY(env.mmu.ttr, M68kCPU, 4), 468d21f73c6SLaurent Vivier VMSTATE_UINT32(env.mmu.mmusr, M68kCPU), 469d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 470d21f73c6SLaurent Vivier } 471d21f73c6SLaurent Vivier }; 472d21f73c6SLaurent Vivier 473d21f73c6SLaurent Vivier static bool cpu_68040_spregs_needed(void *opaque) 474d21f73c6SLaurent Vivier { 475d21f73c6SLaurent Vivier M68kCPU *s = opaque; 476d21f73c6SLaurent Vivier 477d21f73c6SLaurent Vivier return m68k_feature(&s->env, M68K_FEATURE_M68040); 478d21f73c6SLaurent Vivier } 479d21f73c6SLaurent Vivier 480d21f73c6SLaurent Vivier const VMStateDescription vmstate_68040_spregs = { 481d21f73c6SLaurent Vivier .name = "cpu/68040_spregs", 482d21f73c6SLaurent Vivier .version_id = 1, 483d21f73c6SLaurent Vivier .minimum_version_id = 1, 484d21f73c6SLaurent Vivier .needed = cpu_68040_spregs_needed, 485f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 486d21f73c6SLaurent Vivier VMSTATE_UINT32(env.vbr, M68kCPU), 487d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cacr, M68kCPU), 488d21f73c6SLaurent Vivier VMSTATE_UINT32(env.sfc, M68kCPU), 489d21f73c6SLaurent Vivier VMSTATE_UINT32(env.dfc, M68kCPU), 490d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 491d21f73c6SLaurent Vivier } 492d21f73c6SLaurent Vivier }; 493d21f73c6SLaurent Vivier 494fcf5ef2aSThomas Huth static const VMStateDescription vmstate_m68k_cpu = { 495fcf5ef2aSThomas Huth .name = "cpu", 496d21f73c6SLaurent Vivier .version_id = 1, 497d21f73c6SLaurent Vivier .minimum_version_id = 1, 498f3fb948fSRichard Henderson .fields = (const VMStateField[]) { 499d21f73c6SLaurent Vivier VMSTATE_UINT32_ARRAY(env.dregs, M68kCPU, 8), 500d21f73c6SLaurent Vivier VMSTATE_UINT32_ARRAY(env.aregs, M68kCPU, 8), 501d21f73c6SLaurent Vivier VMSTATE_UINT32(env.pc, M68kCPU), 502d21f73c6SLaurent Vivier VMSTATE_UINT32(env.sr, M68kCPU), 503d21f73c6SLaurent Vivier VMSTATE_INT32(env.current_sp, M68kCPU), 504d21f73c6SLaurent Vivier VMSTATE_UINT32_ARRAY(env.sp, M68kCPU, 3), 505d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cc_op, M68kCPU), 506d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cc_x, M68kCPU), 507d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cc_n, M68kCPU), 508d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cc_v, M68kCPU), 509d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cc_c, M68kCPU), 510d21f73c6SLaurent Vivier VMSTATE_UINT32(env.cc_z, M68kCPU), 511d21f73c6SLaurent Vivier VMSTATE_INT32(env.pending_vector, M68kCPU), 512d21f73c6SLaurent Vivier VMSTATE_INT32(env.pending_level, M68kCPU), 513d21f73c6SLaurent Vivier VMSTATE_END_OF_LIST() 514d21f73c6SLaurent Vivier }, 515f3fb948fSRichard Henderson .subsections = (const VMStateDescription * const []) { 516d21f73c6SLaurent Vivier &vmmstate_fpu, 517d21f73c6SLaurent Vivier &vmstate_cf_spregs, 518d21f73c6SLaurent Vivier &vmstate_68040_mmu, 519d21f73c6SLaurent Vivier &vmstate_68040_spregs, 520d21f73c6SLaurent Vivier NULL 521d21f73c6SLaurent Vivier }, 522fcf5ef2aSThomas Huth }; 523fcf5ef2aSThomas Huth 5248b80bd28SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h" 5258b80bd28SPhilippe Mathieu-Daudé 5268b80bd28SPhilippe Mathieu-Daudé static const struct SysemuCPUOps m68k_sysemu_ops = { 52708928c6dSPhilippe Mathieu-Daudé .get_phys_page_debug = m68k_cpu_get_phys_page_debug, 5288b80bd28SPhilippe Mathieu-Daudé }; 5296a140586SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */ 5308b80bd28SPhilippe Mathieu-Daudé 53178271684SClaudio Fontana #include "hw/core/tcg-cpu-ops.h" 53278271684SClaudio Fontana 5331764ad70SRichard Henderson static const TCGCPUOps m68k_tcg_ops = { 53478271684SClaudio Fontana .initialize = m68k_tcg_init, 535584fd342SRichard Henderson .restore_state_to_opc = m68k_restore_state_to_opc, 53678271684SClaudio Fontana 53778271684SClaudio Fontana #ifndef CONFIG_USER_ONLY 538028772c4SRichard Henderson .tlb_fill = m68k_cpu_tlb_fill, 539d5db810cSPhilippe Mathieu-Daudé .cpu_exec_interrupt = m68k_cpu_exec_interrupt, 54078271684SClaudio Fontana .do_interrupt = m68k_cpu_do_interrupt, 54178271684SClaudio Fontana .do_transaction_failed = m68k_cpu_transaction_failed, 54278271684SClaudio Fontana #endif /* !CONFIG_USER_ONLY */ 54378271684SClaudio Fontana }; 54478271684SClaudio Fontana 545fcf5ef2aSThomas Huth static void m68k_cpu_class_init(ObjectClass *c, void *data) 546fcf5ef2aSThomas Huth { 547fcf5ef2aSThomas Huth M68kCPUClass *mcc = M68K_CPU_CLASS(c); 548fcf5ef2aSThomas Huth CPUClass *cc = CPU_CLASS(c); 549fcf5ef2aSThomas Huth DeviceClass *dc = DEVICE_CLASS(c); 550bf90b345SPeter Maydell ResettableClass *rc = RESETTABLE_CLASS(c); 551fcf5ef2aSThomas Huth 552bf853881SPhilippe Mathieu-Daudé device_class_set_parent_realize(dc, m68k_cpu_realizefn, 553bf853881SPhilippe Mathieu-Daudé &mcc->parent_realize); 554bf90b345SPeter Maydell resettable_class_set_parent_phases(rc, NULL, m68k_cpu_reset_hold, NULL, 555bf90b345SPeter Maydell &mcc->parent_phases); 556fcf5ef2aSThomas Huth 557fcf5ef2aSThomas Huth cc->class_by_name = m68k_cpu_class_by_name; 558fcf5ef2aSThomas Huth cc->has_work = m68k_cpu_has_work; 559*a5a2d7f6SRichard Henderson cc->mmu_index = m68k_cpu_mmu_index; 560fcf5ef2aSThomas Huth cc->dump_state = m68k_cpu_dump_state; 561fcf5ef2aSThomas Huth cc->set_pc = m68k_cpu_set_pc; 562e4fdf9dfSRichard Henderson cc->get_pc = m68k_cpu_get_pc; 563fcf5ef2aSThomas Huth cc->gdb_read_register = m68k_cpu_gdb_read_register; 564fcf5ef2aSThomas Huth cc->gdb_write_register = m68k_cpu_gdb_write_register; 5656a140586SPhilippe Mathieu-Daudé #if !defined(CONFIG_USER_ONLY) 566d21f73c6SLaurent Vivier dc->vmsd = &vmstate_m68k_cpu; 5678b80bd28SPhilippe Mathieu-Daudé cc->sysemu_ops = &m68k_sysemu_ops; 568fcf5ef2aSThomas Huth #endif 569fcf5ef2aSThomas Huth cc->disas_set_info = m68k_cpu_disas_set_info; 570fcf5ef2aSThomas Huth 571fcf5ef2aSThomas Huth cc->gdb_num_core_regs = 18; 57278271684SClaudio Fontana cc->tcg_ops = &m68k_tcg_ops; 573fcf5ef2aSThomas Huth } 574fcf5ef2aSThomas Huth 575a976ed3fSKONRAD Frederic static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data) 576a976ed3fSKONRAD Frederic { 577a976ed3fSKONRAD Frederic CPUClass *cc = CPU_CLASS(c); 578a976ed3fSKONRAD Frederic 579a976ed3fSKONRAD Frederic cc->gdb_core_xml_file = "cf-core.xml"; 580a976ed3fSKONRAD Frederic } 581a976ed3fSKONRAD Frederic 582a976ed3fSKONRAD Frederic #define DEFINE_M68K_CPU_TYPE_CF(model) \ 583f61797bdSIgor Mammedov { \ 584a976ed3fSKONRAD Frederic .name = M68K_CPU_TYPE_NAME(#model), \ 585a976ed3fSKONRAD Frederic .instance_init = model##_cpu_initfn, \ 586f61797bdSIgor Mammedov .parent = TYPE_M68K_CPU, \ 587a976ed3fSKONRAD Frederic .class_init = m68k_cpu_class_init_cf_core \ 588a976ed3fSKONRAD Frederic } 589a976ed3fSKONRAD Frederic 590a976ed3fSKONRAD Frederic static void m68k_cpu_class_init_m68k_core(ObjectClass *c, void *data) 591a976ed3fSKONRAD Frederic { 592a976ed3fSKONRAD Frederic CPUClass *cc = CPU_CLASS(c); 593a976ed3fSKONRAD Frederic 594a976ed3fSKONRAD Frederic cc->gdb_core_xml_file = "m68k-core.xml"; 595a976ed3fSKONRAD Frederic } 596a976ed3fSKONRAD Frederic 597a976ed3fSKONRAD Frederic #define DEFINE_M68K_CPU_TYPE_M68K(model) \ 598a976ed3fSKONRAD Frederic { \ 599a976ed3fSKONRAD Frederic .name = M68K_CPU_TYPE_NAME(#model), \ 600a976ed3fSKONRAD Frederic .instance_init = model##_cpu_initfn, \ 601a976ed3fSKONRAD Frederic .parent = TYPE_M68K_CPU, \ 602a976ed3fSKONRAD Frederic .class_init = m68k_cpu_class_init_m68k_core \ 603fcf5ef2aSThomas Huth } 604fcf5ef2aSThomas Huth 605f61797bdSIgor Mammedov static const TypeInfo m68k_cpus_type_infos[] = { 606f61797bdSIgor Mammedov { /* base class should be registered first */ 607fcf5ef2aSThomas Huth .name = TYPE_M68K_CPU, 608fcf5ef2aSThomas Huth .parent = TYPE_CPU, 609fcf5ef2aSThomas Huth .instance_size = sizeof(M68kCPU), 610f669c992SRichard Henderson .instance_align = __alignof(M68kCPU), 611fcf5ef2aSThomas Huth .abstract = true, 612fcf5ef2aSThomas Huth .class_size = sizeof(M68kCPUClass), 613fcf5ef2aSThomas Huth .class_init = m68k_cpu_class_init, 614f61797bdSIgor Mammedov }, 615a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_M68K(m68000), 6164ecce5fbSLucien Murray-Pitts DEFINE_M68K_CPU_TYPE_M68K(m68010), 617a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_M68K(m68020), 618a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_M68K(m68030), 619a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_M68K(m68040), 620a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_M68K(m68060), 621a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_CF(m5206), 622a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_CF(m5208), 623a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_CF(cfv4e), 624a976ed3fSKONRAD Frederic DEFINE_M68K_CPU_TYPE_CF(any), 625fcf5ef2aSThomas Huth }; 626fcf5ef2aSThomas Huth 627f61797bdSIgor Mammedov DEFINE_TYPES(m68k_cpus_type_infos) 628