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