xref: /openbmc/qemu/target/m68k/helper.c (revision f15f7273ea55472d5904c53566c82369d81214c1)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  *  m68k op helpers
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  *  Copyright (c) 2006-2007 CodeSourcery
5fcf5ef2aSThomas Huth  *  Written by Paul Brook
6fcf5ef2aSThomas Huth  *
7fcf5ef2aSThomas Huth  * This library is free software; you can redistribute it and/or
8fcf5ef2aSThomas Huth  * modify it under the terms of the GNU Lesser General Public
9fcf5ef2aSThomas Huth  * License as published by the Free Software Foundation; either
10d749fb85SThomas Huth  * version 2.1 of the License, or (at your option) any later version.
11fcf5ef2aSThomas Huth  *
12fcf5ef2aSThomas Huth  * This library is distributed in the hope that it will be useful,
13fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15d749fb85SThomas Huth  * Lesser General Public License for more details.
16fcf5ef2aSThomas Huth  *
17fcf5ef2aSThomas Huth  * You should have received a copy of the GNU Lesser General Public
18fcf5ef2aSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19fcf5ef2aSThomas Huth  */
20fcf5ef2aSThomas Huth 
21fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22fcf5ef2aSThomas Huth #include "cpu.h"
23fcf5ef2aSThomas Huth #include "exec/exec-all.h"
2474781c08SPhilippe Mathieu-Daudé #include "exec/page-protection.h"
25fcf5ef2aSThomas Huth #include "exec/gdbstub.h"
26fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
274ea5fe99SAlex Bennée #include "gdbstub/helpers.h"
2824f91e81SAlex Bennée #include "fpu/softfloat.h"
290442428aSMarkus Armbruster #include "qemu/qemu-print.h"
30fcf5ef2aSThomas Huth 
31fcf5ef2aSThomas Huth #define SIGNBIT (1u << 31)
32fcf5ef2aSThomas Huth 
cf_fpu_gdb_get_reg(CPUState * cs,GByteArray * mem_buf,int n)3366260159SAkihiko Odaki static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
34fcf5ef2aSThomas Huth {
3566260159SAkihiko Odaki     M68kCPU *cpu = M68K_CPU(cs);
3666260159SAkihiko Odaki     CPUM68KState *env = &cpu->env;
3766260159SAkihiko Odaki 
38fcf5ef2aSThomas Huth     if (n < 8) {
39*ad58ba13SPeter Maydell         float_status s = {};
407ed51401SPeter Maydell         return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
41fcf5ef2aSThomas Huth     }
42ba624944SLaurent Vivier     switch (n) {
43ba624944SLaurent Vivier     case 8: /* fpcontrol */
44462474d7SAlex Bennée         return gdb_get_reg32(mem_buf, env->fpcr);
45ba624944SLaurent Vivier     case 9: /* fpstatus */
46462474d7SAlex Bennée         return gdb_get_reg32(mem_buf, env->fpsr);
47ba624944SLaurent Vivier     case 10: /* fpiar, not implemented */
48462474d7SAlex Bennée         return gdb_get_reg32(mem_buf, 0);
49fcf5ef2aSThomas Huth     }
50fcf5ef2aSThomas Huth     return 0;
51fcf5ef2aSThomas Huth }
52fcf5ef2aSThomas Huth 
cf_fpu_gdb_set_reg(CPUState * cs,uint8_t * mem_buf,int n)5366260159SAkihiko Odaki static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
54fcf5ef2aSThomas Huth {
5566260159SAkihiko Odaki     M68kCPU *cpu = M68K_CPU(cs);
5666260159SAkihiko Odaki     CPUM68KState *env = &cpu->env;
5766260159SAkihiko Odaki 
58fcf5ef2aSThomas Huth     if (n < 8) {
59*ad58ba13SPeter Maydell         float_status s = {};
603a76d302SPhilippe Mathieu-Daudé         env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
61fcf5ef2aSThomas Huth         return 8;
62fcf5ef2aSThomas Huth     }
63ba624944SLaurent Vivier     switch (n) {
64ba624944SLaurent Vivier     case 8: /* fpcontrol */
653a76d302SPhilippe Mathieu-Daudé         cpu_m68k_set_fpcr(env, ldl_be_p(mem_buf));
66ba624944SLaurent Vivier         return 4;
67ba624944SLaurent Vivier     case 9: /* fpstatus */
683a76d302SPhilippe Mathieu-Daudé         env->fpsr = ldl_be_p(mem_buf);
69ba624944SLaurent Vivier         return 4;
70ba624944SLaurent Vivier     case 10: /* fpiar, not implemented */
71fcf5ef2aSThomas Huth         return 4;
72fcf5ef2aSThomas Huth     }
73fcf5ef2aSThomas Huth     return 0;
74fcf5ef2aSThomas Huth }
75fcf5ef2aSThomas Huth 
m68k_fpu_gdb_get_reg(CPUState * cs,GByteArray * mem_buf,int n)7666260159SAkihiko Odaki static int m68k_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
775a4526b2SLaurent Vivier {
7866260159SAkihiko Odaki     M68kCPU *cpu = M68K_CPU(cs);
7966260159SAkihiko Odaki     CPUM68KState *env = &cpu->env;
8066260159SAkihiko Odaki 
815a4526b2SLaurent Vivier     if (n < 8) {
82462474d7SAlex Bennée         int len = gdb_get_reg16(mem_buf, env->fregs[n].l.upper);
834b27f9b0SPhilippe Mathieu-Daudé         len += gdb_get_reg16(mem_buf, 0);
844b27f9b0SPhilippe Mathieu-Daudé         len += gdb_get_reg64(mem_buf, env->fregs[n].l.lower);
85462474d7SAlex Bennée         return len;
865a4526b2SLaurent Vivier     }
875a4526b2SLaurent Vivier     switch (n) {
885a4526b2SLaurent Vivier     case 8: /* fpcontrol */
89462474d7SAlex Bennée         return gdb_get_reg32(mem_buf, env->fpcr);
905a4526b2SLaurent Vivier     case 9: /* fpstatus */
9158883579SKeith Packard         return gdb_get_reg32(mem_buf, cpu_m68k_get_fpsr(env));
925a4526b2SLaurent Vivier     case 10: /* fpiar, not implemented */
93462474d7SAlex Bennée         return gdb_get_reg32(mem_buf, 0);
945a4526b2SLaurent Vivier     }
955a4526b2SLaurent Vivier     return 0;
965a4526b2SLaurent Vivier }
975a4526b2SLaurent Vivier 
m68k_fpu_gdb_set_reg(CPUState * cs,uint8_t * mem_buf,int n)9866260159SAkihiko Odaki static int m68k_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
995a4526b2SLaurent Vivier {
10066260159SAkihiko Odaki     M68kCPU *cpu = M68K_CPU(cs);
10166260159SAkihiko Odaki     CPUM68KState *env = &cpu->env;
10266260159SAkihiko Odaki 
1035a4526b2SLaurent Vivier     if (n < 8) {
1045a4526b2SLaurent Vivier         env->fregs[n].l.upper = lduw_be_p(mem_buf);
1055a4526b2SLaurent Vivier         env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
1065a4526b2SLaurent Vivier         return 12;
1075a4526b2SLaurent Vivier     }
1085a4526b2SLaurent Vivier     switch (n) {
1095a4526b2SLaurent Vivier     case 8: /* fpcontrol */
1103a76d302SPhilippe Mathieu-Daudé         cpu_m68k_set_fpcr(env, ldl_be_p(mem_buf));
1115a4526b2SLaurent Vivier         return 4;
1125a4526b2SLaurent Vivier     case 9: /* fpstatus */
1133a76d302SPhilippe Mathieu-Daudé         cpu_m68k_set_fpsr(env, ldl_be_p(mem_buf));
1145a4526b2SLaurent Vivier         return 4;
1155a4526b2SLaurent Vivier     case 10: /* fpiar, not implemented */
1165a4526b2SLaurent Vivier         return 4;
1175a4526b2SLaurent Vivier     }
1185a4526b2SLaurent Vivier     return 0;
1195a4526b2SLaurent Vivier }
1205a4526b2SLaurent Vivier 
m68k_cpu_init_gdb(M68kCPU * cpu)121fcf5ef2aSThomas Huth void m68k_cpu_init_gdb(M68kCPU *cpu)
122fcf5ef2aSThomas Huth {
123fcf5ef2aSThomas Huth     CPUState *cs = CPU(cpu);
124fcf5ef2aSThomas Huth     CPUM68KState *env = &cpu->env;
125fcf5ef2aSThomas Huth 
126fcf5ef2aSThomas Huth     if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
127f83311e4SLaurent Vivier         gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
128ac1e8671SAkihiko Odaki                                  gdb_find_static_feature("cf-fp.xml"), 18);
1295a4526b2SLaurent Vivier     } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
130ac1e8671SAkihiko Odaki         gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg, m68k_fpu_gdb_set_reg,
131ac1e8671SAkihiko Odaki                                  gdb_find_static_feature("m68k-fp.xml"), 18);
132fcf5ef2aSThomas Huth     }
133fcf5ef2aSThomas Huth     /* TODO: Add [E]MAC registers.  */
134fcf5ef2aSThomas Huth }
135fcf5ef2aSThomas Huth 
HELPER(cf_movec_to)1366e22b28eSLaurent Vivier void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
137fcf5ef2aSThomas Huth {
138fcf5ef2aSThomas Huth     switch (reg) {
1396e22b28eSLaurent Vivier     case M68K_CR_CACR:
140fcf5ef2aSThomas Huth         env->cacr = val;
141fcf5ef2aSThomas Huth         m68k_switch_sp(env);
142fcf5ef2aSThomas Huth         break;
1436e22b28eSLaurent Vivier     case M68K_CR_ACR0:
1446e22b28eSLaurent Vivier     case M68K_CR_ACR1:
1456e22b28eSLaurent Vivier     case M68K_CR_ACR2:
1466e22b28eSLaurent Vivier     case M68K_CR_ACR3:
147fcf5ef2aSThomas Huth         /* TODO: Implement Access Control Registers.  */
148fcf5ef2aSThomas Huth         break;
1496e22b28eSLaurent Vivier     case M68K_CR_VBR:
150fcf5ef2aSThomas Huth         env->vbr = val;
151fcf5ef2aSThomas Huth         break;
152fcf5ef2aSThomas Huth     /* TODO: Implement control registers.  */
153fcf5ef2aSThomas Huth     default:
154a8d92fd8SRichard Henderson         cpu_abort(env_cpu(env),
1556e22b28eSLaurent Vivier                   "Unimplemented control register write 0x%x = 0x%x\n",
1566e22b28eSLaurent Vivier                   reg, val);
1576e22b28eSLaurent Vivier     }
1586e22b28eSLaurent Vivier }
1596e22b28eSLaurent Vivier 
raise_exception_ra(CPUM68KState * env,int tt,uintptr_t raddr)1608df0e6aeSLucien Murray-Pitts static void raise_exception_ra(CPUM68KState *env, int tt, uintptr_t raddr)
1618df0e6aeSLucien Murray-Pitts {
1628df0e6aeSLucien Murray-Pitts     CPUState *cs = env_cpu(env);
1638df0e6aeSLucien Murray-Pitts 
1648df0e6aeSLucien Murray-Pitts     cs->exception_index = tt;
1658df0e6aeSLucien Murray-Pitts     cpu_loop_exit_restore(cs, raddr);
1668df0e6aeSLucien Murray-Pitts }
1678df0e6aeSLucien Murray-Pitts 
HELPER(m68k_movec_to)1686e22b28eSLaurent Vivier void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
1696e22b28eSLaurent Vivier {
1706e22b28eSLaurent Vivier     switch (reg) {
17160d8e964SLucien Murray-Pitts     /* MC680[12346]0 */
1725fa9f1f2SLaurent Vivier     case M68K_CR_SFC:
1735fa9f1f2SLaurent Vivier         env->sfc = val & 7;
1745fa9f1f2SLaurent Vivier         return;
17560d8e964SLucien Murray-Pitts     /* MC680[12346]0 */
1765fa9f1f2SLaurent Vivier     case M68K_CR_DFC:
1775fa9f1f2SLaurent Vivier         env->dfc = val & 7;
1785fa9f1f2SLaurent Vivier         return;
17960d8e964SLucien Murray-Pitts     /* MC680[12346]0 */
1806e22b28eSLaurent Vivier     case M68K_CR_VBR:
1816e22b28eSLaurent Vivier         env->vbr = val;
1826e22b28eSLaurent Vivier         return;
18318b6102eSLaurent Vivier     /* MC680[2346]0 */
1846e22b28eSLaurent Vivier     case M68K_CR_CACR:
18518b6102eSLaurent Vivier         if (m68k_feature(env, M68K_FEATURE_M68020)) {
18618b6102eSLaurent Vivier             env->cacr = val & 0x0000000f;
18718b6102eSLaurent Vivier         } else if (m68k_feature(env, M68K_FEATURE_M68030)) {
18818b6102eSLaurent Vivier             env->cacr = val & 0x00003f1f;
18918b6102eSLaurent Vivier         } else if (m68k_feature(env, M68K_FEATURE_M68040)) {
19018b6102eSLaurent Vivier             env->cacr = val & 0x80008000;
19118b6102eSLaurent Vivier         } else if (m68k_feature(env, M68K_FEATURE_M68060)) {
19218b6102eSLaurent Vivier             env->cacr = val & 0xf8e0e000;
1938df0e6aeSLucien Murray-Pitts         } else {
1948df0e6aeSLucien Murray-Pitts             break;
19518b6102eSLaurent Vivier         }
1966e22b28eSLaurent Vivier         m68k_switch_sp(env);
1976e22b28eSLaurent Vivier         return;
19860d8e964SLucien Murray-Pitts     /* MC680[46]0 */
19988b2fef6SLaurent Vivier     case M68K_CR_TC:
2008df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)
2018df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
20288b2fef6SLaurent Vivier             env->mmu.tcr = val;
20388b2fef6SLaurent Vivier             return;
2048df0e6aeSLucien Murray-Pitts         }
2058df0e6aeSLucien Murray-Pitts         break;
20660d8e964SLucien Murray-Pitts     /* MC68040 */
207e55886c3SLaurent Vivier     case M68K_CR_MMUSR:
2088df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
209e55886c3SLaurent Vivier             env->mmu.mmusr = val;
210e55886c3SLaurent Vivier             return;
2118df0e6aeSLucien Murray-Pitts         }
2128df0e6aeSLucien Murray-Pitts         break;
21360d8e964SLucien Murray-Pitts     /* MC680[46]0 */
21488b2fef6SLaurent Vivier     case M68K_CR_SRP:
2158df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)
2168df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
21788b2fef6SLaurent Vivier             env->mmu.srp = val;
21888b2fef6SLaurent Vivier             return;
2198df0e6aeSLucien Murray-Pitts         }
2208df0e6aeSLucien Murray-Pitts         break;
2218df0e6aeSLucien Murray-Pitts     /* MC680[46]0 */
22288b2fef6SLaurent Vivier     case M68K_CR_URP:
2238df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)
2248df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
22588b2fef6SLaurent Vivier             env->mmu.urp = val;
22688b2fef6SLaurent Vivier             return;
2278df0e6aeSLucien Murray-Pitts         }
2288df0e6aeSLucien Murray-Pitts         break;
2298df0e6aeSLucien Murray-Pitts     /* MC680[12346]0 */
2306e22b28eSLaurent Vivier     case M68K_CR_USP:
2316e22b28eSLaurent Vivier         env->sp[M68K_USP] = val;
2326e22b28eSLaurent Vivier         return;
23360d8e964SLucien Murray-Pitts     /* MC680[234]0 */
2346e22b28eSLaurent Vivier     case M68K_CR_MSP:
2358df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68020)
2368df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68030)
2378df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68040)) {
2386e22b28eSLaurent Vivier             env->sp[M68K_SSP] = val;
2396e22b28eSLaurent Vivier             return;
2408df0e6aeSLucien Murray-Pitts         }
2418df0e6aeSLucien Murray-Pitts         break;
24260d8e964SLucien Murray-Pitts     /* MC680[234]0 */
2436e22b28eSLaurent Vivier     case M68K_CR_ISP:
2448df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68020)
2458df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68030)
2468df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68040)) {
2476e22b28eSLaurent Vivier             env->sp[M68K_ISP] = val;
2486e22b28eSLaurent Vivier             return;
2498df0e6aeSLucien Murray-Pitts         }
2508df0e6aeSLucien Murray-Pitts         break;
251c05c73b0SLaurent Vivier     /* MC68040/MC68LC040 */
2528df0e6aeSLucien Murray-Pitts     case M68K_CR_ITT0: /* MC68EC040 only: M68K_CR_IACR0 */
2538df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
254c05c73b0SLaurent Vivier             env->mmu.ttr[M68K_ITTR0] = val;
255c05c73b0SLaurent Vivier             return;
2568df0e6aeSLucien Murray-Pitts         }
2578df0e6aeSLucien Murray-Pitts         break;
25860d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
2598df0e6aeSLucien Murray-Pitts     case M68K_CR_ITT1: /* MC68EC040 only: M68K_CR_IACR1 */
2608df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
261c05c73b0SLaurent Vivier             env->mmu.ttr[M68K_ITTR1] = val;
262c05c73b0SLaurent Vivier             return;
2638df0e6aeSLucien Murray-Pitts         }
2648df0e6aeSLucien Murray-Pitts         break;
26560d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
2668df0e6aeSLucien Murray-Pitts     case M68K_CR_DTT0: /* MC68EC040 only: M68K_CR_DACR0 */
2678df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
268c05c73b0SLaurent Vivier             env->mmu.ttr[M68K_DTTR0] = val;
269c05c73b0SLaurent Vivier             return;
2708df0e6aeSLucien Murray-Pitts         }
2718df0e6aeSLucien Murray-Pitts         break;
27260d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
2738df0e6aeSLucien Murray-Pitts     case M68K_CR_DTT1: /* MC68EC040 only: M68K_CR_DACR1 */
2748df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
275c05c73b0SLaurent Vivier             env->mmu.ttr[M68K_DTTR1] = val;
276c05c73b0SLaurent Vivier             return;
2778df0e6aeSLucien Murray-Pitts         }
2788df0e6aeSLucien Murray-Pitts         break;
2795736526cSLucien Murray-Pitts     /* Unimplemented Registers */
2805736526cSLucien Murray-Pitts     case M68K_CR_CAAR:
2815736526cSLucien Murray-Pitts     case M68K_CR_PCR:
2825736526cSLucien Murray-Pitts     case M68K_CR_BUSCR:
283a8d92fd8SRichard Henderson         cpu_abort(env_cpu(env),
284a8d92fd8SRichard Henderson                   "Unimplemented control register write 0x%x = 0x%x\n",
285fcf5ef2aSThomas Huth                   reg, val);
286fcf5ef2aSThomas Huth     }
2876e22b28eSLaurent Vivier 
2888df0e6aeSLucien Murray-Pitts     /* Invalid control registers will generate an exception. */
2898df0e6aeSLucien Murray-Pitts     raise_exception_ra(env, EXCP_ILLEGAL, 0);
2908df0e6aeSLucien Murray-Pitts     return;
2918df0e6aeSLucien Murray-Pitts }
2928df0e6aeSLucien Murray-Pitts 
HELPER(m68k_movec_from)2936e22b28eSLaurent Vivier uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
2946e22b28eSLaurent Vivier {
2956e22b28eSLaurent Vivier     switch (reg) {
29660d8e964SLucien Murray-Pitts     /* MC680[12346]0 */
2975fa9f1f2SLaurent Vivier     case M68K_CR_SFC:
2985fa9f1f2SLaurent Vivier         return env->sfc;
29960d8e964SLucien Murray-Pitts     /* MC680[12346]0 */
3005fa9f1f2SLaurent Vivier     case M68K_CR_DFC:
3015fa9f1f2SLaurent Vivier         return env->dfc;
30260d8e964SLucien Murray-Pitts     /* MC680[12346]0 */
3036e22b28eSLaurent Vivier     case M68K_CR_VBR:
3046e22b28eSLaurent Vivier         return env->vbr;
30560d8e964SLucien Murray-Pitts     /* MC680[2346]0 */
3066e22b28eSLaurent Vivier     case M68K_CR_CACR:
3078df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68020)
3088df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68030)
3098df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68040)
3108df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
3116e22b28eSLaurent Vivier             return env->cacr;
3128df0e6aeSLucien Murray-Pitts         }
3138df0e6aeSLucien Murray-Pitts         break;
31460d8e964SLucien Murray-Pitts     /* MC680[46]0 */
31588b2fef6SLaurent Vivier     case M68K_CR_TC:
3168df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)
3178df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
31888b2fef6SLaurent Vivier             return env->mmu.tcr;
3198df0e6aeSLucien Murray-Pitts         }
3208df0e6aeSLucien Murray-Pitts         break;
32160d8e964SLucien Murray-Pitts     /* MC68040 */
322e55886c3SLaurent Vivier     case M68K_CR_MMUSR:
3238df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
324e55886c3SLaurent Vivier             return env->mmu.mmusr;
3258df0e6aeSLucien Murray-Pitts         }
3268df0e6aeSLucien Murray-Pitts         break;
32760d8e964SLucien Murray-Pitts     /* MC680[46]0 */
32888b2fef6SLaurent Vivier     case M68K_CR_SRP:
3298df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)
3308df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
33188b2fef6SLaurent Vivier             return env->mmu.srp;
3328df0e6aeSLucien Murray-Pitts         }
3338df0e6aeSLucien Murray-Pitts         break;
3348df0e6aeSLucien Murray-Pitts     /* MC68040/MC68LC040 */
3358df0e6aeSLucien Murray-Pitts     case M68K_CR_URP:
3368df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)
3378df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68060)) {
3388df0e6aeSLucien Murray-Pitts             return env->mmu.urp;
3398df0e6aeSLucien Murray-Pitts         }
3408df0e6aeSLucien Murray-Pitts         break;
34160d8e964SLucien Murray-Pitts     /* MC680[46]0 */
3426e22b28eSLaurent Vivier     case M68K_CR_USP:
3436e22b28eSLaurent Vivier         return env->sp[M68K_USP];
34460d8e964SLucien Murray-Pitts     /* MC680[234]0 */
3456e22b28eSLaurent Vivier     case M68K_CR_MSP:
3468df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68020)
3478df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68030)
3488df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68040)) {
3496e22b28eSLaurent Vivier             return env->sp[M68K_SSP];
3508df0e6aeSLucien Murray-Pitts         }
3518df0e6aeSLucien Murray-Pitts         break;
35260d8e964SLucien Murray-Pitts     /* MC680[234]0 */
3536e22b28eSLaurent Vivier     case M68K_CR_ISP:
3548df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68020)
3558df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68030)
3568df0e6aeSLucien Murray-Pitts          || m68k_feature(env, M68K_FEATURE_M68040)) {
3576e22b28eSLaurent Vivier             return env->sp[M68K_ISP];
3588df0e6aeSLucien Murray-Pitts         }
3598df0e6aeSLucien Murray-Pitts         break;
36060d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
36160d8e964SLucien Murray-Pitts     case M68K_CR_ITT0: /* MC68EC040 only: M68K_CR_IACR0 */
3628df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
363c05c73b0SLaurent Vivier             return env->mmu.ttr[M68K_ITTR0];
3648df0e6aeSLucien Murray-Pitts         }
3658df0e6aeSLucien Murray-Pitts         break;
36660d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
36760d8e964SLucien Murray-Pitts     case M68K_CR_ITT1: /* MC68EC040 only: M68K_CR_IACR1 */
3688df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
369c05c73b0SLaurent Vivier             return env->mmu.ttr[M68K_ITTR1];
3708df0e6aeSLucien Murray-Pitts         }
3718df0e6aeSLucien Murray-Pitts         break;
37260d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
37360d8e964SLucien Murray-Pitts     case M68K_CR_DTT0: /* MC68EC040 only: M68K_CR_DACR0 */
3748df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
375c05c73b0SLaurent Vivier             return env->mmu.ttr[M68K_DTTR0];
3768df0e6aeSLucien Murray-Pitts         }
3778df0e6aeSLucien Murray-Pitts         break;
37860d8e964SLucien Murray-Pitts     /* MC68040/MC68LC040 */
37960d8e964SLucien Murray-Pitts     case M68K_CR_DTT1: /* MC68EC040 only: M68K_CR_DACR1 */
3808df0e6aeSLucien Murray-Pitts         if (m68k_feature(env, M68K_FEATURE_M68040)) {
381c05c73b0SLaurent Vivier             return env->mmu.ttr[M68K_DTTR1];
3828df0e6aeSLucien Murray-Pitts         }
3838df0e6aeSLucien Murray-Pitts         break;
3845736526cSLucien Murray-Pitts     /* Unimplemented Registers */
3855736526cSLucien Murray-Pitts     case M68K_CR_CAAR:
3865736526cSLucien Murray-Pitts     case M68K_CR_PCR:
3875736526cSLucien Murray-Pitts     case M68K_CR_BUSCR:
388a8d92fd8SRichard Henderson         cpu_abort(env_cpu(env), "Unimplemented control register read 0x%x\n",
3896e22b28eSLaurent Vivier                   reg);
390fcf5ef2aSThomas Huth     }
391fcf5ef2aSThomas Huth 
3928df0e6aeSLucien Murray-Pitts     /* Invalid control registers will generate an exception. */
3938df0e6aeSLucien Murray-Pitts     raise_exception_ra(env, EXCP_ILLEGAL, 0);
3948df0e6aeSLucien Murray-Pitts 
3958df0e6aeSLucien Murray-Pitts     return 0;
3968df0e6aeSLucien Murray-Pitts }
3978df0e6aeSLucien Murray-Pitts 
HELPER(set_macsr)398fcf5ef2aSThomas Huth void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
399fcf5ef2aSThomas Huth {
400fcf5ef2aSThomas Huth     uint32_t acc;
401fcf5ef2aSThomas Huth     int8_t exthigh;
402fcf5ef2aSThomas Huth     uint8_t extlow;
403fcf5ef2aSThomas Huth     uint64_t regval;
404fcf5ef2aSThomas Huth     int i;
405fcf5ef2aSThomas Huth     if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
406fcf5ef2aSThomas Huth         for (i = 0; i < 4; i++) {
407fcf5ef2aSThomas Huth             regval = env->macc[i];
408fcf5ef2aSThomas Huth             exthigh = regval >> 40;
409fcf5ef2aSThomas Huth             if (env->macsr & MACSR_FI) {
410fcf5ef2aSThomas Huth                 acc = regval >> 8;
411fcf5ef2aSThomas Huth                 extlow = regval;
412fcf5ef2aSThomas Huth             } else {
413fcf5ef2aSThomas Huth                 acc = regval;
414fcf5ef2aSThomas Huth                 extlow = regval >> 32;
415fcf5ef2aSThomas Huth             }
416fcf5ef2aSThomas Huth             if (env->macsr & MACSR_FI) {
417fcf5ef2aSThomas Huth                 regval = (((uint64_t)acc) << 8) | extlow;
418fcf5ef2aSThomas Huth                 regval |= ((int64_t)exthigh) << 40;
419fcf5ef2aSThomas Huth             } else if (env->macsr & MACSR_SU) {
420fcf5ef2aSThomas Huth                 regval = acc | (((int64_t)extlow) << 32);
421fcf5ef2aSThomas Huth                 regval |= ((int64_t)exthigh) << 40;
422fcf5ef2aSThomas Huth             } else {
423fcf5ef2aSThomas Huth                 regval = acc | (((uint64_t)extlow) << 32);
424fcf5ef2aSThomas Huth                 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
425fcf5ef2aSThomas Huth             }
426fcf5ef2aSThomas Huth             env->macc[i] = regval;
427fcf5ef2aSThomas Huth         }
428fcf5ef2aSThomas Huth     }
429fcf5ef2aSThomas Huth     env->macsr = val;
430fcf5ef2aSThomas Huth }
431fcf5ef2aSThomas Huth 
m68k_switch_sp(CPUM68KState * env)432fcf5ef2aSThomas Huth void m68k_switch_sp(CPUM68KState *env)
433fcf5ef2aSThomas Huth {
434fcf5ef2aSThomas Huth     int new_sp;
435fcf5ef2aSThomas Huth 
436fcf5ef2aSThomas Huth     env->sp[env->current_sp] = env->aregs[7];
437aece90d8SMark Cave-Ayland     if (m68k_feature(env, M68K_FEATURE_M68K)) {
4386e22b28eSLaurent Vivier         if (env->sr & SR_S) {
4397525a9b9SLucien Murray-Pitts             /* SR:Master-Mode bit unimplemented then ISP is not available */
4407525a9b9SLucien Murray-Pitts             if (!m68k_feature(env, M68K_FEATURE_MSP) || env->sr & SR_M) {
4416e22b28eSLaurent Vivier                 new_sp = M68K_SSP;
4426e22b28eSLaurent Vivier             } else {
4436e22b28eSLaurent Vivier                 new_sp = M68K_ISP;
4446e22b28eSLaurent Vivier             }
4456e22b28eSLaurent Vivier         } else {
4466e22b28eSLaurent Vivier             new_sp = M68K_USP;
4476e22b28eSLaurent Vivier         }
4486e22b28eSLaurent Vivier     } else {
449fcf5ef2aSThomas Huth         new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
450fcf5ef2aSThomas Huth                  ? M68K_SSP : M68K_USP;
4516e22b28eSLaurent Vivier     }
452fcf5ef2aSThomas Huth     env->aregs[7] = env->sp[new_sp];
453fcf5ef2aSThomas Huth     env->current_sp = new_sp;
454fcf5ef2aSThomas Huth }
455fcf5ef2aSThomas Huth 
456fe5f7b1bSRichard Henderson #if !defined(CONFIG_USER_ONLY)
45788b2fef6SLaurent Vivier /* MMU: 68040 only */
458fcf5ef2aSThomas Huth 
print_address_zone(uint32_t logical,uint32_t physical,uint32_t size,int attr)459fad866daSMarkus Armbruster static void print_address_zone(uint32_t logical, uint32_t physical,
4602097dca6SLaurent Vivier                                uint32_t size, int attr)
4612097dca6SLaurent Vivier {
462fad866daSMarkus Armbruster     qemu_printf("%08x - %08x -> %08x - %08x %c ",
4632097dca6SLaurent Vivier                 logical, logical + size - 1,
4642097dca6SLaurent Vivier                 physical, physical + size - 1,
4652097dca6SLaurent Vivier                 attr & 4 ? 'W' : '-');
4662097dca6SLaurent Vivier     size >>= 10;
4672097dca6SLaurent Vivier     if (size < 1024) {
468fad866daSMarkus Armbruster         qemu_printf("(%d KiB)\n", size);
4692097dca6SLaurent Vivier     } else {
4702097dca6SLaurent Vivier         size >>= 10;
4712097dca6SLaurent Vivier         if (size < 1024) {
472fad866daSMarkus Armbruster             qemu_printf("(%d MiB)\n", size);
4732097dca6SLaurent Vivier         } else {
4742097dca6SLaurent Vivier             size >>= 10;
475fad866daSMarkus Armbruster             qemu_printf("(%d GiB)\n", size);
4762097dca6SLaurent Vivier         }
4772097dca6SLaurent Vivier     }
4782097dca6SLaurent Vivier }
4792097dca6SLaurent Vivier 
dump_address_map(CPUM68KState * env,uint32_t root_pointer)480fad866daSMarkus Armbruster static void dump_address_map(CPUM68KState *env, uint32_t root_pointer)
4812097dca6SLaurent Vivier {
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     }
5047d01623aSPeter Maydell     for (unsigned 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         }
5107d01623aSPeter Maydell         for (unsigned 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             }
5167d01623aSPeter Maydell             for (unsigned 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 
dump_ttr(uint32_t ttr)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 
dump_mmu(CPUM68KState * env)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 
check_TTR(uint32_t ttr,int * prot,target_ulong addr,int access_type)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 
get_physical_address(CPUM68KState * env,hwaddr * physical,int * prot,target_ulong address,int access_type,target_ulong * page_size)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 
m68k_cpu_get_phys_page_debug(CPUState * cs,vaddr addr)907fcf5ef2aSThomas Huth hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
908fcf5ef2aSThomas Huth {
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 */
917fcf5ef2aSThomas Huth         return addr;
918fcf5ef2aSThomas Huth     }
919fcf5ef2aSThomas Huth 
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  */
m68k_set_irq_level(M68kCPU * cpu,int level,uint8_t vector)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 
m68k_cpu_tlb_fill(CPUState * cs,vaddr address,int size,MMUAccessType qemu_access_type,int mmu_idx,bool probe,uintptr_t retaddr)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)
956fcf5ef2aSThomas Huth {
957e22a4560SPhilippe Mathieu-Daudé     CPUM68KState *env = cpu_env(cs);
95888b2fef6SLaurent Vivier     hwaddr physical;
959fcf5ef2aSThomas Huth     int prot;
96088b2fef6SLaurent Vivier     int access_type;
96188b2fef6SLaurent Vivier     int ret;
96288b2fef6SLaurent Vivier     target_ulong page_size;
963fcf5ef2aSThomas Huth 
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;
971fcf5ef2aSThomas Huth     }
972fcf5ef2aSThomas Huth 
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 
HELPER(bitrev)1028fcf5ef2aSThomas Huth uint32_t HELPER(bitrev)(uint32_t x)
1029fcf5ef2aSThomas Huth {
1030fcf5ef2aSThomas Huth     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
1031fcf5ef2aSThomas Huth     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
1032fcf5ef2aSThomas Huth     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
1033fcf5ef2aSThomas Huth     return bswap32(x);
1034fcf5ef2aSThomas Huth }
1035fcf5ef2aSThomas Huth 
HELPER(ff1)1036fcf5ef2aSThomas Huth uint32_t HELPER(ff1)(uint32_t x)
1037fcf5ef2aSThomas Huth {
1038fcf5ef2aSThomas Huth     int n;
1039fcf5ef2aSThomas Huth     for (n = 32; x; n--)
1040fcf5ef2aSThomas Huth         x >>= 1;
1041fcf5ef2aSThomas Huth     return n;
1042fcf5ef2aSThomas Huth }
1043fcf5ef2aSThomas Huth 
HELPER(sats)1044fcf5ef2aSThomas Huth uint32_t HELPER(sats)(uint32_t val, uint32_t v)
1045fcf5ef2aSThomas Huth {
1046fcf5ef2aSThomas Huth     /* The result has the opposite sign to the original value.  */
1047fcf5ef2aSThomas Huth     if ((int32_t)v < 0) {
1048fcf5ef2aSThomas Huth         val = (((int32_t)val) >> 31) ^ SIGNBIT;
1049fcf5ef2aSThomas Huth     }
1050fcf5ef2aSThomas Huth     return val;
1051fcf5ef2aSThomas Huth }
1052fcf5ef2aSThomas Huth 
cpu_m68k_set_sr(CPUM68KState * env,uint32_t sr)1053d2f8fb8eSLaurent Vivier void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
1054fcf5ef2aSThomas Huth {
1055d2f8fb8eSLaurent Vivier     env->sr = sr & 0xffe0;
1056d2f8fb8eSLaurent Vivier     cpu_m68k_set_ccr(env, sr);
1057fcf5ef2aSThomas Huth     m68k_switch_sp(env);
1058fcf5ef2aSThomas Huth }
1059fcf5ef2aSThomas Huth 
HELPER(set_sr)1060d2f8fb8eSLaurent Vivier void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
1061d2f8fb8eSLaurent Vivier {
1062d2f8fb8eSLaurent Vivier     cpu_m68k_set_sr(env, val);
1063d2f8fb8eSLaurent Vivier }
1064fcf5ef2aSThomas Huth 
1065fcf5ef2aSThomas Huth /* 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  */
HELPER(mac_move)1071fcf5ef2aSThomas Huth void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
1072fcf5ef2aSThomas Huth {
1073fcf5ef2aSThomas Huth     uint32_t mask;
1074fcf5ef2aSThomas Huth     env->macc[dest] = env->macc[src];
1075fcf5ef2aSThomas Huth     mask = MACSR_PAV0 << dest;
1076fcf5ef2aSThomas Huth     if (env->macsr & (MACSR_PAV0 << src))
1077fcf5ef2aSThomas Huth         env->macsr |= mask;
1078fcf5ef2aSThomas Huth     else
1079fcf5ef2aSThomas Huth         env->macsr &= ~mask;
1080fcf5ef2aSThomas Huth }
1081fcf5ef2aSThomas Huth 
HELPER(macmuls)1082fcf5ef2aSThomas Huth uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
1083fcf5ef2aSThomas Huth {
1084fcf5ef2aSThomas Huth     int64_t product;
1085fcf5ef2aSThomas Huth     int64_t res;
1086fcf5ef2aSThomas Huth 
1087fcf5ef2aSThomas Huth     product = (uint64_t)op1 * op2;
1088fcf5ef2aSThomas Huth     res = (product << 24) >> 24;
1089fcf5ef2aSThomas Huth     if (res != product) {
1090fcf5ef2aSThomas Huth         env->macsr |= MACSR_V;
1091fcf5ef2aSThomas Huth         if (env->macsr & MACSR_OMC) {
1092fcf5ef2aSThomas Huth             /* Make sure the accumulate operation overflows.  */
1093fcf5ef2aSThomas Huth             if (product < 0)
1094fcf5ef2aSThomas Huth                 res = ~(1ll << 50);
1095fcf5ef2aSThomas Huth             else
1096fcf5ef2aSThomas Huth                 res = 1ll << 50;
1097fcf5ef2aSThomas Huth         }
1098fcf5ef2aSThomas Huth     }
1099fcf5ef2aSThomas Huth     return res;
1100fcf5ef2aSThomas Huth }
1101fcf5ef2aSThomas Huth 
HELPER(macmulu)1102fcf5ef2aSThomas Huth uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
1103fcf5ef2aSThomas Huth {
1104fcf5ef2aSThomas Huth     uint64_t product;
1105fcf5ef2aSThomas Huth 
1106fcf5ef2aSThomas Huth     product = (uint64_t)op1 * op2;
1107fcf5ef2aSThomas Huth     if (product & (0xffffffull << 40)) {
1108fcf5ef2aSThomas Huth         env->macsr |= MACSR_V;
1109fcf5ef2aSThomas Huth         if (env->macsr & MACSR_OMC) {
1110fcf5ef2aSThomas Huth             /* Make sure the accumulate operation overflows.  */
1111fcf5ef2aSThomas Huth             product = 1ll << 50;
1112fcf5ef2aSThomas Huth         } else {
1113fcf5ef2aSThomas Huth             product &= ((1ull << 40) - 1);
1114fcf5ef2aSThomas Huth         }
1115fcf5ef2aSThomas Huth     }
1116fcf5ef2aSThomas Huth     return product;
1117fcf5ef2aSThomas Huth }
1118fcf5ef2aSThomas Huth 
HELPER(macmulf)1119fcf5ef2aSThomas Huth uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
1120fcf5ef2aSThomas Huth {
1121fcf5ef2aSThomas Huth     uint64_t product;
1122fcf5ef2aSThomas Huth     uint32_t remainder;
1123fcf5ef2aSThomas Huth 
1124fcf5ef2aSThomas Huth     product = (uint64_t)op1 * op2;
1125fcf5ef2aSThomas Huth     if (env->macsr & MACSR_RT) {
1126fcf5ef2aSThomas Huth         remainder = product & 0xffffff;
1127fcf5ef2aSThomas Huth         product >>= 24;
1128fcf5ef2aSThomas Huth         if (remainder > 0x800000)
1129fcf5ef2aSThomas Huth             product++;
1130fcf5ef2aSThomas Huth         else if (remainder == 0x800000)
1131fcf5ef2aSThomas Huth             product += (product & 1);
1132fcf5ef2aSThomas Huth     } else {
1133fcf5ef2aSThomas Huth         product >>= 24;
1134fcf5ef2aSThomas Huth     }
1135fcf5ef2aSThomas Huth     return product;
1136fcf5ef2aSThomas Huth }
1137fcf5ef2aSThomas Huth 
HELPER(macsats)1138fcf5ef2aSThomas Huth void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
1139fcf5ef2aSThomas Huth {
1140fcf5ef2aSThomas Huth     int64_t tmp;
1141fcf5ef2aSThomas Huth     int64_t result;
1142fcf5ef2aSThomas Huth     tmp = env->macc[acc];
1143fcf5ef2aSThomas Huth     result = ((tmp << 16) >> 16);
1144fcf5ef2aSThomas Huth     if (result != tmp) {
1145fcf5ef2aSThomas Huth         env->macsr |= MACSR_V;
1146fcf5ef2aSThomas Huth     }
1147fcf5ef2aSThomas Huth     if (env->macsr & MACSR_V) {
1148fcf5ef2aSThomas Huth         env->macsr |= MACSR_PAV0 << acc;
1149fcf5ef2aSThomas Huth         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              */
1155fcf5ef2aSThomas Huth             result = (result >> 63) ^ 0x7fffffff;
1156fcf5ef2aSThomas Huth         }
1157fcf5ef2aSThomas Huth     }
1158fcf5ef2aSThomas Huth     env->macc[acc] = result;
1159fcf5ef2aSThomas Huth }
1160fcf5ef2aSThomas Huth 
HELPER(macsatu)1161fcf5ef2aSThomas Huth void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
1162fcf5ef2aSThomas Huth {
1163fcf5ef2aSThomas Huth     uint64_t val;
1164fcf5ef2aSThomas Huth 
1165fcf5ef2aSThomas Huth     val = env->macc[acc];
1166fcf5ef2aSThomas Huth     if (val & (0xffffull << 48)) {
1167fcf5ef2aSThomas Huth         env->macsr |= MACSR_V;
1168fcf5ef2aSThomas Huth     }
1169fcf5ef2aSThomas Huth     if (env->macsr & MACSR_V) {
1170fcf5ef2aSThomas Huth         env->macsr |= MACSR_PAV0 << acc;
1171fcf5ef2aSThomas Huth         if (env->macsr & MACSR_OMC) {
1172fcf5ef2aSThomas Huth             if (val > (1ull << 53))
1173fcf5ef2aSThomas Huth                 val = 0;
1174fcf5ef2aSThomas Huth             else
1175fcf5ef2aSThomas Huth                 val = (1ull << 48) - 1;
1176fcf5ef2aSThomas Huth         } else {
1177fcf5ef2aSThomas Huth             val &= ((1ull << 48) - 1);
1178fcf5ef2aSThomas Huth         }
1179fcf5ef2aSThomas Huth     }
1180fcf5ef2aSThomas Huth     env->macc[acc] = val;
1181fcf5ef2aSThomas Huth }
1182fcf5ef2aSThomas Huth 
HELPER(macsatf)1183fcf5ef2aSThomas Huth void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
1184fcf5ef2aSThomas Huth {
1185fcf5ef2aSThomas Huth     int64_t sum;
1186fcf5ef2aSThomas Huth     int64_t result;
1187fcf5ef2aSThomas Huth 
1188fcf5ef2aSThomas Huth     sum = env->macc[acc];
1189fcf5ef2aSThomas Huth     result = (sum << 16) >> 16;
1190fcf5ef2aSThomas Huth     if (result != sum) {
1191fcf5ef2aSThomas Huth         env->macsr |= MACSR_V;
1192fcf5ef2aSThomas Huth     }
1193fcf5ef2aSThomas Huth     if (env->macsr & MACSR_V) {
1194fcf5ef2aSThomas Huth         env->macsr |= MACSR_PAV0 << acc;
1195fcf5ef2aSThomas Huth         if (env->macsr & MACSR_OMC) {
1196fcf5ef2aSThomas Huth             result = (result >> 63) ^ 0x7fffffffffffll;
1197fcf5ef2aSThomas Huth         }
1198fcf5ef2aSThomas Huth     }
1199fcf5ef2aSThomas Huth     env->macc[acc] = result;
1200fcf5ef2aSThomas Huth }
1201fcf5ef2aSThomas Huth 
HELPER(mac_set_flags)1202fcf5ef2aSThomas Huth void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
1203fcf5ef2aSThomas Huth {
1204fcf5ef2aSThomas Huth     uint64_t val;
1205fcf5ef2aSThomas Huth     val = env->macc[acc];
1206fcf5ef2aSThomas Huth     if (val == 0) {
1207fcf5ef2aSThomas Huth         env->macsr |= MACSR_Z;
1208fcf5ef2aSThomas Huth     } else if (val & (1ull << 47)) {
1209fcf5ef2aSThomas Huth         env->macsr |= MACSR_N;
1210fcf5ef2aSThomas Huth     }
1211fcf5ef2aSThomas Huth     if (env->macsr & (MACSR_PAV0 << acc)) {
1212fcf5ef2aSThomas Huth         env->macsr |= MACSR_V;
1213fcf5ef2aSThomas Huth     }
1214fcf5ef2aSThomas Huth     if (env->macsr & MACSR_FI) {
1215fcf5ef2aSThomas Huth         val = ((int64_t)val) >> 40;
1216fcf5ef2aSThomas Huth         if (val != 0 && val != -1)
1217fcf5ef2aSThomas Huth             env->macsr |= MACSR_EV;
1218fcf5ef2aSThomas Huth     } else if (env->macsr & MACSR_SU) {
1219fcf5ef2aSThomas Huth         val = ((int64_t)val) >> 32;
1220fcf5ef2aSThomas Huth         if (val != 0 && val != -1)
1221fcf5ef2aSThomas Huth             env->macsr |= MACSR_EV;
1222fcf5ef2aSThomas Huth     } else {
1223fcf5ef2aSThomas Huth         if ((val >> 32) != 0)
1224fcf5ef2aSThomas Huth             env->macsr |= MACSR_EV;
1225fcf5ef2aSThomas Huth     }
1226fcf5ef2aSThomas Huth }
1227fcf5ef2aSThomas Huth 
1228fcf5ef2aSThomas Huth #define EXTSIGN(val, index) (     \
1229fcf5ef2aSThomas Huth     (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
1230fcf5ef2aSThomas Huth )
1231fcf5ef2aSThomas Huth 
1232fcf5ef2aSThomas Huth #define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
1233fcf5ef2aSThomas Huth     switch (op) {                                                          \
1234fcf5ef2aSThomas Huth     case CC_OP_FLAGS:                                                      \
1235fcf5ef2aSThomas Huth         /* Everything in place.  */                                        \
1236fcf5ef2aSThomas Huth         break;                                                             \
1237fcf5ef2aSThomas Huth     case CC_OP_ADDB:                                                       \
1238fcf5ef2aSThomas Huth     case CC_OP_ADDW:                                                       \
1239fcf5ef2aSThomas Huth     case CC_OP_ADDL:                                                       \
1240fcf5ef2aSThomas Huth         res = n;                                                           \
1241fcf5ef2aSThomas Huth         src2 = v;                                                          \
1242fcf5ef2aSThomas Huth         src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
1243fcf5ef2aSThomas Huth         c = x;                                                             \
1244fcf5ef2aSThomas Huth         z = n;                                                             \
1245fcf5ef2aSThomas Huth         v = (res ^ src1) & ~(src1 ^ src2);                                 \
1246fcf5ef2aSThomas Huth         break;                                                             \
1247fcf5ef2aSThomas Huth     case CC_OP_SUBB:                                                       \
1248fcf5ef2aSThomas Huth     case CC_OP_SUBW:                                                       \
1249fcf5ef2aSThomas Huth     case CC_OP_SUBL:                                                       \
1250fcf5ef2aSThomas Huth         res = n;                                                           \
1251fcf5ef2aSThomas Huth         src2 = v;                                                          \
1252fcf5ef2aSThomas Huth         src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
1253fcf5ef2aSThomas Huth         c = x;                                                             \
1254fcf5ef2aSThomas Huth         z = n;                                                             \
1255fcf5ef2aSThomas Huth         v = (res ^ src1) & (src1 ^ src2);                                  \
1256fcf5ef2aSThomas Huth         break;                                                             \
1257fcf5ef2aSThomas Huth     case CC_OP_CMPB:                                                       \
1258fcf5ef2aSThomas Huth     case CC_OP_CMPW:                                                       \
1259fcf5ef2aSThomas Huth     case CC_OP_CMPL:                                                       \
1260fcf5ef2aSThomas Huth         src1 = n;                                                          \
1261fcf5ef2aSThomas Huth         src2 = v;                                                          \
1262fcf5ef2aSThomas Huth         res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
1263fcf5ef2aSThomas Huth         n = res;                                                           \
1264fcf5ef2aSThomas Huth         z = res;                                                           \
1265fcf5ef2aSThomas Huth         c = src1 < src2;                                                   \
1266fcf5ef2aSThomas Huth         v = (res ^ src1) & (src1 ^ src2);                                  \
1267fcf5ef2aSThomas Huth         break;                                                             \
1268fcf5ef2aSThomas Huth     case CC_OP_LOGIC:                                                      \
1269fcf5ef2aSThomas Huth         c = v = 0;                                                         \
1270fcf5ef2aSThomas Huth         z = n;                                                             \
1271fcf5ef2aSThomas Huth         break;                                                             \
1272fcf5ef2aSThomas Huth     default:                                                               \
1273a8d92fd8SRichard Henderson         cpu_abort(env_cpu(env), "Bad CC_OP %d", op);                       \
1274fcf5ef2aSThomas Huth     }                                                                      \
1275fcf5ef2aSThomas Huth } while (0)
1276fcf5ef2aSThomas Huth 
cpu_m68k_get_ccr(CPUM68KState * env)1277fcf5ef2aSThomas Huth uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
1278fcf5ef2aSThomas Huth {
1279fcf5ef2aSThomas Huth     uint32_t x, c, n, z, v;
1280fcf5ef2aSThomas Huth     uint32_t res, src1, src2;
1281fcf5ef2aSThomas Huth 
1282fcf5ef2aSThomas Huth     x = env->cc_x;
1283fcf5ef2aSThomas Huth     n = env->cc_n;
1284fcf5ef2aSThomas Huth     z = env->cc_z;
1285fcf5ef2aSThomas Huth     v = env->cc_v;
1286fcf5ef2aSThomas Huth     c = env->cc_c;
1287fcf5ef2aSThomas Huth 
1288fcf5ef2aSThomas Huth     COMPUTE_CCR(env->cc_op, x, n, z, v, c);
1289fcf5ef2aSThomas Huth 
1290fcf5ef2aSThomas Huth     n = n >> 31;
1291fcf5ef2aSThomas Huth     z = (z == 0);
1292fcf5ef2aSThomas Huth     v = v >> 31;
1293fcf5ef2aSThomas Huth 
1294fcf5ef2aSThomas Huth     return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
1295fcf5ef2aSThomas Huth }
1296fcf5ef2aSThomas Huth 
HELPER(get_ccr)1297fcf5ef2aSThomas Huth uint32_t HELPER(get_ccr)(CPUM68KState *env)
1298fcf5ef2aSThomas Huth {
1299fcf5ef2aSThomas Huth     return cpu_m68k_get_ccr(env);
1300fcf5ef2aSThomas Huth }
1301fcf5ef2aSThomas Huth 
cpu_m68k_set_ccr(CPUM68KState * env,uint32_t ccr)1302fcf5ef2aSThomas Huth void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
1303fcf5ef2aSThomas Huth {
1304fcf5ef2aSThomas Huth     env->cc_x = (ccr & CCF_X ? 1 : 0);
1305fcf5ef2aSThomas Huth     env->cc_n = (ccr & CCF_N ? -1 : 0);
1306fcf5ef2aSThomas Huth     env->cc_z = (ccr & CCF_Z ? 0 : 1);
1307fcf5ef2aSThomas Huth     env->cc_v = (ccr & CCF_V ? -1 : 0);
1308fcf5ef2aSThomas Huth     env->cc_c = (ccr & CCF_C ? 1 : 0);
1309fcf5ef2aSThomas Huth     env->cc_op = CC_OP_FLAGS;
1310fcf5ef2aSThomas Huth }
1311fcf5ef2aSThomas Huth 
HELPER(set_ccr)1312fcf5ef2aSThomas Huth void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
1313fcf5ef2aSThomas Huth {
1314fcf5ef2aSThomas Huth     cpu_m68k_set_ccr(env, ccr);
1315fcf5ef2aSThomas Huth }
1316fcf5ef2aSThomas Huth 
HELPER(flush_flags)1317fcf5ef2aSThomas Huth void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
1318fcf5ef2aSThomas Huth {
1319fcf5ef2aSThomas Huth     uint32_t res, src1, src2;
1320fcf5ef2aSThomas Huth 
1321fcf5ef2aSThomas Huth     COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
1322fcf5ef2aSThomas Huth     env->cc_op = CC_OP_FLAGS;
1323fcf5ef2aSThomas Huth }
1324fcf5ef2aSThomas Huth 
HELPER(get_macf)1325fcf5ef2aSThomas Huth uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
1326fcf5ef2aSThomas Huth {
1327fcf5ef2aSThomas Huth     int rem;
1328fcf5ef2aSThomas Huth     uint32_t result;
1329fcf5ef2aSThomas Huth 
1330fcf5ef2aSThomas Huth     if (env->macsr & MACSR_SU) {
1331fcf5ef2aSThomas Huth         /* 16-bit rounding.  */
1332fcf5ef2aSThomas Huth         rem = val & 0xffffff;
1333fcf5ef2aSThomas Huth         val = (val >> 24) & 0xffffu;
1334fcf5ef2aSThomas Huth         if (rem > 0x800000)
1335fcf5ef2aSThomas Huth             val++;
1336fcf5ef2aSThomas Huth         else if (rem == 0x800000)
1337fcf5ef2aSThomas Huth             val += (val & 1);
1338fcf5ef2aSThomas Huth     } else if (env->macsr & MACSR_RT) {
1339fcf5ef2aSThomas Huth         /* 32-bit rounding.  */
1340fcf5ef2aSThomas Huth         rem = val & 0xff;
1341fcf5ef2aSThomas Huth         val >>= 8;
1342fcf5ef2aSThomas Huth         if (rem > 0x80)
1343fcf5ef2aSThomas Huth             val++;
1344fcf5ef2aSThomas Huth         else if (rem == 0x80)
1345fcf5ef2aSThomas Huth             val += (val & 1);
1346fcf5ef2aSThomas Huth     } else {
1347fcf5ef2aSThomas Huth         /* No rounding.  */
1348fcf5ef2aSThomas Huth         val >>= 8;
1349fcf5ef2aSThomas Huth     }
1350fcf5ef2aSThomas Huth     if (env->macsr & MACSR_OMC) {
1351fcf5ef2aSThomas Huth         /* Saturate.  */
1352fcf5ef2aSThomas Huth         if (env->macsr & MACSR_SU) {
1353fcf5ef2aSThomas Huth             if (val != (uint16_t) val) {
1354fcf5ef2aSThomas Huth                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
1355fcf5ef2aSThomas Huth             } else {
1356fcf5ef2aSThomas Huth                 result = val & 0xffff;
1357fcf5ef2aSThomas Huth             }
1358fcf5ef2aSThomas Huth         } else {
1359fcf5ef2aSThomas Huth             if (val != (uint32_t)val) {
1360fcf5ef2aSThomas Huth                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
1361fcf5ef2aSThomas Huth             } else {
1362fcf5ef2aSThomas Huth                 result = (uint32_t)val;
1363fcf5ef2aSThomas Huth             }
1364fcf5ef2aSThomas Huth         }
1365fcf5ef2aSThomas Huth     } else {
1366fcf5ef2aSThomas Huth         /* No saturation.  */
1367fcf5ef2aSThomas Huth         if (env->macsr & MACSR_SU) {
1368fcf5ef2aSThomas Huth             result = val & 0xffff;
1369fcf5ef2aSThomas Huth         } else {
1370fcf5ef2aSThomas Huth             result = (uint32_t)val;
1371fcf5ef2aSThomas Huth         }
1372fcf5ef2aSThomas Huth     }
1373fcf5ef2aSThomas Huth     return result;
1374fcf5ef2aSThomas Huth }
1375fcf5ef2aSThomas Huth 
HELPER(get_macs)1376fcf5ef2aSThomas Huth uint32_t HELPER(get_macs)(uint64_t val)
1377fcf5ef2aSThomas Huth {
1378fcf5ef2aSThomas Huth     if (val == (int32_t)val) {
1379fcf5ef2aSThomas Huth         return (int32_t)val;
1380fcf5ef2aSThomas Huth     } else {
1381fcf5ef2aSThomas Huth         return (val >> 61) ^ ~SIGNBIT;
1382fcf5ef2aSThomas Huth     }
1383fcf5ef2aSThomas Huth }
1384fcf5ef2aSThomas Huth 
HELPER(get_macu)1385fcf5ef2aSThomas Huth uint32_t HELPER(get_macu)(uint64_t val)
1386fcf5ef2aSThomas Huth {
1387fcf5ef2aSThomas Huth     if ((val >> 32) == 0) {
1388fcf5ef2aSThomas Huth         return (uint32_t)val;
1389fcf5ef2aSThomas Huth     } else {
1390fcf5ef2aSThomas Huth         return 0xffffffffu;
1391fcf5ef2aSThomas Huth     }
1392fcf5ef2aSThomas Huth }
1393fcf5ef2aSThomas Huth 
HELPER(get_mac_extf)1394fcf5ef2aSThomas Huth uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
1395fcf5ef2aSThomas Huth {
1396fcf5ef2aSThomas Huth     uint32_t val;
1397fcf5ef2aSThomas Huth     val = env->macc[acc] & 0x00ff;
1398fcf5ef2aSThomas Huth     val |= (env->macc[acc] >> 32) & 0xff00;
1399fcf5ef2aSThomas Huth     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
1400fcf5ef2aSThomas Huth     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
1401fcf5ef2aSThomas Huth     return val;
1402fcf5ef2aSThomas Huth }
1403fcf5ef2aSThomas Huth 
HELPER(get_mac_exti)1404fcf5ef2aSThomas Huth uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
1405fcf5ef2aSThomas Huth {
1406fcf5ef2aSThomas Huth     uint32_t val;
1407fcf5ef2aSThomas Huth     val = (env->macc[acc] >> 32) & 0xffff;
1408fcf5ef2aSThomas Huth     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
1409fcf5ef2aSThomas Huth     return val;
1410fcf5ef2aSThomas Huth }
1411fcf5ef2aSThomas Huth 
HELPER(set_mac_extf)1412fcf5ef2aSThomas Huth void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
1413fcf5ef2aSThomas Huth {
1414fcf5ef2aSThomas Huth     int64_t res;
1415fcf5ef2aSThomas Huth     int32_t tmp;
1416fcf5ef2aSThomas Huth     res = env->macc[acc] & 0xffffffff00ull;
1417fcf5ef2aSThomas Huth     tmp = (int16_t)(val & 0xff00);
1418fcf5ef2aSThomas Huth     res |= ((int64_t)tmp) << 32;
1419fcf5ef2aSThomas Huth     res |= val & 0xff;
1420fcf5ef2aSThomas Huth     env->macc[acc] = res;
1421fcf5ef2aSThomas Huth     res = env->macc[acc + 1] & 0xffffffff00ull;
1422fcf5ef2aSThomas Huth     tmp = (val & 0xff000000);
1423fcf5ef2aSThomas Huth     res |= ((int64_t)tmp) << 16;
1424fcf5ef2aSThomas Huth     res |= (val >> 16) & 0xff;
1425fcf5ef2aSThomas Huth     env->macc[acc + 1] = res;
1426fcf5ef2aSThomas Huth }
1427fcf5ef2aSThomas Huth 
HELPER(set_mac_exts)1428fcf5ef2aSThomas Huth void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
1429fcf5ef2aSThomas Huth {
1430fcf5ef2aSThomas Huth     int64_t res;
1431fcf5ef2aSThomas Huth     int32_t tmp;
1432fcf5ef2aSThomas Huth     res = (uint32_t)env->macc[acc];
1433fcf5ef2aSThomas Huth     tmp = (int16_t)val;
1434fcf5ef2aSThomas Huth     res |= ((int64_t)tmp) << 32;
1435fcf5ef2aSThomas Huth     env->macc[acc] = res;
1436fcf5ef2aSThomas Huth     res = (uint32_t)env->macc[acc + 1];
1437fcf5ef2aSThomas Huth     tmp = val & 0xffff0000;
1438fcf5ef2aSThomas Huth     res |= (int64_t)tmp << 16;
1439fcf5ef2aSThomas Huth     env->macc[acc + 1] = res;
1440fcf5ef2aSThomas Huth }
1441fcf5ef2aSThomas Huth 
HELPER(set_mac_extu)1442fcf5ef2aSThomas Huth void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
1443fcf5ef2aSThomas Huth {
1444fcf5ef2aSThomas Huth     uint64_t res;
1445fcf5ef2aSThomas Huth     res = (uint32_t)env->macc[acc];
1446fcf5ef2aSThomas Huth     res |= ((uint64_t)(val & 0xffff)) << 32;
1447fcf5ef2aSThomas Huth     env->macc[acc] = res;
1448fcf5ef2aSThomas Huth     res = (uint32_t)env->macc[acc + 1];
1449fcf5ef2aSThomas Huth     res |= (uint64_t)(val & 0xffff0000) << 16;
1450fcf5ef2aSThomas Huth     env->macc[acc + 1] = res;
1451fcf5ef2aSThomas Huth }
14520bdb2b3bSLaurent Vivier 
14536a140586SPhilippe Mathieu-Daudé #if !defined(CONFIG_USER_ONLY)
HELPER(ptest)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 
HELPER(pflush)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 
HELPER(reset)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