Annotation of hatari/src/cpu/cpummu.c, revision 1.1.1.5

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 ? &regs.dtt0 : &regs.itt0;
                     91:        uae_u32 * ttr1 = datamode ? &regs.dtt1 : &regs.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: */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.