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

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

unix.superglobalmegacorp.com

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