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

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

unix.superglobalmegacorp.com

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