|
|
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:
1.1.1.4 ! root 26:
1.1.1.2 root 27: #ifndef CPUMMU_H
28: #define CPUMMU_H
29:
1.1.1.3 root 30: #include "mmu_common.h"
1.1.1.2 root 31:
32: #ifndef FULLMMU
33: #define FULLMMU
34: #endif
35:
36: #define DUNUSED(x)
37: #define D
38: #if DEBUG
39: #define bug write_log
40: #else
41: #define bug
42: #endif
43:
44: static __inline void flush_internals (void) { }
45:
1.1.1.4 ! root 46: extern int mmu060_state;
! 47:
! 48: extern int mmu040_movem;
! 49: extern uaecptr mmu040_movem_ea;
! 50: extern uae_u32 mmu040_move16[4];
! 51:
! 52: extern bool mmu_pagesize_8k;
! 53: extern uae_u16 mmu_opcode;
! 54: extern bool mmu_restart;
! 55: extern bool mmu_ttr_enabled;
! 56:
1.1.1.2 root 57: //typedef uae_u8 flagtype;
58:
59: //static m68k_exception except;
60:
61: struct xttrx {
62: uae_u32 log_addr_base : 8;
63: uae_u32 log_addr_mask : 8;
64: uae_u32 enable : 1;
65: uae_u32 s_field : 2;
66: uae_u32 : 3;
67: uae_u32 usr1 : 1;
68: uae_u32 usr0 : 1;
69: uae_u32 : 1;
70: uae_u32 cmode : 2;
71: uae_u32 : 2;
72: uae_u32 write : 1;
73: uae_u32 : 2;
74: };
75:
76: struct mmusr_t {
77: uae_u32 phys_addr : 20;
78: uae_u32 bus_err : 1;
79: uae_u32 global : 1;
80: uae_u32 usr1 : 1;
81: uae_u32 usr0 : 1;
82: uae_u32 super : 1;
83: uae_u32 cmode : 2;
84: uae_u32 modif : 1;
85: uae_u32 : 1;
86: uae_u32 write : 1;
87: uae_u32 ttrhit : 1;
88: uae_u32 resident : 1;
89: };
90:
91: struct log_addr4 {
92: uae_u32 rif : 7;
93: uae_u32 pif : 7;
94: uae_u32 paif : 6;
95: uae_u32 poff : 12;
96: };
97:
98: struct log_addr8 {
99: uae_u32 rif : 7;
100: uae_u32 pif : 7;
101: uae_u32 paif : 5;
102: uae_u32 poff : 13;
103: };
104:
105: #define MMU_TEST_PTEST 1
106: #define MMU_TEST_VERBOSE 2
107: #define MMU_TEST_FORCE_TABLE_SEARCH 4
108: #define MMU_TEST_NO_BUSERR 8
109:
110: extern void mmu_dump_tables(void);
111:
112: #define MMU_TTR_LOGICAL_BASE 0xff000000
113: #define MMU_TTR_LOGICAL_MASK 0x00ff0000
114: #define MMU_TTR_BIT_ENABLED (1 << 15)
115: #define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14)
116: #define MMU_TTR_BIT_SFIELD_SUPER (1 << 13)
117: #define MMU_TTR_SFIELD_SHIFT 13
118: #define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8))
119: #define MMU_TTR_UX_SHIFT 8
120: #define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5))
121: #define MMU_TTR_CACHE_SHIFT 5
122: #define MMU_TTR_BIT_WRITE_PROTECT (1 << 2)
123:
124: #define MMU_UDT_MASK 3
125: #define MMU_PDT_MASK 3
126:
127: #define MMU_DES_WP 4
128: #define MMU_DES_USED 8
129:
130: /* page descriptors only */
131: #define MMU_DES_MODIFIED 16
132: #define MMU_DES_SUPER (1 << 7)
133: #define MMU_DES_GLOBAL (1 << 10)
134:
135: #define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00
136: #define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80
137: #define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00
138:
139: #define MMU_PAGE_INDIRECT_MASK 0xfffffffc
140: #define MMU_PAGE_ADDR_MASK_8 0xffffe000
141: #define MMU_PAGE_ADDR_MASK_4 0xfffff000
142: #define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11))
143: #define MMU_PAGE_UR_MASK_4 (1 << 11)
144: #define MMU_PAGE_UR_SHIFT 11
145:
146: #define MMU_MMUSR_ADDR_MASK 0xfffff000
147: #define MMU_MMUSR_B (1 << 11)
148: #define MMU_MMUSR_G (1 << 10)
149: #define MMU_MMUSR_U1 (1 << 9)
150: #define MMU_MMUSR_U0 (1 << 8)
151: #define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0)
152: #define MMU_MMUSR_S (1 << 7)
153: #define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5))
154: #define MMU_MMUSR_M (1 << 4)
155: #define MMU_MMUSR_W (1 << 2)
156: #define MMU_MMUSR_T (1 << 1)
157: #define MMU_MMUSR_R (1 << 0)
158:
159: #define TTR_I0 4
160: #define TTR_I1 5
161: #define TTR_D0 6
162: #define TTR_D1 7
163:
164: #define TTR_NO_MATCH 0
165: #define TTR_NO_WRITE 1
166: #define TTR_OK_MATCH 2
167:
168: struct mmu_atc_line {
169: uaecptr tag; // tag is 16 or 17 bits S+logical
170: unsigned valid : 1;
171: unsigned global : 1;
172: unsigned modified : 1;
173: unsigned write_protect : 1;
174: uaecptr phys; // phys base address
175: };
176:
177: /*
178: * 68040 ATC is a 4 way 16 slot associative address translation cache
179: * the 68040 has a DATA and an INSTRUCTION ATC.
180: * an ATC lookup may result in : a hit, a miss and a modified state.
181: * the 68060 can disable ATC allocation
182: * we must take care of 8k and 4k page size, index position is relative to page size
183: */
184:
185: #define ATC_WAYS 4
186: #define ATC_SLOTS 16
187: #define ATC_TYPE 2
188:
1.1.1.4 ! root 189: extern uae_u32 mmu_is_super;
! 190: extern uae_u32 mmu_tagmask, mmu_pagemask;
1.1.1.2 root 191: extern struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS];
192:
1.1.1.4 ! root 193: /* Last matched ATC index, next lookup starts from this index as an optimization */
! 194: extern int mmu_atc_ways;
! 195:
1.1.1.2 root 196: /*
197: * mmu access is a 4 step process:
198: * if mmu is not enabled just read physical
199: * check transparent region, if transparent, read physical
200: * check ATC (address translation cache), read immediatly if HIT
201: * read from mmu with the long path (and allocate ATC entry if needed)
202: */
203: static ALWAYS_INLINE bool mmu_lookup(uaecptr addr, bool data, bool write,
204: struct mmu_atc_line **cl)
205: {
1.1.1.4 ! root 206: int way, i, index;
1.1.1.2 root 207: static int way_miss=0;
208:
1.1.1.4 ! root 209: uae_u32 tag = (mmu_is_super | (addr >> 1)) & mmu_tagmask;
! 210: if (mmu_pagesize_8k)
1.1.1.2 root 211: index=(addr & 0x0001E000)>>13;
212: else
213: index=(addr & 0x0000F000)>>12;
1.1.1.4 ! root 214: for (i = 0; i < ATC_WAYS; i++) {
! 215: way = mmu_atc_ways;
1.1.1.2 root 216: // if we have this
1.1.1.4 ! root 217: if ((tag == mmu_atc_array[data][way][index].tag) && (mmu_atc_array[data][way][index].valid)) {
1.1.1.2 root 218: *cl=&mmu_atc_array[data][way][index];
219: // if first write to this take slow path (but modify this slot)
220: if ((!mmu_atc_array[data][way][index].modified & write) || (mmu_atc_array[data][way][index].write_protect & write))
221: return false;
222: return true;
223: }
1.1.1.4 ! root 224: mmu_atc_ways++;
! 225: mmu_atc_ways %= ATC_WAYS;
1.1.1.2 root 226: }
227: // we select a random way to void
228: *cl=&mmu_atc_array[data][way_miss%ATC_WAYS][index];
1.1.1.4 ! root 229: (*cl)->tag = tag;
1.1.1.2 root 230: way_miss++;
231: return false;
232: }
233:
234: /*
235: */
236: static ALWAYS_INLINE bool mmu_user_lookup(uaecptr addr, bool super, bool data,
237: bool write, struct mmu_atc_line **cl)
238: {
1.1.1.4 ! root 239: int way, i, index;
1.1.1.2 root 240: static int way_miss=0;
241:
1.1.1.4 ! root 242: uae_u32 tag = ((super ? 0x80000000 : 0x00000000) | (addr >> 1)) & mmu_tagmask;
! 243: if (mmu_pagesize_8k)
1.1.1.2 root 244: index=(addr & 0x0001E000)>>13;
245: else
246: index=(addr & 0x0000F000)>>12;
1.1.1.4 ! root 247: for (i = 0; i < ATC_WAYS; i++) {
! 248: way = mmu_atc_ways;
1.1.1.2 root 249: // if we have this
1.1.1.4 ! root 250: if ((tag == mmu_atc_array[data][way][index].tag) && (mmu_atc_array[data][way][index].valid)) {
1.1.1.2 root 251: *cl=&mmu_atc_array[data][way][index];
252: // if first write to this take slow path (but modify this slot)
253: if ((!mmu_atc_array[data][way][index].modified & write) || (mmu_atc_array[data][way][index].write_protect & write))
254: return false;
255: return true;
256: }
1.1.1.4 ! root 257: mmu_atc_ways++;
! 258: mmu_atc_ways %= ATC_WAYS;
1.1.1.2 root 259: }
260: // we select a random way to void
261: *cl=&mmu_atc_array[data][way_miss%ATC_WAYS][index];
1.1.1.4 ! root 262: (*cl)->tag = tag;
1.1.1.2 root 263: way_miss++;
264: return false;
265: }
266:
267: /* check if an address matches a ttr */
1.1.1.4 ! root 268: STATIC_INLINE int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super)
1.1.1.2 root 269: {
270: if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */
271: uae_u8 msb, mask;
272:
273: msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24;
274: mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16;
275:
276: if (!(msb & ~mask)) {
277:
278: if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) {
279: if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) {
280: return TTR_NO_MATCH;
281: }
282: }
283:
284: return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH;
285: }
286: }
287: return TTR_NO_MATCH;
288: }
289:
1.1.1.4 ! root 290: STATIC_INLINE int mmu_match_ttr(uaecptr addr, bool super, bool data, bool rmw)
1.1.1.2 root 291: {
292: int res;
293:
1.1.1.4 ! root 294: if (!mmu_ttr_enabled)
! 295: return TTR_NO_MATCH;
1.1.1.2 root 296: if (data) {
297: res = mmu_do_match_ttr(regs.dtt0, addr, super);
298: if (res == TTR_NO_MATCH)
299: res = mmu_do_match_ttr(regs.dtt1, addr, super);
300: } else {
301: res = mmu_do_match_ttr(regs.itt0, addr, super);
302: if (res == TTR_NO_MATCH)
303: res = mmu_do_match_ttr(regs.itt1, addr, super);
304: }
305: return res;
306: }
1.1.1.4 ! root 307: extern void mmu_bus_error_ttr_write_fault(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw);
! 308: STATIC_INLINE int mmu_match_ttr_write(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw)
! 309: {
! 310: if (!mmu_ttr_enabled)
! 311: return TTR_NO_MATCH;
! 312: int res = mmu_match_ttr(addr, super, data, rmw);
! 313: if (res == TTR_NO_WRITE)
! 314: mmu_bus_error_ttr_write_fault(addr, super, data, val, size, rmw);
! 315: return res;
! 316: }
! 317:
! 318: extern void mmu_tt_modified (void);
1.1.1.2 root 319:
1.1.1.4 ! root 320: extern uae_u32 REGPARAM3 mmu060_get_rmw_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM;
! 321: extern void REGPARAM3 mmu060_put_rmw_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM;
! 322:
! 323: extern uae_u16 REGPARAM3 mmu_get_word_unaligned(uaecptr addr, bool data, bool rmw) REGPARAM;
! 324: extern uae_u32 REGPARAM3 mmu_get_long_unaligned(uaecptr addr, bool data, bool rmw) REGPARAM;
1.1.1.2 root 325:
326: extern uae_u8 REGPARAM3 mmu_get_byte_slow(uaecptr addr, bool super, bool data,
1.1.1.4 ! root 327: int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
1.1.1.2 root 328: extern uae_u16 REGPARAM3 mmu_get_word_slow(uaecptr addr, bool super, bool data,
1.1.1.4 ! root 329: int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
1.1.1.2 root 330: extern uae_u32 REGPARAM3 mmu_get_long_slow(uaecptr addr, bool super, bool data,
1.1.1.4 ! root 331: int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
1.1.1.2 root 332:
1.1.1.4 ! root 333: extern void REGPARAM3 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data, bool rmw) REGPARAM;
! 334: extern void REGPARAM3 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data, bool rmw) REGPARAM;
1.1.1.2 root 335:
336: extern void REGPARAM3 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data,
1.1.1.4 ! root 337: int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
1.1.1.2 root 338: extern void REGPARAM3 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data,
1.1.1.4 ! root 339: int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
1.1.1.2 root 340: extern void REGPARAM3 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data,
1.1.1.4 ! root 341: int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
1.1.1.2 root 342:
343: extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode);
344:
345: #define FC_DATA (regs.s ? 5 : 1)
346: #define FC_INST (regs.s ? 6 : 2)
347:
348: extern uaecptr REGPARAM3 mmu_translate(uaecptr addr, bool super, bool data, bool write) REGPARAM;
1.1.1.4 ! root 349: extern void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 status, bool nonmmu);
1.1.1.2 root 350:
351: extern uae_u32 REGPARAM3 sfc_get_long(uaecptr addr) REGPARAM;
352: extern uae_u16 REGPARAM3 sfc_get_word(uaecptr addr) REGPARAM;
353: extern uae_u8 REGPARAM3 sfc_get_byte(uaecptr addr) REGPARAM;
354: extern void REGPARAM3 dfc_put_long(uaecptr addr, uae_u32 val) REGPARAM;
355: extern void REGPARAM3 dfc_put_word(uaecptr addr, uae_u16 val) REGPARAM;
356: extern void REGPARAM3 dfc_put_byte(uaecptr addr, uae_u8 val) REGPARAM;
357:
1.1.1.4 ! root 358: #define sfc040_get_long sfc_get_long
! 359: #define sfc040_get_word sfc_get_word
! 360: #define sfc040_get_byte sfc_get_byte
! 361: #define dfc040_put_long dfc_put_long
! 362: #define dfc040_put_word dfc_put_word
! 363: #define dfc040_put_byte dfc_put_byte
! 364:
! 365: #define sfc060_get_long sfc_get_long
! 366: #define sfc060_get_word sfc_get_word
! 367: #define sfc060_get_byte sfc_get_byte
! 368: #define dfc060_put_long dfc_put_long
! 369: #define dfc060_put_word dfc_put_word
! 370: #define dfc060_put_byte dfc_put_byte
! 371:
! 372: extern void uae_mmu_put_lrmw (uaecptr addr, uae_u32 v, int size, int type);
! 373: extern uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type);
1.1.1.2 root 374:
375: extern void REGPARAM3 mmu_flush_atc(uaecptr addr, bool super, bool global) REGPARAM;
376: extern void REGPARAM3 mmu_flush_atc_all(bool global) REGPARAM;
377: extern void REGPARAM3 mmu_op_real(uae_u32 opcode, uae_u16 extra) REGPARAM;
378:
379: extern void REGPARAM3 mmu_reset(void) REGPARAM;
380: extern void REGPARAM3 mmu_set_tc(uae_u16 tc) REGPARAM;
381: extern void REGPARAM3 mmu_set_super(bool super) REGPARAM;
382:
383: static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl)
384: {
1.1.1.4 ! root 385: return cl->phys | (addr & mmu_pagemask);
1.1.1.2 root 386: }
387:
1.1.1.4 ! root 388: extern void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size);
! 389: extern void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size);
! 390:
! 391: static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size, bool rmw)
1.1.1.2 root 392: {
393: struct mmu_atc_line *cl;
394:
395: // addr,super,data
1.1.1.4 ! root 396: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH))
1.1.1.2 root 397: return phys_get_long(addr);
398: if (likely(mmu_lookup(addr, data, false, &cl)))
399: return phys_get_long(mmu_get_real_address(addr, cl));
1.1.1.4 ! root 400: return mmu_get_long_slow(addr, regs.s != 0, data, size, rmw, cl);
1.1.1.2 root 401: }
402:
1.1.1.4 ! root 403: static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size, bool rmw)
1.1.1.2 root 404: {
405: struct mmu_atc_line *cl;
406:
407: // addr,super,data
1.1.1.4 ! root 408: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH))
1.1.1.2 root 409: return phys_get_word(addr);
410: if (likely(mmu_lookup(addr, data, false, &cl)))
411: return phys_get_word(mmu_get_real_address(addr, cl));
1.1.1.4 ! root 412: return mmu_get_word_slow(addr, regs.s != 0, data, size, rmw, cl);
1.1.1.2 root 413: }
414:
1.1.1.4 ! root 415: static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size, bool rmw)
1.1.1.2 root 416: {
417: struct mmu_atc_line *cl;
418:
419: // addr,super,data
1.1.1.4 ! root 420: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH))
1.1.1.2 root 421: return phys_get_byte(addr);
422: if (likely(mmu_lookup(addr, data, false, &cl)))
423: return phys_get_byte(mmu_get_real_address(addr, cl));
1.1.1.4 ! root 424: return mmu_get_byte_slow(addr, regs.s != 0, data, size, rmw, cl);
1.1.1.2 root 425: }
426:
1.1.1.4 ! root 427: static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int size, bool rmw)
1.1.1.2 root 428: {
429: struct mmu_atc_line *cl;
430:
431: // addr,super,data
1.1.1.4 ! root 432: if ((!regs.mmu_enabled) || mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH) {
1.1.1.2 root 433: phys_put_long(addr,val);
434: return;
435: }
436: if (likely(mmu_lookup(addr, data, true, &cl)))
437: phys_put_long(mmu_get_real_address(addr, cl), val);
438: else
1.1.1.4 ! root 439: mmu_put_long_slow(addr, val, regs.s != 0, data, size, rmw, cl);
1.1.1.2 root 440: }
441:
1.1.1.4 ! root 442: static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int size, bool rmw)
1.1.1.2 root 443: {
444: struct mmu_atc_line *cl;
445:
446: // addr,super,data
1.1.1.4 ! root 447: if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH)) {
1.1.1.2 root 448: phys_put_word(addr,val);
449: return;
450: }
451: if (likely(mmu_lookup(addr, data, true, &cl)))
452: phys_put_word(mmu_get_real_address(addr, cl), val);
453: else
1.1.1.4 ! root 454: mmu_put_word_slow(addr, val, regs.s != 0, data, size, rmw, cl);
1.1.1.2 root 455: }
456:
1.1.1.4 ! root 457: static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int size, bool rmw)
1.1.1.2 root 458: {
459: struct mmu_atc_line *cl;
460:
461: // addr,super,data
1.1.1.4 ! root 462: if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH)) {
1.1.1.2 root 463: phys_put_byte(addr,val);
464: return;
465: }
466: if (likely(mmu_lookup(addr, data, true, &cl)))
467: phys_put_byte(mmu_get_real_address(addr, cl), val);
468: else
1.1.1.4 ! root 469: mmu_put_byte_slow(addr, val, regs.s != 0, data, size, rmw, cl);
1.1.1.2 root 470: }
471:
1.1.1.4 ! root 472: static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, bool write, int size)
1.1.1.2 root 473: {
474: struct mmu_atc_line *cl;
475:
476: // addr,super,data
1.1.1.4 ! root 477: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH))
1.1.1.2 root 478: return phys_get_long(addr);
1.1.1.4 ! root 479: if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
1.1.1.2 root 480: return phys_get_long(mmu_get_real_address(addr, cl));
1.1.1.4 ! root 481: return mmu_get_long_slow(addr, super, data, size, false, cl);
1.1.1.2 root 482: }
483:
1.1.1.4 ! root 484: static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, bool write, int size)
1.1.1.2 root 485: {
486: struct mmu_atc_line *cl;
487:
488: // addr,super,data
1.1.1.4 ! root 489: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH))
1.1.1.2 root 490: return phys_get_word(addr);
1.1.1.4 ! root 491: if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
1.1.1.2 root 492: return phys_get_word(mmu_get_real_address(addr, cl));
1.1.1.4 ! root 493: return mmu_get_word_slow(addr, super, data, size, false, cl);
1.1.1.2 root 494: }
495:
1.1.1.4 ! root 496: static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, bool write, int size)
1.1.1.2 root 497: {
498: struct mmu_atc_line *cl;
499:
500: // addr,super,data
1.1.1.4 ! root 501: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH))
1.1.1.2 root 502: return phys_get_byte(addr);
1.1.1.4 ! root 503: if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
1.1.1.2 root 504: return phys_get_byte(mmu_get_real_address(addr, cl));
1.1.1.4 ! root 505: return mmu_get_byte_slow(addr, super, data, size, false, cl);
1.1.1.2 root 506: }
507:
508: static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, bool data, int size)
509: {
510: struct mmu_atc_line *cl;
511:
512: // addr,super,data
1.1.1.4 ! root 513: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) {
1.1.1.2 root 514: phys_put_long(addr,val);
515: return;
516: }
517: if (likely(mmu_user_lookup(addr, super, data, true, &cl)))
518: phys_put_long(mmu_get_real_address(addr, cl), val);
519: else
1.1.1.4 ! root 520: mmu_put_long_slow(addr, val, super, data, size, false, cl);
1.1.1.2 root 521: }
522:
523: static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, bool data, int size)
524: {
525: struct mmu_atc_line *cl;
526:
527: // addr,super,data
1.1.1.4 ! root 528: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) {
1.1.1.2 root 529: phys_put_word(addr,val);
530: return;
531: }
532: if (likely(mmu_user_lookup(addr, super, data, true, &cl)))
533: phys_put_word(mmu_get_real_address(addr, cl), val);
534: else
1.1.1.4 ! root 535: mmu_put_word_slow(addr, val, super, data, size, false, cl);
1.1.1.2 root 536: }
537:
538: static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, bool data, int size)
539: {
540: struct mmu_atc_line *cl;
541:
542: // addr,super,data
1.1.1.4 ! root 543: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) {
1.1.1.2 root 544: phys_put_byte(addr,val);
545: return;
546: }
547: if (likely(mmu_user_lookup(addr, super, data, true, &cl)))
548: phys_put_byte(mmu_get_real_address(addr, cl), val);
549: else
1.1.1.4 ! root 550: mmu_put_byte_slow(addr, val, super, data, size, false, cl);
1.1.1.2 root 551: }
552:
553:
554: static ALWAYS_INLINE void HWput_l(uaecptr addr, uae_u32 l)
555: {
556: put_long (addr, l);
557: }
558: static ALWAYS_INLINE void HWput_w(uaecptr addr, uae_u32 w)
559: {
560: put_word (addr, w);
561: }
562: static ALWAYS_INLINE void HWput_b(uaecptr addr, uae_u32 b)
563: {
564: put_byte (addr, b);
565: }
566: static ALWAYS_INLINE uae_u32 HWget_l(uaecptr addr)
567: {
568: return get_long (addr);
569: }
570: static ALWAYS_INLINE uae_u32 HWget_w(uaecptr addr)
571: {
572: return get_word (addr);
573: }
574: static ALWAYS_INLINE uae_u32 HWget_b(uaecptr addr)
575: {
576: return get_byte (addr);
577: }
578:
1.1.1.4 ! root 579: static ALWAYS_INLINE uae_u32 uae_mmu040_get_ilong(uaecptr addr)
! 580: {
! 581: if (unlikely(is_unaligned(addr, 4)))
! 582: return mmu_get_long_unaligned(addr, false, false);
! 583: return mmu_get_long(addr, false, sz_long, false);
! 584: }
! 585: static ALWAYS_INLINE uae_u16 uae_mmu040_get_iword(uaecptr addr)
! 586: {
! 587: if (unlikely(is_unaligned(addr, 2)))
! 588: return mmu_get_word_unaligned(addr, false, false);
! 589: return mmu_get_word(addr, false, sz_word, false);
! 590: }
! 591: static ALWAYS_INLINE uae_u16 uae_mmu040_get_ibyte(uaecptr addr)
! 592: {
! 593: return mmu_get_byte(addr, false, sz_byte, false);
! 594: }
! 595: static ALWAYS_INLINE uae_u32 uae_mmu040_get_long(uaecptr addr)
! 596: {
! 597: if (unlikely(is_unaligned(addr, 4)))
! 598: return mmu_get_long_unaligned(addr, true, false);
! 599: return mmu_get_long(addr, true, sz_long, false);
! 600: }
! 601: static ALWAYS_INLINE uae_u16 uae_mmu040_get_word(uaecptr addr)
! 602: {
! 603: if (unlikely(is_unaligned(addr, 2)))
! 604: return mmu_get_word_unaligned(addr, true, false);
! 605: return mmu_get_word(addr, true, sz_word, false);
! 606: }
! 607: static ALWAYS_INLINE uae_u8 uae_mmu040_get_byte(uaecptr addr)
! 608: {
! 609: return mmu_get_byte(addr, true, sz_byte, false);
! 610: }
! 611:
! 612: static ALWAYS_INLINE void uae_mmu040_put_word(uaecptr addr, uae_u16 val)
! 613: {
! 614: if (unlikely(is_unaligned(addr, 2)))
! 615: mmu_put_word_unaligned(addr, val, true, false);
! 616: else
! 617: mmu_put_word(addr, val, true, sz_word, false);
! 618: }
! 619: static ALWAYS_INLINE void uae_mmu040_put_byte(uaecptr addr, uae_u8 val)
! 620: {
! 621: mmu_put_byte(addr, val, true, sz_byte, false);
! 622: }
! 623: static ALWAYS_INLINE void uae_mmu040_put_long(uaecptr addr, uae_u32 val)
! 624: {
! 625: if (unlikely(is_unaligned(addr, 4)))
! 626: mmu_put_long_unaligned(addr, val, true, false);
! 627: else
! 628: mmu_put_long(addr, val, true, sz_long, false);
! 629: }
! 630:
! 631:
! 632: static ALWAYS_INLINE uae_u32 uae_mmu060_get_ilong(uaecptr addr)
1.1.1.2 root 633: {
634: if (unlikely(is_unaligned(addr, 4)))
1.1.1.4 ! root 635: return mmu_get_long_unaligned(addr, false, false);
! 636: return mmu_get_long(addr, false, sz_long, false);
1.1.1.2 root 637: }
1.1.1.4 ! root 638: static ALWAYS_INLINE uae_u16 uae_mmu060_get_iword(uaecptr addr)
1.1.1.2 root 639: {
640: if (unlikely(is_unaligned(addr, 2)))
1.1.1.4 ! root 641: return mmu_get_word_unaligned(addr, false, false);
! 642: return mmu_get_word(addr, false, sz_word, false);
1.1.1.2 root 643: }
1.1.1.4 ! root 644: static ALWAYS_INLINE uae_u16 uae_mmu060_get_ibyte(uaecptr addr)
1.1.1.2 root 645: {
1.1.1.4 ! root 646: return mmu_get_byte(addr, false, sz_byte, false);
1.1.1.2 root 647: }
1.1.1.4 ! root 648: static ALWAYS_INLINE uae_u32 uae_mmu060_get_long(uaecptr addr, bool rmw)
1.1.1.2 root 649: {
650: if (unlikely(is_unaligned(addr, 4)))
1.1.1.4 ! root 651: return mmu_get_long_unaligned(addr, true, rmw);
! 652: return mmu_get_long(addr, true, sz_long, rmw);
1.1.1.2 root 653: }
1.1.1.4 ! root 654: static ALWAYS_INLINE uae_u16 uae_mmu060_get_word(uaecptr addr, bool rmw)
1.1.1.2 root 655: {
656: if (unlikely(is_unaligned(addr, 2)))
1.1.1.4 ! root 657: return mmu_get_word_unaligned(addr, true, rmw);
! 658: return mmu_get_word(addr, true, sz_word, rmw);
1.1.1.2 root 659: }
1.1.1.4 ! root 660: static ALWAYS_INLINE uae_u8 uae_mmu060_get_byte(uaecptr addr, bool rmw)
1.1.1.2 root 661: {
1.1.1.4 ! root 662: return mmu_get_byte(addr, true, sz_byte, rmw);
1.1.1.2 root 663: }
1.1.1.4 ! root 664: static ALWAYS_INLINE void uae_mmu_get_move16(uaecptr addr, uae_u32 *val)
! 665: {
! 666: // move16 is always aligned
! 667: mmu_get_move16(addr, val, true, 16);
! 668: }
! 669:
! 670: static ALWAYS_INLINE void uae_mmu060_put_long(uaecptr addr, uae_u32 val, bool rmw)
1.1.1.2 root 671: {
672: if (unlikely(is_unaligned(addr, 4)))
1.1.1.4 ! root 673: mmu_put_long_unaligned(addr, val, true, rmw);
1.1.1.2 root 674: else
1.1.1.4 ! root 675: mmu_put_long(addr, val, true, sz_long, rmw);
1.1.1.2 root 676: }
1.1.1.4 ! root 677: static ALWAYS_INLINE void uae_mmu060_put_word(uaecptr addr, uae_u16 val, bool rmw)
1.1.1.2 root 678: {
679: if (unlikely(is_unaligned(addr, 2)))
1.1.1.4 ! root 680: mmu_put_word_unaligned(addr, val, true, rmw);
1.1.1.2 root 681: else
1.1.1.4 ! root 682: mmu_put_word(addr, val, true, sz_word, rmw);
! 683: }
! 684: static ALWAYS_INLINE void uae_mmu060_put_byte(uaecptr addr, uae_u8 val, bool rmw)
! 685: {
! 686: mmu_put_byte(addr, val, true, sz_byte, rmw);
1.1.1.2 root 687: }
1.1.1.4 ! root 688: static ALWAYS_INLINE void uae_mmu_put_move16(uaecptr addr, uae_u32 *val)
1.1.1.2 root 689: {
1.1.1.4 ! root 690: // move16 is always aligned
! 691: mmu_put_move16(addr, val, true, 16);
1.1.1.2 root 692: }
693:
1.1.1.4 ! root 694: // normal 040
! 695: STATIC_INLINE void put_byte_mmu040 (uaecptr addr, uae_u32 v)
! 696: {
! 697: uae_mmu040_put_byte (addr, v);
! 698: }
! 699: STATIC_INLINE void put_word_mmu040 (uaecptr addr, uae_u32 v)
! 700: {
! 701: uae_mmu040_put_word (addr, v);
! 702: }
! 703: STATIC_INLINE void put_long_mmu040 (uaecptr addr, uae_u32 v)
! 704: {
! 705: uae_mmu040_put_long (addr, v);
! 706: }
! 707: STATIC_INLINE uae_u32 get_byte_mmu040 (uaecptr addr)
1.1.1.2 root 708: {
1.1.1.4 ! root 709: return uae_mmu040_get_byte (addr);
1.1.1.2 root 710: }
1.1.1.4 ! root 711: STATIC_INLINE uae_u32 get_word_mmu040 (uaecptr addr)
1.1.1.2 root 712: {
1.1.1.4 ! root 713: return uae_mmu040_get_word (addr);
1.1.1.2 root 714: }
1.1.1.4 ! root 715: STATIC_INLINE uae_u32 get_long_mmu040 (uaecptr addr)
1.1.1.2 root 716: {
1.1.1.4 ! root 717: return uae_mmu040_get_long (addr);
1.1.1.2 root 718: }
1.1.1.4 ! root 719: // normal 060
! 720: STATIC_INLINE void put_byte_mmu060 (uaecptr addr, uae_u32 v)
1.1.1.2 root 721: {
1.1.1.4 ! root 722: uae_mmu060_put_byte (addr, v, false);
1.1.1.2 root 723: }
1.1.1.4 ! root 724: STATIC_INLINE void put_word_mmu060 (uaecptr addr, uae_u32 v)
1.1.1.2 root 725: {
1.1.1.4 ! root 726: uae_mmu060_put_word (addr, v, false);
1.1.1.2 root 727: }
1.1.1.4 ! root 728: STATIC_INLINE void put_long_mmu060 (uaecptr addr, uae_u32 v)
1.1.1.2 root 729: {
1.1.1.4 ! root 730: uae_mmu060_put_long (addr, v, false);
1.1.1.2 root 731: }
1.1.1.4 ! root 732: STATIC_INLINE uae_u32 get_byte_mmu060 (uaecptr addr)
! 733: {
! 734: return uae_mmu060_get_byte (addr, false);
! 735: }
! 736: STATIC_INLINE uae_u32 get_word_mmu060 (uaecptr addr)
! 737: {
! 738: return uae_mmu060_get_word (addr, false);
! 739: }
! 740: STATIC_INLINE uae_u32 get_long_mmu060 (uaecptr addr)
! 741: {
! 742: return uae_mmu060_get_long (addr, false);
! 743: }
! 744:
! 745: STATIC_INLINE void get_move16_mmu (uaecptr addr, uae_u32 *v)
! 746: {
! 747: uae_mmu_get_move16 (addr, v);
! 748: }
! 749: STATIC_INLINE void put_move16_mmu (uaecptr addr, uae_u32 *v)
! 750: {
! 751: uae_mmu_put_move16 (addr, v);
! 752: }
! 753:
! 754: // locked rmw 060
! 755: STATIC_INLINE void put_lrmw_byte_mmu060 (uaecptr addr, uae_u32 v)
! 756: {
! 757: uae_mmu_put_lrmw (addr, v, sz_byte, 1);
! 758: }
! 759: STATIC_INLINE void put_lrmw_word_mmu060 (uaecptr addr, uae_u32 v)
! 760: {
! 761: uae_mmu_put_lrmw (addr, v, sz_word, 1);
! 762: }
! 763: STATIC_INLINE void put_lrmw_long_mmu060 (uaecptr addr, uae_u32 v)
! 764: {
! 765: uae_mmu_put_lrmw (addr, v, sz_long, 1);
! 766: }
! 767: STATIC_INLINE uae_u32 get_lrmw_byte_mmu060 (uaecptr addr)
! 768: {
! 769: return uae_mmu_get_lrmw (addr, sz_byte, 1);
! 770: }
! 771: STATIC_INLINE uae_u32 get_lrmw_word_mmu060 (uaecptr addr)
! 772: {
! 773: return uae_mmu_get_lrmw (addr, sz_word, 1);
! 774: }
! 775: STATIC_INLINE uae_u32 get_lrmw_long_mmu060 (uaecptr addr)
! 776: {
! 777: return uae_mmu_get_lrmw (addr, sz_long, 1);
! 778: }
! 779: // normal rmw 060
! 780: STATIC_INLINE void put_rmw_byte_mmu060 (uaecptr addr, uae_u32 v)
! 781: {
! 782: uae_mmu060_put_byte (addr, v, true);
! 783: }
! 784: STATIC_INLINE void put_rmw_word_mmu060 (uaecptr addr, uae_u32 v)
! 785: {
! 786: uae_mmu060_put_word (addr, v, true);
! 787: }
! 788: STATIC_INLINE void put_rmw_long_mmu060 (uaecptr addr, uae_u32 v)
! 789: {
! 790: uae_mmu060_put_long (addr, v, true);
! 791: }
! 792: STATIC_INLINE uae_u32 get_rmw_byte_mmu060 (uaecptr addr)
! 793: {
! 794: return uae_mmu060_get_byte (addr, true);
! 795: }
! 796: STATIC_INLINE uae_u32 get_rmw_word_mmu060 (uaecptr addr)
! 797: {
! 798: return uae_mmu060_get_word (addr, true);
! 799: }
! 800: STATIC_INLINE uae_u32 get_rmw_long_mmu060 (uaecptr addr)
! 801: {
! 802: return uae_mmu060_get_long (addr, true);
! 803: }
! 804: // locked rmw 040
! 805: STATIC_INLINE void put_lrmw_byte_mmu040 (uaecptr addr, uae_u32 v)
! 806: {
! 807: uae_mmu_put_lrmw (addr, v, sz_byte, 0);
! 808: }
! 809: STATIC_INLINE void put_lrmw_word_mmu040 (uaecptr addr, uae_u32 v)
! 810: {
! 811: uae_mmu_put_lrmw (addr, v, sz_word, 0);
! 812: }
! 813: STATIC_INLINE void put_lrmw_long_mmu040 (uaecptr addr, uae_u32 v)
! 814: {
! 815: uae_mmu_put_lrmw (addr, v, sz_long, 0);
! 816: }
! 817: STATIC_INLINE uae_u32 get_lrmw_byte_mmu040 (uaecptr addr)
! 818: {
! 819: return uae_mmu_get_lrmw (addr, sz_byte, 0);
! 820: }
! 821: STATIC_INLINE uae_u32 get_lrmw_word_mmu040 (uaecptr addr)
! 822: {
! 823: return uae_mmu_get_lrmw (addr, sz_word, 0);
! 824: }
! 825: STATIC_INLINE uae_u32 get_lrmw_long_mmu040 (uaecptr addr)
! 826: {
! 827: return uae_mmu_get_lrmw (addr, sz_long, 0);
! 828: }
! 829:
! 830: STATIC_INLINE uae_u32 get_ibyte_mmu040 (int o)
! 831: {
! 832: uae_u32 pc = m68k_getpc () + o;
! 833: return uae_mmu040_get_iword (pc);
! 834: }
! 835: STATIC_INLINE uae_u32 get_iword_mmu040 (int o)
! 836: {
! 837: uae_u32 pc = m68k_getpc () + o;
! 838: return uae_mmu040_get_iword (pc);
! 839: }
! 840: STATIC_INLINE uae_u32 get_ilong_mmu040 (int o)
! 841: {
! 842: uae_u32 pc = m68k_getpc () + o;
! 843: return uae_mmu040_get_ilong (pc);
! 844: }
! 845: STATIC_INLINE uae_u32 next_iword_mmu040 (void)
! 846: {
! 847: uae_u32 pc = m68k_getpc ();
! 848: m68k_incpci (2);
! 849: return uae_mmu040_get_iword (pc);
! 850: }
! 851: STATIC_INLINE uae_u32 next_ilong_mmu040 (void)
! 852: {
! 853: uae_u32 pc = m68k_getpc ();
! 854: m68k_incpci (4);
! 855: return uae_mmu040_get_ilong (pc);
! 856: }
! 857:
! 858: STATIC_INLINE uae_u32 get_ibyte_mmu060 (int o)
1.1.1.2 root 859: {
860: uae_u32 pc = m68k_getpc () + o;
1.1.1.4 ! root 861: return uae_mmu060_get_iword (pc);
1.1.1.2 root 862: }
1.1.1.4 ! root 863: STATIC_INLINE uae_u32 get_iword_mmu060 (int o)
1.1.1.2 root 864: {
865: uae_u32 pc = m68k_getpc () + o;
1.1.1.4 ! root 866: return uae_mmu060_get_iword (pc);
1.1.1.2 root 867: }
1.1.1.4 ! root 868: STATIC_INLINE uae_u32 get_ilong_mmu060 (int o)
1.1.1.2 root 869: {
870: uae_u32 pc = m68k_getpc () + o;
1.1.1.4 ! root 871: return uae_mmu060_get_ilong (pc);
1.1.1.2 root 872: }
1.1.1.4 ! root 873: STATIC_INLINE uae_u32 next_iword_mmu060 (void)
1.1.1.2 root 874: {
875: uae_u32 pc = m68k_getpc ();
876: m68k_incpci (2);
1.1.1.4 ! root 877: return uae_mmu060_get_iword (pc);
1.1.1.2 root 878: }
1.1.1.4 ! root 879: STATIC_INLINE uae_u32 next_ilong_mmu060 (void)
1.1.1.2 root 880: {
881: uae_u32 pc = m68k_getpc ();
882: m68k_incpci (4);
1.1.1.4 ! root 883: return uae_mmu060_get_ilong (pc);
1.1.1.2 root 884: }
885:
1.1.1.4 ! root 886: extern void flush_mmu040 (uaecptr, int);
! 887: extern void m68k_do_rts_mmu040 (void);
! 888: extern void m68k_do_rte_mmu040 (uaecptr a7);
! 889: extern void m68k_do_bsr_mmu040 (uaecptr oldpc, uae_s32 offset);
! 890:
! 891: extern void flush_mmu060 (uaecptr, int);
! 892: extern void m68k_do_rts_mmu060 (void);
! 893: extern void m68k_do_rte_mmu060 (uaecptr a7);
! 894: extern void m68k_do_bsr_mmu060 (uaecptr oldpc, uae_s32 offset);
1.1.1.2 root 895:
896: #endif /* CPUMMU_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.