|
|
1.1.1.2 ! root 1: /* ! 2: * cpummu.h - MMU emulation ! 3: * ! 4: * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) ! 5: * ! 6: * Inspired by UAE MMU patch ! 7: * ! 8: * This file is part of the ARAnyM project which builds a new and powerful ! 9: * TOS/FreeMiNT compatible virtual machine running on almost any hardware. ! 10: * ! 11: * ARAnyM is free software; you can redistribute it and/or modify ! 12: * it under the terms of the GNU General Public License as published by ! 13: * the Free Software Foundation; either version 2 of the License, or ! 14: * (at your option) any later version. ! 15: * ! 16: * ARAnyM is distributed in the hope that it will be useful, ! 17: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 18: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 19: * GNU General Public License for more details. ! 20: * ! 21: * You should have received a copy of the GNU General Public License ! 22: * along with ARAnyM; if not, write to the Free Software ! 23: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 24: */ ! 25: ! 26: #ifndef CPUMMU_H ! 27: #define CPUMMU_H ! 28: ! 29: #include "compat.h" ! 30: ! 31: #ifndef FULLMMU ! 32: #define FULLMMU ! 33: #endif ! 34: ! 35: #define DUNUSED(x) ! 36: #define D ! 37: #if DEBUG ! 38: #define bug write_log ! 39: #else ! 40: #define bug ! 41: #endif ! 42: ! 43: #if 0 ! 44: struct m68k_exception { ! 45: int prb; ! 46: m68k_exception (int exc) : prb (exc) {} ! 47: operator int() { return prb; } ! 48: }; ! 49: #define SAVE_EXCEPTION ! 50: #define RESTORE_EXCEPTION ! 51: #define TRY(var) try ! 52: #define CATCH(var) catch(m68k_exception var) ! 53: #define THROW(n) throw m68k_exception(n) ! 54: #define THROW_AGAIN(var) throw ! 55: ! 56: #else ! 57: /* we are in plain C, just use a stack of long jumps */ ! 58: #include <setjmp.h> ! 59: extern jmp_buf __exbuf; ! 60: extern int __exvalue; ! 61: #define TRY(DUMMY) __exvalue=setjmp(__exbuf); \ ! 62: if (__exvalue==0) { __pushtry(&__exbuf); ! 63: #define CATCH(x) __poptry(); } else { fprintf(stderr,"Gotcha! %d %s in %d\n",__exvalue,__FILE__,__LINE__); __poptry(); ! 64: #define ENDTRY } ! 65: #define THROW(x) if (__is_catched()) {fprintf(stderr,"Longjumping %s in %d\n",__FILE__,__LINE__);longjmp(__exbuf,x);} else fprintf(stderr,"/!\\ cannot Longjumping %s in %d\n",__FILE__,__LINE__) ! 66: #define THROW_AGAIN(var) if (__is_catched()) longjmp(__exbuf,__exvalue); else fprintf(stderr,"/!\\ cannot Longjumping %s in %d\n",__FILE__,__LINE__) ! 67: #define SAVE_EXCEPTION ! 68: #define RESTORE_EXCEPTION ! 69: jmp_buf* __poptry(void); ! 70: void __pushtry(jmp_buf *j); ! 71: int __is_catched(void); ! 72: ! 73: typedef int m68k_exception; ! 74: ! 75: #endif ! 76: ! 77: #define VOLATILE ! 78: #define ALWAYS_INLINE __inline ! 79: ! 80: static __inline void flush_internals (void) { } ! 81: ! 82: //typedef uae_u8 flagtype; ! 83: ! 84: //static m68k_exception except; ! 85: ! 86: struct xttrx { ! 87: uae_u32 log_addr_base : 8; ! 88: uae_u32 log_addr_mask : 8; ! 89: uae_u32 enable : 1; ! 90: uae_u32 s_field : 2; ! 91: uae_u32 : 3; ! 92: uae_u32 usr1 : 1; ! 93: uae_u32 usr0 : 1; ! 94: uae_u32 : 1; ! 95: uae_u32 cmode : 2; ! 96: uae_u32 : 2; ! 97: uae_u32 write : 1; ! 98: uae_u32 : 2; ! 99: }; ! 100: ! 101: struct mmusr_t { ! 102: uae_u32 phys_addr : 20; ! 103: uae_u32 bus_err : 1; ! 104: uae_u32 global : 1; ! 105: uae_u32 usr1 : 1; ! 106: uae_u32 usr0 : 1; ! 107: uae_u32 super : 1; ! 108: uae_u32 cmode : 2; ! 109: uae_u32 modif : 1; ! 110: uae_u32 : 1; ! 111: uae_u32 write : 1; ! 112: uae_u32 ttrhit : 1; ! 113: uae_u32 resident : 1; ! 114: }; ! 115: ! 116: struct log_addr4 { ! 117: uae_u32 rif : 7; ! 118: uae_u32 pif : 7; ! 119: uae_u32 paif : 6; ! 120: uae_u32 poff : 12; ! 121: }; ! 122: ! 123: struct log_addr8 { ! 124: uae_u32 rif : 7; ! 125: uae_u32 pif : 7; ! 126: uae_u32 paif : 5; ! 127: uae_u32 poff : 13; ! 128: }; ! 129: ! 130: #define MMU_TEST_PTEST 1 ! 131: #define MMU_TEST_VERBOSE 2 ! 132: #define MMU_TEST_FORCE_TABLE_SEARCH 4 ! 133: #define MMU_TEST_NO_BUSERR 8 ! 134: ! 135: extern void mmu_dump_tables(void); ! 136: ! 137: #define MMU_TTR_LOGICAL_BASE 0xff000000 ! 138: #define MMU_TTR_LOGICAL_MASK 0x00ff0000 ! 139: #define MMU_TTR_BIT_ENABLED (1 << 15) ! 140: #define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) ! 141: #define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) ! 142: #define MMU_TTR_SFIELD_SHIFT 13 ! 143: #define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) ! 144: #define MMU_TTR_UX_SHIFT 8 ! 145: #define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) ! 146: #define MMU_TTR_CACHE_SHIFT 5 ! 147: #define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) ! 148: ! 149: #define MMU_UDT_MASK 3 ! 150: #define MMU_PDT_MASK 3 ! 151: ! 152: #define MMU_DES_WP 4 ! 153: #define MMU_DES_USED 8 ! 154: ! 155: /* page descriptors only */ ! 156: #define MMU_DES_MODIFIED 16 ! 157: #define MMU_DES_SUPER (1 << 7) ! 158: #define MMU_DES_GLOBAL (1 << 10) ! 159: ! 160: #define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 ! 161: #define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 ! 162: #define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 ! 163: ! 164: #define MMU_PAGE_INDIRECT_MASK 0xfffffffc ! 165: #define MMU_PAGE_ADDR_MASK_8 0xffffe000 ! 166: #define MMU_PAGE_ADDR_MASK_4 0xfffff000 ! 167: #define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) ! 168: #define MMU_PAGE_UR_MASK_4 (1 << 11) ! 169: #define MMU_PAGE_UR_SHIFT 11 ! 170: ! 171: #define MMU_MMUSR_ADDR_MASK 0xfffff000 ! 172: #define MMU_MMUSR_B (1 << 11) ! 173: #define MMU_MMUSR_G (1 << 10) ! 174: #define MMU_MMUSR_U1 (1 << 9) ! 175: #define MMU_MMUSR_U0 (1 << 8) ! 176: #define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) ! 177: #define MMU_MMUSR_S (1 << 7) ! 178: #define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) ! 179: #define MMU_MMUSR_M (1 << 4) ! 180: #define MMU_MMUSR_W (1 << 2) ! 181: #define MMU_MMUSR_T (1 << 1) ! 182: #define MMU_MMUSR_R (1 << 0) ! 183: ! 184: /* special status word (access error stack frame) */ ! 185: #define MMU_SSW_TM 0x0007 ! 186: #define MMU_SSW_TT 0x0018 ! 187: #define MMU_SSW_SIZE 0x0060 ! 188: #define MMU_SSW_SIZE_B 0x0020 ! 189: #define MMU_SSW_SIZE_W 0x0040 ! 190: #define MMU_SSW_SIZE_L 0x0000 ! 191: #define MMU_SSW_RW 0x0100 ! 192: #define MMU_SSW_LK 0x0200 ! 193: #define MMU_SSW_ATC 0x0400 ! 194: #define MMU_SSW_MA 0x0800 ! 195: #define MMU_SSW_CM 0x1000 ! 196: #define MMU_SSW_CT 0x2000 ! 197: #define MMU_SSW_CU 0x4000 ! 198: #define MMU_SSW_CP 0x8000 ! 199: ! 200: #define TTR_I0 4 ! 201: #define TTR_I1 5 ! 202: #define TTR_D0 6 ! 203: #define TTR_D1 7 ! 204: ! 205: #define TTR_NO_MATCH 0 ! 206: #define TTR_NO_WRITE 1 ! 207: #define TTR_OK_MATCH 2 ! 208: ! 209: struct mmu_atc_line { ! 210: uaecptr tag; // tag is 16 or 17 bits S+logical ! 211: unsigned valid : 1; ! 212: unsigned global : 1; ! 213: unsigned modified : 1; ! 214: unsigned write_protect : 1; ! 215: uaecptr phys; // phys base address ! 216: }; ! 217: ! 218: /* ! 219: * 68040 ATC is a 4 way 16 slot associative address translation cache ! 220: * the 68040 has a DATA and an INSTRUCTION ATC. ! 221: * an ATC lookup may result in : a hit, a miss and a modified state. ! 222: * the 68060 can disable ATC allocation ! 223: * we must take care of 8k and 4k page size, index position is relative to page size ! 224: */ ! 225: ! 226: #define ATC_WAYS 4 ! 227: #define ATC_SLOTS 16 ! 228: #define ATC_TYPE 2 ! 229: ! 230: extern bool mmu_is_super; ! 231: extern struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS]; ! 232: ! 233: /* ! 234: * mmu access is a 4 step process: ! 235: * if mmu is not enabled just read physical ! 236: * check transparent region, if transparent, read physical ! 237: * check ATC (address translation cache), read immediatly if HIT ! 238: * read from mmu with the long path (and allocate ATC entry if needed) ! 239: */ ! 240: static ALWAYS_INLINE bool mmu_lookup(uaecptr addr, bool data, bool write, ! 241: struct mmu_atc_line **cl) ! 242: { ! 243: int way,index; ! 244: static int way_miss=0; ! 245: ! 246: addr = ((mmu_is_super?0x80000000:0x00000000)|(addr >> 1)) & (regs.mmu_pagesize_8k?0xFFFE0000:0xFFFF0000); ! 247: if (regs.mmu_pagesize_8k) ! 248: index=(addr & 0x0001E000)>>13; ! 249: else ! 250: index=(addr & 0x0000F000)>>12; ! 251: for (way=0;way<ATC_WAYS;way++) { ! 252: // if we have this ! 253: if ((addr == mmu_atc_array[data][way][index].tag) && (mmu_atc_array[data][way][index].valid)) { ! 254: *cl=&mmu_atc_array[data][way][index]; ! 255: // if first write to this take slow path (but modify this slot) ! 256: if ((!mmu_atc_array[data][way][index].modified & write) || (mmu_atc_array[data][way][index].write_protect & write)) ! 257: return false; ! 258: return true; ! 259: } ! 260: } ! 261: // we select a random way to void ! 262: *cl=&mmu_atc_array[data][way_miss%ATC_WAYS][index]; ! 263: way_miss++; ! 264: return false; ! 265: } ! 266: ! 267: /* ! 268: */ ! 269: static ALWAYS_INLINE bool mmu_user_lookup(uaecptr addr, bool super, bool data, ! 270: bool write, struct mmu_atc_line **cl) ! 271: { ! 272: int way,index; ! 273: static int way_miss=0; ! 274: ! 275: addr = ((super?0x80000000:0x00000000)|(addr >> 1)) & (regs.mmu_pagesize_8k?0xFFFE0000:0xFFFF0000); ! 276: if (regs.mmu_pagesize_8k) ! 277: index=(addr & 0x0001E000)>>13; ! 278: else ! 279: index=(addr & 0x0000F000)>>12; ! 280: for (way=0;way<ATC_WAYS;way++) { ! 281: // if we have this ! 282: if ((addr == mmu_atc_array[data][way][index].tag) && (mmu_atc_array[data][way][index].valid)) { ! 283: *cl=&mmu_atc_array[data][way][index]; ! 284: // if first write to this take slow path (but modify this slot) ! 285: if ((!mmu_atc_array[data][way][index].modified & write) || (mmu_atc_array[data][way][index].write_protect & write)) ! 286: return false; ! 287: return true; ! 288: } ! 289: } ! 290: // we select a random way to void ! 291: *cl=&mmu_atc_array[data][way_miss%ATC_WAYS][index]; ! 292: way_miss++; ! 293: return false; ! 294: } ! 295: ! 296: /* check if an address matches a ttr */ ! 297: static inline int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super) ! 298: { ! 299: if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ ! 300: uae_u8 msb, mask; ! 301: ! 302: msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; ! 303: mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; ! 304: ! 305: if (!(msb & ~mask)) { ! 306: ! 307: if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { ! 308: if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { ! 309: return TTR_NO_MATCH; ! 310: } ! 311: } ! 312: ! 313: return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; ! 314: } ! 315: } ! 316: return TTR_NO_MATCH; ! 317: } ! 318: ! 319: static inline int mmu_match_ttr(uaecptr addr, bool super, bool data) ! 320: { ! 321: int res; ! 322: ! 323: if (data) { ! 324: res = mmu_do_match_ttr(regs.dtt0, addr, super); ! 325: if (res == TTR_NO_MATCH) ! 326: res = mmu_do_match_ttr(regs.dtt1, addr, super); ! 327: } else { ! 328: res = mmu_do_match_ttr(regs.itt0, addr, super); ! 329: if (res == TTR_NO_MATCH) ! 330: res = mmu_do_match_ttr(regs.itt1, addr, super); ! 331: } ! 332: return res; ! 333: } ! 334: ! 335: extern uae_u16 REGPARAM3 mmu_get_word_unaligned(uaecptr addr, bool data) REGPARAM; ! 336: extern uae_u32 REGPARAM3 mmu_get_long_unaligned(uaecptr addr, bool data) REGPARAM; ! 337: ! 338: extern uae_u8 REGPARAM3 mmu_get_byte_slow(uaecptr addr, bool super, bool data, ! 339: int size, struct mmu_atc_line *cl) REGPARAM; ! 340: extern uae_u16 REGPARAM3 mmu_get_word_slow(uaecptr addr, bool super, bool data, ! 341: int size, struct mmu_atc_line *cl) REGPARAM; ! 342: extern uae_u32 REGPARAM3 mmu_get_long_slow(uaecptr addr, bool super, bool data, ! 343: int size, struct mmu_atc_line *cl) REGPARAM; ! 344: ! 345: extern void REGPARAM3 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data) REGPARAM; ! 346: extern void REGPARAM3 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data) REGPARAM; ! 347: ! 348: extern void REGPARAM3 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data, ! 349: int size, struct mmu_atc_line *cl) REGPARAM; ! 350: extern void REGPARAM3 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data, ! 351: int size, struct mmu_atc_line *cl) REGPARAM; ! 352: extern void REGPARAM3 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data, ! 353: int size, struct mmu_atc_line *cl) REGPARAM; ! 354: ! 355: extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); ! 356: ! 357: #define FC_DATA (regs.s ? 5 : 1) ! 358: #define FC_INST (regs.s ? 6 : 2) ! 359: ! 360: extern uaecptr REGPARAM3 mmu_translate(uaecptr addr, bool super, bool data, bool write) REGPARAM; ! 361: ! 362: extern uae_u32 REGPARAM3 sfc_get_long(uaecptr addr) REGPARAM; ! 363: extern uae_u16 REGPARAM3 sfc_get_word(uaecptr addr) REGPARAM; ! 364: extern uae_u8 REGPARAM3 sfc_get_byte(uaecptr addr) REGPARAM; ! 365: extern void REGPARAM3 dfc_put_long(uaecptr addr, uae_u32 val) REGPARAM; ! 366: extern void REGPARAM3 dfc_put_word(uaecptr addr, uae_u16 val) REGPARAM; ! 367: extern void REGPARAM3 dfc_put_byte(uaecptr addr, uae_u8 val) REGPARAM; ! 368: ! 369: ! 370: extern void REGPARAM3 mmu_flush_atc(uaecptr addr, bool super, bool global) REGPARAM; ! 371: extern void REGPARAM3 mmu_flush_atc_all(bool global) REGPARAM; ! 372: extern void REGPARAM3 mmu_op_real(uae_u32 opcode, uae_u16 extra) REGPARAM; ! 373: ! 374: extern void REGPARAM3 mmu_reset(void) REGPARAM; ! 375: extern void REGPARAM3 mmu_set_tc(uae_u16 tc) REGPARAM; ! 376: extern void REGPARAM3 mmu_set_super(bool super) REGPARAM; ! 377: ! 378: // take care of 2 kinds of alignement, bus size and page ! 379: static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size) ! 380: { ! 381: return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000); ! 382: } ! 383: ! 384: static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) ! 385: { ! 386: return cl->phys | (addr & (regs.mmu_pagesize_8k?0x00001fff:0x00000fff)); ! 387: } ! 388: ! 389: static ALWAYS_INLINE void phys_put_long(uaecptr addr, uae_u32 l) ! 390: { ! 391: longput(addr, l); ! 392: } ! 393: static ALWAYS_INLINE void phys_put_word(uaecptr addr, uae_u32 w) ! 394: { ! 395: wordput(addr, w); ! 396: } ! 397: static ALWAYS_INLINE void phys_put_byte(uaecptr addr, uae_u32 b) ! 398: { ! 399: byteput(addr, b); ! 400: } ! 401: static ALWAYS_INLINE uae_u32 phys_get_long(uaecptr addr) ! 402: { ! 403: return longget (addr); ! 404: } ! 405: static ALWAYS_INLINE uae_u32 phys_get_word(uaecptr addr) ! 406: { ! 407: return wordget (addr); ! 408: } ! 409: static ALWAYS_INLINE uae_u32 phys_get_byte(uaecptr addr) ! 410: { ! 411: return byteget (addr); ! 412: } ! 413: ! 414: static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size) ! 415: { ! 416: struct mmu_atc_line *cl; ! 417: ! 418: // addr,super,data ! 419: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data)!=TTR_NO_MATCH)) ! 420: return phys_get_long(addr); ! 421: if (likely(mmu_lookup(addr, data, false, &cl))) ! 422: return phys_get_long(mmu_get_real_address(addr, cl)); ! 423: return mmu_get_long_slow(addr, regs.s != 0, data, size, cl); ! 424: } ! 425: ! 426: static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size) ! 427: { ! 428: struct mmu_atc_line *cl; ! 429: ! 430: // addr,super,data ! 431: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data)!=TTR_NO_MATCH)) ! 432: return phys_get_word(addr); ! 433: if (likely(mmu_lookup(addr, data, false, &cl))) ! 434: return phys_get_word(mmu_get_real_address(addr, cl)); ! 435: return mmu_get_word_slow(addr, regs.s != 0, data, size, cl); ! 436: } ! 437: ! 438: static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size) ! 439: { ! 440: struct mmu_atc_line *cl; ! 441: ! 442: // addr,super,data ! 443: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data)!=TTR_NO_MATCH)) ! 444: return phys_get_byte(addr); ! 445: if (likely(mmu_lookup(addr, data, false, &cl))) ! 446: return phys_get_byte(mmu_get_real_address(addr, cl)); ! 447: return mmu_get_byte_slow(addr, regs.s != 0, data, size, cl); ! 448: } ! 449: ! 450: ! 451: static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int size) ! 452: { ! 453: struct mmu_atc_line *cl; ! 454: ! 455: // addr,super,data ! 456: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data)==TTR_OK_MATCH)) { ! 457: phys_put_long(addr,val); ! 458: return; ! 459: } ! 460: if (likely(mmu_lookup(addr, data, true, &cl))) ! 461: phys_put_long(mmu_get_real_address(addr, cl), val); ! 462: else ! 463: mmu_put_long_slow(addr, val, regs.s != 0, data, size, cl); ! 464: } ! 465: ! 466: static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int size) ! 467: { ! 468: struct mmu_atc_line *cl; ! 469: ! 470: // addr,super,data ! 471: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data)==TTR_OK_MATCH)) { ! 472: phys_put_word(addr,val); ! 473: return; ! 474: } ! 475: if (likely(mmu_lookup(addr, data, true, &cl))) ! 476: phys_put_word(mmu_get_real_address(addr, cl), val); ! 477: else ! 478: mmu_put_word_slow(addr, val, regs.s != 0, data, size, cl); ! 479: } ! 480: ! 481: static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int size) ! 482: { ! 483: struct mmu_atc_line *cl; ! 484: ! 485: // addr,super,data ! 486: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data)==TTR_OK_MATCH)) { ! 487: phys_put_byte(addr,val); ! 488: return; ! 489: } ! 490: if (likely(mmu_lookup(addr, data, true, &cl))) ! 491: phys_put_byte(mmu_get_real_address(addr, cl), val); ! 492: else ! 493: mmu_put_byte_slow(addr, val, regs.s != 0, data, size, cl); ! 494: } ! 495: ! 496: static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, int size) ! 497: { ! 498: struct mmu_atc_line *cl; ! 499: ! 500: // addr,super,data ! 501: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH)) ! 502: return phys_get_long(addr); ! 503: if (likely(mmu_user_lookup(addr, super, data, false, &cl))) ! 504: return phys_get_long(mmu_get_real_address(addr, cl)); ! 505: return mmu_get_long_slow(addr, super, data, size, cl); ! 506: } ! 507: ! 508: static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, int size) ! 509: { ! 510: struct mmu_atc_line *cl; ! 511: ! 512: // addr,super,data ! 513: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH)) ! 514: return phys_get_word(addr); ! 515: if (likely(mmu_user_lookup(addr, super, data, false, &cl))) ! 516: return phys_get_word(mmu_get_real_address(addr, cl)); ! 517: return mmu_get_word_slow(addr, super, data, size, cl); ! 518: } ! 519: ! 520: static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, int size) ! 521: { ! 522: struct mmu_atc_line *cl; ! 523: ! 524: // addr,super,data ! 525: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH)) ! 526: return phys_get_byte(addr); ! 527: if (likely(mmu_user_lookup(addr, super, data, false, &cl))) ! 528: return phys_get_byte(mmu_get_real_address(addr, cl)); ! 529: return mmu_get_byte_slow(addr, super, data, size, cl); ! 530: } ! 531: ! 532: static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, bool data, int size) ! 533: { ! 534: struct mmu_atc_line *cl; ! 535: ! 536: // addr,super,data ! 537: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)==TTR_OK_MATCH)) { ! 538: phys_put_long(addr,val); ! 539: return; ! 540: } ! 541: if (likely(mmu_user_lookup(addr, super, data, true, &cl))) ! 542: phys_put_long(mmu_get_real_address(addr, cl), val); ! 543: else ! 544: mmu_put_long_slow(addr, val, super, data, size, cl); ! 545: } ! 546: ! 547: static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, bool data, int size) ! 548: { ! 549: struct mmu_atc_line *cl; ! 550: ! 551: // addr,super,data ! 552: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)==TTR_OK_MATCH)) { ! 553: phys_put_word(addr,val); ! 554: return; ! 555: } ! 556: if (likely(mmu_user_lookup(addr, super, data, true, &cl))) ! 557: phys_put_word(mmu_get_real_address(addr, cl), val); ! 558: else ! 559: mmu_put_word_slow(addr, val, super, data, size, cl); ! 560: } ! 561: ! 562: static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, bool data, int size) ! 563: { ! 564: struct mmu_atc_line *cl; ! 565: ! 566: // addr,super,data ! 567: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)==TTR_OK_MATCH)) { ! 568: phys_put_byte(addr,val); ! 569: return; ! 570: } ! 571: if (likely(mmu_user_lookup(addr, super, data, true, &cl))) ! 572: phys_put_byte(mmu_get_real_address(addr, cl), val); ! 573: else ! 574: mmu_put_byte_slow(addr, val, super, data, size, cl); ! 575: } ! 576: ! 577: ! 578: static ALWAYS_INLINE void HWput_l(uaecptr addr, uae_u32 l) ! 579: { ! 580: put_long (addr, l); ! 581: } ! 582: static ALWAYS_INLINE void HWput_w(uaecptr addr, uae_u32 w) ! 583: { ! 584: put_word (addr, w); ! 585: } ! 586: static ALWAYS_INLINE void HWput_b(uaecptr addr, uae_u32 b) ! 587: { ! 588: put_byte (addr, b); ! 589: } ! 590: static ALWAYS_INLINE uae_u32 HWget_l(uaecptr addr) ! 591: { ! 592: return get_long (addr); ! 593: } ! 594: static ALWAYS_INLINE uae_u32 HWget_w(uaecptr addr) ! 595: { ! 596: return get_word (addr); ! 597: } ! 598: static ALWAYS_INLINE uae_u32 HWget_b(uaecptr addr) ! 599: { ! 600: return get_byte (addr); ! 601: } ! 602: ! 603: static ALWAYS_INLINE uae_u32 uae_mmu_get_ilong(uaecptr addr) ! 604: { ! 605: if (unlikely(is_unaligned(addr, 4))) ! 606: return mmu_get_long_unaligned(addr, false); ! 607: return mmu_get_long(addr, false, sz_long); ! 608: } ! 609: static ALWAYS_INLINE uae_u16 uae_mmu_get_iword(uaecptr addr) ! 610: { ! 611: if (unlikely(is_unaligned(addr, 2))) ! 612: return mmu_get_word_unaligned(addr, false); ! 613: return mmu_get_word(addr, false, sz_word); ! 614: } ! 615: static ALWAYS_INLINE uae_u16 uae_mmu_get_ibyte(uaecptr addr) ! 616: { ! 617: return mmu_get_byte(addr, false, sz_byte); ! 618: } ! 619: static ALWAYS_INLINE uae_u32 uae_mmu_get_long(uaecptr addr) ! 620: { ! 621: if (unlikely(is_unaligned(addr, 4))) ! 622: return mmu_get_long_unaligned(addr, true); ! 623: return mmu_get_long(addr, true, sz_long); ! 624: } ! 625: static ALWAYS_INLINE uae_u16 uae_mmu_get_word(uaecptr addr) ! 626: { ! 627: if (unlikely(is_unaligned(addr, 2))) ! 628: return mmu_get_word_unaligned(addr, true); ! 629: return mmu_get_word(addr, true, sz_word); ! 630: } ! 631: static ALWAYS_INLINE uae_u8 uae_mmu_get_byte(uaecptr addr) ! 632: { ! 633: return mmu_get_byte(addr, true, sz_byte); ! 634: } ! 635: static ALWAYS_INLINE void uae_mmu_put_long(uaecptr addr, uae_u32 val) ! 636: { ! 637: if (unlikely(is_unaligned(addr, 4))) ! 638: mmu_put_long_unaligned(addr, val, true); ! 639: else ! 640: mmu_put_long(addr, val, true, sz_long); ! 641: } ! 642: static ALWAYS_INLINE void uae_mmu_put_word(uaecptr addr, uae_u16 val) ! 643: { ! 644: if (unlikely(is_unaligned(addr, 2))) ! 645: mmu_put_word_unaligned(addr, val, true); ! 646: else ! 647: mmu_put_word(addr, val, true, sz_word); ! 648: } ! 649: static ALWAYS_INLINE void uae_mmu_put_byte(uaecptr addr, uae_u8 val) ! 650: { ! 651: mmu_put_byte(addr, val, true, sz_byte); ! 652: } ! 653: ! 654: STATIC_INLINE void put_byte_mmu (uaecptr addr, uae_u32 v) ! 655: { ! 656: uae_mmu_put_byte (addr, v); ! 657: } ! 658: STATIC_INLINE void put_word_mmu (uaecptr addr, uae_u32 v) ! 659: { ! 660: uae_mmu_put_word (addr, v); ! 661: } ! 662: STATIC_INLINE void put_long_mmu (uaecptr addr, uae_u32 v) ! 663: { ! 664: uae_mmu_put_long (addr, v); ! 665: } ! 666: STATIC_INLINE uae_u32 get_byte_mmu (uaecptr addr) ! 667: { ! 668: return uae_mmu_get_byte (addr); ! 669: } ! 670: STATIC_INLINE uae_u32 get_word_mmu (uaecptr addr) ! 671: { ! 672: return uae_mmu_get_word (addr); ! 673: } ! 674: STATIC_INLINE uae_u32 get_long_mmu (uaecptr addr) ! 675: { ! 676: return uae_mmu_get_long (addr); ! 677: } ! 678: STATIC_INLINE uae_u32 get_ibyte_mmu (int o) ! 679: { ! 680: uae_u32 pc = m68k_getpc () + o; ! 681: return uae_mmu_get_iword (pc); ! 682: } ! 683: STATIC_INLINE uae_u32 get_iword_mmu (int o) ! 684: { ! 685: uae_u32 pc = m68k_getpc () + o; ! 686: return uae_mmu_get_iword (pc); ! 687: } ! 688: STATIC_INLINE uae_u32 get_ilong_mmu (int o) ! 689: { ! 690: uae_u32 pc = m68k_getpc () + o; ! 691: return uae_mmu_get_ilong (pc); ! 692: } ! 693: STATIC_INLINE uae_u32 next_iword_mmu (void) ! 694: { ! 695: uae_u32 pc = m68k_getpc (); ! 696: m68k_incpci (2); ! 697: return uae_mmu_get_iword (pc); ! 698: } ! 699: STATIC_INLINE uae_u32 next_ilong_mmu (void) ! 700: { ! 701: uae_u32 pc = m68k_getpc (); ! 702: m68k_incpci (4); ! 703: return uae_mmu_get_ilong (pc); ! 704: } ! 705: ! 706: extern void m68k_do_rts_mmu (void); ! 707: extern void m68k_do_rte_mmu (uaecptr a7); ! 708: extern void m68k_do_bsr_mmu (uaecptr oldpc, uae_s32 offset); ! 709: ! 710: struct mmufixup ! 711: { ! 712: int reg; ! 713: uae_u32 value; ! 714: }; ! 715: extern struct mmufixup mmufixup[2]; ! 716: ! 717: #endif /* CPUMMU_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.