mirror of
https://github.com/Wiimpathy/HatariWii.git
synced 2024-06-02 16:48:43 +02:00
478 lines
13 KiB
C
478 lines
13 KiB
C
#ifndef CPUMMU030_H
|
|
#define CPUMMU030_H
|
|
|
|
#include "mmu_common.h"
|
|
|
|
extern uae_u64 srp_030, crp_030;
|
|
extern uae_u32 tt0_030, tt1_030, tc_030;
|
|
extern uae_u16 mmusr_030;
|
|
|
|
#define MAX_MMU030_ACCESS 10
|
|
extern uae_u32 mm030_stageb_address;
|
|
extern int mmu030_idx;
|
|
extern bool mmu030_retry;
|
|
extern int mmu030_opcode, mmu030_opcode_stageb;
|
|
extern int mmu030_fake_prefetch;
|
|
extern uaecptr mmu030_fake_prefetch_addr;
|
|
extern uae_u16 mmu030_state[3];
|
|
extern uae_u32 mmu030_data_buffer;
|
|
extern uae_u32 mmu030_disp_store[2];
|
|
extern uae_u32 mmu030_fmovem_store[2];
|
|
|
|
#define MMU030_STATEFLAG1_FMOVEM 0x2000
|
|
#define MMU030_STATEFLAG1_MOVEM1 0x4000
|
|
#define MMU030_STATEFLAG1_MOVEM2 0x8000
|
|
#define MMU030_STATEFLAG1_DISP0 0x0001
|
|
#define MMU030_STATEFLAG1_DISP1 0x0002
|
|
|
|
struct mmu030_access
|
|
{
|
|
bool done;
|
|
uae_u32 val;
|
|
};
|
|
extern struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS];
|
|
|
|
uae_u32 REGPARAM3 get_disp_ea_020_mmu030 (uae_u32 base, int idx) REGPARAM;
|
|
void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc);
|
|
|
|
bool mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra);
|
|
bool mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra);
|
|
bool mmu_op30_pload (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra);
|
|
bool mmu_op30_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra);
|
|
|
|
uae_u32 mmu_op30_helper_get_fc(uae_u16 next);
|
|
|
|
void mmu030_ptest_atc_search(uaecptr logical_addr, uae_u32 fc, bool write);
|
|
uae_u32 mmu030_ptest_table_search(uaecptr extra, uae_u32 fc, bool write, int level);
|
|
uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int level);
|
|
|
|
|
|
typedef struct {
|
|
uae_u32 addr_base;
|
|
uae_u32 addr_mask;
|
|
uae_u32 fc_base;
|
|
uae_u32 fc_mask;
|
|
} TT_info;
|
|
|
|
TT_info mmu030_decode_tt(uae_u32 TT);
|
|
bool mmu030_decode_tc(uae_u32 TC);
|
|
bool mmu030_decode_rp(uae_u64 RP);
|
|
|
|
int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write);
|
|
void mmu030_atc_handle_history_bit(int entry_num);
|
|
|
|
void mmu030_put_long_atc(uaecptr addr, uae_u32 val, int l, uae_u32 fc);
|
|
void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc);
|
|
void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc);
|
|
uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc);
|
|
uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc);
|
|
uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc);
|
|
#ifdef WINUAE_FOR_HATARI
|
|
uae_u32 mmu030_get_ilong_atc(uaecptr addr, int l, uae_u32 fc);
|
|
uae_u16 mmu030_get_iword_atc(uaecptr addr, int l, uae_u32 fc);
|
|
#endif
|
|
|
|
void mmu030_put_atc_generic(uaecptr addr, uae_u32 val, int l, uae_u32 fc, int size, int flags);
|
|
uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int flags, bool checkwrite);
|
|
|
|
void mmu030_flush_atc_fc(uae_u32 fc_base, uae_u32 fc_mask);
|
|
void mmu030_flush_atc_page(uaecptr logical_addr);
|
|
void mmu030_flush_atc_page_fc(uaecptr logical_addr, uae_u32 fc_base, uae_u32 fc_mask);
|
|
void mmu030_flush_atc_all(void);
|
|
void mmu030_reset(int hardreset);
|
|
void mmu030_set_funcs(void);
|
|
uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write);
|
|
|
|
int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write);
|
|
int mmu030_match_ttr_access(uaecptr addr, uae_u32 fc, bool write);
|
|
int mmu030_match_lrmw_ttr_access(uaecptr addr, uae_u32 fc);
|
|
int mmu030_do_match_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc, bool write);
|
|
int mmu030_do_match_lrmw_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc);
|
|
|
|
void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc);
|
|
void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc);
|
|
void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc);
|
|
uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc);
|
|
uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc);
|
|
uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc);
|
|
uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc);
|
|
uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc);
|
|
|
|
uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size);
|
|
void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size);
|
|
|
|
void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int accesssize, int flags);
|
|
uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags);
|
|
|
|
extern uae_u16 REGPARAM3 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
|
|
extern uae_u32 REGPARAM3 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
|
|
extern uae_u32 REGPARAM3 mmu030_get_ilong_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
|
|
extern uae_u16 REGPARAM3 mmu030_get_lrmw_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
|
|
extern uae_u32 REGPARAM3 mmu030_get_lrmw_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
|
|
extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) REGPARAM;
|
|
extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags) REGPARAM;
|
|
|
|
static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 2;
|
|
|
|
if (unlikely(is_unaligned(addr, 4)))
|
|
return mmu030_get_ilong_unaligned(addr, fc, 0);
|
|
return mmu030_get_ilong(addr, fc);
|
|
}
|
|
static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword(uaecptr addr)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 2;
|
|
return mmu030_get_iword(addr, fc);
|
|
}
|
|
static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte(uaecptr addr)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 2;
|
|
|
|
return mmu030_get_byte(addr, fc);
|
|
}
|
|
static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 1;
|
|
|
|
if (unlikely(is_unaligned(addr, 4)))
|
|
return mmu030_get_long_unaligned(addr, fc, 0);
|
|
return mmu030_get_long(addr, fc);
|
|
}
|
|
static ALWAYS_INLINE uae_u16 uae_mmu030_get_word(uaecptr addr)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 1;
|
|
|
|
if (unlikely(is_unaligned(addr, 2)))
|
|
return mmu030_get_word_unaligned(addr, fc, 0);
|
|
return mmu030_get_word(addr, fc);
|
|
}
|
|
static ALWAYS_INLINE uae_u8 uae_mmu030_get_byte(uaecptr addr)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 1;
|
|
|
|
return mmu030_get_byte(addr, fc);
|
|
}
|
|
static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 1;
|
|
|
|
if (unlikely(is_unaligned(addr, 4)))
|
|
mmu030_put_long_unaligned(addr, val, fc, 0);
|
|
else
|
|
mmu030_put_long(addr, val, fc);
|
|
}
|
|
static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u16 val)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 1;
|
|
|
|
if (unlikely(is_unaligned(addr, 2)))
|
|
mmu030_put_word_unaligned(addr, val, fc, 0);
|
|
else
|
|
mmu030_put_word(addr, val, fc);
|
|
}
|
|
static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u8 val)
|
|
{
|
|
uae_u32 fc = (regs.s ? 4 : 0) | 1;
|
|
|
|
mmu030_put_byte(addr, val, fc);
|
|
}
|
|
|
|
static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr)
|
|
{
|
|
uae_u32 fc = regs.sfc;
|
|
#if MMUDEBUG > 2
|
|
write_log(_T("sfc030_get_long: FC = %i\n"),fc);
|
|
#endif
|
|
if (unlikely(is_unaligned(addr, 4)))
|
|
return mmu030_get_long_unaligned(addr, fc, 0);
|
|
return mmu030_get_long(addr, fc);
|
|
}
|
|
|
|
static ALWAYS_INLINE uae_u16 sfc030_get_word(uaecptr addr)
|
|
{
|
|
uae_u32 fc = regs.sfc;
|
|
#if MMUDEBUG > 2
|
|
write_log(_T("sfc030_get_word: FC = %i\n"),fc);
|
|
#endif
|
|
if (unlikely(is_unaligned(addr, 2)))
|
|
return mmu030_get_word_unaligned(addr, fc, 0);
|
|
return mmu030_get_word(addr, fc);
|
|
}
|
|
|
|
static ALWAYS_INLINE uae_u8 sfc030_get_byte(uaecptr addr)
|
|
{
|
|
uae_u32 fc = regs.sfc;
|
|
#if MMUDEBUG > 2
|
|
write_log(_T("sfc030_get_byte: FC = %i\n"),fc);
|
|
#endif
|
|
return mmu030_get_byte(addr, fc);
|
|
}
|
|
|
|
static ALWAYS_INLINE void dfc030_put_long(uaecptr addr, uae_u32 val)
|
|
{
|
|
uae_u32 fc = regs.dfc;
|
|
#if MMUDEBUG > 2
|
|
write_log(_T("dfc030_put_long: %08X = %08X FC = %i\n"), addr, val, fc);
|
|
#endif
|
|
if (unlikely(is_unaligned(addr, 4)))
|
|
mmu030_put_long_unaligned(addr, val, fc, 0);
|
|
else
|
|
mmu030_put_long(addr, val, fc);
|
|
}
|
|
|
|
static ALWAYS_INLINE void dfc030_put_word(uaecptr addr, uae_u16 val)
|
|
{
|
|
uae_u32 fc = regs.dfc;
|
|
#if MMUDEBUG > 2
|
|
write_log(_T("dfc030_put_word: %08X = %04X FC = %i\n"), addr, val, fc);
|
|
#endif
|
|
if (unlikely(is_unaligned(addr, 2)))
|
|
mmu030_put_word_unaligned(addr, val, fc, 0);
|
|
else
|
|
mmu030_put_word(addr, val, fc);
|
|
}
|
|
|
|
static ALWAYS_INLINE void dfc030_put_byte(uaecptr addr, uae_u8 val)
|
|
{
|
|
uae_u32 fc = regs.dfc;
|
|
#if MMUDEBUG > 2
|
|
write_log(_T("dfc030_put_byte: %08X = %02X FC = %i\n"), addr, val, fc);
|
|
#endif
|
|
mmu030_put_byte(addr, val, fc);
|
|
}
|
|
|
|
#define ACCESS_CHECK_PUT \
|
|
if (!mmu030_ad[mmu030_idx].done) { \
|
|
mmu030_ad[mmu030_idx].val = v; \
|
|
} else if (mmu030_ad[mmu030_idx].done) { \
|
|
mmu030_idx++; \
|
|
return; \
|
|
}
|
|
|
|
#define ACCESS_CHECK_GET \
|
|
if (mmu030_ad[mmu030_idx].done) { \
|
|
v = mmu030_ad[mmu030_idx].val; \
|
|
mmu030_idx++; \
|
|
return v; \
|
|
}
|
|
|
|
#define ACCESS_CHECK_GET_PC(pc) \
|
|
if (mmu030_ad[mmu030_idx].done) { \
|
|
v = mmu030_ad[mmu030_idx].val; \
|
|
mmu030_idx++; \
|
|
m68k_incpci (pc); \
|
|
return v; \
|
|
}
|
|
|
|
#define ACCESS_EXIT_PUT \
|
|
mmu030_ad[mmu030_idx].done = true; \
|
|
mmu030_idx++; \
|
|
mmu030_ad[mmu030_idx].done = false;
|
|
|
|
#define ACCESS_EXIT_GET \
|
|
mmu030_ad[mmu030_idx].val = v; \
|
|
mmu030_ad[mmu030_idx].done = true; \
|
|
mmu030_idx++; \
|
|
mmu030_ad[mmu030_idx].done = false;
|
|
|
|
STATIC_INLINE void put_byte_mmu030_state (uaecptr addr, uae_u32 v)
|
|
{
|
|
ACCESS_CHECK_PUT
|
|
uae_mmu030_put_byte (addr, v);
|
|
ACCESS_EXIT_PUT
|
|
}
|
|
STATIC_INLINE void put_lrmw_byte_mmu030_state (uaecptr addr, uae_u32 v)
|
|
{
|
|
ACCESS_CHECK_PUT
|
|
uae_mmu030_put_lrmw (addr, v, sz_byte);
|
|
ACCESS_EXIT_PUT
|
|
}
|
|
STATIC_INLINE void put_word_mmu030_state (uaecptr addr, uae_u32 v)
|
|
{
|
|
ACCESS_CHECK_PUT
|
|
uae_mmu030_put_word (addr, v);
|
|
ACCESS_EXIT_PUT
|
|
}
|
|
STATIC_INLINE void put_lrmw_word_mmu030_state (uaecptr addr, uae_u32 v)
|
|
{
|
|
ACCESS_CHECK_PUT
|
|
uae_mmu030_put_lrmw (addr, v, sz_word);
|
|
ACCESS_EXIT_PUT
|
|
}
|
|
STATIC_INLINE void put_long_mmu030_state (uaecptr addr, uae_u32 v)
|
|
{
|
|
ACCESS_CHECK_PUT
|
|
uae_mmu030_put_long (addr, v);
|
|
ACCESS_EXIT_PUT
|
|
}
|
|
STATIC_INLINE void put_lrmw_long_mmu030_state (uaecptr addr, uae_u32 v)
|
|
{
|
|
ACCESS_CHECK_PUT
|
|
uae_mmu030_put_lrmw (addr, v, sz_long);
|
|
ACCESS_EXIT_PUT
|
|
}
|
|
|
|
STATIC_INLINE uae_u32 get_byte_mmu030_state (uaecptr addr)
|
|
{
|
|
uae_u32 v;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_byte (addr);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 get_lrmw_byte_mmu030_state (uaecptr addr)
|
|
{
|
|
uae_u32 v;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_lrmw (addr, sz_byte);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
|
|
STATIC_INLINE uae_u32 get_word_mmu030_state (uaecptr addr)
|
|
{
|
|
uae_u32 v;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_word (addr);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 get_lrmw_word_mmu030_state (uaecptr addr)
|
|
{
|
|
uae_u32 v;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_lrmw (addr, sz_word);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 get_long_mmu030_state (uaecptr addr)
|
|
{
|
|
uae_u32 v;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_long (addr);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 get_lrmw_long_mmu030_state (uaecptr addr)
|
|
{
|
|
uae_u32 v;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_lrmw (addr, sz_long);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
|
|
STATIC_INLINE uae_u32 get_ibyte_mmu030_state (int o)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 addr = m68k_getpci () + o;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_iword (addr);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 get_iword_mmu030_state (int o)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 addr = m68k_getpci () + o;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_iword (addr);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 get_ilong_mmu030_state (int o)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 addr = m68k_getpci () + o;
|
|
ACCESS_CHECK_GET
|
|
v = uae_mmu030_get_ilong (addr);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 next_iword_mmu030_state (void)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 addr = m68k_getpci ();
|
|
ACCESS_CHECK_GET_PC(2);
|
|
v = uae_mmu030_get_iword (addr);
|
|
m68k_incpci (2);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 next_ilong_mmu030_state (void)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 addr = m68k_getpci ();
|
|
ACCESS_CHECK_GET_PC(4);
|
|
v = uae_mmu030_get_ilong (addr);
|
|
m68k_incpci (4);
|
|
ACCESS_EXIT_GET
|
|
return v;
|
|
}
|
|
|
|
STATIC_INLINE uae_u32 get_byte_mmu030 (uaecptr addr)
|
|
{
|
|
return uae_mmu030_get_byte (addr);
|
|
}
|
|
STATIC_INLINE uae_u32 get_word_mmu030 (uaecptr addr)
|
|
{
|
|
return uae_mmu030_get_word (addr);
|
|
}
|
|
STATIC_INLINE uae_u32 get_long_mmu030 (uaecptr addr)
|
|
{
|
|
return uae_mmu030_get_long (addr);
|
|
}
|
|
STATIC_INLINE void put_byte_mmu030 (uaecptr addr, uae_u32 v)
|
|
{
|
|
uae_mmu030_put_byte (addr, v);
|
|
}
|
|
|
|
STATIC_INLINE void put_word_mmu030 (uaecptr addr, uae_u32 v)
|
|
{
|
|
uae_mmu030_put_word (addr, v);
|
|
}
|
|
STATIC_INLINE void put_long_mmu030 (uaecptr addr, uae_u32 v)
|
|
{
|
|
uae_mmu030_put_long (addr, v);
|
|
}
|
|
|
|
STATIC_INLINE uae_u32 get_ibyte_mmu030 (int o)
|
|
{
|
|
uae_u32 pc = m68k_getpci () + o;
|
|
return uae_mmu030_get_iword (pc);
|
|
}
|
|
STATIC_INLINE uae_u32 get_iword_mmu030 (int o)
|
|
{
|
|
uae_u32 pc = m68k_getpci () + o;
|
|
return uae_mmu030_get_iword (pc);
|
|
}
|
|
STATIC_INLINE uae_u32 get_ilong_mmu030 (int o)
|
|
{
|
|
uae_u32 pc = m68k_getpci () + o;
|
|
return uae_mmu030_get_ilong (pc);
|
|
}
|
|
STATIC_INLINE uae_u32 next_iword_mmu030 (void)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 pc = m68k_getpci ();
|
|
v = uae_mmu030_get_iword (pc);
|
|
m68k_incpci (2);
|
|
return v;
|
|
}
|
|
STATIC_INLINE uae_u32 next_ilong_mmu030 (void)
|
|
{
|
|
uae_u32 v;
|
|
uae_u32 pc = m68k_getpci ();
|
|
v = uae_mmu030_get_ilong (pc);
|
|
m68k_incpci (4);
|
|
return v;
|
|
}
|
|
|
|
extern void m68k_do_rts_mmu030 (void);
|
|
extern void m68k_do_rte_mmu030 (uaecptr a7);
|
|
extern void flush_mmu030 (uaecptr, int);
|
|
extern void m68k_do_bsr_mmu030 (uaecptr oldpc, uae_s32 offset);
|
|
|
|
#endif
|