1e6e5906bSpbrook /* 2e6e5906bSpbrook * m68k op helpers 3e6e5906bSpbrook * 40633879fSpbrook * Copyright (c) 2006-2007 CodeSourcery 5e6e5906bSpbrook * Written by Paul Brook 6e6e5906bSpbrook * 7e6e5906bSpbrook * This library is free software; you can redistribute it and/or 8e6e5906bSpbrook * modify it under the terms of the GNU Lesser General Public 9e6e5906bSpbrook * License as published by the Free Software Foundation; either 10d749fb85SThomas Huth * version 2.1 of the License, or (at your option) any later version. 11e6e5906bSpbrook * 12e6e5906bSpbrook * This library is distributed in the hope that it will be useful, 13e6e5906bSpbrook * but WITHOUT ANY WARRANTY; without even the implied warranty of 14e6e5906bSpbrook * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15d749fb85SThomas Huth * Lesser General Public License for more details. 16e6e5906bSpbrook * 17e6e5906bSpbrook * You should have received a copy of the GNU Lesser General Public 188167ee88SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19e6e5906bSpbrook */ 20e6e5906bSpbrook 21d8416665SPeter Maydell #include "qemu/osdep.h" 22e6e5906bSpbrook #include "cpu.h" 2363c91552SPaolo Bonzini #include "exec/exec-all.h" 24022c62cbSPaolo Bonzini #include "exec/gdbstub.h" 252ef6175aSRichard Henderson #include "exec/helper-proto.h" 264ea5fe99SAlex Bennée #include "gdbstub/helpers.h" 2724f91e81SAlex Bennée #include "fpu/softfloat.h" 280442428aSMarkus Armbruster #include "qemu/qemu-print.h" 29e1f3808eSpbrook 30e1f3808eSpbrook #define SIGNBIT (1u << 31) 31e1f3808eSpbrook 3266260159SAkihiko Odaki static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n) 3356aebc89Spbrook { 3466260159SAkihiko Odaki M68kCPU *cpu = M68K_CPU(cs); 3566260159SAkihiko Odaki CPUM68KState *env = &cpu->env; 3666260159SAkihiko Odaki 3756aebc89Spbrook if (n < 8) { 38f83311e4SLaurent Vivier float_status s; 397ed51401SPeter Maydell return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s)); 4056aebc89Spbrook } 41ba624944SLaurent Vivier switch (n) { 42ba624944SLaurent Vivier case 8: /* fpcontrol */ 43462474d7SAlex Bennée return gdb_get_reg32(mem_buf, env->fpcr); 44ba624944SLaurent Vivier case 9: /* fpstatus */ 45462474d7SAlex Bennée return gdb_get_reg32(mem_buf, env->fpsr); 46ba624944SLaurent Vivier case 10: /* fpiar, not implemented */ 47462474d7SAlex Bennée return gdb_get_reg32(mem_buf, 0); 4856aebc89Spbrook } 4956aebc89Spbrook return 0; 5056aebc89Spbrook } 5156aebc89Spbrook 5266260159SAkihiko Odaki static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n) 5356aebc89Spbrook { 5466260159SAkihiko Odaki M68kCPU *cpu = M68K_CPU(cs); 5566260159SAkihiko Odaki CPUM68KState *env = &cpu->env; 5666260159SAkihiko Odaki 5756aebc89Spbrook if (n < 8) { 58f83311e4SLaurent Vivier float_status s; 597ed51401SPeter Maydell env->fregs[n].d = float64_to_floatx80(ldq_p(mem_buf), &s); 6056aebc89Spbrook return 8; 6156aebc89Spbrook } 62ba624944SLaurent Vivier switch (n) { 63ba624944SLaurent Vivier case 8: /* fpcontrol */ 64ba624944SLaurent Vivier cpu_m68k_set_fpcr(env, ldl_p(mem_buf)); 65ba624944SLaurent Vivier return 4; 66ba624944SLaurent Vivier case 9: /* fpstatus */ 67ba624944SLaurent Vivier env->fpsr = ldl_p(mem_buf); 68ba624944SLaurent Vivier return 4; 69ba624944SLaurent Vivier case 10: /* fpiar, not implemented */ 7056aebc89Spbrook return 4; 7156aebc89Spbrook } 7256aebc89Spbrook return 0; 7356aebc89Spbrook } 7456aebc89Spbrook 7566260159SAkihiko Odaki static int m68k_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n) 765a4526b2SLaurent Vivier { 7766260159SAkihiko Odaki M68kCPU *cpu = M68K_CPU(cs); 7866260159SAkihiko Odaki CPUM68KState *env = &cpu->env; 7966260159SAkihiko Odaki 805a4526b2SLaurent Vivier if (n < 8) { 81462474d7SAlex Bennée int len = gdb_get_reg16(mem_buf, env->fregs[n].l.upper); 824b27f9b0SPhilippe Mathieu-Daudé len += gdb_get_reg16(mem_buf, 0); 834b27f9b0SPhilippe Mathieu-Daudé len += gdb_get_reg64(mem_buf, env->fregs[n].l.lower); 84462474d7SAlex Bennée return len; 855a4526b2SLaurent Vivier } 865a4526b2SLaurent Vivier switch (n) { 875a4526b2SLaurent Vivier case 8: /* fpcontrol */ 88462474d7SAlex Bennée return gdb_get_reg32(mem_buf, env->fpcr); 895a4526b2SLaurent Vivier case 9: /* fpstatus */ 90*58883579SKeith Packard return gdb_get_reg32(mem_buf, cpu_m68k_get_fpsr(env)); 915a4526b2SLaurent Vivier case 10: /* fpiar, not implemented */ 92462474d7SAlex Bennée return gdb_get_reg32(mem_buf, 0); 935a4526b2SLaurent Vivier } 945a4526b2SLaurent Vivier return 0; 955a4526b2SLaurent Vivier } 965a4526b2SLaurent Vivier 9766260159SAkihiko Odaki static int m68k_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n) 985a4526b2SLaurent Vivier { 9966260159SAkihiko Odaki M68kCPU *cpu = M68K_CPU(cs); 10066260159SAkihiko Odaki CPUM68KState *env = &cpu->env; 10166260159SAkihiko Odaki 1025a4526b2SLaurent Vivier if (n < 8) { 1035a4526b2SLaurent Vivier env->fregs[n].l.upper = lduw_be_p(mem_buf); 1045a4526b2SLaurent Vivier env->fregs[n].l.lower = ldq_be_p(mem_buf + 4); 1055a4526b2SLaurent Vivier return 12; 1065a4526b2SLaurent Vivier } 1075a4526b2SLaurent Vivier switch (n) { 1085a4526b2SLaurent Vivier case 8: /* fpcontrol */ 109ba624944SLaurent Vivier cpu_m68k_set_fpcr(env, ldl_p(mem_buf)); 1105a4526b2SLaurent Vivier return 4; 1115a4526b2SLaurent Vivier case 9: /* fpstatus */ 112*58883579SKeith Packard cpu_m68k_set_fpsr(env, ldl_p(mem_buf)); 1135a4526b2SLaurent Vivier return 4; 1145a4526b2SLaurent Vivier case 10: /* fpiar, not implemented */ 1155a4526b2SLaurent Vivier return 4; 1165a4526b2SLaurent Vivier } 1175a4526b2SLaurent Vivier return 0; 1185a4526b2SLaurent Vivier } 1195a4526b2SLaurent Vivier 1206d1bbc62SAndreas Färber void m68k_cpu_init_gdb(M68kCPU *cpu) 1216d1bbc62SAndreas Färber { 12222169d41SAndreas Färber CPUState *cs = CPU(cpu); 1236d1bbc62SAndreas Färber CPUM68KState *env = &cpu->env; 1246d1bbc62SAndreas Färber 12511150915SAndreas Färber if (m68k_feature(env, M68K_FEATURE_CF_FPU)) { 126f83311e4SLaurent Vivier gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg, 127ac1e8671SAkihiko Odaki gdb_find_static_feature("cf-fp.xml"), 18); 1285a4526b2SLaurent Vivier } else if (m68k_feature(env, M68K_FEATURE_FPU)) { 129ac1e8671SAkihiko Odaki gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg, m68k_fpu_gdb_set_reg, 130ac1e8671SAkihiko Odaki gdb_find_static_feature("m68k-fp.xml"), 18); 131aaed909aSbellard } 13211150915SAndreas Färber /* TODO: Add [E]MAC registers. */ 133aaed909aSbellard } 134aaed909aSbellard 1356e22b28eSLaurent Vivier void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val) 1360633879fSpbrook { 1370633879fSpbrook switch (reg) { 1386e22b28eSLaurent Vivier case M68K_CR_CACR: 13920dcee94Spbrook env->cacr = val; 14020dcee94Spbrook m68k_switch_sp(env); 14120dcee94Spbrook break; 1426e22b28eSLaurent Vivier case M68K_CR_ACR0: 1436e22b28eSLaurent Vivier case M68K_CR_ACR1: 1446e22b28eSLaurent Vivier case M68K_CR_ACR2: 1456e22b28eSLaurent Vivier case M68K_CR_ACR3: 14620dcee94Spbrook /* TODO: Implement Access Control Registers. */ 1470633879fSpbrook break; 1486e22b28eSLaurent Vivier case M68K_CR_VBR: 1490633879fSpbrook env->vbr = val; 1500633879fSpbrook break; 1510633879fSpbrook /* TODO: Implement control registers. */ 1520633879fSpbrook default: 153a8d92fd8SRichard Henderson cpu_abort(env_cpu(env), 1546e22b28eSLaurent Vivier "Unimplemented control register write 0x%x = 0x%x\n", 1556e22b28eSLaurent Vivier reg, val); 1566e22b28eSLaurent Vivier } 1576e22b28eSLaurent Vivier } 1586e22b28eSLaurent Vivier 1598df0e6aeSLucien Murray-Pitts static void raise_exception_ra(CPUM68KState *env, int tt, uintptr_t raddr) 1608df0e6aeSLucien Murray-Pitts { 1618df0e6aeSLucien Murray-Pitts CPUState *cs = env_cpu(env); 1628df0e6aeSLucien Murray-Pitts 1638df0e6aeSLucien Murray-Pitts cs->exception_index = tt; 1648df0e6aeSLucien Murray-Pitts cpu_loop_exit_restore(cs, raddr); 1658df0e6aeSLucien Murray-Pitts } 1668df0e6aeSLucien Murray-Pitts 1676e22b28eSLaurent Vivier void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val) 1686e22b28eSLaurent Vivier { 1696e22b28eSLaurent Vivier switch (reg) { 17060d8e964SLucien Murray-Pitts /* MC680[12346]0 */ 1715fa9f1f2SLaurent Vivier case M68K_CR_SFC: 1725fa9f1f2SLaurent Vivier env->sfc = val & 7; 1735fa9f1f2SLaurent Vivier return; 17460d8e964SLucien Murray-Pitts /* MC680[12346]0 */ 1755fa9f1f2SLaurent Vivier case M68K_CR_DFC: 1765fa9f1f2SLaurent Vivier env->dfc = val & 7; 1775fa9f1f2SLaurent Vivier return; 17860d8e964SLucien Murray-Pitts /* MC680[12346]0 */ 1796e22b28eSLaurent Vivier case M68K_CR_VBR: 1806e22b28eSLaurent Vivier env->vbr = val; 1816e22b28eSLaurent Vivier return; 18218b6102eSLaurent Vivier /* MC680[2346]0 */ 1836e22b28eSLaurent Vivier case M68K_CR_CACR: 18418b6102eSLaurent Vivier if (m68k_feature(env, M68K_FEATURE_M68020)) { 18518b6102eSLaurent Vivier env->cacr = val & 0x0000000f; 18618b6102eSLaurent Vivier } else if (m68k_feature(env, M68K_FEATURE_M68030)) { 18718b6102eSLaurent Vivier env->cacr = val & 0x00003f1f; 18818b6102eSLaurent Vivier } else if (m68k_feature(env, M68K_FEATURE_M68040)) { 18918b6102eSLaurent Vivier env->cacr = val & 0x80008000; 19018b6102eSLaurent Vivier } else if (m68k_feature(env, M68K_FEATURE_M68060)) { 19118b6102eSLaurent Vivier env->cacr = val & 0xf8e0e000; 1928df0e6aeSLucien Murray-Pitts } else { 1938df0e6aeSLucien Murray-Pitts break; 19418b6102eSLaurent Vivier } 1956e22b28eSLaurent Vivier m68k_switch_sp(env); 1966e22b28eSLaurent Vivier return; 19760d8e964SLucien Murray-Pitts /* MC680[46]0 */ 19888b2fef6SLaurent Vivier case M68K_CR_TC: 1998df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040) 2008df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 20188b2fef6SLaurent Vivier env->mmu.tcr = val; 20288b2fef6SLaurent Vivier return; 2038df0e6aeSLucien Murray-Pitts } 2048df0e6aeSLucien Murray-Pitts break; 20560d8e964SLucien Murray-Pitts /* MC68040 */ 206e55886c3SLaurent Vivier case M68K_CR_MMUSR: 2078df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 208e55886c3SLaurent Vivier env->mmu.mmusr = val; 209e55886c3SLaurent Vivier return; 2108df0e6aeSLucien Murray-Pitts } 2118df0e6aeSLucien Murray-Pitts break; 21260d8e964SLucien Murray-Pitts /* MC680[46]0 */ 21388b2fef6SLaurent Vivier case M68K_CR_SRP: 2148df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040) 2158df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 21688b2fef6SLaurent Vivier env->mmu.srp = val; 21788b2fef6SLaurent Vivier return; 2188df0e6aeSLucien Murray-Pitts } 2198df0e6aeSLucien Murray-Pitts break; 2208df0e6aeSLucien Murray-Pitts /* MC680[46]0 */ 22188b2fef6SLaurent Vivier case M68K_CR_URP: 2228df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040) 2238df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 22488b2fef6SLaurent Vivier env->mmu.urp = val; 22588b2fef6SLaurent Vivier return; 2268df0e6aeSLucien Murray-Pitts } 2278df0e6aeSLucien Murray-Pitts break; 2288df0e6aeSLucien Murray-Pitts /* MC680[12346]0 */ 2296e22b28eSLaurent Vivier case M68K_CR_USP: 2306e22b28eSLaurent Vivier env->sp[M68K_USP] = val; 2316e22b28eSLaurent Vivier return; 23260d8e964SLucien Murray-Pitts /* MC680[234]0 */ 2336e22b28eSLaurent Vivier case M68K_CR_MSP: 2348df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68020) 2358df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68030) 2368df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68040)) { 2376e22b28eSLaurent Vivier env->sp[M68K_SSP] = val; 2386e22b28eSLaurent Vivier return; 2398df0e6aeSLucien Murray-Pitts } 2408df0e6aeSLucien Murray-Pitts break; 24160d8e964SLucien Murray-Pitts /* MC680[234]0 */ 2426e22b28eSLaurent Vivier case M68K_CR_ISP: 2438df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68020) 2448df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68030) 2458df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68040)) { 2466e22b28eSLaurent Vivier env->sp[M68K_ISP] = val; 2476e22b28eSLaurent Vivier return; 2488df0e6aeSLucien Murray-Pitts } 2498df0e6aeSLucien Murray-Pitts break; 250c05c73b0SLaurent Vivier /* MC68040/MC68LC040 */ 2518df0e6aeSLucien Murray-Pitts case M68K_CR_ITT0: /* MC68EC040 only: M68K_CR_IACR0 */ 2528df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 253c05c73b0SLaurent Vivier env->mmu.ttr[M68K_ITTR0] = val; 254c05c73b0SLaurent Vivier return; 2558df0e6aeSLucien Murray-Pitts } 2568df0e6aeSLucien Murray-Pitts break; 25760d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 2588df0e6aeSLucien Murray-Pitts case M68K_CR_ITT1: /* MC68EC040 only: M68K_CR_IACR1 */ 2598df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 260c05c73b0SLaurent Vivier env->mmu.ttr[M68K_ITTR1] = val; 261c05c73b0SLaurent Vivier return; 2628df0e6aeSLucien Murray-Pitts } 2638df0e6aeSLucien Murray-Pitts break; 26460d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 2658df0e6aeSLucien Murray-Pitts case M68K_CR_DTT0: /* MC68EC040 only: M68K_CR_DACR0 */ 2668df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 267c05c73b0SLaurent Vivier env->mmu.ttr[M68K_DTTR0] = val; 268c05c73b0SLaurent Vivier return; 2698df0e6aeSLucien Murray-Pitts } 2708df0e6aeSLucien Murray-Pitts break; 27160d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 2728df0e6aeSLucien Murray-Pitts case M68K_CR_DTT1: /* MC68EC040 only: M68K_CR_DACR1 */ 2738df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 274c05c73b0SLaurent Vivier env->mmu.ttr[M68K_DTTR1] = val; 275c05c73b0SLaurent Vivier return; 2768df0e6aeSLucien Murray-Pitts } 2778df0e6aeSLucien Murray-Pitts break; 2785736526cSLucien Murray-Pitts /* Unimplemented Registers */ 2795736526cSLucien Murray-Pitts case M68K_CR_CAAR: 2805736526cSLucien Murray-Pitts case M68K_CR_PCR: 2815736526cSLucien Murray-Pitts case M68K_CR_BUSCR: 282a8d92fd8SRichard Henderson cpu_abort(env_cpu(env), 283a8d92fd8SRichard Henderson "Unimplemented control register write 0x%x = 0x%x\n", 2840633879fSpbrook reg, val); 2850633879fSpbrook } 2866e22b28eSLaurent Vivier 2878df0e6aeSLucien Murray-Pitts /* Invalid control registers will generate an exception. */ 2888df0e6aeSLucien Murray-Pitts raise_exception_ra(env, EXCP_ILLEGAL, 0); 2898df0e6aeSLucien Murray-Pitts return; 2908df0e6aeSLucien Murray-Pitts } 2918df0e6aeSLucien Murray-Pitts 2926e22b28eSLaurent Vivier uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg) 2936e22b28eSLaurent Vivier { 2946e22b28eSLaurent Vivier switch (reg) { 29560d8e964SLucien Murray-Pitts /* MC680[12346]0 */ 2965fa9f1f2SLaurent Vivier case M68K_CR_SFC: 2975fa9f1f2SLaurent Vivier return env->sfc; 29860d8e964SLucien Murray-Pitts /* MC680[12346]0 */ 2995fa9f1f2SLaurent Vivier case M68K_CR_DFC: 3005fa9f1f2SLaurent Vivier return env->dfc; 30160d8e964SLucien Murray-Pitts /* MC680[12346]0 */ 3026e22b28eSLaurent Vivier case M68K_CR_VBR: 3036e22b28eSLaurent Vivier return env->vbr; 30460d8e964SLucien Murray-Pitts /* MC680[2346]0 */ 3056e22b28eSLaurent Vivier case M68K_CR_CACR: 3068df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68020) 3078df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68030) 3088df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68040) 3098df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 3106e22b28eSLaurent Vivier return env->cacr; 3118df0e6aeSLucien Murray-Pitts } 3128df0e6aeSLucien Murray-Pitts break; 31360d8e964SLucien Murray-Pitts /* MC680[46]0 */ 31488b2fef6SLaurent Vivier case M68K_CR_TC: 3158df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040) 3168df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 31788b2fef6SLaurent Vivier return env->mmu.tcr; 3188df0e6aeSLucien Murray-Pitts } 3198df0e6aeSLucien Murray-Pitts break; 32060d8e964SLucien Murray-Pitts /* MC68040 */ 321e55886c3SLaurent Vivier case M68K_CR_MMUSR: 3228df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 323e55886c3SLaurent Vivier return env->mmu.mmusr; 3248df0e6aeSLucien Murray-Pitts } 3258df0e6aeSLucien Murray-Pitts break; 32660d8e964SLucien Murray-Pitts /* MC680[46]0 */ 32788b2fef6SLaurent Vivier case M68K_CR_SRP: 3288df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040) 3298df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 33088b2fef6SLaurent Vivier return env->mmu.srp; 3318df0e6aeSLucien Murray-Pitts } 3328df0e6aeSLucien Murray-Pitts break; 3338df0e6aeSLucien Murray-Pitts /* MC68040/MC68LC040 */ 3348df0e6aeSLucien Murray-Pitts case M68K_CR_URP: 3358df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040) 3368df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68060)) { 3378df0e6aeSLucien Murray-Pitts return env->mmu.urp; 3388df0e6aeSLucien Murray-Pitts } 3398df0e6aeSLucien Murray-Pitts break; 34060d8e964SLucien Murray-Pitts /* MC680[46]0 */ 3416e22b28eSLaurent Vivier case M68K_CR_USP: 3426e22b28eSLaurent Vivier return env->sp[M68K_USP]; 34360d8e964SLucien Murray-Pitts /* MC680[234]0 */ 3446e22b28eSLaurent Vivier case M68K_CR_MSP: 3458df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68020) 3468df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68030) 3478df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68040)) { 3486e22b28eSLaurent Vivier return env->sp[M68K_SSP]; 3498df0e6aeSLucien Murray-Pitts } 3508df0e6aeSLucien Murray-Pitts break; 35160d8e964SLucien Murray-Pitts /* MC680[234]0 */ 3526e22b28eSLaurent Vivier case M68K_CR_ISP: 3538df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68020) 3548df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68030) 3558df0e6aeSLucien Murray-Pitts || m68k_feature(env, M68K_FEATURE_M68040)) { 3566e22b28eSLaurent Vivier return env->sp[M68K_ISP]; 3578df0e6aeSLucien Murray-Pitts } 3588df0e6aeSLucien Murray-Pitts break; 35960d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 36060d8e964SLucien Murray-Pitts case M68K_CR_ITT0: /* MC68EC040 only: M68K_CR_IACR0 */ 3618df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 362c05c73b0SLaurent Vivier return env->mmu.ttr[M68K_ITTR0]; 3638df0e6aeSLucien Murray-Pitts } 3648df0e6aeSLucien Murray-Pitts break; 36560d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 36660d8e964SLucien Murray-Pitts case M68K_CR_ITT1: /* MC68EC040 only: M68K_CR_IACR1 */ 3678df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 368c05c73b0SLaurent Vivier return env->mmu.ttr[M68K_ITTR1]; 3698df0e6aeSLucien Murray-Pitts } 3708df0e6aeSLucien Murray-Pitts break; 37160d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 37260d8e964SLucien Murray-Pitts case M68K_CR_DTT0: /* MC68EC040 only: M68K_CR_DACR0 */ 3738df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 374c05c73b0SLaurent Vivier return env->mmu.ttr[M68K_DTTR0]; 3758df0e6aeSLucien Murray-Pitts } 3768df0e6aeSLucien Murray-Pitts break; 37760d8e964SLucien Murray-Pitts /* MC68040/MC68LC040 */ 37860d8e964SLucien Murray-Pitts case M68K_CR_DTT1: /* MC68EC040 only: M68K_CR_DACR1 */ 3798df0e6aeSLucien Murray-Pitts if (m68k_feature(env, M68K_FEATURE_M68040)) { 380c05c73b0SLaurent Vivier return env->mmu.ttr[M68K_DTTR1]; 3818df0e6aeSLucien Murray-Pitts } 3828df0e6aeSLucien Murray-Pitts break; 3835736526cSLucien Murray-Pitts /* Unimplemented Registers */ 3845736526cSLucien Murray-Pitts case M68K_CR_CAAR: 3855736526cSLucien Murray-Pitts case M68K_CR_PCR: 3865736526cSLucien Murray-Pitts case M68K_CR_BUSCR: 387a8d92fd8SRichard Henderson cpu_abort(env_cpu(env), "Unimplemented control register read 0x%x\n", 3886e22b28eSLaurent Vivier reg); 3890633879fSpbrook } 3900633879fSpbrook 3918df0e6aeSLucien Murray-Pitts /* Invalid control registers will generate an exception. */ 3928df0e6aeSLucien Murray-Pitts raise_exception_ra(env, EXCP_ILLEGAL, 0); 3938df0e6aeSLucien Murray-Pitts 3948df0e6aeSLucien Murray-Pitts return 0; 3958df0e6aeSLucien Murray-Pitts } 3968df0e6aeSLucien Murray-Pitts 397e1f3808eSpbrook void HELPER(set_macsr)(CPUM68KState *env, uint32_t val) 398acf930aaSpbrook { 399acf930aaSpbrook uint32_t acc; 400acf930aaSpbrook int8_t exthigh; 401acf930aaSpbrook uint8_t extlow; 402acf930aaSpbrook uint64_t regval; 403acf930aaSpbrook int i; 404acf930aaSpbrook if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) { 405acf930aaSpbrook for (i = 0; i < 4; i++) { 406acf930aaSpbrook regval = env->macc[i]; 407acf930aaSpbrook exthigh = regval >> 40; 408acf930aaSpbrook if (env->macsr & MACSR_FI) { 409acf930aaSpbrook acc = regval >> 8; 410acf930aaSpbrook extlow = regval; 411acf930aaSpbrook } else { 412acf930aaSpbrook acc = regval; 413acf930aaSpbrook extlow = regval >> 32; 414acf930aaSpbrook } 415acf930aaSpbrook if (env->macsr & MACSR_FI) { 416acf930aaSpbrook regval = (((uint64_t)acc) << 8) | extlow; 417acf930aaSpbrook regval |= ((int64_t)exthigh) << 40; 418acf930aaSpbrook } else if (env->macsr & MACSR_SU) { 419acf930aaSpbrook regval = acc | (((int64_t)extlow) << 32); 420acf930aaSpbrook regval |= ((int64_t)exthigh) << 40; 421acf930aaSpbrook } else { 422acf930aaSpbrook regval = acc | (((uint64_t)extlow) << 32); 423acf930aaSpbrook regval |= ((uint64_t)(uint8_t)exthigh) << 40; 424acf930aaSpbrook } 425acf930aaSpbrook env->macc[i] = regval; 426acf930aaSpbrook } 427acf930aaSpbrook } 428acf930aaSpbrook env->macsr = val; 429acf930aaSpbrook } 430acf930aaSpbrook 43120dcee94Spbrook void m68k_switch_sp(CPUM68KState *env) 43220dcee94Spbrook { 43320dcee94Spbrook int new_sp; 43420dcee94Spbrook 43520dcee94Spbrook env->sp[env->current_sp] = env->aregs[7]; 436aece90d8SMark Cave-Ayland if (m68k_feature(env, M68K_FEATURE_M68K)) { 4376e22b28eSLaurent Vivier if (env->sr & SR_S) { 4387525a9b9SLucien Murray-Pitts /* SR:Master-Mode bit unimplemented then ISP is not available */ 4397525a9b9SLucien Murray-Pitts if (!m68k_feature(env, M68K_FEATURE_MSP) || env->sr & SR_M) { 4406e22b28eSLaurent Vivier new_sp = M68K_SSP; 4416e22b28eSLaurent Vivier } else { 4426e22b28eSLaurent Vivier new_sp = M68K_ISP; 4436e22b28eSLaurent Vivier } 4446e22b28eSLaurent Vivier } else { 4456e22b28eSLaurent Vivier new_sp = M68K_USP; 4466e22b28eSLaurent Vivier } 4476e22b28eSLaurent Vivier } else { 44820dcee94Spbrook new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP) 44920dcee94Spbrook ? M68K_SSP : M68K_USP; 4506e22b28eSLaurent Vivier } 45120dcee94Spbrook env->aregs[7] = env->sp[new_sp]; 45220dcee94Spbrook env->current_sp = new_sp; 45320dcee94Spbrook } 45420dcee94Spbrook 455fe5f7b1bSRichard Henderson #if !defined(CONFIG_USER_ONLY) 45688b2fef6SLaurent Vivier /* MMU: 68040 only */ 4574fcc562bSPaul Brook 458fad866daSMarkus Armbruster static void print_address_zone(uint32_t logical, uint32_t physical, 4592097dca6SLaurent Vivier uint32_t size, int attr) 4602097dca6SLaurent Vivier { 461fad866daSMarkus Armbruster qemu_printf("%08x - %08x -> %08x - %08x %c ", 4622097dca6SLaurent Vivier logical, logical + size - 1, 4632097dca6SLaurent Vivier physical, physical + size - 1, 4642097dca6SLaurent Vivier attr & 4 ? 'W' : '-'); 4652097dca6SLaurent Vivier size >>= 10; 4662097dca6SLaurent Vivier if (size < 1024) { 467fad866daSMarkus Armbruster qemu_printf("(%d KiB)\n", size); 4682097dca6SLaurent Vivier } else { 4692097dca6SLaurent Vivier size >>= 10; 4702097dca6SLaurent Vivier if (size < 1024) { 471fad866daSMarkus Armbruster qemu_printf("(%d MiB)\n", size); 4722097dca6SLaurent Vivier } else { 4732097dca6SLaurent Vivier size >>= 10; 474fad866daSMarkus Armbruster qemu_printf("(%d GiB)\n", size); 4752097dca6SLaurent Vivier } 4762097dca6SLaurent Vivier } 4772097dca6SLaurent Vivier } 4782097dca6SLaurent Vivier 479fad866daSMarkus Armbruster static void dump_address_map(CPUM68KState *env, uint32_t root_pointer) 4802097dca6SLaurent Vivier { 4812097dca6SLaurent Vivier int i, j, k; 4822097dca6SLaurent Vivier int tic_size, tic_shift; 4832097dca6SLaurent Vivier uint32_t tib_mask; 4842097dca6SLaurent Vivier uint32_t tia, tib, tic; 4852097dca6SLaurent Vivier uint32_t logical = 0xffffffff, physical = 0xffffffff; 4862097dca6SLaurent Vivier uint32_t first_logical = 0xffffffff, first_physical = 0xffffffff; 4872097dca6SLaurent Vivier uint32_t last_logical, last_physical; 4882097dca6SLaurent Vivier int32_t size; 4892097dca6SLaurent Vivier int last_attr = -1, attr = -1; 490a8d92fd8SRichard Henderson CPUState *cs = env_cpu(env); 491f80b551dSPeter Maydell MemTxResult txres; 4922097dca6SLaurent Vivier 4932097dca6SLaurent Vivier if (env->mmu.tcr & M68K_TCR_PAGE_8K) { 4942097dca6SLaurent Vivier /* 8k page */ 4952097dca6SLaurent Vivier tic_size = 32; 4962097dca6SLaurent Vivier tic_shift = 13; 4972097dca6SLaurent Vivier tib_mask = M68K_8K_PAGE_MASK; 4982097dca6SLaurent Vivier } else { 4992097dca6SLaurent Vivier /* 4k page */ 5002097dca6SLaurent Vivier tic_size = 64; 5012097dca6SLaurent Vivier tic_shift = 12; 5022097dca6SLaurent Vivier tib_mask = M68K_4K_PAGE_MASK; 5032097dca6SLaurent Vivier } 5042097dca6SLaurent Vivier for (i = 0; i < M68K_ROOT_POINTER_ENTRIES; i++) { 505f80b551dSPeter Maydell tia = address_space_ldl(cs->as, M68K_POINTER_BASE(root_pointer) + i * 4, 506f80b551dSPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 507f80b551dSPeter Maydell if (txres != MEMTX_OK || !M68K_UDT_VALID(tia)) { 5082097dca6SLaurent Vivier continue; 5092097dca6SLaurent Vivier } 5102097dca6SLaurent Vivier for (j = 0; j < M68K_ROOT_POINTER_ENTRIES; j++) { 511f80b551dSPeter Maydell tib = address_space_ldl(cs->as, M68K_POINTER_BASE(tia) + j * 4, 512f80b551dSPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 513f80b551dSPeter Maydell if (txres != MEMTX_OK || !M68K_UDT_VALID(tib)) { 5142097dca6SLaurent Vivier continue; 5152097dca6SLaurent Vivier } 5162097dca6SLaurent Vivier for (k = 0; k < tic_size; k++) { 517f80b551dSPeter Maydell tic = address_space_ldl(cs->as, (tib & tib_mask) + k * 4, 518f80b551dSPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 519f80b551dSPeter Maydell if (txres != MEMTX_OK || !M68K_PDT_VALID(tic)) { 5202097dca6SLaurent Vivier continue; 5212097dca6SLaurent Vivier } 5222097dca6SLaurent Vivier if (M68K_PDT_INDIRECT(tic)) { 523f80b551dSPeter Maydell tic = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(tic), 524f80b551dSPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 525f80b551dSPeter Maydell if (txres != MEMTX_OK) { 526f80b551dSPeter Maydell continue; 527f80b551dSPeter Maydell } 5282097dca6SLaurent Vivier } 5292097dca6SLaurent Vivier 5302097dca6SLaurent Vivier last_logical = logical; 5312097dca6SLaurent Vivier logical = (i << M68K_TTS_ROOT_SHIFT) | 5322097dca6SLaurent Vivier (j << M68K_TTS_POINTER_SHIFT) | 5332097dca6SLaurent Vivier (k << tic_shift); 5342097dca6SLaurent Vivier 5352097dca6SLaurent Vivier last_physical = physical; 5362097dca6SLaurent Vivier physical = tic & ~((1 << tic_shift) - 1); 5372097dca6SLaurent Vivier 5382097dca6SLaurent Vivier last_attr = attr; 5392097dca6SLaurent Vivier attr = tic & ((1 << tic_shift) - 1); 5402097dca6SLaurent Vivier 5412097dca6SLaurent Vivier if ((logical != (last_logical + (1 << tic_shift))) || 5422097dca6SLaurent Vivier (physical != (last_physical + (1 << tic_shift))) || 5432097dca6SLaurent Vivier (attr & 4) != (last_attr & 4)) { 5442097dca6SLaurent Vivier 5452097dca6SLaurent Vivier if (first_logical != 0xffffffff) { 5462097dca6SLaurent Vivier size = last_logical + (1 << tic_shift) - 5472097dca6SLaurent Vivier first_logical; 548fad866daSMarkus Armbruster print_address_zone(first_logical, 5492097dca6SLaurent Vivier first_physical, size, last_attr); 5502097dca6SLaurent Vivier } 5512097dca6SLaurent Vivier first_logical = logical; 5522097dca6SLaurent Vivier first_physical = physical; 5532097dca6SLaurent Vivier } 5542097dca6SLaurent Vivier } 5552097dca6SLaurent Vivier } 5562097dca6SLaurent Vivier } 5572097dca6SLaurent Vivier if (first_logical != logical || (attr & 4) != (last_attr & 4)) { 5582097dca6SLaurent Vivier size = logical + (1 << tic_shift) - first_logical; 559fad866daSMarkus Armbruster print_address_zone(first_logical, first_physical, size, last_attr); 5602097dca6SLaurent Vivier } 5612097dca6SLaurent Vivier } 5622097dca6SLaurent Vivier 5632097dca6SLaurent Vivier #define DUMP_CACHEFLAGS(a) \ 5642097dca6SLaurent Vivier switch (a & M68K_DESC_CACHEMODE) { \ 5658b81968cSMichael Tokarev case M68K_DESC_CM_WRTHRU: /* cacheable, write-through */ \ 566fad866daSMarkus Armbruster qemu_printf("T"); \ 5672097dca6SLaurent Vivier break; \ 5688b81968cSMichael Tokarev case M68K_DESC_CM_COPYBK: /* cacheable, copyback */ \ 569fad866daSMarkus Armbruster qemu_printf("C"); \ 5702097dca6SLaurent Vivier break; \ 5712097dca6SLaurent Vivier case M68K_DESC_CM_SERIAL: /* noncachable, serialized */ \ 572fad866daSMarkus Armbruster qemu_printf("S"); \ 5732097dca6SLaurent Vivier break; \ 5742097dca6SLaurent Vivier case M68K_DESC_CM_NCACHE: /* noncachable */ \ 575fad866daSMarkus Armbruster qemu_printf("N"); \ 5762097dca6SLaurent Vivier break; \ 5772097dca6SLaurent Vivier } 5782097dca6SLaurent Vivier 579fad866daSMarkus Armbruster static void dump_ttr(uint32_t ttr) 5802097dca6SLaurent Vivier { 5812097dca6SLaurent Vivier if ((ttr & M68K_TTR_ENABLED) == 0) { 582fad866daSMarkus Armbruster qemu_printf("disabled\n"); 5832097dca6SLaurent Vivier return; 5842097dca6SLaurent Vivier } 585fad866daSMarkus Armbruster qemu_printf("Base: 0x%08x Mask: 0x%08x Control: ", 5862097dca6SLaurent Vivier ttr & M68K_TTR_ADDR_BASE, 5872097dca6SLaurent Vivier (ttr & M68K_TTR_ADDR_MASK) << M68K_TTR_ADDR_MASK_SHIFT); 5882097dca6SLaurent Vivier switch (ttr & M68K_TTR_SFIELD) { 5892097dca6SLaurent Vivier case M68K_TTR_SFIELD_USER: 590fad866daSMarkus Armbruster qemu_printf("U"); 5912097dca6SLaurent Vivier break; 5922097dca6SLaurent Vivier case M68K_TTR_SFIELD_SUPER: 593fad866daSMarkus Armbruster qemu_printf("S"); 5942097dca6SLaurent Vivier break; 5952097dca6SLaurent Vivier default: 596fad866daSMarkus Armbruster qemu_printf("*"); 5972097dca6SLaurent Vivier break; 5982097dca6SLaurent Vivier } 5992097dca6SLaurent Vivier DUMP_CACHEFLAGS(ttr); 6002097dca6SLaurent Vivier if (ttr & M68K_DESC_WRITEPROT) { 601fad866daSMarkus Armbruster qemu_printf("R"); 6022097dca6SLaurent Vivier } else { 603fad866daSMarkus Armbruster qemu_printf("W"); 6042097dca6SLaurent Vivier } 605fad866daSMarkus Armbruster qemu_printf(" U: %d\n", (ttr & M68K_DESC_USERATTR) >> 6062097dca6SLaurent Vivier M68K_DESC_USERATTR_SHIFT); 6072097dca6SLaurent Vivier } 6082097dca6SLaurent Vivier 609fad866daSMarkus Armbruster void dump_mmu(CPUM68KState *env) 6102097dca6SLaurent Vivier { 6112097dca6SLaurent Vivier if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) { 612fad866daSMarkus Armbruster qemu_printf("Translation disabled\n"); 6132097dca6SLaurent Vivier return; 6142097dca6SLaurent Vivier } 615fad866daSMarkus Armbruster qemu_printf("Page Size: "); 6162097dca6SLaurent Vivier if (env->mmu.tcr & M68K_TCR_PAGE_8K) { 617fad866daSMarkus Armbruster qemu_printf("8kB\n"); 6182097dca6SLaurent Vivier } else { 619fad866daSMarkus Armbruster qemu_printf("4kB\n"); 6202097dca6SLaurent Vivier } 6212097dca6SLaurent Vivier 622fad866daSMarkus Armbruster qemu_printf("MMUSR: "); 6232097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_B_040) { 624fad866daSMarkus Armbruster qemu_printf("BUS ERROR\n"); 6252097dca6SLaurent Vivier } else { 626fad866daSMarkus Armbruster qemu_printf("Phy=%08x Flags: ", env->mmu.mmusr & 0xfffff000); 6272097dca6SLaurent Vivier /* flags found on the page descriptor */ 6282097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_G_040) { 629fad866daSMarkus Armbruster qemu_printf("G"); /* Global */ 6302097dca6SLaurent Vivier } else { 631fad866daSMarkus Armbruster qemu_printf("."); 6322097dca6SLaurent Vivier } 6332097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_S_040) { 634fad866daSMarkus Armbruster qemu_printf("S"); /* Supervisor */ 6352097dca6SLaurent Vivier } else { 636fad866daSMarkus Armbruster qemu_printf("."); 6372097dca6SLaurent Vivier } 6382097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_M_040) { 639fad866daSMarkus Armbruster qemu_printf("M"); /* Modified */ 6402097dca6SLaurent Vivier } else { 641fad866daSMarkus Armbruster qemu_printf("."); 6422097dca6SLaurent Vivier } 6432097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_WP_040) { 644fad866daSMarkus Armbruster qemu_printf("W"); /* Write protect */ 6452097dca6SLaurent Vivier } else { 646fad866daSMarkus Armbruster qemu_printf("."); 6472097dca6SLaurent Vivier } 6482097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_T_040) { 649fad866daSMarkus Armbruster qemu_printf("T"); /* Transparent */ 6502097dca6SLaurent Vivier } else { 651fad866daSMarkus Armbruster qemu_printf("."); 6522097dca6SLaurent Vivier } 6532097dca6SLaurent Vivier if (env->mmu.mmusr & M68K_MMU_R_040) { 654fad866daSMarkus Armbruster qemu_printf("R"); /* Resident */ 6552097dca6SLaurent Vivier } else { 656fad866daSMarkus Armbruster qemu_printf("."); 6572097dca6SLaurent Vivier } 658fad866daSMarkus Armbruster qemu_printf(" Cache: "); 6592097dca6SLaurent Vivier DUMP_CACHEFLAGS(env->mmu.mmusr); 660fad866daSMarkus Armbruster qemu_printf(" U: %d\n", (env->mmu.mmusr >> 8) & 3); 661fad866daSMarkus Armbruster qemu_printf("\n"); 6622097dca6SLaurent Vivier } 6632097dca6SLaurent Vivier 664fad866daSMarkus Armbruster qemu_printf("ITTR0: "); 665fad866daSMarkus Armbruster dump_ttr(env->mmu.ttr[M68K_ITTR0]); 666fad866daSMarkus Armbruster qemu_printf("ITTR1: "); 667fad866daSMarkus Armbruster dump_ttr(env->mmu.ttr[M68K_ITTR1]); 668fad866daSMarkus Armbruster qemu_printf("DTTR0: "); 669fad866daSMarkus Armbruster dump_ttr(env->mmu.ttr[M68K_DTTR0]); 670fad866daSMarkus Armbruster qemu_printf("DTTR1: "); 671fad866daSMarkus Armbruster dump_ttr(env->mmu.ttr[M68K_DTTR1]); 6722097dca6SLaurent Vivier 673fad866daSMarkus Armbruster qemu_printf("SRP: 0x%08x\n", env->mmu.srp); 674fad866daSMarkus Armbruster dump_address_map(env, env->mmu.srp); 6752097dca6SLaurent Vivier 676fad866daSMarkus Armbruster qemu_printf("URP: 0x%08x\n", env->mmu.urp); 677fad866daSMarkus Armbruster dump_address_map(env, env->mmu.urp); 6782097dca6SLaurent Vivier } 6792097dca6SLaurent Vivier 680c05c73b0SLaurent Vivier static int check_TTR(uint32_t ttr, int *prot, target_ulong addr, 681c05c73b0SLaurent Vivier int access_type) 682c05c73b0SLaurent Vivier { 683c05c73b0SLaurent Vivier uint32_t base, mask; 684c05c73b0SLaurent Vivier 685c05c73b0SLaurent Vivier /* check if transparent translation is enabled */ 686c05c73b0SLaurent Vivier if ((ttr & M68K_TTR_ENABLED) == 0) { 687c05c73b0SLaurent Vivier return 0; 688c05c73b0SLaurent Vivier } 689c05c73b0SLaurent Vivier 690c05c73b0SLaurent Vivier /* check mode access */ 691c05c73b0SLaurent Vivier switch (ttr & M68K_TTR_SFIELD) { 692c05c73b0SLaurent Vivier case M68K_TTR_SFIELD_USER: 693c05c73b0SLaurent Vivier /* match only if user */ 694c05c73b0SLaurent Vivier if ((access_type & ACCESS_SUPER) != 0) { 695c05c73b0SLaurent Vivier return 0; 696c05c73b0SLaurent Vivier } 697c05c73b0SLaurent Vivier break; 698c05c73b0SLaurent Vivier case M68K_TTR_SFIELD_SUPER: 699c05c73b0SLaurent Vivier /* match only if supervisor */ 700c05c73b0SLaurent Vivier if ((access_type & ACCESS_SUPER) == 0) { 701c05c73b0SLaurent Vivier return 0; 702c05c73b0SLaurent Vivier } 703c05c73b0SLaurent Vivier break; 704c05c73b0SLaurent Vivier default: 705c05c73b0SLaurent Vivier /* all other values disable mode matching (FC2) */ 706c05c73b0SLaurent Vivier break; 707c05c73b0SLaurent Vivier } 708c05c73b0SLaurent Vivier 709c05c73b0SLaurent Vivier /* check address matching */ 710c05c73b0SLaurent Vivier 711c05c73b0SLaurent Vivier base = ttr & M68K_TTR_ADDR_BASE; 712c05c73b0SLaurent Vivier mask = (ttr & M68K_TTR_ADDR_MASK) ^ M68K_TTR_ADDR_MASK; 713c05c73b0SLaurent Vivier mask <<= M68K_TTR_ADDR_MASK_SHIFT; 714c05c73b0SLaurent Vivier 715c05c73b0SLaurent Vivier if ((addr & mask) != (base & mask)) { 716c05c73b0SLaurent Vivier return 0; 717c05c73b0SLaurent Vivier } 718c05c73b0SLaurent Vivier 719c05c73b0SLaurent Vivier *prot = PAGE_READ | PAGE_EXEC; 720c05c73b0SLaurent Vivier if ((ttr & M68K_DESC_WRITEPROT) == 0) { 721c05c73b0SLaurent Vivier *prot |= PAGE_WRITE; 722c05c73b0SLaurent Vivier } 723c05c73b0SLaurent Vivier 724c05c73b0SLaurent Vivier return 1; 725c05c73b0SLaurent Vivier } 726c05c73b0SLaurent Vivier 72788b2fef6SLaurent Vivier static int get_physical_address(CPUM68KState *env, hwaddr *physical, 72888b2fef6SLaurent Vivier int *prot, target_ulong address, 72988b2fef6SLaurent Vivier int access_type, target_ulong *page_size) 73088b2fef6SLaurent Vivier { 731a8d92fd8SRichard Henderson CPUState *cs = env_cpu(env); 73288b2fef6SLaurent Vivier uint32_t entry; 73388b2fef6SLaurent Vivier uint32_t next; 73488b2fef6SLaurent Vivier target_ulong page_mask; 73588b2fef6SLaurent Vivier bool debug = access_type & ACCESS_DEBUG; 73688b2fef6SLaurent Vivier int page_bits; 737c05c73b0SLaurent Vivier int i; 738adcf0bf0SPeter Maydell MemTxResult txres; 739c05c73b0SLaurent Vivier 740c05c73b0SLaurent Vivier /* Transparent Translation (physical = logical) */ 741c05c73b0SLaurent Vivier for (i = 0; i < M68K_MAX_TTR; i++) { 742c05c73b0SLaurent Vivier if (check_TTR(env->mmu.TTR(access_type, i), 743c05c73b0SLaurent Vivier prot, address, access_type)) { 744e55886c3SLaurent Vivier if (access_type & ACCESS_PTEST) { 745e55886c3SLaurent Vivier /* Transparent Translation Register bit */ 746e55886c3SLaurent Vivier env->mmu.mmusr = M68K_MMU_T_040 | M68K_MMU_R_040; 747e55886c3SLaurent Vivier } 748852002b5SMark Cave-Ayland *physical = address; 749c05c73b0SLaurent Vivier *page_size = TARGET_PAGE_SIZE; 750c05c73b0SLaurent Vivier return 0; 751c05c73b0SLaurent Vivier } 752c05c73b0SLaurent Vivier } 75388b2fef6SLaurent Vivier 75488b2fef6SLaurent Vivier /* Page Table Root Pointer */ 75588b2fef6SLaurent Vivier *prot = PAGE_READ | PAGE_WRITE; 75688b2fef6SLaurent Vivier if (access_type & ACCESS_CODE) { 75788b2fef6SLaurent Vivier *prot |= PAGE_EXEC; 75888b2fef6SLaurent Vivier } 75988b2fef6SLaurent Vivier if (access_type & ACCESS_SUPER) { 76088b2fef6SLaurent Vivier next = env->mmu.srp; 76188b2fef6SLaurent Vivier } else { 76288b2fef6SLaurent Vivier next = env->mmu.urp; 76388b2fef6SLaurent Vivier } 76488b2fef6SLaurent Vivier 76588b2fef6SLaurent Vivier /* Root Index */ 76688b2fef6SLaurent Vivier entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address); 76788b2fef6SLaurent Vivier 768adcf0bf0SPeter Maydell next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres); 769adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 770adcf0bf0SPeter Maydell goto txfail; 771adcf0bf0SPeter Maydell } 77288b2fef6SLaurent Vivier if (!M68K_UDT_VALID(next)) { 77388b2fef6SLaurent Vivier return -1; 77488b2fef6SLaurent Vivier } 77588b2fef6SLaurent Vivier if (!(next & M68K_DESC_USED) && !debug) { 776adcf0bf0SPeter Maydell address_space_stl(cs->as, entry, next | M68K_DESC_USED, 777adcf0bf0SPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 778adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 779adcf0bf0SPeter Maydell goto txfail; 780adcf0bf0SPeter Maydell } 78188b2fef6SLaurent Vivier } 78288b2fef6SLaurent Vivier if (next & M68K_DESC_WRITEPROT) { 783e55886c3SLaurent Vivier if (access_type & ACCESS_PTEST) { 784e55886c3SLaurent Vivier env->mmu.mmusr |= M68K_MMU_WP_040; 785e55886c3SLaurent Vivier } 78688b2fef6SLaurent Vivier *prot &= ~PAGE_WRITE; 78788b2fef6SLaurent Vivier if (access_type & ACCESS_STORE) { 78888b2fef6SLaurent Vivier return -1; 78988b2fef6SLaurent Vivier } 79088b2fef6SLaurent Vivier } 79188b2fef6SLaurent Vivier 79288b2fef6SLaurent Vivier /* Pointer Index */ 79388b2fef6SLaurent Vivier entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address); 79488b2fef6SLaurent Vivier 795adcf0bf0SPeter Maydell next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres); 796adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 797adcf0bf0SPeter Maydell goto txfail; 798adcf0bf0SPeter Maydell } 79988b2fef6SLaurent Vivier if (!M68K_UDT_VALID(next)) { 80088b2fef6SLaurent Vivier return -1; 80188b2fef6SLaurent Vivier } 80288b2fef6SLaurent Vivier if (!(next & M68K_DESC_USED) && !debug) { 803adcf0bf0SPeter Maydell address_space_stl(cs->as, entry, next | M68K_DESC_USED, 804adcf0bf0SPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 805adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 806adcf0bf0SPeter Maydell goto txfail; 807adcf0bf0SPeter Maydell } 80888b2fef6SLaurent Vivier } 80988b2fef6SLaurent Vivier if (next & M68K_DESC_WRITEPROT) { 810e55886c3SLaurent Vivier if (access_type & ACCESS_PTEST) { 811e55886c3SLaurent Vivier env->mmu.mmusr |= M68K_MMU_WP_040; 812e55886c3SLaurent Vivier } 81388b2fef6SLaurent Vivier *prot &= ~PAGE_WRITE; 81488b2fef6SLaurent Vivier if (access_type & ACCESS_STORE) { 81588b2fef6SLaurent Vivier return -1; 81688b2fef6SLaurent Vivier } 81788b2fef6SLaurent Vivier } 81888b2fef6SLaurent Vivier 81988b2fef6SLaurent Vivier /* Page Index */ 82088b2fef6SLaurent Vivier if (env->mmu.tcr & M68K_TCR_PAGE_8K) { 82188b2fef6SLaurent Vivier entry = M68K_8K_PAGE_BASE(next) | M68K_8K_PAGE_INDEX(address); 82288b2fef6SLaurent Vivier } else { 82388b2fef6SLaurent Vivier entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address); 82488b2fef6SLaurent Vivier } 82588b2fef6SLaurent Vivier 826adcf0bf0SPeter Maydell next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres); 827adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 828adcf0bf0SPeter Maydell goto txfail; 829adcf0bf0SPeter Maydell } 83088b2fef6SLaurent Vivier 83188b2fef6SLaurent Vivier if (!M68K_PDT_VALID(next)) { 83288b2fef6SLaurent Vivier return -1; 83388b2fef6SLaurent Vivier } 83488b2fef6SLaurent Vivier if (M68K_PDT_INDIRECT(next)) { 835adcf0bf0SPeter Maydell next = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(next), 836adcf0bf0SPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 837adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 838adcf0bf0SPeter Maydell goto txfail; 839adcf0bf0SPeter Maydell } 84088b2fef6SLaurent Vivier } 84188b2fef6SLaurent Vivier if (access_type & ACCESS_STORE) { 84288b2fef6SLaurent Vivier if (next & M68K_DESC_WRITEPROT) { 84388b2fef6SLaurent Vivier if (!(next & M68K_DESC_USED) && !debug) { 844adcf0bf0SPeter Maydell address_space_stl(cs->as, entry, next | M68K_DESC_USED, 845adcf0bf0SPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 846adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 847adcf0bf0SPeter Maydell goto txfail; 848adcf0bf0SPeter Maydell } 84988b2fef6SLaurent Vivier } 85088b2fef6SLaurent Vivier } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) != 85188b2fef6SLaurent Vivier (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) { 852adcf0bf0SPeter Maydell address_space_stl(cs->as, entry, 853adcf0bf0SPeter Maydell next | (M68K_DESC_MODIFIED | M68K_DESC_USED), 854adcf0bf0SPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 855adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 856adcf0bf0SPeter Maydell goto txfail; 857adcf0bf0SPeter Maydell } 85888b2fef6SLaurent Vivier } 85988b2fef6SLaurent Vivier } else { 86088b2fef6SLaurent Vivier if (!(next & M68K_DESC_USED) && !debug) { 861adcf0bf0SPeter Maydell address_space_stl(cs->as, entry, next | M68K_DESC_USED, 862adcf0bf0SPeter Maydell MEMTXATTRS_UNSPECIFIED, &txres); 863adcf0bf0SPeter Maydell if (txres != MEMTX_OK) { 864adcf0bf0SPeter Maydell goto txfail; 865adcf0bf0SPeter Maydell } 86688b2fef6SLaurent Vivier } 86788b2fef6SLaurent Vivier } 86888b2fef6SLaurent Vivier 86988b2fef6SLaurent Vivier if (env->mmu.tcr & M68K_TCR_PAGE_8K) { 87088b2fef6SLaurent Vivier page_bits = 13; 87188b2fef6SLaurent Vivier } else { 87288b2fef6SLaurent Vivier page_bits = 12; 87388b2fef6SLaurent Vivier } 87488b2fef6SLaurent Vivier *page_size = 1 << page_bits; 87588b2fef6SLaurent Vivier page_mask = ~(*page_size - 1); 876852002b5SMark Cave-Ayland *physical = (next & page_mask) + (address & (*page_size - 1)); 87788b2fef6SLaurent Vivier 878e55886c3SLaurent Vivier if (access_type & ACCESS_PTEST) { 879e55886c3SLaurent Vivier env->mmu.mmusr |= next & M68K_MMU_SR_MASK_040; 880e55886c3SLaurent Vivier env->mmu.mmusr |= *physical & 0xfffff000; 881e55886c3SLaurent Vivier env->mmu.mmusr |= M68K_MMU_R_040; 882e55886c3SLaurent Vivier } 883e55886c3SLaurent Vivier 88488b2fef6SLaurent Vivier if (next & M68K_DESC_WRITEPROT) { 88588b2fef6SLaurent Vivier *prot &= ~PAGE_WRITE; 88688b2fef6SLaurent Vivier if (access_type & ACCESS_STORE) { 88788b2fef6SLaurent Vivier return -1; 88888b2fef6SLaurent Vivier } 88988b2fef6SLaurent Vivier } 89088b2fef6SLaurent Vivier if (next & M68K_DESC_SUPERONLY) { 89188b2fef6SLaurent Vivier if ((access_type & ACCESS_SUPER) == 0) { 89288b2fef6SLaurent Vivier return -1; 89388b2fef6SLaurent Vivier } 89488b2fef6SLaurent Vivier } 89588b2fef6SLaurent Vivier 89688b2fef6SLaurent Vivier return 0; 897adcf0bf0SPeter Maydell 898adcf0bf0SPeter Maydell txfail: 899adcf0bf0SPeter Maydell /* 900adcf0bf0SPeter Maydell * A page table load/store failed. TODO: we should really raise a 901adcf0bf0SPeter Maydell * suitable guest fault here if this is not a debug access. 902adcf0bf0SPeter Maydell * For now just return that the translation failed. 903adcf0bf0SPeter Maydell */ 904adcf0bf0SPeter Maydell return -1; 90588b2fef6SLaurent Vivier } 90688b2fef6SLaurent Vivier 90700b941e5SAndreas Färber hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 9084fcc562bSPaul Brook { 909e22a4560SPhilippe Mathieu-Daudé CPUM68KState *env = cpu_env(cs); 91088b2fef6SLaurent Vivier hwaddr phys_addr; 91188b2fef6SLaurent Vivier int prot; 91288b2fef6SLaurent Vivier int access_type; 91388b2fef6SLaurent Vivier target_ulong page_size; 91488b2fef6SLaurent Vivier 91588b2fef6SLaurent Vivier if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) { 91688b2fef6SLaurent Vivier /* MMU disabled */ 9174fcc562bSPaul Brook return addr; 9184fcc562bSPaul Brook } 9194fcc562bSPaul Brook 92088b2fef6SLaurent Vivier access_type = ACCESS_DATA | ACCESS_DEBUG; 92188b2fef6SLaurent Vivier if (env->sr & SR_S) { 92288b2fef6SLaurent Vivier access_type |= ACCESS_SUPER; 92388b2fef6SLaurent Vivier } 92478318119SMark Cave-Ayland 92588b2fef6SLaurent Vivier if (get_physical_address(env, &phys_addr, &prot, 92688b2fef6SLaurent Vivier addr, access_type, &page_size) != 0) { 92788b2fef6SLaurent Vivier return -1; 92888b2fef6SLaurent Vivier } 92978318119SMark Cave-Ayland 93088b2fef6SLaurent Vivier return phys_addr; 93188b2fef6SLaurent Vivier } 93288b2fef6SLaurent Vivier 933fe5f7b1bSRichard Henderson /* 934fe5f7b1bSRichard Henderson * Notify CPU of a pending interrupt. Prioritization and vectoring should 935fe5f7b1bSRichard Henderson * be handled by the interrupt controller. Real hardware only requests 936fe5f7b1bSRichard Henderson * the vector when the interrupt is acknowledged by the CPU. For 937fe5f7b1bSRichard Henderson * simplicity we calculate it when the interrupt is signalled. 938fe5f7b1bSRichard Henderson */ 939fe5f7b1bSRichard Henderson void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) 940fe5f7b1bSRichard Henderson { 941fe5f7b1bSRichard Henderson CPUState *cs = CPU(cpu); 942fe5f7b1bSRichard Henderson CPUM68KState *env = &cpu->env; 943fe5f7b1bSRichard Henderson 944fe5f7b1bSRichard Henderson env->pending_level = level; 945fe5f7b1bSRichard Henderson env->pending_vector = vector; 946fe5f7b1bSRichard Henderson if (level) { 947fe5f7b1bSRichard Henderson cpu_interrupt(cs, CPU_INTERRUPT_HARD); 948fe5f7b1bSRichard Henderson } else { 949fe5f7b1bSRichard Henderson cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 950fe5f7b1bSRichard Henderson } 951fe5f7b1bSRichard Henderson } 952fe5f7b1bSRichard Henderson 953fe5f7b1bSRichard Henderson bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 954fe5f7b1bSRichard Henderson MMUAccessType qemu_access_type, int mmu_idx, 955fe5f7b1bSRichard Henderson bool probe, uintptr_t retaddr) 9560633879fSpbrook { 957e22a4560SPhilippe Mathieu-Daudé CPUM68KState *env = cpu_env(cs); 95888b2fef6SLaurent Vivier hwaddr physical; 9590633879fSpbrook int prot; 96088b2fef6SLaurent Vivier int access_type; 96188b2fef6SLaurent Vivier int ret; 96288b2fef6SLaurent Vivier target_ulong page_size; 9630633879fSpbrook 96488b2fef6SLaurent Vivier if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) { 96588b2fef6SLaurent Vivier /* MMU disabled */ 96688b2fef6SLaurent Vivier tlb_set_page(cs, address & TARGET_PAGE_MASK, 96788b2fef6SLaurent Vivier address & TARGET_PAGE_MASK, 96888b2fef6SLaurent Vivier PAGE_READ | PAGE_WRITE | PAGE_EXEC, 96988b2fef6SLaurent Vivier mmu_idx, TARGET_PAGE_SIZE); 970fe5f7b1bSRichard Henderson return true; 9710633879fSpbrook } 9720633879fSpbrook 973fe5f7b1bSRichard Henderson if (qemu_access_type == MMU_INST_FETCH) { 97488b2fef6SLaurent Vivier access_type = ACCESS_CODE; 97588b2fef6SLaurent Vivier } else { 97688b2fef6SLaurent Vivier access_type = ACCESS_DATA; 977fe5f7b1bSRichard Henderson if (qemu_access_type == MMU_DATA_STORE) { 97888b2fef6SLaurent Vivier access_type |= ACCESS_STORE; 97988b2fef6SLaurent Vivier } 98088b2fef6SLaurent Vivier } 98188b2fef6SLaurent Vivier if (mmu_idx != MMU_USER_IDX) { 98288b2fef6SLaurent Vivier access_type |= ACCESS_SUPER; 98388b2fef6SLaurent Vivier } 98488b2fef6SLaurent Vivier 985ee1004bbSPhilippe Mathieu-Daudé ret = get_physical_address(env, &physical, &prot, 98688b2fef6SLaurent Vivier address, access_type, &page_size); 987fe5f7b1bSRichard Henderson if (likely(ret == 0)) { 988852002b5SMark Cave-Ayland tlb_set_page(cs, address & TARGET_PAGE_MASK, 989852002b5SMark Cave-Ayland physical & TARGET_PAGE_MASK, prot, mmu_idx, page_size); 990fe5f7b1bSRichard Henderson return true; 99188b2fef6SLaurent Vivier } 992fe5f7b1bSRichard Henderson 993fe5f7b1bSRichard Henderson if (probe) { 994fe5f7b1bSRichard Henderson return false; 995fe5f7b1bSRichard Henderson } 996fe5f7b1bSRichard Henderson 99788b2fef6SLaurent Vivier /* page fault */ 99888b2fef6SLaurent Vivier env->mmu.ssw = M68K_ATC_040; 99988b2fef6SLaurent Vivier switch (size) { 100088b2fef6SLaurent Vivier case 1: 100188b2fef6SLaurent Vivier env->mmu.ssw |= M68K_BA_SIZE_BYTE; 100288b2fef6SLaurent Vivier break; 100388b2fef6SLaurent Vivier case 2: 100488b2fef6SLaurent Vivier env->mmu.ssw |= M68K_BA_SIZE_WORD; 100588b2fef6SLaurent Vivier break; 100688b2fef6SLaurent Vivier case 4: 100788b2fef6SLaurent Vivier env->mmu.ssw |= M68K_BA_SIZE_LONG; 100888b2fef6SLaurent Vivier break; 100988b2fef6SLaurent Vivier } 101088b2fef6SLaurent Vivier if (access_type & ACCESS_SUPER) { 101188b2fef6SLaurent Vivier env->mmu.ssw |= M68K_TM_040_SUPER; 101288b2fef6SLaurent Vivier } 101388b2fef6SLaurent Vivier if (access_type & ACCESS_CODE) { 101488b2fef6SLaurent Vivier env->mmu.ssw |= M68K_TM_040_CODE; 101588b2fef6SLaurent Vivier } else { 101688b2fef6SLaurent Vivier env->mmu.ssw |= M68K_TM_040_DATA; 101788b2fef6SLaurent Vivier } 101888b2fef6SLaurent Vivier if (!(access_type & ACCESS_STORE)) { 101988b2fef6SLaurent Vivier env->mmu.ssw |= M68K_RW_040; 102088b2fef6SLaurent Vivier } 1021fe5f7b1bSRichard Henderson 102288b2fef6SLaurent Vivier cs->exception_index = EXCP_ACCESS; 1023fe5f7b1bSRichard Henderson env->mmu.ar = address; 1024fe5f7b1bSRichard Henderson cpu_loop_exit_restore(cs, retaddr); 102588b2fef6SLaurent Vivier } 1026028772c4SRichard Henderson #endif /* !CONFIG_USER_ONLY */ 102788b2fef6SLaurent Vivier 1028e1f3808eSpbrook uint32_t HELPER(bitrev)(uint32_t x) 1029e1f3808eSpbrook { 1030e1f3808eSpbrook x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau); 1031e1f3808eSpbrook x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu); 1032e1f3808eSpbrook x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u); 1033e1f3808eSpbrook return bswap32(x); 1034e1f3808eSpbrook } 1035e1f3808eSpbrook 1036e1f3808eSpbrook uint32_t HELPER(ff1)(uint32_t x) 1037e1f3808eSpbrook { 1038e1f3808eSpbrook int n; 1039e1f3808eSpbrook for (n = 32; x; n--) 1040e1f3808eSpbrook x >>= 1; 1041e1f3808eSpbrook return n; 1042e1f3808eSpbrook } 1043e1f3808eSpbrook 1044620c6cf6SRichard Henderson uint32_t HELPER(sats)(uint32_t val, uint32_t v) 1045e1f3808eSpbrook { 1046e1f3808eSpbrook /* The result has the opposite sign to the original value. */ 1047620c6cf6SRichard Henderson if ((int32_t)v < 0) { 1048e1f3808eSpbrook val = (((int32_t)val) >> 31) ^ SIGNBIT; 1049620c6cf6SRichard Henderson } 1050e1f3808eSpbrook return val; 1051e1f3808eSpbrook } 1052e1f3808eSpbrook 1053d2f8fb8eSLaurent Vivier void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr) 1054e1f3808eSpbrook { 1055d2f8fb8eSLaurent Vivier env->sr = sr & 0xffe0; 1056d2f8fb8eSLaurent Vivier cpu_m68k_set_ccr(env, sr); 1057e1f3808eSpbrook m68k_switch_sp(env); 1058e1f3808eSpbrook } 1059e1f3808eSpbrook 1060d2f8fb8eSLaurent Vivier void HELPER(set_sr)(CPUM68KState *env, uint32_t val) 1061d2f8fb8eSLaurent Vivier { 1062d2f8fb8eSLaurent Vivier cpu_m68k_set_sr(env, val); 1063d2f8fb8eSLaurent Vivier } 1064e1f3808eSpbrook 1065e1f3808eSpbrook /* MAC unit. */ 1066808d77bcSLucien Murray-Pitts /* 1067808d77bcSLucien Murray-Pitts * FIXME: The MAC unit implementation is a bit of a mess. Some helpers 1068808d77bcSLucien Murray-Pitts * take values, others take register numbers and manipulate the contents 1069808d77bcSLucien Murray-Pitts * in-place. 1070808d77bcSLucien Murray-Pitts */ 10712b3e3cfeSAndreas Färber void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src) 1072e1f3808eSpbrook { 1073e1f3808eSpbrook uint32_t mask; 1074e1f3808eSpbrook env->macc[dest] = env->macc[src]; 1075e1f3808eSpbrook mask = MACSR_PAV0 << dest; 1076e1f3808eSpbrook if (env->macsr & (MACSR_PAV0 << src)) 1077e1f3808eSpbrook env->macsr |= mask; 1078e1f3808eSpbrook else 1079e1f3808eSpbrook env->macsr &= ~mask; 1080e1f3808eSpbrook } 1081e1f3808eSpbrook 10822b3e3cfeSAndreas Färber uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2) 1083e1f3808eSpbrook { 1084e1f3808eSpbrook int64_t product; 1085e1f3808eSpbrook int64_t res; 1086e1f3808eSpbrook 1087e1f3808eSpbrook product = (uint64_t)op1 * op2; 1088e1f3808eSpbrook res = (product << 24) >> 24; 1089e1f3808eSpbrook if (res != product) { 1090e1f3808eSpbrook env->macsr |= MACSR_V; 1091e1f3808eSpbrook if (env->macsr & MACSR_OMC) { 1092e1f3808eSpbrook /* Make sure the accumulate operation overflows. */ 1093e1f3808eSpbrook if (product < 0) 1094e1f3808eSpbrook res = ~(1ll << 50); 1095e1f3808eSpbrook else 1096e1f3808eSpbrook res = 1ll << 50; 1097e1f3808eSpbrook } 1098e1f3808eSpbrook } 1099e1f3808eSpbrook return res; 1100e1f3808eSpbrook } 1101e1f3808eSpbrook 11022b3e3cfeSAndreas Färber uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2) 1103e1f3808eSpbrook { 1104e1f3808eSpbrook uint64_t product; 1105e1f3808eSpbrook 1106e1f3808eSpbrook product = (uint64_t)op1 * op2; 1107e1f3808eSpbrook if (product & (0xffffffull << 40)) { 1108e1f3808eSpbrook env->macsr |= MACSR_V; 1109e1f3808eSpbrook if (env->macsr & MACSR_OMC) { 1110e1f3808eSpbrook /* Make sure the accumulate operation overflows. */ 1111e1f3808eSpbrook product = 1ll << 50; 1112e1f3808eSpbrook } else { 1113e1f3808eSpbrook product &= ((1ull << 40) - 1); 1114e1f3808eSpbrook } 1115e1f3808eSpbrook } 1116e1f3808eSpbrook return product; 1117e1f3808eSpbrook } 1118e1f3808eSpbrook 11192b3e3cfeSAndreas Färber uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2) 1120e1f3808eSpbrook { 1121e1f3808eSpbrook uint64_t product; 1122e1f3808eSpbrook uint32_t remainder; 1123e1f3808eSpbrook 1124e1f3808eSpbrook product = (uint64_t)op1 * op2; 1125e1f3808eSpbrook if (env->macsr & MACSR_RT) { 1126e1f3808eSpbrook remainder = product & 0xffffff; 1127e1f3808eSpbrook product >>= 24; 1128e1f3808eSpbrook if (remainder > 0x800000) 1129e1f3808eSpbrook product++; 1130e1f3808eSpbrook else if (remainder == 0x800000) 1131e1f3808eSpbrook product += (product & 1); 1132e1f3808eSpbrook } else { 1133e1f3808eSpbrook product >>= 24; 1134e1f3808eSpbrook } 1135e1f3808eSpbrook return product; 1136e1f3808eSpbrook } 1137e1f3808eSpbrook 11382b3e3cfeSAndreas Färber void HELPER(macsats)(CPUM68KState *env, uint32_t acc) 1139e1f3808eSpbrook { 1140e1f3808eSpbrook int64_t tmp; 1141e1f3808eSpbrook int64_t result; 1142e1f3808eSpbrook tmp = env->macc[acc]; 1143e1f3808eSpbrook result = ((tmp << 16) >> 16); 1144e1f3808eSpbrook if (result != tmp) { 1145e1f3808eSpbrook env->macsr |= MACSR_V; 1146e1f3808eSpbrook } 1147e1f3808eSpbrook if (env->macsr & MACSR_V) { 1148e1f3808eSpbrook env->macsr |= MACSR_PAV0 << acc; 1149e1f3808eSpbrook if (env->macsr & MACSR_OMC) { 1150808d77bcSLucien Murray-Pitts /* 1151808d77bcSLucien Murray-Pitts * The result is saturated to 32 bits, despite overflow occurring 1152808d77bcSLucien Murray-Pitts * at 48 bits. Seems weird, but that's what the hardware docs 1153808d77bcSLucien Murray-Pitts * say. 1154808d77bcSLucien Murray-Pitts */ 1155e1f3808eSpbrook result = (result >> 63) ^ 0x7fffffff; 1156e1f3808eSpbrook } 1157e1f3808eSpbrook } 1158e1f3808eSpbrook env->macc[acc] = result; 1159e1f3808eSpbrook } 1160e1f3808eSpbrook 11612b3e3cfeSAndreas Färber void HELPER(macsatu)(CPUM68KState *env, uint32_t acc) 1162e1f3808eSpbrook { 1163e1f3808eSpbrook uint64_t val; 1164e1f3808eSpbrook 1165e1f3808eSpbrook val = env->macc[acc]; 1166e1f3808eSpbrook if (val & (0xffffull << 48)) { 1167e1f3808eSpbrook env->macsr |= MACSR_V; 1168e1f3808eSpbrook } 1169e1f3808eSpbrook if (env->macsr & MACSR_V) { 1170e1f3808eSpbrook env->macsr |= MACSR_PAV0 << acc; 1171e1f3808eSpbrook if (env->macsr & MACSR_OMC) { 1172e1f3808eSpbrook if (val > (1ull << 53)) 1173e1f3808eSpbrook val = 0; 1174e1f3808eSpbrook else 1175e1f3808eSpbrook val = (1ull << 48) - 1; 1176e1f3808eSpbrook } else { 1177e1f3808eSpbrook val &= ((1ull << 48) - 1); 1178e1f3808eSpbrook } 1179e1f3808eSpbrook } 1180e1f3808eSpbrook env->macc[acc] = val; 1181e1f3808eSpbrook } 1182e1f3808eSpbrook 11832b3e3cfeSAndreas Färber void HELPER(macsatf)(CPUM68KState *env, uint32_t acc) 1184e1f3808eSpbrook { 1185e1f3808eSpbrook int64_t sum; 1186e1f3808eSpbrook int64_t result; 1187e1f3808eSpbrook 1188e1f3808eSpbrook sum = env->macc[acc]; 1189e1f3808eSpbrook result = (sum << 16) >> 16; 1190e1f3808eSpbrook if (result != sum) { 1191e1f3808eSpbrook env->macsr |= MACSR_V; 1192e1f3808eSpbrook } 1193e1f3808eSpbrook if (env->macsr & MACSR_V) { 1194e1f3808eSpbrook env->macsr |= MACSR_PAV0 << acc; 1195e1f3808eSpbrook if (env->macsr & MACSR_OMC) { 1196e1f3808eSpbrook result = (result >> 63) ^ 0x7fffffffffffll; 1197e1f3808eSpbrook } 1198e1f3808eSpbrook } 1199e1f3808eSpbrook env->macc[acc] = result; 1200e1f3808eSpbrook } 1201e1f3808eSpbrook 12022b3e3cfeSAndreas Färber void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc) 1203e1f3808eSpbrook { 1204e1f3808eSpbrook uint64_t val; 1205e1f3808eSpbrook val = env->macc[acc]; 1206c4162574SBlue Swirl if (val == 0) { 1207e1f3808eSpbrook env->macsr |= MACSR_Z; 1208c4162574SBlue Swirl } else if (val & (1ull << 47)) { 1209e1f3808eSpbrook env->macsr |= MACSR_N; 1210c4162574SBlue Swirl } 1211e1f3808eSpbrook if (env->macsr & (MACSR_PAV0 << acc)) { 1212e1f3808eSpbrook env->macsr |= MACSR_V; 1213e1f3808eSpbrook } 1214e1f3808eSpbrook if (env->macsr & MACSR_FI) { 1215e1f3808eSpbrook val = ((int64_t)val) >> 40; 1216e1f3808eSpbrook if (val != 0 && val != -1) 1217e1f3808eSpbrook env->macsr |= MACSR_EV; 1218e1f3808eSpbrook } else if (env->macsr & MACSR_SU) { 1219e1f3808eSpbrook val = ((int64_t)val) >> 32; 1220e1f3808eSpbrook if (val != 0 && val != -1) 1221e1f3808eSpbrook env->macsr |= MACSR_EV; 1222e1f3808eSpbrook } else { 1223e1f3808eSpbrook if ((val >> 32) != 0) 1224e1f3808eSpbrook env->macsr |= MACSR_EV; 1225e1f3808eSpbrook } 1226e1f3808eSpbrook } 1227e1f3808eSpbrook 1228db3d7945SLaurent Vivier #define EXTSIGN(val, index) ( \ 1229db3d7945SLaurent Vivier (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \ 1230db3d7945SLaurent Vivier ) 1231620c6cf6SRichard Henderson 1232620c6cf6SRichard Henderson #define COMPUTE_CCR(op, x, n, z, v, c) { \ 1233620c6cf6SRichard Henderson switch (op) { \ 1234620c6cf6SRichard Henderson case CC_OP_FLAGS: \ 1235620c6cf6SRichard Henderson /* Everything in place. */ \ 1236620c6cf6SRichard Henderson break; \ 1237db3d7945SLaurent Vivier case CC_OP_ADDB: \ 1238db3d7945SLaurent Vivier case CC_OP_ADDW: \ 1239db3d7945SLaurent Vivier case CC_OP_ADDL: \ 1240620c6cf6SRichard Henderson res = n; \ 1241620c6cf6SRichard Henderson src2 = v; \ 1242db3d7945SLaurent Vivier src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \ 1243620c6cf6SRichard Henderson c = x; \ 1244620c6cf6SRichard Henderson z = n; \ 1245620c6cf6SRichard Henderson v = (res ^ src1) & ~(src1 ^ src2); \ 1246620c6cf6SRichard Henderson break; \ 1247db3d7945SLaurent Vivier case CC_OP_SUBB: \ 1248db3d7945SLaurent Vivier case CC_OP_SUBW: \ 1249db3d7945SLaurent Vivier case CC_OP_SUBL: \ 1250620c6cf6SRichard Henderson res = n; \ 1251620c6cf6SRichard Henderson src2 = v; \ 1252db3d7945SLaurent Vivier src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \ 1253620c6cf6SRichard Henderson c = x; \ 1254620c6cf6SRichard Henderson z = n; \ 1255620c6cf6SRichard Henderson v = (res ^ src1) & (src1 ^ src2); \ 1256620c6cf6SRichard Henderson break; \ 1257db3d7945SLaurent Vivier case CC_OP_CMPB: \ 1258db3d7945SLaurent Vivier case CC_OP_CMPW: \ 1259db3d7945SLaurent Vivier case CC_OP_CMPL: \ 1260620c6cf6SRichard Henderson src1 = n; \ 1261620c6cf6SRichard Henderson src2 = v; \ 1262db3d7945SLaurent Vivier res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \ 1263620c6cf6SRichard Henderson n = res; \ 1264620c6cf6SRichard Henderson z = res; \ 1265620c6cf6SRichard Henderson c = src1 < src2; \ 1266620c6cf6SRichard Henderson v = (res ^ src1) & (src1 ^ src2); \ 1267620c6cf6SRichard Henderson break; \ 1268620c6cf6SRichard Henderson case CC_OP_LOGIC: \ 1269620c6cf6SRichard Henderson c = v = 0; \ 1270620c6cf6SRichard Henderson z = n; \ 1271620c6cf6SRichard Henderson break; \ 1272620c6cf6SRichard Henderson default: \ 1273a8d92fd8SRichard Henderson cpu_abort(env_cpu(env), "Bad CC_OP %d", op); \ 1274620c6cf6SRichard Henderson } \ 1275620c6cf6SRichard Henderson } while (0) 1276620c6cf6SRichard Henderson 1277620c6cf6SRichard Henderson uint32_t cpu_m68k_get_ccr(CPUM68KState *env) 1278e1f3808eSpbrook { 1279620c6cf6SRichard Henderson uint32_t x, c, n, z, v; 1280620c6cf6SRichard Henderson uint32_t res, src1, src2; 1281620c6cf6SRichard Henderson 1282620c6cf6SRichard Henderson x = env->cc_x; 1283620c6cf6SRichard Henderson n = env->cc_n; 1284620c6cf6SRichard Henderson z = env->cc_z; 1285620c6cf6SRichard Henderson v = env->cc_v; 1286db3d7945SLaurent Vivier c = env->cc_c; 1287620c6cf6SRichard Henderson 1288620c6cf6SRichard Henderson COMPUTE_CCR(env->cc_op, x, n, z, v, c); 1289620c6cf6SRichard Henderson 1290620c6cf6SRichard Henderson n = n >> 31; 1291620c6cf6SRichard Henderson z = (z == 0); 1292db3d7945SLaurent Vivier v = v >> 31; 1293620c6cf6SRichard Henderson 1294620c6cf6SRichard Henderson return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C; 1295620c6cf6SRichard Henderson } 1296620c6cf6SRichard Henderson 1297620c6cf6SRichard Henderson uint32_t HELPER(get_ccr)(CPUM68KState *env) 1298620c6cf6SRichard Henderson { 1299620c6cf6SRichard Henderson return cpu_m68k_get_ccr(env); 1300620c6cf6SRichard Henderson } 1301620c6cf6SRichard Henderson 1302620c6cf6SRichard Henderson void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr) 1303620c6cf6SRichard Henderson { 1304620c6cf6SRichard Henderson env->cc_x = (ccr & CCF_X ? 1 : 0); 1305620c6cf6SRichard Henderson env->cc_n = (ccr & CCF_N ? -1 : 0); 1306620c6cf6SRichard Henderson env->cc_z = (ccr & CCF_Z ? 0 : 1); 1307620c6cf6SRichard Henderson env->cc_v = (ccr & CCF_V ? -1 : 0); 1308620c6cf6SRichard Henderson env->cc_c = (ccr & CCF_C ? 1 : 0); 1309620c6cf6SRichard Henderson env->cc_op = CC_OP_FLAGS; 1310620c6cf6SRichard Henderson } 1311620c6cf6SRichard Henderson 1312620c6cf6SRichard Henderson void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr) 1313620c6cf6SRichard Henderson { 1314620c6cf6SRichard Henderson cpu_m68k_set_ccr(env, ccr); 1315620c6cf6SRichard Henderson } 1316620c6cf6SRichard Henderson 1317620c6cf6SRichard Henderson void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op) 1318620c6cf6SRichard Henderson { 1319620c6cf6SRichard Henderson uint32_t res, src1, src2; 1320620c6cf6SRichard Henderson 1321620c6cf6SRichard Henderson COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c); 1322620c6cf6SRichard Henderson env->cc_op = CC_OP_FLAGS; 1323e1f3808eSpbrook } 1324e1f3808eSpbrook 13252b3e3cfeSAndreas Färber uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val) 1326e1f3808eSpbrook { 1327e1f3808eSpbrook int rem; 1328e1f3808eSpbrook uint32_t result; 1329e1f3808eSpbrook 1330e1f3808eSpbrook if (env->macsr & MACSR_SU) { 1331e1f3808eSpbrook /* 16-bit rounding. */ 1332e1f3808eSpbrook rem = val & 0xffffff; 1333e1f3808eSpbrook val = (val >> 24) & 0xffffu; 1334e1f3808eSpbrook if (rem > 0x800000) 1335e1f3808eSpbrook val++; 1336e1f3808eSpbrook else if (rem == 0x800000) 1337e1f3808eSpbrook val += (val & 1); 1338e1f3808eSpbrook } else if (env->macsr & MACSR_RT) { 1339e1f3808eSpbrook /* 32-bit rounding. */ 1340e1f3808eSpbrook rem = val & 0xff; 1341e1f3808eSpbrook val >>= 8; 1342e1f3808eSpbrook if (rem > 0x80) 1343e1f3808eSpbrook val++; 1344e1f3808eSpbrook else if (rem == 0x80) 1345e1f3808eSpbrook val += (val & 1); 1346e1f3808eSpbrook } else { 1347e1f3808eSpbrook /* No rounding. */ 1348e1f3808eSpbrook val >>= 8; 1349e1f3808eSpbrook } 1350e1f3808eSpbrook if (env->macsr & MACSR_OMC) { 1351e1f3808eSpbrook /* Saturate. */ 1352e1f3808eSpbrook if (env->macsr & MACSR_SU) { 1353e1f3808eSpbrook if (val != (uint16_t) val) { 1354e1f3808eSpbrook result = ((val >> 63) ^ 0x7fff) & 0xffff; 1355e1f3808eSpbrook } else { 1356e1f3808eSpbrook result = val & 0xffff; 1357e1f3808eSpbrook } 1358e1f3808eSpbrook } else { 1359e1f3808eSpbrook if (val != (uint32_t)val) { 1360e1f3808eSpbrook result = ((uint32_t)(val >> 63) & 0x7fffffff); 1361e1f3808eSpbrook } else { 1362e1f3808eSpbrook result = (uint32_t)val; 1363e1f3808eSpbrook } 1364e1f3808eSpbrook } 1365e1f3808eSpbrook } else { 1366e1f3808eSpbrook /* No saturation. */ 1367e1f3808eSpbrook if (env->macsr & MACSR_SU) { 1368e1f3808eSpbrook result = val & 0xffff; 1369e1f3808eSpbrook } else { 1370e1f3808eSpbrook result = (uint32_t)val; 1371e1f3808eSpbrook } 1372e1f3808eSpbrook } 1373e1f3808eSpbrook return result; 1374e1f3808eSpbrook } 1375e1f3808eSpbrook 1376e1f3808eSpbrook uint32_t HELPER(get_macs)(uint64_t val) 1377e1f3808eSpbrook { 1378e1f3808eSpbrook if (val == (int32_t)val) { 1379e1f3808eSpbrook return (int32_t)val; 1380e1f3808eSpbrook } else { 1381e1f3808eSpbrook return (val >> 61) ^ ~SIGNBIT; 1382e1f3808eSpbrook } 1383e1f3808eSpbrook } 1384e1f3808eSpbrook 1385e1f3808eSpbrook uint32_t HELPER(get_macu)(uint64_t val) 1386e1f3808eSpbrook { 1387e1f3808eSpbrook if ((val >> 32) == 0) { 1388e1f3808eSpbrook return (uint32_t)val; 1389e1f3808eSpbrook } else { 1390e1f3808eSpbrook return 0xffffffffu; 1391e1f3808eSpbrook } 1392e1f3808eSpbrook } 1393e1f3808eSpbrook 13942b3e3cfeSAndreas Färber uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc) 1395e1f3808eSpbrook { 1396e1f3808eSpbrook uint32_t val; 1397e1f3808eSpbrook val = env->macc[acc] & 0x00ff; 13985ce747cfSPaolo Bonzini val |= (env->macc[acc] >> 32) & 0xff00; 1399e1f3808eSpbrook val |= (env->macc[acc + 1] << 16) & 0x00ff0000; 1400e1f3808eSpbrook val |= (env->macc[acc + 1] >> 16) & 0xff000000; 1401e1f3808eSpbrook return val; 1402e1f3808eSpbrook } 1403e1f3808eSpbrook 14042b3e3cfeSAndreas Färber uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc) 1405e1f3808eSpbrook { 1406e1f3808eSpbrook uint32_t val; 1407e1f3808eSpbrook val = (env->macc[acc] >> 32) & 0xffff; 1408e1f3808eSpbrook val |= (env->macc[acc + 1] >> 16) & 0xffff0000; 1409e1f3808eSpbrook return val; 1410e1f3808eSpbrook } 1411e1f3808eSpbrook 14122b3e3cfeSAndreas Färber void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc) 1413e1f3808eSpbrook { 1414e1f3808eSpbrook int64_t res; 1415e1f3808eSpbrook int32_t tmp; 1416e1f3808eSpbrook res = env->macc[acc] & 0xffffffff00ull; 1417e1f3808eSpbrook tmp = (int16_t)(val & 0xff00); 1418e1f3808eSpbrook res |= ((int64_t)tmp) << 32; 1419e1f3808eSpbrook res |= val & 0xff; 1420e1f3808eSpbrook env->macc[acc] = res; 1421e1f3808eSpbrook res = env->macc[acc + 1] & 0xffffffff00ull; 1422e1f3808eSpbrook tmp = (val & 0xff000000); 1423e1f3808eSpbrook res |= ((int64_t)tmp) << 16; 1424e1f3808eSpbrook res |= (val >> 16) & 0xff; 1425e1f3808eSpbrook env->macc[acc + 1] = res; 1426e1f3808eSpbrook } 1427e1f3808eSpbrook 14282b3e3cfeSAndreas Färber void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc) 1429e1f3808eSpbrook { 1430e1f3808eSpbrook int64_t res; 1431e1f3808eSpbrook int32_t tmp; 1432e1f3808eSpbrook res = (uint32_t)env->macc[acc]; 1433e1f3808eSpbrook tmp = (int16_t)val; 1434e1f3808eSpbrook res |= ((int64_t)tmp) << 32; 1435e1f3808eSpbrook env->macc[acc] = res; 1436e1f3808eSpbrook res = (uint32_t)env->macc[acc + 1]; 1437e1f3808eSpbrook tmp = val & 0xffff0000; 1438e1f3808eSpbrook res |= (int64_t)tmp << 16; 1439e1f3808eSpbrook env->macc[acc + 1] = res; 1440e1f3808eSpbrook } 1441e1f3808eSpbrook 14422b3e3cfeSAndreas Färber void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc) 1443e1f3808eSpbrook { 1444e1f3808eSpbrook uint64_t res; 1445e1f3808eSpbrook res = (uint32_t)env->macc[acc]; 1446e1f3808eSpbrook res |= ((uint64_t)(val & 0xffff)) << 32; 1447e1f3808eSpbrook env->macc[acc] = res; 1448e1f3808eSpbrook res = (uint32_t)env->macc[acc + 1]; 1449e1f3808eSpbrook res |= (uint64_t)(val & 0xffff0000) << 16; 1450e1f3808eSpbrook env->macc[acc + 1] = res; 1451e1f3808eSpbrook } 14520bdb2b3bSLaurent Vivier 14536a140586SPhilippe Mathieu-Daudé #if !defined(CONFIG_USER_ONLY) 1454e55886c3SLaurent Vivier void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read) 1455e55886c3SLaurent Vivier { 1456e55886c3SLaurent Vivier hwaddr physical; 1457e55886c3SLaurent Vivier int access_type; 1458e55886c3SLaurent Vivier int prot; 1459e55886c3SLaurent Vivier int ret; 1460e55886c3SLaurent Vivier target_ulong page_size; 1461e55886c3SLaurent Vivier 1462e55886c3SLaurent Vivier access_type = ACCESS_PTEST; 1463e55886c3SLaurent Vivier if (env->dfc & 4) { 1464e55886c3SLaurent Vivier access_type |= ACCESS_SUPER; 1465e55886c3SLaurent Vivier } 1466e55886c3SLaurent Vivier if ((env->dfc & 3) == 2) { 1467e55886c3SLaurent Vivier access_type |= ACCESS_CODE; 1468e55886c3SLaurent Vivier } 1469e55886c3SLaurent Vivier if (!is_read) { 1470e55886c3SLaurent Vivier access_type |= ACCESS_STORE; 1471e55886c3SLaurent Vivier } 1472e55886c3SLaurent Vivier 1473e55886c3SLaurent Vivier env->mmu.mmusr = 0; 1474e55886c3SLaurent Vivier env->mmu.ssw = 0; 1475e55886c3SLaurent Vivier ret = get_physical_address(env, &physical, &prot, addr, 1476e55886c3SLaurent Vivier access_type, &page_size); 1477e55886c3SLaurent Vivier if (ret == 0) { 1478852002b5SMark Cave-Ayland tlb_set_page(env_cpu(env), addr & TARGET_PAGE_MASK, 1479852002b5SMark Cave-Ayland physical & TARGET_PAGE_MASK, 1480e55886c3SLaurent Vivier prot, access_type & ACCESS_SUPER ? 1481e55886c3SLaurent Vivier MMU_KERNEL_IDX : MMU_USER_IDX, page_size); 1482e55886c3SLaurent Vivier } 1483e55886c3SLaurent Vivier } 1484e55886c3SLaurent Vivier 1485e55886c3SLaurent Vivier void HELPER(pflush)(CPUM68KState *env, uint32_t addr, uint32_t opmode) 1486e55886c3SLaurent Vivier { 1487a8d92fd8SRichard Henderson CPUState *cs = env_cpu(env); 1488e55886c3SLaurent Vivier 1489e55886c3SLaurent Vivier switch (opmode) { 1490e55886c3SLaurent Vivier case 0: /* Flush page entry if not global */ 1491e55886c3SLaurent Vivier case 1: /* Flush page entry */ 1492a8d92fd8SRichard Henderson tlb_flush_page(cs, addr); 1493e55886c3SLaurent Vivier break; 1494e55886c3SLaurent Vivier case 2: /* Flush all except global entries */ 1495a8d92fd8SRichard Henderson tlb_flush(cs); 1496e55886c3SLaurent Vivier break; 1497e55886c3SLaurent Vivier case 3: /* Flush all entries */ 1498a8d92fd8SRichard Henderson tlb_flush(cs); 1499e55886c3SLaurent Vivier break; 1500e55886c3SLaurent Vivier } 1501e55886c3SLaurent Vivier } 1502e55886c3SLaurent Vivier 15030bdb2b3bSLaurent Vivier void HELPER(reset)(CPUM68KState *env) 15040bdb2b3bSLaurent Vivier { 15050bdb2b3bSLaurent Vivier /* FIXME: reset all except CPU */ 15060bdb2b3bSLaurent Vivier } 15076a140586SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */ 1508