1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * memory management
5   *
6   * Copyright 1995 Bernd Schmidt
7   *
8   * Adaptation to Hatari by Thomas Huth
9   *
10   * This file is distributed under the GNU General Public License, version 2
11   * or at your option any later version. Read the file gpl.txt for details.
12   */
13 
14 #ifndef UAE_MEMORY_H
15 #define UAE_MEMORY_H
16 
17 #include "maccess.h"
18 
19 #define call_mem_get_func(func, addr) ((*func)(addr))
20 #define call_mem_put_func(func, addr, v) ((*func)(addr, v))
21 
22 
23 /* Enabling this adds one additional native memory reference per 68k memory
24  * access, but saves one shift (on the x86). Enabling this is probably
25  * better for the cache. My favourite benchmark (PP2) doesn't show a
26  * difference, so I leave this enabled. */
27 #if 1 || defined SAVE_MEMORY
28 #define SAVE_MEMORY_BANKS
29 #endif
30 
31 
32 typedef uae_u32 (*mem_get_func)(uaecptr) REGPARAM;
33 typedef void (*mem_put_func)(uaecptr, uae_u32) REGPARAM;
34 typedef uae_u8 *(*xlate_func)(uaecptr) REGPARAM;
35 typedef int (*check_func)(uaecptr, uae_u32) REGPARAM;
36 
37 extern char *address_space, *good_address_map;
38 
39 
40 enum
41 {
42 	ABFLAG_UNK = 0, ABFLAG_RAM = 1, ABFLAG_ROM = 2, ABFLAG_ROMIN = 4, ABFLAG_IO = 8,
43 	ABFLAG_NONE = 16, ABFLAG_SAFE = 32, ABFLAG_INDIRECT = 64, ABFLAG_NOALLOC = 128,
44 	ABFLAG_RTG = 256, ABFLAG_THREADSAFE = 512, ABFLAG_DIRECTMAP = 1024
45 };
46 typedef struct {
47     /* These ones should be self-explanatory... */
48     mem_get_func lget, wget, bget;
49     mem_put_func lput, wput, bput;
50     /* Use xlateaddr to translate an Atari address to a uae_u8 * that can
51      * be used to address memory without calling the wget/wput functions.
52      * This doesn't work for all memory banks, so this function may call
53      * abort(). */
54     xlate_func xlateaddr;
55     /* To prevent calls to abort(), use check before calling xlateaddr.
56      * It checks not only that the memory bank can do xlateaddr, but also
57      * that the pointer points to an area of at least the specified size.
58      * This is used for example to translate bitplane pointers in custom.c */
59     check_func check;
60     /* For those banks that refer to real memory, we can save the whole trouble
61     of going through function calls, and instead simply grab the memory
62     ourselves. This holds the memory address where the start of memory is
63     for this particular bank. */
64     uae_u8 *baseaddr;
65     int flags;
66     uae_u32 mask;
67     uae_u32 start;
68 } addrbank;
69 
70 
71 #define bankindex(addr) (((uaecptr)(addr)) >> 16)
72 
73 #ifdef SAVE_MEMORY_BANKS
74 extern addrbank *mem_banks[65536];
75 #define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
76 #define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b))
77 #else
78 extern addrbank mem_banks[65536];
79 #define get_mem_bank(addr) (mem_banks[bankindex(addr)])
80 #define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b))
81 #endif
82 
83 extern bool memory_region_bus_error ( uaecptr addr );
84 extern void memory_map_Standard_RAM ( Uint32 MMU_Bank0_Size , Uint32 MMU_Bank1_Size );
85 extern void memory_init(uae_u32 nNewSTMemSize, uae_u32 nNewTTMemSize, uae_u32 nNewRomMemStart);
86 extern void memory_uninit (void);
87 extern void map_banks(addrbank *bank, int first, int count);
88 
89 #ifndef NO_INLINE_MEMORY_ACCESS
90 
91 #define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
92 #define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
93 #define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
94 #define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
95 #define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
96 #define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
97 
98 #else
99 
100 extern uae_u32 alongget(uaecptr addr);
101 extern uae_u32 awordget(uaecptr addr);
102 extern uae_u32 longget(uaecptr addr);
103 extern uae_u32 wordget(uaecptr addr);
104 extern uae_u32 byteget(uaecptr addr);
105 extern void longput(uaecptr addr, uae_u32 l);
106 extern void wordput(uaecptr addr, uae_u32 w);
107 extern void byteput(uaecptr addr, uae_u32 b);
108 
109 #endif
110 
111 
get_long(uaecptr addr)112 static inline uae_u32 get_long(uaecptr addr)
113 {
114     return longget(addr);
115 }
116 
get_word(uaecptr addr)117 static inline uae_u32 get_word(uaecptr addr)
118 {
119     return wordget(addr);
120 }
121 
get_byte(uaecptr addr)122 static inline uae_u32 get_byte(uaecptr addr)
123 {
124     return byteget(addr);
125 }
126 
put_long(uaecptr addr,uae_u32 l)127 static inline void put_long(uaecptr addr, uae_u32 l)
128 {
129     longput(addr, l);
130 }
131 
put_word(uaecptr addr,uae_u32 w)132 static inline void put_word(uaecptr addr, uae_u32 w)
133 {
134     wordput(addr, w);
135 }
136 
put_byte(uaecptr addr,uae_u32 b)137 static inline void put_byte(uaecptr addr, uae_u32 b)
138 {
139     byteput(addr, b);
140 }
141 
get_real_address(uaecptr addr)142 static inline uae_u8 *get_real_address(uaecptr addr)
143 {
144     return get_mem_bank(addr).xlateaddr(addr);
145 }
146 
valid_address(uaecptr addr,uae_u32 size)147 static inline int valid_address(uaecptr addr, uae_u32 size)
148 {
149     return get_mem_bank(addr).check(addr, size);
150 }
151 
152 
153 #endif /* UAE_MEMORY_H */
154