1 /*
2  * memory.h - memory management
3  *
4  * Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS)
5  *
6  * Inspired by Christian Bauer's Basilisk II
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   * UAE - The Un*x Amiga Emulator
27   *
28   * memory management
29   *
30   * Copyright 1995 Bernd Schmidt
31   */
32 
33 #ifndef UAE_MEMORY_H
34 #define UAE_MEMORY_H
35 
36 #include "sysdeps.h"
37 #include "string.h"
38 #include "hardware.h"
39 #include "parameters.h"
40 #include "registers.h"
41 #include "cpummu.h"
42 #include "readcpu.h"
43 
44 # include <csetjmp>
45 
46 // newcpu.h
47 extern void Exception (int, uaecptr);
48 #ifdef EXCEPTIONS_VIA_LONGJMP
49 	extern JMP_BUF excep_env;
50 	#define SAVE_EXCEPTION \
51 		JMP_BUF excep_env_old; \
52 		memcpy(excep_env_old, excep_env, sizeof(JMP_BUF))
53 	#define RESTORE_EXCEPTION \
54 		memcpy(excep_env, excep_env_old, sizeof(JMP_BUF))
55 	#define TRY(var) int var = SETJMP(excep_env); if (!var)
56 	#define CATCH(var) else
57 	#define THROW(n) LONGJMP(excep_env, n)
58 	#define THROW_AGAIN(var) LONGJMP(excep_env, var)
59 	#define VOLATILE volatile
60 #else
61 	struct m68k_exception {
62 		int prb;
m68k_exceptionm68k_exception63 		m68k_exception (int exc) : prb (exc) {}
64 		operator int() { return prb; }
65 	};
66 	#define SAVE_EXCEPTION
67 	#define RESTORE_EXCEPTION
68 	#define TRY(var) try
69 	#define CATCH(var) catch(m68k_exception var)
70 	#define THROW(n) throw m68k_exception(n)
71 	#define THROW_AGAIN(var) throw
72 	#define VOLATILE
73 #endif /* EXCEPTIONS_VIA_LONGJMP */
74 extern int in_exception_2;
75 
76 #define STRAM_END	0x0e00000UL	// should be replaced by global ROMBase as soon as ROMBase will be a constant
77 #define ROM_END		0x0e80000UL	// should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes
78 #define FastRAM_BEGIN	0x1000000UL	// should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant
79 #ifdef FixedSizeFastRAM
80 #define FastRAM_SIZE	(FixedSizeFastRAM * 1024 * 1024)
81 #else
82 #define FastRAM_SIZE	FastRAMSize
83 #endif
84 
85 #ifdef FIXED_VIDEORAM
86 #define ARANYMVRAMSTART 0xf0000000UL
87 #endif
88 
89 #define ARANYMVRAMSIZE	0x00100000	// should be a variable to protect VGA card offscreen memory
90 
91 #ifdef FIXED_VIDEORAM
92 extern uintptr VMEMBaseDiff;
93 #else
94 extern uae_u32 VideoRAMBase;
95 #endif
96 
97 #ifdef ARAM_PAGE_CHECK
98 extern uaecptr pc_page, read_page, write_page;
99 extern uintptr pc_offset, read_offset, write_offset;
100 # ifdef PROTECT2K
101 #  define ARAM_PAGE_MASK 0x7ff
102 # else
103 #  ifdef FULLMMU
104 #   define ARAM_PAGE_MASK 0xfff
105 #  else
106 #   define ARAM_PAGE_MASK 0xfffff
107 #  endif
108 # endif
109 #endif
110 
111 extern uintptr MEMBaseDiff;
112 extern uintptr ROMBaseDiff;
113 extern uintptr FastRAMBaseDiff;
114 # define InitMEMBaseDiff(va, ra)	(MEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
115 # define InitROMBaseDiff(va, ra)        (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra))
116 # define InitFastRAMBaseDiff(va, ra)        (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra))
117 
118 #ifdef FIXED_VIDEORAM
119 #define InitVMEMBaseDiff(va, ra)	(VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
120 #else
121 #define InitVMEMBaseDiff(va, ra)        (ra = (uintptr)(va) + MEMBaseDiff)
122 #endif
123 
124 extern "C" void breakpt(void);
125 
126 
do_get_mem_quad(uae_u64 * a)127 static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);}
do_put_mem_quad(uae_u64 * a,uae_u64 v)128 static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);}
129 
130 
131 #ifndef NOCHECKBOUNDARY
test_ram_boundary(uaecptr addr,int size,bool super,bool write)132 static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write)
133 {
134 	if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) {
135 #ifdef PROTECT2K
136 		// protect first 2kB of RAM - access in supervisor mode only
137 		if (!super && addr < 0x00000800UL)
138 			return false;
139 #endif
140 		// check for write access to protected areas:
141 		// - first two longwords of ST-RAM are non-writable (ROM shadow)
142 		// - non-writable area between end of ST-RAM and begin of FastRAM
143 		if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size)))
144 			return true;
145 	}
146 #ifdef FIXED_VIDEORAM
147 	return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size);
148 #else
149 	return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size);
150 #endif
151 }
152 /*
153  * "size" is the size of the memory access (byte = 1, word = 2, long = 4)
154  */
check_ram_boundary(uaecptr addr,int size,bool write)155 static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write)
156 {
157 	if (test_ram_boundary(addr, size, regs.s, write))
158 		return;
159 
160 	// D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr));
161 	regs.mmu_fault_addr = addr;
162 	regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8));
163 	breakpt();
164 	THROW(2);
165 }
166 
167 #else
test_ram_boundary(uaecptr,int,bool,bool)168 static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; }
check_ram_boundary(uaecptr,int,bool)169 static inline void check_ram_boundary(uaecptr, int, bool) { }
170 #endif
171 
172 #ifdef FIXED_VIDEORAM
173 # define do_get_real_address(a)		((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff)))
174 #else
175 # define do_get_real_address(a)		((uae_u8 *)((uintptr)(a) + MEMBaseDiff))
176 #endif
177 
phys_get_real_address(uaecptr addr)178 static inline uae_u8 *phys_get_real_address(uaecptr addr)
179 {
180     return do_get_real_address(addr);
181 }
182 
183 #ifndef NOCHECKBOUNDARY
phys_valid_address(uaecptr addr,bool write,int sz)184 static inline bool phys_valid_address(uaecptr addr, bool write, int sz)
185 {
186 	return test_ram_boundary(addr, sz, regs.s, write);
187 }
188 #else
phys_valid_address(uaecptr,bool,int)189 static inline bool phys_valid_address(uaecptr, bool, int) { return true; }
190 #endif
191 
phys_get_quad(uaecptr addr)192 static inline uae_u64 phys_get_quad(uaecptr addr)
193 {
194 #ifdef ARAM_PAGE_CHECK
195     if (((addr ^ read_page) <= ARAM_PAGE_MASK))
196         return do_get_mem_quad((uae_u64*)(addr + read_offset));
197 #endif
198 #ifndef HW_SIGSEGV
199     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
200     if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */
201 #endif
202     check_ram_boundary(addr, 8, false);
203     uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
204 #ifdef ARAM_PAGE_CHECK
205     read_page = addr;
206     read_offset = (uintptr)m - (uintptr)addr;
207 #endif
208     return do_get_mem_quad(m);
209 }
210 
phys_get_long(uaecptr addr)211 static inline uae_u32 phys_get_long(uaecptr addr)
212 {
213 #ifdef ARAM_PAGE_CHECK
214     if (((addr ^ read_page) <= ARAM_PAGE_MASK))
215         return do_get_mem_long((uae_u32*)(addr + read_offset));
216 #endif
217 #ifndef HW_SIGSEGV
218     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
219     if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr);
220 #endif
221     check_ram_boundary(addr, 4, false);
222     uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
223 #ifdef ARAM_PAGE_CHECK
224     read_page = addr;
225     read_offset = (uintptr)m - (uintptr)addr;
226 #endif
227     return do_get_mem_long(m);
228 }
229 
phys_get_word(uaecptr addr)230 static inline uae_u32 phys_get_word(uaecptr addr)
231 {
232 #ifdef ARAM_PAGE_CHECK
233     if (((addr ^ read_page) <= ARAM_PAGE_MASK))
234         return do_get_mem_word((uae_u16*)(addr + read_offset));
235 #endif
236 #ifndef HW_SIGSEGV
237     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
238     if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr);
239 #endif
240     check_ram_boundary(addr, 2, false);
241     uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
242 #ifdef ARAM_PAGE_CHECK
243     read_page = addr;
244     read_offset = (uintptr)m - (uintptr)addr;
245 #endif
246     return do_get_mem_word(m);
247 }
248 
phys_get_byte(uaecptr addr)249 static inline uae_u32 phys_get_byte(uaecptr addr)
250 {
251 #ifdef ARAM_PAGE_CHECK
252     if (((addr ^ read_page) <= ARAM_PAGE_MASK))
253         return do_get_mem_byte((uae_u8*)(addr + read_offset));
254 #endif
255 #ifndef HW_SIGSEGV
256     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
257     if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr);
258 #endif
259     check_ram_boundary(addr, 1, false);
260     uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
261 #ifdef ARAM_PAGE_CHECK
262     read_page = addr;
263     read_offset = (uintptr)m - (uintptr)addr;
264 #endif
265     return do_get_mem_byte(m);
266 }
267 
phys_put_quad(uaecptr addr,uae_u64 l)268 static inline void phys_put_quad(uaecptr addr, uae_u64 l)
269 {
270 #ifdef ARAM_PAGE_CHECK
271     if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
272         do_put_mem_quad((uae_u64*)(addr + write_offset), l);
273         return;
274     }
275 #endif
276 #ifndef HW_SIGSEGV
277     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
278     if ((addr & 0xfff00000) == 0x00f00000) {
279         HWput_l(addr, l); /* TODO: must be HWput_q */
280         return;
281     }
282 #endif
283     check_ram_boundary(addr, 8, true);
284     uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
285 #ifdef ARAM_PAGE_CHECK
286     write_page = addr;
287     write_offset = (uintptr)m - (uintptr)addr;
288 #endif
289     do_put_mem_quad(m, l);
290 }
291 
phys_put_long(uaecptr addr,uae_u32 l)292 static inline void phys_put_long(uaecptr addr, uae_u32 l)
293 {
294 #ifdef ARAM_PAGE_CHECK
295     if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
296         do_put_mem_long((uae_u32*)(addr + write_offset), l);
297         return;
298     }
299 #endif
300 #ifndef HW_SIGSEGV
301     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
302     if ((addr & 0xfff00000) == 0x00f00000) {
303         HWput_l(addr, l);
304         return;
305     }
306 #endif
307     check_ram_boundary(addr, 4, true);
308     uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
309 #ifdef ARAM_PAGE_CHECK
310     write_page = addr;
311     write_offset = (uintptr)m - (uintptr)addr;
312 #endif
313     do_put_mem_long(m, l);
314 }
315 
phys_put_word(uaecptr addr,uae_u32 w)316 static inline void phys_put_word(uaecptr addr, uae_u32 w)
317 {
318 #ifdef ARAM_PAGE_CHECK
319     if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
320         do_put_mem_word((uae_u16*)(addr + write_offset), w);
321         return;
322     }
323 #endif
324 #ifndef HW_SIGSEGV
325     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
326     if ((addr & 0xfff00000) == 0x00f00000) {
327         HWput_w(addr, w);
328         return;
329     }
330 #endif
331     check_ram_boundary(addr, 2, true);
332     uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
333 #ifdef ARAM_PAGE_CHECK
334     write_page = addr;
335     write_offset = (uintptr)m - (uintptr)addr;
336 #endif
337     do_put_mem_word(m, w);
338 }
339 
phys_put_byte(uaecptr addr,uae_u32 b)340 static inline void phys_put_byte(uaecptr addr, uae_u32 b)
341 {
342 #ifdef ARAM_PAGE_CHECK
343     if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
344         do_put_mem_byte((uae_u8*)(addr + write_offset), b);
345         return;
346     }
347 #endif
348 #ifndef HW_SIGSEGV
349     addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
350     if ((addr & 0xfff00000) == 0x00f00000) {
351         HWput_b(addr, b);
352         return;
353     }
354 #endif
355     check_ram_boundary(addr, 1, true);
356     uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
357 #ifdef ARAM_PAGE_CHECK
358     write_page = addr;
359     write_offset = (uintptr)m - (uintptr)addr;
360 #endif
361     do_put_mem_byte(m, b);
362 }
363 
364 #ifdef FULLMMU
is_unaligned(uaecptr addr,int size)365 static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size)
366 {
367     return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000);
368 }
369 
mmu_get_real_address(uaecptr addr,struct mmu_atc_line * cl)370 static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl)
371 {
372 	return do_get_real_address(cl->phys + addr);
373 }
374 
mmu_get_quad(uaecptr addr,int data)375 static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data)
376 {
377 	struct mmu_atc_line *cl;
378 
379 	if (likely(mmu_lookup(addr, data, 0, &cl)))
380 		return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl));
381 	return mmu_get_quad_slow(addr, regs.s, data, cl);
382 }
383 
get_quad(uaecptr addr)384 static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr)
385 {
386 	return mmu_get_quad(addr, 1);
387 }
388 
mmu_get_long(uaecptr addr,int data,int size)389 static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size)
390 {
391 	struct mmu_atc_line *cl;
392 
393 	if (likely(mmu_lookup(addr, data, 0, &cl)))
394 		return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
395 	return mmu_get_long_slow(addr, regs.s, data, size, cl);
396 }
397 
get_long(uaecptr addr)398 static ALWAYS_INLINE uae_u32 get_long(uaecptr addr)
399 {
400 	if (unlikely(is_unaligned(addr, 4)))
401 		return mmu_get_long_unaligned(addr, 1);
402 	return mmu_get_long(addr, 1, sz_long);
403 }
404 
mmu_get_word(uaecptr addr,int data,int size)405 static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size)
406 {
407 	struct mmu_atc_line *cl;
408 
409 	if (likely(mmu_lookup(addr, data, 0, &cl)))
410 		return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
411 	return mmu_get_word_slow(addr, regs.s, data, size, cl);
412 }
413 
get_word(uaecptr addr)414 static ALWAYS_INLINE uae_u16 get_word(uaecptr addr)
415 {
416 	if (unlikely(is_unaligned(addr, 2)))
417 		return mmu_get_word_unaligned(addr, 1);
418 	return mmu_get_word(addr, 1, sz_word);
419 }
420 
mmu_get_byte(uaecptr addr,int data,int size)421 static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size)
422 {
423 	struct mmu_atc_line *cl;
424 
425 	if (likely(mmu_lookup(addr, data, 0, &cl)))
426 		return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
427 	return mmu_get_byte_slow(addr, regs.s, data, size, cl);
428 }
429 
get_byte(uaecptr addr)430 static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr)
431 {
432 	return mmu_get_byte(addr, 1, sz_byte);
433 }
434 
mmu_put_quad(uaecptr addr,uae_u64 val,int data)435 static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data)
436 {
437 	struct mmu_atc_line *cl;
438 
439 	if (likely(mmu_lookup(addr, data, 1, &cl)))
440 		do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val);
441 	else
442 		mmu_put_quad_slow(addr, val, regs.s, data, cl);
443 }
444 
put_quad(uaecptr addr,uae_u32 val)445 static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val)
446 {
447 	mmu_put_quad(addr, val, 1);
448 }
449 
mmu_put_long(uaecptr addr,uae_u32 val,int data,int size)450 static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size)
451 {
452 	struct mmu_atc_line *cl;
453 
454 	if (likely(mmu_lookup(addr, data, 1, &cl)))
455 		do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
456 	else
457 		mmu_put_long_slow(addr, val, regs.s, data, size, cl);
458 }
459 
put_long(uaecptr addr,uae_u32 val)460 static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val)
461 {
462 	if (unlikely(is_unaligned(addr, 4)))
463 		mmu_put_long_unaligned(addr, val, 1);
464 	else
465 		mmu_put_long(addr, val, 1, sz_long);
466 }
467 
mmu_put_word(uaecptr addr,uae_u16 val,int data,int size)468 static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size)
469 {
470 	struct mmu_atc_line *cl;
471 
472 	if (likely(mmu_lookup(addr, data, 1, &cl)))
473 		do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
474 	else
475 		mmu_put_word_slow(addr, val, regs.s, data, size, cl);
476 }
477 
put_word(uaecptr addr,uae_u16 val)478 static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val)
479 {
480 	if (unlikely(is_unaligned(addr, 2)))
481 		mmu_put_word_unaligned(addr, val, 1);
482 	else
483 		mmu_put_word(addr, val, 1, sz_word);
484 }
485 
mmu_put_byte(uaecptr addr,uae_u8 val,int data,int size)486 static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size)
487 {
488 	struct mmu_atc_line *cl;
489 
490 	if (likely(mmu_lookup(addr, data, 1, &cl)))
491 		do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
492 	else
493 		mmu_put_byte_slow(addr, val, regs.s, data, size, cl);
494 }
495 
put_byte(uaecptr addr,uae_u8 val)496 static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val)
497 {
498 	mmu_put_byte(addr, val, 1, sz_byte);
499 }
500 
get_real_address(uaecptr addr,int write,int sz)501 static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
502 {
503 	(void)sz;
504     return phys_get_real_address(mmu_translate(addr, regs.s, 1, write));
505 }
506 
mmu_get_user_long(uaecptr addr,int super,int data,int size)507 static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size)
508 {
509 	struct mmu_atc_line *cl;
510 
511 	if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
512 		return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
513 	return mmu_get_long_slow(addr, super, data, size, cl);
514 }
515 
mmu_get_user_word(uaecptr addr,int super,int data,int size)516 static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size)
517 {
518 	struct mmu_atc_line *cl;
519 
520 	if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
521 		return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
522 	return mmu_get_word_slow(addr, super, data, size, cl);
523 }
524 
mmu_get_user_byte(uaecptr addr,int super,int data,int size)525 static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size)
526 {
527 	struct mmu_atc_line *cl;
528 
529 	if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
530 		return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
531 	return mmu_get_byte_slow(addr, super, data, size, cl);
532 }
533 
mmu_put_user_long(uaecptr addr,uae_u32 val,int super,int data,int size)534 static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size)
535 {
536 	struct mmu_atc_line *cl;
537 
538 	if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
539 		do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
540 	else
541 		mmu_put_long_slow(addr, val, super, data, size, cl);
542 }
543 
mmu_put_user_word(uaecptr addr,uae_u16 val,int super,int data,int size)544 static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size)
545 {
546 	struct mmu_atc_line *cl;
547 
548 	if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
549 		do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
550 	else
551 		mmu_put_word_slow(addr, val, super, data, size, cl);
552 }
553 
mmu_put_user_byte(uaecptr addr,uae_u8 val,int super,int data,int size)554 static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size)
555 {
556 	struct mmu_atc_line *cl;
557 
558 	if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
559 		do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
560 	else
561 		mmu_put_byte_slow(addr, val, super, data, size, cl);
562 }
563 
valid_address(uaecptr addr,bool write,int sz)564 static inline bool valid_address(uaecptr addr, bool write, int sz)
565 {
566     SAVE_EXCEPTION;
567     TRY(prb) {
568 		(void)sz;
569 		check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write);
570 		RESTORE_EXCEPTION;
571 		return true;
572     }
573     CATCH(prb) {
574 		RESTORE_EXCEPTION;
575 		return false;
576     }
577 }
578 
579 #else
580 
581 #  define get_quad(a)			phys_get_quad(a)
582 #  define get_long(a)			phys_get_long(a)
583 #  define get_word(a)			phys_get_word(a)
584 #  define get_byte(a)			phys_get_byte(a)
585 #  define put_quad(a,b)			phys_put_quad(a,b)
586 #  define put_long(a,b)			phys_put_long(a,b)
587 #  define put_word(a,b)			phys_put_word(a,b)
588 #  define put_byte(a,b)			phys_put_byte(a,b)
589 #  define get_real_address(a,w,s)	phys_get_real_address(a)
590 
591 #define valid_address(a,w,s)		phys_valid_address(a,w,s)
592 #endif
593 
flush_internals()594 static inline void flush_internals() {
595 #ifdef ARAM_PAGE_CHECK
596     pc_page = 0xeeeeeeee;
597     read_page = 0xeeeeeeee;
598     write_page = 0xeeeeeeee;
599 #endif
600 }
601 
602 #endif /* MEMORY_H */
603 
604 /*
605 vim:ts=4:sw=4:
606 */
607