Annotation of hatari/src/cpu/newcpu.c, revision 1.1

1.1     ! root        1: /*
        !             2: * UAE - The Un*x Amiga Emulator
        !             3: *
        !             4: * MC68000 emulation
        !             5: *
        !             6: * (c) 1995 Bernd Schmidt
        !             7: */
        !             8: 
        !             9: #define MOVEC_DEBUG 0
        !            10: #define MMUOP_DEBUG 2
        !            11: #define DEBUG_CD32CDTVIO 0
        !            12: 
        !            13: /*
        !            14:  * #include "compat.h"
        !            15: #include "sysconfig.h"
        !            16: #include "sysdeps.h"
        !            17: 
        !            18: #include "options_cpu.h"
        !            19: #include "events.h"
        !            20: //#include "uae.h"
        !            21: #include "memory.h"
        !            22: #include "custom.h"
        !            23: #include "newcpu.h"
        !            24: #include "cpummu.h"
        !            25: #include "cpu_prefetch.h"
        !            26: //#include "autoconf.h"
        !            27: //#include "traps.h"
        !            28: //#include "ersatz.h"
        !            29: //#include "debug.h"
        !            30: //#include "gui.h"
        !            31: #include "savestate.h"
        !            32: #include "blitter.h"
        !            33: #include "ar.h"
        !            34: //#include "gayle.h"
        !            35: //#include "cia.h"
        !            36: //#include "inputdevice.h"
        !            37: */
        !            38: 
        !            39: #include "compat.h"
        !            40: #include "sysconfig.h"
        !            41: #include "sysdeps.h"
        !            42: #include "hatari-glue.h"
        !            43: #include "options_cpu.h"
        !            44: #include "events.h"
        !            45: #include "custom.h"
        !            46: #include "maccess.h"
        !            47: #include "memory.h"
        !            48: #include "newcpu.h"
        !            49: #include "main.h"
        !            50: #include "cpummu.h"
        !            51: #include "cpu_prefetch.h"
        !            52: #include "main.h"
        !            53: #include "m68000.h"
        !            54: #include "reset.h"
        !            55: #include "cycInt.h"
        !            56: #include "mfp.h"
        !            57: #include "tos.h"
        !            58: #include "vdi.h"
        !            59: #include "cart.h"
        !            60: #include "dialog.h"
        !            61: #include "bios.h"
        !            62: #include "xbios.h"
        !            63: #include "screen.h"
        !            64: #include "video.h"
        !            65: #include "options.h"
        !            66: #include "dsp.h"
        !            67: #include "log.h"
        !            68: #include "debugui.h"
        !            69: #include "debugcpu.h"
        !            70: 
        !            71: 
        !            72: #ifdef JIT
        !            73: #include "jit/compemu.h"
        !            74: #include <signal.h>
        !            75: #else
        !            76: /* Need to have these somewhere */
        !            77: // static void build_comp (void) {}
        !            78: // bool check_prefs_changed_comp (void) { return false; }
        !            79: #endif
        !            80: /* For faster JIT cycles handling */
        !            81: signed long pissoff = 0;
        !            82: 
        !            83: uaecptr rtarea_base = RTAREA_DEFAULT;
        !            84: 
        !            85: /* Opcode of faulting instruction */
        !            86: static uae_u16 last_op_for_exception_3;
        !            87: /* PC at fault time */
        !            88: static uaecptr last_addr_for_exception_3;
        !            89: /* Address that generated the exception */
        !            90: static uaecptr last_fault_for_exception_3;
        !            91: /* read (0) or write (1) access */
        !            92: static int last_writeaccess_for_exception_3;
        !            93: /* instruction (1) or data (0) access */
        !            94: static int last_instructionaccess_for_exception_3;
        !            95: unsigned long irqcycles[15];
        !            96: int irqdelay[15];
        !            97: int mmu_enabled, mmu_triggered;
        !            98: int cpu_cycles;
        !            99: static int baseclock;
        !           100: int cpucycleunit;
        !           101: 
        !           102: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
        !           103: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
        !           104: 
        !           105: int movem_index1[256];
        !           106: int movem_index2[256];
        !           107: int movem_next[256];
        !           108: 
        !           109: cpuop_func *cpufunctbl[65536];
        !           110: 
        !           111: int OpcodeFamily;
        !           112: struct mmufixup mmufixup[2];
        !           113: 
        !           114: extern uae_u32 get_fpsr (void);
        !           115: 
        !           116: #define COUNT_INSTRS 0
        !           117: #define MC68060_PCR   0x04300000
        !           118: #define MC68EC060_PCR 0x04310000
        !           119: 
        !           120: static uae_u64 srp_030, crp_030;
        !           121: static uae_u32 tt0_030, tt1_030, tc_030;
        !           122: static uae_u16 mmusr_030;
        !           123: 
        !           124: static struct cache020 caches020[CACHELINES020];
        !           125: static struct cache030 icaches030[CACHELINES030];
        !           126: static struct cache030 dcaches030[CACHELINES030];
        !           127: static struct cache040 caches040[CACHESETS040];
        !           128: static void InterruptAddJitter (int Level , int Pending);
        !           129: 
        !           130: static void m68k_disasm_2 (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode);
        !           131: 
        !           132: 
        !           133: #if COUNT_INSTRS
        !           134: static unsigned long int instrcount[65536];
        !           135: static uae_u16 opcodenums[65536];
        !           136: 
        !           137: static int compfn (const void *el1, const void *el2)
        !           138: {
        !           139:        return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
        !           140: }
        !           141: 
        !           142: static TCHAR *icountfilename (void)
        !           143: {
        !           144:        TCHAR *name = getenv ("INSNCOUNT");
        !           145:        if (name)
        !           146:                return name;
        !           147:        return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
        !           148: }
        !           149: 
        !           150: void dump_counts (void)
        !           151: {
        !           152:        FILE *f = fopen (icountfilename (), "w");
        !           153:        unsigned long int total;
        !           154:        int i;
        !           155: 
        !           156:        write_log ("Writing instruction count file...\n");
        !           157:        for (i = 0; i < 65536; i++) {
        !           158:                opcodenums[i] = i;
        !           159:                total += instrcount[i];
        !           160:        }
        !           161:        qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
        !           162: 
        !           163:        fprintf (f, "Total: %lu\n", total);
        !           164:        for (i=0; i < 65536; i++) {
        !           165:                unsigned long int cnt = instrcount[opcodenums[i]];
        !           166:                struct instr *dp;
        !           167:                struct mnemolookup *lookup;
        !           168:                if (!cnt)
        !           169:                        break;
        !           170:                dp = table68k + opcodenums[i];
        !           171:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
        !           172:                        ;
        !           173:                fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
        !           174:        }
        !           175:        fclose (f);
        !           176: }
        !           177: #else
        !           178: void dump_counts (void)
        !           179: {
        !           180: }
        !           181: #endif
        !           182: 
        !           183: 
        !           184: uae_u32 (*x_prefetch)(int);
        !           185: uae_u32 (*x_next_iword)(void);
        !           186: uae_u32 (*x_next_ilong)(void);
        !           187: uae_u32 (*x_get_long)(uaecptr);
        !           188: uae_u32 (*x_get_word)(uaecptr);
        !           189: uae_u32 (*x_get_byte)(uaecptr);
        !           190: void (*x_put_long)(uaecptr,uae_u32);
        !           191: void (*x_put_word)(uaecptr,uae_u32);
        !           192: void (*x_put_byte)(uaecptr,uae_u32);
        !           193: 
        !           194: // shared memory access functions
        !           195: static void set_x_funcs (void)
        !           196: {
        !           197:        if (currprefs.mmu_model) {
        !           198:                x_prefetch = get_iword_mmu;
        !           199:                x_next_iword = next_iword_mmu;
        !           200:                x_next_ilong = next_ilong_mmu;
        !           201:                x_put_long = put_long_mmu;
        !           202:                x_put_word = put_word_mmu;
        !           203:                x_put_byte = put_byte_mmu;
        !           204:                x_get_long = get_long_mmu;
        !           205:                x_get_word = get_word_mmu;
        !           206:                x_get_byte = get_byte_mmu;
        !           207:        } else if (!currprefs.cpu_cycle_exact) {
        !           208:                x_prefetch = get_iword;
        !           209:                x_next_iword = next_iword;
        !           210:                x_next_ilong = next_ilong;
        !           211:                x_put_long = put_long;
        !           212:                x_put_word = put_word;
        !           213:                x_put_byte = put_byte;
        !           214:                x_get_long = get_long;
        !           215:                x_get_word = get_word;
        !           216:                x_get_byte = get_byte;
        !           217:        } else if (currprefs.cpu_model < 68020) {
        !           218:                x_prefetch = NULL;
        !           219:                x_next_iword = NULL;
        !           220:                x_next_ilong = NULL;
        !           221:                x_put_long = put_long_ce;
        !           222:                x_put_word = put_word_ce;
        !           223:                x_put_byte = put_byte_ce;
        !           224:                x_get_long = get_long_ce;
        !           225:                x_get_word = get_word_ce;
        !           226:                x_get_byte = get_byte_ce;
        !           227:        } else if (currprefs.cpu_model == 68020) {
        !           228:                x_prefetch = get_word_ce020_prefetch;
        !           229:                x_next_iword = next_iword_020ce;
        !           230:                x_next_ilong = next_ilong_020ce;
        !           231:                x_put_long = put_long_ce020;
        !           232:                x_put_word = put_word_ce020;
        !           233:                x_put_byte = put_byte_ce020;
        !           234:                x_get_long = get_long_ce020;
        !           235:                x_get_word = get_word_ce020;
        !           236:                x_get_byte = get_byte_ce020;
        !           237:        } else {
        !           238:                x_prefetch = get_word_ce030_prefetch;
        !           239:                x_next_iword = next_iword_030ce;
        !           240:                x_next_ilong = next_ilong_030ce;
        !           241:                x_put_long = put_long_ce030;
        !           242:                x_put_word = put_word_ce030;
        !           243:                x_put_byte = put_byte_ce030;
        !           244:                x_get_long = get_long_ce030;
        !           245:                x_get_word = get_word_ce030;
        !           246:                x_get_byte = get_byte_ce030;
        !           247:        }
        !           248: 
        !           249: }
        !           250: 
        !           251: static void set_cpu_caches (void)
        !           252: {
        !           253:        int i;
        !           254: 
        !           255:        for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !           256:                regs.prefetch020addr[i] = 0xffffffff;
        !           257: 
        !           258: #ifdef JIT
        !           259:        if (currprefs.cachesize) {
        !           260:                if (currprefs.cpu_model < 68040) {
        !           261:                        set_cache_state (regs.cacr & 1);
        !           262:                        if (regs.cacr & 0x08) {
        !           263:                                flush_icache (0, 3);
        !           264:                        }
        !           265:                } else {
        !           266:                        set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
        !           267:                }
        !           268:        }
        !           269: #endif
        !           270:        if (currprefs.cpu_model == 68020) {
        !           271:                if (regs.cacr & 0x08) { // clear instr cache
        !           272:                        for (i = 0; i < CACHELINES020; i++)
        !           273:                                caches020[i].valid = 0;
        !           274:                }
        !           275:                if (regs.cacr & 0x04) { // clear entry in instr cache
        !           276:                        caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
        !           277:                        regs.cacr &= ~0x04;
        !           278:                }
        !           279:        } else if (currprefs.cpu_model == 68030) {
        !           280:                //regs.cacr |= 0x100;
        !           281:                if (regs.cacr & 0x08) { // clear instr cache
        !           282:                        for (i = 0; i < CACHELINES030; i++) {
        !           283:                                icaches030[i].valid[0] = 0;
        !           284:                                icaches030[i].valid[1] = 0;
        !           285:                                icaches030[i].valid[2] = 0;
        !           286:                                icaches030[i].valid[3] = 0;
        !           287:                        }
        !           288:                }
        !           289:                if (regs.cacr & 0x04) { // clear entry in instr cache
        !           290:                        icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
        !           291:                        regs.cacr &= ~0x04;
        !           292:                }
        !           293:                if (regs.cacr & 0x800) { // clear data cache
        !           294:                        for (i = 0; i < CACHELINES030; i++) {
        !           295:                                dcaches030[i].valid[0] = 0;
        !           296:                                dcaches030[i].valid[1] = 0;
        !           297:                                dcaches030[i].valid[2] = 0;
        !           298:                                dcaches030[i].valid[3] = 0;
        !           299:                        }
        !           300:                        regs.cacr &= ~0x800;
        !           301:                }
        !           302:                if (regs.cacr & 0x400) { // clear entry in data cache
        !           303:                        dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
        !           304:                        regs.cacr &= ~0x400;
        !           305:                }
        !           306:        } else if (currprefs.cpu_model == 68040) {
        !           307:                if (!(regs.cacr & 0x8000)) {
        !           308:                        for (i = 0; i < CACHESETS040; i++) {
        !           309:                                caches040[i].valid[0] = 0;
        !           310:                                caches040[i].valid[1] = 0;
        !           311:                                caches040[i].valid[2] = 0;
        !           312:                                caches040[i].valid[3] = 0;
        !           313:                        }
        !           314:                }
        !           315:        }
        !           316: }
        !           317: 
        !           318: STATIC_INLINE void count_instr (unsigned int opcode)
        !           319: {
        !           320: }
        !           321: 
        !           322: static unsigned long REGPARAM3 op_illg_1 (uae_u32 opcode) REGPARAM;
        !           323: 
        !           324: static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode)
        !           325: {
        !           326:        op_illg (opcode);
        !           327:        return 4;
        !           328: }
        !           329: 
        !           330: void build_cpufunctbl (void)
        !           331: {
        !           332:        int i, opcnt;
        !           333:        unsigned long opcode;
        !           334:        const struct cputbl *tbl = 0;
        !           335:        int lvl;
        !           336: 
        !           337:        switch (currprefs.cpu_model)
        !           338:        {
        !           339: #ifdef CPUEMU_0
        !           340: #ifndef CPUEMU_68000_ONLY
        !           341:        case 68060:
        !           342:                lvl = 5;
        !           343:                tbl = op_smalltbl_0_ff;
        !           344:                if (currprefs.cpu_cycle_exact)
        !           345:                        tbl = op_smalltbl_21_ff;
        !           346:                if (currprefs.mmu_model)
        !           347:                        tbl = op_smalltbl_31_ff;
        !           348:                break;
        !           349:        case 68040:
        !           350:                lvl = 4;
        !           351:                tbl = op_smalltbl_1_ff;
        !           352:                if (currprefs.cpu_cycle_exact)
        !           353:                        tbl = op_smalltbl_22_ff;
        !           354:                if (currprefs.mmu_model)
        !           355:                        tbl = op_smalltbl_31_ff;
        !           356:                break;
        !           357:        case 68030:
        !           358:                lvl = 3;
        !           359:                tbl = op_smalltbl_2_ff;
        !           360:                if (currprefs.cpu_cycle_exact)
        !           361:                        tbl = op_smalltbl_23_ff;
        !           362:                break;
        !           363:        case 68020:
        !           364:                lvl = 2;
        !           365:                tbl = op_smalltbl_3_ff;
        !           366:                if (currprefs.cpu_cycle_exact)
        !           367:                        tbl = op_smalltbl_20_ff;
        !           368:                break;
        !           369:        case 68010:
        !           370:                lvl = 1;
        !           371:                tbl = op_smalltbl_4_ff;
        !           372:                break;
        !           373: #endif
        !           374: #endif
        !           375:        default:
        !           376:                changed_prefs.cpu_model = currprefs.cpu_model = 68000;
        !           377:        case 68000:
        !           378:                lvl = 0;
        !           379:                tbl = op_smalltbl_5_ff;
        !           380: #ifdef CPUEMU_11
        !           381:                if (currprefs.cpu_compatible)
        !           382:                        tbl = op_smalltbl_11_ff; /* prefetch */
        !           383: #endif
        !           384: #ifdef CPUEMU_12
        !           385:                if (currprefs.cpu_cycle_exact)
        !           386:                        tbl = op_smalltbl_12_ff; /* prefetch and cycle-exact */
        !           387: #endif
        !           388:                break;
        !           389:        }
        !           390: 
        !           391:        if (tbl == 0) {
        !           392:                write_log ("no CPU emulation cores available CPU=%d!", currprefs.cpu_model);
        !           393:                abort ();
        !           394:        }
        !           395: 
        !           396:        for (opcode = 0; opcode < 65536; opcode++)
        !           397:                cpufunctbl[opcode] = op_illg_1;
        !           398:        for (i = 0; tbl[i].handler != NULL; i++) {
        !           399:                opcode = tbl[i].opcode;
        !           400:                cpufunctbl[opcode] = tbl[i].handler;
        !           401:        }
        !           402: 
        !           403:        /* hack fpu to 68000/68010 mode */
        !           404:        if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
        !           405:                tbl = op_smalltbl_3_ff;
        !           406:                for (i = 0; tbl[i].handler != NULL; i++) {
        !           407:                        if ((tbl[i].opcode & 0xfe00) == 0xf200)
        !           408:                                cpufunctbl[tbl[i].opcode] = tbl[i].handler;
        !           409:                }
        !           410:        }
        !           411:        opcnt = 0;
        !           412:        for (opcode = 0; opcode < 65536; opcode++) {
        !           413:                cpuop_func *f;
        !           414: 
        !           415:                if (table68k[opcode].mnemo == i_ILLG)
        !           416:                        continue;
        !           417:                if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
        !           418:                        /* more hack fpu to 68000/68010 mode */
        !           419:                        if (table68k[opcode].clev > lvl && (opcode & 0xfe00) != 0xf200)
        !           420:                                continue;
        !           421:                } else if (table68k[opcode].clev > lvl) {
        !           422:                        continue;
        !           423:                }
        !           424: 
        !           425:                if (table68k[opcode].handler != -1) {
        !           426:                        int idx = table68k[opcode].handler;
        !           427:                        f = cpufunctbl[idx];
        !           428:                        if (f == op_illg_1)
        !           429:                                abort ();
        !           430:                        cpufunctbl[opcode] = f;
        !           431:                        opcnt++;
        !           432:                }
        !           433:        }
        !           434:        write_log ("Building CPU, %d opcodes (%d %d %d)\n",
        !           435:                opcnt, lvl,
        !           436:                currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24);
        !           437:        write_log ("CPU=%d, FPU=%d, MMU=%d, JIT%s=%d.\n",
        !           438:                currprefs.cpu_model, currprefs.fpu_model,
        !           439:                currprefs.mmu_model,
        !           440:                currprefs.cachesize ? (currprefs.compfpu ? "=CPU/FPU" : "=CPU") : "",
        !           441:                currprefs.cachesize);
        !           442: #ifdef JIT
        !           443:        build_comp ();
        !           444: #endif
        !           445:        set_cpu_caches ();
        !           446:        if (currprefs.mmu_model) {
        !           447:                mmu_reset ();
        !           448:                mmu_set_tc (regs.tcr);
        !           449:                mmu_set_super (regs.s != 0);
        !           450:        }
        !           451: }
        !           452: 
        !           453: void fill_prefetch_slow (void)
        !           454: {
        !           455:        if (currprefs.mmu_model)
        !           456:                return;
        !           457:        regs.ir = x_get_word (m68k_getpc ());
        !           458:        regs.irc = x_get_word (m68k_getpc () + 2);
        !           459: }
        !           460: 
        !           461: unsigned long cycles_mask, cycles_val;
        !           462: 
        !           463: static void update_68k_cycles (void)
        !           464: {
        !           465:        cycles_mask = 0;
        !           466:        cycles_val = currprefs.m68k_speed;
        !           467:        if (currprefs.m68k_speed < 1) {
        !           468:                cycles_mask = 0xFFFFFFFF;
        !           469:                cycles_val = 0;
        !           470:        }
        !           471:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
        !           472:        currprefs.cpu_frequency = changed_prefs.cpu_frequency;
        !           473: 
        !           474:        baseclock = currprefs.ntscmode ? 28636360 : 28375160;
        !           475:        cpucycleunit = CYCLE_UNIT / 2;
        !           476:        if (currprefs.cpu_clock_multiplier) {
        !           477:                if (currprefs.cpu_clock_multiplier >= 256) {
        !           478:                        cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
        !           479:                } else {
        !           480:                        cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
        !           481:                }
        !           482:        } else if (currprefs.cpu_frequency) {
        !           483:                cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
        !           484:        }
        !           485:        if (cpucycleunit < 1)
        !           486:                cpucycleunit = 1;
        !           487:        if (currprefs.cpu_cycle_exact)
        !           488:                write_log ("CPU cycleunit: %d (%.3f)\n", cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
        !           489:        config_changed = 1;
        !           490: }
        !           491: 
        !           492: static void prefs_changed_cpu (void)
        !           493: {
        !           494:        fixup_cpu (&changed_prefs);
        !           495:        currprefs.cpu_model = changed_prefs.cpu_model;
        !           496:        currprefs.fpu_model = changed_prefs.fpu_model;
        !           497:        currprefs.mmu_model = changed_prefs.mmu_model;
        !           498:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
        !           499:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
        !           500:        currprefs.blitter_cycle_exact = changed_prefs.cpu_cycle_exact;
        !           501: }
        !           502: 
        !           503: void check_prefs_changed_cpu (void)
        !           504: {
        !           505:        bool changed = 0;
        !           506: 
        !           507:        if (!config_changed)
        !           508:                return;
        !           509: #ifdef JIT
        !           510:        changed = check_prefs_changed_comp ();
        !           511: #endif
        !           512:        if (changed
        !           513:                || currprefs.cpu_model != changed_prefs.cpu_model
        !           514:                || currprefs.fpu_model != changed_prefs.fpu_model
        !           515:                || currprefs.mmu_model != changed_prefs.mmu_model
        !           516:                || currprefs.cpu_compatible != changed_prefs.cpu_compatible
        !           517:                || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) {
        !           518: 
        !           519:                        prefs_changed_cpu ();
        !           520:                        if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible)
        !           521:                                fill_prefetch_slow ();
        !           522:                        build_cpufunctbl ();
        !           523:                        changed = 1;
        !           524:        }
        !           525:        if (changed
        !           526:                || currprefs.m68k_speed != changed_prefs.m68k_speed
        !           527:                || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
        !           528:                || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
        !           529:                        currprefs.m68k_speed = changed_prefs.m68k_speed;
        !           530:                        reset_frame_rate_hack ();
        !           531:                        update_68k_cycles ();
        !           532:                        changed = 1;
        !           533:        }
        !           534: 
        !           535:        if (currprefs.cpu_idle != changed_prefs.cpu_idle) {
        !           536:                currprefs.cpu_idle = changed_prefs.cpu_idle;
        !           537:        }
        !           538:        if (changed)
        !           539:                set_special (SPCFLAG_BRK);
        !           540: 
        !           541: }
        !           542: 
        !           543: void init_m68k (void)
        !           544: {
        !           545:        int i;
        !           546: 
        !           547:        prefs_changed_cpu ();
        !           548:        update_68k_cycles ();
        !           549: 
        !           550:        for (i = 0 ; i < 256 ; i++) {
        !           551:                int j;
        !           552:                for (j = 0 ; j < 8 ; j++) {
        !           553:                        if (i & (1 << j)) break;
        !           554:                }
        !           555:                movem_index1[i] = j;
        !           556:                movem_index2[i] = 7-j;
        !           557:                movem_next[i] = i & (~(1 << j));
        !           558:        }
        !           559: 
        !           560: #if COUNT_INSTRS
        !           561:        {
        !           562:                FILE *f = fopen (icountfilename (), "r");
        !           563:                memset (instrcount, 0, sizeof instrcount);
        !           564:                if (f) {
        !           565:                        uae_u32 opcode, count, total;
        !           566:                        TCHAR name[20];
        !           567:                        write_log ("Reading instruction count file...\n");
        !           568:                        fscanf (f, "Total: %lu\n", &total);
        !           569:                        while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
        !           570:                                instrcount[opcode] = count;
        !           571:                        }
        !           572:                        fclose (f);
        !           573:                }
        !           574:        }
        !           575: #endif
        !           576:        write_log ("Building CPU table for configuration: %d", currprefs.cpu_model);
        !           577:        regs.address_space_mask = 0xffffffff;
        !           578: //     if (currprefs.cpu_compatible) {
        !           579: //             if (currprefs.address_space_24 && currprefs.cpu_model >= 68030)
        !           580: //                     currprefs.address_space_24 = false;
        !           581: //     }
        !           582:        if (currprefs.fpu_model > 0)
        !           583:                write_log ("/%d", currprefs.fpu_model);
        !           584:        if (currprefs.cpu_cycle_exact) {
        !           585:                if (currprefs.cpu_model == 68000)
        !           586:                        write_log (" prefetch and cycle-exact");
        !           587:                else
        !           588:                        write_log (" ~cycle-exact");
        !           589:        } else if (currprefs.cpu_compatible)
        !           590:                write_log (" prefetch");
        !           591:        if (currprefs.address_space_24) {
        !           592:                regs.address_space_mask = 0x00ffffff;
        !           593:                write_log (" 24-bit");
        !           594:        }
        !           595:        write_log ("\n");
        !           596: 
        !           597:        read_table68k ();
        !           598:        do_merges ();
        !           599: 
        !           600:        write_log ("%d CPU functions\n", nr_cpuop_funcs);
        !           601: 
        !           602:        build_cpufunctbl ();
        !           603:        set_x_funcs ();
        !           604: 
        !           605: #ifdef JIT
        !           606:        /* We need to check whether NATMEM settings have changed
        !           607:        * before starting the CPU */
        !           608:        check_prefs_changed_comp ();
        !           609: #endif
        !           610: }
        !           611: 
        !           612: struct regstruct regs, mmu_backup_regs;
        !           613: struct flag_struct regflags;
        !           614: static struct regstruct regs_backup[16];
        !           615: static int backup_pointer = 0;
        !           616: static long int m68kpc_offset;
        !           617: 
        !           618: #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
        !           619: #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
        !           620: #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
        !           621: 
        !           622: static uae_s32 ShowEA (FILE *f, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
        !           623: {
        !           624:        uae_u16 dp;
        !           625:        uae_s8 disp8;
        !           626:        uae_s16 disp16;
        !           627:        int r;
        !           628:        uae_u32 dispreg;
        !           629:        uaecptr addr = 0;
        !           630:        uae_s32 offset = 0;
        !           631:        TCHAR buffer[80];
        !           632: 
        !           633:        switch (mode){
        !           634:        case Dreg:
        !           635:                _stprintf (buffer, "D%d", reg);
        !           636:                break;
        !           637:        case Areg:
        !           638:                _stprintf (buffer, "A%d", reg);
        !           639:                break;
        !           640:        case Aind:
        !           641:                _stprintf (buffer, "(A%d)", reg);
        !           642:                addr = regs.regs[reg + 8];
        !           643:                break;
        !           644:        case Aipi:
        !           645:                _stprintf (buffer, "(A%d)+", reg);
        !           646:                addr = regs.regs[reg + 8];
        !           647:                break;
        !           648:        case Apdi:
        !           649:                _stprintf (buffer, "-(A%d)", reg);
        !           650:                addr = regs.regs[reg + 8];
        !           651:                break;
        !           652:        case Ad16:
        !           653:                {
        !           654:                        TCHAR offtxt[80];
        !           655:                        disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           656:                        if (disp16 < 0)
        !           657:                                _stprintf (offtxt, "-$%04x", -disp16);
        !           658:                        else
        !           659:                                _stprintf (offtxt, "$%04x", disp16);
        !           660:                        addr = m68k_areg (regs, reg) + disp16;
        !           661:                        _stprintf (buffer, "(A%d, %s) == $%08lx", reg, offtxt, (unsigned long)addr);
        !           662:                }
        !           663:                break;
        !           664:        case Ad8r:
        !           665:                dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           666:                disp8 = dp & 0xFF;
        !           667:                r = (dp & 0x7000) >> 12;
        !           668:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
        !           669:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
        !           670:                dispreg <<= (dp >> 9) & 3;
        !           671: 
        !           672:                if (dp & 0x100) {
        !           673:                        uae_s32 outer = 0, disp = 0;
        !           674:                        uae_s32 base = m68k_areg (regs, reg);
        !           675:                        TCHAR name[10];
        !           676:                        _stprintf (name, "A%d, ", reg);
        !           677:                        if (dp & 0x80) { base = 0; name[0] = 0; }
        !           678:                        if (dp & 0x40) dispreg = 0;
        !           679:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
        !           680:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
        !           681:                        base += disp;
        !           682: 
        !           683:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
        !           684:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
        !           685: 
        !           686:                        if (!(dp & 4)) base += dispreg;
        !           687:                        if ((dp & 3) && !safemode) base = get_long (base);
        !           688:                        if (dp & 4) base += dispreg;
        !           689: 
        !           690:                        addr = base + outer;
        !           691:                        _stprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08lx", name,
        !           692:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
        !           693:                                1 << ((dp >> 9) & 3),
        !           694:                                disp, outer,
        !           695:                                (unsigned long)addr);
        !           696:                } else {
        !           697:                        addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
        !           698:                        _stprintf (buffer, "(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg,
        !           699:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
        !           700:                                1 << ((dp >> 9) & 3), disp8,
        !           701:                                (unsigned long)addr);
        !           702:                }
        !           703:                break;
        !           704:        case PC16:
        !           705:                addr = m68k_getpc () + m68kpc_offset;
        !           706:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           707:                addr += (uae_s16)disp16;
        !           708:                _stprintf (buffer, "(PC,$%04x) == $%08lx", disp16 & 0xffff, (unsigned long)addr);
        !           709:                break;
        !           710:        case PC8r:
        !           711:                addr = m68k_getpc () + m68kpc_offset;
        !           712:                dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           713:                disp8 = dp & 0xFF;
        !           714:                r = (dp & 0x7000) >> 12;
        !           715:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
        !           716:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
        !           717:                dispreg <<= (dp >> 9) & 3;
        !           718: 
        !           719:                if (dp & 0x100) {
        !           720:                        uae_s32 outer = 0, disp = 0;
        !           721:                        uae_s32 base = addr;
        !           722:                        TCHAR name[10];
        !           723:                        _stprintf (name, "PC, ");
        !           724:                        if (dp & 0x80) { base = 0; name[0] = 0; }
        !           725:                        if (dp & 0x40) dispreg = 0;
        !           726:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
        !           727:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
        !           728:                        base += disp;
        !           729: 
        !           730:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
        !           731:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
        !           732: 
        !           733:                        if (!(dp & 4)) base += dispreg;
        !           734:                        if ((dp & 3) && !safemode) base = get_long (base);
        !           735:                        if (dp & 4) base += dispreg;
        !           736: 
        !           737:                        addr = base + outer;
        !           738:                        _stprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08lx", name,
        !           739:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
        !           740:                                1 << ((dp >> 9) & 3),
        !           741:                                disp, outer,
        !           742:                                (unsigned long)addr);
        !           743:                } else {
        !           744:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
        !           745:                        _stprintf (buffer, "(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D',
        !           746:                                (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
        !           747:                                disp8, (unsigned long)addr);
        !           748:                }
        !           749:                break;
        !           750:        case absw:
        !           751:                addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
        !           752:                _stprintf (buffer, "$%08lx", (unsigned long)addr);
        !           753:                m68kpc_offset += 2;
        !           754:                break;
        !           755:        case absl:
        !           756:                addr = get_ilong_1 (m68kpc_offset);
        !           757:                _stprintf (buffer, "$%08lx", (unsigned long)addr);
        !           758:                m68kpc_offset += 4;
        !           759:                break;
        !           760:        case imm:
        !           761:                switch (size){
        !           762:                case sz_byte:
        !           763:                        _stprintf (buffer, "#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff));
        !           764:                        m68kpc_offset += 2;
        !           765:                        break;
        !           766:                case sz_word:
        !           767:                        _stprintf (buffer, "#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff));
        !           768:                        m68kpc_offset += 2;
        !           769:                        break;
        !           770:                case sz_long:
        !           771:                        _stprintf (buffer, "#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
        !           772:                        m68kpc_offset += 4;
        !           773:                        break;
        !           774:                default:
        !           775:                        break;
        !           776:                }
        !           777:                break;
        !           778:        case imm0:
        !           779:                offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
        !           780:                m68kpc_offset += 2;
        !           781:                _stprintf (buffer, "#$%02x", (unsigned int)(offset & 0xff));
        !           782:                break;
        !           783:        case imm1:
        !           784:                offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
        !           785:                m68kpc_offset += 2;
        !           786:                buffer[0] = 0;
        !           787:                _stprintf (buffer, "#$%04x", (unsigned int)(offset & 0xffff));
        !           788:                break;
        !           789:        case imm2:
        !           790:                offset = (uae_s32)get_ilong_1 (m68kpc_offset);
        !           791:                m68kpc_offset += 4;
        !           792:                _stprintf (buffer, "#$%08lx", (unsigned long)offset);
        !           793:                break;
        !           794:        case immi:
        !           795:                offset = (uae_s32)(uae_s8)(reg & 0xff);
        !           796:                _stprintf (buffer, "#$%08lx", (unsigned long)offset);
        !           797:                break;
        !           798:        default:
        !           799:                break;
        !           800:        }
        !           801:        if (buf == 0)
        !           802:                f_out (f, "%s", buffer);
        !           803:        else
        !           804:                _tcscat (buf, buffer);
        !           805:        if (eaddr)
        !           806:                *eaddr = addr;
        !           807:        return offset;
        !           808: }
        !           809: 
        !           810: #if 0
        !           811: /* The plan is that this will take over the job of exception 3 handling -
        !           812: * the CPU emulation functions will just do a longjmp to m68k_go whenever
        !           813: * they hit an odd address. */
        !           814: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
        !           815: {
        !           816:        uae_u16 dp;
        !           817:        uae_s8 disp8;
        !           818:        uae_s16 disp16;
        !           819:        int r;
        !           820:        uae_u32 dispreg;
        !           821:        uaecptr addr;
        !           822:        uae_s32 offset = 0;
        !           823: 
        !           824:        switch (mode){
        !           825:        case Dreg:
        !           826:                *val = m68k_dreg (regs, reg);
        !           827:                return 1;
        !           828:        case Areg:
        !           829:                *val = m68k_areg (regs, reg);
        !           830:                return 1;
        !           831: 
        !           832:        case Aind:
        !           833:        case Aipi:
        !           834:                addr = m68k_areg (regs, reg);
        !           835:                break;
        !           836:        case Apdi:
        !           837:                addr = m68k_areg (regs, reg);
        !           838:                break;
        !           839:        case Ad16:
        !           840:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           841:                addr = m68k_areg (regs, reg) + (uae_s16)disp16;
        !           842:                break;
        !           843:        case Ad8r:
        !           844:                addr = m68k_areg (regs, reg);
        !           845: d8r_common:
        !           846:                dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           847:                disp8 = dp & 0xFF;
        !           848:                r = (dp & 0x7000) >> 12;
        !           849:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
        !           850:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
        !           851:                dispreg <<= (dp >> 9) & 3;
        !           852: 
        !           853:                if (dp & 0x100) {
        !           854:                        uae_s32 outer = 0, disp = 0;
        !           855:                        uae_s32 base = addr;
        !           856:                        if (dp & 0x80) base = 0;
        !           857:                        if (dp & 0x40) dispreg = 0;
        !           858:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
        !           859:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
        !           860:                        base += disp;
        !           861: 
        !           862:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
        !           863:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
        !           864: 
        !           865:                        if (!(dp & 4)) base += dispreg;
        !           866:                        if (dp & 3) base = get_long (base);
        !           867:                        if (dp & 4) base += dispreg;
        !           868: 
        !           869:                        addr = base + outer;
        !           870:                } else {
        !           871:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
        !           872:                }
        !           873:                break;
        !           874:        case PC16:
        !           875:                addr = m68k_getpc () + m68kpc_offset;
        !           876:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
        !           877:                addr += (uae_s16)disp16;
        !           878:                break;
        !           879:        case PC8r:
        !           880:                addr = m68k_getpc () + m68kpc_offset;
        !           881:                goto d8r_common;
        !           882:        case absw:
        !           883:                addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
        !           884:                m68kpc_offset += 2;
        !           885:                break;
        !           886:        case absl:
        !           887:                addr = get_ilong_1 (m68kpc_offset);
        !           888:                m68kpc_offset += 4;
        !           889:                break;
        !           890:        case imm:
        !           891:                switch (size){
        !           892:                case sz_byte:
        !           893:                        *val = get_iword_1 (m68kpc_offset) & 0xff;
        !           894:                        m68kpc_offset += 2;
        !           895:                        break;
        !           896:                case sz_word:
        !           897:                        *val = get_iword_1 (m68kpc_offset) & 0xffff;
        !           898:                        m68kpc_offset += 2;
        !           899:                        break;
        !           900:                case sz_long:
        !           901:                        *val = get_ilong_1 (m68kpc_offset);
        !           902:                        m68kpc_offset += 4;
        !           903:                        break;
        !           904:                default:
        !           905:                        break;
        !           906:                }
        !           907:                return 1;
        !           908:        case imm0:
        !           909:                *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
        !           910:                m68kpc_offset += 2;
        !           911:                return 1;
        !           912:        case imm1:
        !           913:                *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
        !           914:                m68kpc_offset += 2;
        !           915:                return 1;
        !           916:        case imm2:
        !           917:                *val = get_ilong_1 (m68kpc_offset);
        !           918:                m68kpc_offset += 4;
        !           919:                return 1;
        !           920:        case immi:
        !           921:                *val = (uae_s32)(uae_s8)(reg & 0xff);
        !           922:                return 1;
        !           923:        default:
        !           924:                addr = 0;
        !           925:                break;
        !           926:        }
        !           927:        if ((addr & 1) == 0)
        !           928:                return 1;
        !           929: 
        !           930:        last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
        !           931:        last_fault_for_exception_3 = addr;
        !           932:        last_writeaccess_for_exception_3 = 0;
        !           933:        last_instructionaccess_for_exception_3 = 0;
        !           934:        return 0;
        !           935: }
        !           936: #endif
        !           937: 
        !           938: int get_cpu_model (void)
        !           939: {
        !           940:        return currprefs.cpu_model;
        !           941: }
        !           942: 
        !           943: /*
        !           944: * extract bitfield data from memory and return it in the MSBs
        !           945: * bdata caches the unmodified data for put_bitfield()
        !           946: */
        !           947: uae_u32 REGPARAM2 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
        !           948: {
        !           949:        uae_u32 tmp, res, mask;
        !           950: 
        !           951:        offset &= 7;
        !           952:        mask = 0xffffffffu << (32 - width);
        !           953:        switch ((offset + width + 7) >> 3) {
        !           954:        case 1:
        !           955:                tmp = get_byte (src);
        !           956:                res = tmp << (24 + offset);
        !           957:                bdata[0] = tmp & ~(mask >> (24 + offset));
        !           958:                break;
        !           959:        case 2:
        !           960:                tmp = get_word (src);
        !           961:                res = tmp << (16 + offset);
        !           962:                bdata[0] = tmp & ~(mask >> (16 + offset));
        !           963:                break;
        !           964:        case 3:
        !           965:                tmp = get_word (src);
        !           966:                res = tmp << (16 + offset);
        !           967:                bdata[0] = tmp & ~(mask >> (16 + offset));
        !           968:                tmp = get_byte (src + 2);
        !           969:                res |= tmp << (8 + offset);
        !           970:                bdata[1] = tmp & ~(mask >> (8 + offset));
        !           971:                break;
        !           972:        case 4:
        !           973:                tmp = get_long (src);
        !           974:                res = tmp << offset;
        !           975:                bdata[0] = tmp & ~(mask >> offset);
        !           976:                break;
        !           977:        case 5:
        !           978:                tmp = get_long (src);
        !           979:                res = tmp << offset;
        !           980:                bdata[0] = tmp & ~(mask >> offset);
        !           981:                tmp = get_byte (src + 4);
        !           982:                res |= tmp >> (8 - offset);
        !           983:                bdata[1] = tmp & ~(mask << (8 - offset));
        !           984:                break;
        !           985:        default:
        !           986:                /* Panic? */
        !           987:                res = 0;
        !           988:                break;
        !           989:        }
        !           990:        return res;
        !           991: }
        !           992: /*
        !           993: * write bitfield data (in the LSBs) back to memory, upper bits
        !           994: * must be cleared already.
        !           995: */
        !           996: void REGPARAM2 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
        !           997: {
        !           998:        offset = (offset & 7) + width;
        !           999:        switch ((offset + 7) >> 3) {
        !          1000:        case 1:
        !          1001:                put_byte (dst, bdata[0] | (val << (8 - offset)));
        !          1002:                break;
        !          1003:        case 2:
        !          1004:                put_word (dst, bdata[0] | (val << (16 - offset)));
        !          1005:                break;
        !          1006:        case 3:
        !          1007:                put_word (dst, bdata[0] | (val >> (offset - 16)));
        !          1008:                put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
        !          1009:                break;
        !          1010:        case 4:
        !          1011:                put_long (dst, bdata[0] | (val << (32 - offset)));
        !          1012:                break;
        !          1013:        case 5:
        !          1014:                put_long (dst, bdata[0] | (val >> (offset - 32)));
        !          1015:                put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
        !          1016:                break;
        !          1017:        }
        !          1018: }
        !          1019: 
        !          1020: uae_u32 REGPARAM2 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
        !          1021: {
        !          1022:        uae_u32 tmp, res, mask;
        !          1023: 
        !          1024:        offset &= 7;
        !          1025:        mask = 0xffffffffu << (32 - width);
        !          1026:        switch ((offset + width + 7) >> 3) {
        !          1027:        case 1:
        !          1028:                tmp = x_get_byte (src);
        !          1029:                res = tmp << (24 + offset);
        !          1030:                bdata[0] = tmp & ~(mask >> (24 + offset));
        !          1031:                break;
        !          1032:        case 2:
        !          1033:                tmp = x_get_word (src);
        !          1034:                res = tmp << (16 + offset);
        !          1035:                bdata[0] = tmp & ~(mask >> (16 + offset));
        !          1036:                break;
        !          1037:        case 3:
        !          1038:                tmp = x_get_word (src);
        !          1039:                res = tmp << (16 + offset);
        !          1040:                bdata[0] = tmp & ~(mask >> (16 + offset));
        !          1041:                tmp = x_get_byte (src + 2);
        !          1042:                res |= tmp << (8 + offset);
        !          1043:                bdata[1] = tmp & ~(mask >> (8 + offset));
        !          1044:                break;
        !          1045:        case 4:
        !          1046:                tmp = x_get_long (src);
        !          1047:                res = tmp << offset;
        !          1048:                bdata[0] = tmp & ~(mask >> offset);
        !          1049:                break;
        !          1050:        case 5:
        !          1051:                tmp = x_get_long (src);
        !          1052:                res = tmp << offset;
        !          1053:                bdata[0] = tmp & ~(mask >> offset);
        !          1054:                tmp = x_get_byte (src + 4);
        !          1055:                res |= tmp >> (8 - offset);
        !          1056:                bdata[1] = tmp & ~(mask << (8 - offset));
        !          1057:                break;
        !          1058:        default:
        !          1059:                /* Panic? */
        !          1060:                res = 0;
        !          1061:                break;
        !          1062:        }
        !          1063:        return res;
        !          1064: }
        !          1065: 
        !          1066: void REGPARAM2 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
        !          1067: {
        !          1068:        offset = (offset & 7) + width;
        !          1069:        switch ((offset + 7) >> 3) {
        !          1070:        case 1:
        !          1071:                x_put_byte (dst, bdata[0] | (val << (8 - offset)));
        !          1072:                break;
        !          1073:        case 2:
        !          1074:                x_put_word (dst, bdata[0] | (val << (16 - offset)));
        !          1075:                break;
        !          1076:        case 3:
        !          1077:                x_put_word (dst, bdata[0] | (val >> (offset - 16)));
        !          1078:                x_put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
        !          1079:                break;
        !          1080:        case 4:
        !          1081:                x_put_long (dst, bdata[0] | (val << (32 - offset)));
        !          1082:                break;
        !          1083:        case 5:
        !          1084:                x_put_long (dst, bdata[0] | (val >> (offset - 32)));
        !          1085:                x_put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
        !          1086:                break;
        !          1087:        }
        !          1088: }
        !          1089: 
        !          1090: uae_u32 REGPARAM2 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
        !          1091: {
        !          1092:        int reg = (dp >> 12) & 15;
        !          1093:        uae_s32 regd = regs.regs[reg];
        !          1094:        if ((dp & 0x800) == 0)
        !          1095:                regd = (uae_s32)(uae_s16)regd;
        !          1096:        regd <<= (dp >> 9) & 3;
        !          1097:        if (dp & 0x100) {
        !          1098:                uae_s32 outer = 0;
        !          1099:                if (dp & 0x80) base = 0;
        !          1100:                if (dp & 0x40) regd = 0;
        !          1101: 
        !          1102:                if ((dp & 0x30) == 0x20)
        !          1103:                        base += (uae_s32)(uae_s16) next_iword ();
        !          1104:                if ((dp & 0x30) == 0x30)
        !          1105:                        base += next_ilong ();
        !          1106: 
        !          1107:                if ((dp & 0x3) == 0x2)
        !          1108:                        outer = (uae_s32)(uae_s16) next_iword ();
        !          1109:                if ((dp & 0x3) == 0x3)
        !          1110:                        outer = next_ilong ();
        !          1111: 
        !          1112:                if ((dp & 0x4) == 0)
        !          1113:                        base += regd;
        !          1114:                if (dp & 0x3)
        !          1115:                        base = get_long (base);
        !          1116:                if (dp & 0x4)
        !          1117:                        base += regd;
        !          1118: 
        !          1119:                return base + outer;
        !          1120:        } else {
        !          1121:                return base + (uae_s32)((uae_s8)dp) + regd;
        !          1122:        }
        !          1123: }
        !          1124: 
        !          1125: uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, uae_u32 dp)
        !          1126: {
        !          1127:        int reg = (dp >> 12) & 15;
        !          1128:        int cycles = 0;
        !          1129:        uae_u32 v;
        !          1130: 
        !          1131:        uae_s32 regd = regs.regs[reg];
        !          1132:        if ((dp & 0x800) == 0)
        !          1133:                regd = (uae_s32)(uae_s16)regd;
        !          1134:        regd <<= (dp >> 9) & 3;
        !          1135:        if (dp & 0x100) {
        !          1136:                uae_s32 outer = 0;
        !          1137:                if (dp & 0x80)
        !          1138:                        base = 0;
        !          1139:                if (dp & 0x40)
        !          1140:                        regd = 0;
        !          1141: 
        !          1142:                if ((dp & 0x30) == 0x20) {
        !          1143:                        base += (uae_s32)(uae_s16) x_next_iword ();
        !          1144:                        cycles++;
        !          1145:                }
        !          1146:                if ((dp & 0x30) == 0x30) {
        !          1147:                        base += x_next_ilong ();
        !          1148:                        cycles++;
        !          1149:                }
        !          1150: 
        !          1151:                if ((dp & 0x3) == 0x2) {
        !          1152:                        outer = (uae_s32)(uae_s16) x_next_iword ();
        !          1153:                        cycles++;
        !          1154:                }
        !          1155:                if ((dp & 0x3) == 0x3) {
        !          1156:                        outer = x_next_ilong ();
        !          1157:                        cycles++;
        !          1158:                }
        !          1159: 
        !          1160:                if ((dp & 0x4) == 0) {
        !          1161:                        base += regd;
        !          1162:                        cycles++;
        !          1163:                }
        !          1164:                if (dp & 0x3) {
        !          1165:                        base = x_get_long (base);
        !          1166:                        cycles++;
        !          1167:                }
        !          1168:                if (dp & 0x4) {
        !          1169:                        base += regd;
        !          1170:                        cycles++;
        !          1171:                }
        !          1172:                v = base + outer;
        !          1173:        } else {
        !          1174:                v = base + (uae_s32)((uae_s8)dp) + regd;
        !          1175:        }
        !          1176:        if (cycles)
        !          1177:                do_cycles_ce020 (cycles);
        !          1178:        return v;
        !          1179: }
        !          1180: 
        !          1181: 
        !          1182: uae_u32 REGPARAM3 get_disp_ea_000 (uae_u32 base, uae_u32 dp) REGPARAM
        !          1183: {
        !          1184:        int reg = (dp >> 12) & 15;
        !          1185:        uae_s32 regd = regs.regs[reg];
        !          1186: #if 1
        !          1187:        if ((dp & 0x800) == 0)
        !          1188:                regd = (uae_s32)(uae_s16)regd;
        !          1189:        return base + (uae_s8)dp + regd;
        !          1190: #else
        !          1191:        /* Branch-free code... benchmark this again now that
        !          1192:        * things are no longer inline.  */
        !          1193:        uae_s32 regd16;
        !          1194:        uae_u32 mask;
        !          1195:        mask = ((dp & 0x800) >> 11) - 1;
        !          1196:        regd16 = (uae_s32)(uae_s16)regd;
        !          1197:        regd16 &= mask;
        !          1198:        mask = ~mask;
        !          1199:        base += (uae_s8)dp;
        !          1200:        regd &= mask;
        !          1201:        regd |= regd16;
        !          1202:        return base + regd;
        !          1203: #endif
        !          1204: }
        !          1205: 
        !          1206: STATIC_INLINE int in_rom (uaecptr pc)
        !          1207: {
        !          1208:        return (munge24 (pc) & 0xFFF80000) == 0xF80000;
        !          1209: }
        !          1210: 
        !          1211: #if AMIGA_ONLY
        !          1212: STATIC_INLINE int in_rtarea (uaecptr pc)
        !          1213: {
        !          1214:        return (munge24 (pc) & 0xFFFF0000) == rtarea_base && uae_boot_rom;
        !          1215: }
        !          1216: #endif
        !          1217: 
        !          1218: void REGPARAM2 MakeSR (void)
        !          1219: {
        !          1220:        regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
        !          1221:                | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
        !          1222:                | (GET_XFLG () << 4) | (GET_NFLG () << 3)
        !          1223:                | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
        !          1224:                |  GET_CFLG ());
        !          1225: }
        !          1226: 
        !          1227: void REGPARAM2 MakeFromSR (void)
        !          1228: {
        !          1229:        int oldm = regs.m;
        !          1230:        int olds = regs.s;
        !          1231: 
        !          1232:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model >= 68020) {
        !          1233:                do_cycles_ce (6 * CYCLE_UNIT);
        !          1234:                regs.ce020memcycles = 0;
        !          1235:        }
        !          1236: 
        !          1237:        SET_XFLG ((regs.sr >> 4) & 1);
        !          1238:        SET_NFLG ((regs.sr >> 3) & 1);
        !          1239:        SET_ZFLG ((regs.sr >> 2) & 1);
        !          1240:        SET_VFLG ((regs.sr >> 1) & 1);
        !          1241:        SET_CFLG (regs.sr & 1);
        !          1242:        if (regs.t1 == ((regs.sr >> 15) & 1) &&
        !          1243:                regs.t0 == ((regs.sr >> 14) & 1) &&
        !          1244:                regs.s  == ((regs.sr >> 13) & 1) &&
        !          1245:                regs.m  == ((regs.sr >> 12) & 1) &&
        !          1246:                regs.intmask == ((regs.sr >> 8) & 7))
        !          1247:                return;
        !          1248:        regs.t1 = (regs.sr >> 15) & 1;
        !          1249:        regs.t0 = (regs.sr >> 14) & 1;
        !          1250:        regs.s  = (regs.sr >> 13) & 1;
        !          1251:        regs.m  = (regs.sr >> 12) & 1;
        !          1252:        regs.intmask = (regs.sr >> 8) & 7;
        !          1253:        if (currprefs.cpu_model >= 68020) {
        !          1254:                /* 68060 does not have MSP but does have M-bit.. */
        !          1255:                if (currprefs.cpu_model >= 68060)
        !          1256:                        regs.msp = regs.isp;
        !          1257:                if (olds != regs.s) {
        !          1258:                        if (olds) {
        !          1259:                                if (oldm)
        !          1260:                                        regs.msp = m68k_areg (regs, 7);
        !          1261:                                else
        !          1262:                                        regs.isp = m68k_areg (regs, 7);
        !          1263:                                m68k_areg (regs, 7) = regs.usp;
        !          1264:                        } else {
        !          1265:                                regs.usp = m68k_areg (regs, 7);
        !          1266:                                m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
        !          1267:                        }
        !          1268:                } else if (olds && oldm != regs.m) {
        !          1269:                        if (oldm) {
        !          1270:                                regs.msp = m68k_areg (regs, 7);
        !          1271:                                m68k_areg (regs, 7) = regs.isp;
        !          1272:                        } else {
        !          1273:                                regs.isp = m68k_areg (regs, 7);
        !          1274:                                m68k_areg (regs, 7) = regs.msp;
        !          1275:                        }
        !          1276:                }
        !          1277:                if (currprefs.cpu_model >= 68060)
        !          1278:                        regs.t0 = 0;
        !          1279:        } else {
        !          1280:                regs.t0 = regs.m = 0;
        !          1281:                if (olds != regs.s) {
        !          1282:                        if (olds) {
        !          1283:                                regs.isp = m68k_areg (regs, 7);
        !          1284:                                m68k_areg (regs, 7) = regs.usp;
        !          1285:                        } else {
        !          1286:                                regs.usp = m68k_areg (regs, 7);
        !          1287:                                m68k_areg (regs, 7) = regs.isp;
        !          1288:                        }
        !          1289:                }
        !          1290:        }
        !          1291:        if (currprefs.mmu_model)
        !          1292:                mmu_set_super (regs.s != 0);
        !          1293: 
        !          1294:        doint ();
        !          1295:        if (regs.t1 || regs.t0)
        !          1296:                set_special (SPCFLAG_TRACE);
        !          1297:        else
        !          1298:                /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
        !          1299:                SR-modifying instructions (including STOP).  */
        !          1300:                unset_special (SPCFLAG_TRACE);
        !          1301: }
        !          1302: 
        !          1303: static void exception_trace (int nr)
        !          1304: {
        !          1305:        unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
        !          1306:        if (regs.t1 && !regs.t0) {
        !          1307:                /* trace stays pending if exception is div by zero, chk,
        !          1308:                * trapv or trap #x
        !          1309:                */
        !          1310:                if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
        !          1311:                        set_special (SPCFLAG_DOTRACE);
        !          1312:        }
        !          1313:        regs.t1 = regs.t0 = regs.m = 0;
        !          1314: }
        !          1315: 
        !          1316: static void exception_debug (int nr)
        !          1317: {
        !          1318: #ifdef DEBUGGER
        !          1319:        if (!exception_debugging)
        !          1320:                return;
        !          1321:        console_out_f ("Exception %d, PC=%08X\n", nr, M68K_GETPC);
        !          1322: #endif
        !          1323: }
        !          1324: 
        !          1325: #ifdef CPUEMU_12
        !          1326: 
        !          1327: /* cycle-exact exception handler, 68000 only */
        !          1328: 
        !          1329: /*
        !          1330: 
        !          1331: Address/Bus Error:
        !          1332: 
        !          1333: - 6 idle cycles
        !          1334: - write PC low word
        !          1335: - write SR
        !          1336: - write PC high word
        !          1337: - write instruction word
        !          1338: - write fault address low word
        !          1339: - write status code
        !          1340: - write fault address high word
        !          1341: - 2 idle cycles
        !          1342: - read exception address high word
        !          1343: - read exception address low word
        !          1344: - prefetch
        !          1345: - 2 idle cycles
        !          1346: - prefetch
        !          1347: 
        !          1348: Division by Zero:
        !          1349: 
        !          1350: - 6 idle cycles
        !          1351: - write PC low word
        !          1352: - write SR
        !          1353: - write PC high word
        !          1354: - read exception address high word
        !          1355: - read exception address low word
        !          1356: - prefetch
        !          1357: - 2 idle cycles
        !          1358: - prefetch
        !          1359: 
        !          1360: Traps:
        !          1361: 
        !          1362: - 2 idle cycles
        !          1363: - write PC low word
        !          1364: - write SR
        !          1365: - write PC high word
        !          1366: - read exception address high word
        !          1367: - read exception address low word
        !          1368: - prefetch
        !          1369: - 2 idle cycles
        !          1370: - prefetch
        !          1371: 
        !          1372: TrapV:
        !          1373: 
        !          1374: - write PC low word
        !          1375: - write SR
        !          1376: - write PC high word
        !          1377: - read exception address high word
        !          1378: - read exception address low word
        !          1379: - prefetch
        !          1380: - 2 idle cycles
        !          1381: - prefetch
        !          1382: 
        !          1383: CHK:
        !          1384: 
        !          1385: - 6 idle cycles
        !          1386: - write PC low word
        !          1387: - write SR
        !          1388: - write PC high word
        !          1389: - read exception address high word
        !          1390: - read exception address low word
        !          1391: - prefetch
        !          1392: - 2 idle cycles
        !          1393: - prefetch
        !          1394: 
        !          1395: Illegal Instruction:
        !          1396: 
        !          1397: - 2 idle cycles
        !          1398: - write PC low word
        !          1399: - write SR
        !          1400: - write PC high word
        !          1401: - read exception address high word
        !          1402: - read exception address low word
        !          1403: - prefetch
        !          1404: - 2 idle cycles
        !          1405: - prefetch
        !          1406: 
        !          1407: Interrupt cycle diagram:
        !          1408: 
        !          1409: - 6 idle cycles
        !          1410: - write PC low word
        !          1411: - read exception number byte from (0xfffff1 | (interrupt number << 1))
        !          1412: - 4 idle cycles
        !          1413: - write SR
        !          1414: - write PC high word
        !          1415: - read exception address high word
        !          1416: - read exception address low word
        !          1417: - prefetch
        !          1418: - 2 idle cycles
        !          1419: - prefetch
        !          1420: 
        !          1421: */
        !          1422: 
        !          1423: static void Exception_ce000 (int nr, uaecptr oldpc)
        !          1424: {
        !          1425:        uae_u32 currpc = m68k_getpc (), newpc;
        !          1426:        int sv = regs.s;
        !          1427:        int start, interrupt;
        !          1428: 
        !          1429:        start = 6;
        !          1430:        if (nr == 7) // TRAPV
        !          1431:                start = 0;
        !          1432:        else if (nr >= 32 && nr < 32 + 16) // TRAP #x
        !          1433:                start = 2;
        !          1434:        else if (nr == 4 || nr == 8) // ILLG & PRIVIL VIOL
        !          1435:                start = 2;
        !          1436:        interrupt = nr >= 24 && nr < 24 + 8;
        !          1437: 
        !          1438:        if (start)
        !          1439:                do_cycles_ce000 (start);
        !          1440: 
        !          1441:        exception_debug (nr);
        !          1442:        MakeSR ();
        !          1443: 
        !          1444:        if (!regs.s) {
        !          1445:                regs.usp = m68k_areg (regs, 7);
        !          1446:                m68k_areg (regs, 7) = regs.isp;
        !          1447:                regs.s = 1;
        !          1448:        }
        !          1449:        if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
        !          1450:                uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
        !          1451:                mode |= last_writeaccess_for_exception_3 ? 0 : 16;
        !          1452:                m68k_areg (regs, 7) -= 14;
        !          1453:                /* fixme: bit3=I/N */
        !          1454:                put_word_ce (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
        !          1455:                put_word_ce (m68k_areg (regs, 7) + 8, regs.sr);
        !          1456:                put_word_ce (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
        !          1457:                put_word_ce (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
        !          1458:                put_word_ce (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
        !          1459:                put_word_ce (m68k_areg (regs, 7) + 0, mode);
        !          1460:                put_word_ce (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
        !          1461:                do_cycles_ce000 (2);
        !          1462:                write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (4 * nr));
        !          1463:                goto kludge_me_do;
        !          1464:        }
        !          1465:        m68k_areg (regs, 7) -= 6;
        !          1466:        put_word_ce (m68k_areg (regs, 7) + 4, currpc); // write low address
        !          1467:        if (interrupt) {
        !          1468:                // fetch interrupt vector number
        !          1469:                nr = get_byte_ce (0x00fffff1 | ((nr - 24) << 1));
        !          1470:                do_cycles_ce000 (4);
        !          1471:        }
        !          1472:        put_word_ce (m68k_areg (regs, 7) + 0, regs.sr); // write SR
        !          1473:        put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
        !          1474: kludge_me_do:
        !          1475:        newpc = get_word_ce (4 * nr) << 16; // read high address
        !          1476:        newpc |= get_word_ce (4 * nr + 2); // read low address
        !          1477:        if (newpc & 1) {
        !          1478:                if (nr == 2 || nr == 3)
        !          1479:                        Reset_Cold(); /* there is nothing else we can do.. */
        !          1480:                else
        !          1481:                        exception3 (regs.ir, m68k_getpc (), newpc);
        !          1482:                return;
        !          1483:        }
        !          1484:        m68k_setpc (newpc);
        !          1485:        regs.ir = get_word_ce (m68k_getpc ()); // prefetch 1
        !          1486:        do_cycles_ce000 (2);
        !          1487:        regs.irc = get_word_ce (m68k_getpc () + 2); // prefetch 2
        !          1488: #ifdef JIT
        !          1489:        set_special (SPCFLAG_END_COMPILE);
        !          1490: #endif
        !          1491:        exception_trace (nr);
        !          1492: }
        !          1493: #endif
        !          1494: 
        !          1495: static void Exception_mmu (int nr, uaecptr oldpc)
        !          1496: {
        !          1497:        uae_u32 currpc = m68k_getpc (), newpc;
        !          1498:        int sv = regs.s;
        !          1499:        int i;
        !          1500: 
        !          1501:        exception_debug (nr);
        !          1502:        MakeSR ();
        !          1503: 
        !          1504:        if (!regs.s) {
        !          1505:                regs.usp = m68k_areg (regs, 7);
        !          1506:                if (currprefs.cpu_model >= 68020)
        !          1507:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
        !          1508:                else
        !          1509:                        m68k_areg (regs, 7) = regs.isp;
        !          1510:                regs.s = 1;
        !          1511:                mmu_set_super (1);
        !          1512:        }
        !          1513:        if (nr == 2) {
        !          1514: //             write_log ("%08x %08x %08x\n", currpc, oldpc, regs.mmu_fault_addr);
        !          1515: //             if (currpc == 0x0013b5e2)
        !          1516: //                     activate_debugger ();
        !          1517:                // bus error
        !          1518:                for (i = 0 ; i < 7 ; i++) {
        !          1519:                        m68k_areg (regs, 7) -= 4;
        !          1520:                        put_long_mmu (m68k_areg (regs, 7), 0);
        !          1521:                }
        !          1522:                m68k_areg (regs, 7) -= 4;
        !          1523:                put_long_mmu (m68k_areg (regs, 7), regs.wb3_data);
        !          1524:                m68k_areg (regs, 7) -= 4;
        !          1525:                put_long_mmu (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          1526:                m68k_areg (regs, 7) -= 4;
        !          1527:                put_long_mmu (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          1528:                m68k_areg (regs, 7) -= 2;
        !          1529:                put_word_mmu (m68k_areg (regs, 7), 0);
        !          1530:                m68k_areg (regs, 7) -= 2;
        !          1531:                put_word_mmu (m68k_areg (regs, 7), 0);
        !          1532:                m68k_areg (regs, 7) -= 2;
        !          1533:                put_word_mmu (m68k_areg (regs, 7), regs.wb3_status);
        !          1534:                regs.wb3_status = 0;
        !          1535:                m68k_areg (regs, 7) -= 2;
        !          1536:                put_word_mmu (m68k_areg (regs, 7), regs.mmu_ssw);
        !          1537:                m68k_areg (regs, 7) -= 4;
        !          1538:                put_long_mmu (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          1539: 
        !          1540:                m68k_areg (regs, 7) -= 2;
        !          1541:                put_word_mmu (m68k_areg (regs, 7), 0x7000 + nr * 4);
        !          1542:                m68k_areg (regs, 7) -= 4;
        !          1543:                put_long_mmu (m68k_areg (regs, 7), oldpc);
        !          1544:                m68k_areg (regs, 7) -= 2;
        !          1545:                put_word_mmu (m68k_areg (regs, 7), regs.sr);
        !          1546:                goto kludge_me_do;
        !          1547: 
        !          1548:        } else if (nr == 3) {
        !          1549: 
        !          1550:                // address error
        !          1551:                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
        !          1552:                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
        !          1553:                ssw |= 0x20;
        !          1554:                for (i = 0 ; i < 36; i++) {
        !          1555:                        m68k_areg (regs, 7) -= 2;
        !          1556:                        put_word_mmu (m68k_areg (regs, 7), 0);
        !          1557:                }
        !          1558:                m68k_areg (regs, 7) -= 4;
        !          1559:                put_long_mmu (m68k_areg (regs, 7), last_fault_for_exception_3);
        !          1560:                m68k_areg (regs, 7) -= 2;
        !          1561:                put_word_mmu (m68k_areg (regs, 7), 0);
        !          1562:                m68k_areg (regs, 7) -= 2;
        !          1563:                put_word_mmu (m68k_areg (regs, 7), 0);
        !          1564:                m68k_areg (regs, 7) -= 2;
        !          1565:                put_word_mmu (m68k_areg (regs, 7), 0);
        !          1566:                m68k_areg (regs, 7) -= 2;
        !          1567:                put_word_mmu (m68k_areg (regs, 7), ssw);
        !          1568:                m68k_areg (regs, 7) -= 2;
        !          1569:                put_word_mmu (m68k_areg (regs, 7), 0xb000 + nr * 4);
        !          1570:                write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (regs.vbr + 4*nr));
        !          1571: 
        !          1572:        } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
        !          1573: 
        !          1574:                m68k_areg (regs, 7) -= 4;
        !          1575:                put_long_mmu (m68k_areg (regs, 7), oldpc);
        !          1576:                m68k_areg (regs, 7) -= 2;
        !          1577:                put_word_mmu (m68k_areg (regs, 7), 0x2000 + nr * 4);
        !          1578: 
        !          1579:        } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
        !          1580: 
        !          1581:                m68k_areg (regs, 7) -= 2;
        !          1582:                put_word_mmu (m68k_areg (regs, 7), nr * 4);
        !          1583:                m68k_areg (regs, 7) -= 4;
        !          1584:                put_long_mmu (m68k_areg (regs, 7), currpc);
        !          1585:                m68k_areg (regs, 7) -= 2;
        !          1586:                put_word_mmu (m68k_areg (regs, 7), regs.sr);
        !          1587:                regs.sr |= (1 << 13);
        !          1588:                regs.msp = m68k_areg (regs, 7);
        !          1589:                m68k_areg (regs, 7) = regs.isp;
        !          1590:                m68k_areg (regs, 7) -= 2;
        !          1591:                put_word_mmu (m68k_areg (regs, 7), 0x1000 + nr * 4);
        !          1592: 
        !          1593:        } else {
        !          1594: 
        !          1595:                m68k_areg (regs, 7) -= 2;
        !          1596:                put_word_mmu (m68k_areg (regs, 7), nr * 4);
        !          1597: 
        !          1598:        }
        !          1599:        m68k_areg (regs, 7) -= 4;
        !          1600:        put_long_mmu (m68k_areg (regs, 7), currpc);
        !          1601:        m68k_areg (regs, 7) -= 2;
        !          1602:        put_word_mmu (m68k_areg (regs, 7), regs.sr);
        !          1603: kludge_me_do:
        !          1604:        newpc = get_long_mmu (regs.vbr + 4 * nr);
        !          1605:        if (newpc & 1) {
        !          1606:                if (nr == 2 || nr == 3)
        !          1607:                        Reset_Cold();  /* there is nothing else we can do.. */
        !          1608:                else
        !          1609:                        exception3 (regs.ir, m68k_getpc (), newpc);
        !          1610:                return;
        !          1611:        }
        !          1612:        m68k_setpc (newpc);
        !          1613: #ifdef JIT
        !          1614:        set_special (SPCFLAG_END_COMPILE);
        !          1615: #endif
        !          1616:        fill_prefetch_slow ();
        !          1617:        exception_trace (nr);
        !          1618: }
        !          1619: 
        !          1620: /* Handle exceptions. We need a special case to handle MFP exceptions */
        !          1621: /* on Atari ST, because it's possible to change the MFP's vector base */
        !          1622: /* and get a conflict with 'normal' cpu exceptions. */
        !          1623: static void Exception_normal (int nr, uaecptr oldpc, int ExceptionSource)
        !          1624: {
        !          1625:        uae_u32 currpc = m68k_getpc (), newpc;
        !          1626:        int sv = regs.s;
        !          1627: 
        !          1628:        if (ExceptionSource == M68000_EXC_SRC_CPU) {
        !          1629:                if (bVdiAesIntercept && nr == 0x22) {
        !          1630:                        /* Intercept VDI & AES exceptions (Trap #2) */
        !          1631:                        if (VDI_AES_Entry()) {
        !          1632:                                /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
        !          1633:                                 * This will call OpCode_VDI() after completion of Trap call!
        !          1634:                                 * This is used to modify specific VDI return vectors contents.
        !          1635:                                */
        !          1636:                                VDI_OldPC = currpc;
        !          1637:                                currpc = CART_VDI_OPCODE_ADDR;
        !          1638:                        }
        !          1639:                }
        !          1640: 
        !          1641:                if (bBiosIntercept) {
        !          1642:                        /* Intercept BIOS or XBIOS trap (Trap #13 or #14) */
        !          1643:                        if (nr == 0x2d) {
        !          1644:                                /* Intercept BIOS calls */
        !          1645:                                if (Bios())  return;
        !          1646:                        }
        !          1647:                        else if (nr == 0x2e) {
        !          1648:                                /* Intercept XBIOS calls */
        !          1649:                                if (XBios())  return;
        !          1650:                        }
        !          1651:                }
        !          1652:        }
        !          1653: 
        !          1654: #if AMIGA_ONLY
        !          1655:        if (nr >= 24 && nr < 24 + 8 && currprefs.cpu_model <= 68010)
        !          1656:                nr = x_get_byte (0x00fffff1 | (nr << 1));
        !          1657: #endif
        !          1658: 
        !          1659:        exception_debug (nr);
        !          1660:        MakeSR ();
        !          1661: 
        !          1662:        /* Change to supervisor mode if necessary */
        !          1663:        if (!regs.s) {
        !          1664:                regs.usp = m68k_areg (regs, 7);
        !          1665:                if (currprefs.cpu_model >= 68020)
        !          1666:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
        !          1667:                else
        !          1668:                        m68k_areg (regs, 7) = regs.isp;
        !          1669:                regs.s = 1;
        !          1670:                if (currprefs.mmu_model)
        !          1671:                        mmu_set_super (regs.s != 0);
        !          1672:        }
        !          1673:        if (currprefs.cpu_model > 68000) {
        !          1674:                /* Build additional exception stack frame for 68010 and higher */
        !          1675:                /* (special case for MFP) */
        !          1676:                if (ExceptionSource == M68000_EXC_SRC_INT_MFP || ExceptionSource == M68000_EXC_SRC_INT_DSP) {
        !          1677:                        m68k_areg(regs, 7) -= 2;
        !          1678:                        put_word (m68k_areg(regs, 7), nr * 4);  /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
        !          1679:                }
        !          1680:                else if (nr == 2 || nr == 3) {
        !          1681:                        int i;
        !          1682:                        if (currprefs.cpu_model >= 68040) {
        !          1683:                                if (nr == 2) {
        !          1684:                                        // bus error
        !          1685:                                        if (currprefs.mmu_model) {
        !          1686: 
        !          1687:                                                for (i = 0 ; i < 7 ; i++) {
        !          1688:                                                        m68k_areg (regs, 7) -= 4;
        !          1689:                                                        x_put_long (m68k_areg (regs, 7), 0);
        !          1690:                                                }
        !          1691:                                                m68k_areg (regs, 7) -= 4;
        !          1692:                                                x_put_long (m68k_areg (regs, 7), regs.wb3_data);
        !          1693:                                                m68k_areg (regs, 7) -= 4;
        !          1694:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          1695:                                                m68k_areg (regs, 7) -= 4;
        !          1696:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          1697:                                                m68k_areg (regs, 7) -= 2;
        !          1698:                                                x_put_word (m68k_areg (regs, 7), 0);
        !          1699:                                                m68k_areg (regs, 7) -= 2;
        !          1700:                                                x_put_word (m68k_areg (regs, 7), 0);
        !          1701:                                                m68k_areg (regs, 7) -= 2;
        !          1702:                                                x_put_word (m68k_areg (regs, 7), regs.wb3_status);
        !          1703:                                                regs.wb3_status = 0;
        !          1704:                                                m68k_areg (regs, 7) -= 2;
        !          1705:                                                x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
        !          1706:                                                m68k_areg (regs, 7) -= 4;
        !          1707:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          1708: 
        !          1709:                                                m68k_areg (regs, 7) -= 2;
        !          1710:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
        !          1711:                                                m68k_areg (regs, 7) -= 4;
        !          1712:                                                x_put_long (m68k_areg (regs, 7), oldpc);
        !          1713:                                                m68k_areg (regs, 7) -= 2;
        !          1714:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
        !          1715:                                                newpc = x_get_long (regs.vbr + 4 * nr);
        !          1716:                                                if (newpc & 1) {
        !          1717:                                                        if (nr == 2 || nr == 3)
        !          1718:                                                                uae_reset (1); /* there is nothing else we can do.. */
        !          1719:                                                        else
        !          1720:                                                                exception3 (regs.ir, m68k_getpc (), newpc);
        !          1721:                                                        return;
        !          1722:                                                }
        !          1723:                                                m68k_setpc (newpc);
        !          1724: #ifdef JIT
        !          1725:                                                set_special (SPCFLAG_END_COMPILE);
        !          1726: #endif
        !          1727:                                                exception_trace (nr);
        !          1728:                                                return;
        !          1729: 
        !          1730:                                        } else {
        !          1731: 
        !          1732:                                                for (i = 0 ; i < 18 ; i++) {
        !          1733:                                                        m68k_areg (regs, 7) -= 2;
        !          1734:                                                        x_put_word (m68k_areg (regs, 7), 0);
        !          1735:                                                }
        !          1736:                                                m68k_areg (regs, 7) -= 4;
        !          1737:                                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
        !          1738:                                                m68k_areg (regs, 7) -= 2;
        !          1739:                                                x_put_word (m68k_areg (regs, 7), 0);
        !          1740:                                                m68k_areg (regs, 7) -= 2;
        !          1741:                                                x_put_word (m68k_areg (regs, 7), 0);
        !          1742:                                                m68k_areg (regs, 7) -= 2;
        !          1743:                                                x_put_word (m68k_areg (regs, 7), 0);
        !          1744:                                                m68k_areg (regs, 7) -= 2;
        !          1745:                                                x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
        !          1746:                                                m68k_areg (regs, 7) -= 4;
        !          1747:                                                x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
        !          1748:                                                m68k_areg (regs, 7) -= 2;
        !          1749:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
        !          1750:                                                m68k_areg (regs, 7) -= 4;
        !          1751:                                                x_put_long (m68k_areg (regs, 7), oldpc);
        !          1752:                                                m68k_areg (regs, 7) -= 2;
        !          1753:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
        !          1754:                                                goto kludge_me_do;
        !          1755: 
        !          1756:                                        }
        !          1757: 
        !          1758:                                } else {
        !          1759:                                        m68k_areg (regs, 7) -= 4;
        !          1760:                                        x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
        !          1761:                                        m68k_areg (regs, 7) -= 2;
        !          1762:                                        x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
        !          1763:                                }
        !          1764:                        } else {
        !          1765:                                // address error
        !          1766:                                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
        !          1767:                                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
        !          1768:                                ssw |= 0x20;
        !          1769:                                for (i = 0 ; i < 36; i++) {
        !          1770:                                        m68k_areg (regs, 7) -= 2;
        !          1771:                                        x_put_word (m68k_areg (regs, 7), 0);
        !          1772:                                }
        !          1773:                                m68k_areg (regs, 7) -= 4;
        !          1774:                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
        !          1775:                                m68k_areg (regs, 7) -= 2;
        !          1776:                                x_put_word (m68k_areg (regs, 7), 0);
        !          1777:                                m68k_areg (regs, 7) -= 2;
        !          1778:                                x_put_word (m68k_areg (regs, 7), 0);
        !          1779:                                m68k_areg (regs, 7) -= 2;
        !          1780:                                x_put_word (m68k_areg (regs, 7), 0);
        !          1781:                                m68k_areg (regs, 7) -= 2;
        !          1782:                                x_put_word (m68k_areg (regs, 7), ssw);
        !          1783:                                m68k_areg (regs, 7) -= 2;
        !          1784:                                x_put_word (m68k_areg (regs, 7), 0xb000 + nr * 4);
        !          1785:                        }
        !          1786:                        write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, x_get_long (regs.vbr + 4*nr));
        !          1787:                } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
        !          1788:                        m68k_areg (regs, 7) -= 4;
        !          1789:                        x_put_long (m68k_areg (regs, 7), oldpc);
        !          1790:                        m68k_areg (regs, 7) -= 2;
        !          1791:                        x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
        !          1792:                } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
        !          1793:                        m68k_areg (regs, 7) -= 2;
        !          1794:                        x_put_word (m68k_areg (regs, 7), nr * 4);
        !          1795:                        m68k_areg (regs, 7) -= 4;
        !          1796:                        x_put_long (m68k_areg (regs, 7), currpc);
        !          1797:                        m68k_areg (regs, 7) -= 2;
        !          1798:                        x_put_word (m68k_areg (regs, 7), regs.sr);
        !          1799:                        regs.sr |= (1 << 13);
        !          1800:                        regs.msp = m68k_areg (regs, 7);
        !          1801:                        m68k_areg (regs, 7) = regs.isp;
        !          1802:                        m68k_areg (regs, 7) -= 2;
        !          1803:                        x_put_word (m68k_areg (regs, 7), 0x1000 + nr * 4);
        !          1804:                } else {
        !          1805:                        m68k_areg (regs, 7) -= 2;
        !          1806:                        x_put_word (m68k_areg (regs, 7), nr * 4);
        !          1807:                }
        !          1808:        } else if (nr == 2 || nr == 3) {
        !          1809:                uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
        !          1810:                mode |= last_writeaccess_for_exception_3 ? 0 : 16;
        !          1811:                m68k_areg (regs, 7) -= 14;
        !          1812:                /* fixme: bit3=I/N */
        !          1813:                x_put_word (m68k_areg (regs, 7) + 0, mode);
        !          1814:                x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
        !          1815:                x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
        !          1816:                x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
        !          1817:                x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
        !          1818:                write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, x_get_long (regs.vbr + 4*nr));
        !          1819:                goto kludge_me_do;
        !          1820:        }
        !          1821: 
        !          1822:        /* Push PC on stack: */
        !          1823:        m68k_areg (regs, 7) -= 4;
        !          1824:        x_put_long (m68k_areg (regs, 7), currpc);
        !          1825:        /* Push SR on stack: */
        !          1826:        m68k_areg (regs, 7) -= 2;
        !          1827:        x_put_word (m68k_areg (regs, 7), regs.sr);
        !          1828: kludge_me_do:
        !          1829:        newpc = x_get_long (regs.vbr + 4 * nr);
        !          1830:        if (newpc & 1) {
        !          1831:                if (nr == 2 || nr == 3)
        !          1832:                        uae_reset (1); /* there is nothing else we can do.. */
        !          1833:                else
        !          1834:                        exception3 (regs.ir, m68k_getpc (), newpc);
        !          1835:                return;
        !          1836:        }
        !          1837:        m68k_setpc (newpc);
        !          1838: #ifdef JIT
        !          1839:        set_special (SPCFLAG_END_COMPILE);
        !          1840: #endif
        !          1841:        fill_prefetch_slow ();
        !          1842:        exception_trace (nr);
        !          1843:        
        !          1844:     /* Handle exception cycles (special case for MFP) */
        !          1845:     if (ExceptionSource == M68000_EXC_SRC_INT_MFP)
        !          1846:     {
        !          1847:       M68000_AddCycles(44+12);                 /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
        !          1848:     }
        !          1849:     else if (nr >= 24 && nr <= 31)
        !          1850:     {
        !          1851:       if ( nr == 26 )                          /* HBL */
        !          1852:       {
        !          1853:         /* store current cycle pos when then interrupt was received (see video.c) */
        !          1854:         LastCycleHblException = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
        !          1855:         M68000_AddCycles(44+12);               /* Video Interrupt */
        !          1856:       }
        !          1857:       else if ( nr == 28 )                     /* VBL */
        !          1858:         M68000_AddCycles(44+12);               /* Video Interrupt */
        !          1859:       else
        !          1860:         M68000_AddCycles(44+4);                        /* Other Interrupts */
        !          1861:     }
        !          1862:     else if(nr >= 32 && nr <= 47)
        !          1863:     {
        !          1864:       M68000_AddCycles(34-4);                  /* Trap (total is 34, but cpuemu.c already adds 4) */
        !          1865:     }
        !          1866:     else switch(nr)
        !          1867:     {
        !          1868:       case 2: M68000_AddCycles(50); break;     /* Bus error */
        !          1869:       case 3: M68000_AddCycles(50); break;     /* Address error */
        !          1870:       case 4: M68000_AddCycles(34); break;     /* Illegal instruction */
        !          1871:       case 5: M68000_AddCycles(38); break;     /* Div by zero */
        !          1872:       case 6: M68000_AddCycles(40); break;     /* CHK */
        !          1873:       case 7: M68000_AddCycles(34); break;     /* TRAPV */
        !          1874:       case 8: M68000_AddCycles(34); break;     /* Privilege violation */
        !          1875:       case 9: M68000_AddCycles(34); break;     /* Trace */
        !          1876:       case 10: M68000_AddCycles(34); break;    /* Line-A - probably wrong */
        !          1877:       case 11: M68000_AddCycles(34); break;    /* Line-F - probably wrong */
        !          1878:       default:
        !          1879:         /* FIXME: Add right cycles value for MFP interrupts and copro exceptions ... */
        !          1880:         if(nr < 64)
        !          1881:           M68000_AddCycles(4);                 /* Coprocessor and unassigned exceptions (???) */
        !          1882:         else
        !          1883:           M68000_AddCycles(44+12);             /* Must be a MFP or DSP interrupt */
        !          1884:         break;
        !          1885:     }
        !          1886: 
        !          1887: }
        !          1888: 
        !          1889: /* Handle exceptions. We need a special case to handle MFP exceptions */
        !          1890: /* on Atari ST, because it's possible to change the MFP's vector base */
        !          1891: /* and get a conflict with 'normal' cpu exceptions. */
        !          1892: void REGPARAM2 Exception (int nr, uaecptr oldpc, int ExceptionSource)
        !          1893: {
        !          1894: #ifdef CPUEMU_12
        !          1895:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000)
        !          1896:                Exception_ce000 (nr, oldpc);
        !          1897:        else
        !          1898: #endif
        !          1899:                if (currprefs.mmu_model)
        !          1900:                        Exception_mmu (nr, oldpc); // Todo: add ExceptionSource
        !          1901:                else
        !          1902:                        Exception_normal (nr, oldpc, ExceptionSource);
        !          1903: 
        !          1904: #if AMIGA_ONLY
        !          1905:        if (debug_illegal && !in_rom (M68K_GETPC)) {
        !          1906:                int v = nr;
        !          1907:                if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
        !          1908:                        write_log ("Exception %d breakpoint\n", nr);
        !          1909:                        activate_debugger ();
        !          1910:                }
        !          1911:        }
        !          1912: #endif
        !          1913: }
        !          1914: 
        !          1915: STATIC_INLINE void do_interrupt (int nr, int Pending)
        !          1916: {
        !          1917: #if AMIGA_ONLY
        !          1918:        if (debug_dma)
        !          1919:                record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
        !          1920: #endif
        !          1921: 
        !          1922:        regs.stopped = 0;
        !          1923:        unset_special (SPCFLAG_STOP);
        !          1924:        assert (nr < 8 && nr >= 0);
        !          1925: 
        !          1926:        /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */
        !          1927:        Exception (nr + 24, 0, M68000_EXC_SRC_AUTOVEC);
        !          1928: 
        !          1929:        regs.intmask = nr;
        !          1930:        doint ();
        !          1931: 
        !          1932:        set_special (SPCFLAG_INT);
        !          1933:        /* Handle Atari ST's specific jitter for hbl/vbl */
        !          1934:        InterruptAddJitter (nr , Pending);
        !          1935: }
        !          1936: 
        !          1937: 
        !          1938: void NMI (void)
        !          1939: {
        !          1940:        do_interrupt (7, false);
        !          1941: }
        !          1942: 
        !          1943: #ifndef CPUEMU_68000_ONLY
        !          1944: 
        !          1945: int movec_illg (int regno)
        !          1946: {
        !          1947:        int regno2 = regno & 0x7ff;
        !          1948: 
        !          1949:        if (currprefs.cpu_model == 68060) {
        !          1950:                if (regno <= 8)
        !          1951:                        return 0;
        !          1952:                if (regno == 0x800 || regno == 0x801 ||
        !          1953:                        regno == 0x806 || regno == 0x807 || regno == 0x808)
        !          1954:                        return 0;
        !          1955:                return 1;
        !          1956:        } else if (currprefs.cpu_model == 68010) {
        !          1957:                if (regno2 < 2)
        !          1958:                        return 0;
        !          1959:                return 1;
        !          1960:        } else if (currprefs.cpu_model == 68020) {
        !          1961:                if (regno == 3)
        !          1962:                        return 1; /* 68040/060 only */
        !          1963:                /* 4 is >=68040, but 0x804 is in 68020 */
        !          1964:                if (regno2 < 4 || regno == 0x804)
        !          1965:                        return 0;
        !          1966:                return 1;
        !          1967:        } else if (currprefs.cpu_model == 68030) {
        !          1968:                if (regno2 <= 2)
        !          1969:                        return 0;
        !          1970:                if (regno == 0x803 || regno == 0x804)
        !          1971:                        return 0;
        !          1972:                return 1;
        !          1973:        } else if (currprefs.cpu_model == 68040) {
        !          1974:                if (regno == 0x802)
        !          1975:                        return 1; /* 68020 only */
        !          1976:                if (regno2 < 8) return 0;
        !          1977:                return 1;
        !          1978:        }
        !          1979:        return 1;
        !          1980: }
        !          1981: 
        !          1982: int m68k_move2c (int regno, uae_u32 *regp)
        !          1983: {
        !          1984: #if MOVEC_DEBUG > 0
        !          1985:        write_log ("move2c %04X <- %08X PC=%x\n", regno, *regp, M68K_GETPC);
        !          1986: #endif
        !          1987:        if (movec_illg (regno)) {
        !          1988:                op_illg (0x4E7B);
        !          1989:                return 0;
        !          1990:        } else {
        !          1991:                switch (regno) {
        !          1992:                case 0: regs.sfc = *regp & 7; break;
        !          1993:                case 1: regs.dfc = *regp & 7; break;
        !          1994:                case 2:
        !          1995:                        {
        !          1996:                                uae_u32 cacr_mask = 0;
        !          1997:                                if (currprefs.cpu_model == 68020)
        !          1998:                                        cacr_mask = 0x0000000f;
        !          1999:                                else if (currprefs.cpu_model == 68030)
        !          2000:                                        cacr_mask = 0x00003f1f;
        !          2001:                                else if (currprefs.cpu_model == 68040)
        !          2002:                                        cacr_mask = 0x80008000;
        !          2003:                                else if (currprefs.cpu_model == 68060)
        !          2004:                                        cacr_mask = 0xf8e0e000;
        !          2005:                                regs.cacr = *regp & cacr_mask;
        !          2006:                                set_cpu_caches ();
        !          2007:                        }
        !          2008:                        break;
        !          2009:                        /* 68040/060 only */
        !          2010:                case 3:
        !          2011:                        regs.tcr = *regp & (currprefs.cpu_model == 68060 ? 0xfffe : 0xc000);
        !          2012:                        if (currprefs.mmu_model)
        !          2013:                                mmu_set_tc (regs.tcr);
        !          2014:                        break;
        !          2015: 
        !          2016:                        /* no differences between 68040 and 68060 */
        !          2017:                case 4: regs.itt0 = *regp & 0xffffe364; break;
        !          2018:                case 5: regs.itt1 = *regp & 0xffffe364; break;
        !          2019:                case 6: regs.dtt0 = *regp & 0xffffe364; break;
        !          2020:                case 7: regs.dtt1 = *regp & 0xffffe364; break;
        !          2021:                        /* 68060 only */
        !          2022:                case 8: regs.buscr = *regp & 0xf0000000; break;
        !          2023: 
        !          2024:                case 0x800: regs.usp = *regp; break;
        !          2025:                case 0x801: regs.vbr = *regp; break;
        !          2026:                case 0x802: regs.caar = *regp & 0xfc; break;
        !          2027:                case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (regs, 7) = regs.msp; break;
        !          2028:                case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (regs, 7) = regs.isp; break;
        !          2029:                        /* 68040 only */
        !          2030:                case 0x805: regs.mmusr = *regp; break;
        !          2031:                        /* 68040/060 */
        !          2032:                case 0x806: regs.urp = *regp & 0xfffffe00; break;
        !          2033:                case 0x807: regs.srp = *regp & 0xfffffe00; break;
        !          2034:                        /* 68060 only */
        !          2035:                case 0x808:
        !          2036:                        {
        !          2037:                                uae_u32 opcr = regs.pcr;
        !          2038:                                regs.pcr &= ~(0x40 | 2 | 1);
        !          2039:                                regs.pcr |= (*regp) & (0x40 | 2 | 1);
        !          2040:                                if (((opcr ^ regs.pcr) & 2) == 2) {
        !          2041:                                        write_log ("68060 FPU state: %s\n", regs.pcr & 2 ? "disabled" : "enabled");
        !          2042:                                        /* flush possible already translated FPU instructions */
        !          2043:                                        flush_icache (0, 3);
        !          2044:                                }
        !          2045:                        }
        !          2046:                        break;
        !          2047:                default:
        !          2048:                        op_illg (0x4E7B);
        !          2049:                        return 0;
        !          2050:                }
        !          2051:        }
        !          2052:        return 1;
        !          2053: }
        !          2054: 
        !          2055: int m68k_movec2 (int regno, uae_u32 *regp)
        !          2056: {
        !          2057: #if MOVEC_DEBUG > 0
        !          2058:        write_log ("movec2 %04X PC=%x\n", regno, M68K_GETPC);
        !          2059: #endif
        !          2060:        if (movec_illg (regno)) {
        !          2061:                op_illg (0x4E7A);
        !          2062:                return 0;
        !          2063:        } else {
        !          2064:                switch (regno) {
        !          2065:                case 0: *regp = regs.sfc; break;
        !          2066:                case 1: *regp = regs.dfc; break;
        !          2067:                case 2:
        !          2068:                        {
        !          2069:                                uae_u32 v = regs.cacr;
        !          2070:                                uae_u32 cacr_mask = 0;
        !          2071:                                if (currprefs.cpu_model == 68020)
        !          2072:                                        cacr_mask = 0x00000003;
        !          2073:                                else if (currprefs.cpu_model == 68030)
        !          2074:                                        cacr_mask = 0x00003313;
        !          2075:                                else if (currprefs.cpu_model == 68040)
        !          2076:                                        cacr_mask = 0x80008000;
        !          2077:                                else if (currprefs.cpu_model == 68060)
        !          2078:                                        cacr_mask = 0xf880e000;
        !          2079:                                *regp = v & cacr_mask;
        !          2080:                        }
        !          2081:                        break;
        !          2082:                case 3: *regp = regs.tcr; break;
        !          2083:                case 4: *regp = regs.itt0; break;
        !          2084:                case 5: *regp = regs.itt1; break;
        !          2085:                case 6: *regp = regs.dtt0; break;
        !          2086:                case 7: *regp = regs.dtt1; break;
        !          2087:                case 8: *regp = regs.buscr; break;
        !          2088: 
        !          2089:                case 0x800: *regp = regs.usp; break;
        !          2090:                case 0x801: *regp = regs.vbr; break;
        !          2091:                case 0x802: *regp = regs.caar; break;
        !          2092:                case 0x803: *regp = regs.m == 1 ? m68k_areg (regs, 7) : regs.msp; break;
        !          2093:                case 0x804: *regp = regs.m == 0 ? m68k_areg (regs, 7) : regs.isp; break;
        !          2094:                case 0x805: *regp = regs.mmusr; break;
        !          2095:                case 0x806: *regp = regs.urp; break;
        !          2096:                case 0x807: *regp = regs.srp; break;
        !          2097:                case 0x808: *regp = regs.pcr; break;
        !          2098: 
        !          2099:                default:
        !          2100:                        op_illg (0x4E7A);
        !          2101:                        return 0;
        !          2102:                }
        !          2103:        }
        !          2104: #if MOVEC_DEBUG > 0
        !          2105:        write_log ("-> %08X\n", *regp);
        !          2106: #endif
        !          2107:        return 1;
        !          2108: }
        !          2109: 
        !          2110: STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
        !          2111: {
        !          2112:        uae_u32 q = 0, cbit = 0;
        !          2113:        int i;
        !          2114: 
        !          2115:        if (div <= src_hi) {
        !          2116:                return 1;
        !          2117:        }
        !          2118:        for (i = 0 ; i < 32 ; i++) {
        !          2119:                cbit = src_hi & 0x80000000ul;
        !          2120:                src_hi <<= 1;
        !          2121:                if (src_lo & 0x80000000ul) src_hi++;
        !          2122:                src_lo <<= 1;
        !          2123:                q = q << 1;
        !          2124:                if (cbit || div <= src_hi) {
        !          2125:                        q |= 1;
        !          2126:                        src_hi -= div;
        !          2127:                }
        !          2128:        }
        !          2129:        *quot = q;
        !          2130:        *rem = src_hi;
        !          2131:        return 0;
        !          2132: }
        !          2133: 
        !          2134: void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
        !          2135: {
        !          2136: #if defined (uae_s64)
        !          2137:        if (src == 0) {
        !          2138:                Exception (5, oldpc, M68000_EXC_SRC_CPU);
        !          2139:                return;
        !          2140:        }
        !          2141:        if (extra & 0x800) {
        !          2142:                /* signed variant */
        !          2143:                uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2144:                uae_s64 quot, rem;
        !          2145: 
        !          2146:                if (extra & 0x400) {
        !          2147:                        a &= 0xffffffffu;
        !          2148:                        a |= (uae_s64)m68k_dreg (regs, extra & 7) << 32;
        !          2149:                }
        !          2150:                rem = a % (uae_s64)(uae_s32)src;
        !          2151:                quot = a / (uae_s64)(uae_s32)src;
        !          2152:                if ((quot & UVAL64 (0xffffffff80000000)) != 0
        !          2153:                        && (quot & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
        !          2154:                {
        !          2155:                        SET_VFLG (1);
        !          2156:                        SET_NFLG (1);
        !          2157:                        SET_CFLG (0);
        !          2158:                } else {
        !          2159:                        if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
        !          2160:                        SET_VFLG (0);
        !          2161:                        SET_CFLG (0);
        !          2162:                        SET_ZFLG (((uae_s32)quot) == 0);
        !          2163:                        SET_NFLG (((uae_s32)quot) < 0);
        !          2164:                        m68k_dreg (regs, extra & 7) = (uae_u32)rem;
        !          2165:                        m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
        !          2166:                }
        !          2167:        } else {
        !          2168:                /* unsigned */
        !          2169:                uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2170:                uae_u64 quot, rem;
        !          2171: 
        !          2172:                if (extra & 0x400) {
        !          2173:                        a &= 0xffffffffu;
        !          2174:                        a |= (uae_u64)m68k_dreg (regs, extra & 7) << 32;
        !          2175:                }
        !          2176:                rem = a % (uae_u64)src;
        !          2177:                quot = a / (uae_u64)src;
        !          2178:                if (quot > 0xffffffffu) {
        !          2179:                        SET_VFLG (1);
        !          2180:                        SET_NFLG (1);
        !          2181:                        SET_CFLG (0);
        !          2182:                } else {
        !          2183:                        SET_VFLG (0);
        !          2184:                        SET_CFLG (0);
        !          2185:                        SET_ZFLG (((uae_s32)quot) == 0);
        !          2186:                        SET_NFLG (((uae_s32)quot) < 0);
        !          2187:                        m68k_dreg (regs, extra & 7) = (uae_u32)rem;
        !          2188:                        m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
        !          2189:                }
        !          2190:        }
        !          2191: #else
        !          2192:        if (src == 0) {
        !          2193:                Exception (5, oldpc, M68000_EXC_SRC_CPU);
        !          2194:                return;
        !          2195:        }
        !          2196:        if (extra & 0x800) {
        !          2197:                /* signed variant */
        !          2198:                uae_s32 lo = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2199:                uae_s32 hi = lo < 0 ? -1 : 0;
        !          2200:                uae_s32 save_high;
        !          2201:                uae_u32 quot, rem;
        !          2202:                uae_u32 sign;
        !          2203: 
        !          2204:                if (extra & 0x400) {
        !          2205:                        hi = (uae_s32)m68k_dreg (regs, extra & 7);
        !          2206:                }
        !          2207:                save_high = hi;
        !          2208:                sign = (hi ^ src);
        !          2209:                if (hi < 0) {
        !          2210:                        hi = ~hi;
        !          2211:                        lo = -lo;
        !          2212:                        if (lo == 0) hi++;
        !          2213:                }
        !          2214:                if ((uae_s32)src < 0) src = -src;
        !          2215:                if (div_unsigned (hi, lo, src, &quot, &rem) ||
        !          2216:                        (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
        !          2217:                                SET_VFLG (1);
        !          2218:                                SET_NFLG (1);
        !          2219:                                SET_CFLG (0);
        !          2220:                } else {
        !          2221:                        if (sign & 0x80000000) quot = -quot;
        !          2222:                        if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
        !          2223:                        SET_VFLG (0);
        !          2224:                        SET_CFLG (0);
        !          2225:                        SET_ZFLG (((uae_s32)quot) == 0);
        !          2226:                        SET_NFLG (((uae_s32)quot) < 0);
        !          2227:                        m68k_dreg (regs, extra & 7) = rem;
        !          2228:                        m68k_dreg (regs, (extra >> 12) & 7) = quot;
        !          2229:                }
        !          2230:        } else {
        !          2231:                /* unsigned */
        !          2232:                uae_u32 lo = (uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2233:                uae_u32 hi = 0;
        !          2234:                uae_u32 quot, rem;
        !          2235: 
        !          2236:                if (extra & 0x400) {
        !          2237:                        hi = (uae_u32)m68k_dreg (regs, extra & 7);
        !          2238:                }
        !          2239:                if (div_unsigned (hi, lo, src, &quot, &rem)) {
        !          2240:                        SET_VFLG (1);
        !          2241:                        SET_NFLG (1);
        !          2242:                        SET_CFLG (0);
        !          2243:                } else {
        !          2244:                        SET_VFLG (0);
        !          2245:                        SET_CFLG (0);
        !          2246:                        SET_ZFLG (((uae_s32)quot) == 0);
        !          2247:                        SET_NFLG (((uae_s32)quot) < 0);
        !          2248:                        m68k_dreg (regs, extra & 7) = rem;
        !          2249:                        m68k_dreg (regs, (extra >> 12) & 7) = quot;
        !          2250:                }
        !          2251:        }
        !          2252: #endif
        !          2253: }
        !          2254: 
        !          2255: STATIC_INLINE void mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
        !          2256: {
        !          2257:        uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
        !          2258:        uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
        !          2259:        uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
        !          2260:        uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
        !          2261:        uae_u32 lo;
        !          2262: 
        !          2263:        lo = r0 + ((r1 << 16) & 0xffff0000ul);
        !          2264:        if (lo < r0) r3++;
        !          2265:        r0 = lo;
        !          2266:        lo = r0 + ((r2 << 16) & 0xffff0000ul);
        !          2267:        if (lo < r0) r3++;
        !          2268:        r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
        !          2269:        *dst_lo = lo;
        !          2270:        *dst_hi = r3;
        !          2271: }
        !          2272: 
        !          2273: void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
        !          2274: {
        !          2275: #if defined (uae_s64)
        !          2276:        if (extra & 0x800) {
        !          2277:                /* signed variant */
        !          2278:                uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2279: 
        !          2280:                a *= (uae_s64)(uae_s32)src;
        !          2281:                SET_VFLG (0);
        !          2282:                SET_CFLG (0);
        !          2283:                SET_ZFLG (a == 0);
        !          2284:                SET_NFLG (a < 0);
        !          2285:                if (extra & 0x400)
        !          2286:                        m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
        !          2287:                else if ((a & UVAL64 (0xffffffff80000000)) != 0
        !          2288:                        && (a & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
        !          2289:                {
        !          2290:                        SET_VFLG (1);
        !          2291:                }
        !          2292:                m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
        !          2293:        } else {
        !          2294:                /* unsigned */
        !          2295:                uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2296: 
        !          2297:                a *= (uae_u64)src;
        !          2298:                SET_VFLG (0);
        !          2299:                SET_CFLG (0);
        !          2300:                SET_ZFLG (a == 0);
        !          2301:                SET_NFLG (((uae_s64)a) < 0);
        !          2302:                if (extra & 0x400)
        !          2303:                        m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
        !          2304:                else if ((a & UVAL64 (0xffffffff00000000)) != 0) {
        !          2305:                        SET_VFLG (1);
        !          2306:                }
        !          2307:                m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
        !          2308:        }
        !          2309: #else
        !          2310:        if (extra & 0x800) {
        !          2311:                /* signed variant */
        !          2312:                uae_s32 src1, src2;
        !          2313:                uae_u32 dst_lo, dst_hi;
        !          2314:                uae_u32 sign;
        !          2315: 
        !          2316:                src1 = (uae_s32)src;
        !          2317:                src2 = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !          2318:                sign = (src1 ^ src2);
        !          2319:                if (src1 < 0) src1 = -src1;
        !          2320:                if (src2 < 0) src2 = -src2;
        !          2321:                mul_unsigned ((uae_u32)src1, (uae_u32)src2, &dst_hi, &dst_lo);
        !          2322:                if (sign & 0x80000000) {
        !          2323:                        dst_hi = ~dst_hi;
        !          2324:                        dst_lo = -dst_lo;
        !          2325:                        if (dst_lo == 0) dst_hi++;
        !          2326:                }
        !          2327:                SET_VFLG (0);
        !          2328:                SET_CFLG (0);
        !          2329:                SET_ZFLG (dst_hi == 0 && dst_lo == 0);
        !          2330:                SET_NFLG (((uae_s32)dst_hi) < 0);
        !          2331:                if (extra & 0x400)
        !          2332:                        m68k_dreg (regs, extra & 7) = dst_hi;
        !          2333:                else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
        !          2334:                        && ((dst_hi & 0xffffffff) != 0xffffffff
        !          2335:                        || (dst_lo & 0x80000000) != 0x80000000))
        !          2336:                {
        !          2337:                        SET_VFLG (1);
        !          2338:                }
        !          2339:                m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
        !          2340:        } else {
        !          2341:                /* unsigned */
        !          2342:                uae_u32 dst_lo, dst_hi;
        !          2343: 
        !          2344:                mul_unsigned (src, (uae_u32)m68k_dreg (regs, (extra >> 12) & 7), &dst_hi, &dst_lo);
        !          2345: 
        !          2346:                SET_VFLG (0);
        !          2347:                SET_CFLG (0);
        !          2348:                SET_ZFLG (dst_hi == 0 && dst_lo == 0);
        !          2349:                SET_NFLG (((uae_s32)dst_hi) < 0);
        !          2350:                if (extra & 0x400)
        !          2351:                        m68k_dreg (regs, extra & 7) = dst_hi;
        !          2352:                else if (dst_hi != 0) {
        !          2353:                        SET_VFLG (1);
        !          2354:                }
        !          2355:                m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
        !          2356:        }
        !          2357: #endif
        !          2358: }
        !          2359: 
        !          2360: #endif
        !          2361: 
        !          2362: void m68k_reset (int hardreset)
        !          2363: {
        !          2364:        regs.spcflags = 0;
        !          2365:        regs.ipl = regs.ipl_pin = 0;
        !          2366: #ifdef SAVESTATE
        !          2367:        if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) {
        !          2368:                m68k_setpc (regs.pc);
        !          2369:                SET_XFLG ((regs.sr >> 4) & 1);
        !          2370:                SET_NFLG ((regs.sr >> 3) & 1);
        !          2371:                SET_ZFLG ((regs.sr >> 2) & 1);
        !          2372:                SET_VFLG ((regs.sr >> 1) & 1);
        !          2373:                SET_CFLG (regs.sr & 1);
        !          2374:                regs.t1 = (regs.sr >> 15) & 1;
        !          2375:                regs.t0 = (regs.sr >> 14) & 1;
        !          2376:                regs.s  = (regs.sr >> 13) & 1;
        !          2377:                regs.m  = (regs.sr >> 12) & 1;
        !          2378:                regs.intmask = (regs.sr >> 8) & 7;
        !          2379:                /* set stack pointer */
        !          2380:                if (regs.s)
        !          2381:                        m68k_areg (regs, 7) = regs.isp;
        !          2382:                else
        !          2383:                        m68k_areg (regs, 7) = regs.usp;
        !          2384:                return;
        !          2385:        }
        !          2386: #endif
        !          2387:        regs.s = 1;
        !          2388:        regs.m = 0;
        !          2389:        regs.stopped = 0;
        !          2390:        regs.t1 = 0;
        !          2391:        regs.t0 = 0;
        !          2392:        SET_ZFLG (0);
        !          2393:        SET_XFLG (0);
        !          2394:        SET_CFLG (0);
        !          2395:        SET_VFLG (0);
        !          2396:        SET_NFLG (0);
        !          2397:        regs.intmask = 7;
        !          2398:        regs.vbr = regs.sfc = regs.dfc = 0;
        !          2399:        regs.irc = 0xffff;
        !          2400:        
        !          2401:        m68k_areg (regs, 7) = get_long (0);
        !          2402:        m68k_setpc (get_long (4));
        !          2403: 
        !          2404: #ifdef FPUEMU
        !          2405:        fpu_reset ();
        !          2406: #endif
        !          2407:        regs.caar = regs.cacr = 0;
        !          2408:        regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
        !          2409:        regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
        !          2410:        if (currprefs.cpu_model == 68020) {
        !          2411:                regs.cacr |= 8;
        !          2412:                set_cpu_caches ();
        !          2413:        }
        !          2414: 
        !          2415:        mmufixup[0].reg = -1;
        !          2416:        mmufixup[1].reg = -1;
        !          2417:        if (currprefs.mmu_model) {
        !          2418:                mmu_reset ();
        !          2419:                mmu_set_tc (regs.tcr);
        !          2420:                mmu_set_super (regs.s != 0);
        !          2421:        }
        !          2422: 
        !          2423: #if AMIGA_ONLY
        !          2424:        a3000_fakekick (0);
        !          2425: #endif
        !          2426:        /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
        !          2427:        tc_030 &= ~0x80000000;
        !          2428:        tt0_030 &= ~0x80000000;
        !          2429:        tt1_030 &= ~0x80000000;
        !          2430:        if (hardreset) {
        !          2431:                srp_030 = crp_030 = 0;
        !          2432:                tt0_030 = tt1_030 = tc_030 = 0;
        !          2433:        }
        !          2434:        mmusr_030 = 0;
        !          2435: 
        !          2436:        /* 68060 FPU is not compatible with 68040,
        !          2437:        * 68060 accelerators' boot ROM disables the FPU
        !          2438:        */
        !          2439:        regs.pcr = 0;
        !          2440:        if (currprefs.cpu_model == 68060) {
        !          2441:                regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
        !          2442:                regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
        !          2443:                if (kickstart_rom)
        !          2444:                        regs.pcr |= 2; /* disable FPU */
        !          2445:        }
        !          2446:        fill_prefetch_slow ();
        !          2447: }
        !          2448: 
        !          2449: unsigned long REGPARAM2 op_illg (uae_u32 opcode)
        !          2450: {
        !          2451:        uaecptr pc = m68k_getpc ();
        !          2452:        static int warned;
        !          2453: 
        !          2454: #if AMIGA_ONLY
        !          2455:        int inrom = in_rom (pc);
        !          2456:        int inrt = in_rtarea (pc);
        !          2457: 
        !          2458:        if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
        !          2459:                m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
        !          2460:                m68k_incpc (2);
        !          2461:                fill_prefetch_slow ();
        !          2462:                return 4;
        !          2463:        }
        !          2464: 
        !          2465:        if (opcode == 0x4E7B && inrom && get_long (0x10) == 0) {
        !          2466:                notify_user (NUMSG_KS68020);
        !          2467:                uae_restart (-1, NULL);
        !          2468:        }
        !          2469: #endif
        !          2470: 
        !          2471: #ifdef AUTOCONFIG
        !          2472:        if (opcode == 0xFF0D) {
        !          2473:                if (inrom) {
        !          2474:                        /* This is from the dummy Kickstart replacement */
        !          2475:                        uae_u16 arg = get_iword (2);
        !          2476:                        m68k_incpc (4);
        !          2477:                        ersatz_perform (arg);
        !          2478:                        fill_prefetch_slow ();
        !          2479:                        return 4;
        !          2480:                } else if (inrt) {
        !          2481:                        /* User-mode STOP replacement */
        !          2482:                        m68k_setstopped ();
        !          2483:                        return 4;
        !          2484:                }
        !          2485:        }
        !          2486: 
        !          2487:        if ((opcode & 0xF000) == 0xA000 && inrt) {
        !          2488:                /* Calltrap. */
        !          2489:                m68k_incpc (2);
        !          2490:                m68k_handle_trap (opcode & 0xFFF);
        !          2491:                fill_prefetch_slow ();
        !          2492:                return 4;
        !          2493:        }
        !          2494: #endif
        !          2495: 
        !          2496:        if ((opcode & 0xF000) == 0xF000) {
        !          2497:                if (warned < 20) {
        !          2498:                        write_log ("B-Trap %x at %x (%p)\n", opcode, pc, regs.pc_p);
        !          2499:                        warned++;
        !          2500:                }
        !          2501:                Exception (0xB, 0, M68000_EXC_SRC_CPU);
        !          2502:                //activate_debugger ();
        !          2503:                return 4;
        !          2504:        }
        !          2505:        if ((opcode & 0xF000) == 0xA000) {
        !          2506:                if (warned < 20) {
        !          2507:                        write_log ("A-Trap %x at %x (%p)\n", opcode, pc, regs.pc_p);
        !          2508:                        warned++;
        !          2509:                }
        !          2510:                Exception (0xA, 0, M68000_EXC_SRC_CPU);
        !          2511:                //activate_debugger();
        !          2512:                return 4;
        !          2513:        }
        !          2514:        if (warned < 20) {
        !          2515:                write_log ("Illegal instruction: %04x at %08X -> %08X\n", opcode, pc, get_long (regs.vbr + 0x10));
        !          2516:                warned++;
        !          2517:                //activate_debugger();
        !          2518:        }
        !          2519: 
        !          2520:        Exception (4, 0, M68000_EXC_SRC_CPU);
        !          2521:        return 4;
        !          2522: }
        !          2523: 
        !          2524: #ifdef CPUEMU_0
        !          2525: 
        !          2526: static const TCHAR *mmu30regs[] = { "TCR", "", "SRP", "CRP", "", "", "", "" };
        !          2527: 
        !          2528: static void mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          2529: {
        !          2530:        int preg = (next >> 10) & 31;
        !          2531:        int rw = (next >> 9) & 1;
        !          2532:        int fd = (next >> 8) & 1;
        !          2533:        const TCHAR *reg = NULL;
        !          2534:        uae_u32 otc = tc_030;
        !          2535:        int siz;
        !          2536: 
        !          2537:        switch (preg)
        !          2538:        {
        !          2539:        case 0x10: // TC
        !          2540:                reg = "TC";
        !          2541:                siz = 4;
        !          2542:                if (rw)
        !          2543:                        x_put_long (extra, tc_030);
        !          2544:                else
        !          2545:                        tc_030 = x_get_long (extra);
        !          2546:                break;
        !          2547:        case 0x12: // SRP
        !          2548:                reg = "SRP";
        !          2549:                siz = 8;
        !          2550:                if (rw) {
        !          2551:                        x_put_long (extra, srp_030 >> 32);
        !          2552:                        x_put_long (extra + 4, srp_030);
        !          2553:                } else {
        !          2554:                        srp_030 = (uae_u64)x_get_long (extra) << 32;
        !          2555:                        srp_030 |= x_get_long (extra + 4);
        !          2556:                }
        !          2557:                break;
        !          2558:        case 0x13: // CRP
        !          2559:                reg = "CRP";
        !          2560:                siz = 8;
        !          2561:                if (rw) {
        !          2562:                        x_put_long (extra, crp_030 >> 32);
        !          2563:                        x_put_long (extra + 4, crp_030);
        !          2564:                } else {
        !          2565:                        crp_030 = (uae_u64)x_get_long (extra) << 32;
        !          2566:                        crp_030 |= x_get_long (extra + 4);
        !          2567:                }
        !          2568:                break;
        !          2569:        case 0x18: // MMUSR
        !          2570:                reg = "MMUSR";
        !          2571:                siz = 2;
        !          2572:                if (rw)
        !          2573:                        x_put_word (extra, mmusr_030);
        !          2574:                else
        !          2575:                        mmusr_030 = x_get_word (extra);
        !          2576:                break;
        !          2577:        case 0x02: // TT0
        !          2578:                reg = "TT0";
        !          2579:                siz = 4;
        !          2580:                if (rw)
        !          2581:                        x_put_long (extra, tt0_030);
        !          2582:                else
        !          2583:                        tt0_030 = x_get_long (extra);
        !          2584:                break;
        !          2585:        case 0x03: // TT1
        !          2586:                reg = "TT1";
        !          2587:                siz = 4;
        !          2588:                if (rw)
        !          2589:                        x_put_long (extra, tt1_030);
        !          2590:                else
        !          2591:                        tt1_030 = x_get_long (extra);
        !          2592:                break;
        !          2593:        }
        !          2594: 
        !          2595:        if (!reg) {
        !          2596:                op_illg (opcode);
        !          2597:                return;
        !          2598:        }
        !          2599: #if MMUOP_DEBUG > 0
        !          2600:        {
        !          2601:                uae_u32 val;
        !          2602:                if (siz == 8) {
        !          2603:                        uae_u32 val2 = x_get_long (extra);
        !          2604:                        val = x_get_long (extra + 4);
        !          2605:                        if (rw)
        !          2606:                                write_log ("PMOVE %s,%08X%08X", reg, val2, val);
        !          2607:                        else
        !          2608:                                write_log ("PMOVE %08X%08X,%s", val2, val, reg);
        !          2609:                } else {
        !          2610:                        if (siz == 4)
        !          2611:                                val = x_get_long (extra);
        !          2612:                        else
        !          2613:                                val = x_get_word (extra);
        !          2614:                        if (rw)
        !          2615:                                write_log ("PMOVE %s,%08X", reg, val);
        !          2616:                        else
        !          2617:                                write_log ("PMOVE %08X,%s", val, reg);
        !          2618:                }
        !          2619:                write_log (" PC=%08X\n", pc);
        !          2620:        }
        !          2621: #endif
        !          2622:        if (currprefs.cs_mbdmac == 1 && currprefs.mbresmem_low_size > 0) {
        !          2623:                if (otc != tc_030) {
        !          2624: #if AMIGA_ONLY
        !          2625:                        a3000_fakekick (tc_030 & 0x80000000);
        !          2626: #endif
        !          2627:                }
        !          2628:        }
        !          2629: }
        !          2630: 
        !          2631: static void mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          2632: {
        !          2633: #if MMUOP_DEBUG > 0
        !          2634:        TCHAR tmp[10];
        !          2635: 
        !          2636:        tmp[0] = 0;
        !          2637:        if ((next >> 8) & 1)
        !          2638:                _stprintf (tmp, ",A%d", (next >> 4) & 15);
        !          2639:        write_log ("PTEST%c %02X,%08X,#%X%s PC=%08X\n",
        !          2640:                ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
        !          2641: #endif
        !          2642:        mmusr_030 = 0;
        !          2643: }
        !          2644: 
        !          2645: static void mmu_op30_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          2646: {
        !          2647: #if MMUOP_DEBUG > 0
        !          2648:        write_log ("PFLUSH PC=%08X\n", pc);
        !          2649: #endif
        !          2650: }
        !          2651: 
        !          2652: void mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
        !          2653: {
        !          2654:        if (currprefs.cpu_model != 68030) {
        !          2655:                m68k_setpc (pc);
        !          2656:                op_illg (opcode);
        !          2657:                return;
        !          2658:        }
        !          2659:        if (extra & 0x8000)
        !          2660:                mmu_op30_ptest (pc, opcode, extra, extraa);
        !          2661:        else if (extra & 0x2000)
        !          2662:                mmu_op30_pflush (pc, opcode, extra, extraa);
        !          2663:        else
        !          2664:                mmu_op30_pmove (pc, opcode, extra, extraa);
        !          2665: }
        !          2666: 
        !          2667: void mmu_op (uae_u32 opcode, uae_u32 extra)
        !          2668: {
        !          2669:        if (currprefs.cpu_model) {
        !          2670:                mmu_op_real (opcode, extra);
        !          2671:                return;
        !          2672:        }
        !          2673: #if MMUOP_DEBUG > 1
        !          2674:        write_log ("mmu_op %04X PC=%08X\n", opcode, m68k_getpc ());
        !          2675: #endif
        !          2676:        if ((opcode & 0xFE0) == 0x0500) {
        !          2677:                /* PFLUSH */
        !          2678:                regs.mmusr = 0;
        !          2679: #if MMUOP_DEBUG > 0
        !          2680:                write_log ("PFLUSH\n");
        !          2681: #endif
        !          2682:                return;
        !          2683:        } else if ((opcode & 0x0FD8) == 0x548) {
        !          2684:                if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
        !          2685:                        /* PTEST */
        !          2686: #if MMUOP_DEBUG > 0
        !          2687:                        write_log ("PTEST\n");
        !          2688: #endif
        !          2689:                        return;
        !          2690:                }
        !          2691:        } else if ((opcode & 0x0FB8) == 0x588) {
        !          2692:                /* PLPA */
        !          2693:                if (currprefs.cpu_model == 68060) {
        !          2694: #if MMUOP_DEBUG > 0
        !          2695:                        write_log ("PLPA\n");
        !          2696: #endif
        !          2697:                        return;
        !          2698:                }
        !          2699:        }
        !          2700: #if MMUOP_DEBUG > 0
        !          2701:        write_log ("Unknown MMU OP %04X\n", opcode);
        !          2702: #endif
        !          2703:        m68k_setpc (m68k_getpc () - 2);
        !          2704:        op_illg (opcode);
        !          2705: }
        !          2706: 
        !          2707: #endif
        !          2708: 
        !          2709: static uaecptr last_trace_ad = 0;
        !          2710: 
        !          2711: static void do_trace (void)
        !          2712: {
        !          2713:        if (regs.t0 && currprefs.cpu_model >= 68020) {
        !          2714:                uae_u16 opcode;
        !          2715:                /* should also include TRAP, CHK, SR modification FPcc */
        !          2716:                /* probably never used so why bother */
        !          2717:                /* We can afford this to be inefficient... */
        !          2718:                m68k_setpc (m68k_getpc ());
        !          2719:                fill_prefetch_slow ();
        !          2720:                opcode = x_get_word (regs.pc);
        !          2721:                if (opcode == 0x4e73                    /* RTE */
        !          2722:                        || opcode == 0x4e74             /* RTD */
        !          2723:                        || opcode == 0x4e75             /* RTS */
        !          2724:                        || opcode == 0x4e77             /* RTR */
        !          2725:                        || opcode == 0x4e76             /* TRAPV */
        !          2726:                        || (opcode & 0xffc0) == 0x4e80  /* JSR */
        !          2727:                        || (opcode & 0xffc0) == 0x4ec0  /* JMP */
        !          2728:                        || (opcode & 0xff00) == 0x6100  /* BSR */
        !          2729:                        || ((opcode & 0xf000) == 0x6000 /* Bcc */
        !          2730:                        && cctrue ((opcode >> 8) & 0xf))
        !          2731:                        || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
        !          2732:                        && !cctrue ((opcode >> 8) & 0xf)
        !          2733:                        && (uae_s16)m68k_dreg (regs, opcode & 7) != 0))
        !          2734:                {
        !          2735:                        last_trace_ad = m68k_getpc ();
        !          2736:                        unset_special (SPCFLAG_TRACE);
        !          2737:                        set_special (SPCFLAG_DOTRACE);
        !          2738:                }
        !          2739:        } else if (regs.t1) {
        !          2740:                last_trace_ad = m68k_getpc ();
        !          2741:                unset_special (SPCFLAG_TRACE);
        !          2742:                set_special (SPCFLAG_DOTRACE);
        !          2743:        }
        !          2744: }
        !          2745: 
        !          2746: 
        !          2747: // handle interrupt delay (few cycles)
        !          2748: STATIC_INLINE int time_for_interrupt (void)
        !          2749: {
        !          2750:        if (regs.ipl > regs.intmask || regs.ipl == 7) {
        !          2751: #if 0
        !          2752:                if (regs.ipl == 3 && current_hpos () < 11) {
        !          2753:                        write_log ("%d\n", current_hpos ());
        !          2754:                        activate_debugger ();
        !          2755:                }
        !          2756: #endif
        !          2757:                return 1;
        !          2758:        }
        !          2759:        return 0;
        !          2760: }
        !          2761: 
        !          2762: void doint (void)
        !          2763: {
        !          2764:        if (currprefs.cpu_cycle_exact) {
        !          2765:                regs.ipl_pin = intlev ();
        !          2766:                set_special (SPCFLAG_INT);
        !          2767:                return;
        !          2768:        }
        !          2769:        if (currprefs.cpu_compatible)
        !          2770:                set_special (SPCFLAG_INT);
        !          2771:        else
        !          2772:                set_special (SPCFLAG_DOINT);
        !          2773: }
        !          2774: 
        !          2775: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 700)
        !          2776: 
        !          2777: /*
        !          2778:  * Compute the number of jitter cycles to add when a video interrupt occurs
        !          2779:  * (this is specific to the Atari ST)
        !          2780:  */
        !          2781: STATIC_INLINE void InterruptAddJitter (int Level , int Pending)
        !          2782: {
        !          2783:        int cycles = 0;
        !          2784: 
        !          2785:        if ( Level == 2 )                               /* HBL */
        !          2786:        {
        !          2787:                if ( Pending )
        !          2788:                        cycles = HblJitterArrayPending[ HblJitterIndex ];
        !          2789:                else
        !          2790:                        cycles = HblJitterArray[ HblJitterIndex ];
        !          2791:        }
        !          2792:        else if ( Level == 4 )                  /* VBL */
        !          2793:        {
        !          2794:                if ( Pending )
        !          2795:                        cycles = VblJitterArrayPending[ VblJitterIndex ];
        !          2796:                else
        !          2797:                        cycles = VblJitterArray[ VblJitterIndex ];
        !          2798:        }
        !          2799: 
        !          2800:        //fprintf ( stderr , "jitter %d\n" , cycles );
        !          2801:        //cycles=0;
        !          2802:        if ( cycles > 0 )                               /* no need to call M68000_AddCycles if cycles == 0 */
        !          2803:                M68000_AddCycles ( cycles );
        !          2804: }
        !          2805: 
        !          2806: 
        !          2807: /*
        !          2808:  * Handle special flags
        !          2809:  */
        !          2810: 
        !          2811: static bool do_specialties_interrupt (int Pending)
        !          2812: {
        !          2813:     /* Check for MFP ints first (level 6) */
        !          2814:     if (regs.spcflags & SPCFLAG_MFP) {
        !          2815:        if (MFP_CheckPendingInterrupts() == true)
        !          2816:          return true;                                  /* MFP exception was generated, no higher interrupt can happen */
        !          2817:     }
        !          2818: 
        !          2819:     /* No MFP int, check for VBL/HBL ints (levels 4/2) */
        !          2820:     if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
        !          2821:        int intr = intlev ();
        !          2822:        /* SPCFLAG_DOINT will be enabled again in MakeFromSR to handle pending interrupts! */
        !          2823: //     unset_special (SPCFLAG_DOINT);
        !          2824:        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
        !          2825:        if (intr != -1 && intr > regs.intmask) {
        !          2826:            do_interrupt (intr , Pending);                      /* process the interrupt and add pending jitter if necessary */
        !          2827:            return true;
        !          2828:        }
        !          2829:     }
        !          2830: 
        !          2831:     return false;                                      /* no interrupt was found */
        !          2832: }
        !          2833: 
        !          2834: STATIC_INLINE int do_specialties (int cycles)
        !          2835: {
        !          2836: #ifdef JIT
        !          2837:        unset_special (SPCFLAG_END_COMPILE);   /* has done its job */
        !          2838: #endif
        !          2839: 
        !          2840: #if AMIGA_ONLY
        !          2841:        while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
        !          2842:                /* Laurent : I don't know if our blitter code should be called here ! */
        !          2843:                int c = blitnasty ();
        !          2844:                if (c > 0) {
        !          2845:                        cycles -= c * CYCLE_UNIT * 2;
        !          2846:                        if (cycles < CYCLE_UNIT)
        !          2847:                                cycles = 0;
        !          2848:                } else
        !          2849:                        c = 4;
        !          2850:                do_cycles (c * CYCLE_UNIT);
        !          2851:                if (regs.spcflags & SPCFLAG_COPPER)
        !          2852:                        do_copper ();
        !          2853:        }
        !          2854: #endif
        !          2855: 
        !          2856:        if (regs.spcflags & SPCFLAG_BUSERROR) {
        !          2857:                /* We can not execute bus errors directly in the memory handler
        !          2858:                * functions since the PC should point to the address of the next
        !          2859:                * instruction, so we're executing the bus errors here: */
        !          2860:                unset_special(SPCFLAG_BUSERROR);
        !          2861:                Exception(2, 0, M68000_EXC_SRC_CPU);
        !          2862:        }
        !          2863: 
        !          2864:        if(regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          2865:                /* Add some extra cycles to simulate a wait state */
        !          2866:                unset_special(SPCFLAG_EXTRA_CYCLES);
        !          2867:                M68000_AddCycles(nWaitStateCycles);
        !          2868:                nWaitStateCycles = 0;
        !          2869:        }
        !          2870: 
        !          2871:        if (regs.spcflags & SPCFLAG_DOTRACE)
        !          2872:                Exception (9, last_trace_ad, M68000_EXC_SRC_CPU);
        !          2873: 
        !          2874:        if (regs.spcflags & SPCFLAG_TRAP) {
        !          2875:                unset_special (SPCFLAG_TRAP);
        !          2876:                Exception (3, 0, M68000_EXC_SRC_CPU);
        !          2877:        }
        !          2878: 
        !          2879:     /* Handle the STOP instruction */
        !          2880:     if ( regs.spcflags & SPCFLAG_STOP ) {
        !          2881:         /* We first test if there's a pending interrupt that would */
        !          2882:         /* allow to immediatly leave the STOP state */
        !          2883:         if ( do_specialties_interrupt(true) ) {                /* test if there's an interrupt and add pending jitter */
        !          2884:             regs.stopped = 0;
        !          2885:             unset_special (SPCFLAG_STOP);
        !          2886:         }
        !          2887: #if 0
        !          2888:        if (regs.spcflags & SPCFLAG_MFP)                        /* MFP int */
        !          2889:            MFP_CheckPendingInterrupts();
        !          2890:        
        !          2891:        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {    /* VBL/HBL ints */
        !          2892:            int intr = intlev ();
        !          2893:            unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
        !          2894:            if (intr != -1 && intr > regs.intmask) {
        !          2895:                Interrupt (intr , true);                /* process the interrupt and add pending jitter */
        !          2896:                regs.stopped = 0;
        !          2897:                unset_special (SPCFLAG_STOP);
        !          2898:            }
        !          2899:        }
        !          2900: #endif
        !          2901: 
        !          2902:        while (regs.spcflags & SPCFLAG_STOP) {
        !          2903: 
        !          2904:            /* Take care of quit event if needed */
        !          2905:            if (regs.spcflags & SPCFLAG_BRK)
        !          2906:                        return 1;
        !          2907:        
        !          2908:                do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
        !          2909:                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
        !          2910: 
        !          2911:            /* It is possible one or more ints happen at the same time */
        !          2912:            /* We must process them during the same cpu cycle until the special INT flag is set */
        !          2913:                while (PendingInterruptCount<=0 && PendingInterruptFunction) {
        !          2914:                        /* 1st, we call the interrupt handler */
        !          2915:                        CALL_VAR(PendingInterruptFunction);
        !          2916:                
        !          2917:                        /* Then we check if this handler triggered an interrupt to process */
        !          2918:                        if ( do_specialties_interrupt(false) ) {        /* test if there's an interrupt and add non pending jitter */
        !          2919:                                regs.stopped = 0;
        !          2920:                                unset_special (SPCFLAG_STOP);
        !          2921:                                break;
        !          2922:                        }
        !          2923: 
        !          2924:                        /* Then we check if this handler triggered an MFP int to process */
        !          2925:                        if (regs.spcflags & SPCFLAG_MFP) {          /* Check for MFP interrupts */
        !          2926:                                MFP_CheckPendingInterrupts();
        !          2927:                        }
        !          2928:                
        !          2929: #if AMIGA_ONLY
        !          2930:                        if (regs.spcflags & SPCFLAG_COPPER)
        !          2931:                                do_copper ();
        !          2932: #endif
        !          2933: 
        !          2934:                        if (currprefs.cpu_cycle_exact) {
        !          2935:                                ipl_fetch ();
        !          2936:                                if (time_for_interrupt ()) {
        !          2937:                                        do_interrupt (regs.ipl, true);
        !          2938:                                }
        !          2939:                        } else {
        !          2940: #if 0
        !          2941:                                if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
        !          2942:                                        int intr = intlev ();
        !          2943:                                        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
        !          2944:                                        if (intr > 0 && intr > regs.intmask)
        !          2945:                                                do_interrupt (intr, true);
        !          2946:                                }
        !          2947: #endif
        !          2948:                        }
        !          2949:                        if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
        !          2950:                                unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
        !          2951:                                // SPCFLAG_BRK breaks STOP condition, need to prefetch
        !          2952:                                m68k_resumestopped ();
        !          2953:                                return 1;
        !          2954:                        }
        !          2955: 
        !          2956:                        if (currprefs.cpu_idle && currprefs.m68k_speed != 0 && ((regs.spcflags & SPCFLAG_STOP)) == SPCFLAG_STOP) {
        !          2957:                                /* sleep 1ms if STOP-instruction is executed */
        !          2958:                                if (1) {
        !          2959:                                        static int sleepcnt, lvpos, zerocnt;
        !          2960:                                                if (vpos != lvpos) {
        !          2961:                                                        sleepcnt--;
        !          2962: #ifdef JIT
        !          2963:                                                if (pissoff == 0 && currprefs.cachesize && --zerocnt < 0) {
        !          2964:                                                        sleepcnt = -1;
        !          2965:                                                        zerocnt = IDLETIME / 4;
        !          2966:                                                }
        !          2967: #endif
        !          2968:                                                lvpos = vpos;
        !          2969:                                                if (sleepcnt < 0) {
        !          2970:                                                        /*sleepcnt = IDLETIME / 2; */  /* Laurent : badly removed for now */
        !          2971:                                                        sleep_millis (1);
        !          2972:                                                }
        !          2973:                                        }
        !          2974:                                }
        !          2975:                        }
        !          2976:                }
        !          2977:        }
        !          2978:        }
        !          2979: 
        !          2980:        if (regs.spcflags & SPCFLAG_TRACE)
        !          2981:                do_trace ();
        !          2982: 
        !          2983:        if (currprefs.cpu_cycle_exact) {
        !          2984:                if (time_for_interrupt ()) {
        !          2985:                        do_interrupt (regs.ipl, true);
        !          2986:                }
        !          2987:        } else {
        !          2988:                if (regs.spcflags & SPCFLAG_INT) {
        !          2989:                        int intr = intlev ();
        !          2990:                        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
        !          2991:                        if (intr > 0 && (intr > regs.intmask || intr == 7))
        !          2992:                                do_interrupt (intr, false);             /* call do_interrupt() with Pending=false, not necessarily true but harmless */
        !          2993:                }
        !          2994:        }
        !          2995: 
        !          2996:        if (regs.spcflags & SPCFLAG_DOINT) {
        !          2997:                unset_special (SPCFLAG_DOINT);
        !          2998:                set_special (SPCFLAG_INT);
        !          2999:        }
        !          3000: 
        !          3001:        if ( do_specialties_interrupt(false) ) {        /* test if there's an interrupt and add non pending jitter */
        !          3002:                /* TODO: Always do do_specialties_interrupt() in m68k_run_x instead? */
        !          3003:                regs.stopped = 0;
        !          3004:        }
        !          3005: 
        !          3006:     if (regs.spcflags & SPCFLAG_DEBUGGER)
        !          3007:                DebugCpu_Check();
        !          3008: 
        !          3009:        if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
        !          3010:                unset_special(SPCFLAG_MODE_CHANGE);
        !          3011:                return 1;
        !          3012:        }
        !          3013:        return 0;
        !          3014: }
        !          3015: 
        !          3016: //static uae_u32 pcs[1000];
        !          3017: 
        !          3018: #if DEBUG_CD32CDTVIO
        !          3019: 
        !          3020: static uae_u32 cd32nextpc, cd32request;
        !          3021: 
        !          3022: static void out_cd32io2 (void)
        !          3023: {
        !          3024:        uae_u32 request = cd32request;
        !          3025:        write_log ("%08x returned\n", request);
        !          3026:        //write_log ("ACTUAL=%d ERROR=%d\n", get_long (request + 32), get_byte (request + 31));
        !          3027:        cd32nextpc = 0;
        !          3028:        cd32request = 0;
        !          3029: }
        !          3030: 
        !          3031: static void out_cd32io (uae_u32 pc)
        !          3032: {
        !          3033:        TCHAR out[100];
        !          3034:        int ioreq = 0;
        !          3035:        uae_u32 request = m68k_areg (regs, 1);
        !          3036: 
        !          3037:        if (pc == cd32nextpc) {
        !          3038:                out_cd32io2 ();
        !          3039:                return;
        !          3040:        }
        !          3041:        out[0] = 0;
        !          3042:        switch (pc)
        !          3043:        {
        !          3044:        case 0xe57cc0:
        !          3045:        case 0xf04c34:
        !          3046:                _stprintf (out, "opendevice");
        !          3047:                break;
        !          3048:        case 0xe57ce6:
        !          3049:        case 0xf04c56:
        !          3050:                _stprintf (out, "closedevice");
        !          3051:                break;
        !          3052:        case 0xe57e44:
        !          3053:        case 0xf04f2c:
        !          3054:                _stprintf (out, "beginio");
        !          3055:                ioreq = 1;
        !          3056:                break;
        !          3057:        case 0xe57ef2:
        !          3058:        case 0xf0500e:
        !          3059:                _stprintf (out, "abortio");
        !          3060:                ioreq = -1;
        !          3061:                break;
        !          3062:        }
        !          3063:        if (out[0] == 0)
        !          3064:                return;
        !          3065:        if (cd32request)
        !          3066:                write_log ("old request still not returned!\n");
        !          3067:        cd32request = request;
        !          3068:        cd32nextpc = get_long (m68k_areg (regs, 7));
        !          3069:        write_log ("%s A1=%08X\n", out, request);
        !          3070:        if (ioreq) {
        !          3071:                static int cnt = 0;
        !          3072:                int cmd = get_word (request + 28);
        !          3073: #if 0
        !          3074:                if (cmd == 37) {
        !          3075:                        cnt--;
        !          3076:                        if (cnt <= 0)
        !          3077:                                activate_debugger ();
        !          3078:                }
        !          3079: #endif
        !          3080:                write_log ("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n",
        !          3081:                        cmd, get_long (request + 40),
        !          3082:                        get_long (request + 36), get_long (request + 44), M68K_GETPC);
        !          3083:        }
        !          3084:        if (ioreq < 0)
        !          3085:                ;//activate_debugger ();
        !          3086: }
        !          3087: 
        !          3088: #endif /* DEBUG_CD32CDTVIO */
        !          3089: 
        !          3090: #ifndef CPUEMU_11
        !          3091: 
        !          3092: static void m68k_run_1 (void)
        !          3093: {
        !          3094: }
        !          3095: 
        !          3096: #else
        !          3097: 
        !          3098: /* It's really sad to have two almost identical functions for this, but we
        !          3099: do it all for performance... :(
        !          3100: This version emulates 68000's prefetch "cache" */
        !          3101: static void m68k_run_1 (void)
        !          3102: {
        !          3103:        struct regstruct *r = &regs;
        !          3104: 
        !          3105:        for (;;) {
        !          3106:                uae_u32 opcode = r->ir;
        !          3107: 
        !          3108:                count_instr (opcode);
        !          3109: 
        !          3110:        /*m68k_dumpstate(stderr, NULL);*/
        !          3111:        if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3112:        {
        !          3113:            int FrameCycles, HblCounterVideo, LineCycles;
        !          3114: 
        !          3115:            Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3116: 
        !          3117:            LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3118:            m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3119:        }
        !          3120: 
        !          3121: #if DEBUG_CD32CDTVIO
        !          3122:                out_cd32io (m68k_getpc ());
        !          3123: #endif
        !          3124: 
        !          3125: #if 0
        !          3126:                int pc = m68k_getpc ();
        !          3127:                if (pc == 0xdff002)
        !          3128:                        write_log ("hip\n");
        !          3129:                if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
        !          3130:                        memmove (pcs + 1, pcs, 998 * 4);
        !          3131:                        pcs[0] = pc;
        !          3132:                        //write_log ("%08X-%04X ", pc, opcode);
        !          3133:                }
        !          3134: #endif
        !          3135:                do_cycles (cpu_cycles);
        !          3136:                cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3137:                cpu_cycles &= cycles_mask;
        !          3138:                cpu_cycles |= cycles_val;
        !          3139:                
        !          3140:                /* We can have several interrupts at the same time before the next CPU instruction */
        !          3141:                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          3142:                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          3143:                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          3144:                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          3145:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
        !          3146:                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          3147:                        do_specialties_interrupt(false);                /* test if there's an mfp/video interrupt and add non pending jitter */
        !          3148:                }
        !          3149:                
        !          3150:                if (r->spcflags) {
        !          3151:                        if (do_specialties (cpu_cycles))
        !          3152:                                return;
        !          3153:                }
        !          3154:                regs.ipl = regs.ipl_pin;
        !          3155:                if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000))
        !          3156:                        return;
        !          3157:        }
        !          3158: }
        !          3159: 
        !          3160: #endif /* CPUEMU_11 */
        !          3161: 
        !          3162: #ifndef CPUEMU_12
        !          3163: 
        !          3164: static void m68k_run_1_ce (void)
        !          3165: {
        !          3166: }
        !          3167: 
        !          3168: #else
        !          3169: 
        !          3170: /* cycle-exact m68k_run () */
        !          3171: 
        !          3172: static void m68k_run_1_ce (void)
        !          3173: {
        !          3174:        struct regstruct *r = &regs;
        !          3175: 
        !          3176:        ipl_fetch ();
        !          3177:        for (;;) {
        !          3178:                uae_u32 opcode = r->ir;
        !          3179: 
        !          3180:                /*m68k_dumpstate(stderr, NULL);*/
        !          3181:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3182:                {
        !          3183:                        int FrameCycles, HblCounterVideo, LineCycles;
        !          3184:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3185:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3186:                        m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3187:                }
        !          3188: 
        !          3189: #if DEBUG_CD32CDTVIO
        !          3190:                out_cd32io (m68k_getpc ());
        !          3191: #endif
        !          3192:                (*cpufunctbl[opcode])(opcode);
        !          3193:                if (r->spcflags) {
        !          3194:                        if (do_specialties (0))
        !          3195:                                return;
        !          3196:                }
        !          3197:                if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68000)
        !          3198:                        return;
        !          3199:        }
        !          3200: }
        !          3201: #endif
        !          3202: 
        !          3203: #ifdef JIT  /* Completely different run_2 replacement */
        !          3204: 
        !          3205: void do_nothing (void)
        !          3206: {
        !          3207:        /* What did you expect this to do? */
        !          3208:        do_cycles (0);
        !          3209:        /* I bet you didn't expect *that* ;-) */
        !          3210: }
        !          3211: 
        !          3212: void exec_nostats (void)
        !          3213: {
        !          3214:        struct regstruct *r = &regs;
        !          3215: 
        !          3216:        for (;;)
        !          3217:        {
        !          3218:                uae_u16 opcode = get_iword (0);
        !          3219: 
        !          3220:                cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3221: 
        !          3222:                cpu_cycles &= cycles_mask;
        !          3223:                cpu_cycles |= cycles_val;
        !          3224: 
        !          3225:                do_cycles (cpu_cycles);
        !          3226: 
        !          3227:                if (end_block (opcode) || r->spcflags || uae_int_requested)
        !          3228:                        return; /* We will deal with the spcflags in the caller */
        !          3229:        }
        !          3230: }
        !          3231: 
        !          3232: static int triggered;
        !          3233: 
        !          3234: void execute_normal (void)
        !          3235: {
        !          3236:        struct regstruct *r = &regs;
        !          3237:        int blocklen;
        !          3238:        cpu_history pc_hist[MAXRUN];
        !          3239:        int total_cycles;
        !          3240: 
        !          3241:        if (check_for_cache_miss ())
        !          3242:                return;
        !          3243: 
        !          3244:        total_cycles = 0;
        !          3245:        blocklen = 0;
        !          3246:        start_pc_p = r->pc_oldp;
        !          3247:        start_pc = r->pc;
        !          3248:        for (;;) {
        !          3249:                /* Take note: This is the do-it-normal loop */
        !          3250:                uae_u16 opcode = get_iword (0);
        !          3251: 
        !          3252:                special_mem = DISTRUST_CONSISTENT_MEM;
        !          3253:                pc_hist[blocklen].location = (uae_u16*)r->pc_p;
        !          3254: 
        !          3255:                cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3256: 
        !          3257:                cpu_cycles &= cycles_mask;
        !          3258:                cpu_cycles |= cycles_val;
        !          3259:                do_cycles (cpu_cycles);
        !          3260:                total_cycles += cpu_cycles;
        !          3261:                pc_hist[blocklen].specmem = special_mem;
        !          3262:                blocklen++;
        !          3263:                if (end_block (opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested) {
        !          3264:                        compile_block (pc_hist, blocklen, total_cycles);
        !          3265:                        return; /* We will deal with the spcflags in the caller */
        !          3266:                }
        !          3267:                /* No need to check regs.spcflags, because if they were set,
        !          3268:                we'd have ended up inside that "if" */
        !          3269:        }
        !          3270: }
        !          3271: 
        !          3272: typedef void compiled_handler (void);
        !          3273: 
        !          3274: static void m68k_run_jit (void)
        !          3275: {
        !          3276:        for (;;) {
        !          3277: 
        !          3278:                /*m68k_dumpstate(stderr, NULL);*/
        !          3279:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3280:                {
        !          3281:                        int FrameCycles, HblCounterVideo, LineCycles;
        !          3282:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3283:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3284:                        m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3285:                }
        !          3286: 
        !          3287:                ((compiled_handler*)(pushall_call_handler))();
        !          3288:                /* Whenever we return from that, we should check spcflags */
        !          3289:                if (uae_int_requested) {
        !          3290:                        INTREQ_f (0x8008);
        !          3291:                        set_special (SPCFLAG_INT);
        !          3292:                }
        !          3293:                if (regs.spcflags) {
        !          3294:                        if (do_specialties (0)) {
        !          3295:                                return;
        !          3296:                        }
        !          3297:                }
        !          3298:        }
        !          3299: }
        !          3300: #endif /* JIT */
        !          3301: 
        !          3302: #ifndef CPUEMU_0
        !          3303: 
        !          3304: static void m68k_run_2 (void)
        !          3305: {
        !          3306: }
        !          3307: 
        !          3308: #else
        !          3309: 
        !          3310: #if 0
        !          3311: static void opcodedebug (uae_u32 pc, uae_u16 opcode)
        !          3312: {
        !          3313:        struct mnemolookup *lookup;
        !          3314:        struct instr *dp;
        !          3315:        uae_u32 addr;
        !          3316:        int fault;
        !          3317: 
        !          3318:        if (cpufunctbl[opcode] == op_illg_1)
        !          3319:                opcode = 0x4AFC;
        !          3320:        dp = table68k + opcode;
        !          3321:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
        !          3322:                ;
        !          3323:        fault = 0;
        !          3324: //     TRY(prb) {
        !          3325:        except = 0;
        !          3326:        addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0);
        !          3327: //     } CATCH (prb) {
        !          3328:        if (except != 0) {
        !          3329:                fault = 1;
        !          3330:        }
        !          3331:        if (!fault) {
        !          3332:                write_log ("mmufixup=%d %04x %04x\n", mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
        !          3333:                m68k_disasm_2 (stdout, addr, NULL, 1, NULL, NULL, 0);
        !          3334:                write_log ("%s\n", buf);
        !          3335:                m68k_dumpstate (stdout, NULL);
        !          3336:        }
        !          3337: }
        !          3338: #endif
        !          3339: 
        !          3340: /* Aranym MMU 68040  */
        !          3341: static void m68k_run_mmu040 (void)
        !          3342: {
        !          3343:        uae_u32 opcode;
        !          3344:        uaecptr pc;
        !          3345:        m68k_exception save_except;
        !          3346:        
        !          3347: retry:
        !          3348: //     TRY (prb) {
        !          3349:                except = 0;
        !          3350:                for (;;) {
        !          3351:                        if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3352:                        {
        !          3353:                                int FrameCycles, HblCounterVideo, LineCycles;
        !          3354:                                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3355:                                LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3356:                                m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3357:                        }
        !          3358: 
        !          3359:                        pc = regs.fault_pc = m68k_getpc ();
        !          3360: #if 0
        !          3361:                        static int done;
        !          3362:                        if (pc == 0x16AF94) {
        !          3363: //                             write_log ("D0=%d A7=%08x\n", regs.regs[0], regs.regs[15]);
        !          3364:                                if (regs.regs[0] == 360) {
        !          3365:                                        done = 1;
        !          3366:                                        activate_debugger ();
        !          3367:                                }
        !          3368:                        }
        !          3369: /*
        !          3370:                        if (pc == 0x16B01A) {
        !          3371:                                write_log ("-> ERR\n");
        !          3372:                        }
        !          3373:                        if (pc == 0x16B018) {
        !          3374:                                write_log ("->\n");
        !          3375:                        }
        !          3376: */
        !          3377:                        if (pc == 0x17967C || pc == 0x13b5e2 - 4) {
        !          3378:                                if (done) {
        !          3379:                                        write_log ("*\n");
        !          3380:                                        mmu_dump_tables ();
        !          3381:                                        activate_debugger ();
        !          3382:                                }
        !          3383:                        }
        !          3384: #endif
        !          3385:                        opcode = x_prefetch (0);
        !          3386:                        count_instr (opcode);
        !          3387:                        do_cycles (cpu_cycles);
        !          3388:                        cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3389:                        cpu_cycles &= cycles_mask;
        !          3390:                        cpu_cycles |= cycles_val;
        !          3391: 
        !          3392: 
        !          3393:                        M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
        !          3394: 
        !          3395:                        if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          3396:                                /* Add some extra cycles to simulate a wait state */
        !          3397:                                unset_special(SPCFLAG_EXTRA_CYCLES);
        !          3398:                                M68000_AddCycles(nWaitStateCycles);
        !          3399:                                nWaitStateCycles = 0;
        !          3400:                        }
        !          3401: 
        !          3402:                        /* We can have several interrupts at the same time before the next CPU instruction */
        !          3403:                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          3404:                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          3405:                        /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          3406:                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          3407:                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
        !          3408:                                CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          3409:                                do_specialties_interrupt(false);                /* test if there's an mfp/video interrupt and add non pending jitter */
        !          3410:                        }
        !          3411:                
        !          3412:                        if (regs.spcflags) {
        !          3413:                                if (do_specialties (cpu_cycles* 2 / CYCLE_UNIT))
        !          3414:                                        return;
        !          3415:                        }
        !          3416:        
        !          3417:                        /* Run DSP 56k code if necessary */
        !          3418:                        if (bDspEnabled) {
        !          3419:                                DSP_Run(cpu_cycles* 2 / CYCLE_UNIT);
        !          3420:                        }
        !          3421:                }
        !          3422:        
        !          3423: //     } CATCH (prb) {
        !          3424:        if (except != 0) {
        !          3425:                save_except = except;
        !          3426:                if (currprefs.mmu_model == 68060) {
        !          3427:                        regs.fault_pc = pc;
        !          3428:                        if (mmufixup[1].reg >= 0) {
        !          3429:                                m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
        !          3430:                                mmufixup[1].reg = -1;
        !          3431:                        }
        !          3432:                } else {
        !          3433:                        if (regs.wb3_status & 0x80) {
        !          3434:                                // movem to memory?
        !          3435:                                if ((opcode & 0xff80) == 0x4880) {
        !          3436:                                        regs.mmu_ssw |= MMU_SSW_CM;
        !          3437:                                        //write_log ("MMU_SSW_CM\n");
        !          3438:                                }
        !          3439:                        }
        !          3440:                }
        !          3441: 
        !          3442:                //opcodedebug (regs.fault_pc, opcode);
        !          3443: 
        !          3444:                if (mmufixup[0].reg >= 0) {
        !          3445:                        m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
        !          3446:                        mmufixup[0].reg = -1;
        !          3447:                }
        !          3448:                //activate_debugger ();
        !          3449: //             TRY (prb2) {
        !          3450:                        except = 0;
        !          3451:                        Exception (save_except, regs.fault_pc, true);
        !          3452: //             } CATCH (prb2) {
        !          3453:                if (except != 0) {
        !          3454:                        write_log ("MMU: double bus error, rebooting..\n");
        !          3455:                        regs.tcr = 0;
        !          3456:                        m68k_reset (0);
        !          3457:                        m68k_setpc (0xf80002);
        !          3458:                        mmu_reset ();
        !          3459:                        uae_reset (1);
        !          3460:                        return;
        !          3461:                }
        !          3462:                goto retry;
        !          3463:        }
        !          3464: 
        !          3465: }
        !          3466: 
        !          3467: /* "cycle exact" 68020/030  */
        !          3468: #define MAX68020CYCLES 4
        !          3469: static void m68k_run_2ce (void)
        !          3470: {
        !          3471:        struct regstruct *r = &regs;
        !          3472:        int tmpcycles = MAX68020CYCLES;
        !          3473: 
        !          3474:        ipl_fetch ();
        !          3475:        for (;;) {
        !          3476:                /*m68k_dumpstate(stderr, NULL);*/
        !          3477:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3478:                {
        !          3479:                        int FrameCycles, HblCounterVideo, LineCycles;
        !          3480:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3481:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3482:                        m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3483:                }
        !          3484: 
        !          3485:                uae_u32 opcode = x_prefetch (0);
        !          3486:                (*cpufunctbl[opcode])(opcode);
        !          3487:                if (r->ce020memcycles > 0) {
        !          3488:                        tmpcycles = CYCLE_UNIT * MAX68020CYCLES;
        !          3489:                        do_cycles_ce (r->ce020memcycles);
        !          3490:                        r->ce020memcycles = 0;
        !          3491:                }
        !          3492:                if (r->spcflags) {
        !          3493:                        if (do_specialties (0))
        !          3494:                                return;
        !          3495:                }
        !          3496:                tmpcycles -= cpucycleunit;
        !          3497:                if (tmpcycles <= 0) {
        !          3498:                        do_cycles_ce (1 * CYCLE_UNIT);
        !          3499:                        tmpcycles = CYCLE_UNIT * MAX68020CYCLES;;
        !          3500:                }
        !          3501:                regs.ipl = regs.ipl_pin;
        !          3502:        }
        !          3503: }
        !          3504: 
        !          3505: /* emulate simple prefetch  */
        !          3506: static void m68k_run_2p (void)
        !          3507: {
        !          3508:        uae_u32 prefetch, prefetch_pc;
        !          3509:        struct regstruct *r = &regs;
        !          3510: 
        !          3511:        prefetch_pc = m68k_getpc ();
        !          3512:        prefetch = get_longi (prefetch_pc);
        !          3513:        for (;;) {
        !          3514:                uae_u32 opcode;
        !          3515:                uae_u32 pc = m68k_getpc ();
        !          3516: 
        !          3517:                /*m68k_dumpstate(stderr, NULL);*/
        !          3518:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3519:                {
        !          3520:                        int FrameCycles, HblCounterVideo, LineCycles;
        !          3521:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3522:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3523:                        m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3524:                }
        !          3525: 
        !          3526: #if DEBUG_CD32CDTVIO
        !          3527:                out_cd32io (m68k_getpc ());
        !          3528: #endif
        !          3529: 
        !          3530:                do_cycles (cpu_cycles);
        !          3531: 
        !          3532:                if (pc == prefetch_pc)
        !          3533:                        opcode = prefetch >> 16;
        !          3534:                else if (pc == prefetch_pc + 2)
        !          3535:                        opcode = prefetch & 0xffff;
        !          3536:                else
        !          3537:                        opcode = get_wordi (pc);
        !          3538: 
        !          3539:                count_instr (opcode);
        !          3540: 
        !          3541:                prefetch_pc = m68k_getpc () + 2;
        !          3542:                prefetch = get_longi (prefetch_pc);
        !          3543:                cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3544:                cpu_cycles &= cycles_mask;
        !          3545:                cpu_cycles |= cycles_val;
        !          3546: 
        !          3547:                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
        !          3548: 
        !          3549:                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          3550:                        /* Add some extra cycles to simulate a wait state */
        !          3551:                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          3552:                        M68000_AddCycles(nWaitStateCycles);
        !          3553:                        nWaitStateCycles = 0;
        !          3554:                }
        !          3555:                
        !          3556:                /* We can have several interrupts at the same time before the next CPU instruction */
        !          3557:                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          3558:                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          3559:                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          3560:                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          3561:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
        !          3562:                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          3563:                        do_specialties_interrupt(false);                /* test if there's an mfp/video interrupt and add non pending jitter */
        !          3564:                }
        !          3565:                
        !          3566:                if (r->spcflags) {
        !          3567:                        if (do_specialties (cpu_cycles* 2 / CYCLE_UNIT))
        !          3568:                                return;
        !          3569:                }
        !          3570:        
        !          3571:                /* Run DSP 56k code if necessary */
        !          3572:                if (bDspEnabled) {
        !          3573:                        DSP_Run(cpu_cycles* 2 / CYCLE_UNIT);
        !          3574:                }
        !          3575:        }
        !          3576: }
        !          3577: 
        !          3578: 
        !          3579: //static int used[65536];
        !          3580: 
        !          3581: /* Same thing, but don't use prefetch to get opcode.  */
        !          3582: static void m68k_run_2 (void)
        !          3583: {
        !          3584:        struct regstruct *r = &regs;
        !          3585: 
        !          3586:        for (;;) {
        !          3587:                uae_u32 opcode = get_iword (0);
        !          3588:                count_instr (opcode);
        !          3589: 
        !          3590:                /*m68k_dumpstate(stderr, NULL);*/
        !          3591:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3592:                {
        !          3593:                        int FrameCycles, HblCounterVideo, LineCycles;
        !          3594:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3595:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3596:                        m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3597:                }
        !          3598: 
        !          3599: #if 0
        !          3600:                if (!used[opcode]) {
        !          3601:                        write_log ("%04X ", opcode);
        !          3602:                        used[opcode] = 1;
        !          3603:                }
        !          3604: #endif 
        !          3605:                do_cycles (cpu_cycles);
        !          3606:                cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3607:                cpu_cycles &= cycles_mask;
        !          3608:                cpu_cycles |= cycles_val;
        !          3609: 
        !          3610:                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
        !          3611: 
        !          3612:                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          3613:                        /* Add some extra cycles to simulate a wait state */
        !          3614:                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          3615:                        M68000_AddCycles(nWaitStateCycles);
        !          3616:                        nWaitStateCycles = 0;
        !          3617:                }
        !          3618: 
        !          3619:                /* We can have several interrupts at the same time before the next CPU instruction */
        !          3620:                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          3621:                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          3622:                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          3623:                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          3624:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
        !          3625:                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          3626:                        do_specialties_interrupt(false);                /* test if there's an mfp/video interrupt and add non pending jitter */
        !          3627:                }
        !          3628:                
        !          3629:                
        !          3630:                if (r->spcflags) {
        !          3631:                        if (do_specialties (cpu_cycles* 2 / CYCLE_UNIT))
        !          3632:                                return;   
        !          3633:                }
        !          3634:                
        !          3635:                /* Run DSP 56k code if necessary */
        !          3636:                if (bDspEnabled) {
        !          3637:                        DSP_Run(cpu_cycles* 2 / CYCLE_UNIT);    
        !          3638:                }
        !          3639:        }
        !          3640: }
        !          3641: 
        !          3642: 
        !          3643: /* fake MMU 68k  */
        !          3644: static void m68k_run_mmu (void)
        !          3645: {
        !          3646:        for (;;) {
        !          3647: 
        !          3648:                /*m68k_dumpstate(stderr, NULL);*/
        !          3649:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          3650:                {
        !          3651:                        int FrameCycles, HblCounterVideo, LineCycles;
        !          3652:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          3653:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          3654:                        m68k_disasm(stderr, m68k_getpc (), NULL, 1);
        !          3655:                }
        !          3656: 
        !          3657:                uae_u32 opcode = get_iword (0);
        !          3658:                do_cycles (cpu_cycles);
        !          3659:                mmu_backup_regs = regs;
        !          3660:                cpu_cycles = (*cpufunctbl[opcode])(opcode);
        !          3661:                cpu_cycles &= cycles_mask;
        !          3662:                cpu_cycles |= cycles_val;
        !          3663:                if (mmu_triggered)
        !          3664:                        mmu_do_hit ();
        !          3665:                if (regs.spcflags) {
        !          3666:                        if (do_specialties (cpu_cycles))
        !          3667:                                return;
        !          3668:                }
        !          3669:        }
        !          3670: }
        !          3671: 
        !          3672: #endif /* CPUEMU_0 */
        !          3673: 
        !          3674: int in_m68k_go = 0;
        !          3675: 
        !          3676: static void exception2_handle (uaecptr addr, uaecptr fault)
        !          3677: {
        !          3678:        last_addr_for_exception_3 = addr;
        !          3679:        last_fault_for_exception_3 = fault;
        !          3680:        last_writeaccess_for_exception_3 = 0;
        !          3681:        last_instructionaccess_for_exception_3 = 0;
        !          3682:        Exception (2, m68k_getpc (), true);
        !          3683: }
        !          3684: 
        !          3685: void m68k_go (int may_quit)
        !          3686: {
        !          3687:        int hardboot = 1;
        !          3688: 
        !          3689:        if (in_m68k_go || !may_quit) {
        !          3690:                write_log ("Bug! m68k_go is not reentrant.\n");
        !          3691:                abort ();
        !          3692:        }
        !          3693: 
        !          3694:        reset_frame_rate_hack ();
        !          3695:        update_68k_cycles ();
        !          3696: 
        !          3697:        in_m68k_go++;
        !          3698:        for (;;) {
        !          3699:                void (*run_func)(void);
        !          3700:                
        !          3701:                if (regs.spcflags & SPCFLAG_BRK) {
        !          3702:                        unset_special(SPCFLAG_BRK);
        !          3703:                        break;
        !          3704:                }
        !          3705: 
        !          3706:                quit_program = 0;
        !          3707:                hardboot = 0;
        !          3708: 
        !          3709: #ifdef DEBUGGER
        !          3710:                if (debugging)
        !          3711:                        debug ();
        !          3712: #endif
        !          3713:                if (regs.panic) {
        !          3714:                        regs.panic = 0;
        !          3715:                        /* program jumped to non-existing memory and cpu was >= 68020 */
        !          3716:                        get_real_address (regs.isp); /* stack in no one's land? -> reboot */
        !          3717:                        if (regs.isp & 1)
        !          3718:                                regs.panic = 1;
        !          3719:                        if (!regs.panic)
        !          3720:                                exception2_handle (regs.panic_pc, regs.panic_addr);
        !          3721:                        if (regs.panic) {
        !          3722:                                /* system is very badly confused */
        !          3723:                                write_log ("double bus error or corrupted stack, forcing reboot..\n");
        !          3724:                                regs.panic = 0;
        !          3725:                                uae_reset (1);
        !          3726:                        }
        !          3727:                }
        !          3728: 
        !          3729: #if 0 /* what was the meaning of this? this breaks trace emulation if debugger is used */
        !          3730:                if (regs.spcflags) {
        !          3731:                        uae_u32 of = regs.spcflags;
        !          3732:                        regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
        !          3733:                        do_specialties (0);
        !          3734:                        regs.spcflags |= of & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
        !          3735:                }
        !          3736: #endif
        !          3737: 
        !          3738:                set_x_funcs ();
        !          3739:                if (mmu_enabled && !currprefs.cachesize) {
        !          3740:                        run_func = m68k_run_mmu;
        !          3741:                } else {
        !          3742:                        run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000 ? m68k_run_1_ce :
        !          3743:                                currprefs.cpu_compatible && currprefs.cpu_model == 68000 ? m68k_run_1 :
        !          3744: #ifdef JIT
        !          3745:                                currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
        !          3746: #endif
        !          3747:                                (currprefs.cpu_model == 68040 || currprefs.cpu_model == 68060) && currprefs.mmu_model ? m68k_run_mmu040 :
        !          3748:                                currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
        !          3749:                                currprefs.cpu_compatible ? m68k_run_2p : m68k_run_2;
        !          3750:                }
        !          3751:                run_func ();
        !          3752:        }
        !          3753:        in_m68k_go--;
        !          3754: }
        !          3755: 
        !          3756: #if 0
        !          3757: static void m68k_verify (uaecptr addr, uaecptr *nextpc)
        !          3758: {
        !          3759:        uae_u32 opcode, val;
        !          3760:        struct instr *dp;
        !          3761: 
        !          3762:        opcode = get_iword_1 (0);
        !          3763:        last_op_for_exception_3 = opcode;
        !          3764:        m68kpc_offset = 2;
        !          3765: 
        !          3766:        if (cpufunctbl[opcode] == op_illg_1) {
        !          3767:                opcode = 0x4AFC;
        !          3768:        }
        !          3769:        dp = table68k + opcode;
        !          3770: 
        !          3771:        if (dp->suse) {
        !          3772:                if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
        !          3773:                        Exception (3, 0);
        !          3774:                        return;
        !          3775:                }
        !          3776:        }
        !          3777:        if (dp->duse) {
        !          3778:                if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
        !          3779:                        Exception (3, 0);
        !          3780:                        return;
        !          3781:                }
        !          3782:        }
        !          3783: }
        !          3784: #endif
        !          3785: 
        !          3786: static const TCHAR *ccnames[] =
        !          3787: { "T ","F ","HI","LS","CC","CS","NE","EQ",
        !          3788: "VC","VS","PL","MI","GE","LT","GT","LE" };
        !          3789: 
        !          3790: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg)
        !          3791: {
        !          3792:        TCHAR *p = out + _tcslen (out);
        !          3793:        if (*prevreg < 0) {
        !          3794:                *prevreg = reg;
        !          3795:                *lastreg = reg;
        !          3796:                return;
        !          3797:        }
        !          3798:        if ((*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
        !          3799:                _stprintf (p, "%s%c%d", (*first) ? "" : "/", (*lastreg) < 8 ? 'D' : 'A', (*lastreg) & 7);
        !          3800:                p = p + _tcslen (p);
        !          3801:                if ((*lastreg) + 2 == reg) {
        !          3802:                        _stprintf (p, "/%c%d", (*prevreg) < 8 ? 'D' : 'A', (*prevreg) & 7);
        !          3803:                } else if ((*lastreg) != (*prevreg)) {
        !          3804:                        _stprintf (p, "-%c%d", (*prevreg) < 8 ? 'D' : 'A', (*prevreg) & 7);
        !          3805:                }
        !          3806:                *lastreg = reg;
        !          3807:                *first = 0;
        !          3808:        }
        !          3809:        *prevreg = reg;
        !          3810: }
        !          3811: 
        !          3812: static void movemout (TCHAR *out, uae_u16 mask, int mode)
        !          3813: {
        !          3814:        unsigned int dmask, amask;
        !          3815:        int prevreg = -1, lastreg = -1, first = 1;
        !          3816: 
        !          3817:        if (mode == Apdi) {
        !          3818:                int i;
        !          3819:                uae_u8 dmask2 = (mask >> 8) & 0xff;
        !          3820:                uae_u8 amask2 = mask & 0xff;
        !          3821:                dmask = 0;
        !          3822:                amask = 0;
        !          3823:                for (i = 0; i < 8; i++) {
        !          3824:                        if (dmask2 & (1 << i))
        !          3825:                                dmask |= 1 << (7 - i);
        !          3826:                        if (amask2 & (1 << i))
        !          3827:                                amask |= 1 << (7 - i);
        !          3828:                }
        !          3829:        } else {
        !          3830:                dmask = mask & 0xff;
        !          3831:                amask = (mask >> 8) & 0xff;
        !          3832:        }
        !          3833:        while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask]); dmask = movem_next[dmask]; }
        !          3834:        while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8); amask = movem_next[amask]; }
        !          3835:        addmovemreg (out, &prevreg, &lastreg, &first, -1);
        !          3836: }
        !          3837: 
        !          3838: static void disasm_size (TCHAR *instrname, struct instr *dp)
        !          3839: {
        !          3840: #if 0
        !          3841:        int i, size;
        !          3842:        uae_u16 mnemo = dp->mnemo;
        !          3843: 
        !          3844:        size = dp->size;
        !          3845:        for (i = 0; i < 65536; i++) {
        !          3846:                struct instr *in = &table68k[i];
        !          3847:                if (in->mnemo == mnemo && in != dp) {
        !          3848:                        if (size != in->size)
        !          3849:                                break;
        !          3850:                }
        !          3851:        }
        !          3852:        if (i == 65536)
        !          3853:                size = -1;
        !          3854: #endif
        !          3855:        switch (dp->size)
        !          3856:        {
        !          3857:        case sz_byte:
        !          3858:                _tcscat (instrname, ".B ");
        !          3859:                break;
        !          3860:        case sz_word:
        !          3861:                _tcscat (instrname, ".W ");
        !          3862:                break;
        !          3863:        case sz_long:
        !          3864:                _tcscat (instrname, ".L ");
        !          3865:                break;
        !          3866:        default:
        !          3867:                _tcscat (instrname, "   ");
        !          3868:                break;
        !          3869:        }
        !          3870: }
        !          3871: 
        !          3872: static void m68k_disasm_2 (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
        !          3873: {
        !          3874:        uaecptr newpc = 0;
        !          3875:        m68kpc_offset = addr - m68k_getpc ();
        !          3876: 
        !          3877:        if (!table68k)
        !          3878:                return;
        !          3879:        while (cnt-- > 0) {
        !          3880:                TCHAR instrname[100], *ccpt;
        !          3881:                int i;
        !          3882:                uae_u32 opcode;
        !          3883:                struct mnemolookup *lookup;
        !          3884:                struct instr *dp;
        !          3885:                int oldpc;
        !          3886: 
        !          3887:                oldpc = m68kpc_offset;
        !          3888:                opcode = get_iword_1 (m68kpc_offset);
        !          3889:                if (cpufunctbl[opcode] == op_illg_1) {
        !          3890:                        opcode = 0x4AFC;
        !          3891:                }
        !          3892:                dp = table68k + opcode;
        !          3893:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
        !          3894:                        ;
        !          3895: 
        !          3896:                fprintf(f, "%08lX ", m68k_getpc () + m68kpc_offset);
        !          3897:                m68kpc_offset += 2;
        !          3898: 
        !          3899:                if (strcmp(lookup->friendlyname, ""))
        !          3900:                        _tcscpy (instrname, lookup->friendlyname);
        !          3901:                else
        !          3902:                        _tcscpy (instrname, lookup->name);
        !          3903:                ccpt = _tcsstr (instrname, "cc");
        !          3904:                if (ccpt != 0) {
        !          3905:                        _tcsncpy (ccpt, ccnames[dp->cc], 2);
        !          3906:                }
        !          3907:                disasm_size (instrname, dp);
        !          3908: 
        !          3909:                if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
        !          3910:                        uae_u16 imm = get_iword_1 (m68kpc_offset);
        !          3911:                        uae_u16 creg = imm & 0x0fff;
        !          3912:                        uae_u16 r = imm >> 12;
        !          3913:                        TCHAR regs[16];
        !          3914:                        const TCHAR *cname = "?";
        !          3915:                        int i;
        !          3916:                        for (i = 0; m2cregs[i].regname; i++) {
        !          3917:                                if (m2cregs[i].regno == creg)
        !          3918:                                        break;
        !          3919:                        }
        !          3920:                        _stprintf (regs, "%c%d", r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
        !          3921:                        if (m2cregs[i].regname)
        !          3922:                                cname = m2cregs[i].regname;
        !          3923:                        if (lookup->mnemo == i_MOVE2C) {
        !          3924:                                _tcscat (instrname, regs);
        !          3925:                                _tcscat (instrname, ",");
        !          3926:                                _tcscat (instrname, cname);
        !          3927:                        } else {
        !          3928:                                _tcscat (instrname, cname);
        !          3929:                                _tcscat (instrname, ",");
        !          3930:                                _tcscat (instrname, regs);
        !          3931:                        }
        !          3932:                        m68kpc_offset += 2;
        !          3933:                } else if (lookup->mnemo == i_MVMEL) {
        !          3934:                        newpc = m68k_getpc () + m68kpc_offset;
        !          3935:                        m68kpc_offset += 2;
        !          3936:                        newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          3937:                        _tcscat (instrname, ",");
        !          3938:                        movemout (instrname, get_iword_1 (oldpc + 2), dp->dmode);
        !          3939:                } else if (lookup->mnemo == i_MVMLE) {
        !          3940:                        m68kpc_offset += 2;
        !          3941:                        movemout (instrname, get_iword_1 (oldpc + 2), dp->dmode);
        !          3942:                        _tcscat (instrname, ",");
        !          3943:                        newpc = m68k_getpc () + m68kpc_offset;
        !          3944:                        newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          3945:                } else {
        !          3946:                        if (dp->suse) {
        !          3947:                                newpc = m68k_getpc () + m68kpc_offset;
        !          3948:                                newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr, safemode);
        !          3949:                        }
        !          3950:                        if (dp->suse && dp->duse)
        !          3951:                                _tcscat (instrname, ",");
        !          3952:                        if (dp->duse) {
        !          3953:                                newpc = m68k_getpc () + m68kpc_offset;
        !          3954:                                newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          3955:                        }
        !          3956:                }
        !          3957: 
        !          3958:                for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++) {
        !          3959:                        fprintf(f, "%04x ", get_iword_1 (oldpc + i * 2));
        !          3960:                }
        !          3961: 
        !          3962:                while (i++ < 5)
        !          3963:                        fprintf(f, "%s", "     ");
        !          3964: 
        !          3965:                fprintf(f, "%s", instrname);
        !          3966: 
        !          3967:                if (ccpt != 0) {
        !          3968:                        if (deaddr)
        !          3969:                                *deaddr = newpc;
        !          3970:                        if (cctrue (dp->cc))
        !          3971:                                fprintf(f, " == $%08X (T)", newpc);
        !          3972:                        else
        !          3973:                                fprintf(f, " == $%08X (F)", newpc);
        !          3974:                } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
        !          3975:                        if (deaddr)
        !          3976:                                *deaddr = newpc;
        !          3977:                        fprintf(f, " == $%08X", newpc);
        !          3978:                }
        !          3979:                fprintf(f, "%s", "\n");
        !          3980:        }
        !          3981:        if (nextpc)
        !          3982:                *nextpc = m68k_getpc () + m68kpc_offset;
        !          3983: }
        !          3984: 
        !          3985: void m68k_disasm_ea (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
        !          3986: {
        !          3987:        m68k_disasm_2 (f, addr, nextpc, cnt, seaddr, deaddr, 1);
        !          3988: }
        !          3989: void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
        !          3990: {
        !          3991:        m68k_disasm_2 (f, addr, nextpc, cnt, NULL, NULL, 0);
        !          3992: }
        !          3993: 
        !          3994: /*************************************************************
        !          3995: Disasm the m68kcode at the given address into instrname
        !          3996: and instrcode
        !          3997: *************************************************************/
        !          3998: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
        !          3999: {
        !          4000:        TCHAR *ccpt;
        !          4001:        uae_u32 opcode;
        !          4002:        struct mnemolookup *lookup;
        !          4003:        struct instr *dp;
        !          4004:        int oldpc;
        !          4005: 
        !          4006:        uaecptr newpc = 0;
        !          4007: 
        !          4008:        m68kpc_offset = addr - m68k_getpc ();
        !          4009: 
        !          4010:        oldpc = m68kpc_offset;
        !          4011:        opcode = get_iword_1 (m68kpc_offset);
        !          4012:        if (cpufunctbl[opcode] == op_illg_1) {
        !          4013:                opcode = 0x4AFC;
        !          4014:        }
        !          4015:        dp = table68k + opcode;
        !          4016:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
        !          4017: 
        !          4018:        m68kpc_offset += 2;
        !          4019: 
        !          4020:        _tcscpy (instrname, lookup->name);
        !          4021:        ccpt = _tcsstr (instrname, "cc");
        !          4022:        if (ccpt != 0) {
        !          4023:                _tcsncpy (ccpt, ccnames[dp->cc], 2);
        !          4024:        }
        !          4025:        switch (dp->size){
        !          4026:        case sz_byte: _tcscat (instrname, ".B "); break;
        !          4027:        case sz_word: _tcscat (instrname, ".W "); break;
        !          4028:        case sz_long: _tcscat (instrname, ".L "); break;
        !          4029:        default: _tcscat (instrname, "   "); break;
        !          4030:        }
        !          4031: 
        !          4032:        if (dp->suse) {
        !          4033:                newpc = m68k_getpc () + m68kpc_offset;
        !          4034:                newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
        !          4035:        }
        !          4036:        if (dp->suse && dp->duse)
        !          4037:                _tcscat (instrname, ",");
        !          4038:        if (dp->duse) {
        !          4039:                newpc = m68k_getpc () + m68kpc_offset;
        !          4040:                newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
        !          4041:        }
        !          4042: 
        !          4043:        if (instrcode)
        !          4044:        {
        !          4045:                int i;
        !          4046:                for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++)
        !          4047:                {
        !          4048:                        _stprintf (instrcode, "%04x ", get_iword_1 (oldpc + i * 2));
        !          4049:                        instrcode += _tcslen (instrcode);
        !          4050:                }
        !          4051:        }
        !          4052: 
        !          4053:        if (nextpc)
        !          4054:                *nextpc = m68k_getpc () + m68kpc_offset;
        !          4055: }
        !          4056: 
        !          4057: struct cpum2c m2cregs[] = {
        !          4058:        { 0, "SFC" },
        !          4059:        { 1, "DFC" },
        !          4060:        { 2, "CACR" },
        !          4061:        { 3, "TC" },
        !          4062:        { 4, "ITT0" },
        !          4063:        { 5, "ITT1" },
        !          4064:        { 6, "DTT0" },
        !          4065:        { 7, "DTT1" },
        !          4066:        { 8, "BUSC" },
        !          4067:        { 0x800, "USP" },
        !          4068:        { 0x801, "VBR" },
        !          4069:        { 0x802, "CAAR" },
        !          4070:        { 0x803, "MSP" },
        !          4071:        { 0x804, "ISP" },
        !          4072:        { 0x805, "MMUS" },
        !          4073:        { 0x806, "URP" },
        !          4074:        { 0x807, "SRP" },
        !          4075:        { 0x808, "PCR" },
        !          4076:        { -1, NULL }
        !          4077: };
        !          4078: 
        !          4079: void val_move2c2 (int regno, uae_u32 val)
        !          4080: {
        !          4081:        switch (regno) {
        !          4082:        case 0: regs.sfc = val; break;
        !          4083:        case 1: regs.dfc = val; break;
        !          4084:        case 2: regs.cacr = val; break;
        !          4085:        case 3: regs.tcr = val; break;
        !          4086:        case 4: regs.itt0 = val; break;
        !          4087:        case 5: regs.itt1 = val; break;
        !          4088:        case 6: regs.dtt0 = val; break;
        !          4089:        case 7: regs.dtt1 = val; break;
        !          4090:        case 8: regs.buscr = val; break;
        !          4091:        case 0x800: regs.usp = val; break;
        !          4092:        case 0x801: regs.vbr = val; break;
        !          4093:        case 0x802: regs.caar = val; break;
        !          4094:        case 0x803: regs.msp = val; break;
        !          4095:        case 0x804: regs.isp = val; break;
        !          4096:        case 0x805: regs.mmusr = val; break;
        !          4097:        case 0x806: regs.urp = val; break;
        !          4098:        case 0x807: regs.srp = val; break;
        !          4099:        case 0x808: regs.pcr = val; break;
        !          4100:        }
        !          4101: }
        !          4102: 
        !          4103: uae_u32 val_move2c (int regno)
        !          4104: {
        !          4105:        switch (regno) {
        !          4106:        case 0: return regs.sfc;
        !          4107:        case 1: return regs.dfc;
        !          4108:        case 2: return regs.cacr;
        !          4109:        case 3: return regs.tcr;
        !          4110:        case 4: return regs.itt0;
        !          4111:        case 5: return regs.itt1;
        !          4112:        case 6: return regs.dtt0;
        !          4113:        case 7: return regs.dtt1;
        !          4114:        case 8: return regs.buscr;
        !          4115:        case 0x800: return regs.usp;
        !          4116:        case 0x801: return regs.vbr;
        !          4117:        case 0x802: return regs.caar;
        !          4118:        case 0x803: return regs.msp;
        !          4119:        case 0x804: return regs.isp;
        !          4120:        case 0x805: return regs.mmusr;
        !          4121:        case 0x806: return regs.urp;
        !          4122:        case 0x807: return regs.srp;
        !          4123:        case 0x808: return regs.pcr;
        !          4124:        default: return 0;
        !          4125:        }
        !          4126: }
        !          4127: 
        !          4128: void m68k_dumpstate (FILE *f, uaecptr *nextpc)
        !          4129: {
        !          4130:        int i, j;
        !          4131: 
        !          4132:        for (i = 0; i < 8; i++){
        !          4133:                f_out (f, "  D%d %08lX ", i, m68k_dreg (regs, i));
        !          4134:                if ((i & 3) == 3) f_out (f, "\n");
        !          4135:        }
        !          4136:        for (i = 0; i < 8; i++){
        !          4137:                f_out (f, "  A%d %08lX ", i, m68k_areg (regs, i));
        !          4138:                if ((i & 3) == 3) f_out (f, "\n");
        !          4139:        }
        !          4140:        if (regs.s == 0)
        !          4141:                regs.usp = m68k_areg (regs, 7);
        !          4142:        if (regs.s && regs.m)
        !          4143:                regs.msp = m68k_areg (regs, 7);
        !          4144:        if (regs.s && regs.m == 0)
        !          4145:                regs.isp = m68k_areg (regs, 7);
        !          4146:        j = 2;
        !          4147:        f_out (f, "USP  %08X ISP  %08X ", regs.usp, regs.isp);
        !          4148:        for (i = 0; m2cregs[i].regno>= 0; i++) {
        !          4149:                if (!movec_illg (m2cregs[i].regno)) {
        !          4150:                        if (!_tcscmp (m2cregs[i].regname, "USP") || !_tcscmp (m2cregs[i].regname, "ISP"))
        !          4151:                                continue;
        !          4152:                        if (j > 0 && (j % 4) == 0)
        !          4153:                                f_out (f, "\n");
        !          4154:                        f_out (f, "%-4s %08X ", m2cregs[i].regname, val_move2c (m2cregs[i].regno));
        !          4155:                        j++;
        !          4156:                }
        !          4157:        }
        !          4158:        if (j > 0)
        !          4159:                f_out (f, "\n");
        !          4160:        f_out (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n",
        !          4161:                regs.t1, regs.t0, regs.s, regs.m,
        !          4162:                GET_XFLG (), GET_NFLG (), GET_ZFLG (),
        !          4163:                GET_VFLG (), GET_CFLG (),
        !          4164:                regs.intmask, regs.stopped);
        !          4165: #ifdef FPUEMU
        !          4166:        if (currprefs.fpu_model) {
        !          4167:                uae_u32 fpsr;
        !          4168:                for (i = 0; i < 8; i++){
        !          4169:                        f_out (f, "FP%d: %g ", i, regs.fp[i]);
        !          4170:                        if ((i & 3) == 3)
        !          4171:                                f_out (f, "\n");
        !          4172:                }
        !          4173:                fpsr = get_fpsr ();
        !          4174:                f_out (f, "N=%d Z=%d I=%d NAN=%d\n",
        !          4175:                        (fpsr & 0x8000000) != 0,
        !          4176:                        (fpsr & 0x4000000) != 0,
        !          4177:                        (fpsr & 0x2000000) != 0,
        !          4178:                        (fpsr & 0x1000000) != 0);
        !          4179:        }
        !          4180: #endif
        !          4181:        if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
        !          4182:                struct instr *dp;
        !          4183:                struct mnemolookup *lookup1, *lookup2;
        !          4184:                dp = table68k + regs.irc;
        !          4185:                for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
        !          4186:                dp = table68k + regs.ir;
        !          4187:                for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
        !          4188:                f_out (f, "Prefetch %04x (%s) %04x (%s)\n", regs.irc, lookup1->name, regs.ir, lookup2->name);
        !          4189:        }
        !          4190: 
        !          4191:        m68k_disasm (f, m68k_getpc (), nextpc, 1);
        !          4192:        if (nextpc)
        !          4193:                f_out (f, "Next PC: %08lx\n", *nextpc);
        !          4194: }
        !          4195: 
        !          4196: #ifdef SAVESTATE
        !          4197: 
        !          4198: /* CPU save/restore code */
        !          4199: 
        !          4200: #define CPUTYPE_EC 1
        !          4201: #define CPUMODE_HALT 1
        !          4202: 
        !          4203: 
        !          4204: 
        !          4205: uae_u8 *restore_cpu (uae_u8 *src)
        !          4206: {
        !          4207:        int i, flags, model;
        !          4208:        uae_u32 l;
        !          4209: 
        !          4210:        changed_prefs.cpu_model = model = restore_u32 ();
        !          4211:        flags = restore_u32 ();
        !          4212:        changed_prefs.address_space_24 = 0;
        !          4213:        if (flags & CPUTYPE_EC)
        !          4214:                changed_prefs.address_space_24 = 1;
        !          4215:        if (model > 68020)
        !          4216:                changed_prefs.cpu_compatible = 0;
        !          4217:        currprefs.address_space_24 = changed_prefs.address_space_24;
        !          4218:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
        !          4219:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
        !          4220:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
        !          4221:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
        !          4222:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
        !          4223:        for (i = 0; i < 15; i++)
        !          4224:                regs.regs[i] = restore_u32 ();
        !          4225:        regs.pc = restore_u32 ();
        !          4226:        regs.irc = restore_u16 ();
        !          4227:        regs.ir = restore_u16 ();
        !          4228:        regs.usp = restore_u32 ();
        !          4229:        regs.isp = restore_u32 ();
        !          4230:        regs.sr = restore_u16 ();
        !          4231:        l = restore_u32 ();
        !          4232:        if (l & CPUMODE_HALT) {
        !          4233:                regs.stopped = 1;
        !          4234:        } else {
        !          4235:                regs.stopped = 0;
        !          4236:        }
        !          4237:        if (model >= 68010) {
        !          4238:                regs.dfc = restore_u32 ();
        !          4239:                regs.sfc = restore_u32 ();
        !          4240:                regs.vbr = restore_u32 ();
        !          4241:        }
        !          4242:        if (model >= 68020) {
        !          4243:                regs.caar = restore_u32 ();
        !          4244:                regs.cacr = restore_u32 ();
        !          4245:                regs.msp = restore_u32 ();
        !          4246:                /* A500 speed in 68020 mode isn't too logical.. */
        !          4247:                if (changed_prefs.m68k_speed == 0 && !(currprefs.cpu_cycle_exact))
        !          4248:                        currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
        !          4249:        }
        !          4250:        if (model >= 68030) {
        !          4251:                crp_030 = restore_u64 ();
        !          4252:                srp_030 = restore_u64 ();
        !          4253:                tt0_030 =restore_u32 ();
        !          4254:                tt1_030 = restore_u32 ();
        !          4255:                tc_030 = restore_u32 ();
        !          4256:                mmusr_030 = restore_u16 ();
        !          4257:        }
        !          4258:        if (model >= 68040) {
        !          4259:                regs.itt0 = restore_u32 ();
        !          4260:                regs.itt1 = restore_u32 ();
        !          4261:                regs.dtt0 = restore_u32 ();
        !          4262:                regs.dtt1 = restore_u32 ();
        !          4263:                regs.tcr = restore_u32 ();
        !          4264:                regs.urp = restore_u32 ();
        !          4265:                regs.srp = restore_u32 ();
        !          4266:        }
        !          4267:        if (model >= 68060) {
        !          4268:                regs.buscr = restore_u32 ();
        !          4269:                regs.pcr = restore_u32 ();
        !          4270:        }
        !          4271:        if (flags & 0x80000000) {
        !          4272:                int khz = restore_u32 ();
        !          4273:                restore_u32 ();
        !          4274:                if (khz > 0 && khz < 800000)
        !          4275:                        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
        !          4276:        }
        !          4277:        write_log ("CPU: %d%s%03d, PC=%08X\n",
        !          4278:                model / 1000, flags & 1 ? "EC" : "", model % 1000, regs.pc);
        !          4279: 
        !          4280:        return src;
        !          4281: }
        !          4282: 
        !          4283: void restore_cpu_finish (void)
        !          4284: {
        !          4285:        init_m68k ();
        !          4286:        m68k_setpc (regs.pc);
        !          4287:        set_cpu_caches ();
        !          4288:        doint ();
        !          4289:        if (regs.stopped)
        !          4290:                set_special (SPCFLAG_STOP);
        !          4291:        //activate_debugger ();
        !          4292: }
        !          4293: 
        !          4294: uae_u8 *restore_cpu_extra (uae_u8 *src)
        !          4295: {
        !          4296:        restore_u32 ();
        !          4297:        uae_u32 flags = restore_u32 ();
        !          4298: 
        !          4299: 
        !          4300:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
        !          4301:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
        !          4302:        currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
        !          4303:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
        !          4304:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
        !          4305:        currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
        !          4306: 
        !          4307:        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
        !          4308:        if (flags & 4)
        !          4309:                currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
        !          4310: 
        !          4311:        currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
        !          4312:        currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
        !          4313: 
        !          4314:        return src;
        !          4315: }
        !          4316: 
        !          4317: uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
        !          4318: {
        !          4319:        uae_u8 *dstbak, *dst;
        !          4320:        uae_u32 flags;
        !          4321: 
        !          4322:        if (dstptr)
        !          4323:                dstbak = dst = dstptr;
        !          4324:        else
        !          4325:                dstbak = dst = xmalloc (uae_u8, 1000);
        !          4326:        save_u32 (0); // version
        !          4327:        flags = 0;
        !          4328:        flags |= currprefs.cpu_cycle_exact ? 1 : 0;
        !          4329:        flags |= currprefs.cpu_compatible ? 2 : 0;
        !          4330:        flags |= currprefs.m68k_speed < 0 ? 4 : 0;
        !          4331:        flags |= currprefs.cachesize > 0 ? 8 : 0;
        !          4332:        save_u32 (flags);
        !          4333:        save_u32 (currprefs.cpu_frequency);
        !          4334:        save_u32 (currprefs.cpu_clock_multiplier);
        !          4335:        save_u8 (currprefs.cpu060_revision);
        !          4336:        save_u8 (currprefs.fpu_revision);
        !          4337:        *len = dst - dstbak;
        !          4338:        return dstbak;
        !          4339: }
        !          4340: 
        !          4341: uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
        !          4342: {
        !          4343:        uae_u8 *dstbak, *dst;
        !          4344:        int model, i, khz;
        !          4345: 
        !          4346:        if (dstptr)
        !          4347:                dstbak = dst = dstptr;
        !          4348:        else
        !          4349:                dstbak = dst = xmalloc (uae_u8, 1000);
        !          4350:        model = currprefs.cpu_model;
        !          4351:        save_u32 (model);                                       /* MODEL */
        !          4352:        save_u32 (0x80000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
        !          4353:        for (i = 0;i < 15; i++)
        !          4354:                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
        !          4355:        save_u32 (m68k_getpc ());                       /* PC */
        !          4356:        save_u16 (regs.irc);                            /* prefetch */
        !          4357:        save_u16 (regs.ir);                                     /* instruction prefetch */
        !          4358:        MakeSR ();
        !          4359:        save_u32 (!regs.s ? regs.regs[15] : regs.usp);  /* USP */
        !          4360:        save_u32 (regs.s ? regs.regs[15] : regs.isp);   /* ISP */
        !          4361:        save_u16 (regs.sr);                                                             /* SR/CCR */
        !          4362:        save_u32 (regs.stopped ? CPUMODE_HALT : 0);             /* flags */
        !          4363:        if (model >= 68010) {
        !          4364:                save_u32 (regs.dfc);                    /* DFC */
        !          4365:                save_u32 (regs.sfc);                    /* SFC */
        !          4366:                save_u32 (regs.vbr);                    /* VBR */
        !          4367:        }
        !          4368:        if (model >= 68020) {
        !          4369:                save_u32 (regs.caar);                   /* CAAR */
        !          4370:                save_u32 (regs.cacr);                   /* CACR */
        !          4371:                save_u32 (regs.msp);                    /* MSP */
        !          4372:        }
        !          4373:        if (model >= 68030) {
        !          4374:                save_u64 (crp_030);                             /* CRP */
        !          4375:                save_u64 (srp_030);                             /* SRP */
        !          4376:                save_u32 (tt0_030);                             /* TT0/AC0 */
        !          4377:                save_u32 (tt1_030);                             /* TT1/AC1 */
        !          4378:                save_u32 (tc_030);                              /* TCR */
        !          4379:                save_u16 (mmusr_030);                   /* MMUSR/ACUSR */
        !          4380:        }
        !          4381:        if (model >= 68040) {
        !          4382:                save_u32 (regs.itt0);                   /* ITT0 */
        !          4383:                save_u32 (regs.itt1);                   /* ITT1 */
        !          4384:                save_u32 (regs.dtt0);                   /* DTT0 */
        !          4385:                save_u32 (regs.dtt1);                   /* DTT1 */
        !          4386:                save_u32 (regs.tcr);                    /* TCR */
        !          4387:                save_u32 (regs.urp);                    /* URP */
        !          4388:                save_u32 (regs.srp);                    /* SRP */
        !          4389:        }
        !          4390:        if (model >= 68060) {
        !          4391:                save_u32 (regs.buscr);                  /* BUSCR */
        !          4392:                save_u32 (regs.pcr);                    /* PCR */
        !          4393:        }
        !          4394:        khz = -1;
        !          4395:        if (currprefs.m68k_speed == 0) {
        !          4396:                khz = currprefs.ntscmode ? 715909 : 709379;
        !          4397:                if (currprefs.cpu_model >= 68020)
        !          4398:                        khz *= 2;
        !          4399:        }
        !          4400:        save_u32 (khz); // clock rate in KHz: -1 = fastest possible
        !          4401:        save_u32 (0); // spare
        !          4402:        *len = dst - dstbak;
        !          4403:        return dstbak;
        !          4404: }
        !          4405: 
        !          4406: uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
        !          4407: {
        !          4408:        uae_u8 *dstbak, *dst;
        !          4409:        int model;
        !          4410: 
        !          4411:        model = currprefs.mmu_model;
        !          4412:        if (model != 68040 && model != 68060)
        !          4413:                return NULL;
        !          4414:        if (dstptr)
        !          4415:                dstbak = dst = dstptr;
        !          4416:        else
        !          4417:                dstbak = dst = xmalloc (uae_u8, 1000);
        !          4418:        save_u32 (model);       /* MODEL */
        !          4419:        save_u32 (0);   /* FLAGS */
        !          4420:        *len = dst - dstbak;
        !          4421:        return dstbak;
        !          4422: }
        !          4423: 
        !          4424: uae_u8 *restore_mmu (uae_u8 *src)
        !          4425: {
        !          4426:        int flags, model;
        !          4427: 
        !          4428:        changed_prefs.mmu_model = model = restore_u32 ();
        !          4429:        flags = restore_u32 ();
        !          4430:        write_log ("MMU: %d\n", model);
        !          4431:        return src;
        !          4432: }
        !          4433: 
        !          4434: #endif /* SAVESTATE */
        !          4435: 
        !          4436: static void exception3f (uae_u32 opcode, uaecptr addr, uaecptr fault, int writeaccess, int instructionaccess)
        !          4437: {
        !          4438:        if (currprefs.cpu_model >= 68040)
        !          4439:                addr &= ~1;
        !          4440:        last_addr_for_exception_3 = addr;
        !          4441:        last_fault_for_exception_3 = fault;
        !          4442:        last_op_for_exception_3 = opcode;
        !          4443:        last_writeaccess_for_exception_3 = writeaccess;
        !          4444:        last_instructionaccess_for_exception_3 = instructionaccess;
        !          4445:        Exception (3, fault, true);
        !          4446: }
        !          4447: 
        !          4448: void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault)
        !          4449: {
        !          4450:        exception3f (opcode, addr, fault, 0, 0);
        !          4451: }
        !          4452: 
        !          4453: void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault)
        !          4454: {
        !          4455:        exception3f (opcode, addr, fault, 0, 1);
        !          4456: }
        !          4457: 
        !          4458: void exception2 (uaecptr addr, uaecptr fault)
        !          4459: {
        !          4460:        write_log ("delayed exception2!\n");
        !          4461:        regs.panic_pc = m68k_getpc ();
        !          4462:        regs.panic_addr = addr;
        !          4463:        regs.panic = 2;
        !          4464:        set_special (SPCFLAG_BRK);
        !          4465:        m68k_setpc (0xf80000);
        !          4466: #ifdef JIT
        !          4467:        set_special (SPCFLAG_END_COMPILE);
        !          4468: #endif
        !          4469:        fill_prefetch_slow ();
        !          4470: }
        !          4471: 
        !          4472: void cpureset (void)
        !          4473: {
        !          4474:        uaecptr pc;
        !          4475:        uaecptr ksboot = 0xf80002 - 2; /* -2 = RESET hasn't increased PC yet */
        !          4476:        uae_u16 ins;
        !          4477: 
        !          4478:        if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) {
        !          4479: //             customreset (0);
        !          4480:                customreset ();
        !          4481:                return;
        !          4482:        }
        !          4483:        pc = m68k_getpc ();
        !          4484:        if (pc >= currprefs.chipmem_size) {
        !          4485:                addrbank *b = &get_mem_bank (pc);
        !          4486:                if (b->check (pc, 2 + 2)) {
        !          4487:                        /* We have memory, hope for the best.. */
        !          4488: //                     customreset (0);
        !          4489:                        customreset ();
        !          4490:                        return;
        !          4491:                }
        !          4492:                write_log ("M68K RESET PC=%x, rebooting..\n", pc);
        !          4493: //             customreset (0);
        !          4494:                customreset ();
        !          4495:                m68k_setpc (ksboot);
        !          4496:                return;
        !          4497:        }
        !          4498:        /* panic, RAM is going to disappear under PC */
        !          4499:        ins = get_word (pc + 2);
        !          4500:        if ((ins & ~7) == 0x4ed0) {
        !          4501:                int reg = ins & 7;
        !          4502:                uae_u32 addr = m68k_areg (regs, reg);
        !          4503:                write_log ("reset/jmp (ax) combination emulated -> %x\n", addr);
        !          4504: //             customreset (0);
        !          4505:                customreset ();
        !          4506:                if (addr < 0x80000)
        !          4507:                        addr += 0xf80000;
        !          4508:                m68k_setpc (addr - 2);
        !          4509:                return;
        !          4510:        }
        !          4511:        write_log ("M68K RESET PC=%x, rebooting..\n", pc);
        !          4512: //     customreset (0);
        !          4513:        customreset ();
        !          4514:        m68k_setpc (ksboot);
        !          4515: }
        !          4516: 
        !          4517: 
        !          4518: void m68k_setstopped (void)
        !          4519: {
        !          4520:        regs.stopped = 1;
        !          4521:        /* A traced STOP instruction drops through immediately without
        !          4522:        actually stopping.  */
        !          4523:        if ((regs.spcflags & SPCFLAG_DOTRACE) == 0)
        !          4524:                set_special (SPCFLAG_STOP);
        !          4525:        else
        !          4526:                m68k_resumestopped ();
        !          4527: }
        !          4528: 
        !          4529: void m68k_resumestopped (void)
        !          4530: {
        !          4531:        if (!regs.stopped)
        !          4532:                return;
        !          4533:        regs.stopped = 0;
        !          4534:        if (currprefs.cpu_cycle_exact) {
        !          4535:                if (currprefs.cpu_model == 68000)
        !          4536:                        do_cycles_ce000 (6);
        !          4537:        }
        !          4538:        fill_prefetch_slow ();
        !          4539:        unset_special (SPCFLAG_STOP);
        !          4540: }
        !          4541: 
        !          4542: /*
        !          4543: * Compute exact number of CPU cycles taken
        !          4544: * by DIVU and DIVS on a 68000 processor.
        !          4545: *
        !          4546: * Copyright (c) 2005 by Jorge Cwik, [email protected]
        !          4547: *
        !          4548: * This is free software; you can redistribute it and/or modify
        !          4549: * it under the terms of the GNU General Public License as published by
        !          4550: * the Free Software Foundation; either version 2 of the License, or
        !          4551: * (at your option) any later version.
        !          4552: *
        !          4553: * This software is distributed in the hope that it will be useful,
        !          4554: * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !          4555: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !          4556: * GNU General Public License for more details.
        !          4557: *
        !          4558: * You should have received a copy of the GNU General Public License
        !          4559: * along with this software; if not, write to the Free Software
        !          4560: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !          4561: *
        !          4562: */
        !          4563: 
        !          4564: 
        !          4565: /*
        !          4566: 
        !          4567: The routines below take dividend and divisor as parameters.
        !          4568: They return 0 if division by zero, or exact number of cycles otherwise.
        !          4569: 
        !          4570: The number of cycles returned assumes a register operand.
        !          4571: Effective address time must be added if memory operand.
        !          4572: 
        !          4573: For 68000 only (not 68010, 68012, 68020, etc).
        !          4574: Probably valid for 68008 after adding the extra prefetch cycle.
        !          4575: 
        !          4576: 
        !          4577: Best and worst cases for register operand:
        !          4578: (Note the difference with the documented range.)
        !          4579: 
        !          4580: 
        !          4581: DIVU:
        !          4582: 
        !          4583: Overflow (always): 10 cycles.
        !          4584: Worst case: 136 cycles.
        !          4585: Best case: 76 cycles.
        !          4586: 
        !          4587: 
        !          4588: DIVS:
        !          4589: 
        !          4590: Absolute overflow: 16-18 cycles.
        !          4591: Signed overflow is not detected prematurely.
        !          4592: 
        !          4593: Worst case: 156 cycles.
        !          4594: Best case without signed overflow: 122 cycles.
        !          4595: Best case with signed overflow: 120 cycles
        !          4596: 
        !          4597: 
        !          4598: */
        !          4599: 
        !          4600: int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor)
        !          4601: {
        !          4602:        int mcycles;
        !          4603:        uae_u32 hdivisor;
        !          4604:        int i;
        !          4605: 
        !          4606:        if (divisor == 0)
        !          4607:                return 0;
        !          4608: 
        !          4609:        // Overflow
        !          4610:        if ((dividend >> 16) >= divisor)
        !          4611:                return (mcycles = 5) * 2;
        !          4612: 
        !          4613:        mcycles = 38;
        !          4614:        hdivisor = divisor << 16;
        !          4615: 
        !          4616:        for (i = 0; i < 15; i++) {
        !          4617:                uae_u32 temp;
        !          4618:                temp = dividend;
        !          4619: 
        !          4620:                dividend <<= 1;
        !          4621: 
        !          4622:                // If carry from shift
        !          4623:                if ((uae_s32)temp < 0)
        !          4624:                        dividend -= hdivisor;
        !          4625:                else {
        !          4626:                        mcycles += 2;
        !          4627:                        if (dividend >= hdivisor) {
        !          4628:                                dividend -= hdivisor;
        !          4629:                                mcycles--;
        !          4630:                        }
        !          4631:                }
        !          4632:        }
        !          4633:        return mcycles * 2;
        !          4634: }
        !          4635: 
        !          4636: int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
        !          4637: {
        !          4638:        int mcycles;
        !          4639:        uae_u32 aquot;
        !          4640:        int i;
        !          4641: 
        !          4642:        if (divisor == 0)
        !          4643:                return 0;
        !          4644: 
        !          4645:        mcycles = 6;
        !          4646: 
        !          4647:        if (dividend < 0)
        !          4648:                mcycles++;
        !          4649: 
        !          4650:        // Check for absolute overflow
        !          4651:        if (((uae_u32)abs (dividend) >> 16) >= (uae_u16)abs (divisor))
        !          4652:                return (mcycles + 2) * 2;
        !          4653: 
        !          4654:        // Absolute quotient
        !          4655:        aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor);
        !          4656: 
        !          4657:        mcycles += 55;
        !          4658: 
        !          4659:        if (divisor >= 0) {
        !          4660:                if (dividend >= 0)
        !          4661:                        mcycles--;
        !          4662:                else
        !          4663:                        mcycles++;
        !          4664:        }
        !          4665: 
        !          4666:        // Count 15 msbits in absolute of quotient
        !          4667: 
        !          4668:        for (i = 0; i < 15; i++) {
        !          4669:                if ((uae_s16)aquot >= 0)
        !          4670:                        mcycles++;
        !          4671:                aquot <<= 1;
        !          4672:        }
        !          4673: 
        !          4674:        return mcycles * 2;
        !          4675: }
        !          4676: 
        !          4677: STATIC_INLINE void fill_cache040 (uae_u32 addr)
        !          4678: {
        !          4679:        int index, i, lws;
        !          4680:        uae_u32 tag;
        !          4681:        uae_u32 data;
        !          4682:        struct cache040 *c;
        !          4683:        static int linecnt;
        !          4684: 
        !          4685:        addr &= ~15;
        !          4686:        index = (addr >> 4) & (CACHESETS040 - 1);
        !          4687:        tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
        !          4688:        lws = (addr >> 2) & 3;
        !          4689:        c = &caches040[index];
        !          4690:        for (i = 0; i < CACHELINES040; i++) {
        !          4691:                if (c->valid[i] && c->tag[i] == tag) {
        !          4692:                        // cache hit
        !          4693:                        regs.prefetch020addr[0] = addr;
        !          4694:                        regs.prefetch020data[0] = c->data[i][lws];
        !          4695:                        return;
        !          4696:                }
        !          4697:        }
        !          4698:        // cache miss
        !          4699:        data = mem_access_delay_longi_read_ce020 (addr);
        !          4700:        int line = linecnt;
        !          4701:        for (i = 0; i < CACHELINES040; i++) {
        !          4702:                int line = (linecnt + i) & (CACHELINES040 - 1);
        !          4703:                if (c->tag[i] != tag || c->valid[i] == false) {
        !          4704:                        c->tag[i] = tag;
        !          4705:                        c->valid[i] = true;
        !          4706:                        c->data[i][0] = data;
        !          4707:                }
        !          4708:        }
        !          4709:        regs.prefetch020addr[0] = addr;
        !          4710:        regs.prefetch020data[0] = data;
        !          4711: }
        !          4712: 
        !          4713: // this one is really simple and easy
        !          4714: STATIC_INLINE void fill_icache020 (uae_u32 addr, int idx)
        !          4715: {
        !          4716:        int index;
        !          4717:        uae_u32 tag;
        !          4718:        uae_u32 data;
        !          4719:        struct cache020 *c;
        !          4720: 
        !          4721:        addr &= ~3;
        !          4722:        index = (addr >> 2) & (CACHELINES020 - 1);
        !          4723:        tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
        !          4724:        c = &caches020[index];
        !          4725:        if (c->valid && c->tag == tag) {
        !          4726:                // cache hit
        !          4727:                regs.prefetch020addr[idx] = addr;
        !          4728:                regs.prefetch020data[idx] = c->data;
        !          4729:                return;
        !          4730:        }
        !          4731:        // cache miss
        !          4732:        data = mem_access_delay_longi_read_ce020 (addr);
        !          4733:        if (!(regs.cacr & 2)) {
        !          4734:                c->tag = tag;
        !          4735:                c->valid = !!(regs.cacr & 1);
        !          4736:                c->data = data;
        !          4737:        }
        !          4738:        regs.prefetch020addr[idx] = addr;
        !          4739:        regs.prefetch020data[idx] = data;
        !          4740: }
        !          4741: 
        !          4742: uae_u32 get_word_ce020_prefetch (int o)
        !          4743: {
        !          4744:        int i;
        !          4745:        uae_u32 pc = m68k_getpc () + o;
        !          4746: 
        !          4747:        for (;;) {
        !          4748:                for (i = 0; i < 2; i++) {
        !          4749:                        if (pc == regs.prefetch020addr[0]) {
        !          4750:                                uae_u32 v = regs.prefetch020data[0] >> 16;
        !          4751:                                fill_icache020 (regs.prefetch020addr[0] + 4, 1);
        !          4752:                                return v;
        !          4753:                        }
        !          4754:                        if (pc == regs.prefetch020addr[0] + 2) {
        !          4755:                                uae_u32 v = regs.prefetch020data[0] & 0xffff;
        !          4756:                                if (regs.prefetch020addr[1] == regs.prefetch020addr[0] + 4) {
        !          4757:                                        regs.prefetch020addr[0] = regs.prefetch020addr[1];
        !          4758:                                        regs.prefetch020data[0] = regs.prefetch020data[1];
        !          4759:                                        fill_icache020 (regs.prefetch020addr[0] + 4, 1);
        !          4760:                                } else {
        !          4761:                                        fill_icache020 (pc + 4, 0);
        !          4762:                                        fill_icache020 (regs.prefetch020addr[0] + 4, 1);
        !          4763:                                }
        !          4764:                                return v;
        !          4765:                        }
        !          4766:                        regs.prefetch020addr[0] = regs.prefetch020addr[1];
        !          4767:                        regs.prefetch020data[0] = regs.prefetch020data[1];
        !          4768:                }
        !          4769:                fill_icache020 (pc + 0, 0);
        !          4770:                fill_icache020 (pc + 4, 1);
        !          4771:        }
        !          4772: }
        !          4773: 
        !          4774: // 68030 caches aren't so simple as 68020 cache..
        !          4775: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
        !          4776: {
        !          4777:        int index, lws;
        !          4778:        uae_u32 tag;
        !          4779:        struct cache030 *c;
        !          4780: 
        !          4781:        addr &= ~3;
        !          4782:        index = (addr >> 4) & (CACHELINES030 - 1);
        !          4783:        tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
        !          4784:        lws = (addr >> 2) & 3;
        !          4785:        c = &cp[index];
        !          4786:        *tagp = tag;
        !          4787:        *lwsp = lws;
        !          4788:        return c;
        !          4789: }
        !          4790: 
        !          4791: STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
        !          4792: {
        !          4793:        if (c->tag != tag)
        !          4794:                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
        !          4795:        c->tag = tag;
        !          4796:        c->valid[lws] = true;
        !          4797:        c->data[lws] = val;
        !          4798: }
        !          4799: 
        !          4800: STATIC_INLINE void fill_icache030 (uae_u32 addr, int idx)
        !          4801: {
        !          4802:        int lws;
        !          4803:        uae_u32 tag;
        !          4804:        uae_u32 data;
        !          4805:        struct cache030 *c;
        !          4806: 
        !          4807:        addr &= ~3;
        !          4808:        c = getcache030 (icaches030, addr, &tag, &lws);
        !          4809:        if (c->valid[lws] && c->tag == tag) {
        !          4810:                // cache hit
        !          4811:                regs.prefetch020addr[idx] = addr;
        !          4812:                regs.prefetch020data[idx] = c->data[lws];
        !          4813:                return;
        !          4814:        }
        !          4815:        // cache miss
        !          4816:        data = mem_access_delay_longi_read_ce020 (addr);
        !          4817:        if ((regs.cacr & 3) == 1) { // not frozen and enabled
        !          4818:                update_cache030 (c, data, tag, lws);
        !          4819: #if 0
        !          4820:                if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[0] && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST) {
        !          4821:                        // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
        !          4822:                        c->data[1] = mem_access_delay_long_read_ce020 (addr + 4);
        !          4823:                        c->data[2] = mem_access_delay_long_read_ce020 (addr + 8);
        !          4824:                        c->data[3] = mem_access_delay_long_read_ce020 (addr + 12);
        !          4825:                        c->valid[1] = c->valid[2] = c->valid[3] = true;
        !          4826:                }
        !          4827: #endif
        !          4828:        }
        !          4829:        regs.prefetch020addr[idx] = addr;
        !          4830:        regs.prefetch020data[idx] = data;
        !          4831: }
        !          4832: 
        !          4833: STATIC_INLINE bool cancache030 (uaecptr addr)
        !          4834: {
        !          4835:        return ce_cachable[addr >> 16] != 0;
        !          4836: }
        !          4837: 
        !          4838: // and finally the worst part, 68030 data cache..
        !          4839: void write_dcache030 (uaecptr addr, uae_u32 val, int size)
        !          4840: {
        !          4841:        struct cache030 *c1, *c2;
        !          4842:        int lws1, lws2;
        !          4843:        uae_u32 tag1, tag2;
        !          4844:        int aligned = addr & 3;
        !          4845: 
        !          4846:        if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040) // data cache disabled? 68040 shares this too.
        !          4847:                return;
        !          4848:        if (!cancache030 (addr))
        !          4849:                return;
        !          4850: 
        !          4851:        c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
        !          4852:        if (!(regs.cacr & 0x2000)) { // write allocate
        !          4853:                if (c1->tag != tag1 || c1->valid[lws1] == false)
        !          4854:                        return;
        !          4855:        }
        !          4856: 
        !          4857: #if 0
        !          4858:        uaecptr a = 0x1db0c;
        !          4859:        if (addr - (1 << size) + 1 <= a && addr + (1 << size) >= a) {
        !          4860:                write_log ("%08x %d %d %08x %08x %d\n", addr, aligned, size, val, tag1, lws1);
        !          4861:                if (aligned == 2)
        !          4862:                        write_log ("*\n");
        !          4863:        }
        !          4864: #endif
        !          4865: 
        !          4866:        // easy one
        !          4867:        if (size == 2 && aligned == 0) {
        !          4868:                update_cache030 (c1, val, tag1, lws1);
        !          4869: #if 0
        !          4870:                if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[0] && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST) {
        !          4871:                        // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
        !          4872:                        c1->data[1] = mem_access_delay_long_read_ce020 (addr + 4);
        !          4873:                        c1->data[2] = mem_access_delay_long_read_ce020 (addr + 8);
        !          4874:                        c1->data[3] = mem_access_delay_long_read_ce020 (addr + 12);
        !          4875:                        c1->valid[1] = c1->valid[2] = c1->valid[3] = true;
        !          4876:                }
        !          4877: #endif
        !          4878:                return;
        !          4879:        }
        !          4880:        // argh!! merge partial write
        !          4881:        c2 = getcache030 (dcaches030, addr + 4, &tag2, &lws2);
        !          4882:        if (size == 2) {
        !          4883:                if (c1->valid[lws1] && c1->tag == tag1) {
        !          4884:                        c1->data[lws1] &= ~(0xffffffff >> (aligned * 8));
        !          4885:                        c1->data[lws1] |= val >> (aligned * 8);
        !          4886:                }
        !          4887:                if (c2->valid[lws2] && c2->tag == tag2) {
        !          4888:                        c2->data[lws2] &= 0xffffffff >> ((4 - aligned) * 8);
        !          4889:                        c2->data[lws2] |= val << ((4 - aligned) * 8);
        !          4890:                }
        !          4891:        } else if (size == 1) {
        !          4892:                val <<= 16;
        !          4893:                if (c1->valid[lws1] && c1->tag == tag1) {
        !          4894:                        c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8));
        !          4895:                        c1->data[lws1] |= val >> (aligned * 8);
        !          4896:                }
        !          4897:                if (c2->valid[lws2] && c2->tag == tag2 && aligned == 3) {
        !          4898:                        c2->data[lws2] &= 0x00ffffff;
        !          4899:                        c2->data[lws2] |= val << 8;
        !          4900:                }
        !          4901:        } else if (size == 0) {
        !          4902:                val <<= 24;
        !          4903:                if (c1->valid[lws1] && c1->tag == tag1) {
        !          4904:                        c1->data[lws1] &= ~(0xff000000 >> (aligned * 8));
        !          4905:                        c1->data[lws1] |= val >> (aligned * 8);
        !          4906:                }
        !          4907:        }
        !          4908: }
        !          4909: 
        !          4910: uae_u32 read_dcache030 (uaecptr addr, int size)
        !          4911: {
        !          4912:        struct cache030 *c1, *c2;
        !          4913:        int lws1, lws2;
        !          4914:        uae_u32 tag1, tag2;
        !          4915:        int aligned = addr & 3;
        !          4916:        int len = (1 << size) * 8;
        !          4917:        uae_u32 v1, v2;
        !          4918: 
        !          4919:        if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040 || !cancache030 (addr)) { // data cache disabled? shared with 68040 "ce"
        !          4920:                if (size == 2)
        !          4921:                        return mem_access_delay_long_read_ce020 (addr);
        !          4922:                else if (size == 1)
        !          4923:                        return mem_access_delay_word_read_ce020 (addr);
        !          4924:                else
        !          4925:                        return mem_access_delay_byte_read_ce020 (addr);
        !          4926:        }
        !          4927: 
        !          4928:        c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
        !          4929:        addr &= ~3;
        !          4930:        if (!c1->valid[lws1] || c1->tag != tag1) {
        !          4931:                v1 = mem_access_delay_long_read_ce020 (addr);
        !          4932:                update_cache030 (c1, v1, tag1, lws1);
        !          4933:        } else {
        !          4934:                v1 = c1->data[lws1];
        !          4935:                if (get_long (addr) != v1) {
        !          4936:                        write_log ("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n",
        !          4937:                                size, aligned, addr, get_long (addr), v1, tag1, lws1, M68K_GETPC);
        !          4938:                        v1 = get_long (addr);
        !          4939:                }
        !          4940:        }
        !          4941:        // only one long fetch needed?
        !          4942:        if (size == 0) {
        !          4943:                v1 >>= (3 - aligned) * 8;
        !          4944:                return v1;
        !          4945:        } else if (size == 1 && aligned <= 2) {
        !          4946:                v1 >>= (2 - aligned) * 8;
        !          4947:                return v1;
        !          4948:        } else if (size == 2 && aligned == 0) {
        !          4949:                return v1;
        !          4950:        }
        !          4951:        // need two longs
        !          4952:        addr += 4;
        !          4953:        c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
        !          4954:        if (!c2->valid[lws2] || c2->tag != tag2) {
        !          4955:                v2 = mem_access_delay_long_read_ce020 (addr);
        !          4956:                update_cache030 (c2, v2, tag2, lws2);
        !          4957:        } else {
        !          4958:                v2 = c2->data[lws2];
        !          4959:                if (get_long (addr) != v2) {
        !          4960:                        write_log ("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n",
        !          4961:                                size, aligned, addr, get_long (addr), v2, tag2, lws2, M68K_GETPC);
        !          4962:                        v2 = get_long (addr);
        !          4963:                }
        !          4964:        }
        !          4965:        if (size == 1 && aligned == 3)
        !          4966:                return (v1 << 8) | (v2 >> 24);
        !          4967:        else if (size == 2 && aligned == 1)
        !          4968:                return (v1 << 8) | (v2 >> 24);
        !          4969:        else if (size == 2 && aligned == 2)
        !          4970:                return (v1 << 16) | (v2 >> 16);
        !          4971:        else if (size == 2 && aligned == 3)
        !          4972:                return (v1 << 24) | (v2 >> 8);
        !          4973: 
        !          4974:        write_log ("dcache030 weirdness!?\n");
        !          4975:        return 0;
        !          4976: }
        !          4977: 
        !          4978: uae_u32 get_word_ce030_prefetch (int o)
        !          4979: {
        !          4980:        int i;
        !          4981:        uae_u32 pc = m68k_getpc () + o;
        !          4982: 
        !          4983:        for (;;) {
        !          4984:                for (i = 0; i < 2; i++) {
        !          4985:                        if (pc == regs.prefetch020addr[0]) {
        !          4986:                                uae_u32 v = regs.prefetch020data[0] >> 16;
        !          4987:                                fill_icache030 (regs.prefetch020addr[0] + 4, 1);
        !          4988:                                return v;
        !          4989:                        }
        !          4990:                        if (pc == regs.prefetch020addr[0] + 2) {
        !          4991:                                uae_u32 v = regs.prefetch020data[0] & 0xffff;
        !          4992:                                if (regs.prefetch020addr[1] == regs.prefetch020addr[0] + 4) {
        !          4993:                                        regs.prefetch020addr[0] = regs.prefetch020addr[1];
        !          4994:                                        regs.prefetch020data[0] = regs.prefetch020data[1];
        !          4995:                                        fill_icache030 (regs.prefetch020addr[0] + 4, 1);
        !          4996:                                } else {
        !          4997:                                        fill_icache030 (pc + 4, 0);
        !          4998:                                        fill_icache030 (regs.prefetch020addr[0] + 4, 1);
        !          4999:                                }
        !          5000:                                return v;
        !          5001:                        }
        !          5002:                        regs.prefetch020addr[0] = regs.prefetch020addr[1];
        !          5003:                        regs.prefetch020data[0] = regs.prefetch020data[1];
        !          5004:                }
        !          5005:                fill_icache030 (pc + 0, 0);
        !          5006:                fill_icache030 (pc + 4, 1);
        !          5007:        }
        !          5008: }
        !          5009: 
        !          5010: 
        !          5011: void flush_dcache (uaecptr addr, int size)
        !          5012: {
        !          5013:        int i;
        !          5014:        if (!currprefs.cpu_cycle_exact)
        !          5015:                return;
        !          5016:        if (currprefs.cpu_model >= 68030) {
        !          5017:                for (i = 0; i < CACHELINES030; i++) {
        !          5018:                        dcaches030[i].valid[0] = 0;
        !          5019:                        dcaches030[i].valid[1] = 0;
        !          5020:                        dcaches030[i].valid[2] = 0;
        !          5021:                        dcaches030[i].valid[3] = 0;
        !          5022:                }
        !          5023:        }
        !          5024: }
        !          5025: 
        !          5026: void do_cycles_ce020 (int clocks)
        !          5027: {
        !          5028:        do_cycles_ce (clocks * cpucycleunit);
        !          5029: }
        !          5030: void do_cycles_ce020_mem (int clocks)
        !          5031: {
        !          5032:        regs.ce020memcycles -= clocks * cpucycleunit;
        !          5033:        do_cycles_ce (clocks * cpucycleunit);
        !          5034: }
        !          5035: 
        !          5036: void do_cycles_ce000 (int clocks)
        !          5037: {
        !          5038:        do_cycles_ce (clocks * cpucycleunit);
        !          5039: }
        !          5040: 
        !          5041: void m68k_do_rte_mmu (uaecptr a7)
        !          5042: {
        !          5043:        uae_u16 ssr = get_word_mmu (a7 + 8 + 4);
        !          5044:        if (ssr & MMU_SSW_CT) {
        !          5045:                uaecptr src_a7 = a7 + 8 - 8;
        !          5046:                uaecptr dst_a7 = a7 + 8 + 52;
        !          5047:                put_word_mmu (dst_a7 + 0, get_word_mmu (src_a7 + 0));
        !          5048:                put_long_mmu (dst_a7 + 2, get_long_mmu (src_a7 + 2));
        !          5049:                // skip this word
        !          5050:                put_long_mmu (dst_a7 + 8, get_long_mmu (src_a7 + 8));
        !          5051:        }
        !          5052: }
        !          5053: 
        !          5054: void flush_mmu (uaecptr addr, int n)
        !          5055: {
        !          5056: }
        !          5057: 
        !          5058: void m68k_do_rts_mmu (void)
        !          5059: {
        !          5060:        m68k_setpc (get_long_mmu (m68k_areg (regs, 7)));
        !          5061:        m68k_areg (regs, 7) += 4;
        !          5062: }
        !          5063: 
        !          5064: void m68k_do_bsr_mmu (uaecptr oldpc, uae_s32 offset)
        !          5065: {
        !          5066:        put_long_mmu (m68k_areg (regs, 7) - 4, oldpc);
        !          5067:        m68k_areg (regs, 7) -= 4;
        !          5068:        m68k_incpci (offset);
        !          5069: }

unix.superglobalmegacorp.com

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