|
|
1.1.1.2 root 1: /*
2: * cpummu.cpp - MMU emulation
3: *
4: * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
1.1.1.5 root 5: *
1.1.1.2 root 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: #include "sysconfig.h"
28: #include "sysdeps.h"
29:
1.1.1.5 root 30: #include "main.h"
31: #include "hatari-glue.h"
32:
33:
1.1.1.2 root 34: #include "options_cpu.h"
35: #include "memory.h"
36: #include "newcpu.h"
37: #include "cpummu.h"
1.1.1.5 root 38:
39: #define MMUDUMP 0
1.1.1.2 root 40:
41: #define DBG_MMU_VERBOSE 1
42: #define DBG_MMU_SANITY 1
1.1.1.4 root 43: #if 0
1.1.1.2 root 44: #define write_log printf
1.1.1.4 root 45: #endif
1.1.1.2 root 46:
47: #ifdef FULLMMU
48:
49:
1.1.1.4 root 50: uae_u32 mmu_is_super;
51: uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski;
1.1.1.2 root 52: struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS];
1.1.1.4 root 53: bool mmu_pagesize_8k;
54:
55: int mmu060_state;
56: uae_u16 mmu_opcode;
57: bool mmu_restart;
58: static bool locked_rmw_cycle;
59: static bool ismoves;
60: bool mmu_ttr_enabled;
1.1.1.5 root 61: int mmu_atc_ways[2];
62: int way_random;
1.1.1.4 root 63:
64: int mmu040_movem;
65: uaecptr mmu040_movem_ea;
66: uae_u32 mmu040_move16[4];
1.1.1.2 root 67:
68: static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr)
69: {
1.1.1.5 root 70: DUNUSED(label);
1.1.1.4 root 71: #if MMUDEBUG > 0
1.1.1.5 root 72: uae_u32 from_addr, to_addr;
73:
74: from_addr = ttr & MMU_TTR_LOGICAL_BASE;
75: to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8;
76:
77: write_log(_T("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d\n"),
78: label, ttr,
79: from_addr, to_addr,
80: ttr & MMU_TTR_BIT_ENABLED ? 1 : 0,
81: (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT,
82: ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0,
83: (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT
84: );
1.1.1.4 root 85: #endif
1.1.1.2 root 86: }
87:
88: void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode)
89: {
1.1.1.5 root 90: uae_u32 * ttr;
91: uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0;
92: uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1;
93:
94: if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0)
95: ttr = ttr1;
96: else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0)
97: ttr = ttr0;
98: else
99: return;
100:
101: *ttr = baseaddr & MMU_TTR_LOGICAL_BASE;
102: *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8;
103: *ttr |= MMU_TTR_BIT_ENABLED;
104:
1.1.1.4 root 105: #if MMUDEBUG > 0
1.1.1.5 root 106: write_log(_T("MMU: map transparent mapping of %08x\n"), *ttr);
1.1.1.4 root 107: #endif
1.1.1.2 root 108: }
109:
1.1.1.4 root 110: void mmu_tt_modified (void)
111: {
1.1.1.5 root 112: mmu_ttr_enabled = ((regs.dtt0 | regs.dtt1 | regs.itt0 | regs.itt1) & MMU_TTR_BIT_ENABLED) != 0;
1.1.1.4 root 113: }
1.1.1.2 root 114:
115: #if 0
1.1.1.5 root 116: #if MMUDUMP
117:
118: /* This dump output makes much more sense than old one */
119:
120: #define LEVELA_SIZE 7
121: #define LEVELB_SIZE 7
122: #define LEVELC_SIZE 6
123: #define PAGE_SIZE 12 // = 1 << 12 = 4096
124:
125: #define LEVELA_VAL(x) ((((uae_u32)(x)) >> (32 - (LEVELA_SIZE ))) & ((1 << LEVELA_SIZE) - 1))
126: #define LEVELB_VAL(x) ((((uae_u32)(x)) >> (32 - (LEVELA_SIZE + LEVELB_SIZE ))) & ((1 << LEVELB_SIZE) - 1))
127: #define LEVELC_VAL(x) ((((uae_u32)(x)) >> (32 - (LEVELA_SIZE + LEVELB_SIZE + LEVELC_SIZE))) & ((1 << LEVELC_SIZE) - 1))
128:
129: #define LEVELA(root, x) (get_long(root + LEVELA_VAL(x) * 4))
130: #define LEVELB(a, x) (get_long((((uae_u32)a) & ~((1 << (LEVELB_SIZE + 2)) - 1)) + LEVELB_VAL(x) * 4))
131: #define LEVELC(b, x) (get_long((((uae_u32)b) & ~((1 << (LEVELC_SIZE + 2)) - 1)) + LEVELC_VAL(x) * 4))
132:
133: #define ISINVALID(x) ((((ULONG)x) & 3) == 0)
134:
135: static uae_u32 getdesc(uae_u32 root, uae_u32 addr)
136: {
137: ULONG desc;
138:
139: desc = LEVELA(root, addr);
140: if (ISINVALID(desc))
141: return desc;
142: desc = LEVELB(desc, addr);
143: if (ISINVALID(desc))
144: return desc;
145: desc = LEVELC(desc, addr);
146: return desc;
147: }
1.1.1.2 root 148: static void mmu_dump_table(const char * label, uaecptr root_ptr)
149: {
1.1.1.5 root 150: ULONG i;
151: ULONG startaddr;
152: ULONG odesc;
153: ULONG totalpages;
154: ULONG pagemask = (1 << PAGE_SIZE) - 1;
155:
156: console_out_f(_T("MMU dump start. Root = %08x\n"), root_ptr);
157: totalpages = 1 << (32 - PAGE_SIZE);
158: startaddr = 0;
159: odesc = getdesc(root_ptr, startaddr);
160: for (i = 0; i <= totalpages; i++) {
161: ULONG addr = i << PAGE_SIZE;
162: ULONG desc = 0;
163: if (i < totalpages)
164: desc = getdesc(root_ptr, addr);
165: if ((desc & pagemask) != (odesc & pagemask) || i == totalpages) {
166: uae_u8 cm, sp;
167: cm = (odesc >> 5) & 3;
168: sp = (odesc >> 7) & 1;
169: console_out_f(_T("%08x - %08x: %08x WP=%d S=%d CM=%d (%08x)\n"),
170: startaddr, addr - 1, odesc & ~((1 << PAGE_SIZE) - 1),
171: (odesc & 4) ? 1 : 0, sp, cm, odesc);
172: startaddr = addr;
173: odesc = desc;
174: }
175: }
176: console_out_f(_T("MMU dump end\n"));
177: }
1.1.1.2 root 178:
1.1.1.5 root 179: #else
180: /* {{{ mmu_dump_table */
181: static void mmu_dump_table(const char * label, uaecptr root_ptr)
182: {
183: DUNUSED(label);
184: const int ROOT_TABLE_SIZE = 128,
185: PTR_TABLE_SIZE = 128,
186: PAGE_TABLE_SIZE = 64,
187: ROOT_INDEX_SHIFT = 25,
188: PTR_INDEX_SHIFT = 18;
189: // const int PAGE_INDEX_SHIFT = 12;
190: int root_idx, ptr_idx, page_idx;
191: uae_u32 root_des, ptr_des, page_des;
192: uaecptr ptr_des_addr, page_addr,
193: root_log, ptr_log, page_log;
194:
195: console_out_f(_T("%s: root=%x\n"), label, root_ptr);
196:
197: for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) {
198: root_des = phys_get_long(root_ptr + root_idx);
199:
200: if ((root_des & 2) == 0)
201: continue; /* invalid */
202:
203: console_out_f(_T("ROOT: %03d U=%d W=%d UDT=%02d\n"), root_idx,
204: root_des & 8 ? 1 : 0,
205: root_des & 4 ? 1 : 0,
206: root_des & 3
207: );
208:
209: root_log = root_idx << ROOT_INDEX_SHIFT;
210:
211: ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK;
212:
213: for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) {
214: struct {
215: uaecptr log, phys;
216: int start_idx, n_pages; /* number of pages covered by this entry */
217: uae_u32 match;
218: } page_info[PAGE_TABLE_SIZE];
219: int n_pages_used;
220:
221: ptr_des = phys_get_long(ptr_des_addr + ptr_idx);
222: ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT);
223:
224: if ((ptr_des & 2) == 0)
225: continue; /* invalid */
226:
227: page_addr = ptr_des & (mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4);
228:
229: n_pages_used = -1;
230: for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) {
231:
232: page_des = phys_get_long(page_addr + page_idx);
233: page_log = ptr_log | (page_idx << 2); // ??? PAGE_INDEX_SHIFT
234:
235: switch (page_des & 3) {
236: case 0: /* invalid */
237: continue;
238: case 1: case 3: /* resident */
239: case 2: /* indirect */
240: if (n_pages_used == -1 || page_info[n_pages_used].match != page_des) {
241: /* use the next entry */
242: n_pages_used++;
243:
244: page_info[n_pages_used].match = page_des;
245: page_info[n_pages_used].n_pages = 1;
246: page_info[n_pages_used].start_idx = page_idx;
247: page_info[n_pages_used].log = page_log;
248: } else {
249: page_info[n_pages_used].n_pages++;
250: }
251: break;
252: }
253: }
254:
255: if (n_pages_used == -1)
256: continue;
257:
258: console_out_f(_T(" PTR: %03d U=%d W=%d UDT=%02d\n"), ptr_idx,
259: ptr_des & 8 ? 1 : 0,
260: ptr_des & 4 ? 1 : 0,
261: ptr_des & 3
262: );
263:
264:
265: for (page_idx = 0; page_idx <= n_pages_used; page_idx++) {
266: page_des = page_info[page_idx].match;
267:
268: if ((page_des & MMU_PDT_MASK) == 2) {
269: console_out_f(_T(" PAGE: %03d-%03d log=%08x INDIRECT --> addr=%08x\n"),
270: page_info[page_idx].start_idx,
271: page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
272: page_info[page_idx].log,
273: page_des & MMU_PAGE_INDIRECT_MASK
274: );
275:
276: } else {
277: console_out_f(_T(" PAGE: %03d-%03d log=%08x addr=%08x UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d\n"),
278: page_info[page_idx].start_idx,
279: page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
280: page_info[page_idx].log,
281: page_des & (mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4),
282: (page_des & (mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4)) >> MMU_PAGE_UR_SHIFT,
283: page_des & MMU_DES_GLOBAL ? 1 : 0,
284: (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT,
285: page_des & MMU_DES_SUPER ? 1 : 0,
286: (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT,
287: page_des & MMU_DES_MODIFIED ? 1 : 0,
288: page_des & MMU_DES_USED ? 1 : 0,
289: page_des & MMU_DES_WP ? 1 : 0
290: );
291: }
292: }
293: }
294:
295: }
1.1.1.2 root 296: }
297: /* }}} */
298: #endif
1.1.1.5 root 299: #endif
1.1.1.2 root 300:
301: /* {{{ mmu_dump_atc */
1.1.1.5 root 302: static void mmu_dump_atc(void)
1.1.1.2 root 303: {
1.1.1.5 root 304:
1.1.1.2 root 305: }
306: /* }}} */
307:
308: /* {{{ mmu_dump_tables */
309: void mmu_dump_tables(void)
310: {
1.1.1.5 root 311: write_log(_T("URP: %08x SRP: %08x MMUSR: %x TC: %x\n"), regs.urp, regs.srp, regs.mmusr, regs.tcr);
312: mmu_dump_ttr(_T("DTT0"), regs.dtt0);
313: mmu_dump_ttr(_T("DTT1"), regs.dtt1);
314: mmu_dump_ttr(_T("ITT0"), regs.itt0);
315: mmu_dump_ttr(_T("ITT1"), regs.itt1);
316: mmu_dump_atc();
317: #if MMUDUMP
318: mmu_dump_table("SRP", regs.srp);
1.1.1.2 root 319: #endif
320: }
321: /* }}} */
322:
1.1.1.5 root 323: void mmu_bus_error(uaecptr addr, uae_u32 val, int fc, bool write, int size, bool nonmmu)
1.1.1.2 root 324: {
1.1.1.5 root 325: uae_u16 ssw = 0;
326:
327: if (ismoves) {
328: ismoves = false;
329: // MOVES special behavior
330: int fc2 = write ? regs.dfc : regs.sfc;
331: if (fc2 == 0 || fc2 == 3 || fc2 == 4 || fc2 == 7)
332: ssw |= MMU_SSW_TT1;
333: if (fc2 == 2 || fc2 == 6)
334: fc2--;
1.1.1.4 root 335: #if MMUDEBUGMISC > 0
1.1.1.5 root 336: write_log (_T("040 MMU MOVES fc=%d -> %d\n"), fc, fc2);
1.1.1.4 root 337: #endif
1.1.1.5 root 338: fc = fc2;
339: }
340:
341: ssw |= fc & MMU_SSW_TM; /* TM = FC */
342:
343: switch (size) {
344: case sz_byte:
345: ssw |= MMU_SSW_SIZE_B;
346: break;
347: case sz_word:
348: ssw |= MMU_SSW_SIZE_W;
349: break;
350: case sz_long:
351: ssw |= MMU_SSW_SIZE_L;
352: break;
353: }
354:
355: regs.wb3_status = write ? 0x80 | (ssw & 0x7f) : 0;
356: regs.wb3_data = val;
357: regs.wb2_status = 0;
358: if (!write)
359: ssw |= MMU_SSW_RW;
360:
361: if (size == 16) { // MOVE16
362: ssw |= MMU_SSW_SIZE_CL;
363: ssw |= MMU_SSW_TT0;
364: regs.mmu_effective_addr &= ~15;
365: if (write) {
366: // clear normal writeback if MOVE16 write
367: regs.wb3_status &= ~0x80;
368: // wb2 = cacheline size writeback
369: regs.wb2_status = 0x80 | MMU_SSW_SIZE_CL | (ssw & 0x1f);
370: regs.wb2_address = regs.mmu_effective_addr;
371: write_log (_T("040 MMU MOVE16 WRITE FAULT!\n"));
1.1.1.4 root 372: }
1.1.1.5 root 373: }
374:
375: if (mmu040_movem) {
376: ssw |= MMU_SSW_CM;
377: regs.mmu_effective_addr = mmu040_movem_ea;
378: mmu040_movem = 0;
1.1.1.4 root 379: #if MMUDEBUGMISC > 0
1.1.1.5 root 380: write_log (_T("040 MMU_SSW_CM EA=%08X\n"), mmu040_movem_ea);
1.1.1.4 root 381: #endif
1.1.1.5 root 382: }
383: if (locked_rmw_cycle) {
384: ssw |= MMU_SSW_LK;
385: ssw &= ~MMU_SSW_RW;
386: locked_rmw_cycle = false;
1.1.1.4 root 387: #if MMUDEBUGMISC > 0
1.1.1.5 root 388: write_log (_T("040 MMU_SSW_LK!\n"));
1.1.1.4 root 389: #endif
1.1.1.5 root 390: }
391:
392: if (!nonmmu)
393: ssw |= MMU_SSW_ATC;
394: regs.mmu_ssw = ssw;
395:
1.1.1.4 root 396: #if MMUDEBUG > 0
1.1.1.5 root 397: write_log(_T("BF: fc=%d w=%d logical=%08x ssw=%04x PC=%08x INS=%04X\n"), fc, write, addr, ssw, m68k_getpc(), mmu_opcode);
1.1.1.4 root 398: #endif
1.1.1.5 root 399:
400: regs.mmu_fault_addr = addr;
401:
402: THROW(2);
1.1.1.4 root 403: }
404:
1.1.1.2 root 405: /*
406: * Lookup the address by walking the page table and updating
407: * the page descriptors accordingly. Returns the found descriptor
408: * or produces a bus error.
409: */
1.1.1.5 root 410: static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, struct mmu_atc_line *l)
1.1.1.2 root 411: {
1.1.1.5 root 412: uae_u32 desc, desc_addr, wp, status;
413: int i;
414:
415: wp = 0;
416: desc = super ? regs.srp : regs.urp;
417:
418: /* fetch root table descriptor */
419: i = (addr >> 23) & 0x1fc;
420: desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
421:
422: SAVE_EXCEPTION;
423: TRY(prb) {
424: desc = phys_get_long(desc_addr);
425: if ((desc & 2) == 0) {
1.1.1.4 root 426: #if MMUDEBUG > 1
1.1.1.5 root 427: write_log(_T("MMU: invalid root descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"),
428: addr, desc_addr, desc);
1.1.1.4 root 429: #endif
1.1.1.5 root 430: goto fail;
431: }
432:
433: wp |= desc;
434: if ((desc & MMU_DES_USED) == 0)
435: phys_put_long(desc_addr, desc | MMU_DES_USED);
436:
437: /* fetch pointer table descriptor */
438: i = (addr >> 16) & 0x1fc;
439: desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
440: desc = phys_get_long(desc_addr);
441: if ((desc & 2) == 0) {
1.1.1.4 root 442: #if MMUDEBUG > 1
1.1.1.5 root 443: write_log(_T("MMU: invalid ptr descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"),
444: addr, desc_addr, desc);
1.1.1.4 root 445: #endif
1.1.1.5 root 446: goto fail;
447: }
448: wp |= desc;
449: if ((desc & MMU_DES_USED) == 0)
450: phys_put_long(desc_addr, desc | MMU_DES_USED);
451:
452: /* fetch page table descriptor */
453: if (mmu_pagesize_8k) {
454: i = (addr >> 11) & 0x7c;
455: desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) + i;
456: } else {
457: i = (addr >> 10) & 0xfc;
458: desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) + i;
459: }
460:
461: desc = phys_get_long(desc_addr);
462: if ((desc & 3) == 2) {
463: /* indirect */
464: desc_addr = desc & MMU_PAGE_INDIRECT_MASK;
465: desc = phys_get_long(desc_addr);
466: }
467: if ((desc & 1) == 1) {
468: wp |= desc;
469: if (write) {
470: if ((wp & MMU_DES_WP) || ((desc & MMU_DES_SUPER) && !super)) {
471: if ((desc & MMU_DES_USED) == 0) {
472: desc |= MMU_DES_USED;
473: phys_put_long(desc_addr, desc);
474: }
475: } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) !=
476: (MMU_DES_USED|MMU_DES_MODIFIED)) {
477: desc |= MMU_DES_USED|MMU_DES_MODIFIED;
478: phys_put_long(desc_addr, desc);
479: }
480: } else {
481: if ((desc & MMU_DES_USED) == 0) {
482: desc |= MMU_DES_USED;
483: phys_put_long(desc_addr, desc);
484: }
485: }
486: desc |= wp & MMU_DES_WP;
487: } else {
1.1.1.4 root 488: #if MMUDEBUG > 2
1.1.1.5 root 489: write_log(_T("MMU: invalid page descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr);
1.1.1.4 root 490: #endif
1.1.1.5 root 491: if ((desc & 3) == 2) {
1.1.1.4 root 492: #if MMUDEBUG > 1
1.1.1.5 root 493: write_log(_T("MMU: double indirect descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr);
494: #endif
495: }
496: fail:
497: desc = 0;
498: }
499:
500: /* Create new ATC entry and return status */
501: l->status = desc & (MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S|MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W|MMU_MMUSR_R);
502: l->phys = desc & mmu_pagemaski;
503: status = l->phys | l->status;
504: RESTORE_EXCEPTION;
505: } CATCH(prb) {
506: RESTORE_EXCEPTION;
507: /* bus error during table search */
508: l->status = 0;
509: l->phys = 0;
510: status = MMU_MMUSR_B;
511: #if MMUDEBUG > 0
512: write_log(_T("MMU: bus error during table search.\n"));
513: #endif
514: } ENDTRY
515:
516: l->valid = 1;
517: l->tag = tag;
518:
519: #if MMUDEBUG > 2
520: write_log(_T("translate: %x,%u,%u -> %x\n"), addr, super, write, desc);
521: #endif
522:
523: return status;
524: }
525:
526: uaecptr mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size)
527: {
528: int way, i, index, way_invalid;
529: uae_u32 tag = ((super ? 0x80000000 : 0x00000000) | (addr >> 1)) &
530: mmu_tagmask;
531: struct mmu_atc_line *l;
532:
533: if (mmu_pagesize_8k)
534: index=(addr & 0x0001E000)>>13;
535: else
536: index=(addr & 0x0000F000)>>12;
537: way_invalid = ATC_WAYS;
538: way_random++;
539: way = mmu_atc_ways[data];
540:
541: for (i = 0; i < ATC_WAYS; i++) {
542: // if we have this
543: l = &mmu_atc_array[data][way][index];
544: if (l->valid) {
545: if (tag == l->tag) {
546: atc_retry:
547: // check if we need to cause a page fault
548: if (((l->status&(MMU_MMUSR_W|MMU_MMUSR_S|MMU_MMUSR_R))!=MMU_MMUSR_R)) {
549: if (((l->status&MMU_MMUSR_W) && write) ||
550: ((l->status&MMU_MMUSR_S) && !super) ||
551: !(l->status&MMU_MMUSR_R)) {
552: mmu_bus_error(addr, val, mmu_get_fc(super, data), write, size, false);
553: return 0; // never reach, bus error longjumps out of the function
554: }
555: }
556: // if first write to this page initiate table search to set M bit (but modify this slot)
557: if (!(l->status&MMU_MMUSR_M) && write) {
558: way_invalid = way;
559: break;
560: }
561: // save way for next access (likely in same page)
562: mmu_atc_ways[data] = way;
563:
564: // return translated addr
565: return l->phys | (addr & mmu_pagemask);
566: }
567: } else {
568: way_invalid = way;
569: }
570: way++;
571: way %= ATC_WAYS;
572: }
573: // no entry found, we need to create a new one, first find an atc line to replace
574: way_random %= ATC_WAYS;
575: way = (way_invalid < ATC_WAYS) ? way_invalid : way_random;
576:
577: // then initiate table search and create a new entry
578: l = &mmu_atc_array[data][way][index];
579: mmu_fill_atc(addr, super, tag, write, l);
580:
581: // and retry the ATC search
582: way_random++;
583: goto atc_retry;
584:
585: // never reach
586: return 0;
1.1.1.2 root 587: }
588:
1.1.1.4 root 589: static void misalignednotfirst(uaecptr addr)
590: {
591: #if MMUDEBUGMISC > 0
1.1.1.5 root 592: write_log (_T("misalignednotfirst %08x -> %08x %08X\n"), regs.mmu_fault_addr, addr, regs.instruction_pc);
1.1.1.4 root 593: #endif
1.1.1.5 root 594: regs.mmu_fault_addr = addr;
595: regs.mmu_ssw |= MMU_SSW_MA;
1.1.1.4 root 596: }
597:
598: static void misalignednotfirstcheck(uaecptr addr)
599: {
1.1.1.5 root 600: if (regs.mmu_fault_addr == addr)
601: return;
602: misalignednotfirst (addr);
1.1.1.2 root 603: }
604:
1.1.1.5 root 605: uae_u16 REGPARAM2 mmu_get_word_unaligned(uaecptr addr)
606: {
607: uae_u16 res;
608:
609: res = (uae_u16)mmu_get_byte(addr, sz_word) << 8;
610: SAVE_EXCEPTION;
611: TRY(prb) {
612: res |= mmu_get_byte(addr + 1, sz_word);
613: RESTORE_EXCEPTION;
614: }
615: CATCH(prb) {
616: RESTORE_EXCEPTION;
617: misalignednotfirst(addr);
618: THROW_AGAIN(prb);
619: } ENDTRY
620: return res;
621: }
622:
623: uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr)
624: {
625: uae_u32 res;
626:
627: if (likely(!(addr & 1))) {
628: res = (uae_u32)mmu_get_word(addr, sz_long) << 16;
629: SAVE_EXCEPTION;
630: TRY(prb) {
631: res |= mmu_get_word(addr + 2, sz_long);
632: RESTORE_EXCEPTION;
633: }
634: CATCH(prb) {
635: RESTORE_EXCEPTION;
636: misalignednotfirst(addr);
637: THROW_AGAIN(prb);
638: } ENDTRY
639: } else {
640: res = (uae_u32)mmu_get_byte(addr, sz_long) << 8;
641: SAVE_EXCEPTION;
642: TRY(prb) {
643: res = (res | mmu_get_byte(addr + 1, sz_long)) << 8;
644: res = (res | mmu_get_byte(addr + 2, sz_long)) << 8;
645: res |= mmu_get_byte(addr + 3, sz_long);
646: RESTORE_EXCEPTION;
647: }
648: CATCH(prb) {
649: RESTORE_EXCEPTION;
650: misalignednotfirst(addr);
651: THROW_AGAIN(prb);
652: } ENDTRY
653: }
654: return res;
655: }
656:
657: uae_u32 REGPARAM2 mmu_get_ilong_unaligned(uaecptr addr)
1.1.1.2 root 658: {
1.1.1.5 root 659: uae_u32 res;
660:
661: res = (uae_u32)mmu_get_iword(addr, sz_long) << 16;
662: SAVE_EXCEPTION;
663: TRY(prb) {
664: res |= mmu_get_iword(addr + 2, sz_long);
665: RESTORE_EXCEPTION;
666: }
667: CATCH(prb) {
668: RESTORE_EXCEPTION;
669: misalignednotfirst(addr);
670: THROW_AGAIN(prb);
671: } ENDTRY
672: return res;
673: }
674:
675: static uae_u16 REGPARAM2 mmu_get_lrmw_word_unaligned(uaecptr addr)
676: {
677: uae_u16 res;
678:
679: res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, true, sz_word) << 8;
680: SAVE_EXCEPTION;
681: TRY(prb) {
682: res |= mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_word);
683: RESTORE_EXCEPTION;
684: }
685: CATCH(prb) {
686: RESTORE_EXCEPTION;
687: misalignednotfirst(addr);
688: THROW_AGAIN(prb);
689: } ENDTRY
690: return res;
691: }
692:
693: static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr)
694: {
695: uae_u32 res;
696:
697: if (likely(!(addr & 1))) {
698: res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, true, sz_long) << 16;
699: SAVE_EXCEPTION;
700: TRY(prb) {
701: res |= mmu_get_user_word(addr + 2, regs.s != 0, true, sz_long);
702: RESTORE_EXCEPTION;
703: }
704: CATCH(prb) {
705: RESTORE_EXCEPTION;
706: misalignednotfirst(addr);
707: THROW_AGAIN(prb);
708: } ENDTRY
709: } else {
710: res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, true, sz_long) << 8;
711: SAVE_EXCEPTION;
712: TRY(prb) {
713: res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_long)) << 8;
714: res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, true, sz_long)) << 8;
715: res |= mmu_get_user_byte(addr + 3, regs.s != 0, true, sz_long);
716: RESTORE_EXCEPTION;
717: }
718: CATCH(prb) {
719: RESTORE_EXCEPTION;
720: misalignednotfirst(addr);
721: THROW_AGAIN(prb);
722: } ENDTRY
723: }
724: return res;
725: }
726:
727: void REGPARAM2 mmu_put_long_unaligned(uaecptr addr, uae_u32 val)
728: {
729: SAVE_EXCEPTION;
730: TRY(prb) {
731: if (likely(!(addr & 1))) {
732: mmu_put_word(addr, val >> 16, sz_long);
733: mmu_put_word(addr + 2, val, sz_long);
734: } else {
735: mmu_put_byte(addr, val >> 24, sz_long);
736: mmu_put_byte(addr + 1, val >> 16, sz_long);
737: mmu_put_byte(addr + 2, val >> 8, sz_long);
738: mmu_put_byte(addr + 3, val, sz_long);
739: }
740: RESTORE_EXCEPTION;
741: }
742: CATCH(prb) {
743: RESTORE_EXCEPTION;
744: regs.wb3_data = val;
745: misalignednotfirstcheck(addr);
746: THROW_AGAIN(prb);
747: } ENDTRY
748: }
1.1.1.4 root 749:
1.1.1.5 root 750: void REGPARAM2 mmu_put_word_unaligned(uaecptr addr, uae_u16 val)
751: {
752: SAVE_EXCEPTION;
753: TRY(prb) {
754: mmu_put_byte(addr, val >> 8, sz_word);
755: mmu_put_byte(addr + 1, val, sz_word);
756: RESTORE_EXCEPTION;
757: }
758: CATCH(prb) {
759: RESTORE_EXCEPTION;
760: regs.wb3_data = val;
761: misalignednotfirstcheck(addr);
762: THROW_AGAIN(prb);
763: } ENDTRY
764: }
765:
766: uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
767: {
768: bool super = (regs.sfc & 4) != 0;
769: uae_u32 res;
770:
771: ismoves = true;
772: if (likely(!is_unaligned(addr, 4))) {
773: res = mmu_get_user_long(addr, super, false, sz_long);
774: } else {
775: if (likely(!(addr & 1))) {
776: res = (uae_u32)mmu_get_user_word(addr, super, false, sz_long) << 16;
777: SAVE_EXCEPTION;
778: TRY(prb) {
779: res |= mmu_get_user_word(addr + 2, super, false, sz_long);
780: RESTORE_EXCEPTION;
781: }
782: CATCH(prb) {
783: RESTORE_EXCEPTION;
784: misalignednotfirst(addr);
785: THROW_AGAIN(prb);
786: } ENDTRY
787: } else {
788: res = (uae_u32)mmu_get_user_byte(addr, super, false, sz_long) << 8;
789: SAVE_EXCEPTION;
790: TRY(prb) {
791: res = (res | mmu_get_user_byte(addr + 1, super, false, sz_long)) << 8;
792: res = (res | mmu_get_user_byte(addr + 2, super, false, sz_long)) << 8;
793: res |= mmu_get_user_byte(addr + 3, super, false, sz_long);
794: RESTORE_EXCEPTION;
795: }
796: CATCH(prb) {
797: RESTORE_EXCEPTION;
798: misalignednotfirst(addr);
799: THROW_AGAIN(prb);
800: } ENDTRY
801: }
802: }
803:
804: ismoves = false;
805: return res;
1.1.1.2 root 806: }
807:
808: uae_u16 REGPARAM2 sfc_get_word(uaecptr addr)
809: {
1.1.1.5 root 810: bool super = (regs.sfc & 4) != 0;
811: uae_u16 res;
812:
813: ismoves = true;
814: if (likely(!is_unaligned(addr, 2))) {
815: res = mmu_get_user_word(addr, super, false, sz_word);
816: } else {
817: res = (uae_u16)mmu_get_user_byte(addr, super, false, sz_word) << 8;
818: SAVE_EXCEPTION;
819: TRY(prb) {
820: res |= mmu_get_user_byte(addr + 1, super, false, sz_word);
821: RESTORE_EXCEPTION;
822: }
823: CATCH(prb) {
824: RESTORE_EXCEPTION;
825: misalignednotfirst(addr);
826: THROW_AGAIN(prb);
827: } ENDTRY
828: }
829: ismoves = false;
830: return res;
1.1.1.2 root 831: }
832:
833: uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr)
834: {
1.1.1.5 root 835: bool super = (regs.sfc & 4) != 0;
836: uae_u8 res;
837:
838: ismoves = true;
839: res = mmu_get_user_byte(addr, super, false, sz_byte);
840: ismoves = false;
841: return res;
1.1.1.2 root 842: }
843:
844: void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val)
845: {
1.1.1.5 root 846: bool super = (regs.dfc & 4) != 0;
847:
848: ismoves = true;
849: SAVE_EXCEPTION;
850: TRY(prb) {
851: if (likely(!is_unaligned(addr, 4))) {
852: mmu_put_user_long(addr, val, super, sz_long);
853: } else if (likely(!(addr & 1))) {
854: mmu_put_user_word(addr, val >> 16, super, sz_long);
855: mmu_put_user_word(addr + 2, val, super, sz_long);
856: } else {
857: mmu_put_user_byte(addr, val >> 24, super, sz_long);
858: mmu_put_user_byte(addr + 1, val >> 16, super, sz_long);
859: mmu_put_user_byte(addr + 2, val >> 8, super, sz_long);
860: mmu_put_user_byte(addr + 3, val, super, sz_long);
861: }
862: RESTORE_EXCEPTION;
863: }
864: CATCH(prb) {
865: RESTORE_EXCEPTION;
866: regs.wb3_data = val;
867: misalignednotfirstcheck(addr);
868: THROW_AGAIN(prb);
869: } ENDTRY
870: ismoves = false;
1.1.1.2 root 871: }
872:
873: void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val)
874: {
1.1.1.5 root 875: bool super = (regs.dfc & 4) != 0;
876:
877: ismoves = true;
878: SAVE_EXCEPTION;
879: TRY(prb) {
880: if (likely(!is_unaligned(addr, 2))) {
881: mmu_put_user_word(addr, val, super, sz_word);
882: } else {
883: mmu_put_user_byte(addr, val >> 8, super, sz_word);
884: mmu_put_user_byte(addr + 1, val, super, sz_word);
885: }
886: RESTORE_EXCEPTION;
887: }
888: CATCH(prb) {
889: RESTORE_EXCEPTION;
890: regs.wb3_data = val;
891: misalignednotfirstcheck(addr);
892: THROW_AGAIN(prb);
893: } ENDTRY
894: ismoves = false;
1.1.1.2 root 895: }
896:
897: void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val)
898: {
1.1.1.5 root 899: bool super = (regs.dfc & 4) != 0;
900:
901: ismoves = true;
902: SAVE_EXCEPTION;
903: TRY(prb) {
904: mmu_put_user_byte(addr, val, super, sz_byte);
905: RESTORE_EXCEPTION;
906: }
907: CATCH(prb) {
908: RESTORE_EXCEPTION;
909: regs.wb3_data = val;
910: THROW_AGAIN(prb);
911: } ENDTRY
912: ismoves = false;
1.1.1.4 root 913: }
914:
915:
1.1.1.2 root 916: void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra)
917: {
1.1.1.5 root 918: bool super = (regs.dfc & 4) != 0;
919: DUNUSED(extra);
920: if ((opcode & 0xFE0) == 0x0500) { // PFLUSH
921: bool glob;
922: int regno;
923: //D(didflush = 0);
924: uae_u32 addr;
925: /* PFLUSH */
926: regno = opcode & 7;
927: glob = (opcode & 8) != 0;
928:
929: if (opcode & 16) {
1.1.1.4 root 930: #if MMUINSDEBUG > 1
1.1.1.5 root 931: write_log(_T("pflusha(%u,%u) PC=%08x\n"), glob, regs.dfc, m68k_getpc ());
1.1.1.4 root 932: #endif
1.1.1.5 root 933: mmu_flush_atc_all(glob);
934: } else {
935: addr = m68k_areg(regs, regno);
1.1.1.4 root 936: #if MMUINSDEBUG > 1
1.1.1.5 root 937: write_log(_T("pflush(%u,%u,%x) PC=%08x\n"), glob, regs.dfc, addr, m68k_getpc ());
1.1.1.4 root 938: #endif
1.1.1.5 root 939: mmu_flush_atc(addr, super, glob);
940: }
941: flush_internals();
1.1.1.2 root 942: #ifdef USE_JIT
1.1.1.5 root 943: flush_icache(0);
1.1.1.2 root 944: #endif
1.1.1.5 root 945: } else if ((opcode & 0x0FD8) == 0x0548) { // PTEST (68040)
946: bool write;
947: int regno;
948: uae_u32 addr;
949:
950: regno = opcode & 7;
951: write = (opcode & 32) == 0;
952: addr = m68k_areg(regs, regno);
1.1.1.4 root 953: #if MMUINSDEBUG > 0
1.1.1.5 root 954: write_log(_T("PTEST%c (A%d) %08x DFC=%d\n"), write ? 'W' : 'R', regno, addr, regs.dfc);
1.1.1.4 root 955: #endif
1.1.1.5 root 956: mmu_flush_atc(addr, super, true);
957:
958: bool data = (regs.dfc & 3) != 2;
959: int ttr_match = mmu_match_ttr(addr,super,data);
960:
961: if (ttr_match != TTR_NO_MATCH) {
962: if (ttr_match == TTR_NO_WRITE && write) {
963: regs.mmusr = MMU_MMUSR_B;
964: } else {
965: regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
966: }
967: } else {
968: int way;
969: uae_u32 index;
970: uae_u32 tag = ((super ? 0x80000000 : 0x00000000) | (addr >> 1)) & mmu_tagmask;
971: if (mmu_pagesize_8k)
972: index=(addr & 0x0001E000)>>13;
973: else
974: index=(addr & 0x0000F000)>>12;
975:
976: for (way = 0; way < ATC_WAYS; way++) {
977: if (!mmu_atc_array[data][way][index].valid)
978: break;
979: }
980: if (way >= ATC_WAYS) {
981: way = way_random % ATC_WAYS;
982: }
983: regs.mmusr = mmu_fill_atc(addr, super, tag, write, &mmu_atc_array[data][way][index]);
984: }
1.1.1.4 root 985: #if MMUINSDEBUG > 0
1.1.1.5 root 986: write_log(_T("PTEST result: mmusr %08x\n"), regs.mmusr);
1.1.1.4 root 987: #endif
1.1.1.5 root 988: }
989: #if 0
990: else if ((opcode & 0xFFB8) == 0xF588) { // PLPA (68060)
991: int write = (opcode & 0x40) == 0;
992: int regno = opcode & 7;
993: uae_u32 addr = m68k_areg (regs, regno);
994: bool data = (regs.dfc & 3) != 2;
995:
1.1.1.4 root 996: #if MMUINSDEBUG > 0
1.1.1.5 root 997: write_log(_T("PLPA%c param: %08x\n"), write ? 'W' : 'R', addr);
1.1.1.4 root 998: #endif
1.1.1.5 root 999: if (mmu_match_ttr_write(addr,super,data,0,1,write)==TTR_NO_MATCH) {
1000: m68k_areg (regs, regno) = mmu_translate(addr, 0, super, data, write, 1);
1001: }
1.1.1.4 root 1002: #if MMUINSDEBUG > 0
1.1.1.5 root 1003: write_log(_T("PLPA%c result: %08x\n"), write ? 'W' : 'R', m68k_areg (regs, regno));
1004: #endif
1005: }
1.1.1.4 root 1006: #endif
1.1.1.5 root 1007: else {
1008: op_illg (opcode);
1009: }
1.1.1.2 root 1010: }
1011:
1012: // fixme : global parameter?
1013: void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global)
1014: {
1.1.1.5 root 1015: int way,type,index;
1016:
1017: uaecptr tag = ((super ? 0x80000000 : 0) | (addr >> 1)) & mmu_tagmask;
1018: if (mmu_pagesize_8k)
1019: index=(addr & 0x0001E000)>>13;
1020: else
1021: index=(addr & 0x0000F000)>>12;
1022: for (type=0;type<ATC_TYPE;type++) {
1023: for (way=0;way<ATC_WAYS;way++) {
1024: if (!global && mmu_atc_array[type][way][index].status&MMU_MMUSR_G)
1025: continue;
1026: // if we have this
1027: if ((tag == mmu_atc_array[type][way][index].tag) && (mmu_atc_array[type][way][index].valid)) {
1028: mmu_atc_array[type][way][index].valid=false;
1029: }
1030: }
1031: }
1.1.1.2 root 1032: }
1033:
1034: void REGPARAM2 mmu_flush_atc_all(bool global)
1035: {
1.1.1.5 root 1036: unsigned int way,slot,type;
1037: for (type=0;type<ATC_TYPE;type++) {
1038: for (way=0;way<ATC_WAYS;way++) {
1039: for (slot=0;slot<ATC_SLOTS;slot++) {
1040: if (!global && mmu_atc_array[type][way][slot].status&MMU_MMUSR_G)
1041: continue;
1042: mmu_atc_array[type][way][slot].valid=false;
1043: }
1044: }
1045: }
1.1.1.2 root 1046: }
1047:
1.1.1.5 root 1048: void REGPARAM2 mmu_set_funcs(void)
1.1.1.2 root 1049: {
1050: }
1051:
1.1.1.5 root 1052: void REGPARAM2 mmu_reset(void)
1053: {
1054: mmu_flush_atc_all(true);
1055: mmu_set_funcs();
1056: }
1.1.1.2 root 1057:
1058: void REGPARAM2 mmu_set_tc(uae_u16 tc)
1059: {
1.1.1.5 root 1060: regs.mmu_enabled = (tc & 0x8000) != 0;
1061: mmu_pagesize_8k = (tc & 0x4000) != 0;
1062: mmu_tagmask = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000;
1063: mmu_pagemask = mmu_pagesize_8k ? 0x00001FFF : 0x00000FFF;
1064: mmu_pagemaski = ~mmu_pagemask;
1065: regs.mmu_page_size = mmu_pagesize_8k ? 8192 : 4096;
1066:
1067: mmu_flush_atc_all(true);
1068:
1069: write_log(_T("%d MMU: enabled=%d page8k=%d PC=%08x\n"), currprefs.mmu_model, regs.mmu_enabled, mmu_pagesize_8k, m68k_getpc());
1070: #if MMUDUMP
1071: if (regs.mmu_enabled)
1072: mmu_dump_tables();
1073: #endif
1.1.1.2 root 1074: }
1075:
1076: void REGPARAM2 mmu_set_super(bool super)
1077: {
1.1.1.5 root 1078: mmu_is_super = super ? 0x80000000 : 0;
1.1.1.4 root 1079: }
1080:
1081: void m68k_do_rte_mmu040 (uaecptr a7)
1082: {
1.1.1.5 root 1083: uae_u16 ssr = get_word_mmu040 (a7 + 8 + 4);
1084: if (ssr & MMU_SSW_CT) {
1085: uaecptr src_a7 = a7 + 8 - 8;
1086: uaecptr dst_a7 = a7 + 8 + 52;
1087: put_word_mmu040 (dst_a7 + 0, get_word_mmu040 (src_a7 + 0));
1088: put_long_mmu040 (dst_a7 + 2, get_long_mmu040 (src_a7 + 2));
1089: // skip this word
1090: put_long_mmu040 (dst_a7 + 8, get_long_mmu040 (src_a7 + 8));
1091: }
1092: if (ssr & MMU_SSW_CM) {
1093: mmu040_movem = 1;
1094: mmu040_movem_ea = get_long_mmu040 (a7 + 8);
1.1.1.4 root 1095: #if MMUDEBUGMISC > 0
1.1.1.5 root 1096: write_log (_T("MMU restarted MOVEM EA=%08X\n"), mmu040_movem_ea);
1.1.1.4 root 1097: #endif
1.1.1.5 root 1098: }
1.1.1.4 root 1099: }
1100:
1101: void m68k_do_rte_mmu060 (uaecptr a7)
1102: {
1103: #if 0
1.1.1.5 root 1104: mmu060_state = 2;
1.1.1.4 root 1105: #endif
1106: }
1107:
1108: void flush_mmu040 (uaecptr addr, int n)
1109: {
1110: }
1111: void m68k_do_rts_mmu040 (void)
1112: {
1.1.1.5 root 1113: uaecptr stack = m68k_areg (regs, 7);
1114: uaecptr newpc = get_long_mmu040 (stack);
1115: m68k_areg (regs, 7) += 4;
1116: m68k_setpc (newpc);
1.1.1.4 root 1117: }
1118: void m68k_do_bsr_mmu040 (uaecptr oldpc, uae_s32 offset)
1119: {
1.1.1.5 root 1120: uaecptr newstack = m68k_areg (regs, 7) - 4;
1121: put_long_mmu040 (newstack, oldpc);
1122: m68k_areg (regs, 7) -= 4;
1123: m68k_incpci (offset);
1.1.1.4 root 1124: }
1125: void uae_mmu_put_lrmw (uaecptr addr, uae_u32 v, int size, int type)
1126: {
1.1.1.5 root 1127: locked_rmw_cycle = true;
1128: if (size == sz_byte) {
1129: mmu_put_byte(addr, v, sz_byte);
1130: } else if (size == sz_word) {
1131: if (unlikely(is_unaligned(addr, 2))) {
1132: mmu_put_word_unaligned(addr, v);
1133: } else {
1134: mmu_put_word(addr, v, sz_word);
1135: }
1136: } else {
1137: if (unlikely(is_unaligned(addr, 4)))
1138: mmu_put_long_unaligned(addr, v);
1139: else
1140: mmu_put_long(addr, v, sz_long);
1141: }
1142: locked_rmw_cycle = false;
1.1.1.4 root 1143: }
1144: uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type)
1145: {
1.1.1.5 root 1146: uae_u32 v;
1147: locked_rmw_cycle = true;
1148: if (size == sz_byte) {
1149: v = mmu_get_user_byte(addr, regs.s != 0, true, sz_byte);
1150: } else if (size == sz_word) {
1151: if (unlikely(is_unaligned(addr, 2))) {
1152: v = mmu_get_lrmw_word_unaligned(addr);
1153: } else {
1154: v = mmu_get_user_word(addr, regs.s != 0, true, sz_word);
1155: }
1156: } else {
1157: if (unlikely(is_unaligned(addr, 4)))
1158: v = mmu_get_lrmw_long_unaligned(addr);
1159: else
1160: v = mmu_get_user_long(addr, regs.s != 0, true, sz_long);
1161: }
1162: locked_rmw_cycle = false;
1163: return v;
1.1.1.4 root 1164: }
1165:
1166:
1167: #ifndef __cplusplus
1.1.1.6 ! root 1168: sigjmp_buf __exbuf;
1.1.1.2 root 1169: int __exvalue;
1170: #define MAX_TRY_STACK 256
1171: static int s_try_stack_size=0;
1.1.1.6 ! root 1172: static sigjmp_buf s_try_stack[MAX_TRY_STACK];
! 1173: sigjmp_buf* __poptry(void) {
1.1.1.5 root 1174: if (s_try_stack_size>0) {
1.1.1.3 root 1175: s_try_stack_size--;
1176: if (s_try_stack_size == 0)
1177: return NULL;
1.1.1.6 ! root 1178: memcpy(&__exbuf,&s_try_stack[s_try_stack_size-1],sizeof(sigjmp_buf));
1.1.1.5 root 1179: // fprintf(stderr,"pop %d jmpbuf=%08x\n",s_try_stack_size, s_try_stack[s_try_stack_size][0]);
1.1.1.3 root 1180: return &s_try_stack[s_try_stack_size-1];
1181: }
1.1.1.5 root 1182: else {
1183: fprintf(stderr,"try stack underflow...\n");
1184: // return (NULL);
1185: abort();
1186: }
1.1.1.2 root 1187: }
1.1.1.6 ! root 1188: void __pushtry(sigjmp_buf* j) {
1.1.1.5 root 1189: if (s_try_stack_size<MAX_TRY_STACK) {
1190: // fprintf(stderr,"push %d jmpbuf=%08x\n",s_try_stack_size, (*j)[0]);
1.1.1.6 ! root 1191: memcpy(&s_try_stack[s_try_stack_size],j,sizeof(sigjmp_buf));
1.1.1.5 root 1192: s_try_stack_size++;
1193: } else {
1194: fprintf(stderr,"try stack overflow...\n");
1195: abort();
1196: }
1.1.1.2 root 1197: }
1198: int __is_catched(void) {return (s_try_stack_size>0); }
1.1.1.4 root 1199: #endif
1200:
1.1.1.2 root 1201: #else
1202:
1203: void mmu_op(uae_u32 opcode, uae_u16 /*extra*/)
1204: {
1.1.1.5 root 1205: if ((opcode & 0xFE0) == 0x0500) {
1206: /* PFLUSH instruction */
1207: flush_internals();
1208: } else if ((opcode & 0x0FD8) == 0x548) {
1209: /* PTEST instruction */
1210: } else
1211: op_illg(opcode);
1.1.1.2 root 1212: }
1213:
1214: #endif
1215:
1.1.1.5 root 1216:
1.1.1.2 root 1217: /*
1.1.1.5 root 1218: vim:ts=4:sw=4:
1219: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.