Annotation of previous/src/cpu/cpummu.c, revision 1.1.1.3

1.1.1.2   root        1: /*
                      2:  * cpummu.cpp -  MMU emulation
                      3:  *
                      4:  * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
                      5:  * 
                      6:  * Inspired by UAE MMU patch
                      7:  *
                      8:  * This file is part of the ARAnyM project which builds a new and powerful
                      9:  * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
                     10:  *
                     11:  * ARAnyM is free software; you can redistribute it and/or modify
                     12:  * it under the terms of the GNU General Public License as published by
                     13:  * the Free Software Foundation; either version 2 of the License, or
                     14:  * (at your option) any later version.
                     15:  *
                     16:  * ARAnyM is distributed in the hope that it will be useful,
                     17:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     18:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     19:  * GNU General Public License for more details.
                     20:  *
                     21:  * You should have received a copy of the GNU General Public License
                     22:  * along with ARAnyM; if not, write to the Free Software
                     23:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     24:  */
                     25: 
                     26: #define DEBUG 1
                     27: #define USETAG 0
                     28: 
                     29: #include "sysconfig.h"
                     30: #include "sysdeps.h"
                     31: 
                     32: #include "options_cpu.h"
                     33: #include "memory.h"
                     34: #include "newcpu.h"
                     35: //#include "debug.h"
                     36: #include "main.h"
                     37: #include "cpummu.h"
                     38: 
                     39: #define DBG_MMU_VERBOSE        1
                     40: #define DBG_MMU_SANITY 1
                     41: #define write_log printf
                     42: 
                     43: #ifdef FULLMMU
                     44: 
                     45: 
                     46: bool mmu_is_super;
                     47: struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS];
                     48: 
                     49: static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr)
                     50: {
                     51:        DUNUSED(label);
                     52:        uae_u32 from_addr, to_addr;
                     53: 
                     54:        from_addr = ttr & MMU_TTR_LOGICAL_BASE;
                     55:        to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8;
                     56: 
                     57:        
                     58:        fprintf(stderr, "%s: [%08lx] %08lx - %08lx enabled=%d supervisor=%d wp=%d cm=%02d\n",
                     59:                        label, ttr,
                     60:                        from_addr, to_addr,
                     61:                        ttr & MMU_TTR_BIT_ENABLED ? 1 : 0,
                     62:                        (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT,
                     63:                        ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0,
                     64:                        (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT
                     65:                  );
                     66: }
                     67: 
                     68: void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode)
                     69: {
                     70:        uae_u32 * ttr;
                     71:        uae_u32 * ttr0 = datamode ? &regs.dtt0 : &regs.itt0;
                     72:        uae_u32 * ttr1 = datamode ? &regs.dtt1 : &regs.itt1;
                     73: 
                     74:        if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0)
                     75:                ttr = ttr1;
                     76:        else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0)
                     77:                ttr = ttr0;
                     78:        else
                     79:                return;
                     80: 
                     81:        *ttr = baseaddr & MMU_TTR_LOGICAL_BASE;
                     82:        *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8;
                     83:        *ttr |= MMU_TTR_BIT_ENABLED;
                     84: 
                     85:        fprintf(stderr, "MMU: map transparent mapping of %08x\n", *ttr);
                     86: }
                     87: 
                     88: 
                     89: 
                     90: #if 0
                     91: /* {{{ mmu_dump_table */
                     92: static void mmu_dump_table(const char * label, uaecptr root_ptr)
                     93: {
                     94:        DUNUSED(label);
                     95:        const int ROOT_TABLE_SIZE = 128,
                     96:                PTR_TABLE_SIZE = 128,
                     97:                PAGE_TABLE_SIZE = 64,
                     98:                ROOT_INDEX_SHIFT = 25,
                     99:                PTR_INDEX_SHIFT = 18;
                    100:        // const int PAGE_INDEX_SHIFT = 12;
                    101:        int root_idx, ptr_idx, page_idx;
                    102:        uae_u32 root_des, ptr_des, page_des;
                    103:        uaecptr ptr_des_addr, page_addr,
                    104:                root_log, ptr_log, page_log;
                    105: 
                    106:        fprintf(stderr, "%s: root=%lx\n", label, root_ptr);
                    107: 
                    108:        for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) {
                    109:                root_des = phys_get_long(root_ptr + root_idx);
                    110: 
                    111:                if ((root_des & 2) == 0)
                    112:                        continue;       /* invalid */
                    113: 
                    114:                fprintf(stderr, "ROOT: %03d U=%d W=%d UDT=%02d\n", root_idx,
                    115:                                root_des & 8 ? 1 : 0,
                    116:                                root_des & 4 ? 1 : 0,
                    117:                                root_des & 3
                    118:                          );
                    119: 
                    120:                root_log = root_idx << ROOT_INDEX_SHIFT;
                    121: 
                    122:                ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK;
                    123: 
                    124:                for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) {
                    125:                        struct {
                    126:                                uaecptr log, phys;
                    127:                                int start_idx, n_pages; /* number of pages covered by this entry */
                    128:                                uae_u32 match;
                    129:                        } page_info[PAGE_TABLE_SIZE];
                    130:                        int n_pages_used;
                    131: 
                    132:                        ptr_des = phys_get_long(ptr_des_addr + ptr_idx);
                    133:                        ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT);
                    134: 
                    135:                        if ((ptr_des & 2) == 0)
                    136:                                continue; /* invalid */
                    137: 
                    138:                        page_addr = ptr_des & (regs.mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4);
                    139: 
                    140:                        n_pages_used = -1;
                    141:                        for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) {
                    142: 
                    143:                                page_des = phys_get_long(page_addr + page_idx);
                    144:                                page_log = ptr_log | (page_idx << 2);           // ??? PAGE_INDEX_SHIFT
                    145: 
                    146:                                switch (page_des & 3) {
                    147:                                        case 0: /* invalid */
                    148:                                                continue;
                    149:                                        case 1: case 3: /* resident */
                    150:                                        case 2: /* indirect */
                    151:                                                if (n_pages_used == -1 || page_info[n_pages_used].match != page_des) {
                    152:                                                        /* use the next entry */
                    153:                                                        n_pages_used++;
                    154: 
                    155:                                                        page_info[n_pages_used].match = page_des;
                    156:                                                        page_info[n_pages_used].n_pages = 1;
                    157:                                                        page_info[n_pages_used].start_idx = page_idx;
                    158:                                                        page_info[n_pages_used].log = page_log;
                    159:                                                } else {
                    160:                                                        page_info[n_pages_used].n_pages++;
                    161:                                                }
                    162:                                                break;
                    163:                                }
                    164:                        }
                    165: 
                    166:                        if (n_pages_used == -1)
                    167:                                continue;
                    168: 
                    169:                        fprintf(stderr, " PTR: %03d U=%d W=%d UDT=%02d\n", ptr_idx,
                    170:                                ptr_des & 8 ? 1 : 0,
                    171:                                ptr_des & 4 ? 1 : 0,
                    172:                                ptr_des & 3
                    173:                          );
                    174: 
                    175: 
                    176:                        for (page_idx = 0; page_idx <= n_pages_used; page_idx++) {
                    177:                                page_des = page_info[page_idx].match;
                    178: 
                    179:                                if ((page_des & MMU_PDT_MASK) == 2) {
                    180:                                        fprintf(stderr, "  PAGE: %03d-%03d log=%08lx INDIRECT --> addr=%08lx\n",
                    181:                                                        page_info[page_idx].start_idx,
                    182:                                                        page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
                    183:                                                        page_info[page_idx].log,
                    184:                                                        page_des & MMU_PAGE_INDIRECT_MASK
                    185:                                                  );
                    186: 
                    187:                                } else {
                    188:                                        fprintf(stderr, "  PAGE: %03d-%03d log=%08lx addr=%08lx UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d\n",
                    189:                                                        page_info[page_idx].start_idx,
                    190:                                                        page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
                    191:                                                        page_info[page_idx].log,
                    192:                                                        page_des & (regs.mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4),
                    193:                                                        (page_des & (regs.mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4)) >> MMU_PAGE_UR_SHIFT,
                    194:                                                        page_des & MMU_DES_GLOBAL ? 1 : 0,
                    195:                                                        (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT,
                    196:                                                        page_des & MMU_DES_SUPER ? 1 : 0,
                    197:                                                        (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT,
                    198:                                                        page_des & MMU_DES_MODIFIED ? 1 : 0,
                    199:                                                        page_des & MMU_DES_USED ? 1 : 0,
                    200:                                                        page_des & MMU_DES_WP ? 1 : 0
                    201:                                                  );
                    202:                                }
                    203:                        }
                    204:                }
                    205: 
                    206:        }
                    207: }
                    208: /* }}} */
                    209: #endif
                    210: 
                    211: /* {{{ mmu_dump_atc */
                    212: void mmu_dump_atc(void)
                    213: {
                    214: 
                    215: }
                    216: /* }}} */
                    217: 
                    218: /* {{{ mmu_dump_tables */
                    219: void mmu_dump_tables(void)
                    220: {
                    221:        fprintf(stderr, "URP: %08x   SRP: %08x  MMUSR: %x  TC: %x\n", regs.urp, regs.srp, regs.mmusr, regs.tcr);
                    222:        mmu_dump_ttr(L"DTT0", regs.dtt0);
                    223:        mmu_dump_ttr(L"DTT1", regs.dtt1);
                    224:        mmu_dump_ttr(L"ITT0", regs.itt0);
                    225:        mmu_dump_ttr(L"ITT1", regs.itt1);
                    226:        mmu_dump_atc();
                    227: #if DEBUG
                    228:        // mmu_dump_table("SRP", regs.srp);
                    229: #endif
                    230: }
                    231: /* }}} */
                    232: 
                    233: static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, bool super, bool write);
                    234: 
                    235: static ALWAYS_INLINE int mmu_get_fc(bool super, bool data)
                    236: {
                    237:        return (super ? 4 : 0) | (data ? 1 : 2);
                    238: }
                    239: 
                    240: static void mmu_bus_error(uaecptr addr, int fc, bool write, int size)
                    241: {
                    242:        uae_u16 ssw = 0;
                    243: 
                    244:        ssw |= fc & MMU_SSW_TM;                         /* Copy TM */
                    245:        switch (size) {
                    246:        case sz_byte:
                    247:                ssw |= MMU_SSW_SIZE_B;
                    248:                break;
                    249:        case sz_word:
                    250:                ssw |= MMU_SSW_SIZE_W;
                    251:                break;
                    252:        case sz_long:
                    253:                ssw |= MMU_SSW_SIZE_L;
                    254:                break;
                    255:        }
                    256: 
                    257:        regs.wb3_status = write ? 0x80 | ssw : 0;
                    258:        if (!write)
                    259:                ssw |= MMU_SSW_RW;
                    260: 
                    261:        regs.mmu_fault_addr = addr;
                    262:        regs.mmu_ssw = ssw | MMU_SSW_ATC;
                    263: 
                    264:        fprintf(stderr, "BUS ERROR: fc=%d w=%d logical=%08x ssw=%04x PC=%08x\n", fc, write, addr, ssw, m68k_getpc());
                    265: 
                    266:        THROW(2);
                    267: }
                    268: 
                    269: /*
                    270:  * Update the atc line for a given address by doing a mmu lookup.
                    271:  */
                    272: static uaecptr mmu_fill_atc(uaecptr addr, bool super, bool data, bool write, struct mmu_atc_line *l)
                    273: {
                    274:        int res;
                    275:        uae_u32 desc;
                    276: 
                    277:        SAVE_EXCEPTION;
                    278:        TRY(prb) {
                    279:                desc = mmu_lookup_pagetable(addr, super, write);
                    280: #if DEBUG > 2
                    281:                fprintf(stderr, "translate: %x,%u,%u,%u -> %x\n", addr, super, write, data, desc);
                    282: #endif
                    283:                RESTORE_EXCEPTION;
                    284:        }
                    285:        CATCH(prb) {
                    286:                RESTORE_EXCEPTION;
                    287:                /* bus error during table search */
                    288:                desc = 0;
                    289:                // goto fail;
                    290:        } ENDTRY
                    291: 
                    292:        if ((desc & 1) == 0 || (!super && desc & MMU_MMUSR_S)) {
                    293:        fail:
                    294:                l->valid = 0;
                    295:                l->global = 0;
                    296:        } else {
                    297:                l->valid = 1;
                    298:                if (regs.mmu_pagesize_8k)
                    299:                        l->phys = (desc & ~0x1fff);
                    300:                else
                    301:                        l->phys = (desc & ~0xfff);
                    302:                l->global = (desc & MMU_MMUSR_G) != 0;
                    303:                l->modified = (desc & MMU_MMUSR_M) != 0;
                    304:                l->write_protect = (desc & MMU_MMUSR_W) != 0;
                    305:        }
                    306: 
                    307:        return desc;
                    308: }
                    309: 
                    310: static ALWAYS_INLINE bool mmu_fill_atc_try(uaecptr addr, bool super, bool data, bool write, struct mmu_atc_line *l1)
                    311: {
                    312:        mmu_fill_atc(addr,super,data,write,l1);
                    313:        if (!(l1->valid)) {
                    314:                fprintf(stderr, "MMU: non-resident page (%x,%x,%x)!\n", addr, regs.pc, regs.fault_pc);
                    315:                goto fail;
                    316:        }
                    317:        if (write) {
                    318:                if (l1->write_protect) {
                    319:                        fprintf(stderr, "MMU: write protected %lx by atc \n", addr);
                    320:                        mmu_dump_atc();
                    321:                        goto fail;
                    322:                }
                    323: 
                    324:        }
                    325:        return true;
                    326: 
                    327: fail:
                    328:        return false;
                    329: }
                    330: 
                    331: uaecptr REGPARAM2 mmu_translate(uaecptr addr, bool super, bool data, bool write)
                    332: {
                    333:        struct mmu_atc_line *l;
                    334:        
                    335:        // this should return a miss but choose a valid line
                    336:        mmu_user_lookup(addr, super, data, write, &l);
                    337: 
                    338:        mmu_fill_atc(addr, super, data, write, l);
                    339:        if (!l->valid) {
                    340:                fprintf(stderr, "[MMU] mmu_translate error");
                    341:                THROW(2);
                    342:        }
                    343: 
                    344:     return l->phys | (addr & (regs.mmu_pagesize_8k?0x00001fff:0x00000fff));
                    345: 
                    346: }
                    347: 
                    348: /*
                    349:  * Lookup the address by walking the page table and updating
                    350:  * the page descriptors accordingly. Returns the found descriptor
                    351:  * or produces a bus error.
                    352:  */
                    353: static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, bool super, bool write)
                    354: {
                    355:        uae_u32 desc, desc_addr, wp;
                    356:        int i;
                    357: 
                    358:        wp = 0;
                    359:        desc = super ? regs.srp : regs.urp;
                    360: 
                    361:        /* fetch root table descriptor */
                    362:        i = (addr >> 23) & 0x1fc;
                    363:        desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
                    364:        desc = phys_get_long(desc_addr);
                    365:        if ((desc & 2) == 0) {
                    366:                fprintf(stderr, "MMU: invalid root descriptor %s for %lx desc at %lx desc=%lx %s at %d\n", super ? "srp":"urp",
                    367:                                addr,desc_addr,desc,__FILE__,__LINE__);
                    368:                return 0;
                    369:        }
                    370: 
                    371:        wp |= desc;
                    372:        if ((desc & MMU_DES_USED) == 0)
                    373:                phys_put_long(desc_addr, desc | MMU_DES_USED);
                    374: 
                    375:        /* fetch pointer table descriptor */
                    376:        i = (addr >> 16) & 0x1fc;
                    377:        desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
                    378:        desc = phys_get_long(desc_addr);
                    379:        if ((desc & 2) == 0) {
                    380:                fprintf(stderr, "MMU: invalid ptr descriptor %s for %lx desc at %lx desc=%lx %s at %d\n", super ? "srp":"urp", 
                    381:                                addr,desc_addr,desc,__FILE__,__LINE__);
                    382:                return 0;
                    383:        }
                    384:        wp |= desc;
                    385:        if ((desc & MMU_DES_USED) == 0)
                    386:                phys_put_long(desc_addr, desc | MMU_DES_USED);
                    387: 
                    388:        /* fetch page table descriptor */
                    389:        if (regs.mmu_pagesize_8k) {
                    390:                i = (addr >> 11) & 0x7c;
                    391:                desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) + i;
                    392:        } else {
                    393:                i = (addr >> 10) & 0xfc;
                    394:                desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) + i;
                    395:        }
                    396: 
                    397:        desc = phys_get_long(desc_addr);
                    398:        if ((desc & 3) == 2) {
                    399:                /* indirect */
                    400:                desc_addr = desc & MMU_PAGE_INDIRECT_MASK;
                    401:                desc = phys_get_long(desc_addr);
                    402:        }
                    403:        if ((desc & 1) == 0) {
                    404:                fprintf(stderr, "MMU: invalid page descriptor log=%08lx desc=%08lx @%08lx %s at %d\n", addr, desc, desc_addr,__FILE__,__LINE__);
                    405:                return desc;
                    406:        }
                    407: 
                    408:        desc |= wp & MMU_DES_WP;
                    409:        if (write) {
                    410:                if (desc & MMU_DES_WP) {
                    411:                        if ((desc & MMU_DES_USED) == 0) {
                    412:                                desc |= MMU_DES_USED;
                    413:                                phys_put_long(desc_addr, desc);
                    414:                        }
                    415:                } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) !=
                    416:                                   (MMU_DES_USED|MMU_DES_MODIFIED)) {
                    417:                        desc |= MMU_DES_USED|MMU_DES_MODIFIED;
                    418:                        phys_put_long(desc_addr, desc);
                    419:                }
                    420:        } else {
                    421:                if ((desc & MMU_DES_USED) == 0) {
                    422:                        desc |= MMU_DES_USED;
                    423:                        phys_put_long(desc_addr, desc);
                    424:                }
                    425:        }
                    426:        return desc;
                    427: }
                    428: 
                    429: uae_u16 REGPARAM2 mmu_get_word_unaligned(uaecptr addr, bool data)
                    430: {
                    431:        uae_u16 res;
                    432: 
                    433:        res = (uae_u16)mmu_get_byte(addr, data, sz_word) << 8;
                    434:        SAVE_EXCEPTION;
                    435:        TRY(prb) {
                    436:                res |= mmu_get_byte(addr + 1, data, sz_word);
                    437:                RESTORE_EXCEPTION;
                    438:        }
                    439:        CATCH(prb) {
                    440:                RESTORE_EXCEPTION;
                    441:                regs.mmu_fault_addr = addr;
                    442:                regs.mmu_ssw |= MMU_SSW_MA;
                    443:                THROW_AGAIN(prb);
                    444:        } ENDTRY
                    445:        return res;
                    446: }
                    447: 
                    448: uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data)
                    449: {
                    450:        uae_u32 res;
                    451: 
                    452:        if (likely(!(addr & 1))) {
                    453:                res = (uae_u32)mmu_get_word(addr, data, sz_long) << 16;
                    454:                SAVE_EXCEPTION;
                    455:                TRY(prb) {
                    456:                        res |= mmu_get_word(addr + 2, data, sz_long);
                    457:                        RESTORE_EXCEPTION;
                    458:                }
                    459:                CATCH(prb) {
                    460:                        RESTORE_EXCEPTION;
                    461:                        regs.mmu_fault_addr = addr;
                    462:                        regs.mmu_ssw |= MMU_SSW_MA;
                    463:                        THROW_AGAIN(prb);
                    464:                } ENDTRY
                    465:        } else {
                    466:                res = (uae_u32)mmu_get_byte(addr, data, sz_long) << 8;
                    467:                SAVE_EXCEPTION;
                    468:                TRY(prb) {
                    469:                        res = (res | mmu_get_byte(addr + 1, data, sz_long)) << 8;
                    470:                        res = (res | mmu_get_byte(addr + 2, data, sz_long)) << 8;
                    471:                        res |= mmu_get_byte(addr + 3, data, sz_long);
                    472:                        RESTORE_EXCEPTION;
                    473:                }
                    474:                CATCH(prb) {
                    475:                        RESTORE_EXCEPTION;
                    476:                        regs.mmu_fault_addr = addr;
                    477:                        regs.mmu_ssw |= MMU_SSW_MA;
                    478:                        THROW_AGAIN(prb);
                    479:                } ENDTRY
                    480:        }
                    481:        return res;
                    482: }
                    483: 
                    484: uae_u8 REGPARAM2 mmu_get_byte_slow(uaecptr addr, bool super, bool data,
                    485:                                                 int size, struct mmu_atc_line *cl)
                    486: {
                    487:        if (!mmu_fill_atc_try(addr, super, data, 0, cl)) {
                    488:                mmu_bus_error(addr, mmu_get_fc(super, data), 0, size);
                    489:                return 0;
                    490:        }
                    491:        return phys_get_byte(mmu_get_real_address(addr, cl));
                    492: }
                    493: 
                    494: uae_u16 REGPARAM2 mmu_get_word_slow(uaecptr addr, bool super, bool data,
                    495:                                                  int size, struct mmu_atc_line *cl)
                    496: {
                    497:        if (!mmu_fill_atc_try(addr, super, data, 0, cl)) {
                    498:                mmu_bus_error(addr, mmu_get_fc(super, data), 0, size);
                    499:                return 0;
                    500:        }
                    501:        return phys_get_word(mmu_get_real_address(addr, cl));
                    502: }
                    503: 
                    504: uae_u32 REGPARAM2 mmu_get_long_slow(uaecptr addr, bool super, bool data,
                    505:                                                  int size, struct mmu_atc_line *cl)
                    506: {
                    507:        if (!mmu_fill_atc_try(addr, super, data, 0, cl)) {
                    508:                mmu_bus_error(addr, mmu_get_fc(super, data), 0, size);
                    509:                return 0;
                    510:        }
                    511:        return phys_get_long(mmu_get_real_address(addr, cl));
                    512: }
                    513: 
                    514: void REGPARAM2 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data)
                    515: {
                    516:        SAVE_EXCEPTION;
                    517:        TRY(prb) {
                    518:                if (likely(!(addr & 1))) {
                    519:                        mmu_put_word(addr, val >> 16, data, sz_long);
                    520:                        mmu_put_word(addr + 2, val, data, sz_long);
                    521:                } else {
                    522:                        mmu_put_byte(addr, val >> 24, data, sz_long);
                    523:                        mmu_put_byte(addr + 1, val >> 16, data, sz_long);
                    524:                        mmu_put_byte(addr + 2, val >> 8, data, sz_long);
                    525:                        mmu_put_byte(addr + 3, val, data, sz_long);
                    526:                }
                    527:                RESTORE_EXCEPTION;
                    528:        }
                    529:        CATCH(prb) {
                    530:                RESTORE_EXCEPTION;
                    531:                regs.wb3_data = val;
                    532:                if (regs.mmu_fault_addr != addr) {
                    533:                        regs.mmu_fault_addr = addr;
                    534:                        regs.mmu_ssw |= MMU_SSW_MA;
                    535:                }
                    536:                THROW_AGAIN(prb);
                    537:        } ENDTRY
                    538: }
                    539: 
                    540: void REGPARAM2 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data)
                    541: {
                    542:        SAVE_EXCEPTION;
                    543:        TRY(prb) {
                    544:                mmu_put_byte(addr, val >> 8, data, sz_word);
                    545:                mmu_put_byte(addr + 1, val, data, sz_word);
                    546:                RESTORE_EXCEPTION;
                    547:        }
                    548:        CATCH(prb) {
                    549:                RESTORE_EXCEPTION;
                    550:                regs.wb3_data = val;
                    551:                if (regs.mmu_fault_addr != addr) {
                    552:                        regs.mmu_fault_addr = addr;
                    553:                        regs.mmu_ssw |= MMU_SSW_MA;
                    554:                }
                    555:                THROW_AGAIN(prb);
                    556:        } ENDTRY
                    557: }
                    558: 
                    559: void REGPARAM2 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data,
                    560:                                                                 int size, struct mmu_atc_line *cl)
                    561: {
                    562:        if (!mmu_fill_atc_try(addr, super, data, 1, cl)) {
                    563:                regs.wb3_data = val;
                    564:                mmu_bus_error(addr, mmu_get_fc(super, data), 1, size);
                    565:                return;
                    566:        }
                    567:        phys_put_byte(mmu_get_real_address(addr, cl), val);
                    568: }
                    569: 
                    570: void REGPARAM2 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data,
                    571:                                                                 int size, struct mmu_atc_line *cl)
                    572: {
                    573:        if (!mmu_fill_atc_try(addr, super, data, 1, cl)) {
                    574:                regs.wb3_data = val;
                    575:                mmu_bus_error(addr, mmu_get_fc(super, data), 1, size);
                    576:                return;
                    577:        }
                    578:        phys_put_word(mmu_get_real_address(addr, cl), val);
                    579: }
                    580: 
                    581: void REGPARAM2 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data,
                    582:                                                                 int size, struct mmu_atc_line *cl)
                    583: {
                    584:        if (!mmu_fill_atc_try(addr, super, data, 1, cl)) {
                    585:                regs.wb3_data = val;
                    586:                mmu_bus_error(addr, mmu_get_fc(super, data), 1, size);
                    587:                return;
                    588:        }
                    589:        phys_put_long(mmu_get_real_address(addr, cl), val);
                    590: }
                    591: 
                    592: uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
                    593: {
                    594:        bool super = (regs.sfc & 4) != 0;
                    595:        bool data = (regs.sfc & 3) != 2;
                    596:        uae_u32 res;
                    597: 
                    598:        if (likely(!is_unaligned(addr, 4)))
                    599:                return mmu_get_user_long(addr, super, data, sz_long);
                    600: 
                    601:        if (likely(!(addr & 1))) {
                    602:                res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16;
                    603:                SAVE_EXCEPTION;
                    604:                TRY(prb) {
                    605:                        res |= mmu_get_user_word(addr + 2, super, data, sz_long);
                    606:                        RESTORE_EXCEPTION;
                    607:                }
                    608:                CATCH(prb) {
                    609:                        RESTORE_EXCEPTION;
                    610:                        regs.mmu_fault_addr = addr;
                    611:                        regs.mmu_ssw |= MMU_SSW_MA;
                    612:                        THROW_AGAIN(prb);
                    613:                } ENDTRY
                    614:        } else {
                    615:                res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8;
                    616:                SAVE_EXCEPTION;
                    617:                TRY(prb) {
                    618:                        res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8;
                    619:                        res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8;
                    620:                        res |= mmu_get_user_byte(addr + 3, super, data, sz_long);
                    621:                        RESTORE_EXCEPTION;
                    622:                }
                    623:                CATCH(prb) {
                    624:                        RESTORE_EXCEPTION;
                    625:                        regs.mmu_fault_addr = addr;
                    626:                        regs.mmu_ssw |= MMU_SSW_MA;
                    627:                        THROW_AGAIN(prb);
                    628:                } ENDTRY
                    629:        }
                    630:        return res;
                    631: }
                    632: 
                    633: uae_u16 REGPARAM2 sfc_get_word(uaecptr addr)
                    634: {
                    635:        bool super = (regs.sfc & 4) != 0;
                    636:        bool data = (regs.sfc & 3) != 2;
                    637:        uae_u16 res;
                    638: 
                    639:        if (likely(!is_unaligned(addr, 2)))
                    640:                return mmu_get_user_word(addr, super, data, sz_word);
                    641: 
                    642:        res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8;
                    643:        SAVE_EXCEPTION;
                    644:        TRY(prb) {
                    645:                res |= mmu_get_user_byte(addr + 1, super, data, sz_word);
                    646:                RESTORE_EXCEPTION;
                    647:        }
                    648:        CATCH(prb) {
                    649:                RESTORE_EXCEPTION;
                    650:                regs.mmu_fault_addr = addr;
                    651:                regs.mmu_ssw |= MMU_SSW_MA;
                    652:                THROW_AGAIN(prb);
                    653:        } ENDTRY
                    654:        return res;
                    655: }
                    656: 
                    657: uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr)
                    658: {
                    659:        bool super = (regs.sfc & 4) != 0;
                    660:        bool data = (regs.sfc & 3) != 2;
                    661: 
                    662:        return mmu_get_user_byte(addr, super, data, sz_byte);
                    663: }
                    664: 
                    665: void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val)
                    666: {
                    667:        bool super = (regs.dfc & 4) != 0;
                    668:        bool data = (regs.dfc & 3) != 2;
                    669: 
                    670:        SAVE_EXCEPTION;
                    671:        TRY(prb) {
                    672:                if (likely(!is_unaligned(addr, 4)))
                    673:                        mmu_put_user_long(addr, val, super, data, sz_long);
                    674:                else if (likely(!(addr & 1))) {
                    675:                        mmu_put_user_word(addr, val >> 16, super, data, sz_long);
                    676:                        mmu_put_user_word(addr + 2, val, super, data, sz_long);
                    677:                } else {
                    678:                        mmu_put_user_byte(addr, val >> 24, super, data, sz_long);
                    679:                        mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long);
                    680:                        mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long);
                    681:                        mmu_put_user_byte(addr + 3, val, super, data, sz_long);
                    682:                }
                    683:                RESTORE_EXCEPTION;
                    684:        }
                    685:        CATCH(prb) {
                    686:                RESTORE_EXCEPTION;
                    687:                regs.wb3_data = val;
                    688:                if (regs.mmu_fault_addr != addr) {
                    689:                        regs.mmu_fault_addr = addr;
                    690:                        regs.mmu_ssw |= MMU_SSW_MA;
                    691:                }
                    692:                THROW_AGAIN(prb);
                    693:        } ENDTRY
                    694: }
                    695: 
                    696: void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val)
                    697: {
                    698:        bool super = (regs.dfc & 4) != 0;
                    699:        bool data = (regs.dfc & 3) != 2;
                    700: 
                    701:        SAVE_EXCEPTION;
                    702:        TRY(prb) {
                    703:                if (likely(!is_unaligned(addr, 2)))
                    704:                        mmu_put_user_word(addr, val, super, data, sz_word);
                    705:                else {
                    706:                        mmu_put_user_byte(addr, val >> 8, super, data, sz_word);
                    707:                        mmu_put_user_byte(addr + 1, val, super, data, sz_word);
                    708:                }
                    709:                RESTORE_EXCEPTION;
                    710:        }
                    711:        CATCH(prb) {
                    712:                RESTORE_EXCEPTION;
                    713:                regs.wb3_data = val;
                    714:                if (regs.mmu_fault_addr != addr) {
                    715:                        regs.mmu_fault_addr = addr;
                    716:                        regs.mmu_ssw |= MMU_SSW_MA;
                    717:                }
                    718:                THROW_AGAIN(prb);
                    719:        } ENDTRY
                    720: }
                    721: 
                    722: void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val)
                    723: {
                    724:        bool super = (regs.dfc & 4) != 0;
                    725:        bool data = (regs.dfc & 3) != 2;
                    726: 
                    727:        SAVE_EXCEPTION;
                    728:        TRY(prb) {
                    729:                mmu_put_user_byte(addr, val, super, data, sz_byte);
                    730:                RESTORE_EXCEPTION;
                    731:        }
                    732:        CATCH(prb) {
                    733:                RESTORE_EXCEPTION;
                    734:                regs.wb3_data = val;
                    735:                THROW_AGAIN(prb);
                    736:        } ENDTRY
                    737: }
                    738: 
                    739: void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra)
                    740: {
                    741:        bool super = (regs.dfc & 4) != 0;
                    742:        DUNUSED(extra);
                    743:        if ((opcode & 0xFE0) == 0x0500) {
                    744:                bool glob;
                    745:                int regno;
                    746:                //D(didflush = 0);
                    747:                uae_u32 addr;
                    748:                /* PFLUSH */
                    749:                regno = opcode & 7;
                    750:                glob = (opcode & 8) != 0;
                    751: 
                    752:                if (opcode & 16) {
                    753:                        fprintf(stderr, "pflusha(%u,%u)\n", glob, regs.dfc);
                    754:                        mmu_flush_atc_all(glob);
                    755:                } else {
                    756:                        addr = m68k_areg(regs, regno);
                    757:                        fprintf(stderr, "pflush(%u,%u,%x)\n", glob, regs.dfc, addr);
                    758:                        mmu_flush_atc(addr, super, glob);
                    759:                }
                    760:                flush_internals();
                    761: #ifdef USE_JIT
                    762:                flush_icache(0);
                    763: #endif
                    764:        } else if ((opcode & 0x0FD8) == 0x548) {
                    765:                bool write;
                    766:                int regno;
                    767:                uae_u32 addr;
                    768: 
                    769:                regno = opcode & 7;
                    770:                write = (opcode & 32) == 0;
                    771:                addr = m68k_areg(regs, regno);
                    772:                fprintf(stderr, "PTEST%c (A%d) %08x DFC=%d\n", write ? 'W' : 'R', regno, addr, regs.dfc);
                    773:                mmu_flush_atc(addr, super, true);
                    774:                SAVE_EXCEPTION;
                    775:                TRY(prb) {
                    776:                        struct mmu_atc_line *l;
                    777:                        uae_u32 desc;
                    778:                        bool data = (regs.dfc & 3) != 2;
                    779: 
                    780:                        if (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH) 
                    781:                                regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
                    782:                        else {
                    783:                                mmu_user_lookup(addr, super, data, write, &l);
                    784:                                desc = mmu_fill_atc(addr, super, data, write, l);
                    785:                                if (!(l->valid))
                    786:                                        regs.mmusr = MMU_MMUSR_B;
                    787:                                else {
                    788:                                        regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S|
                    789:                                                                                 MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W);
                    790:                                        regs.mmusr |= MMU_MMUSR_R;
                    791:                                }
                    792:                        }
                    793:                }
                    794:                CATCH(prb) {
                    795:                        regs.mmusr = MMU_MMUSR_B;
                    796:                } ENDTRY
                    797:                RESTORE_EXCEPTION;
                    798:                fprintf(stderr, "PTEST result: mmusr %08x\n", regs.mmusr);
                    799:        } else
                    800:                op_illg (opcode);
                    801: }
                    802: 
                    803: // fixme : global parameter?
                    804: void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global)
                    805: {
                    806:        int way,type,index;
                    807: 
                    808:        addr = ((mmu_is_super?0x80000000:0x00000000)|(addr >> 1)) & (regs.mmu_pagesize_8k?0xFFFE0000:0xFFFF0000);
                    809:        if (regs.mmu_pagesize_8k)
                    810:                index=(addr & 0x0001E000)>>13;
                    811:        else
                    812:                index=(addr & 0x0000F000)>>12;
                    813:        for (type=0;type<ATC_TYPE;type++)
                    814:        for (way=0;way<ATC_WAYS;way++) {
                    815:                if (!global && mmu_atc_array[type][way][index].global)
                    816:                        continue;
                    817:                // if we have this 
                    818:                if ((addr == mmu_atc_array[type][way][index].tag) && (mmu_atc_array[type][way][index].valid)) {
                    819:                        mmu_atc_array[type][way][index].valid=false;
                    820:                }
                    821:        }       
                    822: }
                    823: 
                    824: void REGPARAM2 mmu_flush_atc_all(bool global)
                    825: {
                    826:        unsigned int way,slot,type;
                    827:        for (type=0;type<ATC_TYPE;type++) 
                    828:        for (way=0;way<ATC_WAYS;way++) 
                    829:        for (slot=0;slot<ATC_SLOTS;slot++) {
                    830:                if (!global && mmu_atc_array[type][way][slot].global)
                    831:                        continue;
                    832:                mmu_atc_array[type][way][slot].valid=false;
                    833:        }
                    834: }
                    835: 
                    836: void REGPARAM2 mmu_reset(void)
                    837: {
                    838:        mmu_flush_atc_all(true);
                    839: }
                    840: 
                    841: 
                    842: void REGPARAM2 mmu_set_tc(uae_u16 tc)
                    843: {
                    844:        regs.mmu_enabled = tc & 0x8000 ? 1 : 0;
                    845:        regs.mmu_pagesize_8k = tc & 0x4000 ? 1 : 0;
                    846:        mmu_flush_atc_all(true);
                    847: 
                    848:        write_log("MMU: enabled=%d page8k=%d\n", regs.mmu_enabled, regs.mmu_pagesize_8k);
                    849: }
                    850: 
                    851: void REGPARAM2 mmu_set_super(bool super)
                    852: {
                    853:        mmu_is_super=super;
                    854: }
                    855: 
                    856: jmp_buf __exbuf;
                    857: int     __exvalue;
                    858: #define MAX_TRY_STACK 256
                    859: static int s_try_stack_size=0;
                    860: static jmp_buf s_try_stack[MAX_TRY_STACK];
                    861: jmp_buf* __poptry(void) {
                    862:        if (s_try_stack_size>0) {
1.1.1.3 ! root      863:         s_try_stack_size--;
        !           864:         if (s_try_stack_size == 0)
        !           865:             return NULL;
        !           866:         memcpy(&__exbuf,&s_try_stack[s_try_stack_size-1],sizeof(jmp_buf));
        !           867:         // fprintf(stderr,"pop jmpbuf=%08x\n",s_try_stack[s_try_stack_size][0]);
        !           868:         return &s_try_stack[s_try_stack_size-1];
        !           869:     }
1.1.1.2   root      870:        else {
                    871:                fprintf(stderr,"try stack underflow...\n");
                    872:            // return (NULL);
                    873:                abort();
                    874:        }
                    875: }
1.1.1.3 ! root      876: void __pushtry(jmp_buf* j) {
1.1.1.2   root      877:        if (s_try_stack_size<MAX_TRY_STACK) {
                    878:                // fprintf(stderr,"push jmpbuf=%08x\n",(*j)[0]);
                    879:                memcpy(&s_try_stack[s_try_stack_size],j,sizeof(jmp_buf));
                    880:                s_try_stack_size++;
                    881:        } else {
                    882:                fprintf(stderr,"try stack overflow...\n");
                    883:                abort();
                    884:        }
                    885: }
                    886: int __is_catched(void) {return (s_try_stack_size>0); }
                    887: #else
                    888: 
                    889: void mmu_op(uae_u32 opcode, uae_u16 /*extra*/)
                    890: {
                    891:        if ((opcode & 0xFE0) == 0x0500) {
                    892:                /* PFLUSH instruction */
                    893:                flush_internals();
                    894:        } else if ((opcode & 0x0FD8) == 0x548) {
                    895:                /* PTEST instruction */
                    896:        } else
                    897:                op_illg(opcode);
                    898: }
                    899: 
                    900: #endif
                    901: 
                    902: /*
                    903: vim:ts=4:sw=4:
                    904: */

unix.superglobalmegacorp.com

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