1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * memory management
5   *
6   * Copyright 1995 Bernd Schmidt
7   */
8 
9 extern void memory_reset (void);
10 extern void a1000_reset (void);
11 
12 typedef uae_u32 (*mem_get_func)(uaecptr) REGPARAM;
13 typedef void (*mem_put_func)(uaecptr, uae_u32) REGPARAM;
14 typedef uae_u8 *(*xlate_func)(uaecptr) REGPARAM;
15 typedef int (*check_func)(uaecptr, uae_u32) REGPARAM;
16 
17 extern char *address_space, *good_address_map;
18 extern uae_u8 *chipmemory;
19 
20 extern uae_u32 allocated_chipmem;
21 extern uae_u32 allocated_fastmem;
22 extern uae_u32 allocated_bogomem;
23 extern uae_u32 allocated_gfxmem;
24 extern uae_u32 allocated_z3fastmem;
25 extern uae_u32 allocated_a3000mem;
26 
27 #undef DIRECT_MEMFUNCS_SUCCESSFUL
28 #include "machdep/maccess.h"
29 
30 #ifndef CAN_MAP_MEMORY
31 #undef USE_COMPILER
32 #endif
33 
34 #if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
35 #define USE_MAPPED_MEMORY
36 #endif
37 
38 #define kickmem_size 0x080000
39 
40 #define chipmem_start 0x00000000
41 #define bogomem_start 0x00C00000
42 #define a3000mem_start 0x07000000
43 #define kickmem_start 0x00F80000
44 
45 extern int ersatzkickfile;
46 extern int cloanto_rom;
47 extern uae_u16 kickstart_version;
48 extern int uae_boot_rom, uae_boot_rom_size;
49 
50 extern uae_u8* baseaddr[];
51 
52 typedef struct {
53     /* These ones should be self-explanatory... */
54     mem_get_func lget, wget, bget;
55     mem_put_func lput, wput, bput;
56     /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
57      * be used to address memory without calling the wget/wput functions.
58      * This doesn't work for all memory banks, so this function may call
59      * abort(). */
60     xlate_func xlateaddr;
61     /* To prevent calls to abort(), use check before calling xlateaddr.
62      * It checks not only that the memory bank can do xlateaddr, but also
63      * that the pointer points to an area of at least the specified size.
64      * This is used for example to translate bitplane pointers in custom.c */
65     check_func check;
66     /* For those banks that refer to real memory, we can save the whole trouble
67        of going through function calls, and instead simply grab the memory
68        ourselves. This holds the memory address where the start of memory is
69        for this particular bank. */
70     uae_u8 *baseaddr;
71     const char *name;
72 } addrbank;
73 
74 extern uae_u8 *filesysory;
75 extern uae_u8 *rtarea;
76 
77 extern addrbank chipmem_bank;
78 extern addrbank kickmem_bank;
79 extern addrbank custom_bank;
80 extern addrbank clock_bank;
81 extern addrbank cia_bank;
82 extern addrbank rtarea_bank;
83 extern addrbank expamem_bank;
84 extern addrbank fastmem_bank;
85 extern addrbank gfxmem_bank;
86 extern addrbank gayle_bank;
87 extern addrbank gayle2_bank;
88 extern addrbank gayle_attr_bank;
89 extern addrbank mbres_bank;
90 
91 extern void rtarea_init (void);
92 extern void rtarea_setup (void);
93 extern void expamem_init (void);
94 extern void expamem_reset (void);
95 
96 extern uae_u32 gfxmem_start;
97 extern uae_u8 *gfxmemory;
98 extern uae_u32 gfxmem_mask;
99 extern int address_space_24;
100 
101 /* Default memory access functions */
102 
103 extern int default_check(uaecptr addr, uae_u32 size) REGPARAM;
104 extern uae_u8 *default_xlate(uaecptr addr) REGPARAM;
105 
106 #define bankindex(addr) (((uaecptr)(addr)) >> 16)
107 
108 extern addrbank *mem_banks[65536];
109 extern uae_u8 *baseaddr[65536];
110 #define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
111 #define put_mem_bank(addr, b, realstart) do { \
112     (mem_banks[bankindex(addr)] = (b)); \
113     if ((b)->baseaddr) \
114 	baseaddr[bankindex(addr)] = (b)->baseaddr - (realstart); \
115     else \
116 	baseaddr[bankindex(addr)] = (uae_u8*)(((long)b)+1); \
117 } while (0)
118 
119 extern void memory_init (void);
120 extern void memory_cleanup (void);
121 extern void map_banks (addrbank *bank, int first, int count, int realsize);
122 extern void map_overlay (int chip);
123 
124 #ifndef NO_INLINE_MEMORY_ACCESS
125 
126 #define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
127 #define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
128 #define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
129 #define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
130 #define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
131 #define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
132 
133 #else
134 
135 extern uae_u32 alongget(uaecptr addr);
136 extern uae_u32 awordget(uaecptr addr);
137 extern uae_u32 longget(uaecptr addr);
138 extern uae_u32 wordget(uaecptr addr);
139 extern uae_u32 byteget(uaecptr addr);
140 extern void longput(uaecptr addr, uae_u32 l);
141 extern void wordput(uaecptr addr, uae_u32 w);
142 extern void byteput(uaecptr addr, uae_u32 b);
143 
144 #endif
145 
146 #ifndef MD_HAVE_MEM_1_FUNCS
147 
148 #define longget_1 longget
149 #define wordget_1 wordget
150 #define byteget_1 byteget
151 #define longput_1 longput
152 #define wordput_1 wordput
153 #define byteput_1 byteput
154 
155 #endif
156 
get_long(uaecptr addr)157 STATIC_INLINE uae_u32 get_long (uaecptr addr)
158 {
159     return longget_1(addr);
160 }
get_word(uaecptr addr)161 STATIC_INLINE uae_u32 get_word (uaecptr addr)
162 {
163     return wordget_1(addr);
164 }
get_byte(uaecptr addr)165 STATIC_INLINE uae_u32 get_byte (uaecptr addr)
166 {
167     return byteget_1(addr);
168 }
169 
170 /*
171  * Read a host pointer from addr
172  */
173 #if SIZEOF_VOID_P == 4
174 # define get_pointer(addr) ((void *)get_long (addr))
175 #else
176 # if SIZEOF_VOID_P == 8
get_pointer(uaecptr addr)177 STATIC_INLINE void *get_pointer (uaecptr addr)
178 {
179     const unsigned int n = SIZEOF_VOID_P / 4;
180     union {
181 	void *ptr;
182 	uae_u32  longs[SIZEOF_VOID_P / 4];
183     } p;
184     unsigned int i;
185 
186     for (i = 0; i < n; i++) {
187 #ifdef WORDS_BIGENDIAN
188 	p.longs[i] = get_long (addr + i * 4);
189 #else
190 	p.longs[n - 1 - i] = get_long (addr + i * 4);
191 #endif
192     }
193     return p.ptr;
194 }
195 # else
196 #  error "Unknown or unsupported pointer size."
197 # endif
198 #endif
199 
put_long(uaecptr addr,uae_u32 l)200 STATIC_INLINE void put_long (uaecptr addr, uae_u32 l)
201 {
202     longput_1(addr, l);
203 }
put_word(uaecptr addr,uae_u32 w)204 STATIC_INLINE void put_word (uaecptr addr, uae_u32 w)
205 {
206     wordput_1(addr, w);
207 }
put_byte(uaecptr addr,uae_u32 b)208 STATIC_INLINE void put_byte (uaecptr addr, uae_u32 b)
209 {
210     byteput_1(addr, b);
211 }
212 
213 /*
214  * Store host pointer v at addr
215  */
216 #if SIZEOF_VOID_P == 4
217 # define put_pointer(addr, p) (put_long ((addr), (uae_u32)(p)))
218 #else
219 # if SIZEOF_VOID_P == 8
put_pointer(uaecptr addr,void * v)220 STATIC_INLINE void put_pointer (uaecptr addr, void *v)
221 {
222     const unsigned int n = SIZEOF_VOID_P / 4;
223     union {
224 	void *ptr;
225 	uae_u32 longs[SIZEOF_VOID_P / 4];
226     } p;
227     unsigned int i;
228 
229     p.ptr = v;
230 
231     for (i = 0; i < n; i++) {
232 #ifdef WORDS_BIGENDIAN
233 	put_long (addr + i * 4, p.longs[i]);
234 #else
235 	put_long (addr + i * 4, p.longs[n - 1 - i]);
236 #endif
237     }
238 }
239 # endif
240 #endif
241 
get_real_address(uaecptr addr)242 STATIC_INLINE uae_u8 *get_real_address (uaecptr addr)
243 {
244     return get_mem_bank(addr).xlateaddr(addr);
245 }
246 
valid_address(uaecptr addr,uae_u32 size)247 STATIC_INLINE int valid_address(uaecptr addr, uae_u32 size)
248 {
249     return get_mem_bank(addr).check(addr, size);
250 }
251 
252 /* For faster access in custom chip emulation.  */
253 extern uae_u32 chipmem_lget (uaecptr) REGPARAM;
254 extern uae_u32 chipmem_wget (uaecptr) REGPARAM;
255 extern uae_u32 chipmem_bget (uaecptr) REGPARAM;
256 extern void chipmem_lput (uaecptr, uae_u32) REGPARAM;
257 extern void chipmem_wput (uaecptr, uae_u32) REGPARAM;
258 extern void chipmem_bput (uaecptr, uae_u32) REGPARAM;
259 
260 extern uae_u32 chipmem_agnus_wget (uaecptr) REGPARAM;
261 extern void chipmem_agnus_wput (uaecptr, uae_u32) REGPARAM;
262 
263 #ifdef NATMEM_OFFSET
264 
265 typedef struct shmpiece_reg {
266     uae_u8 *native_address;
267     int id;
268     uae_u32 size;
269     struct shmpiece_reg *next;
270     struct shmpiece_reg *prev;
271 } shmpiece;
272 
273 extern shmpiece *shm_start;
274 extern int canbang;
275 
276 #endif
277 
278 extern uae_u8 *mapped_malloc (size_t, char *);
279 extern void mapped_free (uae_u8 *);
280 extern void memory_hardreset (void);
281 
282 uaecptr strcpyha_safe (uaecptr dst, const char *src);
283 uaecptr strncpyha_safe (uaecptr dst, const char *src, int size);
284 extern char *strcpyah_safe (char *dst, uaecptr src);
285 extern void memcpyha_safe (uaecptr dst, const uae_u8 *src, int size);
286 extern void memcpyha (uaecptr dst, const uae_u8 *src, int size);
287 extern void memcpyah_safe (uae_u8 *dst, uaecptr src, int size);
288 extern void memcpyah (uae_u8 *dst, uaecptr src, int size);
289