--- previous/src/cpu/cpummu.h 2018/04/24 19:25:47 1.1 +++ previous/src/cpu/cpummu.h 2018/04/24 19:33:34 1.1.1.6 @@ -1,595 +1,678 @@ -/* - * cpummu.h - MMU emulation - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by UAE MMU patch - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CPUMMU_H -#define CPUMMU_H - -#include "compat.h" - -#ifndef FULLMMU -#define FULLMMU -#endif - -#define DUNUSED(x) -#define D -#if DEBUG -#define bug write_log -#else -#define bug -#endif - -/*struct m68k_exception { - int prb; - m68k_exception (int exc) : prb (exc) {} - operator int() { return prb; } -};*/ -typedef int m68k_exception; - -#define SAVE_EXCEPTION -#define RESTORE_EXCEPTION -//#define TRY(var) try -//#define CATCH(var) catch(m68k_exception var) -#define CATCH(var) if (except != 0) -//#define THROW(n) except=n -//#define THROW_AGAIN(var) except=var -#define VOLATILE -#define ALWAYS_INLINE __inline - -static __inline void flush_internals (void) { } - -//typedef uae_u8 flagtype; - -static m68k_exception except; - -struct xttrx { - uae_u32 log_addr_base : 8; - uae_u32 log_addr_mask : 8; - uae_u32 enable : 1; - uae_u32 s_field : 2; - uae_u32 : 3; - uae_u32 usr1 : 1; - uae_u32 usr0 : 1; - uae_u32 : 1; - uae_u32 cmode : 2; - uae_u32 : 2; - uae_u32 write : 1; - uae_u32 : 2; -}; - -struct mmusr_t { - uae_u32 phys_addr : 20; - uae_u32 bus_err : 1; - uae_u32 global : 1; - uae_u32 usr1 : 1; - uae_u32 usr0 : 1; - uae_u32 super : 1; - uae_u32 cmode : 2; - uae_u32 modif : 1; - uae_u32 : 1; - uae_u32 write : 1; - uae_u32 ttrhit : 1; - uae_u32 resident : 1; -}; - -struct log_addr4 { - uae_u32 rif : 7; - uae_u32 pif : 7; - uae_u32 paif : 6; - uae_u32 poff : 12; -}; - -struct log_addr8 { - uae_u32 rif : 7; - uae_u32 pif : 7; - uae_u32 paif : 5; - uae_u32 poff : 13; -}; - -#define MMU_TEST_PTEST 1 -#define MMU_TEST_VERBOSE 2 -#define MMU_TEST_FORCE_TABLE_SEARCH 4 -#define MMU_TEST_NO_BUSERR 8 - -extern void mmu_dump_tables(void); - -#define MMU_TTR_LOGICAL_BASE 0xff000000 -#define MMU_TTR_LOGICAL_MASK 0x00ff0000 -#define MMU_TTR_BIT_ENABLED (1 << 15) -#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) -#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) -#define MMU_TTR_SFIELD_SHIFT 13 -#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) -#define MMU_TTR_UX_SHIFT 8 -#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) -#define MMU_TTR_CACHE_SHIFT 5 -#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) - -#define MMU_UDT_MASK 3 -#define MMU_PDT_MASK 3 - -#define MMU_DES_WP 4 -#define MMU_DES_USED 8 - -/* page descriptors only */ -#define MMU_DES_MODIFIED 16 -#define MMU_DES_SUPER (1 << 7) -#define MMU_DES_GLOBAL (1 << 10) - -#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 -#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 -#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 - -#define MMU_PAGE_INDIRECT_MASK 0xfffffffc -#define MMU_PAGE_ADDR_MASK_8 0xffffe000 -#define MMU_PAGE_ADDR_MASK_4 0xfffff000 -#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) -#define MMU_PAGE_UR_MASK_4 (1 << 11) -#define MMU_PAGE_UR_SHIFT 11 - -#define MMU_MMUSR_ADDR_MASK 0xfffff000 -#define MMU_MMUSR_B (1 << 11) -#define MMU_MMUSR_G (1 << 10) -#define MMU_MMUSR_U1 (1 << 9) -#define MMU_MMUSR_U0 (1 << 8) -#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) -#define MMU_MMUSR_S (1 << 7) -#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) -#define MMU_MMUSR_M (1 << 4) -#define MMU_MMUSR_W (1 << 2) -#define MMU_MMUSR_T (1 << 1) -#define MMU_MMUSR_R (1 << 0) - -/* special status word (access error stack frame) */ -#define MMU_SSW_TM 0x0007 -#define MMU_SSW_TT 0x0018 -#define MMU_SSW_SIZE 0x0060 -#define MMU_SSW_SIZE_B 0x0020 -#define MMU_SSW_SIZE_W 0x0040 -#define MMU_SSW_SIZE_L 0x0000 -#define MMU_SSW_RW 0x0100 -#define MMU_SSW_LK 0x0200 -#define MMU_SSW_ATC 0x0400 -#define MMU_SSW_MA 0x0800 -#define MMU_SSW_CM 0x1000 -#define MMU_SSW_CT 0x2000 -#define MMU_SSW_CU 0x4000 -#define MMU_SSW_CP 0x8000 - -#define TTR_I0 4 -#define TTR_I1 5 -#define TTR_D0 6 -#define TTR_D1 7 - -#define TTR_NO_MATCH 0 -#define TTR_NO_WRITE 1 -#define TTR_OK_MATCH 2 - -struct mmu_atc_line { - uae_u16 tag; - unsigned tt : 1; - unsigned valid_data : 1; - unsigned valid_inst : 1; - unsigned global : 1; - unsigned modified : 1; - unsigned write_protect : 1; - unsigned hw : 1; - unsigned bus_fault : 1; - uaecptr phys; -}; - -/* - * We don't need to store the whole logical address in the atc cache, as part of - * it is encoded as index into the cache. 14 bits of the address are stored in - * the tag, this means at least 6 bits must go into the index. The upper two - * bits of the tag define the type of data in the atc line: - * - 00: a normal memory address - * - 11: invalid memory address or hardware access - * (generated via ~ATC_TAG(addr) in the slow path) - * - 10: empty atc line - */ - -#define ATC_TAG_SHIFT 18 -#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT) - - -#define ATC_L1_SIZE_LOG 8 -#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG) - -#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE) - -/* - * first level atc cache - * indexed by [super][data][rw][idx] - */ - -typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE]; -extern mmu_atc_l1_array atc_l1[2]; -extern mmu_atc_l1_array *current_atc; - -#define ATC_L2_SIZE_LOG 12 -#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG) - -#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE) - -extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; - -/* - * lookup address in the level 1 atc cache, - * the data and write arguments are constant in the common, - * thus allows gcc to generate a constant offset. - */ -static ALWAYS_INLINE bool mmu_lookup(uaecptr addr, bool data, bool write, - struct mmu_atc_line **cl) -{ - addr >>= 12; - *cl = &(*current_atc)[data ? 1 : 0][write ? 1 : 0][addr % ATC_L1_SIZE]; - return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); -} - -/* - * similiar to mmu_user_lookup, but for the use of the moves instruction - */ -static ALWAYS_INLINE bool mmu_user_lookup(uaecptr addr, bool super, bool data, - bool write, struct mmu_atc_line **cl) -{ - addr >>= 12; - *cl = &atc_l1[super ? 1 : 0][data ? 1 : 0][write ? 1 : 0][addr % ATC_L1_SIZE]; - return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); -} - -extern uae_u16 REGPARAM3 mmu_get_word_unaligned(uaecptr addr, bool data) REGPARAM; -extern uae_u32 REGPARAM3 mmu_get_long_unaligned(uaecptr addr, bool data) REGPARAM; - -extern uae_u8 REGPARAM3 mmu_get_byte_slow(uaecptr addr, bool super, bool data, - int size, struct mmu_atc_line *cl) REGPARAM; -extern uae_u16 REGPARAM3 mmu_get_word_slow(uaecptr addr, bool super, bool data, - int size, struct mmu_atc_line *cl) REGPARAM; -extern uae_u32 REGPARAM3 mmu_get_long_slow(uaecptr addr, bool super, bool data, - int size, struct mmu_atc_line *cl) REGPARAM; - -extern void REGPARAM3 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data) REGPARAM; -extern void REGPARAM3 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data) REGPARAM; - -extern void REGPARAM3 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data, - int size, struct mmu_atc_line *cl) REGPARAM; -extern void REGPARAM3 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data, - int size, struct mmu_atc_line *cl) REGPARAM; -extern void REGPARAM3 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data, - int size, struct mmu_atc_line *cl) REGPARAM; - -extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); - -#define FC_DATA (regs.s ? 5 : 1) -#define FC_INST (regs.s ? 6 : 2) - -extern uaecptr REGPARAM3 mmu_translate(uaecptr addr, bool super, bool data, bool write) REGPARAM; - -extern uae_u32 REGPARAM3 sfc_get_long(uaecptr addr) REGPARAM; -extern uae_u16 REGPARAM3 sfc_get_word(uaecptr addr) REGPARAM; -extern uae_u8 REGPARAM3 sfc_get_byte(uaecptr addr) REGPARAM; -extern void REGPARAM3 dfc_put_long(uaecptr addr, uae_u32 val) REGPARAM; -extern void REGPARAM3 dfc_put_word(uaecptr addr, uae_u16 val) REGPARAM; -extern void REGPARAM3 dfc_put_byte(uaecptr addr, uae_u8 val) REGPARAM; - - -extern void REGPARAM3 mmu_flush_atc(uaecptr addr, bool super, bool global) REGPARAM; -extern void REGPARAM3 mmu_flush_atc_all(bool global) REGPARAM; -extern void REGPARAM3 mmu_op_real(uae_u32 opcode, uae_u16 extra) REGPARAM; - -extern void REGPARAM3 mmu_reset(void) REGPARAM; -extern void REGPARAM3 mmu_set_tc(uae_u16 tc) REGPARAM; -extern void REGPARAM3 mmu_set_super(bool super) REGPARAM; - -static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size) -{ - return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000); -} - -static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) -{ - return cl->phys + addr; -} - -static ALWAYS_INLINE void phys_put_long(uaecptr addr, uae_u32 l) -{ - longput(addr, l); -} -static ALWAYS_INLINE void phys_put_word(uaecptr addr, uae_u32 w) -{ - wordput(addr, w); -} -static ALWAYS_INLINE void phys_put_byte(uaecptr addr, uae_u32 b) -{ - byteput(addr, b); -} -static ALWAYS_INLINE uae_u32 phys_get_long(uaecptr addr) -{ - return longget (addr); -} -static ALWAYS_INLINE uae_u32 phys_get_word(uaecptr addr) -{ - return wordget (addr); -} -static ALWAYS_INLINE uae_u32 phys_get_byte(uaecptr addr) -{ - return byteget (addr); -} - -static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, false, &cl))) - return phys_get_long(mmu_get_real_address(addr, cl)); - return mmu_get_long_slow(addr, regs.s != 0, data, size, cl); -} - -static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, false, &cl))) - return phys_get_word(mmu_get_real_address(addr, cl)); - return mmu_get_word_slow(addr, regs.s != 0, data, size, cl); -} - -static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, false, &cl))) - return phys_get_byte(mmu_get_real_address(addr, cl)); - return mmu_get_byte_slow(addr, regs.s != 0, data, size, cl); -} - - -static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, true, &cl))) - phys_put_long(mmu_get_real_address(addr, cl), val); - else - mmu_put_long_slow(addr, val, regs.s != 0, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, true, &cl))) - phys_put_word(mmu_get_real_address(addr, cl), val); - else - mmu_put_word_slow(addr, val, regs.s != 0, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, true, &cl))) - phys_put_byte(mmu_get_real_address(addr, cl), val); - else - mmu_put_byte_slow(addr, val, regs.s != 0, data, size, cl); -} - -static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, false, &cl))) - return phys_get_long(mmu_get_real_address(addr, cl)); - return mmu_get_long_slow(addr, super, data, size, cl); -} - -static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, false, &cl))) - return phys_get_word(mmu_get_real_address(addr, cl)); - return mmu_get_word_slow(addr, super, data, size, cl); -} - -static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, false, &cl))) - return phys_get_byte(mmu_get_real_address(addr, cl)); - return mmu_get_byte_slow(addr, super, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, true, &cl))) - phys_put_long(mmu_get_real_address(addr, cl), val); - else - mmu_put_long_slow(addr, val, super, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, true, &cl))) - phys_put_word(mmu_get_real_address(addr, cl), val); - else - mmu_put_word_slow(addr, val, super, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, bool data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, true, &cl))) - phys_put_byte(mmu_get_real_address(addr, cl), val); - else - mmu_put_byte_slow(addr, val, super, data, size, cl); -} - - -static ALWAYS_INLINE void HWput_l(uaecptr addr, uae_u32 l) -{ - put_long (addr, l); -} -static ALWAYS_INLINE void HWput_w(uaecptr addr, uae_u32 w) -{ - put_word (addr, w); -} -static ALWAYS_INLINE void HWput_b(uaecptr addr, uae_u32 b) -{ - put_byte (addr, b); -} -static ALWAYS_INLINE uae_u32 HWget_l(uaecptr addr) -{ - return get_long (addr); -} -static ALWAYS_INLINE uae_u32 HWget_w(uaecptr addr) -{ - return get_word (addr); -} -static ALWAYS_INLINE uae_u32 HWget_b(uaecptr addr) -{ - return get_byte (addr); -} - -static ALWAYS_INLINE uae_u32 uae_mmu_get_ilong(uaecptr addr) -{ - if (unlikely(is_unaligned(addr, 4))) - return mmu_get_long_unaligned(addr, false); - return mmu_get_long(addr, false, sz_long); -} -static ALWAYS_INLINE uae_u16 uae_mmu_get_iword(uaecptr addr) -{ - if (unlikely(is_unaligned(addr, 2))) - return mmu_get_word_unaligned(addr, false); - return mmu_get_word(addr, false, sz_word); -} -static ALWAYS_INLINE uae_u16 uae_mmu_get_ibyte(uaecptr addr) -{ - return mmu_get_byte(addr, false, sz_byte); -} -static ALWAYS_INLINE uae_u32 uae_mmu_get_long(uaecptr addr) -{ - if (unlikely(is_unaligned(addr, 4))) - return mmu_get_long_unaligned(addr, true); - return mmu_get_long(addr, true, sz_long); -} -static ALWAYS_INLINE uae_u16 uae_mmu_get_word(uaecptr addr) -{ - if (unlikely(is_unaligned(addr, 2))) - return mmu_get_word_unaligned(addr, true); - return mmu_get_word(addr, true, sz_word); -} -static ALWAYS_INLINE uae_u8 uae_mmu_get_byte(uaecptr addr) -{ - return mmu_get_byte(addr, true, sz_byte); -} -static ALWAYS_INLINE void uae_mmu_put_long(uaecptr addr, uae_u32 val) -{ - if (unlikely(is_unaligned(addr, 4))) - mmu_put_long_unaligned(addr, val, true); - else - mmu_put_long(addr, val, true, sz_long); -} -static ALWAYS_INLINE void uae_mmu_put_word(uaecptr addr, uae_u16 val) -{ - if (unlikely(is_unaligned(addr, 2))) - mmu_put_word_unaligned(addr, val, true); - else - mmu_put_word(addr, val, true, sz_word); -} -static ALWAYS_INLINE void uae_mmu_put_byte(uaecptr addr, uae_u8 val) -{ - mmu_put_byte(addr, val, true, sz_byte); -} - -STATIC_INLINE void put_byte_mmu (uaecptr addr, uae_u32 v) -{ - uae_mmu_put_byte (addr, v); -} -STATIC_INLINE void put_word_mmu (uaecptr addr, uae_u32 v) -{ - uae_mmu_put_word (addr, v); -} -STATIC_INLINE void put_long_mmu (uaecptr addr, uae_u32 v) -{ - uae_mmu_put_long (addr, v); -} -STATIC_INLINE uae_u32 get_byte_mmu (uaecptr addr) -{ - return uae_mmu_get_byte (addr); -} -STATIC_INLINE uae_u32 get_word_mmu (uaecptr addr) -{ - return uae_mmu_get_word (addr); -} -STATIC_INLINE uae_u32 get_long_mmu (uaecptr addr) -{ - return uae_mmu_get_long (addr); -} -STATIC_INLINE uae_u32 get_ibyte_mmu (int o) -{ - uae_u32 pc = m68k_getpc () + o; - return uae_mmu_get_iword (pc); -} -STATIC_INLINE uae_u32 get_iword_mmu (int o) -{ - uae_u32 pc = m68k_getpc () + o; - return uae_mmu_get_iword (pc); -} -STATIC_INLINE uae_u32 get_ilong_mmu (int o) -{ - uae_u32 pc = m68k_getpc () + o; - return uae_mmu_get_ilong (pc); -} -STATIC_INLINE uae_u32 next_iword_mmu (void) -{ - uae_u32 pc = m68k_getpc (); - m68k_incpci (2); - return uae_mmu_get_iword (pc); -} -STATIC_INLINE uae_u32 next_ilong_mmu (void) -{ - uae_u32 pc = m68k_getpc (); - m68k_incpci (4); - return uae_mmu_get_ilong (pc); -} - -extern void m68k_do_rts_mmu (void); -extern void m68k_do_rte_mmu (uaecptr a7); -extern void m68k_do_bsr_mmu (uaecptr oldpc, uae_s32 offset); - -struct mmufixup -{ - int reg; - uae_u32 value; -}; -extern struct mmufixup mmufixup[2]; - -#endif /* CPUMMU_H */ +/* + * cpummu.h - MMU emulation + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by UAE MMU patch + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef UAE_CPUMMU_H +#define UAE_CPUMMU_H + +//#include "uae/types.h" + +#include "mmu_common.h" + +#ifndef FULLMMU +#define FULLMMU +#endif + +#define DUNUSED(x) +#define D +#if DEBUG +#define bug write_log +#else +#define bug +#endif + +static __inline void flush_internals (void) { } + +extern int mmu060_state; + +extern int mmu040_movem; +extern uaecptr mmu040_movem_ea; +extern uae_u32 mmu040_move16[4]; + +extern bool mmu_pagesize_8k; +extern uae_u16 mmu_opcode; +extern bool mmu_restart; +extern bool mmu_ttr_enabled; + +//typedef uae_u8 flagtype; + +//static m68k_exception except; + +struct xttrx { + uae_u32 log_addr_base : 8; + uae_u32 log_addr_mask : 8; + uae_u32 enable : 1; + uae_u32 s_field : 2; + uae_u32 : 3; + uae_u32 usr1 : 1; + uae_u32 usr0 : 1; + uae_u32 : 1; + uae_u32 cmode : 2; + uae_u32 : 2; + uae_u32 write : 1; + uae_u32 : 2; +}; + +struct mmusr_t { + uae_u32 phys_addr : 20; + uae_u32 bus_err : 1; + uae_u32 global : 1; + uae_u32 usr1 : 1; + uae_u32 usr0 : 1; + uae_u32 super : 1; + uae_u32 cmode : 2; + uae_u32 modif : 1; + uae_u32 : 1; + uae_u32 write : 1; + uae_u32 ttrhit : 1; + uae_u32 resident : 1; +}; + +struct log_addr4 { + uae_u32 rif : 7; + uae_u32 pif : 7; + uae_u32 paif : 6; + uae_u32 poff : 12; +}; + +struct log_addr8 { + uae_u32 rif : 7; + uae_u32 pif : 7; + uae_u32 paif : 5; + uae_u32 poff : 13; +}; + +#define MMU_TEST_PTEST 1 +#define MMU_TEST_VERBOSE 2 +#define MMU_TEST_FORCE_TABLE_SEARCH 4 +#define MMU_TEST_NO_BUSERR 8 + +extern void mmu_dump_tables(void); + +#define MMU_TTR_LOGICAL_BASE 0xff000000 +#define MMU_TTR_LOGICAL_MASK 0x00ff0000 +#define MMU_TTR_BIT_ENABLED (1 << 15) +#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) +#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) +#define MMU_TTR_SFIELD_SHIFT 13 +#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) +#define MMU_TTR_UX_SHIFT 8 +#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) +#define MMU_TTR_CACHE_SHIFT 5 +#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) + +#define MMU_UDT_MASK 3 +#define MMU_PDT_MASK 3 + +#define MMU_DES_WP 4 +#define MMU_DES_USED 8 + +/* page descriptors only */ +#define MMU_DES_MODIFIED 16 +#define MMU_DES_SUPER (1 << 7) +#define MMU_DES_GLOBAL (1 << 10) + +#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 +#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 +#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 + +#define MMU_PAGE_INDIRECT_MASK 0xfffffffc +#define MMU_PAGE_ADDR_MASK_8 0xffffe000 +#define MMU_PAGE_ADDR_MASK_4 0xfffff000 +#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) +#define MMU_PAGE_UR_MASK_4 (1 << 11) +#define MMU_PAGE_UR_SHIFT 11 + +#define MMU_MMUSR_ADDR_MASK 0xfffff000 +#define MMU_MMUSR_B (1 << 11) +#define MMU_MMUSR_G (1 << 10) +#define MMU_MMUSR_U1 (1 << 9) +#define MMU_MMUSR_U0 (1 << 8) +#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) +#define MMU_MMUSR_S (1 << 7) +#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) +#define MMU_MMUSR_M (1 << 4) +#define MMU_MMUSR_W (1 << 2) +#define MMU_MMUSR_T (1 << 1) +#define MMU_MMUSR_R (1 << 0) + +#define TTR_I0 4 +#define TTR_I1 5 +#define TTR_D0 6 +#define TTR_D1 7 + +#define TTR_NO_MATCH 0 +#define TTR_NO_WRITE 1 +#define TTR_OK_MATCH 2 + +struct mmu_atc_line { + uaecptr tag; // tag is 16 or 17 bits S+logical + uae_u32 valid; + uae_u32 status; + uaecptr phys; // phys base address +}; + +/* + * 68040 ATC is a 4 way 16 slot associative address translation cache + * the 68040 has a DATA and an INSTRUCTION ATC. + * an ATC lookup may result in : a hit, a miss and a modified state. + * the 68060 can disable ATC allocation + * we must take care of 8k and 4k page size, index position is relative to page size + */ + +#define ATC_WAYS 4 +#define ATC_SLOTS 16 +#define ATC_TYPE 2 + +extern uae_u32 mmu_is_super; +extern uae_u32 mmu_tagmask, mmu_pagemask; +extern struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS]; + +extern void mmu_tt_modified(void); +extern uaecptr mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size); + +extern uae_u32 REGPARAM3 mmu060_get_rmw_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM; +extern void REGPARAM3 mmu060_put_rmw_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM; + +extern uae_u16 REGPARAM3 mmu_get_word_unaligned(uaecptr addr) REGPARAM; +extern uae_u32 REGPARAM3 mmu_get_long_unaligned(uaecptr addr) REGPARAM; + +extern uae_u32 REGPARAM3 mmu_get_ilong_unaligned(uaecptr addr) REGPARAM; + +extern void REGPARAM3 mmu_put_word_unaligned(uaecptr addr, uae_u16 val) REGPARAM; +extern void REGPARAM3 mmu_put_long_unaligned(uaecptr addr, uae_u32 val) REGPARAM; + +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); + +#define FC_DATA (regs.s ? 5 : 1) +#define FC_INST (regs.s ? 6 : 2) + +extern void mmu_bus_error(uaecptr addr, uae_u32 val, int fc, bool write, int size, bool nonmmu); + +extern uae_u32 REGPARAM3 sfc_get_long(uaecptr addr) REGPARAM; +extern uae_u16 REGPARAM3 sfc_get_word(uaecptr addr) REGPARAM; +extern uae_u8 REGPARAM3 sfc_get_byte(uaecptr addr) REGPARAM; +extern void REGPARAM3 dfc_put_long(uaecptr addr, uae_u32 val) REGPARAM; +extern void REGPARAM3 dfc_put_word(uaecptr addr, uae_u16 val) REGPARAM; +extern void REGPARAM3 dfc_put_byte(uaecptr addr, uae_u8 val) REGPARAM; + +#define sfc040_get_long sfc_get_long +#define sfc040_get_word sfc_get_word +#define sfc040_get_byte sfc_get_byte +#define dfc040_put_long dfc_put_long +#define dfc040_put_word dfc_put_word +#define dfc040_put_byte dfc_put_byte + +#define sfc060_get_long sfc_get_long +#define sfc060_get_word sfc_get_word +#define sfc060_get_byte sfc_get_byte +#define dfc060_put_long dfc_put_long +#define dfc060_put_word dfc_put_word +#define dfc060_put_byte dfc_put_byte + +extern void uae_mmu_put_lrmw (uaecptr addr, uae_u32 v, int size, int type); +extern uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type); + +extern void REGPARAM3 mmu_flush_atc(uaecptr addr, bool super, bool global) REGPARAM; +extern void REGPARAM3 mmu_flush_atc_all(bool global) REGPARAM; +extern void REGPARAM3 mmu_op_real(uae_u32 opcode, uae_u16 extra) REGPARAM; + +extern void REGPARAM3 mmu_reset(void) REGPARAM; +extern void REGPARAM3 mmu_set_funcs(void) REGPARAM; +extern void REGPARAM3 mmu_set_tc(uae_u16 tc) REGPARAM; +extern void REGPARAM3 mmu_set_super(bool super) REGPARAM; + +static ALWAYS_INLINE int mmu_get_fc(bool super, bool data) +{ + return (super ? 4 : 0) | (data ? 1 : 2); +} + +/* + * mmu access is a 4 step process: + * if mmu is not enabled just read physical + * check transparent region, if transparent, read physical + * check ATC (address translation cache), read immediatly if HIT + * read from mmu with the long path (and allocate ATC entry if needed) + */ + +/* check if an address matches a ttr */ +static ALWAYS_INLINE int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super) +{ + if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ + uae_u8 msb, mask; + + msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; + mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; + + if (!(msb & ~mask)) { + + if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { + if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { + return TTR_NO_MATCH; + } + } + + return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; + } + } + return TTR_NO_MATCH; +} + +static ALWAYS_INLINE int mmu_match_ttr(uaecptr addr, bool super, bool data) +{ + int res; + + if (!mmu_ttr_enabled) + return TTR_NO_MATCH; + if (data) { + res = mmu_do_match_ttr(regs.dtt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.dtt1, addr, super); + } else { + res = mmu_do_match_ttr(regs.itt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.itt1, addr, super); + } + return res; +} + +static ALWAYS_INLINE int mmu_match_ttr_write(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool write) +{ + if (!mmu_ttr_enabled) + return TTR_NO_MATCH; + int res = mmu_match_ttr(addr, super, data); + if (res == TTR_NO_WRITE && write) + mmu_bus_error(addr, val, mmu_get_fc (super, data), true, size, false); + return res; +} + +static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) +{ + return cl->phys | (addr & mmu_pagemask); +} + +static ALWAYS_INLINE void mmu_get_move16(uaecptr addr, uae_u32 *v, int size) +{ + int i; + bool super = regs.s != 0; + addr &= ~15; + + if (mmu_match_ttr(addr,super,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, super, true, false, size); + } + + for (i = 0; i < 4; i++) { + v[i] = phys_get_long(addr + i * 4); + } +} + +static ALWAYS_INLINE void mmu_put_move16(uaecptr addr, uae_u32 *v, int size) +{ + int i; + bool super = regs.s != 0; + addr &= ~15; + + if (mmu_match_ttr_write(addr,super,true,v[0],size,false) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, v[0], super, true, true, size); + } + + for (i = 0; i < 4; i++) { + phys_put_long(addr + i * 4, v[i]); + } +} + +static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size) +{ + if (mmu_match_ttr(addr,regs.s!=0,false) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, regs.s!=0, false, false, size); + } + return phys_get_long(addr); +} + +static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) +{ + if (mmu_match_ttr(addr,regs.s!=0,false) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, regs.s!=0, false, false, size); + } + return phys_get_word(addr); +} + +static ALWAYS_INLINE uae_u8 mmu_get_ibyte(uaecptr addr, int size) +{ + if (mmu_match_ttr(addr,regs.s!=0,false) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, regs.s!=0, false, false, size); + } + return phys_get_byte(addr); +} + +static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int size) +{ + if (mmu_match_ttr(addr,regs.s!=0,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, regs.s!=0, true, false, size); + } + return phys_get_long(addr); +} + +static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int size) +{ + if (mmu_match_ttr(addr,regs.s!=0,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, regs.s!=0, true, false, size); + } + return phys_get_word(addr); +} + +static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int size) +{ + if (mmu_match_ttr(addr,regs.s!=0,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, regs.s!=0, true, false, size); + } + return phys_get_byte(addr); +} + +static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int size) +{ + if (mmu_match_ttr_write(addr,regs.s!=0,true,val,size,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, val, regs.s!=0, true, true, size); + } + phys_put_long(addr, val); +} + +static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int size) +{ + if (mmu_match_ttr_write(addr,regs.s!=0,true,val,size,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, val, regs.s!=0, true, true, size); + } + phys_put_word(addr, val); +} + +static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int size) +{ + if (mmu_match_ttr_write(addr,regs.s!=0,true,val,size,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, val, regs.s!=0, true, true, size); + } + phys_put_byte(addr, val); +} + +static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool write, int size) +{ + if (mmu_match_ttr_write(addr,super,true,0,size,write) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, super, true, write, size); + } + return phys_get_long(addr); +} + +static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool write, int size) +{ + if (mmu_match_ttr_write(addr,super,true,0,size,write) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, super, true, write, size); + } + return phys_get_word(addr); +} + +static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool write, int size) +{ + if (mmu_match_ttr_write(addr,super,true,0,size,write) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, super, true, write, size); + } + return phys_get_byte(addr); +} + +static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, int size) +{ + if (mmu_match_ttr_write(addr,super,true,val,size,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, val, super, true, true, size); + } + phys_put_long(addr, val); +} + +static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, int size) +{ + if (mmu_match_ttr_write(addr,super,true,val,size,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, val, super, true, true, size); + } + phys_put_word(addr, val); +} + +static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, int size) +{ + if (mmu_match_ttr_write(addr,super,true,val,size,true) == TTR_NO_MATCH && regs.mmu_enabled) { + addr = mmu_translate(addr, val, super, true, true, size); + } + phys_put_byte(addr, val); +} + + +static ALWAYS_INLINE void HWput_l(uaecptr addr, uae_u32 l) +{ + put_long (addr, l); +} +static ALWAYS_INLINE void HWput_w(uaecptr addr, uae_u32 w) +{ + put_word (addr, w); +} +static ALWAYS_INLINE void HWput_b(uaecptr addr, uae_u32 b) +{ + put_byte (addr, b); +} +static ALWAYS_INLINE uae_u32 HWget_l(uaecptr addr) +{ + return get_long (addr); +} +static ALWAYS_INLINE uae_u32 HWget_w(uaecptr addr) +{ + return get_word (addr); +} +static ALWAYS_INLINE uae_u32 HWget_b(uaecptr addr) +{ + return get_byte (addr); +} + +static ALWAYS_INLINE uae_u32 uae_mmu040_get_ilong(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_ilong_unaligned(addr); + return mmu_get_ilong(addr, sz_long); +} +static ALWAYS_INLINE uae_u16 uae_mmu040_get_iword(uaecptr addr) +{ + return mmu_get_iword(addr, sz_word); +} +static ALWAYS_INLINE uae_u16 uae_mmu040_get_ibyte(uaecptr addr) +{ + return mmu_get_ibyte(addr, sz_byte); +} +static ALWAYS_INLINE uae_u32 uae_mmu040_get_long(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_long_unaligned(addr); + return mmu_get_long(addr, sz_long); +} +static ALWAYS_INLINE uae_u16 uae_mmu040_get_word(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 2))) + return mmu_get_word_unaligned(addr); + return mmu_get_word(addr, sz_word); +} +static ALWAYS_INLINE uae_u8 uae_mmu040_get_byte(uaecptr addr) +{ + return mmu_get_byte(addr, sz_byte); +} + +static ALWAYS_INLINE void uae_mmu040_put_word(uaecptr addr, uae_u16 val) +{ + if (unlikely(is_unaligned(addr, 2))) + mmu_put_word_unaligned(addr, val); + else + mmu_put_word(addr, val, sz_word); +} +static ALWAYS_INLINE void uae_mmu040_put_byte(uaecptr addr, uae_u8 val) +{ + mmu_put_byte(addr, val, sz_byte); +} +static ALWAYS_INLINE void uae_mmu040_put_long(uaecptr addr, uae_u32 val) +{ + if (unlikely(is_unaligned(addr, 4))) + mmu_put_long_unaligned(addr, val); + else + mmu_put_long(addr, val, sz_long); +} + + +static ALWAYS_INLINE void uae_mmu_get_move16(uaecptr addr, uae_u32 *val) +{ + // move16 is always aligned + mmu_get_move16(addr, val, 16); +} +static ALWAYS_INLINE void uae_mmu_put_move16(uaecptr addr, uae_u32 *val) +{ + // move16 is always aligned + mmu_put_move16(addr, val, 16); +} + +// normal 040 +STATIC_INLINE void put_byte_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu040_put_byte (addr, v); +} +STATIC_INLINE void put_word_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu040_put_word (addr, v); +} +STATIC_INLINE void put_long_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu040_put_long (addr, v); +} +STATIC_INLINE uae_u32 get_byte_mmu040 (uaecptr addr) +{ + return uae_mmu040_get_byte (addr); +} +STATIC_INLINE uae_u32 get_word_mmu040 (uaecptr addr) +{ + return uae_mmu040_get_word (addr); +} +STATIC_INLINE uae_u32 get_long_mmu040 (uaecptr addr) +{ + return uae_mmu040_get_long (addr); +} +STATIC_INLINE void get_move16_mmu (uaecptr addr, uae_u32 *v) +{ + uae_mmu_get_move16 (addr, v); +} +STATIC_INLINE void put_move16_mmu (uaecptr addr, uae_u32 *v) +{ + uae_mmu_put_move16 (addr, v); +} + +// locked rmw 060 +STATIC_INLINE void put_lrmw_byte_mmu060 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_lrmw (addr, v, sz_byte, 1); +} +STATIC_INLINE void put_lrmw_word_mmu060 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_lrmw (addr, v, sz_word, 1); +} +STATIC_INLINE void put_lrmw_long_mmu060 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_lrmw (addr, v, sz_long, 1); +} +STATIC_INLINE uae_u32 get_lrmw_byte_mmu060 (uaecptr addr) +{ + return uae_mmu_get_lrmw (addr, sz_byte, 1); +} +STATIC_INLINE uae_u32 get_lrmw_word_mmu060 (uaecptr addr) +{ + return uae_mmu_get_lrmw (addr, sz_word, 1); +} +STATIC_INLINE uae_u32 get_lrmw_long_mmu060 (uaecptr addr) +{ + return uae_mmu_get_lrmw (addr, sz_long, 1); +} + +// locked rmw 040 +STATIC_INLINE void put_lrmw_byte_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_lrmw (addr, v, sz_byte, 0); +} +STATIC_INLINE void put_lrmw_word_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_lrmw (addr, v, sz_word, 0); +} +STATIC_INLINE void put_lrmw_long_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_lrmw (addr, v, sz_long, 0); +} +STATIC_INLINE uae_u32 get_lrmw_byte_mmu040 (uaecptr addr) +{ + return uae_mmu_get_lrmw (addr, sz_byte, 0); +} +STATIC_INLINE uae_u32 get_lrmw_word_mmu040 (uaecptr addr) +{ + return uae_mmu_get_lrmw (addr, sz_word, 0); +} +STATIC_INLINE uae_u32 get_lrmw_long_mmu040 (uaecptr addr) +{ + return uae_mmu_get_lrmw (addr, sz_long, 0); +} + +STATIC_INLINE uae_u32 get_ibyte_mmu040 (int o) +{ + uae_u32 pc = m68k_getpci () + o; + return uae_mmu040_get_iword (pc); +} +STATIC_INLINE uae_u32 get_iword_mmu040 (int o) +{ + uae_u32 pc = m68k_getpci () + o; + return uae_mmu040_get_iword (pc); +} +STATIC_INLINE uae_u32 get_ilong_mmu040 (int o) +{ + uae_u32 pc = m68k_getpci () + o; + return uae_mmu040_get_ilong (pc); +} +STATIC_INLINE uae_u32 next_iword_mmu040 (void) +{ + uae_u32 pc = m68k_getpci (); + m68k_incpci (2); + return uae_mmu040_get_iword (pc); +} +STATIC_INLINE uae_u32 next_ilong_mmu040 (void) +{ + uae_u32 pc = m68k_getpci (); + m68k_incpci (4); + return uae_mmu040_get_ilong (pc); +} + +extern void flush_mmu040 (uaecptr, int); +extern void m68k_do_rts_mmu040 (void); +extern void m68k_do_rte_mmu040 (uaecptr a7); +extern void m68k_do_bsr_mmu040 (uaecptr oldpc, uae_s32 offset); + +extern void flush_mmu060 (uaecptr, int); +extern void m68k_do_rts_mmu060 (void); +extern void m68k_do_rte_mmu060 (uaecptr a7); +extern void m68k_do_bsr_mmu060 (uaecptr oldpc, uae_s32 offset); + +#endif /* UAE_CPUMMU_H */