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