|
|
1.1.1.3 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.3 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.3 root 34: #include "options_cpu.h"
35: #include "memory.h"
36: #include "newcpu.h"
37: #include "cpummu.h"
1.1.1.5 ! root 38: #include "debug.h"
! 39:
! 40: #define MMUDUMP 0
1.1.1.3 root 41:
42: #define DBG_MMU_VERBOSE 1
43: #define DBG_MMU_SANITY 1
1.1.1.5 ! root 44: #if 0
1.1.1.3 root 45: #define write_log printf
1.1.1.5 ! root 46: #endif
1.1.1.3 root 47:
48: #ifdef FULLMMU
49:
1.1.1.5 ! root 50: uae_u32 mmu_is_super;
! 51: uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski;
! 52: struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS];
! 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;
! 61: int mmu_atc_ways;
! 62:
! 63: int mmu040_movem;
! 64: uaecptr mmu040_movem_ea;
! 65: uae_u32 mmu040_move16[4];
1.1.1.3 root 66:
67: static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr)
68: {
1.1.1.5 ! root 69: #if MMUDEBUG > 0 // ifdef WINUAE_FOR_HATARI
1.1.1.3 root 70: DUNUSED(label);
71: uae_u32 from_addr, to_addr;
72:
73: from_addr = ttr & MMU_TTR_LOGICAL_BASE;
74: to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8;
75:
1.1.1.5 ! root 76: write_log(_T("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d\n"),
1.1.1.3 root 77: label, ttr,
78: from_addr, to_addr,
79: ttr & MMU_TTR_BIT_ENABLED ? 1 : 0,
80: (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT,
81: ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0,
82: (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT
83: );
1.1.1.5 ! root 84: #endif
1.1.1.3 root 85: }
86:
87: void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode)
88: {
89: uae_u32 * ttr;
90: uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0;
91: uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1;
92:
93: if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0)
94: ttr = ttr1;
95: else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0)
96: ttr = ttr0;
97: else
98: return;
99:
100: *ttr = baseaddr & MMU_TTR_LOGICAL_BASE;
101: *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8;
102: *ttr |= MMU_TTR_BIT_ENABLED;
103:
1.1.1.5 ! root 104: #if MMUDEBUG > 0
! 105: write_log(_T("MMU: map transparent mapping of %08x\n"), *ttr);
! 106: #endif
1.1.1.3 root 107: }
108:
1.1.1.5 ! root 109: void mmu_tt_modified (void)
1.1.1.3 root 110: {
1.1.1.5 ! root 111: mmu_ttr_enabled = ((regs.dtt0 | regs.dtt1 | regs.itt0 | regs.itt1) & MMU_TTR_BIT_ENABLED) != 0;
! 112: }
1.1.1.3 root 113:
114:
1.1.1.5 ! root 115: #if MMUDUMP
1.1.1.3 root 116:
1.1.1.5 ! root 117: /* This dump output makes much more sense than old one */
1.1.1.3 root 118:
1.1.1.5 ! root 119: #define LEVELA_SIZE 7
! 120: #define LEVELB_SIZE 7
! 121: #define LEVELC_SIZE 6
! 122: #define PAGE_SIZE 12 // = 1 << 12 = 4096
! 123:
! 124: #define LEVELA_VAL(x) ((((uae_u32)(x)) >> (32 - (LEVELA_SIZE ))) & ((1 << LEVELA_SIZE) - 1))
! 125: #define LEVELB_VAL(x) ((((uae_u32)(x)) >> (32 - (LEVELA_SIZE + LEVELB_SIZE ))) & ((1 << LEVELB_SIZE) - 1))
! 126: #define LEVELC_VAL(x) ((((uae_u32)(x)) >> (32 - (LEVELA_SIZE + LEVELB_SIZE + LEVELC_SIZE))) & ((1 << LEVELC_SIZE) - 1))
1.1.1.3 root 127:
1.1.1.5 ! root 128: #define LEVELA(root, x) (get_long(root + LEVELA_VAL(x) * 4))
! 129: #define LEVELB(a, x) (get_long((((uae_u32)a) & ~((1 << (LEVELB_SIZE + 2)) - 1)) + LEVELB_VAL(x) * 4))
! 130: #define LEVELC(b, x) (get_long((((uae_u32)b) & ~((1 << (LEVELC_SIZE + 2)) - 1)) + LEVELC_VAL(x) * 4))
! 131:
! 132: #define ISINVALID(x) ((((ULONG)x) & 3) == 0)
! 133:
! 134: static uae_u32 getdesc(uae_u32 root, uae_u32 addr)
1.1.1.3 root 135: {
1.1.1.5 ! root 136: ULONG desc;
1.1.1.3 root 137:
1.1.1.5 ! root 138: desc = LEVELA(root, addr);
! 139: if (ISINVALID(desc))
! 140: return desc;
! 141: desc = LEVELB(desc, addr);
! 142: if (ISINVALID(desc))
! 143: return desc;
! 144: desc = LEVELC(desc, addr);
! 145: return desc;
1.1.1.3 root 146: }
1.1.1.5 ! root 147: static void mmu_dump_table(const char * label, uaecptr root_ptr)
! 148: {
! 149: ULONG i;
! 150: ULONG startaddr;
! 151: ULONG odesc;
! 152: ULONG totalpages;
! 153: ULONG pagemask = (1 << PAGE_SIZE) - 1;
! 154:
! 155: console_out_f(_T("MMU dump start. Root = %08x\n"), root_ptr);
! 156: totalpages = 1 << (32 - PAGE_SIZE);
! 157: startaddr = 0;
! 158: odesc = getdesc(root_ptr, startaddr);
! 159: for (i = 0; i <= totalpages; i++) {
! 160: ULONG addr = i << PAGE_SIZE;
! 161: ULONG desc = 0;
! 162: if (i < totalpages)
! 163: desc = getdesc(root_ptr, addr);
! 164: if ((desc & pagemask) != (odesc & pagemask) || i == totalpages) {
! 165: uae_u8 cm, sp;
! 166: cm = (odesc >> 5) & 3;
! 167: sp = (odesc >> 7) & 1;
! 168: console_out_f(_T("%08x - %08x: %08x WP=%d S=%d CM=%d (%08x)\n"),
! 169: startaddr, addr - 1, odesc & ~((1 << PAGE_SIZE) - 1),
! 170: (odesc & 4) ? 1 : 0, sp, cm, odesc);
! 171: startaddr = addr;
! 172: odesc = desc;
! 173: }
! 174: }
! 175: console_out_f(_T("MMU dump end\n"));
! 176: }
1.1.1.3 root 177:
1.1.1.5 ! root 178: #else
1.1.1.3 root 179: /* {{{ mmu_dump_table */
180: static void mmu_dump_table(const char * label, uaecptr root_ptr)
181: {
182: DUNUSED(label);
183: const int ROOT_TABLE_SIZE = 128,
184: PTR_TABLE_SIZE = 128,
185: PAGE_TABLE_SIZE = 64,
186: ROOT_INDEX_SHIFT = 25,
187: PTR_INDEX_SHIFT = 18;
188: // const int PAGE_INDEX_SHIFT = 12;
189: int root_idx, ptr_idx, page_idx;
190: uae_u32 root_des, ptr_des, page_des;
191: uaecptr ptr_des_addr, page_addr,
192: root_log, ptr_log, page_log;
193:
1.1.1.5 ! root 194: console_out_f(_T("%s: root=%x\n"), label, root_ptr);
1.1.1.3 root 195:
196: for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) {
197: root_des = phys_get_long(root_ptr + root_idx);
198:
199: if ((root_des & 2) == 0)
200: continue; /* invalid */
201:
1.1.1.5 ! root 202: console_out_f(_T("ROOT: %03d U=%d W=%d UDT=%02d\n"), root_idx,
1.1.1.3 root 203: root_des & 8 ? 1 : 0,
204: root_des & 4 ? 1 : 0,
205: root_des & 3
206: );
207:
208: root_log = root_idx << ROOT_INDEX_SHIFT;
209:
210: ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK;
211:
212: for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) {
213: struct {
214: uaecptr log, phys;
215: int start_idx, n_pages; /* number of pages covered by this entry */
216: uae_u32 match;
217: } page_info[PAGE_TABLE_SIZE];
218: int n_pages_used;
219:
220: ptr_des = phys_get_long(ptr_des_addr + ptr_idx);
221: ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT);
222:
223: if ((ptr_des & 2) == 0)
224: continue; /* invalid */
225:
1.1.1.5 ! root 226: page_addr = ptr_des & (mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4);
1.1.1.3 root 227:
228: n_pages_used = -1;
229: for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) {
230:
231: page_des = phys_get_long(page_addr + page_idx);
232: page_log = ptr_log | (page_idx << 2); // ??? PAGE_INDEX_SHIFT
233:
234: switch (page_des & 3) {
235: case 0: /* invalid */
236: continue;
237: case 1: case 3: /* resident */
238: case 2: /* indirect */
239: if (n_pages_used == -1 || page_info[n_pages_used].match != page_des) {
240: /* use the next entry */
241: n_pages_used++;
242:
243: page_info[n_pages_used].match = page_des;
244: page_info[n_pages_used].n_pages = 1;
245: page_info[n_pages_used].start_idx = page_idx;
246: page_info[n_pages_used].log = page_log;
247: } else {
248: page_info[n_pages_used].n_pages++;
249: }
250: break;
251: }
252: }
253:
254: if (n_pages_used == -1)
255: continue;
256:
1.1.1.5 ! root 257: console_out_f(_T(" PTR: %03d U=%d W=%d UDT=%02d\n"), ptr_idx,
1.1.1.3 root 258: ptr_des & 8 ? 1 : 0,
259: ptr_des & 4 ? 1 : 0,
260: ptr_des & 3
261: );
262:
263:
264: for (page_idx = 0; page_idx <= n_pages_used; page_idx++) {
265: page_des = page_info[page_idx].match;
266:
267: if ((page_des & MMU_PDT_MASK) == 2) {
1.1.1.5 ! root 268: console_out_f(_T(" PAGE: %03d-%03d log=%08x INDIRECT --> addr=%08x\n"),
1.1.1.3 root 269: page_info[page_idx].start_idx,
270: page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
271: page_info[page_idx].log,
272: page_des & MMU_PAGE_INDIRECT_MASK
273: );
274:
275: } else {
1.1.1.5 ! root 276: 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"),
1.1.1.3 root 277: page_info[page_idx].start_idx,
278: page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
279: page_info[page_idx].log,
1.1.1.5 ! root 280: page_des & (mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4),
! 281: (page_des & (mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4)) >> MMU_PAGE_UR_SHIFT,
1.1.1.3 root 282: page_des & MMU_DES_GLOBAL ? 1 : 0,
283: (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT,
284: page_des & MMU_DES_SUPER ? 1 : 0,
285: (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT,
286: page_des & MMU_DES_MODIFIED ? 1 : 0,
287: page_des & MMU_DES_USED ? 1 : 0,
288: page_des & MMU_DES_WP ? 1 : 0
289: );
290: }
291: }
292: }
293:
294: }
295: }
296: /* }}} */
297: #endif
298:
299: /* {{{ mmu_dump_atc */
1.1.1.5 ! root 300: void mmu_dump_atc(void)
1.1.1.3 root 301: {
1.1.1.5 ! root 302:
1.1.1.3 root 303: }
304: /* }}} */
305:
306: /* {{{ mmu_dump_tables */
307: void mmu_dump_tables(void)
308: {
1.1.1.5 ! root 309: write_log(_T("URP: %08x SRP: %08x MMUSR: %x TC: %x\n"), regs.urp, regs.srp, regs.mmusr, regs.tcr);
! 310: mmu_dump_ttr(_T("DTT0"), regs.dtt0);
! 311: mmu_dump_ttr(_T("DTT1"), regs.dtt1);
! 312: mmu_dump_ttr(_T("ITT0"), regs.itt0);
! 313: mmu_dump_ttr(_T("ITT1"), regs.itt1);
1.1.1.3 root 314: mmu_dump_atc();
1.1.1.5 ! root 315: #if MMUDUMP
1.1.1.3 root 316: mmu_dump_table("SRP", regs.srp);
317: #endif
318: }
319: /* }}} */
320:
1.1.1.5 ! root 321: static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, bool super, bool write, uae_u32 *status);
1.1.1.3 root 322:
323: static ALWAYS_INLINE int mmu_get_fc(bool super, bool data)
324: {
325: return (super ? 4 : 0) | (data ? 1 : 2);
326: }
327:
1.1.1.5 ! root 328: void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 status, bool nonmmu)
1.1.1.3 root 329: {
1.1.1.5 ! root 330: if (currprefs.mmu_model == 68040) {
! 331: uae_u16 ssw = 0;
1.1.1.3 root 332:
1.1.1.5 ! root 333: if (ismoves) {
! 334: // MOVES special behavior
! 335: int fc2 = write ? regs.dfc : regs.sfc;
! 336: if (fc2 == 0 || fc2 == 3 || fc2 == 4 || fc2 == 7)
! 337: ssw |= MMU_SSW_TT1;
! 338: if ((fc2 & 3) != 3)
! 339: fc2 &= ~2;
! 340: #if MMUDEBUGMISC > 0
! 341: write_log (_T("040 MMU MOVES fc=%d -> %d\n"), fc, fc2);
! 342: #endif
! 343: fc = fc2;
! 344: }
1.1.1.3 root 345:
1.1.1.5 ! root 346: ssw |= fc & MMU_SSW_TM; /* TM = FC */
1.1.1.3 root 347:
1.1.1.5 ! root 348: switch (size) {
! 349: case sz_byte:
! 350: ssw |= MMU_SSW_SIZE_B;
! 351: break;
! 352: case sz_word:
! 353: ssw |= MMU_SSW_SIZE_W;
! 354: break;
! 355: case sz_long:
! 356: ssw |= MMU_SSW_SIZE_L;
! 357: break;
! 358: }
! 359:
! 360: regs.wb3_status = write ? 0x80 | (ssw & 0x7f) : 0;
! 361: regs.wb2_status = 0;
! 362: if (!write)
! 363: ssw |= MMU_SSW_RW;
! 364:
! 365: if (size == 16) { // MOVE16
! 366: ssw |= MMU_SSW_SIZE_CL;
! 367: ssw |= MMU_SSW_TT0;
! 368: regs.mmu_effective_addr &= ~15;
! 369: if (write) {
! 370: // clear normal writeback if MOVE16 write
! 371: regs.wb3_status &= ~0x80;
! 372: // wb2 = cacheline size writeback
! 373: regs.wb2_status = 0x80 | MMU_SSW_SIZE_CL | (ssw & 0x1f);
! 374: regs.wb2_address = regs.mmu_effective_addr;
! 375: write_log (_T("040 MMU MOVE16 WRITE FAULT!\n"));
! 376: }
! 377: }
! 378:
! 379: if (mmu040_movem) {
! 380: ssw |= MMU_SSW_CM;
! 381: regs.mmu_effective_addr = mmu040_movem_ea;
! 382: mmu040_movem = 0;
! 383: #if MMUDEBUGMISC > 0
! 384: write_log (_T("040 MMU_SSW_CM EA=%08X\n"), mmu040_movem_ea);
! 385: #endif
! 386: }
! 387: if (locked_rmw_cycle) {
! 388: ssw |= MMU_SSW_LK;
! 389: ssw &= ~MMU_SSW_RW;
! 390: locked_rmw_cycle = false;
! 391: #if MMUDEBUGMISC > 0
! 392: write_log (_T("040 MMU_SSW_LK!\n"));
! 393: #endif
! 394: }
! 395:
! 396: if (!nonmmu)
! 397: ssw |= MMU_SSW_ATC;
! 398: regs.mmu_ssw = ssw;
1.1.1.3 root 399:
1.1.1.5 ! root 400: #if MMUDEBUG > 0
! 401: 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);
! 402: #endif
! 403: } else {
! 404: uae_u32 fslw = 0;
1.1.1.3 root 405:
1.1.1.5 ! root 406: fslw |= write ? MMU_FSLW_W : MMU_FSLW_R;
! 407: fslw |= fc << 16; /* MMU_FSLW_TM */
1.1.1.3 root 408:
1.1.1.5 ! root 409: switch (size) {
! 410: case sz_byte:
! 411: fslw |= MMU_FSLW_SIZE_B;
! 412: break;
! 413: case sz_word:
! 414: fslw |= MMU_FSLW_SIZE_W;
! 415: break;
! 416: case sz_long:
! 417: fslw |= MMU_FSLW_SIZE_L;
! 418: break;
! 419: case 16: // MOVE16
! 420: addr &= ~15;
! 421: fslw |= MMU_FSLW_SIZE_D;
! 422: fslw |= MMU_FSLW_TT_16;
! 423: break;
! 424: }
! 425: if ((fc & 3) == 2) {
! 426: // instruction faults always point to opcode address
! 427: #if MMUDEBUGMISC > 0
! 428: write_log(_T("INS FAULT %08x %08x %d\n"), addr, regs.instruction_pc, mmu060_state);
! 429: #endif
! 430: addr = regs.instruction_pc;
! 431: if (mmu060_state == 0) {
! 432: fslw |= MMU_FSLW_IO; // opword fetch
! 433: } else {
! 434: fslw |= MMU_FSLW_IO | MMU_FSLW_MA; // extension word
! 435: }
! 436: }
! 437: if (rmw) {
! 438: fslw |= MMU_FSLW_W | MMU_FSLW_R;
! 439: }
! 440: if (locked_rmw_cycle) {
! 441: fslw |= MMU_FSLW_LK;
! 442: locked_rmw_cycle = false;
! 443: write_log (_T("060 MMU_FSLW_LK!\n"));
! 444: }
! 445: fslw |= status;
! 446: regs.mmu_fslw = fslw;
! 447:
! 448: #if MMUDEBUG > 0
! 449: write_log(_T("BF: fc=%d w=%d s=%d log=%08x ssw=%08x rmw=%d PC=%08x INS=%04X\n"), fc, write, 1 << size, addr, fslw, rmw, m68k_getpc(), mmu_opcode);
! 450: #endif
! 451:
! 452: }
! 453:
! 454: regs.mmu_fault_addr = addr;
! 455:
! 456: #if 0
! 457: if (m68k_getpc () == 0x0004B0AC) {
! 458: write_log (_T("*"));
! 459: #if 0
! 460: extern void activate_debugger(void);
! 461: activate_debugger ();
! 462: #endif
! 463: }
! 464: #endif
1.1.1.3 root 465: THROW(2);
466: }
467:
1.1.1.5 ! root 468: void mmu_bus_error_ttr_write_fault(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw)
! 469: {
! 470: uae_u32 status = 0;
! 471:
! 472: if (currprefs.mmu_model == 68060) {
! 473: status |= MMU_FSLW_TTR;
! 474: }
! 475: regs.wb3_data = val;
! 476: mmu_bus_error(addr, mmu_get_fc (super, data), true, size, false, status, false);
! 477: }
! 478:
! 479:
1.1.1.3 root 480: /*
481: * Update the atc line for a given address by doing a mmu lookup.
482: */
1.1.1.5 ! root 483: static uaecptr mmu_fill_atc(uaecptr addr, bool super, bool data, bool write, struct mmu_atc_line *l, uae_u32 *status)
1.1.1.3 root 484: {
485: uae_u32 desc;
486:
1.1.1.5 ! root 487: *status = 0;
1.1.1.3 root 488: SAVE_EXCEPTION;
489: TRY(prb) {
1.1.1.5 ! root 490: desc = mmu_lookup_pagetable(addr, super, write, status);
! 491: #if MMUDEBUG > 2
! 492: write_log(_T("translate: %x,%u,%u,%u -> %x\n"), addr, super, write, data, desc);
1.1.1.3 root 493: #endif
494: RESTORE_EXCEPTION;
495: }
496: CATCH(prb) {
497: RESTORE_EXCEPTION;
498: /* bus error during table search */
499: desc = 0;
1.1.1.5 ! root 500: *status = MMU_FSLW_TWE;
! 501: // goto fail;
1.1.1.3 root 502: } ENDTRY
1.1.1.5 ! root 503: if ((desc & 1) && (!super && desc & MMU_MMUSR_S)) {
! 504: *status |= MMU_FSLW_SP;
! 505: #if MMUDEBUG > 1
! 506: write_log (_T("MMU: supervisor protected %x\n"), addr);
! 507: #endif
! 508: l->valid = 0;
! 509: l->global = 0;
! 510: } else if ((desc & 1) == 0) {
! 511: l->valid = 0;
1.1.1.3 root 512: l->global = 0;
513: } else {
1.1.1.5 ! root 514: l->valid = 1;
! 515: l->phys = desc & mmu_pagemaski;
1.1.1.3 root 516: l->global = (desc & MMU_MMUSR_G) != 0;
517: l->modified = (desc & MMU_MMUSR_M) != 0;
518: l->write_protect = (desc & MMU_MMUSR_W) != 0;
519: }
520:
521: return desc;
522: }
523:
1.1.1.5 ! root 524: static ALWAYS_INLINE bool mmu_fill_atc_try(uaecptr addr, bool super, bool data, bool write, struct mmu_atc_line *l1, uae_u32 *status)
1.1.1.3 root 525: {
1.1.1.5 ! root 526: mmu_fill_atc(addr,super,data,write,l1, status);
! 527: if (!(l1->valid)) {
! 528: #if MMUDEBUG > 2
! 529: write_log(_T("MMU: non-resident page (%x,%x)!\n"), addr, regs.pc);
! 530: #endif
1.1.1.3 root 531: goto fail;
532: }
533: if (write) {
1.1.1.5 ! root 534: if (l1->write_protect) {
! 535: *status |= MMU_FSLW_WP;
! 536: #if MMUDEBUG > 0
! 537: write_log(_T("MMU: write protected %x by atc \n"), addr);
! 538: #endif
! 539: mmu_dump_atc();
1.1.1.3 root 540: goto fail;
541: }
542:
543: }
544: return true;
545:
546: fail:
547: return false;
548: }
549:
550: uaecptr REGPARAM2 mmu_translate(uaecptr addr, bool super, bool data, bool write)
551: {
552: struct mmu_atc_line *l;
1.1.1.5 ! root 553: uae_u32 status = 0;
1.1.1.3 root 554:
1.1.1.5 ! root 555: // this should return a miss but choose a valid line
! 556: mmu_user_lookup(addr, super, data, write, &l);
! 557:
! 558: mmu_fill_atc(addr, super, data, write, l, &status);
! 559: if (!l->valid || (write && l->write_protect)) {
! 560: #if MMUDEBUG > 2
! 561: write_log(_T("[MMU] mmu_translate error"));
! 562: #endif
! 563: mmu_bus_error(addr, mmu_get_fc(super, data), write, 0, false, status, false);
! 564: return 0;
! 565: }
! 566:
! 567: return l->phys | (addr & mmu_pagemask);
1.1.1.3 root 568:
569: }
570:
571: /*
572: * Lookup the address by walking the page table and updating
573: * the page descriptors accordingly. Returns the found descriptor
574: * or produces a bus error.
575: */
1.1.1.5 ! root 576: static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, bool super, bool write, uae_u32 *status)
1.1.1.3 root 577: {
578: uae_u32 desc, desc_addr, wp;
579: int i;
580:
581: wp = 0;
582: desc = super ? regs.srp : regs.urp;
583:
584: /* fetch root table descriptor */
585: i = (addr >> 23) & 0x1fc;
586: desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
587: desc = phys_get_long(desc_addr);
588: if ((desc & 2) == 0) {
1.1.1.5 ! root 589: #if MMUDEBUG > 1
! 590: write_log(_T("MMU: invalid root descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"),
! 591: addr, desc_addr, desc);
! 592: #endif
! 593: *status |= MMU_FSLW_PTA;
1.1.1.3 root 594: return 0;
595: }
596:
597: wp |= desc;
598: if ((desc & MMU_DES_USED) == 0)
599: phys_put_long(desc_addr, desc | MMU_DES_USED);
600:
601: /* fetch pointer table descriptor */
602: i = (addr >> 16) & 0x1fc;
603: desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
604: desc = phys_get_long(desc_addr);
605: if ((desc & 2) == 0) {
1.1.1.5 ! root 606: #if MMUDEBUG > 1
! 607: write_log(_T("MMU: invalid ptr descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"),
! 608: addr, desc_addr, desc);
! 609: #endif
! 610: *status |= MMU_FSLW_PTB;
1.1.1.3 root 611: return 0;
612: }
613: wp |= desc;
614: if ((desc & MMU_DES_USED) == 0)
615: phys_put_long(desc_addr, desc | MMU_DES_USED);
616:
617: /* fetch page table descriptor */
1.1.1.5 ! root 618: if (mmu_pagesize_8k) {
1.1.1.3 root 619: i = (addr >> 11) & 0x7c;
1.1.1.5 ! root 620: desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) + i;
1.1.1.3 root 621: } else {
622: i = (addr >> 10) & 0xfc;
1.1.1.5 ! root 623: desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) + i;
1.1.1.3 root 624: }
625:
626: desc = phys_get_long(desc_addr);
627: if ((desc & 3) == 2) {
628: /* indirect */
629: desc_addr = desc & MMU_PAGE_INDIRECT_MASK;
630: desc = phys_get_long(desc_addr);
631: }
632: if ((desc & 1) == 0) {
1.1.1.5 ! root 633: #if MMUDEBUG > 2
! 634: write_log(_T("MMU: invalid page descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr);
! 635: #endif
! 636: if ((desc & 3) == 2) {
! 637: *status |= MMU_FSLW_IL;
! 638: #if MMUDEBUG > 1
! 639: write_log(_T("MMU: double indirect descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr);
! 640: #endif
! 641: } else {
! 642: *status |= MMU_FSLW_PF;
! 643: }
1.1.1.3 root 644: return desc;
645: }
646:
647: desc |= wp & MMU_DES_WP;
648: if (write) {
649: if (desc & MMU_DES_WP) {
650: if ((desc & MMU_DES_USED) == 0) {
651: desc |= MMU_DES_USED;
652: phys_put_long(desc_addr, desc);
653: }
654: } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) !=
655: (MMU_DES_USED|MMU_DES_MODIFIED)) {
656: desc |= MMU_DES_USED|MMU_DES_MODIFIED;
657: phys_put_long(desc_addr, desc);
658: }
659: } else {
660: if ((desc & MMU_DES_USED) == 0) {
661: desc |= MMU_DES_USED;
662: phys_put_long(desc_addr, desc);
663: }
664: }
665: return desc;
666: }
667:
1.1.1.5 ! root 668: static void misalignednotfirst(uaecptr addr)
! 669: {
! 670: #if MMUDEBUGMISC > 0
! 671: write_log (_T("misalignednotfirst %08x -> %08x %08X\n"), regs.mmu_fault_addr, addr, regs.instruction_pc);
! 672: #endif
! 673: regs.mmu_fault_addr = addr;
! 674: regs.mmu_fslw |= MMU_FSLW_MA;
! 675: regs.mmu_ssw |= MMU_SSW_MA;
! 676: }
! 677:
! 678: static void misalignednotfirstcheck(uaecptr addr)
! 679: {
! 680: if (regs.mmu_fault_addr == addr)
! 681: return;
! 682: misalignednotfirst (addr);
! 683: }
! 684:
! 685: uae_u16 REGPARAM2 mmu_get_word_unaligned(uaecptr addr, bool data, bool rmw)
1.1.1.3 root 686: {
687: uae_u16 res;
688:
1.1.1.5 ! root 689: res = (uae_u16)mmu_get_byte(addr, data, sz_word, rmw) << 8;
1.1.1.3 root 690: SAVE_EXCEPTION;
691: TRY(prb) {
1.1.1.5 ! root 692: res |= mmu_get_byte(addr + 1, data, sz_word, rmw);
1.1.1.3 root 693: RESTORE_EXCEPTION;
694: }
695: CATCH(prb) {
696: RESTORE_EXCEPTION;
1.1.1.5 ! root 697: misalignednotfirst(addr);
1.1.1.3 root 698: THROW_AGAIN(prb);
699: } ENDTRY
700: return res;
701: }
702:
1.1.1.5 ! root 703: uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data, bool rmw)
1.1.1.3 root 704: {
705: uae_u32 res;
706:
707: if (likely(!(addr & 1))) {
1.1.1.5 ! root 708: res = (uae_u32)mmu_get_word(addr, data, sz_long, rmw) << 16;
1.1.1.3 root 709: SAVE_EXCEPTION;
710: TRY(prb) {
1.1.1.5 ! root 711: res |= mmu_get_word(addr + 2, data, sz_long, rmw);
1.1.1.3 root 712: RESTORE_EXCEPTION;
713: }
714: CATCH(prb) {
715: RESTORE_EXCEPTION;
1.1.1.5 ! root 716: misalignednotfirst(addr);
1.1.1.3 root 717: THROW_AGAIN(prb);
718: } ENDTRY
719: } else {
1.1.1.5 ! root 720: res = (uae_u32)mmu_get_byte(addr, data, sz_long, rmw) << 8;
1.1.1.3 root 721: SAVE_EXCEPTION;
722: TRY(prb) {
1.1.1.5 ! root 723: res = (res | mmu_get_byte(addr + 1, data, sz_long, rmw)) << 8;
! 724: res = (res | mmu_get_byte(addr + 2, data, sz_long, rmw)) << 8;
! 725: res |= mmu_get_byte(addr + 3, data, sz_long, rmw);
1.1.1.3 root 726: RESTORE_EXCEPTION;
727: }
728: CATCH(prb) {
729: RESTORE_EXCEPTION;
1.1.1.5 ! root 730: misalignednotfirst(addr);
1.1.1.3 root 731: THROW_AGAIN(prb);
732: } ENDTRY
733: }
734: return res;
735: }
736:
1.1.1.5 ! root 737: uae_u32 REGPARAM2 mmu_get_ilong_unaligned(uaecptr addr)
1.1.1.3 root 738: {
1.1.1.5 ! root 739: uae_u32 res;
1.1.1.3 root 740:
1.1.1.5 ! root 741: if (likely(!(addr & 1))) {
! 742: res = (uae_u32)mmu_get_iword(addr, sz_long) << 16;
! 743: SAVE_EXCEPTION;
! 744: TRY(prb) {
! 745: res |= mmu_get_iword(addr + 2, sz_long);
! 746: RESTORE_EXCEPTION;
! 747: }
! 748: CATCH(prb) {
! 749: RESTORE_EXCEPTION;
! 750: misalignednotfirst(addr);
! 751: THROW_AGAIN(prb);
! 752: } ENDTRY
1.1.1.3 root 753: }
1.1.1.5 ! root 754: return res;
! 755: }
1.1.1.3 root 756:
1.1.1.5 ! root 757: uae_u16 REGPARAM2 mmu_get_lrmw_word_unaligned(uaecptr addr)
! 758: {
! 759: uae_u16 res;
1.1.1.3 root 760:
1.1.1.5 ! root 761: res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, true, true, sz_word) << 8;
! 762: SAVE_EXCEPTION;
! 763: TRY(prb) {
! 764: res |= mmu_get_user_byte(addr + 1, regs.s != 0, true, true, sz_word);
! 765: RESTORE_EXCEPTION;
! 766: }
! 767: CATCH(prb) {
! 768: RESTORE_EXCEPTION;
! 769: misalignednotfirst(addr);
! 770: THROW_AGAIN(prb);
! 771: } ENDTRY
! 772: return res;
1.1.1.3 root 773: }
774:
1.1.1.5 ! root 775: uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr)
1.1.1.3 root 776: {
1.1.1.5 ! root 777: uae_u32 res;
1.1.1.3 root 778:
1.1.1.5 ! root 779: if (likely(!(addr & 1))) {
! 780: res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, true, true, sz_long) << 16;
! 781: SAVE_EXCEPTION;
! 782: TRY(prb) {
! 783: res |= mmu_get_user_word(addr + 2, regs.s != 0, true, true, sz_long);
! 784: RESTORE_EXCEPTION;
! 785: }
! 786: CATCH(prb) {
! 787: RESTORE_EXCEPTION;
! 788: misalignednotfirst(addr);
! 789: THROW_AGAIN(prb);
! 790: } ENDTRY
! 791: } else {
! 792: res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, true, true, sz_long) << 8;
! 793: SAVE_EXCEPTION;
! 794: TRY(prb) {
! 795: res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, true, true, sz_long)) << 8;
! 796: res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, true, true, sz_long)) << 8;
! 797: res |= mmu_get_user_byte(addr + 3, regs.s != 0, true, true, sz_long);
! 798: RESTORE_EXCEPTION;
! 799: }
! 800: CATCH(prb) {
! 801: RESTORE_EXCEPTION;
! 802: misalignednotfirst(addr);
! 803: THROW_AGAIN(prb);
! 804: } ENDTRY
! 805: }
! 806: return res;
! 807: }
! 808: uae_u8 REGPARAM2 mmu_get_byte_slow(uaecptr addr, bool super, bool data,
! 809: int size, bool rmw, struct mmu_atc_line *cl)
! 810: {
! 811: uae_u32 status;
! 812: if (!mmu_fill_atc_try(addr, super, data, 0, cl, &status)) {
! 813: mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status, false);
1.1.1.3 root 814: return 0;
815: }
1.1.1.5 ! root 816: return x_phys_get_byte(mmu_get_real_address(addr, cl));
! 817: }
1.1.1.3 root 818:
1.1.1.5 ! root 819: uae_u16 REGPARAM2 mmu_get_word_slow(uaecptr addr, bool super, bool data,
! 820: int size, bool rmw, struct mmu_atc_line *cl)
! 821: {
! 822: uae_u32 status;
! 823: if (!mmu_fill_atc_try(addr, super, data, 0, cl, &status)) {
! 824: mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status, false);
! 825: return 0;
! 826: }
! 827: return x_phys_get_word(mmu_get_real_address(addr, cl));
! 828: }
! 829: uae_u16 REGPARAM2 mmu_get_iword_slow(uaecptr addr, bool super,
! 830: int size, struct mmu_atc_line *cl)
! 831: {
! 832: uae_u32 status;
! 833: if (!mmu_fill_atc_try(addr, super, false, 0, cl, &status)) {
! 834: mmu_bus_error(addr, mmu_get_fc(super, false), 0, size, false, status, false);
! 835: return 0;
! 836: }
! 837: return x_phys_get_iword(mmu_get_real_address(addr, cl));
1.1.1.3 root 838: }
839:
840: uae_u32 REGPARAM2 mmu_get_long_slow(uaecptr addr, bool super, bool data,
1.1.1.5 ! root 841: int size, bool rmw, struct mmu_atc_line *cl)
1.1.1.3 root 842: {
1.1.1.5 ! root 843: uae_u32 status;
! 844: if (!mmu_fill_atc_try(addr, super, data, 0, cl, &status)) {
! 845: mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status, false);
1.1.1.3 root 846: return 0;
847: }
1.1.1.5 ! root 848: return x_phys_get_long(mmu_get_real_address(addr, cl));
! 849: }
! 850: uae_u32 REGPARAM2 mmu_get_ilong_slow(uaecptr addr, bool super,
! 851: int size, struct mmu_atc_line *cl)
! 852: {
! 853: uae_u32 status;
! 854: if (!mmu_fill_atc_try(addr, super, false, 0, cl, &status)) {
! 855: mmu_bus_error(addr, mmu_get_fc(super, false), 0, size, false, status, false);
! 856: return 0;
! 857: }
! 858: return x_phys_get_ilong(mmu_get_real_address(addr, cl));
1.1.1.3 root 859: }
860:
1.1.1.5 ! root 861: void REGPARAM2 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data, bool rmw)
1.1.1.3 root 862: {
863: SAVE_EXCEPTION;
864: TRY(prb) {
865: if (likely(!(addr & 1))) {
1.1.1.5 ! root 866: mmu_put_word(addr, val >> 16, data, sz_long, rmw);
! 867: mmu_put_word(addr + 2, val, data, sz_long, rmw);
1.1.1.3 root 868: } else {
1.1.1.5 ! root 869: mmu_put_byte(addr, val >> 24, data, sz_long, rmw);
! 870: mmu_put_byte(addr + 1, val >> 16, data, sz_long, rmw);
! 871: mmu_put_byte(addr + 2, val >> 8, data, sz_long, rmw);
! 872: mmu_put_byte(addr + 3, val, data, sz_long, rmw);
1.1.1.3 root 873: }
874: RESTORE_EXCEPTION;
875: }
876: CATCH(prb) {
877: RESTORE_EXCEPTION;
878: regs.wb3_data = val;
1.1.1.5 ! root 879: misalignednotfirstcheck(addr);
1.1.1.3 root 880: THROW_AGAIN(prb);
881: } ENDTRY
882: }
883:
1.1.1.5 ! root 884: void REGPARAM2 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data, bool rmw)
1.1.1.3 root 885: {
886: SAVE_EXCEPTION;
887: TRY(prb) {
1.1.1.5 ! root 888: mmu_put_byte(addr, val >> 8, data, sz_word, rmw);
! 889: mmu_put_byte(addr + 1, val, data, sz_word, rmw);
1.1.1.3 root 890: RESTORE_EXCEPTION;
891: }
892: CATCH(prb) {
893: RESTORE_EXCEPTION;
894: regs.wb3_data = val;
1.1.1.5 ! root 895: misalignednotfirstcheck(addr);
1.1.1.3 root 896: THROW_AGAIN(prb);
897: } ENDTRY
898: }
899:
900: void REGPARAM2 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data,
1.1.1.5 ! root 901: int size, bool rmw, struct mmu_atc_line *cl)
1.1.1.3 root 902: {
1.1.1.5 ! root 903: uae_u32 status;
! 904: if (!mmu_fill_atc_try(addr, super, data, 1, cl, &status)) {
1.1.1.3 root 905: regs.wb3_data = val;
1.1.1.5 ! root 906: mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status, false);
1.1.1.3 root 907: return;
908: }
1.1.1.5 ! root 909: x_phys_put_byte(mmu_get_real_address(addr, cl), val);
1.1.1.3 root 910: }
911:
912: void REGPARAM2 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data,
1.1.1.5 ! root 913: int size, bool rmw, struct mmu_atc_line *cl)
1.1.1.3 root 914: {
1.1.1.5 ! root 915: uae_u32 status;
! 916: if (!mmu_fill_atc_try(addr, super, data, 1, cl, &status)) {
1.1.1.3 root 917: regs.wb3_data = val;
1.1.1.5 ! root 918: mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status, false);
1.1.1.3 root 919: return;
920: }
1.1.1.5 ! root 921: x_phys_put_word(mmu_get_real_address(addr, cl), val);
1.1.1.3 root 922: }
923:
924: void REGPARAM2 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data,
1.1.1.5 ! root 925: int size, bool rmw, struct mmu_atc_line *cl)
1.1.1.3 root 926: {
1.1.1.5 ! root 927: uae_u32 status;
! 928: if (!mmu_fill_atc_try(addr, super, data, 1, cl, &status)) {
1.1.1.3 root 929: regs.wb3_data = val;
1.1.1.5 ! root 930: mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status, false);
1.1.1.3 root 931: return;
932: }
1.1.1.5 ! root 933: x_phys_put_long(mmu_get_real_address(addr, cl), val);
1.1.1.3 root 934: }
935:
936: uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
937: {
938: bool super = (regs.sfc & 4) != 0;
1.1.1.5 ! root 939: bool data = true;
1.1.1.3 root 940: uae_u32 res;
941:
1.1.1.5 ! root 942: ismoves = true;
! 943: if (likely(!is_unaligned(addr, 4))) {
! 944: res = mmu_get_user_long(addr, super, data, false, sz_long);
1.1.1.3 root 945: } else {
1.1.1.5 ! root 946: if (likely(!(addr & 1))) {
! 947: res = (uae_u32)mmu_get_user_word(addr, super, data, false, sz_long) << 16;
! 948: SAVE_EXCEPTION;
! 949: TRY(prb) {
! 950: res |= mmu_get_user_word(addr + 2, super, data, false, sz_long);
! 951: RESTORE_EXCEPTION;
! 952: }
! 953: CATCH(prb) {
! 954: RESTORE_EXCEPTION;
! 955: misalignednotfirst(addr);
! 956: THROW_AGAIN(prb);
! 957: } ENDTRY
! 958: } else {
! 959: res = (uae_u32)mmu_get_user_byte(addr, super, data, false, sz_long) << 8;
! 960: SAVE_EXCEPTION;
! 961: TRY(prb) {
! 962: res = (res | mmu_get_user_byte(addr + 1, super, data, false, sz_long)) << 8;
! 963: res = (res | mmu_get_user_byte(addr + 2, super, data, false, sz_long)) << 8;
! 964: res |= mmu_get_user_byte(addr + 3, super, data, false, sz_long);
! 965: RESTORE_EXCEPTION;
! 966: }
! 967: CATCH(prb) {
! 968: RESTORE_EXCEPTION;
! 969: misalignednotfirst(addr);
! 970: THROW_AGAIN(prb);
! 971: } ENDTRY
1.1.1.3 root 972: }
973: }
1.1.1.5 ! root 974:
! 975: ismoves = false;
1.1.1.3 root 976: return res;
977: }
978:
979: uae_u16 REGPARAM2 sfc_get_word(uaecptr addr)
980: {
981: bool super = (regs.sfc & 4) != 0;
1.1.1.5 ! root 982: bool data = true;
1.1.1.3 root 983: uae_u16 res;
984:
1.1.1.5 ! root 985: ismoves = true;
! 986: if (likely(!is_unaligned(addr, 2))) {
! 987: res = mmu_get_user_word(addr, super, data, false, sz_word);
! 988: } else {
! 989: res = (uae_u16)mmu_get_user_byte(addr, super, data, false, sz_word) << 8;
! 990: SAVE_EXCEPTION;
! 991: TRY(prb) {
! 992: res |= mmu_get_user_byte(addr + 1, super, data, false, sz_word);
! 993: RESTORE_EXCEPTION;
! 994: }
! 995: CATCH(prb) {
! 996: RESTORE_EXCEPTION;
! 997: misalignednotfirst(addr);
! 998: THROW_AGAIN(prb);
! 999: } ENDTRY
1.1.1.3 root 1000: }
1.1.1.5 ! root 1001: ismoves = false;
1.1.1.3 root 1002: return res;
1003: }
1004:
1005: uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr)
1006: {
1007: bool super = (regs.sfc & 4) != 0;
1.1.1.5 ! root 1008: bool data = true;
! 1009: uae_u8 res;
! 1010:
! 1011: ismoves = true;
! 1012: res = mmu_get_user_byte(addr, super, data, false, sz_byte);
! 1013: ismoves = false;
! 1014: return res;
1.1.1.3 root 1015: }
1016:
1017: void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val)
1018: {
1019: bool super = (regs.dfc & 4) != 0;
1.1.1.5 ! root 1020: bool data = true;
1.1.1.3 root 1021:
1.1.1.5 ! root 1022: ismoves = true;
1.1.1.3 root 1023: SAVE_EXCEPTION;
1024: TRY(prb) {
1025: if (likely(!is_unaligned(addr, 4)))
1026: mmu_put_user_long(addr, val, super, data, sz_long);
1027: else if (likely(!(addr & 1))) {
1028: mmu_put_user_word(addr, val >> 16, super, data, sz_long);
1029: mmu_put_user_word(addr + 2, val, super, data, sz_long);
1030: } else {
1031: mmu_put_user_byte(addr, val >> 24, super, data, sz_long);
1032: mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long);
1033: mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long);
1034: mmu_put_user_byte(addr + 3, val, super, data, sz_long);
1035: }
1036: RESTORE_EXCEPTION;
1037: }
1038: CATCH(prb) {
1039: RESTORE_EXCEPTION;
1040: regs.wb3_data = val;
1.1.1.5 ! root 1041: misalignednotfirstcheck(addr);
1.1.1.3 root 1042: THROW_AGAIN(prb);
1043: } ENDTRY
1.1.1.5 ! root 1044: ismoves = false;
1.1.1.3 root 1045: }
1046:
1047: void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val)
1048: {
1049: bool super = (regs.dfc & 4) != 0;
1.1.1.5 ! root 1050: bool data = true;
1.1.1.3 root 1051:
1.1.1.5 ! root 1052: ismoves = true;
1.1.1.3 root 1053: SAVE_EXCEPTION;
1054: TRY(prb) {
1055: if (likely(!is_unaligned(addr, 2)))
1056: mmu_put_user_word(addr, val, super, data, sz_word);
1057: else {
1058: mmu_put_user_byte(addr, val >> 8, super, data, sz_word);
1059: mmu_put_user_byte(addr + 1, val, super, data, sz_word);
1060: }
1061: RESTORE_EXCEPTION;
1062: }
1063: CATCH(prb) {
1064: RESTORE_EXCEPTION;
1065: regs.wb3_data = val;
1.1.1.5 ! root 1066: misalignednotfirstcheck(addr);
1.1.1.3 root 1067: THROW_AGAIN(prb);
1068: } ENDTRY
1.1.1.5 ! root 1069: ismoves = false;
1.1.1.3 root 1070: }
1071:
1072: void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val)
1073: {
1074: bool super = (regs.dfc & 4) != 0;
1.1.1.5 ! root 1075: bool data = true;
1.1.1.3 root 1076:
1.1.1.5 ! root 1077: ismoves = true;
1.1.1.3 root 1078: SAVE_EXCEPTION;
1079: TRY(prb) {
1080: mmu_put_user_byte(addr, val, super, data, sz_byte);
1081: RESTORE_EXCEPTION;
1082: }
1083: CATCH(prb) {
1084: RESTORE_EXCEPTION;
1085: regs.wb3_data = val;
1086: THROW_AGAIN(prb);
1087: } ENDTRY
1.1.1.5 ! root 1088: ismoves = false;
! 1089: }
! 1090:
! 1091: void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size)
! 1092: {
! 1093: struct mmu_atc_line *cl;
! 1094: int i;
! 1095: addr &= ~15;
! 1096: for (i = 0; i < 4; i++) {
! 1097: uaecptr addr2 = addr + i * 4;
! 1098: // addr,super,data
! 1099: if ((!regs.mmu_enabled) || (mmu_match_ttr(addr2,regs.s != 0,data,false)!=TTR_NO_MATCH))
! 1100: v[i] = x_phys_get_long(addr2);
! 1101: else if (likely(mmu_lookup(addr2, data, false, &cl)))
! 1102: v[i] = x_phys_get_long(mmu_get_real_address(addr2, cl));
! 1103: else
! 1104: v[i] = mmu_get_long_slow(addr2, regs.s != 0, data, size, false, cl);
! 1105: }
1.1.1.3 root 1106: }
1107:
1.1.1.5 ! root 1108: void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size)
! 1109: {
! 1110: struct mmu_atc_line *cl;
! 1111: int i;
! 1112: addr &= ~15;
! 1113: for (i = 0; i < 4; i++) {
! 1114: uaecptr addr2 = addr + i * 4;
! 1115: // addr,super,data
! 1116: if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr2,regs.s != 0,data,val[i],size,false)==TTR_OK_MATCH))
! 1117: x_phys_put_long(addr2,val[i]);
! 1118: else if (likely(mmu_lookup(addr2, data, true, &cl)))
! 1119: x_phys_put_long(mmu_get_real_address(addr2, cl), val[i]);
! 1120: else
! 1121: mmu_put_long_slow(addr2, val[i], regs.s != 0, data, size, false, cl);
! 1122: }
! 1123: }
! 1124:
! 1125:
1.1.1.3 root 1126: void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra)
1127: {
1128: bool super = (regs.dfc & 4) != 0;
1129: DUNUSED(extra);
1.1.1.5 ! root 1130: if ((opcode & 0xFE0) == 0x0500) { // PFLUSH
1.1.1.3 root 1131: bool glob;
1132: int regno;
1133: //D(didflush = 0);
1134: uae_u32 addr;
1135: /* PFLUSH */
1136: regno = opcode & 7;
1137: glob = (opcode & 8) != 0;
1138:
1139: if (opcode & 16) {
1.1.1.5 ! root 1140: #if MMUINSDEBUG > 1
! 1141: write_log(_T("pflusha(%u,%u) PC=%08x\n"), glob, regs.dfc, m68k_getpc ());
! 1142: #endif
1.1.1.3 root 1143: mmu_flush_atc_all(glob);
1144: } else {
1145: addr = m68k_areg(regs, regno);
1.1.1.5 ! root 1146: #if MMUINSDEBUG > 1
! 1147: write_log(_T("pflush(%u,%u,%x) PC=%08x\n"), glob, regs.dfc, addr, m68k_getpc ());
! 1148: #endif
1.1.1.3 root 1149: mmu_flush_atc(addr, super, glob);
1150: }
1151: flush_internals();
1152: #ifdef USE_JIT
1153: flush_icache(0);
1154: #endif
1.1.1.5 ! root 1155: } else if ((opcode & 0x0FD8) == 0x0548) { // PTEST (68040)
1.1.1.3 root 1156: bool write;
1157: int regno;
1158: uae_u32 addr;
1159:
1160: regno = opcode & 7;
1161: write = (opcode & 32) == 0;
1162: addr = m68k_areg(regs, regno);
1.1.1.5 ! root 1163: #if MMUINSDEBUG > 0
! 1164: write_log(_T("PTEST%c (A%d) %08x DFC=%d\n"), write ? 'W' : 'R', regno, addr, regs.dfc);
! 1165: #endif
1.1.1.3 root 1166: mmu_flush_atc(addr, super, true);
1167: SAVE_EXCEPTION;
1168: TRY(prb) {
1169: struct mmu_atc_line *l;
1170: uae_u32 desc;
1171: bool data = (regs.dfc & 3) != 2;
1172:
1.1.1.5 ! root 1173: if (mmu_match_ttr(addr,super,data, false)!=TTR_NO_MATCH) {
1.1.1.3 root 1174: regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
1.1.1.5 ! root 1175: } else {
! 1176: uae_u32 status;
! 1177: mmu_user_lookup(addr, super, data, write, &l);
! 1178: desc = mmu_fill_atc(addr, super, data, write, l, &status);
! 1179: if (!(l->valid)) {
! 1180: regs.mmusr = MMU_MMUSR_B;
! 1181: } else {
! 1182: regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S|
! 1183: MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W);
! 1184: regs.mmusr |= MMU_MMUSR_R;
! 1185: }
1.1.1.3 root 1186: }
1187: }
1188: CATCH(prb) {
1189: regs.mmusr = MMU_MMUSR_B;
1190: } ENDTRY
1191: RESTORE_EXCEPTION;
1.1.1.5 ! root 1192: #if MMUINSDEBUG > 0
! 1193: write_log(_T("PTEST result: mmusr %08x\n"), regs.mmusr);
! 1194: #endif
! 1195: } else if ((opcode & 0xFFB8) == 0xF588) { // PLPA (68060)
! 1196: int write = (opcode & 0x40) == 0;
! 1197: int regno = opcode & 7;
! 1198: uae_u32 addr = m68k_areg (regs, regno);
! 1199: bool data = (regs.dfc & 3) != 2;
! 1200:
! 1201: #if MMUINSDEBUG > 0
! 1202: write_log(_T("PLPA%c param: %08x\n"), write ? 'W' : 'R', addr);
! 1203: #endif
! 1204: if (mmu_match_ttr(addr,super,data,false)==TTR_NO_MATCH) {
! 1205: m68k_areg (regs, regno) = mmu_translate (addr, super, data, write != 0);
! 1206: }
! 1207: #if MMUINSDEBUG > 0
! 1208: write_log(_T("PLPA%c result: %08x\n"), write ? 'W' : 'R', m68k_areg (regs, regno));
! 1209: #endif
! 1210: } else {
1.1.1.3 root 1211: op_illg (opcode);
1.1.1.5 ! root 1212: }
1.1.1.3 root 1213: }
1214:
1.1.1.5 ! root 1215: // fixme : global parameter?
1.1.1.3 root 1216: void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global)
1217: {
1.1.1.5 ! root 1218: int way,type,index;
1.1.1.3 root 1219:
1.1.1.5 ! root 1220: uaecptr tag = ((super ? 0x80000000 : 0) | (addr >> 1)) & mmu_tagmask;
! 1221: if (mmu_pagesize_8k)
! 1222: index=(addr & 0x0001E000)>>13;
! 1223: else
! 1224: index=(addr & 0x0000F000)>>12;
! 1225: for (type=0;type<ATC_TYPE;type++) {
! 1226: for (way=0;way<ATC_WAYS;way++) {
! 1227: if (!global && mmu_atc_array[type][way][index].global)
! 1228: continue;
! 1229: // if we have this
! 1230: if ((tag == mmu_atc_array[type][way][index].tag) && (mmu_atc_array[type][way][index].valid)) {
! 1231: mmu_atc_array[type][way][index].valid=false;
! 1232: }
! 1233: }
! 1234: }
1.1.1.3 root 1235: }
1236:
1237: void REGPARAM2 mmu_flush_atc_all(bool global)
1238: {
1.1.1.5 ! root 1239: unsigned int way,slot,type;
! 1240: for (type=0;type<ATC_TYPE;type++) {
! 1241: for (way=0;way<ATC_WAYS;way++) {
! 1242: for (slot=0;slot<ATC_SLOTS;slot++) {
! 1243: if (!global && mmu_atc_array[type][way][slot].global)
! 1244: continue;
! 1245: mmu_atc_array[type][way][slot].valid=false;
! 1246: }
! 1247: }
1.1.1.3 root 1248: }
1.1.1.5 ! root 1249: }
1.1.1.3 root 1250:
1.1.1.5 ! root 1251: void REGPARAM2 mmu_set_funcs(void)
! 1252: {
! 1253: if (currprefs.mmu_model != 68040 && currprefs.mmu_model != 68060)
! 1254: return;
! 1255: if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) {
! 1256: x_phys_get_iword = get_word_icache040;
! 1257: x_phys_get_ilong = get_long_icache040;
! 1258: x_phys_get_byte = get_byte_cache_040;
! 1259: x_phys_get_word = get_word_cache_040;
! 1260: x_phys_get_long = get_long_cache_040;
! 1261: x_phys_put_byte = put_byte_cache_040;
! 1262: x_phys_put_word = put_word_cache_040;
! 1263: x_phys_put_long = put_long_cache_040;
! 1264: } else {
! 1265: x_phys_get_iword = phys_get_word;
! 1266: x_phys_get_ilong = phys_get_long;
! 1267: x_phys_get_byte = phys_get_byte;
! 1268: x_phys_get_word = phys_get_word;
! 1269: x_phys_get_long = phys_get_long;
! 1270: x_phys_put_byte = phys_put_byte;
! 1271: x_phys_put_word = phys_put_word;
! 1272: x_phys_put_long = phys_put_long;
1.1.1.3 root 1273: }
1274: }
1275:
1276: void REGPARAM2 mmu_reset(void)
1277: {
1278: mmu_flush_atc_all(true);
1.1.1.5 ! root 1279: mmu_set_funcs();
! 1280: }
! 1281:
! 1282: void REGPARAM2 mmu_set_tc(uae_u16 tc)
! 1283: {
! 1284: regs.mmu_enabled = (tc & 0x8000) != 0;
! 1285: mmu_pagesize_8k = (tc & 0x4000) != 0;
! 1286: mmu_tagmask = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000;
! 1287: mmu_pagemask = mmu_pagesize_8k ? 0x00001FFF : 0x00000FFF;
! 1288: mmu_pagemaski = ~mmu_pagemask;
! 1289: regs.mmu_page_size = mmu_pagesize_8k ? 8192 : 4096;
! 1290:
! 1291: mmu_flush_atc_all(true);
! 1292:
! 1293: write_log(_T("%d MMU: enabled=%d page8k=%d PC=%08x\n"), currprefs.mmu_model, regs.mmu_enabled, mmu_pagesize_8k, m68k_getpc());
! 1294: #if MMUDUMP
! 1295: if (regs.mmu_enabled)
! 1296: mmu_dump_tables();
1.1.1.3 root 1297: #endif
1298: }
1299:
1.1.1.5 ! root 1300: void REGPARAM2 mmu_set_super(bool super)
! 1301: {
! 1302: mmu_is_super = super ? 0x80000000 : 0;
! 1303: }
1.1.1.3 root 1304:
1.1.1.5 ! root 1305: void m68k_do_rte_mmu040 (uaecptr a7)
! 1306: {
! 1307: uae_u16 ssr = get_word_mmu040 (a7 + 8 + 4);
! 1308: if (ssr & MMU_SSW_CT) {
! 1309: uaecptr src_a7 = a7 + 8 - 8;
! 1310: uaecptr dst_a7 = a7 + 8 + 52;
! 1311: put_word_mmu040 (dst_a7 + 0, get_word_mmu040 (src_a7 + 0));
! 1312: put_long_mmu040 (dst_a7 + 2, get_long_mmu040 (src_a7 + 2));
! 1313: // skip this word
! 1314: put_long_mmu040 (dst_a7 + 8, get_long_mmu040 (src_a7 + 8));
! 1315: }
! 1316: if (ssr & MMU_SSW_CM) {
! 1317: mmu040_movem = 1;
! 1318: mmu040_movem_ea = get_long_mmu040 (a7 + 8);
! 1319: #if MMUDEBUGMISC > 0
! 1320: write_log (_T("MMU restarted MOVEM EA=%08X\n"), mmu040_movem_ea);
! 1321: #endif
! 1322: }
! 1323: }
! 1324:
! 1325: void m68k_do_rte_mmu060 (uaecptr a7)
1.1.1.3 root 1326: {
1327: #if 0
1.1.1.5 ! root 1328: mmu060_state = 2;
1.1.1.3 root 1329: #endif
1.1.1.5 ! root 1330: }
1.1.1.3 root 1331:
1.1.1.5 ! root 1332: void flush_mmu040 (uaecptr addr, int n)
! 1333: {
! 1334: }
! 1335: void m68k_do_rts_mmu040 (void)
! 1336: {
! 1337: uaecptr stack = m68k_areg (regs, 7);
! 1338: uaecptr newpc = get_long_mmu040 (stack);
! 1339: m68k_areg (regs, 7) += 4;
! 1340: m68k_setpc (newpc);
! 1341: }
! 1342: void m68k_do_bsr_mmu040 (uaecptr oldpc, uae_s32 offset)
! 1343: {
! 1344: uaecptr newstack = m68k_areg (regs, 7) - 4;
! 1345: put_long_mmu040 (newstack, oldpc);
! 1346: m68k_areg (regs, 7) -= 4;
! 1347: m68k_incpci (offset);
1.1.1.3 root 1348: }
1349:
1.1.1.5 ! root 1350: void flush_mmu060 (uaecptr addr, int n)
! 1351: {
! 1352: }
! 1353: void m68k_do_rts_mmu060 (void)
1.1.1.3 root 1354: {
1.1.1.5 ! root 1355: uaecptr stack = m68k_areg (regs, 7);
! 1356: uaecptr newpc = get_long_mmu060 (stack);
! 1357: m68k_areg (regs, 7) += 4;
! 1358: m68k_setpc (newpc);
! 1359: }
! 1360: void m68k_do_bsr_mmu060 (uaecptr oldpc, uae_s32 offset)
! 1361: {
! 1362: uaecptr newstack = m68k_areg (regs, 7) - 4;
! 1363: put_long_mmu060 (newstack, oldpc);
! 1364: m68k_areg (regs, 7) -= 4;
! 1365: m68k_incpci (offset);
! 1366: }
! 1367:
! 1368: void uae_mmu_put_lrmw (uaecptr addr, uae_u32 v, int size, int type)
! 1369: {
! 1370: locked_rmw_cycle = true;
! 1371: if (size == sz_byte) {
! 1372: mmu_put_byte(addr, v, true, sz_byte, true);
! 1373: } else if (size == sz_word) {
! 1374: if (unlikely(is_unaligned(addr, 2))) {
! 1375: mmu_put_word_unaligned(addr, v, true, true);
! 1376: } else {
! 1377: mmu_put_word(addr, v, true, sz_word, true);
! 1378: }
! 1379: } else {
! 1380: if (unlikely(is_unaligned(addr, 4)))
! 1381: mmu_put_long_unaligned(addr, v, true, true);
! 1382: else
! 1383: mmu_put_long(addr, v, true, sz_long, true);
! 1384: }
! 1385: locked_rmw_cycle = false;
! 1386: }
! 1387: uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type)
! 1388: {
! 1389: uae_u32 v;
! 1390: locked_rmw_cycle = true;
! 1391: if (size == sz_byte) {
! 1392: v = mmu_get_user_byte(addr, regs.s != 0, true, true, sz_byte);
! 1393: } else if (size == sz_word) {
! 1394: if (unlikely(is_unaligned(addr, 2))) {
! 1395: v = mmu_get_lrmw_word_unaligned(addr);
! 1396: } else {
! 1397: v = mmu_get_user_word(addr, regs.s != 0, true, true, sz_word);
! 1398: }
! 1399: } else {
! 1400: if (unlikely(is_unaligned(addr, 4)))
! 1401: v = mmu_get_lrmw_long_unaligned(addr);
! 1402: else
! 1403: v = mmu_get_user_long(addr, regs.s != 0, true, true, sz_long);
! 1404: }
! 1405: locked_rmw_cycle = false;
! 1406: return v;
! 1407: }
! 1408:
! 1409: uae_u32 REGPARAM2 mmu060_get_rmw_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
! 1410: {
! 1411: uae_u32 tmp1, tmp2, res, mask;
! 1412:
! 1413: offset &= 7;
! 1414: mask = 0xffffffffu << (32 - width);
! 1415: switch ((offset + width + 7) >> 3) {
! 1416: case 1:
! 1417: tmp1 = get_rmw_byte_mmu060 (src);
! 1418: res = tmp1 << (24 + offset);
! 1419: bdata[0] = tmp1 & ~(mask >> (24 + offset));
! 1420: break;
! 1421: case 2:
! 1422: tmp1 = get_rmw_word_mmu060 (src);
! 1423: res = tmp1 << (16 + offset);
! 1424: bdata[0] = tmp1 & ~(mask >> (16 + offset));
! 1425: break;
! 1426: case 3:
! 1427: tmp1 = get_rmw_word_mmu060 (src);
! 1428: tmp2 = get_rmw_byte_mmu060 (src + 2);
! 1429: res = tmp1 << (16 + offset);
! 1430: bdata[0] = tmp1 & ~(mask >> (16 + offset));
! 1431: res |= tmp2 << (8 + offset);
! 1432: bdata[1] = tmp2 & ~(mask >> (8 + offset));
! 1433: break;
! 1434: case 4:
! 1435: tmp1 = get_rmw_long_mmu060 (src);
! 1436: res = tmp1 << offset;
! 1437: bdata[0] = tmp1 & ~(mask >> offset);
! 1438: break;
! 1439: case 5:
! 1440: tmp1 = get_rmw_long_mmu060 (src);
! 1441: tmp2 = get_rmw_byte_mmu060 (src + 4);
! 1442: res = tmp1 << offset;
! 1443: bdata[0] = tmp1 & ~(mask >> offset);
! 1444: res |= tmp2 >> (8 - offset);
! 1445: bdata[1] = tmp2 & ~(mask << (8 - offset));
! 1446: break;
! 1447: default:
! 1448: /* Panic? */
! 1449: write_log (_T("x_get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
! 1450: res = 0;
! 1451: break;
! 1452: }
! 1453: return res;
! 1454: }
! 1455:
! 1456: void REGPARAM2 mmu060_put_rmw_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
! 1457: {
! 1458: offset = (offset & 7) + width;
! 1459: switch ((offset + 7) >> 3) {
! 1460: case 1:
! 1461: put_rmw_byte_mmu060 (dst, bdata[0] | (val << (8 - offset)));
! 1462: break;
! 1463: case 2:
! 1464: put_rmw_word_mmu060 (dst, bdata[0] | (val << (16 - offset)));
! 1465: break;
! 1466: case 3:
! 1467: put_rmw_word_mmu060 (dst, bdata[0] | (val >> (offset - 16)));
! 1468: put_rmw_byte_mmu060 (dst + 2, bdata[1] | (val << (24 - offset)));
! 1469: break;
! 1470: case 4:
! 1471: put_rmw_long_mmu060 (dst, bdata[0] | (val << (32 - offset)));
! 1472: break;
! 1473: case 5:
! 1474: put_rmw_long_mmu060 (dst, bdata[0] | (val >> (offset - 32)));
! 1475: put_rmw_byte_mmu060 (dst + 4, bdata[1] | (val << (40 - offset)));
! 1476: break;
! 1477: default:
! 1478: write_log (_T("x_put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
! 1479: break;
! 1480: }
1.1.1.3 root 1481: }
1482:
1.1.1.5 ! root 1483:
! 1484: #ifndef __cplusplus
1.1.1.3 root 1485: jmp_buf __exbuf;
1486: int __exvalue;
1487: #define MAX_TRY_STACK 256
1488: static int s_try_stack_size=0;
1489: static jmp_buf s_try_stack[MAX_TRY_STACK];
1490: jmp_buf* __poptry(void) {
1491: if (s_try_stack_size>0) {
1.1.1.5 ! root 1492: s_try_stack_size--;
! 1493: if (s_try_stack_size == 0)
! 1494: return NULL;
! 1495: memcpy(&__exbuf,&s_try_stack[s_try_stack_size-1],sizeof(jmp_buf));
! 1496: // fprintf(stderr,"pop %d jmpbuf=%08x\n",s_try_stack_size, s_try_stack[s_try_stack_size][0]);
! 1497: return &s_try_stack[s_try_stack_size-1];
! 1498: }
1.1.1.3 root 1499: else {
1500: fprintf(stderr,"try stack underflow...\n");
1.1.1.5 ! root 1501: // return (NULL);
! 1502: abort();
1.1.1.3 root 1503: }
1504: }
1505: void __pushtry(jmp_buf* j) {
1506: if (s_try_stack_size<MAX_TRY_STACK) {
1.1.1.5 ! root 1507: // fprintf(stderr,"push %d jmpbuf=%08x\n",s_try_stack_size, (*j)[0]);
1.1.1.3 root 1508: memcpy(&s_try_stack[s_try_stack_size],j,sizeof(jmp_buf));
1509: s_try_stack_size++;
1510: } else {
1511: fprintf(stderr,"try stack overflow...\n");
1.1.1.5 ! root 1512: abort();
1.1.1.3 root 1513: }
1514: }
1515: int __is_catched(void) {return (s_try_stack_size>0); }
1.1.1.5 ! root 1516: #endif
! 1517:
1.1.1.3 root 1518: #else
1519:
1520: void mmu_op(uae_u32 opcode, uae_u16 /*extra*/)
1521: {
1522: if ((opcode & 0xFE0) == 0x0500) {
1523: /* PFLUSH instruction */
1524: flush_internals();
1525: } else if ((opcode & 0x0FD8) == 0x548) {
1526: /* PTEST instruction */
1527: } else
1528: op_illg(opcode);
1529: }
1530:
1531: #endif
1532:
1.1.1.5 ! root 1533:
1.1.1.3 root 1534: /*
1535: vim:ts=4:sw=4:
1536: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.