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