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

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 MMUOP_DEBUG 2
                     10: #define DEBUG_CD32CDTVIO 0
1.1.1.7 ! root       11: #define EXCEPTION3_DEBUGGER 0
        !            12: #define CPUTRACE_DEBUG 0
        !            13: 
        !            14: #define MORE_ACCURATE_68020_PIPELINE 1
1.1.1.4   root       15: 
1.1.1.5   root       16: #include "main.h"
1.1.1.4   root       17: #include "compat.h"
1.1.1.7 ! root       18: 
1.1.1.4   root       19: #include "sysconfig.h"
                     20: #include "sysdeps.h"
1.1.1.7 ! root       21: 
1.1.1.4   root       22: #include "hatari-glue.h"
1.1.1.7 ! root       23: 
1.1.1.4   root       24: #include "options_cpu.h"
                     25: #include "events.h"
                     26: #include "memory.h"
1.1.1.7 ! root       27: #include "custom.h"
1.1.1.4   root       28: #include "newcpu.h"
                     29: #include "cpummu.h"
1.1.1.5   root       30: #include "cpummu030.h"
1.1.1.4   root       31: #include "cpu_prefetch.h"
1.1.1.7 ! root       32: #include "savestate.h"
        !            33: #include "md-fpp.h"
        !            34: #ifdef WINUAE_FOR_HATARI
        !            35: #include "debug.h"
        !            36: #endif
        !            37: 
        !            38: #include "m68000.h"
1.1.1.4   root       39: #include "reset.h"
                     40: #include "cycInt.h"
                     41: #include "mfp.h"
                     42: #include "tos.h"
                     43: #include "vdi.h"
                     44: #include "cart.h"
                     45: #include "dialog.h"
                     46: #include "bios.h"
                     47: #include "xbios.h"
                     48: #include "screen.h"
                     49: #include "video.h"
                     50: #include "options.h"
                     51: #include "dsp.h"
                     52: #include "log.h"
                     53: #include "debugui.h"
                     54: #include "debugcpu.h"
1.1.1.5   root       55: #include "stMemory.h"
1.1.1.4   root       56: 
                     57: 
                     58: #ifdef JIT
                     59: #include "jit/compemu.h"
                     60: #include <signal.h>
                     61: #else
                     62: /* Need to have these somewhere */
1.1.1.7 ! root       63: #ifndef WINUAE_FOR_HATARI
        !            64: bool check_prefs_changed_comp (void) { return false; }
        !            65: #endif
1.1.1.4   root       66: #endif
                     67: /* For faster JIT cycles handling */
                     68: signed long pissoff = 0;
                     69: 
                     70: /* Opcode of faulting instruction */
                     71: static uae_u16 last_op_for_exception_3;
                     72: /* PC at fault time */
                     73: static uaecptr last_addr_for_exception_3;
                     74: /* Address that generated the exception */
                     75: static uaecptr last_fault_for_exception_3;
                     76: /* read (0) or write (1) access */
1.1.1.7 ! root       77: static bool last_writeaccess_for_exception_3;
1.1.1.4   root       78: /* instruction (1) or data (0) access */
1.1.1.7 ! root       79: static bool last_instructionaccess_for_exception_3;
        !            80: /* not instruction */
        !            81: static bool last_notinstruction_for_exception_3;
        !            82: /* set when writing exception stack frame */
        !            83: static int exception_in_exception;
        !            84: 
1.1.1.4   root       85: int mmu_enabled, mmu_triggered;
                     86: int cpu_cycles;
1.1.1.7 ! root       87: int bus_error_offset;
        !            88: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root       89: static int baseclock;
1.1.1.7 ! root       90: #endif
        !            91: int m68k_pc_indirect;
        !            92: bool m68k_interrupt_delay;
        !            93: static bool m68k_reset_delay;
        !            94: static int cpu_prefs_changed_flag;
        !            95: 
1.1.1.4   root       96: int cpucycleunit;
1.1.1.7 ! root       97: int cpu_tracer;
1.1.1.4   root       98: 
                     99: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
                    100: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
                    101: 
                    102: int movem_index1[256];
                    103: int movem_index2[256];
                    104: int movem_next[256];
                    105: 
                    106: cpuop_func *cpufunctbl[65536];
                    107: 
1.1.1.7 ! root      108: struct cputbl_data
        !           109: {
        !           110:        uae_s16 length;
        !           111:        uae_s8 disp020[2];
        !           112:        uae_u8 branch;
        !           113: };
        !           114: static struct cputbl_data cpudatatbl[65536];
1.1.1.5   root      115: 
1.1.1.4   root      116: struct mmufixup mmufixup[2];
                    117: 
                    118: #define COUNT_INSTRS 0
                    119: #define MC68060_PCR   0x04300000
                    120: #define MC68EC060_PCR 0x04310000
                    121: 
1.1.1.7 ! root      122: static uae_u64 fake_srp_030, fake_crp_030;
        !           123: static uae_u32 fake_tt0_030, fake_tt1_030, fake_tc_030;
        !           124: static uae_u16 fake_mmusr_030;
1.1.1.4   root      125: 
                    126: static struct cache020 caches020[CACHELINES020];
                    127: static struct cache030 icaches030[CACHELINES030];
                    128: static struct cache030 dcaches030[CACHELINES030];
1.1.1.7 ! root      129: static int icachelinecnt, dcachelinecnt;
        !           130: static struct cache040 icaches040[CACHESETS040];
        !           131: static struct cache040 dcaches040[CACHESETS040];
        !           132: 
        !           133: 
        !           134: #ifdef WINUAE_FOR_HATARI
        !           135: int OpcodeFamily;
        !           136: int BusCyclePenalty = 0;
1.1.1.4   root      137: 
1.1.1.7 ! root      138: FILE *console_out_FILE = NULL;
        !           139: #endif
1.1.1.4   root      140: 
                    141: 
                    142: #if COUNT_INSTRS
                    143: static unsigned long int instrcount[65536];
                    144: static uae_u16 opcodenums[65536];
                    145: 
                    146: static int compfn (const void *el1, const void *el2)
                    147: {
                    148:        return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
                    149: }
                    150: 
                    151: static TCHAR *icountfilename (void)
                    152: {
                    153:        TCHAR *name = getenv ("INSNCOUNT");
                    154:        if (name)
                    155:                return name;
                    156:        return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
                    157: }
                    158: 
                    159: void dump_counts (void)
                    160: {
                    161:        FILE *f = fopen (icountfilename (), "w");
                    162:        unsigned long int total;
                    163:        int i;
                    164: 
1.1.1.7 ! root      165:        write_log (_T("Writing instruction count file...\n"));
1.1.1.4   root      166:        for (i = 0; i < 65536; i++) {
                    167:                opcodenums[i] = i;
                    168:                total += instrcount[i];
                    169:        }
                    170:        qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
                    171: 
                    172:        fprintf (f, "Total: %lu\n", total);
                    173:        for (i=0; i < 65536; i++) {
                    174:                unsigned long int cnt = instrcount[opcodenums[i]];
                    175:                struct instr *dp;
                    176:                struct mnemolookup *lookup;
                    177:                if (!cnt)
                    178:                        break;
                    179:                dp = table68k + opcodenums[i];
                    180:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                    181:                        ;
                    182:                fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
                    183:        }
                    184:        fclose (f);
                    185: }
                    186: #else
                    187: void dump_counts (void)
                    188: {
                    189: }
                    190: #endif
                    191: 
1.1.1.7 ! root      192: /*
        !           193: 
        !           194:  ok, all this to "record" current instruction state
        !           195:  for later 100% cycle-exact restoring
        !           196: 
        !           197:  */
        !           198: 
        !           199: static uae_u32 (*x2_prefetch)(int);
        !           200: static uae_u32 (*x2_prefetch_long)(int);
        !           201: static uae_u32 (*x2_next_iword)(void);
        !           202: static uae_u32 (*x2_next_ilong)(void);
        !           203: static uae_u32 (*x2_get_ilong)(int);
        !           204: static uae_u32 (*x2_get_iword)(int);
        !           205: static uae_u32 (*x2_get_ibyte)(int);
        !           206: static uae_u32 (*x2_get_long)(uaecptr);
        !           207: static uae_u32 (*x2_get_word)(uaecptr);
        !           208: static uae_u32 (*x2_get_byte)(uaecptr);
        !           209: static void (*x2_put_long)(uaecptr,uae_u32);
        !           210: static void (*x2_put_word)(uaecptr,uae_u32);
        !           211: static void (*x2_put_byte)(uaecptr,uae_u32);
        !           212: static void (*x2_do_cycles)(unsigned long);
        !           213: static void (*x2_do_cycles_pre)(unsigned long);
        !           214: static void (*x2_do_cycles_post)(unsigned long, uae_u32);
1.1.1.4   root      215: 
                    216: uae_u32 (*x_prefetch)(int);
                    217: uae_u32 (*x_next_iword)(void);
                    218: uae_u32 (*x_next_ilong)(void);
1.1.1.7 ! root      219: uae_u32 (*x_get_ilong)(int);
        !           220: uae_u32 (*x_get_iword)(int);
        !           221: uae_u32 (*x_get_ibyte)(int);
1.1.1.4   root      222: uae_u32 (*x_get_long)(uaecptr);
                    223: uae_u32 (*x_get_word)(uaecptr);
                    224: uae_u32 (*x_get_byte)(uaecptr);
                    225: void (*x_put_long)(uaecptr,uae_u32);
                    226: void (*x_put_word)(uaecptr,uae_u32);
                    227: void (*x_put_byte)(uaecptr,uae_u32);
                    228: 
1.1.1.7 ! root      229: uae_u32 (*x_cp_next_iword)(void);
        !           230: uae_u32 (*x_cp_next_ilong)(void);
        !           231: uae_u32 (*x_cp_get_long)(uaecptr);
        !           232: uae_u32 (*x_cp_get_word)(uaecptr);
        !           233: uae_u32 (*x_cp_get_byte)(uaecptr);
        !           234: void (*x_cp_put_long)(uaecptr,uae_u32);
        !           235: void (*x_cp_put_word)(uaecptr,uae_u32);
        !           236: void (*x_cp_put_byte)(uaecptr,uae_u32);
        !           237: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
        !           238: 
        !           239: void (*x_do_cycles)(unsigned long);
        !           240: void (*x_do_cycles_pre)(unsigned long);
        !           241: void (*x_do_cycles_post)(unsigned long, uae_u32);
        !           242: 
        !           243: uae_u32(*x_phys_get_iword)(uaecptr);
        !           244: uae_u32(*x_phys_get_ilong)(uaecptr);
        !           245: uae_u32(*x_phys_get_byte)(uaecptr);
        !           246: uae_u32(*x_phys_get_word)(uaecptr);
        !           247: uae_u32(*x_phys_get_long)(uaecptr);
        !           248: void(*x_phys_put_byte)(uaecptr, uae_u32);
        !           249: void(*x_phys_put_word)(uaecptr, uae_u32);
        !           250: void(*x_phys_put_long)(uaecptr, uae_u32);
        !           251: 
        !           252: static void set_x_cp_funcs(void)
        !           253: {
        !           254:        x_cp_put_long = x_put_long;
        !           255:        x_cp_put_word = x_put_word;
        !           256:        x_cp_put_byte = x_put_byte;
        !           257:        x_cp_get_long = x_get_long;
        !           258:        x_cp_get_word = x_get_word;
        !           259:        x_cp_get_byte = x_get_byte;
        !           260:        x_cp_next_iword = x_next_iword;
        !           261:        x_cp_next_ilong = x_next_ilong;
        !           262:        x_cp_get_disp_ea_020 = x_get_disp_ea_020;
        !           263: 
        !           264:        if (currprefs.mmu_model == 68030) {
        !           265:                x_cp_put_long = put_long_mmu030_state;
        !           266:                x_cp_put_word = put_word_mmu030_state;
        !           267:                x_cp_put_byte = put_byte_mmu030_state;
        !           268:                x_cp_get_long = get_long_mmu030_state;
        !           269:                x_cp_get_word = get_word_mmu030_state;
        !           270:                x_cp_get_byte = get_byte_mmu030_state;
        !           271:                x_cp_next_iword = next_iword_mmu030_state;
        !           272:                x_cp_next_ilong = next_ilong_mmu030_state;
        !           273:                x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
        !           274:        }
        !           275: }
        !           276: 
        !           277: static struct cputracestruct cputrace;
        !           278: 
        !           279: #if CPUTRACE_DEBUG
        !           280: static void validate_trace (void)
        !           281: {
        !           282:        for (int i = 0; i < cputrace.memoryoffset; i++) {
        !           283:                struct cputracememory *ctm = &cputrace.ctm[i];
        !           284:                if (ctm->data == 0xdeadf00d) {
        !           285:                        write_log (_T("unfinished write operation %d %08x\n"), i, ctm->addr);
        !           286:                }
        !           287:        }
        !           288: }
        !           289: #endif
        !           290: 
        !           291: static void debug_trace (void)
        !           292: {
        !           293:        if (cputrace.writecounter > 10000 || cputrace.readcounter > 10000)
        !           294:                write_log (_T("cputrace.readcounter=%d cputrace.writecounter=%d\n"), cputrace.readcounter, cputrace.writecounter);
        !           295: }
        !           296: 
        !           297: STATIC_INLINE void clear_trace (void)
        !           298: {
        !           299: #if CPUTRACE_DEBUG
        !           300:        validate_trace ();
        !           301: #endif
        !           302:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
        !           303:        ctm->mode = 0;
        !           304:        cputrace.cyclecounter = 0;
        !           305:        cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
        !           306: }
        !           307: static void set_trace (uaecptr addr, int accessmode, int size)
        !           308: {
        !           309: #if CPUTRACE_DEBUG
        !           310:        validate_trace ();
        !           311: #endif
        !           312:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
        !           313:        ctm->addr = addr;
        !           314:        ctm->data = 0xdeadf00d;
        !           315:        ctm->mode = accessmode | (size << 4);
        !           316:        cputrace.cyclecounter_pre = -1;
        !           317:        if (accessmode == 1)
        !           318:                cputrace.writecounter++;
        !           319:        else
        !           320:                cputrace.readcounter++;
        !           321:        debug_trace ();
        !           322: }
        !           323: static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size)
        !           324: {
        !           325:        if (cputrace.memoryoffset < 1) {
        !           326: #if CPUTRACE_DEBUG
        !           327:                write_log (_T("add_trace memoryoffset=%d!\n"), cputrace.memoryoffset);
        !           328: #endif
        !           329:                return;
        !           330:        }
        !           331:        int mode = accessmode | (size << 4);
        !           332:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
        !           333:        ctm->addr = addr;
        !           334:        ctm->data = val;
        !           335:        if (!ctm->mode) {
        !           336:                ctm->mode = mode;
        !           337:                if (accessmode == 1)
        !           338:                        cputrace.writecounter++;
        !           339:                else
        !           340:                        cputrace.readcounter++;
        !           341:        }
        !           342:        debug_trace ();
        !           343:        cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
        !           344: }
        !           345: 
        !           346: 
        !           347: static void check_trace2 (void)
        !           348: {
        !           349:        if (cputrace.readcounter || cputrace.writecounter ||
        !           350:                cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
        !           351:                write_log (_T("CPU tracer invalid state during playback!\n"));
        !           352: }
        !           353: 
        !           354: static bool check_trace (void)
        !           355: {
        !           356:        if (!cpu_tracer)
        !           357:                return true;
        !           358:        if (!cputrace.readcounter && !cputrace.writecounter && !cputrace.cyclecounter) {
        !           359:                if (cpu_tracer != -2) {
        !           360:                        write_log (_T("CPU trace: dma_cycle() enabled. %08x %08x NOW=%08lx\n"),
        !           361:                                cputrace.cyclecounter_pre, cputrace.cyclecounter_post, get_cycles ());
        !           362:                        cpu_tracer = -2; // dma_cycle() allowed to work now
        !           363:                }
        !           364:        }
        !           365:        if (cputrace.readcounter || cputrace.writecounter ||
        !           366:                cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
        !           367:                return false;
        !           368:        x_prefetch = x2_prefetch;
        !           369:        x_get_ilong = x2_get_ilong;
        !           370:        x_get_iword = x2_get_iword;
        !           371:        x_get_ibyte = x2_get_ibyte;
        !           372:        x_next_iword = x2_next_iword;
        !           373:        x_next_ilong = x2_next_ilong;
        !           374:        x_put_long = x2_put_long;
        !           375:        x_put_word = x2_put_word;
        !           376:        x_put_byte = x2_put_byte;
        !           377:        x_get_long = x2_get_long;
        !           378:        x_get_word = x2_get_word;
        !           379:        x_get_byte = x2_get_byte;
        !           380:        x_do_cycles = x2_do_cycles;
        !           381:        x_do_cycles_pre = x2_do_cycles_pre;
        !           382:        x_do_cycles_post = x2_do_cycles_post;
        !           383:        set_x_cp_funcs();
        !           384:        write_log (_T("CPU tracer playback complete. STARTCYCLES=%08x NOWCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
        !           385:        cputrace.needendcycles = 1;
        !           386:        cpu_tracer = 0;
        !           387:        return true;
        !           388: }
        !           389: 
        !           390: static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data)
        !           391: {
        !           392:        int mode = accessmode | (size << 4);
        !           393:        int i;
        !           394:        for (i = 0; i < cputrace.memoryoffset; i++) {
        !           395:                struct cputracememory *ctm = &cputrace.ctm[i];
        !           396:                if (ctm->addr == addr && ctm->mode == mode) {
        !           397:                        ctm->mode = 0;
        !           398:                        write_log (_T("CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d (%08lx)\n"),
        !           399:                                i, cputrace.pc, addr, ctm->data, accessmode, size,
        !           400:                                cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
        !           401:                                cputrace.readcounter, cputrace.writecounter, get_cycles ());
        !           402:                        if (accessmode == 1)
        !           403:                                cputrace.writecounter--;
        !           404:                        else
        !           405:                                cputrace.readcounter--;
        !           406:                        if (cputrace.writecounter == 0 && cputrace.readcounter == 0) {
        !           407:                                if (cputrace.cyclecounter_post) {
        !           408:                                        int c = cputrace.cyclecounter_post;
        !           409:                                        cputrace.cyclecounter_post = 0;
        !           410:                                        x_do_cycles (c);
        !           411:                                } else if (cputrace.cyclecounter_pre) {
        !           412:                                        check_trace ();
        !           413:                                        *data = ctm->data;
        !           414:                                        return true; // argh, need to rerun the memory access..
        !           415:                                }
        !           416:                        }
        !           417:                        check_trace ();
        !           418:                        *data = ctm->data;
        !           419:                        return false;
        !           420:                }
        !           421:        }
        !           422:        if (cputrace.cyclecounter_post) {
        !           423:                int c = cputrace.cyclecounter_post;
        !           424:                cputrace.cyclecounter_post = 0;
        !           425:                check_trace ();
        !           426:                check_trace2 ();
        !           427:                x_do_cycles (c);
        !           428:                return false;
        !           429:        }
        !           430:        gui_message (_T("CPU trace: GET %08x %d %d NOT FOUND!\n"), addr, accessmode, size);
        !           431:        check_trace ();
        !           432:        *data = 0;
        !           433:        return false;
        !           434: }
        !           435: 
        !           436: static uae_u32 cputracefunc_x_prefetch (int o)
        !           437: {
        !           438:        uae_u32 pc = m68k_getpc ();
        !           439:        set_trace (pc + o, 2, 2);
        !           440:        uae_u32 v = x2_prefetch (o);
        !           441:        add_trace (pc + o, v, 2, 2);
        !           442:        return v;
        !           443: }
        !           444: static uae_u32 cputracefunc2_x_prefetch (int o)
        !           445: {
        !           446:        uae_u32 v;
        !           447:        if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
        !           448:                v = x2_prefetch (o);
        !           449:                check_trace2 ();
        !           450:        }
        !           451:        return v;
        !           452: }
        !           453: 
        !           454: static uae_u32 cputracefunc_x_next_iword (void)
        !           455: {
        !           456:        uae_u32 pc = m68k_getpc ();
        !           457:        set_trace (pc, 2, 2);
        !           458:        uae_u32 v = x2_next_iword ();
        !           459:        add_trace (pc, v, 2, 2);
        !           460:        return v;
        !           461: }
        !           462: static uae_u32 cputracefunc_x_next_ilong (void)
        !           463: {
        !           464:        uae_u32 pc = m68k_getpc ();
        !           465:        set_trace (pc, 2, 4);
        !           466:        uae_u32 v = x2_next_ilong ();
        !           467:        add_trace (pc, v, 2, 4);
        !           468:        return v;
        !           469: }
        !           470: static uae_u32 cputracefunc2_x_next_iword (void)
        !           471: {
        !           472:        uae_u32 v;
        !           473:        if (get_trace (m68k_getpc (), 2, 2, &v)) {
        !           474:                v = x2_next_iword ();
        !           475:                check_trace2 ();
        !           476:        }
        !           477:        return v;
        !           478: }
        !           479: static uae_u32 cputracefunc2_x_next_ilong (void)
        !           480: {
        !           481:        uae_u32 v;
        !           482:        if (get_trace (m68k_getpc (), 2, 4, &v)) {
        !           483:                v = x2_next_ilong ();
        !           484:                check_trace2 ();
        !           485:        }
        !           486:        return v;
        !           487: }
        !           488: 
        !           489: static uae_u32 cputracefunc_x_get_ilong (int o)
        !           490: {
        !           491:        uae_u32 pc = m68k_getpc ();
        !           492:        set_trace (pc + o, 2, 4);
        !           493:        uae_u32 v = x2_get_ilong (o);
        !           494:        add_trace (pc + o, v, 2, 4);
        !           495:        return v;
        !           496: }
        !           497: static uae_u32 cputracefunc_x_get_iword (int o)
        !           498: {
        !           499:        uae_u32 pc = m68k_getpc ();
        !           500:        set_trace (pc + o, 2, 2);
        !           501:        uae_u32 v = x2_get_iword (o);
        !           502:        add_trace (pc + o, v, 2, 2);
        !           503:        return v;
        !           504: }
        !           505: static uae_u32 cputracefunc_x_get_ibyte (int o)
        !           506: {
        !           507:        uae_u32 pc = m68k_getpc ();
        !           508:        set_trace (pc + o, 2, 1);
        !           509:        uae_u32 v = x2_get_ibyte (o);
        !           510:        add_trace (pc + o, v, 2, 1);
        !           511:        return v;
        !           512: }
        !           513: static uae_u32 cputracefunc2_x_get_ilong (int o)
        !           514: {
        !           515:        uae_u32 v;
        !           516:        if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
        !           517:                v = x2_get_ilong (o);
        !           518:                check_trace2 ();
        !           519:        }
        !           520:        return v;
        !           521: }
        !           522: static uae_u32 cputracefunc2_x_get_iword (int o)
        !           523: {
        !           524:        uae_u32 v;
        !           525:        if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
        !           526:                v = x2_get_iword (o);
        !           527:                check_trace2 ();
        !           528:        }
        !           529:        return v;
        !           530: }
        !           531: static uae_u32 cputracefunc2_x_get_ibyte (int o)
        !           532: {
        !           533:        uae_u32 v;
        !           534:        if (get_trace (m68k_getpc () + o, 2, 1, &v)) {
        !           535:                v = x2_get_ibyte (o);
        !           536:                check_trace2 ();
        !           537:        }
        !           538:        return v;
        !           539: }
        !           540: 
        !           541: static uae_u32 cputracefunc_x_get_long (uaecptr o)
        !           542: {
        !           543:        set_trace (o, 0, 4);
        !           544:        uae_u32 v = x2_get_long (o);
        !           545:        add_trace (o, v, 0, 4);
        !           546:        return v;
        !           547: }
        !           548: static uae_u32 cputracefunc_x_get_word (uaecptr o)
        !           549: {
        !           550:        set_trace (o, 0, 2);
        !           551:        uae_u32 v = x2_get_word (o);
        !           552:        add_trace (o, v, 0, 2);
        !           553:        return v;
        !           554: }
        !           555: static uae_u32 cputracefunc_x_get_byte (uaecptr o)
        !           556: {
        !           557:        set_trace (o, 0, 1);
        !           558:        uae_u32 v = x2_get_byte (o);
        !           559:        add_trace (o, v, 0, 1);
        !           560:        return v;
        !           561: }
        !           562: static uae_u32 cputracefunc2_x_get_long (uaecptr o)
        !           563: {
        !           564:        uae_u32 v;
        !           565:        if (get_trace (o, 0, 4, &v)) {
        !           566:                v = x2_get_long (o);
        !           567:                check_trace2 ();
        !           568:        }
        !           569:        return v;
        !           570: }
        !           571: static uae_u32 cputracefunc2_x_get_word (uaecptr o)
        !           572: {
        !           573:        uae_u32 v;
        !           574:        if (get_trace (o, 0, 2, &v)) {
        !           575:                v = x2_get_word (o);
        !           576:                check_trace2 ();
        !           577:        }
        !           578:        return v;
        !           579: }
        !           580: static uae_u32 cputracefunc2_x_get_byte (uaecptr o)
        !           581: {
        !           582:        uae_u32 v;
        !           583:        if (get_trace (o, 0, 1, &v)) {
        !           584:                v = x2_get_byte (o);
        !           585:                check_trace2 ();
        !           586:        }
        !           587:        return v;
        !           588: }
        !           589: 
        !           590: static void cputracefunc_x_put_long (uaecptr o, uae_u32 val)
        !           591: {
        !           592:        clear_trace ();
        !           593:        add_trace (o, val, 1, 4);
        !           594:        x2_put_long (o, val);
        !           595: }
        !           596: static void cputracefunc_x_put_word (uaecptr o, uae_u32 val)
        !           597: {
        !           598:        clear_trace ();
        !           599:        add_trace (o, val, 1, 2);
        !           600:        x2_put_word (o, val);
        !           601: }
        !           602: static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val)
        !           603: {
        !           604:        clear_trace ();
        !           605:        add_trace (o, val, 1, 1);
        !           606:        x2_put_byte (o, val);
        !           607: }
        !           608: static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val)
        !           609: {
        !           610:        uae_u32 v;
        !           611:        if (get_trace (o, 1, 4, &v)) {
        !           612:                x2_put_long (o, val);
        !           613:                check_trace2 ();
        !           614:        }
        !           615:        if (v != val)
        !           616:                write_log (_T("cputracefunc2_x_put_long %d <> %d\n"), v, val);
        !           617: }
        !           618: static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val)
        !           619: {
        !           620:        uae_u32 v;
        !           621:        if (get_trace (o, 1, 2, &v)) {
        !           622:                x2_put_word (o, val);
        !           623:                check_trace2 ();
        !           624:        }
        !           625:        if (v != val)
        !           626:                write_log (_T("cputracefunc2_x_put_word %d <> %d\n"), v, val);
        !           627: }
        !           628: static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val)
        !           629: {
        !           630:        uae_u32 v;
        !           631:        if (get_trace (o, 1, 1, &v)) {
        !           632:                x2_put_byte (o, val);
        !           633:                check_trace2 ();
        !           634:        }
        !           635:        if (v != val)
        !           636:                write_log (_T("cputracefunc2_x_put_byte %d <> %d\n"), v, val);
        !           637: }
        !           638: 
        !           639: static void cputracefunc_x_do_cycles (unsigned long cycles)
        !           640: {
        !           641:        while (cycles >= CYCLE_UNIT) {
        !           642:                cputrace.cyclecounter += CYCLE_UNIT;
        !           643:                cycles -= CYCLE_UNIT;
        !           644:                x2_do_cycles (CYCLE_UNIT);
        !           645:        }
        !           646:        if (cycles > 0) {
        !           647:                cputrace.cyclecounter += cycles;
        !           648:                x2_do_cycles (cycles);
        !           649:        }
        !           650: }
        !           651: 
        !           652: static void cputracefunc2_x_do_cycles (unsigned long cycles)
        !           653: {
        !           654:        if (cputrace.cyclecounter > (long)cycles) {
        !           655:                cputrace.cyclecounter -= cycles;
        !           656:                return;
        !           657:        }
        !           658:        cycles -= cputrace.cyclecounter;
        !           659:        cputrace.cyclecounter = 0;
        !           660:        check_trace ();
        !           661:        x_do_cycles = x2_do_cycles;
        !           662:        if (cycles > 0)
        !           663:                x_do_cycles (cycles);
        !           664: }
        !           665: 
        !           666: static void cputracefunc_x_do_cycles_pre (unsigned long cycles)
        !           667: {
        !           668:        cputrace.cyclecounter_post = 0;
        !           669:        cputrace.cyclecounter_pre = 0;
        !           670:        while (cycles >= CYCLE_UNIT) {
        !           671:                cycles -= CYCLE_UNIT;
        !           672:                cputrace.cyclecounter_pre += CYCLE_UNIT;
        !           673:                x2_do_cycles (CYCLE_UNIT);
        !           674:        }
        !           675:        if (cycles > 0) {
        !           676:                x2_do_cycles (cycles);
        !           677:                cputrace.cyclecounter_pre += cycles;
        !           678:        }
        !           679:        cputrace.cyclecounter_pre = 0;
        !           680: }
        !           681: // cyclecounter_pre = how many cycles we need to SWALLOW
        !           682: // -1 = rerun whole access
        !           683: static void cputracefunc2_x_do_cycles_pre (unsigned long cycles)
        !           684: {
        !           685:        if (cputrace.cyclecounter_pre == -1) {
        !           686:                cputrace.cyclecounter_pre = 0;
        !           687:                check_trace ();
        !           688:                check_trace2 ();
        !           689:                x_do_cycles (cycles);
        !           690:                return;
        !           691:        }
        !           692:        if (cputrace.cyclecounter_pre > (long)cycles) {
        !           693:                cputrace.cyclecounter_pre -= cycles;
        !           694:                return;
        !           695:        }
        !           696:        cycles -= cputrace.cyclecounter_pre;
        !           697:        cputrace.cyclecounter_pre = 0;
        !           698:        check_trace ();
        !           699:        if (cycles > 0)
        !           700:                x_do_cycles (cycles);
        !           701: }
        !           702: 
        !           703: static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v)
        !           704: {
        !           705:        if (cputrace.memoryoffset < 1) {
        !           706: #if CPUTRACE_DEBUG
        !           707:                write_log (_T("cputracefunc_x_do_cycles_post memoryoffset=%d!\n"), cputrace.memoryoffset);
        !           708: #endif
        !           709:                return;
        !           710:        }
        !           711:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
        !           712:        ctm->data = v;
        !           713:        cputrace.cyclecounter_post = cycles;
        !           714:        cputrace.cyclecounter_pre = 0;
        !           715:        while (cycles >= CYCLE_UNIT) {
        !           716:                cycles -= CYCLE_UNIT;
        !           717:                cputrace.cyclecounter_post -= CYCLE_UNIT;
        !           718:                x2_do_cycles (CYCLE_UNIT);
        !           719:        }
        !           720:        if (cycles > 0) {
        !           721:                cputrace.cyclecounter_post -= cycles;
        !           722:                x2_do_cycles (cycles);
        !           723:        }
        !           724:        cputrace.cyclecounter_post = 0;
        !           725: }
        !           726: // cyclecounter_post = how many cycles we need to WAIT
        !           727: static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v)
        !           728: {
        !           729:        uae_u32 c;
        !           730:        if (cputrace.cyclecounter_post) {
        !           731:                c = cputrace.cyclecounter_post;
        !           732:                cputrace.cyclecounter_post = 0;
        !           733:        } else {
        !           734:                c = cycles;
        !           735:        }
        !           736:        check_trace ();
        !           737:        if (c > 0)
        !           738:                x_do_cycles (c);
        !           739: }
        !           740: 
        !           741: static void do_cycles_post (unsigned long cycles, uae_u32 v)
        !           742: {
        !           743:        do_cycles (cycles);
        !           744: }
        !           745: static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
        !           746: {
        !           747:        do_cycles_ce (cycles);
        !           748: }
        !           749: static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
        !           750: {
        !           751: #ifndef WINUAE_FOR_HATARI
        !           752:        do_cycles_ce020 (cycles);
        !           753: #else
        !           754:        do_cycles_ce020_long (cycles);
        !           755: #endif
        !           756: }
        !           757: 
        !           758: static void set_x_ifetches(void)
        !           759: {
        !           760:        if (m68k_pc_indirect) {
        !           761:                if (currprefs.cachesize) {
        !           762:                        // indirect via addrbank
        !           763:                        x_get_ilong = get_iilong_jit;
        !           764:                        x_get_iword = get_iiword_jit;
        !           765:                        x_get_ibyte = get_iibyte_jit;
        !           766:                        x_next_iword = next_iiword_jit;
        !           767:                        x_next_ilong = next_iilong_jit;
        !           768:                } else {
        !           769:                        // indirect via addrbank
        !           770:                        x_get_ilong = get_iilong;
        !           771:                        x_get_iword = get_iiword;
        !           772:                        x_get_ibyte = get_iibyte;
        !           773:                        x_next_iword = next_iiword;
        !           774:                        x_next_ilong = next_iilong;
        !           775:                }
        !           776:        } else {
        !           777:                // direct to memory
        !           778:                x_get_ilong = get_dilong;
        !           779:                x_get_iword = get_diword;
        !           780:                x_get_ibyte = get_dibyte;
        !           781:                x_next_iword = next_diword;
        !           782:                x_next_ilong = next_dilong;
        !           783:        }
        !           784: }
        !           785: 
        !           786: // indirect memory access functions
1.1.1.4   root      787: static void set_x_funcs (void)
                    788: {
1.1.1.7 ! root      789:        if (currprefs.mmu_model) {
        !           790:                if (currprefs.cpu_model == 68060) {
        !           791:                        x_prefetch = get_iword_mmu060;
        !           792:                        x_get_ilong = get_ilong_mmu060;
        !           793:                        x_get_iword = get_iword_mmu060;
        !           794:                        x_get_ibyte = get_ibyte_mmu060;
        !           795:                        x_next_iword = next_iword_mmu060;
        !           796:                        x_next_ilong = next_ilong_mmu060;
        !           797:                        x_put_long = put_long_mmu060;
        !           798:                        x_put_word = put_word_mmu060;
        !           799:                        x_put_byte = put_byte_mmu060;
        !           800:                        x_get_long = get_long_mmu060;
        !           801:                        x_get_word = get_word_mmu060;
        !           802:                        x_get_byte = get_byte_mmu060;
        !           803:                } else if (currprefs.cpu_model == 68040) {
        !           804:                        x_prefetch = get_iword_mmu040;
        !           805:                        x_get_ilong = get_ilong_mmu040;
        !           806:                        x_get_iword = get_iword_mmu040;
        !           807:                        x_get_ibyte = get_ibyte_mmu040;
        !           808:                        x_next_iword = next_iword_mmu040;
        !           809:                        x_next_ilong = next_ilong_mmu040;
        !           810:                        x_put_long = put_long_mmu040;
        !           811:                        x_put_word = put_word_mmu040;
        !           812:                        x_put_byte = put_byte_mmu040;
        !           813:                        x_get_long = get_long_mmu040;
        !           814:                        x_get_word = get_word_mmu040;
        !           815:                        x_get_byte = get_byte_mmu040;
        !           816:                } else {
        !           817:                        x_prefetch = get_iword_mmu030;
        !           818:                        x_get_ilong = get_ilong_mmu030;
        !           819:                        x_get_iword = get_iword_mmu030;
        !           820:                        x_get_ibyte = get_ibyte_mmu030;
        !           821:                        x_next_iword = next_iword_mmu030;
        !           822:                        x_next_ilong = next_ilong_mmu030;
        !           823:                        x_put_long = put_long_mmu030;
        !           824:                        x_put_word = put_word_mmu030;
        !           825:                        x_put_byte = put_byte_mmu030;
        !           826:                        x_get_long = get_long_mmu030;
        !           827:                        x_get_word = get_word_mmu030;
        !           828:                        x_get_byte = get_byte_mmu030;
        !           829:                }
        !           830:                x_do_cycles = do_cycles;
        !           831:                x_do_cycles_pre = do_cycles;
        !           832:                x_do_cycles_post = do_cycles_post;
1.1.1.4   root      833:        } else if (currprefs.cpu_model < 68020) {
1.1.1.7 ! root      834:                // 68000/010
        !           835:                if (currprefs.cpu_cycle_exact) {
        !           836:                        x_prefetch = get_word_ce000_prefetch;
        !           837:                        x_get_ilong = NULL;
        !           838:                        x_get_iword = get_wordi_ce000;
        !           839:                        x_get_ibyte = NULL;
        !           840:                        x_next_iword = NULL;
        !           841:                        x_next_ilong = NULL;
        !           842:                        x_put_long = put_long_ce000;
        !           843:                        x_put_word = put_word_ce000;
        !           844:                        x_put_byte = put_byte_ce000;
        !           845:                        x_get_long = get_long_ce000;
        !           846:                        x_get_word = get_word_ce000;
        !           847:                        x_get_byte = get_byte_ce000;
        !           848:                        x_do_cycles = do_cycles_ce;
        !           849:                        x_do_cycles_pre = do_cycles_ce;
        !           850:                        x_do_cycles_post = do_cycles_ce_post;
        !           851:                } else if (currprefs.cpu_compatible) {
        !           852:                        x_prefetch = get_word_prefetch;
        !           853:                        x_get_ilong = NULL;
        !           854:                        x_get_iword = get_iiword;
        !           855:                        x_get_ibyte = get_iibyte;
        !           856:                        x_next_iword = NULL;
        !           857:                        x_next_ilong = NULL;
        !           858:                        x_put_long = put_long;
        !           859:                        x_put_word = put_word;
        !           860:                        x_put_byte = put_byte;
        !           861:                        x_get_long = get_long;
        !           862:                        x_get_word = get_word;
        !           863:                        x_get_byte = get_byte;
        !           864:                        x_do_cycles = do_cycles;
        !           865:                        x_do_cycles_pre = do_cycles;
        !           866:                        x_do_cycles_post = do_cycles_post;
        !           867:                } else {
        !           868:                        x_prefetch = NULL;
        !           869:                        x_get_ilong = get_dilong;
        !           870:                        x_get_iword = get_diword;
        !           871:                        x_get_ibyte = get_dibyte;
        !           872:                        x_next_iword = next_diword;
        !           873:                        x_next_ilong = next_dilong;
        !           874:                        x_put_long = put_long;
        !           875:                        x_put_word = put_word;
        !           876:                        x_put_byte = put_byte;
        !           877:                        x_get_long = get_long;
        !           878:                        x_get_word = get_word;
        !           879:                        x_get_byte = get_byte;
        !           880:                        x_do_cycles = do_cycles;
        !           881:                        x_do_cycles_pre = do_cycles;
        !           882:                        x_do_cycles_post = do_cycles_post;
        !           883:                }
        !           884:        } else if (!currprefs.cpu_cycle_exact) {
        !           885:                // 68020+ no ce
        !           886:                if (currprefs.cpu_compatible) {
        !           887:                        if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
        !           888:                                x_prefetch = get_word_prefetch;
        !           889:                                x_get_ilong = get_long_020_prefetch;
        !           890:                                x_get_iword = get_word_020_prefetch;
        !           891:                                x_get_ibyte = NULL;
        !           892:                                x_next_iword = next_iword_020_prefetch;
        !           893:                                x_next_ilong = next_ilong_020_prefetch;
        !           894:                                x_put_long = put_long;
        !           895:                                x_put_word = put_word;
        !           896:                                x_put_byte = put_byte;
        !           897:                                x_get_long = get_long;
        !           898:                                x_get_word = get_word;
        !           899:                                x_get_byte = get_byte;
        !           900:                                x_do_cycles = do_cycles;
        !           901:                                x_do_cycles_pre = do_cycles;
        !           902:                                x_do_cycles_post = do_cycles_post;
        !           903:                        } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
        !           904:                                x_prefetch = get_word_prefetch;
        !           905:                                x_get_ilong = get_long_030_prefetch;
        !           906:                                x_get_iword = get_word_030_prefetch;
        !           907:                                x_get_ibyte = NULL;
        !           908:                                x_next_iword = next_iword_030_prefetch;
        !           909:                                x_next_ilong = next_ilong_030_prefetch;
        !           910:                                x_put_long = put_long;
        !           911:                                x_put_word = put_word;
        !           912:                                x_put_byte = put_byte;
        !           913:                                x_get_long = get_long;
        !           914:                                x_get_word = get_word;
        !           915:                                x_get_byte = get_byte;
        !           916:                                x_do_cycles = do_cycles;
        !           917:                                x_do_cycles_pre = do_cycles;
        !           918:                                x_do_cycles_post = do_cycles_post;
        !           919:                        } else if (currprefs.cpu_model < 68040) {
        !           920:                                // JIT or 68030+ does not have real prefetch only emulation
        !           921:                                x_prefetch = NULL;
        !           922:                                set_x_ifetches();
        !           923:                                x_put_long = put_long;
        !           924:                                x_put_word = put_word;
        !           925:                                x_put_byte = put_byte;
        !           926:                                x_get_long = get_long;
        !           927:                                x_get_word = get_word;
        !           928:                                x_get_byte = get_byte;
        !           929:                                x_do_cycles = do_cycles;
        !           930:                                x_do_cycles_pre = do_cycles;
        !           931:                                x_do_cycles_post = do_cycles_post;
        !           932:                        } else {
        !           933:                                x_prefetch = NULL;
        !           934:                                x_get_ilong = get_ilong_cache_040;
        !           935:                                x_get_iword = get_iword_cache_040;
        !           936:                                x_get_ibyte = NULL;
        !           937:                                x_next_iword = next_iword_cache040;
        !           938:                                x_next_ilong = next_ilong_cache040;
        !           939:                                x_put_long = put_long_cache_040;
        !           940:                                x_put_word = put_word_cache_040;
        !           941:                                x_put_byte = put_byte_cache_040;
        !           942:                                x_get_long = get_long_cache_040;
        !           943:                                x_get_word = get_word_cache_040;
        !           944:                                x_get_byte = get_byte_cache_040;
        !           945:                                x_do_cycles = do_cycles;
        !           946:                                x_do_cycles_pre = do_cycles;
        !           947:                                x_do_cycles_post = do_cycles_post;
        !           948:                        }
        !           949:                } else {
        !           950:                        x_prefetch = NULL;
        !           951:                        set_x_ifetches();
        !           952:                        x_put_long = put_long;
        !           953:                        x_put_word = put_word;
        !           954:                        x_put_byte = put_byte;
        !           955:                        x_get_long = get_long;
        !           956:                        x_get_word = get_word;
        !           957:                        x_get_byte = get_byte;
        !           958:                        x_do_cycles = do_cycles;
        !           959:                        x_do_cycles_pre = do_cycles;
        !           960:                        x_do_cycles_post = do_cycles_post;
        !           961:                }
        !           962:                // 68020+ cycle exact
1.1.1.4   root      963:        } else if (currprefs.cpu_model == 68020) {
                    964:                x_prefetch = get_word_ce020_prefetch;
1.1.1.7 ! root      965:                x_get_ilong = get_long_ce020_prefetch;
        !           966:                x_get_iword = get_word_ce020_prefetch;
        !           967:                x_get_ibyte = NULL;
1.1.1.4   root      968:                x_next_iword = next_iword_020ce;
                    969:                x_next_ilong = next_ilong_020ce;
                    970:                x_put_long = put_long_ce020;
                    971:                x_put_word = put_word_ce020;
                    972:                x_put_byte = put_byte_ce020;
                    973:                x_get_long = get_long_ce020;
                    974:                x_get_word = get_word_ce020;
                    975:                x_get_byte = get_byte_ce020;
1.1.1.7 ! root      976: #ifndef WINUAE_FOR_HATARI
        !           977:                x_do_cycles = do_cycles_ce020;
        !           978:                x_do_cycles_pre = do_cycles_ce020;
        !           979:                x_do_cycles_post = do_cycles_ce020_post;
        !           980: #else
        !           981:                x_do_cycles = do_cycles_ce020_long;
        !           982:                x_do_cycles_pre = do_cycles_ce020_long;
        !           983:                x_do_cycles_post = do_cycles_ce020_post;
        !           984: #endif
        !           985:        } else if (currprefs.cpu_model == 68030) {
1.1.1.4   root      986:                x_prefetch = get_word_ce030_prefetch;
1.1.1.7 ! root      987:                x_get_ilong = get_long_ce030_prefetch;
        !           988:                x_get_iword = get_word_ce030_prefetch;
        !           989:                x_get_ibyte = NULL;
1.1.1.4   root      990:                x_next_iword = next_iword_030ce;
                    991:                x_next_ilong = next_ilong_030ce;
                    992:                x_put_long = put_long_ce030;
                    993:                x_put_word = put_word_ce030;
                    994:                x_put_byte = put_byte_ce030;
                    995:                x_get_long = get_long_ce030;
                    996:                x_get_word = get_word_ce030;
                    997:                x_get_byte = get_byte_ce030;
1.1.1.7 ! root      998: #ifndef WINUAE_FOR_HATARI
        !           999:                x_do_cycles = do_cycles_ce020;
        !          1000:                x_do_cycles_pre = do_cycles_ce020;
        !          1001:                x_do_cycles_post = do_cycles_ce020_post;
        !          1002: #else
        !          1003:                x_do_cycles = do_cycles_ce020_long;
        !          1004:                x_do_cycles_pre = do_cycles_ce020_long;
        !          1005:                x_do_cycles_post = do_cycles_ce020_post;
        !          1006: #endif
        !          1007:        } else if (currprefs.cpu_model >= 68040) {
        !          1008:                x_prefetch = NULL;
        !          1009:                x_get_ilong = get_ilong_cache_040;
        !          1010:                x_get_iword = get_iword_cache_040;
        !          1011:                x_get_ibyte = NULL;
        !          1012:                x_next_iword = next_iword_cache040;
        !          1013:                x_next_ilong = next_ilong_cache040;
        !          1014:                x_put_long = put_long_cache_040;
        !          1015:                x_put_word = put_word_cache_040;
        !          1016:                x_put_byte = put_byte_cache_040;
        !          1017:                x_get_long = get_long_cache_040;
        !          1018:                x_get_word = get_word_cache_040;
        !          1019:                x_get_byte = get_byte_cache_040;
        !          1020: #ifndef WINUAE_FOR_HATARI
        !          1021:                x_do_cycles = do_cycles_ce020;
        !          1022:                x_do_cycles_pre = do_cycles_ce020;
        !          1023:                x_do_cycles_post = do_cycles_ce020_post;
        !          1024: #else
        !          1025:                x_do_cycles = do_cycles_ce020_long;
        !          1026:                x_do_cycles_pre = do_cycles_ce020_long;
        !          1027:                x_do_cycles_post = do_cycles_ce020_post;
        !          1028: #endif
        !          1029:        }
        !          1030:        x2_prefetch = x_prefetch;
        !          1031:        x2_get_ilong = x_get_ilong;
        !          1032:        x2_get_iword = x_get_iword;
        !          1033:        x2_get_ibyte = x_get_ibyte;
        !          1034:        x2_next_iword = x_next_iword;
        !          1035:        x2_next_ilong = x_next_ilong;
        !          1036:        x2_put_long = x_put_long;
        !          1037:        x2_put_word = x_put_word;
        !          1038:        x2_put_byte = x_put_byte;
        !          1039:        x2_get_long = x_get_long;
        !          1040:        x2_get_word = x_get_word;
        !          1041:        x2_get_byte = x_get_byte;
        !          1042:        x2_do_cycles = x_do_cycles;
        !          1043:        x2_do_cycles_pre = x_do_cycles_pre;
        !          1044:        x2_do_cycles_post = x_do_cycles_post;
        !          1045: 
        !          1046:        if (cpu_tracer > 0) {
        !          1047:                x_prefetch = cputracefunc_x_prefetch;
        !          1048:                x_get_ilong = cputracefunc_x_get_ilong;
        !          1049:                x_get_iword = cputracefunc_x_get_iword;
        !          1050:                x_get_ibyte = cputracefunc_x_get_ibyte;
        !          1051:                x_next_iword = cputracefunc_x_next_iword;
        !          1052:                x_next_ilong = cputracefunc_x_next_ilong;
        !          1053:                x_put_long = cputracefunc_x_put_long;
        !          1054:                x_put_word = cputracefunc_x_put_word;
        !          1055:                x_put_byte = cputracefunc_x_put_byte;
        !          1056:                x_get_long = cputracefunc_x_get_long;
        !          1057:                x_get_word = cputracefunc_x_get_word;
        !          1058:                x_get_byte = cputracefunc_x_get_byte;
        !          1059:                x_do_cycles = cputracefunc_x_do_cycles;
        !          1060:                x_do_cycles_pre = cputracefunc_x_do_cycles_pre;
        !          1061:                x_do_cycles_post = cputracefunc_x_do_cycles_post;
        !          1062:        } else if (cpu_tracer < 0) {
        !          1063:                if (!check_trace ()) {
        !          1064:                        x_prefetch = cputracefunc2_x_prefetch;
        !          1065:                        x_get_ilong = cputracefunc2_x_get_ilong;
        !          1066:                        x_get_iword = cputracefunc2_x_get_iword;
        !          1067:                        x_get_ibyte = cputracefunc2_x_get_ibyte;
        !          1068:                        x_next_iword = cputracefunc2_x_next_iword;
        !          1069:                        x_next_ilong = cputracefunc2_x_next_ilong;
        !          1070:                        x_put_long = cputracefunc2_x_put_long;
        !          1071:                        x_put_word = cputracefunc2_x_put_word;
        !          1072:                        x_put_byte = cputracefunc2_x_put_byte;
        !          1073:                        x_get_long = cputracefunc2_x_get_long;
        !          1074:                        x_get_word = cputracefunc2_x_get_word;
        !          1075:                        x_get_byte = cputracefunc2_x_get_byte;
        !          1076:                        x_do_cycles = cputracefunc2_x_do_cycles;
        !          1077:                        x_do_cycles_pre = cputracefunc2_x_do_cycles_pre;
        !          1078:                        x_do_cycles_post = cputracefunc2_x_do_cycles_post;
        !          1079:                }
        !          1080:        }
        !          1081: 
        !          1082:        set_x_cp_funcs();
        !          1083:        mmu_set_funcs();
        !          1084:        mmu030_set_funcs();
        !          1085: 
        !          1086: }
        !          1087: 
        !          1088: bool can_cpu_tracer (void)
        !          1089: {
        !          1090:        return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_cycle_exact;
        !          1091: }
        !          1092: 
        !          1093: bool is_cpu_tracer (void)
        !          1094: {
        !          1095:        return cpu_tracer > 0;
        !          1096: }
        !          1097: bool set_cpu_tracer (bool state)
        !          1098: {
        !          1099:        if (cpu_tracer < 0)
        !          1100:                return false;
        !          1101:        int old = cpu_tracer;
        !          1102: #ifndef WINUAE_FOR_HATARI
        !          1103:        if (input_record)
        !          1104:                state = true;
        !          1105: #endif
        !          1106:        cpu_tracer = 0;
        !          1107:        if (state && can_cpu_tracer ()) {
        !          1108:                cpu_tracer = 1;
        !          1109:                set_x_funcs ();
        !          1110:                if (old != cpu_tracer)
        !          1111:                        write_log (_T("CPU tracer enabled\n"));
1.1.1.4   root     1112:        }
1.1.1.7 ! root     1113:        if (old > 0 && state == false) {
        !          1114:                set_x_funcs ();
        !          1115:                write_log (_T("CPU tracer disabled\n"));
        !          1116:        }
        !          1117:        return is_cpu_tracer ();
1.1.1.4   root     1118: }
                   1119: 
1.1.1.7 ! root     1120: void flush_cpu_caches(bool force)
1.1.1.4   root     1121: {
1.1.1.7 ! root     1122:        bool doflush = currprefs.cpu_compatible || currprefs.cpu_cycle_exact;
1.1.1.4   root     1123:        int i;
                   1124: 
                   1125:        if (currprefs.cpu_model == 68020) {
                   1126:                if (regs.cacr & 0x08) { // clear instr cache
                   1127:                        for (i = 0; i < CACHELINES020; i++)
                   1128:                                caches020[i].valid = 0;
1.1.1.7 ! root     1129:                        regs.cacr &= ~0x08;
1.1.1.4   root     1130:                }
                   1131:                if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7 ! root     1132:                        caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
1.1.1.4   root     1133:                        regs.cacr &= ~0x04;
                   1134:                }
                   1135:        } else if (currprefs.cpu_model == 68030) {
                   1136:                if (regs.cacr & 0x08) { // clear instr cache
1.1.1.7 ! root     1137:                        if (doflush) {
        !          1138:                                for (i = 0; i < CACHELINES030; i++) {
        !          1139:                                        icaches030[i].valid[0] = 0;
        !          1140:                                        icaches030[i].valid[1] = 0;
        !          1141:                                        icaches030[i].valid[2] = 0;
        !          1142:                                        icaches030[i].valid[3] = 0;
        !          1143:                                }
1.1.1.4   root     1144:                        }
1.1.1.7 ! root     1145:                        regs.cacr &= ~0x08;
1.1.1.4   root     1146:                }
                   1147:                if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7 ! root     1148:                        icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4   root     1149:                        regs.cacr &= ~0x04;
                   1150:                }
                   1151:                if (regs.cacr & 0x800) { // clear data cache
1.1.1.7 ! root     1152:                        if (doflush) {
        !          1153:                                for (i = 0; i < CACHELINES030; i++) {
        !          1154:                                        dcaches030[i].valid[0] = 0;
        !          1155:                                        dcaches030[i].valid[1] = 0;
        !          1156:                                        dcaches030[i].valid[2] = 0;
        !          1157:                                        dcaches030[i].valid[3] = 0;
        !          1158:                                }
1.1.1.4   root     1159:                        }
                   1160:                        regs.cacr &= ~0x800;
                   1161:                }
                   1162:                if (regs.cacr & 0x400) { // clear entry in data cache
1.1.1.7 ! root     1163:                        dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4   root     1164:                        regs.cacr &= ~0x400;
                   1165:                }
1.1.1.7 ! root     1166:        } else if (currprefs.cpu_model >= 68040) {
        !          1167:                icachelinecnt = 0;
        !          1168:                dcachelinecnt = 0;
        !          1169:                if (doflush) {
1.1.1.4   root     1170:                        for (i = 0; i < CACHESETS040; i++) {
1.1.1.7 ! root     1171:                                icaches040[i].valid[0] = 0;
        !          1172:                                icaches040[i].valid[1] = 0;
        !          1173:                                icaches040[i].valid[2] = 0;
        !          1174:                                icaches040[i].valid[3] = 0;
1.1.1.4   root     1175:                        }
                   1176:                }
                   1177:        }
                   1178: }
                   1179: 
1.1.1.7 ! root     1180: void flush_cpu_caches_040(uae_u16 opcode)
1.1.1.4   root     1181: {
1.1.1.7 ! root     1182:        int cache = (opcode >> 6) & 3;
        !          1183:        if (!(cache & 2))
        !          1184:                        return;
        !          1185:        flush_cpu_caches(true);
1.1.1.4   root     1186: }
                   1187: 
1.1.1.7 ! root     1188: void set_cpu_caches (bool flush)
1.1.1.4   root     1189: {
1.1.1.7 ! root     1190:        regs.prefetch020addr = 0xffffffff;
        !          1191:        regs.cacheholdingaddr020 = 0xffffffff;
1.1.1.4   root     1192: 
1.1.1.7 ! root     1193: #ifdef JIT
        !          1194:        if (currprefs.cachesize) {
        !          1195:                if (currprefs.cpu_model < 68040) {
        !          1196:                        set_cache_state (regs.cacr & 1);
        !          1197:                        if (regs.cacr & 0x08) {
        !          1198:                                flush_icache (0, 3);
        !          1199:                        }
        !          1200:                } else {
        !          1201:                        set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
        !          1202:                }
        !          1203:        }
        !          1204: #endif
        !          1205:        flush_cpu_caches(flush);
        !          1206: }
        !          1207: 
        !          1208: STATIC_INLINE void count_instr (unsigned int opcode)
        !          1209: {
        !          1210: }
        !          1211: 
        !          1212: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
        !          1213: {
        !          1214:        op_illg (opcode);
        !          1215:        return 4;
        !          1216: }
        !          1217: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
        !          1218: {
        !          1219:        if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
        !          1220:                op_illg (opcode);
        !          1221:        else
        !          1222:                op_unimpl (opcode);
        !          1223:        return 4;
        !          1224: }
        !          1225: 
        !          1226: // generic+direct, generic+indirect, more compatible, cycle-exact, mmu
        !          1227: static const struct cputbl *cputbls[6][5] =
        !          1228: {
        !          1229:        // 68000
        !          1230:        { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL },
        !          1231:        // 68010
        !          1232:        { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL },
        !          1233:        // 68020
        !          1234:        { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL },
        !          1235:        // 68030
        !          1236:        { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff },
        !          1237:        // 68040
        !          1238:        { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff },
        !          1239:        // 68060
        !          1240:        { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff }
        !          1241: };
        !          1242: 
        !          1243: static void build_cpufunctbl (void)
1.1.1.4   root     1244: {
                   1245:        int i, opcnt;
                   1246:        unsigned long opcode;
                   1247:        const struct cputbl *tbl = 0;
1.1.1.7 ! root     1248:        int lvl, mode;
1.1.1.4   root     1249: 
1.1.1.7 ! root     1250:        if (!currprefs.cachesize) {
1.1.1.5   root     1251:                if (currprefs.mmu_model)
1.1.1.7 ! root     1252:                        mode = 4;
        !          1253:                else if (currprefs.cpu_cycle_exact)
        !          1254:                        mode = 3;
        !          1255:                else if (currprefs.cpu_compatible)
        !          1256:                        mode = 2;
        !          1257:                else
        !          1258:                        mode = 0;
        !          1259:                m68k_pc_indirect = mode != 0 ? 1 : 0;
        !          1260:        } else {
        !          1261:                mode = 0;
        !          1262:                m68k_pc_indirect = 0;
        !          1263:                if (currprefs.comptrustbyte) {
        !          1264:                        mode = 1;
        !          1265:                        m68k_pc_indirect = -1;
        !          1266:                }
1.1.1.4   root     1267:        }
1.1.1.7 ! root     1268:        lvl = (currprefs.cpu_model - 68000) / 10;
        !          1269:        if (lvl == 6)
        !          1270:                lvl = 5;
        !          1271:        tbl = cputbls[lvl][mode];
1.1.1.4   root     1272: 
1.1.1.7 ! root     1273:        if (tbl == NULL) {
        !          1274:                write_log (_T("no CPU emulation cores available CPU=%d!"), currprefs.cpu_model);
1.1.1.4   root     1275:                abort ();
                   1276:        }
                   1277: 
                   1278:        for (opcode = 0; opcode < 65536; opcode++)
                   1279:                cpufunctbl[opcode] = op_illg_1;
                   1280:        for (i = 0; tbl[i].handler != NULL; i++) {
                   1281:                opcode = tbl[i].opcode;
                   1282:                cpufunctbl[opcode] = tbl[i].handler;
1.1.1.7 ! root     1283:                cpudatatbl[opcode].length = tbl[i].length;
        !          1284:                cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
        !          1285:                cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
        !          1286:                cpudatatbl[opcode].branch = tbl[i].branch;
1.1.1.4   root     1287:        }
                   1288: 
                   1289:        /* hack fpu to 68000/68010 mode */
                   1290:        if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                   1291:                tbl = op_smalltbl_3_ff;
                   1292:                for (i = 0; tbl[i].handler != NULL; i++) {
1.1.1.7 ! root     1293:                        if ((tbl[i].opcode & 0xfe00) == 0xf200) {
1.1.1.4   root     1294:                                cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1.1.1.7 ! root     1295:                                cpudatatbl[tbl[i].opcode].length = tbl[i].length;
        !          1296:                                cpudatatbl[tbl[i].opcode].disp020[0] = tbl[i].disp020[0];
        !          1297:                                cpudatatbl[tbl[i].opcode].disp020[1] = tbl[i].disp020[1];
        !          1298:                                cpudatatbl[tbl[i].opcode].branch = tbl[i].branch;
        !          1299:                        }
1.1.1.4   root     1300:                }
                   1301:        }
1.1.1.7 ! root     1302: 
1.1.1.4   root     1303:        opcnt = 0;
                   1304:        for (opcode = 0; opcode < 65536; opcode++) {
                   1305:                cpuop_func *f;
1.1.1.7 ! root     1306:                struct instr *table = &table68k[opcode];
        !          1307: 
        !          1308:                if (table->mnemo == i_ILLG)
        !          1309:                        continue;               
        !          1310: 
        !          1311:                /* unimplemented opcode? */
        !          1312:                if (table->unimpclev > 0 && lvl >= table->unimpclev) {
        !          1313:                        if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
        !          1314:                                cpufunctbl[opcode] = op_unimpl_1;
        !          1315:                                continue;
        !          1316:                        } else {
        !          1317:                                // emulate 68060 unimplemented instructions if int_no_unimplemented=false
        !          1318:                                if (currprefs.cpu_model != 68060 && table->unimpclev != 5) {
        !          1319:                                        cpufunctbl[opcode] = op_illg_1;
        !          1320:                                        continue;
        !          1321:                                }
        !          1322:                        }
        !          1323:                }
1.1.1.4   root     1324: 
                   1325:                if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                   1326:                        /* more hack fpu to 68000/68010 mode */
1.1.1.7 ! root     1327:                        if (table->clev > lvl && (opcode & 0xfe00) != 0xf200)
1.1.1.4   root     1328:                                continue;
1.1.1.7 ! root     1329:                } else if (table->clev > lvl) {
1.1.1.4   root     1330:                        continue;
                   1331:                }
                   1332: 
1.1.1.7 ! root     1333:                if (table->handler != -1) {
        !          1334:                        int idx = table->handler;
1.1.1.4   root     1335:                        f = cpufunctbl[idx];
                   1336:                        if (f == op_illg_1)
                   1337:                                abort ();
                   1338:                        cpufunctbl[opcode] = f;
1.1.1.7 ! root     1339:                        memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
1.1.1.4   root     1340:                        opcnt++;
                   1341:                }
                   1342:        }
1.1.1.7 ! root     1343:        write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
1.1.1.4   root     1344:                opcnt, lvl,
                   1345:                currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24);
                   1346: #ifdef JIT
                   1347:        build_comp ();
                   1348: #endif
1.1.1.7 ! root     1349: 
        !          1350:        write_log(_T("CPU=%d, FPU=%d, MMU=%d, JIT%s=%d."),
        !          1351:                          currprefs.cpu_model, currprefs.fpu_model,
        !          1352:                          currprefs.mmu_model,
        !          1353:                          currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
        !          1354:                          currprefs.cachesize);
        !          1355: 
        !          1356:        regs.address_space_mask = 0xffffffff;
        !          1357: #ifndef WINUAE_FOR_HATARI
        !          1358:        if (currprefs.cpu_compatible) {
        !          1359:                if (currprefs.address_space_24 && currprefs.cpu_model >= 68040)
        !          1360:                        currprefs.address_space_24 = false;
        !          1361:        }
        !          1362: #else
        !          1363:        /* Hatari : don't force address_space_24=0 for 68030, as the Falcon has a 68030 LC with only 24 bits */
        !          1364:        /* TODO ? Force address_space_24=0 for 68040 ? */
        !          1365: #endif
        !          1366:        m68k_interrupt_delay = false;
        !          1367:        if (currprefs.cpu_cycle_exact) {
        !          1368:                if (tbl == op_smalltbl_14_ff || tbl == op_smalltbl_13_ff || tbl == op_smalltbl_21_ff || tbl == op_smalltbl_23_ff)
        !          1369:                        m68k_interrupt_delay = true;
        !          1370:        }
        !          1371: 
        !          1372:        if (currprefs.cpu_cycle_exact) {
        !          1373:                if (currprefs.cpu_model == 68000)
        !          1374:                        write_log(_T(" prefetch and cycle-exact"));
        !          1375:                else
        !          1376:                        write_log(_T(" ~cycle-exact"));
        !          1377:        } else if (currprefs.cpu_compatible) {
        !          1378:                if (currprefs.cpu_model <= 68020) {
        !          1379:                        write_log(_T(" prefetch"));
        !          1380:                } else {
        !          1381:                        write_log(_T(" fake prefetch"));
1.1.1.5   root     1382:                }
1.1.1.4   root     1383:        }
1.1.1.7 ! root     1384:        if (currprefs.m68k_speed < 0)
        !          1385:                write_log(_T(" fast"));
        !          1386:        if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
        !          1387:                write_log(_T(" no unimplemented integer instructions"));
        !          1388:        }
        !          1389:        if (currprefs.fpu_no_unimplemented && currprefs.fpu_model) {
        !          1390:                write_log(_T(" no unimplemented floating point instructions"));
        !          1391:        }
        !          1392:        if (currprefs.address_space_24) {
        !          1393:                regs.address_space_mask = 0x00ffffff;
        !          1394:                write_log(_T(" 24-bit"));
        !          1395:        }
        !          1396:        write_log(_T("\n"));
1.1.1.4   root     1397: 
1.1.1.7 ! root     1398:        set_cpu_caches (true);
1.1.1.4   root     1399: }
                   1400: 
1.1.1.7 ! root     1401: #define CYCLES_DIV 8192
        !          1402: static unsigned long cycles_mult;
1.1.1.4   root     1403: 
                   1404: static void update_68k_cycles (void)
                   1405: {
1.1.1.7 ! root     1406: fprintf ( stderr , "update cyc speed %d throttle %f clock_mult %d\n", currprefs.m68k_speed, currprefs.m68k_speed_throttle, changed_prefs.cpu_clock_multiplier );
        !          1407:        cycles_mult = 0;
        !          1408: #ifndef WINUAE_FOR_HATARI
        !          1409:        /* [NP] Don't adjust cycles_mult in Hatari and ignore m68k_speed (forced to 0) */
        !          1410:        if (currprefs.m68k_speed >= 0 && !currprefs.cpu_cycle_exact) {
        !          1411:                if (currprefs.m68k_speed_throttle < 0) {
        !          1412:                        cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
        !          1413:                } else if (currprefs.m68k_speed_throttle > 0) {
        !          1414:                        cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
        !          1415:                }
        !          1416:        }
        !          1417:        if (currprefs.m68k_speed == 0) {
        !          1418:                if (currprefs.cpu_model >= 68040) {
        !          1419:                        if (!cycles_mult)
        !          1420:                                cycles_mult = CYCLES_DIV / 8;
        !          1421:                        else
        !          1422:                                cycles_mult /= 8;
        !          1423:                } else if (currprefs.cpu_model >= 68020) {
        !          1424:                        if (!cycles_mult)
        !          1425:                                cycles_mult = CYCLES_DIV / 4;
        !          1426:                        else
        !          1427:                                cycles_mult /= 4;
        !          1428:                }
1.1.1.4   root     1429:        }
1.1.1.7 ! root     1430: #endif
        !          1431: 
1.1.1.4   root     1432:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
                   1433:        currprefs.cpu_frequency = changed_prefs.cpu_frequency;
                   1434: 
1.1.1.7 ! root     1435: #ifndef WINUAE_FOR_HATARI
        !          1436:        baseclock = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) * 8;
        !          1437: #endif
1.1.1.4   root     1438:        cpucycleunit = CYCLE_UNIT / 2;
                   1439:        if (currprefs.cpu_clock_multiplier) {
                   1440:                if (currprefs.cpu_clock_multiplier >= 256) {
                   1441:                        cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
                   1442:                } else {
                   1443:                        cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
                   1444:                }
1.1.1.7 ! root     1445:                if (currprefs.cpu_model >= 68040)
        !          1446:                        cpucycleunit /= 2;
        !          1447: #ifndef WINUAE_FOR_HATARI              /* [NP] TODO : handle any cpu frequency, not just mulltiplier ? */
1.1.1.4   root     1448:        } else if (currprefs.cpu_frequency) {
                   1449:                cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
1.1.1.7 ! root     1450: #endif
        !          1451:        } else if (currprefs.cpu_cycle_exact && currprefs.cpu_clock_multiplier == 0) {
        !          1452:                if (currprefs.cpu_model >= 68040) {
        !          1453:                        cpucycleunit = CYCLE_UNIT / 16;
        !          1454:                } if (currprefs.cpu_model == 68030) {
        !          1455:                        cpucycleunit = CYCLE_UNIT / 8;
        !          1456:                } else if (currprefs.cpu_model == 68020) {
        !          1457:                        cpucycleunit = CYCLE_UNIT / 4;
        !          1458:                } else {
        !          1459:                        cpucycleunit = CYCLE_UNIT / 2;
        !          1460:                }
1.1.1.4   root     1461:        }
                   1462:        if (cpucycleunit < 1)
                   1463:                cpucycleunit = 1;
                   1464:        if (currprefs.cpu_cycle_exact)
1.1.1.7 ! root     1465:                write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
        !          1466: write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
        !          1467: #ifndef WINUAE_FOR_HATARI
        !          1468:        set_config_changed ();
        !          1469: #endif
1.1.1.4   root     1470: }
                   1471: 
                   1472: static void prefs_changed_cpu (void)
                   1473: {
                   1474:        fixup_cpu (&changed_prefs);
                   1475:        currprefs.cpu_model = changed_prefs.cpu_model;
                   1476:        currprefs.fpu_model = changed_prefs.fpu_model;
                   1477:        currprefs.mmu_model = changed_prefs.mmu_model;
                   1478:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                   1479:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1.1.1.7 ! root     1480:        currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented;
        !          1481:        currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented;
        !          1482:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
1.1.1.4   root     1483: }
                   1484: 
1.1.1.7 ! root     1485: static int check_prefs_changed_cpu2(void)
1.1.1.4   root     1486: {
1.1.1.7 ! root     1487:        int changed = 0;
1.1.1.4   root     1488: 
                   1489: #ifdef JIT
1.1.1.7 ! root     1490:        changed = check_prefs_changed_comp() ? 1 : 0;
1.1.1.4   root     1491: #endif
                   1492:        if (changed
                   1493:                || currprefs.cpu_model != changed_prefs.cpu_model
                   1494:                || currprefs.fpu_model != changed_prefs.fpu_model
                   1495:                || currprefs.mmu_model != changed_prefs.mmu_model
1.1.1.7 ! root     1496:                || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
        !          1497:                || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
1.1.1.4   root     1498:                || currprefs.cpu_compatible != changed_prefs.cpu_compatible
                   1499:                || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) {
1.1.1.7 ! root     1500:                        cpu_prefs_changed_flag |= 1;
        !          1501: #ifdef WINUAE_FOR_HATARI
        !          1502:                        /* When changing CPU prefs in Hatari we reset the emulation, */
        !          1503:                        /* so new cpu table should be built now, not in m68k_go() */
        !          1504: //                     uaecptr pc = m68k_getpc();
        !          1505:                        prefs_changed_cpu();
        !          1506:                        build_cpufunctbl();
        !          1507: // done in m68k_go :
        !          1508: //                     m68k_setpc_normal(pc);
        !          1509: //                     fill_prefetch();
        !          1510: #endif
1.1.1.4   root     1511:        }
                   1512:        if (changed
                   1513:                || currprefs.m68k_speed != changed_prefs.m68k_speed
1.1.1.7 ! root     1514:                || currprefs.m68k_speed_throttle != changed_prefs.m68k_speed_throttle
1.1.1.4   root     1515:                || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
1.1.1.7 ! root     1516:                || currprefs.reset_delay != changed_prefs.reset_delay
1.1.1.4   root     1517:                || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
1.1.1.7 ! root     1518:                        cpu_prefs_changed_flag |= 2;
1.1.1.4   root     1519:        }
1.1.1.7 ! root     1520:        return cpu_prefs_changed_flag;
        !          1521: }
1.1.1.4   root     1522: 
1.1.1.7 ! root     1523: void check_prefs_changed_cpu(void)
        !          1524: {
        !          1525: #ifndef WINUAE_FOR_HATARI
        !          1526:        return;                         /* [NP] TODO : handle cpu change on the fly ? */
        !          1527:        if (!config_changed)
        !          1528:                return;
        !          1529: #else
1.1.1.4   root     1530: 
1.1.1.7 ! root     1531:        currprefs.cpu_idle = changed_prefs.cpu_idle;
        !          1532:        currprefs.ppc_cpu_idle = changed_prefs.ppc_cpu_idle;
        !          1533:        currprefs.reset_delay = changed_prefs.reset_delay;
        !          1534: 
        !          1535:        if (check_prefs_changed_cpu2()) {
        !          1536:                set_special(SPCFLAG_MODE_CHANGE);
        !          1537:                reset_frame_rate_hack();
        !          1538:        }
        !          1539: #endif
1.1.1.4   root     1540: }
                   1541: 
                   1542: void init_m68k (void)
                   1543: {
                   1544:        int i;
                   1545: 
                   1546:        prefs_changed_cpu ();
                   1547:        update_68k_cycles ();
                   1548: 
                   1549:        for (i = 0 ; i < 256 ; i++) {
                   1550:                int j;
                   1551:                for (j = 0 ; j < 8 ; j++) {
                   1552:                        if (i & (1 << j)) break;
                   1553:                }
                   1554:                movem_index1[i] = j;
1.1.1.7 ! root     1555:                movem_index2[i] = 7 - j;
1.1.1.4   root     1556:                movem_next[i] = i & (~(1 << j));
                   1557:        }
                   1558: 
                   1559: #if COUNT_INSTRS
                   1560:        {
                   1561:                FILE *f = fopen (icountfilename (), "r");
                   1562:                memset (instrcount, 0, sizeof instrcount);
                   1563:                if (f) {
                   1564:                        uae_u32 opcode, count, total;
                   1565:                        TCHAR name[20];
1.1.1.7 ! root     1566:                        write_log (_T("Reading instruction count file...\n"));
1.1.1.4   root     1567:                        fscanf (f, "Total: %lu\n", &total);
1.1.1.7 ! root     1568:                        while (fscanf (f, "%x: %lu %s\n", &opcode, &count, name) == 3) {
1.1.1.4   root     1569:                                instrcount[opcode] = count;
                   1570:                        }
                   1571:                        fclose (f);
                   1572:                }
                   1573:        }
                   1574: #endif
                   1575: 
                   1576:        read_table68k ();
                   1577:        do_merges ();
                   1578: 
1.1.1.7 ! root     1579:        write_log (_T("%d CPU functions\n"), nr_cpuop_funcs);
1.1.1.4   root     1580: 
                   1581:        build_cpufunctbl ();
                   1582:        set_x_funcs ();
                   1583: 
                   1584: #ifdef JIT
                   1585:        /* We need to check whether NATMEM settings have changed
                   1586:        * before starting the CPU */
                   1587:        check_prefs_changed_comp ();
                   1588: #endif
                   1589: }
                   1590: 
                   1591: struct regstruct regs, mmu_backup_regs;
                   1592: struct flag_struct regflags;
1.1.1.7 ! root     1593: static int m68kpc_offset;
1.1.1.4   root     1594: 
1.1.1.7 ! root     1595: #if 0
1.1.1.4   root     1596: #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
                   1597: #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
                   1598: #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1.1.1.7 ! root     1599: #endif
1.1.1.4   root     1600: 
1.1.1.7 ! root     1601: static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
1.1.1.4   root     1602: {
                   1603:        uae_u16 dp;
                   1604:        uae_s8 disp8;
                   1605:        uae_s16 disp16;
                   1606:        int r;
                   1607:        uae_u32 dispreg;
1.1.1.7 ! root     1608:        uaecptr addr = pc;
1.1.1.4   root     1609:        uae_s32 offset = 0;
                   1610:        TCHAR buffer[80];
                   1611: 
                   1612:        switch (mode){
                   1613:        case Dreg:
1.1.1.7 ! root     1614:                _stprintf (buffer, _T("D%d"), reg);
1.1.1.4   root     1615:                break;
                   1616:        case Areg:
1.1.1.7 ! root     1617:                _stprintf (buffer, _T("A%d"), reg);
1.1.1.4   root     1618:                break;
                   1619:        case Aind:
1.1.1.7 ! root     1620:                _stprintf (buffer, _T("(A%d)"), reg);
1.1.1.4   root     1621:                addr = regs.regs[reg + 8];
                   1622:                break;
                   1623:        case Aipi:
1.1.1.7 ! root     1624:                _stprintf (buffer, _T("(A%d)+"), reg);
1.1.1.4   root     1625:                addr = regs.regs[reg + 8];
                   1626:                break;
                   1627:        case Apdi:
1.1.1.7 ! root     1628:                _stprintf (buffer, _T("-(A%d)"), reg);
1.1.1.4   root     1629:                addr = regs.regs[reg + 8];
                   1630:                break;
                   1631:        case Ad16:
                   1632:                {
                   1633:                        TCHAR offtxt[80];
1.1.1.7 ! root     1634:                        disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4   root     1635:                        if (disp16 < 0)
1.1.1.7 ! root     1636:                                _stprintf (offtxt, _T("-$%04x"), -disp16);
1.1.1.4   root     1637:                        else
1.1.1.7 ! root     1638:                                _stprintf (offtxt, _T("$%04x"), disp16);
1.1.1.4   root     1639:                        addr = m68k_areg (regs, reg) + disp16;
1.1.1.7 ! root     1640:                        _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr);
1.1.1.4   root     1641:                }
                   1642:                break;
                   1643:        case Ad8r:
1.1.1.7 ! root     1644:                dp = get_iword_debug (pc); pc += 2;
1.1.1.4   root     1645:                disp8 = dp & 0xFF;
                   1646:                r = (dp & 0x7000) >> 12;
                   1647:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   1648:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   1649:                dispreg <<= (dp >> 9) & 3;
                   1650: 
                   1651:                if (dp & 0x100) {
                   1652:                        uae_s32 outer = 0, disp = 0;
                   1653:                        uae_s32 base = m68k_areg (regs, reg);
                   1654:                        TCHAR name[10];
1.1.1.7 ! root     1655:                        _stprintf (name, _T("A%d, "), reg);
1.1.1.4   root     1656:                        if (dp & 0x80) { base = 0; name[0] = 0; }
                   1657:                        if (dp & 0x40) dispreg = 0;
1.1.1.7 ! root     1658:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
        !          1659:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     1660:                        base += disp;
                   1661: 
1.1.1.7 ! root     1662:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
        !          1663:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     1664: 
                   1665:                        if (!(dp & 4)) base += dispreg;
1.1.1.7 ! root     1666:                        if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1.1.1.4   root     1667:                        if (dp & 4) base += dispreg;
                   1668: 
                   1669:                        addr = base + outer;
1.1.1.7 ! root     1670:                        _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1.1.1.4   root     1671:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                   1672:                                1 << ((dp >> 9) & 3),
1.1.1.7 ! root     1673:                                disp, outer, addr);
1.1.1.4   root     1674:                } else {
                   1675:                        addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.7 ! root     1676:                        _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg,
1.1.1.4   root     1677:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1.1.1.7 ! root     1678:                                1 << ((dp >> 9) & 3), disp8, addr);
1.1.1.4   root     1679:                }
                   1680:                break;
                   1681:        case PC16:
1.1.1.7 ! root     1682:                disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4   root     1683:                addr += (uae_s16)disp16;
1.1.1.7 ! root     1684:                _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
1.1.1.4   root     1685:                break;
                   1686:        case PC8r:
1.1.1.7 ! root     1687:                dp = get_iword_debug (pc); pc += 2;
1.1.1.4   root     1688:                disp8 = dp & 0xFF;
                   1689:                r = (dp & 0x7000) >> 12;
                   1690:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   1691:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   1692:                dispreg <<= (dp >> 9) & 3;
                   1693: 
                   1694:                if (dp & 0x100) {
                   1695:                        uae_s32 outer = 0, disp = 0;
                   1696:                        uae_s32 base = addr;
                   1697:                        TCHAR name[10];
1.1.1.7 ! root     1698:                        _stprintf (name, _T("PC, "));
1.1.1.4   root     1699:                        if (dp & 0x80) { base = 0; name[0] = 0; }
                   1700:                        if (dp & 0x40) dispreg = 0;
1.1.1.7 ! root     1701:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
        !          1702:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     1703:                        base += disp;
                   1704: 
1.1.1.7 ! root     1705:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
        !          1706:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     1707: 
                   1708:                        if (!(dp & 4)) base += dispreg;
1.1.1.7 ! root     1709:                        if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1.1.1.4   root     1710:                        if (dp & 4) base += dispreg;
                   1711: 
                   1712:                        addr = base + outer;
1.1.1.7 ! root     1713:                        _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1.1.1.4   root     1714:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                   1715:                                1 << ((dp >> 9) & 3),
1.1.1.7 ! root     1716:                                disp, outer, addr);
1.1.1.4   root     1717:                } else {
                   1718:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.7 ! root     1719:                        _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D',
1.1.1.4   root     1720:                                (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
1.1.1.7 ! root     1721:                                disp8, addr);
1.1.1.4   root     1722:                }
                   1723:                break;
                   1724:        case absw:
1.1.1.7 ! root     1725:                addr = (uae_s32)(uae_s16)get_iword_debug (pc);
        !          1726:                _stprintf (buffer, _T("$%08x"), addr);
        !          1727:                pc += 2;
1.1.1.4   root     1728:                break;
                   1729:        case absl:
1.1.1.7 ! root     1730:                addr = get_ilong_debug (pc);
        !          1731:                _stprintf (buffer, _T("$%08x"), addr);
        !          1732:                pc += 4;
1.1.1.4   root     1733:                break;
                   1734:        case imm:
                   1735:                switch (size){
                   1736:                case sz_byte:
1.1.1.7 ! root     1737:                        _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
        !          1738:                        pc += 2;
1.1.1.4   root     1739:                        break;
                   1740:                case sz_word:
1.1.1.7 ! root     1741:                        _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
        !          1742:                        pc += 2;
1.1.1.4   root     1743:                        break;
                   1744:                case sz_long:
1.1.1.7 ! root     1745:                        _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
        !          1746:                        pc += 4;
        !          1747:                        break;
        !          1748:                case sz_single:
        !          1749:                        {
        !          1750:                                fpdata fp;
        !          1751:                                to_single(&fp, get_ilong_debug(pc));
        !          1752:                                _stprintf(buffer, _T("#%e"), fp.fp);
        !          1753:                                pc += 4;
        !          1754:                        }
        !          1755:                        break;
        !          1756:                case sz_double:
        !          1757:                        {
        !          1758:                                fpdata fp;
        !          1759:                                to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
        !          1760:                                _stprintf(buffer, _T("#%e"), fp.fp);
        !          1761:                                pc += 8;
        !          1762:                        }
        !          1763:                        break;
        !          1764:                case sz_extended:
        !          1765:                {
        !          1766:                        fpdata fp;
        !          1767:                        to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
        !          1768: #if USE_LONG_DOUBLE
        !          1769:                        _stprintf(buffer, _T("#%Le"), fp.fp);
        !          1770: #else
        !          1771:                        _stprintf(buffer, _T("#%e"), fp.fp);
        !          1772: #endif
        !          1773:                        pc += 12;
        !          1774:                        break;
        !          1775:                }
        !          1776:                case sz_packed:
        !          1777:                        _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
        !          1778:                        pc += 12;
1.1.1.4   root     1779:                        break;
                   1780:                default:
                   1781:                        break;
                   1782:                }
                   1783:                break;
                   1784:        case imm0:
1.1.1.7 ! root     1785:                offset = (uae_s32)(uae_s8)get_iword_debug (pc);
        !          1786:                _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
        !          1787:                addr = pc + 2 + offset;
        !          1788:                pc += 2;
1.1.1.4   root     1789:                break;
                   1790:        case imm1:
1.1.1.7 ! root     1791:                offset = (uae_s32)(uae_s16)get_iword_debug (pc);
1.1.1.4   root     1792:                buffer[0] = 0;
1.1.1.7 ! root     1793:                _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
        !          1794:                addr = pc + offset;
        !          1795:                pc += 2;
1.1.1.4   root     1796:                break;
                   1797:        case imm2:
1.1.1.7 ! root     1798:                offset = (uae_s32)get_ilong_debug (pc);
        !          1799:                _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
        !          1800:                addr = pc + offset;
        !          1801:                pc += 4;
1.1.1.4   root     1802:                break;
                   1803:        case immi:
                   1804:                offset = (uae_s32)(uae_s8)(reg & 0xff);
1.1.1.7 ! root     1805:                _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
        !          1806:                addr = pc + offset;
1.1.1.4   root     1807:                break;
                   1808:        default:
                   1809:                break;
                   1810:        }
                   1811:        if (buf == 0)
1.1.1.7 ! root     1812:                f_out (f, _T("%s"), buffer);
1.1.1.4   root     1813:        else
                   1814:                _tcscat (buf, buffer);
                   1815:        if (eaddr)
                   1816:                *eaddr = addr;
1.1.1.7 ! root     1817:        return pc;
1.1.1.4   root     1818: }
                   1819: 
                   1820: #if 0
                   1821: /* The plan is that this will take over the job of exception 3 handling -
                   1822: * the CPU emulation functions will just do a longjmp to m68k_go whenever
                   1823: * they hit an odd address. */
                   1824: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
                   1825: {
                   1826:        uae_u16 dp;
                   1827:        uae_s8 disp8;
                   1828:        uae_s16 disp16;
                   1829:        int r;
                   1830:        uae_u32 dispreg;
                   1831:        uaecptr addr;
                   1832:        uae_s32 offset = 0;
                   1833: 
                   1834:        switch (mode){
                   1835:        case Dreg:
                   1836:                *val = m68k_dreg (regs, reg);
                   1837:                return 1;
                   1838:        case Areg:
                   1839:                *val = m68k_areg (regs, reg);
                   1840:                return 1;
                   1841: 
                   1842:        case Aind:
                   1843:        case Aipi:
                   1844:                addr = m68k_areg (regs, reg);
                   1845:                break;
                   1846:        case Apdi:
                   1847:                addr = m68k_areg (regs, reg);
                   1848:                break;
                   1849:        case Ad16:
                   1850:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   1851:                addr = m68k_areg (regs, reg) + (uae_s16)disp16;
                   1852:                break;
                   1853:        case Ad8r:
                   1854:                addr = m68k_areg (regs, reg);
                   1855: d8r_common:
                   1856:                dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   1857:                disp8 = dp & 0xFF;
                   1858:                r = (dp & 0x7000) >> 12;
                   1859:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   1860:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   1861:                dispreg <<= (dp >> 9) & 3;
                   1862: 
                   1863:                if (dp & 0x100) {
                   1864:                        uae_s32 outer = 0, disp = 0;
                   1865:                        uae_s32 base = addr;
                   1866:                        if (dp & 0x80) base = 0;
                   1867:                        if (dp & 0x40) dispreg = 0;
                   1868:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                   1869:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
                   1870:                        base += disp;
                   1871: 
                   1872:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                   1873:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
                   1874: 
                   1875:                        if (!(dp & 4)) base += dispreg;
                   1876:                        if (dp & 3) base = get_long (base);
                   1877:                        if (dp & 4) base += dispreg;
                   1878: 
                   1879:                        addr = base + outer;
                   1880:                } else {
                   1881:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
                   1882:                }
                   1883:                break;
                   1884:        case PC16:
                   1885:                addr = m68k_getpc () + m68kpc_offset;
                   1886:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   1887:                addr += (uae_s16)disp16;
                   1888:                break;
                   1889:        case PC8r:
                   1890:                addr = m68k_getpc () + m68kpc_offset;
                   1891:                goto d8r_common;
                   1892:        case absw:
                   1893:                addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                   1894:                m68kpc_offset += 2;
                   1895:                break;
                   1896:        case absl:
                   1897:                addr = get_ilong_1 (m68kpc_offset);
                   1898:                m68kpc_offset += 4;
                   1899:                break;
                   1900:        case imm:
                   1901:                switch (size){
                   1902:                case sz_byte:
                   1903:                        *val = get_iword_1 (m68kpc_offset) & 0xff;
                   1904:                        m68kpc_offset += 2;
                   1905:                        break;
                   1906:                case sz_word:
                   1907:                        *val = get_iword_1 (m68kpc_offset) & 0xffff;
                   1908:                        m68kpc_offset += 2;
                   1909:                        break;
                   1910:                case sz_long:
                   1911:                        *val = get_ilong_1 (m68kpc_offset);
                   1912:                        m68kpc_offset += 4;
                   1913:                        break;
                   1914:                default:
                   1915:                        break;
                   1916:                }
                   1917:                return 1;
                   1918:        case imm0:
                   1919:                *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
                   1920:                m68kpc_offset += 2;
                   1921:                return 1;
                   1922:        case imm1:
                   1923:                *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                   1924:                m68kpc_offset += 2;
                   1925:                return 1;
                   1926:        case imm2:
                   1927:                *val = get_ilong_1 (m68kpc_offset);
                   1928:                m68kpc_offset += 4;
                   1929:                return 1;
                   1930:        case immi:
                   1931:                *val = (uae_s32)(uae_s8)(reg & 0xff);
                   1932:                return 1;
                   1933:        default:
                   1934:                addr = 0;
                   1935:                break;
                   1936:        }
                   1937:        if ((addr & 1) == 0)
                   1938:                return 1;
                   1939: 
                   1940:        last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
                   1941:        last_fault_for_exception_3 = addr;
                   1942:        last_writeaccess_for_exception_3 = 0;
                   1943:        last_instructionaccess_for_exception_3 = 0;
                   1944:        return 0;
                   1945: }
                   1946: #endif
                   1947: 
                   1948: int get_cpu_model (void)
                   1949: {
                   1950:        return currprefs.cpu_model;
                   1951: }
                   1952: 
1.1.1.7 ! root     1953: #ifndef WINUAE_FOR_HATARI
        !          1954: STATIC_INLINE int in_rom (uaecptr pc)
1.1.1.4   root     1955: {
1.1.1.7 ! root     1956:        return (munge24 (pc) & 0xFFF80000) == 0xF80000;
1.1.1.4   root     1957: }
                   1958: 
1.1.1.7 ! root     1959: STATIC_INLINE int in_rtarea (uaecptr pc)
1.1.1.4   root     1960: {
1.1.1.7 ! root     1961:        return (munge24 (pc) & 0xFFFF0000) == rtarea_base && uae_boot_rom_type;
1.1.1.4   root     1962: }
1.1.1.7 ! root     1963: #endif
1.1.1.4   root     1964: 
1.1.1.7 ! root     1965: STATIC_INLINE void wait_memory_cycles (void)
1.1.1.4   root     1966: {
1.1.1.7 ! root     1967:        if (regs.memory_waitstate_cycles) {
        !          1968:                x_do_cycles(regs.memory_waitstate_cycles);
        !          1969:                regs.memory_waitstate_cycles = 0;
1.1.1.4   root     1970:        }
1.1.1.7 ! root     1971:        if (regs.ce020extracycles >= 16) {
        !          1972:                regs.ce020extracycles = 0;
        !          1973:                x_do_cycles(4 * CYCLE_UNIT);
1.1.1.4   root     1974:        }
                   1975: }
                   1976: 
1.1.1.7 ! root     1977: STATIC_INLINE int adjust_cycles (int cycles)
1.1.1.4   root     1978: {
1.1.1.7 ! root     1979:        int mc = regs.memory_waitstate_cycles;
        !          1980:        regs.memory_waitstate_cycles = 0;
        !          1981:        if (currprefs.m68k_speed < 0 || cycles_mult == 0)
        !          1982:                return cycles + mc;
        !          1983:        cycles *= cycles_mult;
        !          1984:        cycles /= CYCLES_DIV;
        !          1985:        return cycles + mc;
1.1.1.4   root     1986: }
                   1987: 
                   1988: void REGPARAM2 MakeSR (void)
                   1989: {
                   1990:        regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
                   1991:                | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
                   1992:                | (GET_XFLG () << 4) | (GET_NFLG () << 3)
                   1993:                | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
                   1994:                |  GET_CFLG ());
                   1995: }
                   1996: 
1.1.1.7 ! root     1997: void SetSR (uae_u16 sr)
1.1.1.4   root     1998: {
1.1.1.7 ! root     1999:        regs.sr &= 0xff00;
        !          2000:        regs.sr |= sr;
1.1.1.4   root     2001: 
                   2002:        SET_XFLG ((regs.sr >> 4) & 1);
                   2003:        SET_NFLG ((regs.sr >> 3) & 1);
                   2004:        SET_ZFLG ((regs.sr >> 2) & 1);
                   2005:        SET_VFLG ((regs.sr >> 1) & 1);
                   2006:        SET_CFLG (regs.sr & 1);
1.1.1.7 ! root     2007: }
        !          2008: 
        !          2009: void REGPARAM2 MakeFromSR (void)
        !          2010: {
        !          2011:        int oldm = regs.m;
        !          2012:        int olds = regs.s;
        !          2013: 
        !          2014:        SET_XFLG ((regs.sr >> 4) & 1);
        !          2015:        SET_NFLG ((regs.sr >> 3) & 1);
        !          2016:        SET_ZFLG ((regs.sr >> 2) & 1);
        !          2017:        SET_VFLG ((regs.sr >> 1) & 1);
        !          2018:        SET_CFLG (regs.sr & 1);
        !          2019:        if (regs.t1 == ((regs.sr >> 15) & 1) &&
        !          2020:                regs.t0 == ((regs.sr >> 14) & 1) &&
        !          2021:                regs.s  == ((regs.sr >> 13) & 1) &&
1.1.1.4   root     2022:                regs.m  == ((regs.sr >> 12) & 1) &&
                   2023:                regs.intmask == ((regs.sr >> 8) & 7))
                   2024:                return;
                   2025:        regs.t1 = (regs.sr >> 15) & 1;
                   2026:        regs.t0 = (regs.sr >> 14) & 1;
                   2027:        regs.s  = (regs.sr >> 13) & 1;
                   2028:        regs.m  = (regs.sr >> 12) & 1;
                   2029:        regs.intmask = (regs.sr >> 8) & 7;
                   2030:        if (currprefs.cpu_model >= 68020) {
                   2031:                /* 68060 does not have MSP but does have M-bit.. */
                   2032:                if (currprefs.cpu_model >= 68060)
                   2033:                        regs.msp = regs.isp;
                   2034:                if (olds != regs.s) {
                   2035:                        if (olds) {
                   2036:                                if (oldm)
                   2037:                                        regs.msp = m68k_areg (regs, 7);
                   2038:                                else
                   2039:                                        regs.isp = m68k_areg (regs, 7);
                   2040:                                m68k_areg (regs, 7) = regs.usp;
                   2041:                        } else {
                   2042:                                regs.usp = m68k_areg (regs, 7);
                   2043:                                m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
                   2044:                        }
                   2045:                } else if (olds && oldm != regs.m) {
                   2046:                        if (oldm) {
                   2047:                                regs.msp = m68k_areg (regs, 7);
                   2048:                                m68k_areg (regs, 7) = regs.isp;
                   2049:                        } else {
                   2050:                                regs.isp = m68k_areg (regs, 7);
                   2051:                                m68k_areg (regs, 7) = regs.msp;
                   2052:                        }
                   2053:                }
                   2054:                if (currprefs.cpu_model >= 68060)
                   2055:                        regs.t0 = 0;
                   2056:        } else {
                   2057:                regs.t0 = regs.m = 0;
                   2058:                if (olds != regs.s) {
                   2059:                        if (olds) {
                   2060:                                regs.isp = m68k_areg (regs, 7);
                   2061:                                m68k_areg (regs, 7) = regs.usp;
                   2062:                        } else {
                   2063:                                regs.usp = m68k_areg (regs, 7);
                   2064:                                m68k_areg (regs, 7) = regs.isp;
                   2065:                        }
                   2066:                }
                   2067:        }
                   2068:        if (currprefs.mmu_model)
                   2069:                mmu_set_super (regs.s != 0);
                   2070: 
                   2071:        doint ();
                   2072:        if (regs.t1 || regs.t0)
                   2073:                set_special (SPCFLAG_TRACE);
                   2074:        else
                   2075:                /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
                   2076:                SR-modifying instructions (including STOP).  */
                   2077:                unset_special (SPCFLAG_TRACE);
                   2078: }
                   2079: 
                   2080: static void exception_trace (int nr)
                   2081: {
                   2082:        unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                   2083:        if (regs.t1 && !regs.t0) {
                   2084:                /* trace stays pending if exception is div by zero, chk,
                   2085:                * trapv or trap #x
                   2086:                */
                   2087:                if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
                   2088:                        set_special (SPCFLAG_DOTRACE);
                   2089:        }
                   2090:        regs.t1 = regs.t0 = regs.m = 0;
                   2091: }
                   2092: 
                   2093: static void exception_debug (int nr)
                   2094: {
                   2095: #ifdef DEBUGGER
                   2096:        if (!exception_debugging)
                   2097:                return;
1.1.1.7 ! root     2098:        console_out_f (_T("Exception %d, PC=%08X\n"), nr, M68K_GETPC);
1.1.1.4   root     2099: #endif
1.1.1.7 ! root     2100: #ifdef WINUAE_FOR_HATARI
1.1.1.6   root     2101:        DebugUI_Exceptions(nr, M68K_GETPC);
1.1.1.7 ! root     2102: #endif
1.1.1.4   root     2103: }
                   2104: 
1.1.1.7 ! root     2105: #ifdef CPUEMU_13
1.1.1.4   root     2106: 
                   2107: /* cycle-exact exception handler, 68000 only */
                   2108: 
                   2109: /*
                   2110: 
                   2111: Address/Bus Error:
                   2112: 
1.1.1.7 ! root     2113: - 8 idle cycles
1.1.1.4   root     2114: - write PC low word
                   2115: - write SR
                   2116: - write PC high word
                   2117: - write instruction word
                   2118: - write fault address low word
                   2119: - write status code
                   2120: - write fault address high word
                   2121: - 2 idle cycles
                   2122: - read exception address high word
                   2123: - read exception address low word
                   2124: - prefetch
                   2125: - 2 idle cycles
                   2126: - prefetch
                   2127: 
                   2128: Division by Zero:
                   2129: 
1.1.1.7 ! root     2130: - 8 idle cycles
1.1.1.4   root     2131: - write PC low word
                   2132: - write SR
                   2133: - write PC high word
                   2134: - read exception address high word
                   2135: - read exception address low word
                   2136: - prefetch
                   2137: - 2 idle cycles
                   2138: - prefetch
                   2139: 
                   2140: Traps:
                   2141: 
1.1.1.7 ! root     2142: - 4 idle cycles
1.1.1.4   root     2143: - write PC low word
                   2144: - write SR
                   2145: - write PC high word
                   2146: - read exception address high word
                   2147: - read exception address low word
                   2148: - prefetch
                   2149: - 2 idle cycles
                   2150: - prefetch
                   2151: 
                   2152: TrapV:
                   2153: 
1.1.1.7 ! root     2154: (- normal prefetch done by TRAPV)
1.1.1.4   root     2155: - write PC low word
                   2156: - write SR
                   2157: - write PC high word
                   2158: - read exception address high word
                   2159: - read exception address low word
                   2160: - prefetch
                   2161: - 2 idle cycles
                   2162: - prefetch
                   2163: 
                   2164: CHK:
                   2165: 
1.1.1.7 ! root     2166: - 8 idle cycles
1.1.1.4   root     2167: - write PC low word
                   2168: - write SR
                   2169: - write PC high word
                   2170: - read exception address high word
                   2171: - read exception address low word
                   2172: - prefetch
                   2173: - 2 idle cycles
                   2174: - prefetch
                   2175: 
                   2176: Illegal Instruction:
1.1.1.7 ! root     2177: Privilege violation:
        !          2178: Line A:
        !          2179: Line F:
1.1.1.4   root     2180: 
1.1.1.7 ! root     2181: - 4 idle cycles
1.1.1.4   root     2182: - write PC low word
                   2183: - write SR
                   2184: - write PC high word
                   2185: - read exception address high word
                   2186: - read exception address low word
                   2187: - prefetch
                   2188: - 2 idle cycles
                   2189: - prefetch
                   2190: 
1.1.1.7 ! root     2191: Interrupt:
1.1.1.4   root     2192: 
                   2193: - 6 idle cycles
                   2194: - write PC low word
                   2195: - read exception number byte from (0xfffff1 | (interrupt number << 1))
                   2196: - 4 idle cycles
                   2197: - write SR
                   2198: - write PC high word
                   2199: - read exception address high word
                   2200: - read exception address low word
                   2201: - prefetch
                   2202: - 2 idle cycles
                   2203: - prefetch
                   2204: 
                   2205: */
                   2206: 
1.1.1.7 ! root     2207: static int iack_cycle(int nr)
        !          2208: {
        !          2209:        int vector;
        !          2210: 
        !          2211: #ifndef WINUAE_FOR_HATARI
        !          2212:        if (1) {
        !          2213:                // non-autovectored
        !          2214:                vector = x_get_byte(0x00fffff1 | ((nr - 24) << 1));
        !          2215:                if (currprefs.cpu_cycle_exact)
        !          2216:                        x_do_cycles(4 * cpucycleunit);
        !          2217:        } else {
        !          2218:                // autovectored
        !          2219: 
        !          2220:        }
        !          2221: #else
        !          2222:        int iack_start = CPU_IACK_CYCLES_START;
        !          2223:        int e_cycles;
        !          2224: 
        !          2225:        /* In cycle exact mode, the cycles before reaching IACK are already counted */
        !          2226:        if ( currprefs.cpu_cycle_exact )
        !          2227:                iack_start = 0;
        !          2228: 
        !          2229:        /* Pending bits / vector number can change before the end of the IACK sequence. */
        !          2230:        /* We need to handle MFP/DSP and HBL/VBL cases for this. */
        !          2231:        /* - Level 6 (MFP/DSP) use vectored interrupts */
        !          2232:        /* - Level 2 (HBL) and 4 (VBL) use auto-vectored interrupts and require sync with E-clock */
        !          2233:        vector = nr;
        !          2234:        if ( nr == 30 )                                                         /* MFP or DSP */
        !          2235:         {
        !          2236:                vector = -1;
        !          2237:                if (bDspEnabled)                                                /* Check DSP first */
        !          2238:                {
        !          2239:                        /* TODO : For DSP, we just get the vector, we don't add IACK cycles */
        !          2240:                        vector = DSP_ProcessIACK ();
        !          2241:                }
        !          2242: 
        !          2243:                if ( vector < 0 )                                               /* No DSP, check MFP */
        !          2244:                {
        !          2245:                        M68000_AddCycles ( iack_start + CPU_IACK_CYCLES_MFP );
        !          2246:              // TODO : add CE cycles too
        !          2247:                        CPU_IACK = true;
        !          2248:                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
        !          2249:                                CALL_VAR(PendingInterruptFunction);
        !          2250:                        vector = MFP_ProcessIACK ( nr );
        !          2251:                        CPU_IACK = false;
        !          2252:                }
        !          2253:        }
        !          2254:        else if ( ( nr == 26 ) || ( nr == 28 ) )                                /* HBL / VBL */
        !          2255:        {
        !          2256:                iack_start -= 2;                        /* [NP] work in progress for e clock, TODO we need to check the complete sequence of interrupt micro code */
        !          2257:                e_cycles = M68000_WaitEClock ();
        !          2258:                //fprintf ( stderr , "wait e clock %d\n" , e_cycles);
        !          2259: 
        !          2260:                M68000_AddCycles ( iack_start + CPU_IACK_CYCLES_VIDEO + e_cycles );
        !          2261:        // TODO : add CE cycles too
        !          2262:                CPU_IACK = true;
        !          2263:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
        !          2264:                        CALL_VAR(PendingInterruptFunction);
        !          2265:                if ( MFP_UpdateNeeded == true )
        !          2266:                        MFP_UpdateIRQ ( 0 );                                    /* update MFP's state if some internal timers related to MFP expired */
        !          2267:                pendingInterrupts &= ~( 1 << ( nr - 24 ) );                     /* clear HBL or VBL pending bit */
        !          2268:                CPU_IACK = false;
        !          2269:        }
        !          2270: 
        !          2271:        /* TODO If there was no DSP and no MFP IRQ, then we have a spurious interrupt */
        !          2272:        /* In that case, we use vector 24 and we jump to $60 */
        !          2273:        if ( vector < 0 )
        !          2274:        {
        !          2275:        }
        !          2276: #endif
        !          2277:        return vector;
        !          2278: }
        !          2279: 
        !          2280: static void Exception_ce000 (int nr)
1.1.1.4   root     2281: {
                   2282:        uae_u32 currpc = m68k_getpc (), newpc;
                   2283:        int sv = regs.s;
1.1.1.7 ! root     2284:        int start, interrupt;
        !          2285:        int vector_nr = nr;
1.1.1.4   root     2286: 
1.1.1.7 ! root     2287: //fprintf ( stderr , "ex in %d %ld\n" , nr , currcycle );
        !          2288: currcycle=0;
        !          2289:        start = 6;
        !          2290: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     2291:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.7 ! root     2292: #else
        !          2293:        if ( nr >= 24 && nr < 24 + 8 )
        !          2294:                interrupt = 1;
1.1.1.4   root     2295: #endif
1.1.1.7 ! root     2296:        if (!interrupt) {
        !          2297:                start = 8;
        !          2298:                if (nr == 7) // TRAPV
        !          2299:                        start = 0;
        !          2300:                else if (nr >= 32 && nr < 32 + 16) // TRAP #x
        !          2301:                        start = 4;
        !          2302:                else if (nr == 4 || nr == 8 || nr == 10 || nr == 11) // ILLG, PRIV, LINEA, LINEF
        !          2303:                        start = 4;
        !          2304:        }
1.1.1.4   root     2305: 
                   2306:        if (start)
1.1.1.7 ! root     2307:                x_do_cycles (start * cpucycleunit);
1.1.1.4   root     2308: 
1.1.1.7 ! root     2309: #ifdef WINUAE_FOR_HATARI
        !          2310:        LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
        !          2311:                nr, currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
        !          2312: #endif
1.1.1.4   root     2313:        exception_debug (nr);
                   2314:        MakeSR ();
                   2315: 
1.1.1.7 ! root     2316: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     2317:        /* Handle Hatari GEM and BIOS traps */
1.1.1.6   root     2318:        if (nr == 0x22) {
1.1.1.4   root     2319:                /* Intercept VDI & AES exceptions (Trap #2) */
1.1.1.6   root     2320:                if (bVdiAesIntercept && VDI_AES_Entry()) {
1.1.1.4   root     2321:                        /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
1.1.1.7 ! root     2322:                        * This will call OpCode_VDI() after completion of Trap call!
        !          2323:                        * This is used to modify specific VDI return vectors contents.
1.1.1.4   root     2324:                        */
                   2325:                        VDI_OldPC = currpc;
                   2326:                        currpc = CART_VDI_OPCODE_ADDR;
                   2327:                }
                   2328:        }
1.1.1.6   root     2329:        else if (nr == 0x2d) {
                   2330:                /* Intercept BIOS (Trap #13) calls */
                   2331:                if (Bios())  return;
                   2332:        }
                   2333:        else if (nr == 0x2e) {
                   2334:                /* Intercept XBIOS (Trap #14) calls */
                   2335:                if (XBios())  return;
1.1.1.4   root     2336:        }
1.1.1.7 ! root     2337: #endif
1.1.1.4   root     2338: 
                   2339:        if (!regs.s) {
                   2340:                regs.usp = m68k_areg (regs, 7);
                   2341:                m68k_areg (regs, 7) = regs.isp;
                   2342:                regs.s = 1;
                   2343:        }
                   2344:        if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
1.1.1.7 ! root     2345:                if ((m68k_areg(regs, 7) & 1) || exception_in_exception < 0) {
        !          2346:                        cpu_halt (2);
        !          2347:                        return;
        !          2348:                }
1.1.1.4   root     2349:                uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   2350:                mode |= last_writeaccess_for_exception_3 ? 0 : 16;
1.1.1.7 ! root     2351:                mode |= last_notinstruction_for_exception_3 ? 8 : 0;
        !          2352:                // undocumented bits seem to contain opcode
        !          2353:                mode |= last_op_for_exception_3 & ~31;
1.1.1.4   root     2354:                m68k_areg (regs, 7) -= 14;
1.1.1.7 ! root     2355:                exception_in_exception = -1;
        !          2356:                x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
        !          2357:                x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
        !          2358:                x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
        !          2359:                x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
        !          2360:                x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
        !          2361:                x_put_word (m68k_areg (regs, 7) + 0, mode);
        !          2362:                x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
        !          2363:                x_do_cycles (2 * cpucycleunit);
        !          2364:                write_log (_T("Exception %d (%04x %x) at %x -> %x!\n"),
        !          2365:                        nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug (4 * nr));
        !          2366: #ifdef WINUAE_FOR_HATARI
        !          2367:                fprintf(stderr,"%s Error at address $%x, PC=$%x addr_e3=%x op_e3=%x\n", nr==2?"Bus":"Address", last_fault_for_exception_3, currpc, last_addr_for_exception_3 , last_op_for_exception_3);
        !          2368: #endif
1.1.1.4   root     2369:                goto kludge_me_do;
                   2370:        }
1.1.1.7 ! root     2371:        if (currprefs.cpu_model == 68010) {
        !          2372:                // 68010 creates only format 0 and 8 stack frames
        !          2373:                m68k_areg (regs, 7) -= 8;
        !          2374:                if (m68k_areg(regs, 7) & 1) {
        !          2375:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
        !          2376:                        return;
        !          2377:                }
        !          2378:                exception_in_exception = 1;
        !          2379:                x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
        !          2380:                if (interrupt)
        !          2381:                        vector_nr = iack_cycle(nr);
        !          2382:                x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
        !          2383:                x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
        !          2384:                x_put_word (m68k_areg (regs, 7) + 6, vector_nr * 4);
        !          2385:        } else {
        !          2386:                m68k_areg (regs, 7) -= 6;
        !          2387:                if (m68k_areg(regs, 7) & 1) {
        !          2388:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
        !          2389:                        return;
        !          2390:                }
        !          2391:                exception_in_exception = 1;
        !          2392:                x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
        !          2393:                if (interrupt)
        !          2394:                        vector_nr = iack_cycle(nr);
        !          2395:                x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
        !          2396:                x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
1.1.1.4   root     2397:        }
                   2398: kludge_me_do:
1.1.1.7 ! root     2399:        newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
        !          2400:        newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
        !          2401:        exception_in_exception = 0;
1.1.1.4   root     2402:        if (newpc & 1) {
                   2403:                if (nr == 2 || nr == 3)
1.1.1.7 ! root     2404:                        cpu_halt (2);
1.1.1.4   root     2405:                else
1.1.1.7 ! root     2406:                        exception3_notinstruction(regs.ir, newpc);
1.1.1.4   root     2407:                return;
                   2408:        }
                   2409:        m68k_setpc (newpc);
1.1.1.7 ! root     2410:        regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
        !          2411:        x_do_cycles (2 * cpucycleunit);
        !          2412:        regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2
1.1.1.4   root     2413: #ifdef JIT
                   2414:        set_special (SPCFLAG_END_COMPILE);
                   2415: #endif
                   2416:        exception_trace (nr);
1.1.1.7 ! root     2417: 
        !          2418: //fprintf ( stderr , "ex out %d %ld\n" , nr , currcycle );
        !          2419: #ifdef WINUAE_FOR_HATARI
        !          2420:        /* FIXME : Above code already counts 36 cycles for interrupt, add the remaining ST cycles */
        !          2421:        /* This is temporary, code should be in iack_cycle() */
        !          2422:        M68000_AddCycles(currcycle * 2 / CYCLE_UNIT);
        !          2423: 
        !          2424:        /* Handle exception cycles (special case for MFP) */
        !          2425:        if ( nr == 30 ) {
        !          2426:                //M68000_AddCycles(44+12-CPU_IACK_CYCLES_MFP);  /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
        !          2427:                M68000_AddCycles(44-36);        /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
        !          2428:        }
        !          2429:        else if (nr >= 24 && nr <= 31) {
        !          2430:                if ( nr == 26 )                                 /* HBL */
        !          2431:                        //M68000_AddCycles(44+12-CPU_IACK_CYCLES_VIDEO);        /* Video Interrupt */
        !          2432:                        M68000_AddCycles(44-36);        /* Video Interrupt */
        !          2433:                else if ( nr == 28 )                            /* VBL */
        !          2434:                        //M68000_AddCycles(44+12-CPU_IACK_CYCLES_VIDEO);        /* Video Interrupt */
        !          2435:                        M68000_AddCycles(44-36);        /* Video Interrupt */
        !          2436:                else
        !          2437:                        //M68000_AddCycles(44+4);                       /* Other Interrupts */
        !          2438:                        M68000_AddCycles(44-36);                        /* Other Interrupts */
        !          2439:        }
        !          2440: #endif
        !          2441: }
        !          2442: #endif
        !          2443: 
        !          2444: static uae_u32 exception_pc (int nr)
        !          2445: {
        !          2446:        // bus error, address error, illegal instruction, privilege violation, a-line, f-line
        !          2447:        if (nr == 2 || nr == 3 || nr == 4 || nr == 8 || nr == 10 || nr == 11)
        !          2448:                return regs.instruction_pc;
        !          2449:        return m68k_getpc ();
        !          2450: }
        !          2451: 
        !          2452: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
        !          2453: {
        !          2454:     int i;
        !          2455:    
        !          2456: #if 0
        !          2457:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
        !          2458:         write_log(_T("Building exception stack frame (format %X)\n"), format);
        !          2459:     }
        !          2460: #endif
        !          2461: 
        !          2462:     switch (format) {
        !          2463:         case 0x0: // four word stack frame
        !          2464:         case 0x1: // throwaway four word stack frame
        !          2465:             break;
        !          2466:         case 0x2: // six word stack frame
        !          2467:             m68k_areg (regs, 7) -= 4;
        !          2468:             x_put_long (m68k_areg (regs, 7), oldpc);
        !          2469:             break;
        !          2470:         case 0x7: // access error stack frame (68040)
        !          2471: 
        !          2472:                        for (i = 3; i >= 0; i--) {
        !          2473:                                // WB1D/PD0,PD1,PD2,PD3
        !          2474:                 m68k_areg (regs, 7) -= 4;
        !          2475:                 x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
        !          2476:                        }
        !          2477: 
        !          2478:             m68k_areg (regs, 7) -= 4;
        !          2479:             x_put_long (m68k_areg (regs, 7), 0); // WB1A
        !          2480:                        m68k_areg (regs, 7) -= 4;
        !          2481:             x_put_long (m68k_areg (regs, 7), 0); // WB2D
        !          2482:             m68k_areg (regs, 7) -= 4;
        !          2483:             x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
        !          2484:                        m68k_areg (regs, 7) -= 4;
        !          2485:             x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
        !          2486:             m68k_areg (regs, 7) -= 4;
        !          2487:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
        !          2488: 
        !          2489:                        m68k_areg (regs, 7) -= 4;
        !          2490:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
        !          2491:             
        !          2492:                        m68k_areg (regs, 7) -= 2;
        !          2493:             x_put_word (m68k_areg (regs, 7), 0);
        !          2494:             m68k_areg (regs, 7) -= 2;
        !          2495:             x_put_word (m68k_areg (regs, 7), regs.wb2_status);
        !          2496:             regs.wb2_status = 0;
        !          2497:             m68k_areg (regs, 7) -= 2;
        !          2498:             x_put_word (m68k_areg (regs, 7), regs.wb3_status);
        !          2499:             regs.wb3_status = 0;
        !          2500: 
        !          2501:                        m68k_areg (regs, 7) -= 2;
        !          2502:                        x_put_word (m68k_areg (regs, 7), ssw);
        !          2503:             m68k_areg (regs, 7) -= 4;
        !          2504:             x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
        !          2505:             break;
        !          2506:         case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
        !          2507:             m68k_areg (regs, 7) -= 4;
        !          2508:             x_put_long (m68k_areg (regs, 7), 0);
        !          2509:             m68k_areg (regs, 7) -= 4;
        !          2510:             x_put_long (m68k_areg (regs, 7), 0);
        !          2511:             m68k_areg (regs, 7) -= 4;
        !          2512:             x_put_long (m68k_areg (regs, 7), oldpc);
        !          2513:             break;
        !          2514:         case 0x3: // floating point post-instruction stack frame (68040)
        !          2515:         case 0x8: // bus and address error stack frame (68010)
        !          2516:             write_log(_T("Exception stack frame format %X not implemented\n"), format);
        !          2517:             return;
        !          2518:         case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
        !          2519:                                // or 68060 bus access fault stack frame
        !          2520:                        if (currprefs.cpu_model == 68040) {
        !          2521:                                // this is actually created in fpp.c
        !          2522:                                write_log(_T("Exception stack frame format %X not implemented\n"), format);
        !          2523:                                return;
        !          2524:                        }
        !          2525:                        // 68060 bus access fault
        !          2526:                        m68k_areg (regs, 7) -= 4;
        !          2527:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fslw);
        !          2528:                        m68k_areg (regs, 7) -= 4;
        !          2529:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          2530:                        break;
        !          2531:                case 0xB: // long bus cycle fault stack frame (68020, 68030)
        !          2532:                        // We always use B frame because it is easier to emulate,
        !          2533:                        // our PC always points at start of instruction but A frame assumes
        !          2534:                        // it is + 2 and handling this properly is not easy.
        !          2535:                        // Store state information to internal register space
        !          2536:                        for (i = 0; i < mmu030_idx + 1; i++) {
        !          2537:                                m68k_areg (regs, 7) -= 4;
        !          2538:                                x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
        !          2539:                        }
        !          2540:                        while (i < 9) {
        !          2541:                                uae_u32 v = 0;
        !          2542:                                m68k_areg (regs, 7) -= 4;
        !          2543:                                // mmu030_idx is always small enough if instruction is FMOVEM.
        !          2544:                                if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
        !          2545:                                        if (i == 7)
        !          2546:                                                v = mmu030_fmovem_store[0];
        !          2547:                                        else if (i == 8)
        !          2548:                                                v = mmu030_fmovem_store[1];
        !          2549:                                }
        !          2550:                                x_put_long (m68k_areg (regs, 7), v);
        !          2551:                                i++;
        !          2552:                        }
        !          2553:                         // version & internal information (We store index here)
        !          2554:                        m68k_areg (regs, 7) -= 2;
        !          2555:                        x_put_word (m68k_areg (regs, 7), mmu030_idx);
        !          2556:                        // 3* internal registers
        !          2557:                        m68k_areg (regs, 7) -= 2;
        !          2558:                        x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
        !          2559:                        m68k_areg (regs, 7) -= 2;
        !          2560:                        x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
        !          2561:                        m68k_areg (regs, 7) -= 2;
        !          2562:                        x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
        !          2563:                        // data input buffer = fault address
        !          2564:                        m68k_areg (regs, 7) -= 4;
        !          2565:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
        !          2566:                        // 2xinternal
        !          2567:                        m68k_areg (regs, 7) -= 2;
        !          2568:                        x_put_word (m68k_areg (regs, 7), 0);
        !          2569:                        m68k_areg (regs, 7) -= 2;
        !          2570:                        x_put_word (m68k_areg (regs, 7), 0);
        !          2571:                        // stage b address
        !          2572:                        m68k_areg (regs, 7) -= 4;
        !          2573:                        x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
        !          2574:                        // 2xinternal
        !          2575:                        m68k_areg (regs, 7) -= 4;
        !          2576:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
        !          2577:                /* fall through */
        !          2578:                case 0xA: // short bus cycle fault stack frame (68020, 68030)
        !          2579:                        m68k_areg (regs, 7) -= 4;
        !          2580:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
        !          2581:                        m68k_areg (regs, 7) -= 4;
        !          2582:                         // Data output buffer = value that was going to be written
        !          2583:                        x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
        !          2584:                        m68k_areg (regs, 7) -= 4;
        !          2585:                        x_put_long (m68k_areg (regs, 7), mmu030_opcode);  // Internal register (opcode storage)
        !          2586:                        m68k_areg (regs, 7) -= 4;
        !          2587:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
        !          2588:                        m68k_areg (regs, 7) -= 2;
        !          2589:                        x_put_word (m68k_areg (regs, 7), 0);  // Instr. pipe stage B
        !          2590:                        m68k_areg (regs, 7) -= 2;
        !          2591:                        x_put_word (m68k_areg (regs, 7), 0);  // Instr. pipe stage C
        !          2592:                        m68k_areg (regs, 7) -= 2;
        !          2593:                        x_put_word (m68k_areg (regs, 7), ssw);
        !          2594:                        m68k_areg (regs, 7) -= 2;
        !          2595:                        x_put_word (m68k_areg (regs, 7), 0);  // Internal register
        !          2596:                        break;
        !          2597:                default:
        !          2598:             write_log(_T("Unknown exception stack frame format: %X\n"), format);
        !          2599:             return;
        !          2600:     }
        !          2601:     m68k_areg (regs, 7) -= 2;
        !          2602:     x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
        !          2603:     m68k_areg (regs, 7) -= 4;
        !          2604:     x_put_long (m68k_areg (regs, 7), currpc);
        !          2605:     m68k_areg (regs, 7) -= 2;
        !          2606:     x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.4   root     2607: }
1.1.1.7 ! root     2608: 
        !          2609: 
        !          2610: // 68030 MMU
        !          2611: static void Exception_mmu030 (int nr, uaecptr oldpc)
        !          2612: {
        !          2613:     uae_u32 currpc = m68k_getpc (), newpc;
        !          2614:        int interrupt;
        !          2615: 
        !          2616: #ifndef WINUAE_FOR_HATARI
        !          2617:        interrupt = nr >= 24 && nr < 24 + 8;
        !          2618: #else
        !          2619:        if ( nr >= 24 && nr < 24 + 8 )
        !          2620:                interrupt = 1;
1.1.1.4   root     2621: #endif
                   2622: 
1.1.1.7 ! root     2623: #ifdef WINUAE_FOR_HATARI
        !          2624:        if (interrupt)
        !          2625:                nr = iack_cycle(nr);
        !          2626: #endif
        !          2627: 
        !          2628: #ifdef WINUAE_FOR_HATARI
        !          2629:        LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
        !          2630:                nr, currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
        !          2631: #endif
        !          2632:     exception_debug (nr);
        !          2633:     MakeSR ();
        !          2634:     
        !          2635:     if (!regs.s) {
        !          2636:         regs.usp = m68k_areg (regs, 7);
        !          2637:         m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
        !          2638:         regs.s = 1;
        !          2639:         mmu_set_super (1);
        !          2640:     }
        !          2641:  
        !          2642: #if 0
        !          2643:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
        !          2644:         write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
        !          2645:                    nr, currpc, oldpc, regs.mmu_fault_addr);
        !          2646:     }
        !          2647: #endif
        !          2648: 
        !          2649: #if 0
        !          2650:        write_log (_T("Exception %d -> %08x\n", nr, newpc));
        !          2651: #endif
        !          2652: 
        !          2653: 
        !          2654:     newpc = x_get_long (regs.vbr + 4 * nr);
        !          2655: 
        !          2656:        if (regs.m && interrupt) { /* M + Interrupt */
        !          2657:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
        !          2658:                MakeSR ();
        !          2659:                regs.m = 0;
        !          2660:                regs.msp = m68k_areg (regs, 7);
        !          2661:                m68k_areg (regs, 7) = regs.isp;
        !          2662:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
        !          2663:     } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) {
        !          2664:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x2);
        !          2665:     } else if (nr == 2) {
        !          2666:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr,  0xB);
        !          2667:     } else if (nr == 3) {
        !          2668:                regs.mmu_fault_addr = last_fault_for_exception_3;
        !          2669:                mmu030_state[0] = mmu030_state[1] = 0;
        !          2670:                mmu030_data_buffer = 0;
        !          2671:         Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr,  0xA);
        !          2672:     } else {
        !          2673:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
        !          2674:     }
        !          2675:     
        !          2676:        if (newpc & 1) {
        !          2677:                if (nr == 2 || nr == 3)
        !          2678:                        cpu_halt (2);
        !          2679:                else
        !          2680:                        exception3_read(regs.ir, newpc);
        !          2681:                return;
        !          2682:        }
        !          2683:        m68k_setpci (newpc);
        !          2684:        fill_prefetch ();
        !          2685:        exception_trace (nr);
        !          2686: }
        !          2687: 
        !          2688: // 68040/060 MMU
1.1.1.4   root     2689: static void Exception_mmu (int nr, uaecptr oldpc)
                   2690: {
                   2691:        uae_u32 currpc = m68k_getpc (), newpc;
1.1.1.7 ! root     2692:        int interrupt;
1.1.1.4   root     2693: 
1.1.1.7 ! root     2694: #ifndef WINUAE_FOR_HATARI
        !          2695:        interrupt = nr >= 24 && nr < 24 + 8;
        !          2696: #else
        !          2697:        if ( nr >= 24 && nr < 24 + 8 )
        !          2698:                interrupt = 1;
        !          2699: #endif
        !          2700: 
        !          2701: #ifdef WINUAE_FOR_HATARI
        !          2702:        if (interrupt)
        !          2703:                nr = iack_cycle(nr);
        !          2704: #endif
        !          2705: 
        !          2706: #ifdef WINUAE_FOR_HATARI
        !          2707:        LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
        !          2708:                nr, currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
        !          2709: #endif
1.1.1.4   root     2710:        exception_debug (nr);
                   2711:        MakeSR ();
                   2712: 
                   2713:        if (!regs.s) {
                   2714:                regs.usp = m68k_areg (regs, 7);
1.1.1.7 ! root     2715:                if (currprefs.cpu_model == 68060) {
        !          2716:                        m68k_areg (regs, 7) = regs.isp;
        !          2717:                        if (interrupt)
        !          2718:                                regs.m = 0;
        !          2719:                } else if (currprefs.cpu_model >= 68020) {
1.1.1.4   root     2720:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7 ! root     2721:                } else {
1.1.1.4   root     2722:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.7 ! root     2723:                }
1.1.1.4   root     2724:                regs.s = 1;
                   2725:                mmu_set_super (1);
                   2726:        }
1.1.1.7 ! root     2727:     
        !          2728:        newpc = x_get_long (regs.vbr + 4 * nr);
        !          2729: #if 0
        !          2730:        write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
        !          2731: #endif
1.1.1.5   root     2732: 
1.1.1.7 ! root     2733:        if (nr == 2) { // bus error
        !          2734:         //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
        !          2735:         if (currprefs.mmu_model == 68040)
        !          2736:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
        !          2737:                else
        !          2738:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_fslw, nr, 0x4);
        !          2739:        } else if (nr == 3) { // address error
        !          2740:         Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
        !          2741:                write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * nr));
        !          2742:        } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
        !          2743:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
        !          2744:        } else if (regs.m && interrupt) { /* M + Interrupt */
        !          2745:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
        !          2746:        } else if (nr == 61) {
        !          2747:         Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
1.1.1.4   root     2748:        } else {
1.1.1.7 ! root     2749:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
1.1.1.4   root     2750:        }
1.1.1.7 ! root     2751:     
1.1.1.4   root     2752:        if (newpc & 1) {
                   2753:                if (nr == 2 || nr == 3)
1.1.1.7 ! root     2754:                        cpu_halt (2);
1.1.1.4   root     2755:                else
1.1.1.7 ! root     2756:                        exception3_read(regs.ir, newpc);
1.1.1.4   root     2757:                return;
                   2758:        }
1.1.1.7 ! root     2759:        m68k_setpci (newpc);
        !          2760:        fill_prefetch ();
1.1.1.4   root     2761:        exception_trace (nr);
                   2762: }
                   2763: 
1.1.1.7 ! root     2764: static void add_approximate_exception_cycles(int nr)
1.1.1.4   root     2765: {
1.1.1.7 ! root     2766:        int cycles;
        !          2767: 
        !          2768:        if (currprefs.cpu_model > 68000)
        !          2769:                return;
        !          2770: #ifndef WINUAE_FOR_HATARI
        !          2771:        if (nr >= 24 && nr <= 31) {
        !          2772:                /* Interrupts */
        !          2773:                cycles = 44 + 4; 
        !          2774: #else
        !          2775:        if ( nr >= 24 && nr <= 31 ) {
        !          2776:                /* Atari's specific interrupts take 56 cycles instead of 44 */
        !          2777:                /* We must subtract IACK cycles already counted into iack_cycle() */
        !          2778:                if ( nr == 30 )                                 /* MFP/DSP */
        !          2779:                        cycles = 56-CPU_IACK_CYCLES_START-CPU_IACK_CYCLES_MFP;
        !          2780:                else if ( nr == 28 )                            /* VBL */
        !          2781:                        cycles = 56-CPU_IACK_CYCLES_START-CPU_IACK_CYCLES_VIDEO;
        !          2782:                else if ( nr == 26 )                            /* HBL */
        !          2783:                        cycles = 56-CPU_IACK_CYCLES_START- CPU_IACK_CYCLES_VIDEO;
        !          2784:                else
        !          2785:                        cycles = 44+4;                          /* Other interrupts */
        !          2786: #endif
        !          2787:        } else if (nr >= 32 && nr <= 47) {
        !          2788:                /* Trap (total is 34, but cpuemux.c already adds 4) */ 
        !          2789:                cycles = 34 -4;
        !          2790:        } else {
        !          2791:                switch (nr)
        !          2792:                {
        !          2793:                        case 2: cycles = 50; break;             /* Bus error */
        !          2794:                        case 3: cycles = 50; break;             /* Address error */
        !          2795:                        case 4: cycles = 34; break;             /* Illegal instruction */
        !          2796:                        case 5: cycles = 38; break;             /* Division by zero */
        !          2797:                        case 6: cycles = 40; break;             /* CHK */
        !          2798:                        case 7: cycles = 34; break;             /* TRAPV */
        !          2799:                        case 8: cycles = 34; break;             /* Privilege violation */
        !          2800:                        case 9: cycles = 34; break;             /* Trace */
        !          2801:                        case 10: cycles = 34; break;    /* Line-A */
        !          2802:                        case 11: cycles = 34; break;    /* Line-F */
        !          2803:                        default:
        !          2804:                        cycles = 4;
        !          2805:                        break;
        !          2806:                }
        !          2807:        }
        !          2808: #ifdef WINUAE_FOR_HATARI
        !          2809:        M68000_AddCycles ( cycles );
        !          2810: #endif
        !          2811:        cycles = adjust_cycles(cycles * CYCLE_UNIT / 2);
        !          2812:        x_do_cycles(cycles);
        !          2813: }
        !          2814: 
        !          2815: static void Exception_normal (int nr)
        !          2816: {
        !          2817:        uae_u32 currpc, newpc;
1.1.1.4   root     2818:        int sv = regs.s;
1.1.1.7 ! root     2819:        int interrupt;
        !          2820:        int vector_nr = nr;
        !          2821: 
        !          2822:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.4   root     2823: 
1.1.1.7 ! root     2824: /* [NP] TODO : factorize in Hatari_Exception_Intercept() */
        !          2825: #ifdef WINUAE_FOR_HATARI
        !          2826:        if (nr == 0x22) {
        !          2827:                /* Intercept VDI & AES exceptions (Trap #2) */
        !          2828:                if (bVdiAesIntercept && VDI_AES_Entry()) {
        !          2829:                        /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
        !          2830:                         * This will call OpCode_VDI() after completion of Trap call!
        !          2831:                         * This is used to modify specific VDI return vectors contents.
        !          2832:                        */
        !          2833:                        currpc = m68k_getpc ();
        !          2834:                        VDI_OldPC = currpc;
        !          2835:                        currpc = CART_VDI_OPCODE_ADDR;
1.1.1.4   root     2836:                }
                   2837:        }
1.1.1.7 ! root     2838:        else if (nr == 0x2d) {
        !          2839:                /* Intercept BIOS (Trap #13) calls */
        !          2840:                if (Bios())  return;
        !          2841:        }
        !          2842:        else if (nr == 0x2e) {
        !          2843:                /* Intercept XBIOS (Trap #14) calls */
        !          2844:                if (XBios())  return;
        !          2845:        }
        !          2846: #endif
1.1.1.4   root     2847: 
1.1.1.7 ! root     2848: #ifndef WINUAE_FOR_HATARI
        !          2849:        if (interrupt && currprefs.cpu_model <= 68010)
        !          2850: #else
        !          2851:        if (interrupt)
1.1.1.4   root     2852: #endif
1.1.1.7 ! root     2853:                vector_nr = iack_cycle(nr);
1.1.1.4   root     2854: 
                   2855:        exception_debug (nr);
                   2856:        MakeSR ();
                   2857: 
                   2858:        if (!regs.s) {
                   2859:                regs.usp = m68k_areg (regs, 7);
1.1.1.7 ! root     2860:                if (currprefs.cpu_model == 68060) {
        !          2861:                        m68k_areg (regs, 7) = regs.isp;
        !          2862:                        if (interrupt)
        !          2863:                                regs.m = 0;
        !          2864:                } else if (currprefs.cpu_model >= 68020) {
1.1.1.4   root     2865:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7 ! root     2866:                } else {
1.1.1.4   root     2867:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.7 ! root     2868:                }
1.1.1.4   root     2869:                regs.s = 1;
                   2870:                if (currprefs.mmu_model)
                   2871:                        mmu_set_super (regs.s != 0);
                   2872:        }
1.1.1.7 ! root     2873: 
        !          2874:        if (m68k_areg(regs, 7) & 1) {
        !          2875:                if (nr == 2 || nr == 3)
        !          2876:                        cpu_halt (2);
        !          2877:                else
        !          2878:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7));
        !          2879:                return;
        !          2880:        }
        !          2881:        if ((nr == 2 || nr == 3) && exception_in_exception < 0) {
        !          2882:                cpu_halt (2);
        !          2883:                return;
        !          2884:        }
        !          2885: 
        !          2886:        if (currprefs.cpu_model > 68000) {
        !          2887:                currpc = exception_pc (nr);
        !          2888: #ifdef WINUAE_FOR_HATARI
        !          2889:                LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d vector %x currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
        !          2890:                        nr, 4*vector_nr , currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*vector_nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
        !          2891: #endif
        !          2892:                if (nr == 2 || nr == 3) {
        !          2893:                        int i;
1.1.1.4   root     2894:                        if (currprefs.cpu_model >= 68040) {
                   2895:                                if (nr == 2) {
                   2896:                                        if (currprefs.mmu_model) {
1.1.1.7 ! root     2897:                                                // 68040 mmu bus error
1.1.1.4   root     2898:                                                for (i = 0 ; i < 7 ; i++) {
                   2899:                                                        m68k_areg (regs, 7) -= 4;
                   2900:                                                        x_put_long (m68k_areg (regs, 7), 0);
                   2901:                                                }
                   2902:                                                m68k_areg (regs, 7) -= 4;
                   2903:                                                x_put_long (m68k_areg (regs, 7), regs.wb3_data);
                   2904:                                                m68k_areg (regs, 7) -= 4;
                   2905:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   2906:                                                m68k_areg (regs, 7) -= 4;
                   2907:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   2908:                                                m68k_areg (regs, 7) -= 2;
                   2909:                                                x_put_word (m68k_areg (regs, 7), 0);
                   2910:                                                m68k_areg (regs, 7) -= 2;
                   2911:                                                x_put_word (m68k_areg (regs, 7), 0);
                   2912:                                                m68k_areg (regs, 7) -= 2;
                   2913:                                                x_put_word (m68k_areg (regs, 7), regs.wb3_status);
                   2914:                                                regs.wb3_status = 0;
                   2915:                                                m68k_areg (regs, 7) -= 2;
                   2916:                                                x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
                   2917:                                                m68k_areg (regs, 7) -= 4;
                   2918:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   2919: 
                   2920:                                                m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     2921:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4   root     2922:                                                m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root     2923:                                                x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     2924:                                                m68k_areg (regs, 7) -= 2;
                   2925:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.7 ! root     2926:                                                newpc = x_get_long (regs.vbr + 4 * vector_nr);
1.1.1.4   root     2927:                                                if (newpc & 1) {
                   2928:                                                        if (nr == 2 || nr == 3)
1.1.1.7 ! root     2929:                                                                cpu_halt (2);
1.1.1.4   root     2930:                                                        else
1.1.1.7 ! root     2931:                                                                exception3_read(regs.ir, newpc);
1.1.1.4   root     2932:                                                        return;
                   2933:                                                }
                   2934:                                                m68k_setpc (newpc);
                   2935: #ifdef JIT
                   2936:                                                set_special (SPCFLAG_END_COMPILE);
                   2937: #endif
                   2938:                                                exception_trace (nr);
                   2939:                                                return;
                   2940: 
                   2941:                                        } else {
                   2942: 
1.1.1.7 ! root     2943:                                                // 68040 bus error (not really, some garbage?)
1.1.1.4   root     2944:                                                for (i = 0 ; i < 18 ; i++) {
                   2945:                                                        m68k_areg (regs, 7) -= 2;
                   2946:                                                        x_put_word (m68k_areg (regs, 7), 0);
                   2947:                                                }
                   2948:                                                m68k_areg (regs, 7) -= 4;
                   2949:                                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   2950:                                                m68k_areg (regs, 7) -= 2;
                   2951:                                                x_put_word (m68k_areg (regs, 7), 0);
                   2952:                                                m68k_areg (regs, 7) -= 2;
                   2953:                                                x_put_word (m68k_areg (regs, 7), 0);
                   2954:                                                m68k_areg (regs, 7) -= 2;
                   2955:                                                x_put_word (m68k_areg (regs, 7), 0);
                   2956:                                                m68k_areg (regs, 7) -= 2;
                   2957:                                                x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
                   2958:                                                m68k_areg (regs, 7) -= 4;
                   2959:                                                x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
                   2960:                                                m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     2961:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4   root     2962:                                                m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root     2963:                                                x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     2964:                                                m68k_areg (regs, 7) -= 2;
                   2965:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
                   2966:                                                goto kludge_me_do;
                   2967: 
                   2968:                                        }
                   2969: 
                   2970:                                } else {
                   2971:                                        m68k_areg (regs, 7) -= 4;
                   2972:                                        x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   2973:                                        m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     2974:                                        x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
1.1.1.4   root     2975:                                }
                   2976:                        } else {
1.1.1.7 ! root     2977:                                // 68020 address error
1.1.1.4   root     2978:                                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   2979:                                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
                   2980:                                ssw |= 0x20;
                   2981:                                for (i = 0 ; i < 36; i++) {
                   2982:                                        m68k_areg (regs, 7) -= 2;
                   2983:                                        x_put_word (m68k_areg (regs, 7), 0);
                   2984:                                }
                   2985:                                m68k_areg (regs, 7) -= 4;
                   2986:                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   2987:                                m68k_areg (regs, 7) -= 2;
                   2988:                                x_put_word (m68k_areg (regs, 7), 0);
                   2989:                                m68k_areg (regs, 7) -= 2;
                   2990:                                x_put_word (m68k_areg (regs, 7), 0);
                   2991:                                m68k_areg (regs, 7) -= 2;
                   2992:                                x_put_word (m68k_areg (regs, 7), 0);
                   2993:                                m68k_areg (regs, 7) -= 2;
                   2994:                                x_put_word (m68k_areg (regs, 7), ssw);
                   2995:                                m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     2996:                                x_put_word (m68k_areg (regs, 7), 0xb000 + vector_nr * 4);
1.1.1.4   root     2997:                        }
1.1.1.7 ! root     2998:                        write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, regs.instruction_pc, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
1.1.1.4   root     2999:                } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
                   3000:                        m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root     3001:                        x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     3002:                        m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     3003:                        x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
        !          3004:                } else if (regs.m && interrupt) { /* M + Interrupt */
1.1.1.4   root     3005:                        m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     3006:                        x_put_word (m68k_areg (regs, 7), vector_nr * 4);
1.1.1.4   root     3007:                        m68k_areg (regs, 7) -= 4;
                   3008:                        x_put_long (m68k_areg (regs, 7), currpc);
                   3009:                        m68k_areg (regs, 7) -= 2;
                   3010:                        x_put_word (m68k_areg (regs, 7), regs.sr);
                   3011:                        regs.sr |= (1 << 13);
                   3012:                        regs.msp = m68k_areg (regs, 7);
1.1.1.7 ! root     3013:                        regs.m = 0;
1.1.1.4   root     3014:                        m68k_areg (regs, 7) = regs.isp;
                   3015:                        m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     3016:                        x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
1.1.1.4   root     3017:                } else {
                   3018:                        m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root     3019:                        x_put_word (m68k_areg (regs, 7), vector_nr * 4);
        !          3020:                }
        !          3021:        } else {
        !          3022:                add_approximate_exception_cycles(nr);
        !          3023:                currpc = m68k_getpc ();
        !          3024: #ifdef WINUAE_FOR_HATARI
        !          3025:                LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d vector %x currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
        !          3026:                        nr, 4*vector_nr , currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*vector_nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
        !          3027: #endif
        !          3028:                if (nr == 2 || nr == 3) {
        !          3029:                        // 68000 address error
        !          3030:                        uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
        !          3031:                        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
        !          3032:                        mode |= last_notinstruction_for_exception_3 ? 8 : 0;
        !          3033:                        // undocumented bits seem to contain opcode
        !          3034:                        mode |= last_op_for_exception_3 & ~31;
        !          3035:                        m68k_areg (regs, 7) -= 14;
        !          3036:                        exception_in_exception = -1;
        !          3037:                        x_put_word (m68k_areg (regs, 7) + 0, mode);
        !          3038:                        x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
        !          3039:                        x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
        !          3040:                        x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
        !          3041:                        x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
        !          3042:                        write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
        !          3043: #ifdef WINUAE_FOR_HATARI
        !          3044:                        fprintf(stderr,"%s Error at address $%x, PC=$%x addr_e3=%x op_e3=%x\n", nr==2?"Bus":"Address", last_fault_for_exception_3, currpc, last_addr_for_exception_3 , last_op_for_exception_3);
        !          3045: #endif
        !          3046:                        goto kludge_me_do;
1.1.1.4   root     3047:                }
                   3048:        }
                   3049:        m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root     3050: #ifndef WINUAE_FOR_HATARI
        !          3051:        /* TODO NP check exception_pc() is fixed and remove ifndef */
1.1.1.4   root     3052:        x_put_long (m68k_areg (regs, 7), currpc);
1.1.1.7 ! root     3053: #else
        !          3054:        x_put_long (m68k_areg (regs, 7), m68k_getpc ());
        !          3055: #endif
        !          3056:        m68k_areg (regs, 7) -= 2;
1.1.1.4   root     3057:        x_put_word (m68k_areg (regs, 7), regs.sr);
                   3058: kludge_me_do:
1.1.1.7 ! root     3059:        newpc = x_get_long (regs.vbr + 4 * vector_nr);
        !          3060:        exception_in_exception = 0;
1.1.1.4   root     3061:        if (newpc & 1) {
                   3062:                if (nr == 2 || nr == 3)
1.1.1.7 ! root     3063:                        cpu_halt (2);
1.1.1.4   root     3064:                else
1.1.1.7 ! root     3065:                        exception3_notinstruction(regs.ir, newpc);
1.1.1.4   root     3066:                return;
                   3067:        }
                   3068:        m68k_setpc (newpc);
                   3069: #ifdef JIT
                   3070:        set_special (SPCFLAG_END_COMPILE);
                   3071: #endif
1.1.1.7 ! root     3072:        fill_prefetch ();
1.1.1.4   root     3073:        exception_trace (nr);
                   3074: }
                   3075: 
1.1.1.7 ! root     3076: // address = format $2 stack frame address field
        !          3077: static void ExceptionX (int nr, uaecptr address)
1.1.1.4   root     3078: {
1.1.1.7 ! root     3079:        regs.exception = nr;
        !          3080:        if (cpu_tracer) {
        !          3081:                cputrace.state = nr;
1.1.1.6   root     3082:        }
                   3083: 
1.1.1.7 ! root     3084: #ifdef JIT
        !          3085:        if (currprefs.cachesize)
        !          3086:                regs.instruction_pc = address == -1 ? m68k_getpc () : address;
        !          3087: #endif
        !          3088: #ifdef CPUEMU_13
        !          3089:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010)
        !          3090:                Exception_ce000 (nr);
1.1.1.4   root     3091:        else
                   3092: #endif
1.1.1.7 ! root     3093:                if (currprefs.mmu_model) {
        !          3094:                        if (currprefs.cpu_model == 68030)
        !          3095:                                Exception_mmu030 (nr, m68k_getpc ());
        !          3096:                        else
        !          3097:                                Exception_mmu (nr, m68k_getpc ());
        !          3098:                } else {
        !          3099:                        Exception_normal (nr);
        !          3100:                }
1.1.1.4   root     3101: 
1.1.1.7 ! root     3102: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3103:        if (debug_illegal && !in_rom (M68K_GETPC)) {
                   3104:                if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
1.1.1.7 ! root     3105:                        write_log (_T("Exception %d breakpoint\n"), nr);
1.1.1.4   root     3106:                        activate_debugger ();
                   3107:                }
                   3108:        }
                   3109: #endif
1.1.1.7 ! root     3110:        regs.exception = 0;
        !          3111:        if (cpu_tracer) {
        !          3112:                cputrace.state = 0;
        !          3113:        }
        !          3114: }
        !          3115: 
        !          3116: void REGPARAM2 Exception (int nr)
        !          3117: {
        !          3118:        ExceptionX (nr, -1);
        !          3119: }
        !          3120: void REGPARAM2 ExceptionL (int nr, uaecptr address)
        !          3121: {
        !          3122:        ExceptionX (nr, address);
1.1.1.4   root     3123: }
                   3124: 
1.1.1.7 ! root     3125: static void do_interrupt (int nr)
1.1.1.4   root     3126: {
1.1.1.7 ! root     3127: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3128:        if (debug_dma)
                   3129:                record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
1.1.1.7 ! root     3130: 
        !          3131:        if (inputrecord_debug & 2) {
        !          3132:                if (input_record > 0)
        !          3133:                        inprec_recorddebug_cpu (2);
        !          3134:                else if (input_play > 0)
        !          3135:                        inprec_playdebug_cpu (2);
        !          3136:        }
1.1.1.4   root     3137: #endif
                   3138: 
                   3139:        regs.stopped = 0;
                   3140:        unset_special (SPCFLAG_STOP);
                   3141:        assert (nr < 8 && nr >= 0);
                   3142: 
1.1.1.7 ! root     3143:        Exception (nr + 24);
1.1.1.4   root     3144: 
                   3145:        regs.intmask = nr;
                   3146:        doint ();
                   3147: }
                   3148: 
                   3149: void NMI (void)
                   3150: {
1.1.1.7 ! root     3151:        do_interrupt (7);
1.1.1.4   root     3152: }
                   3153: 
1.1.1.7 ! root     3154: static void m68k_reset_sr(void)
1.1.1.4   root     3155: {
1.1.1.7 ! root     3156:        SET_XFLG ((regs.sr >> 4) & 1);
        !          3157:        SET_NFLG ((regs.sr >> 3) & 1);
        !          3158:        SET_ZFLG ((regs.sr >> 2) & 1);
        !          3159:        SET_VFLG ((regs.sr >> 1) & 1);
        !          3160:        SET_CFLG (regs.sr & 1);
        !          3161:        regs.t1 = (regs.sr >> 15) & 1;
        !          3162:        regs.t0 = (regs.sr >> 14) & 1;
        !          3163:        regs.s  = (regs.sr >> 13) & 1;
        !          3164:        regs.m  = (regs.sr >> 12) & 1;
        !          3165:        regs.intmask = (regs.sr >> 8) & 7;
        !          3166:        /* set stack pointer */
        !          3167:        if (regs.s)
        !          3168:                m68k_areg (regs, 7) = regs.isp;
        !          3169:        else
        !          3170:                m68k_areg (regs, 7) = regs.usp;
1.1.1.4   root     3171: }
                   3172: 
1.1.1.7 ! root     3173: static void m68k_reset2(bool hardreset)
1.1.1.4   root     3174: {
1.1.1.7 ! root     3175:        uae_u32 v;
1.1.1.4   root     3176: 
1.1.1.7 ! root     3177:        regs.halted = 0;
        !          3178: #ifndef WINUAE_FOR_HATARI
        !          3179:        gui_data.cpu_halted = 0;
        !          3180:        gui_led (LED_CPU, 0, -1);
1.1.1.4   root     3181: #endif
                   3182: 
1.1.1.7 ! root     3183:        regs.spcflags = 0;
        !          3184:        m68k_reset_delay = 0;
        !          3185:        regs.ipl = regs.ipl_pin = 0;
1.1.1.4   root     3186: 
1.1.1.7 ! root     3187: #ifdef SAVESTATE
        !          3188:        if (isrestore ()) {
        !          3189:                m68k_reset_sr();
        !          3190:                m68k_setpc_normal (regs.pc);
1.1.1.4   root     3191:                return;
                   3192:        } else {
1.1.1.7 ! root     3193:                m68k_reset_delay = currprefs.reset_delay;
        !          3194:                set_special(SPCFLAG_CHECK);
1.1.1.4   root     3195:        }
                   3196: #endif
1.1.1.7 ! root     3197:        regs.s = 1;
        !          3198: #ifndef WINUAE_FOR_HATARI
        !          3199:        if (currprefs.cpuboard_type) {
        !          3200:                        uaecptr stack;
        !          3201:                v = cpuboard_get_reset_pc(&stack);
        !          3202:                m68k_areg (regs, 7) = stack;
1.1.1.4   root     3203:        } else {
1.1.1.7 ! root     3204:                v = get_long (4);
        !          3205:                m68k_areg (regs, 7) = get_long (0);
        !          3206:        }
1.1.1.4   root     3207: #else
1.1.1.7 ! root     3208:        v = get_long (4);
        !          3209:        m68k_areg (regs, 7) = get_long (0);
1.1.1.4   root     3210: #endif
1.1.1.7 ! root     3211:        m68k_setpc_normal(v);
1.1.1.4   root     3212:        regs.m = 0;
                   3213:        regs.stopped = 0;
                   3214:        regs.t1 = 0;
                   3215:        regs.t0 = 0;
                   3216:        SET_ZFLG (0);
                   3217:        SET_XFLG (0);
                   3218:        SET_CFLG (0);
                   3219:        SET_VFLG (0);
                   3220:        SET_NFLG (0);
                   3221:        regs.intmask = 7;
                   3222:        regs.vbr = regs.sfc = regs.dfc = 0;
                   3223:        regs.irc = 0xffff;
                   3224: #ifdef FPUEMU
                   3225:        fpu_reset ();
                   3226: #endif
                   3227:        regs.caar = regs.cacr = 0;
                   3228:        regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
                   3229:        regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
1.1.1.7 ! root     3230:        mmu_tt_modified (); 
1.1.1.4   root     3231:        if (currprefs.cpu_model == 68020) {
                   3232:                regs.cacr |= 8;
1.1.1.7 ! root     3233:                set_cpu_caches (false);
1.1.1.4   root     3234:        }
                   3235: 
                   3236:        mmufixup[0].reg = -1;
                   3237:        mmufixup[1].reg = -1;
1.1.1.7 ! root     3238:        if (currprefs.mmu_model >= 68040) {
        !          3239:                mmu_reset ();
        !          3240:                mmu_set_tc (regs.tcr);
        !          3241:                mmu_set_super (regs.s != 0);
        !          3242:        } else if (currprefs.mmu_model == 68030) {
        !          3243:                mmu030_reset (hardreset || regs.halted);
        !          3244:        } else {
        !          3245: #ifndef WINUAE_FOR_HATARI
        !          3246:                a3000_fakekick (0);
        !          3247: #endif
        !          3248:                /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
        !          3249:                fake_tc_030 &= ~0x80000000;
        !          3250:                fake_tt0_030 &= ~0x80000000;
        !          3251:                fake_tt1_030 &= ~0x80000000;
        !          3252:                if (hardreset || regs.halted) {
        !          3253:                        fake_srp_030 = fake_crp_030 = 0;
        !          3254:                        fake_tt0_030 = fake_tt1_030 = fake_tc_030 = 0;
1.1.1.5   root     3255:                }
1.1.1.7 ! root     3256:                fake_mmusr_030 = 0;
1.1.1.4   root     3257:        }
                   3258: 
                   3259:        /* 68060 FPU is not compatible with 68040,
                   3260:        * 68060 accelerators' boot ROM disables the FPU
                   3261:        */
                   3262:        regs.pcr = 0;
                   3263:        if (currprefs.cpu_model == 68060) {
                   3264:                regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
                   3265:                regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
1.1.1.7 ! root     3266: #ifndef WINUAE_FOR_HATARI
        !          3267:                if (kickstart_rom)
        !          3268:                        regs.pcr |= 2; /* disable FPU */
        !          3269: #endif
        !          3270:        }
        !          3271:        regs.ce020memcycles = 0;
        !          3272:        fill_prefetch ();
        !          3273: }
        !          3274: void m68k_reset(void)
        !          3275: {
        !          3276:        m68k_reset2(false);
        !          3277: }
        !          3278: 
        !          3279: 
        !          3280: void REGPARAM2 op_unimpl (uae_u16 opcode)
        !          3281: {
        !          3282:        static int warned;
        !          3283:        if (warned < 20) {
        !          3284:                write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
        !          3285:                warned++;
1.1.1.4   root     3286:        }
1.1.1.7 ! root     3287:        ExceptionL (61, regs.instruction_pc);
1.1.1.4   root     3288: }
                   3289: 
1.1.1.7 ! root     3290: uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
1.1.1.4   root     3291: {
                   3292:        uaecptr pc = m68k_getpc ();
                   3293:        static int warned;
                   3294: 
1.1.1.7 ! root     3295: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3296:        int inrom = in_rom (pc);
                   3297:        int inrt = in_rtarea (pc);
                   3298: 
                   3299:        if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
                   3300:                m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
1.1.1.7 ! root     3301:                m68k_incpc_normal (2);
        !          3302:                fill_prefetch ();
1.1.1.4   root     3303:                return 4;
                   3304:        }
                   3305: 
1.1.1.7 ! root     3306:        if (opcode == 0x4E7B && inrom) {
        !          3307:                if (get_long (0x10) == 0) {
        !          3308:                        notify_user (NUMSG_KS68020);
        !          3309:                        uae_restart (-1, NULL);
        !          3310:                }
1.1.1.4   root     3311:        }
                   3312: 
                   3313: #ifdef AUTOCONFIG
1.1.1.7 ! root     3314:        if (opcode == 0xFF0D && inrt) {
        !          3315:                /* User-mode STOP replacement */
        !          3316:                m68k_setstopped ();
        !          3317:                return 4;
1.1.1.4   root     3318:        }
                   3319: 
                   3320:        if ((opcode & 0xF000) == 0xA000 && inrt) {
                   3321:                /* Calltrap. */
1.1.1.7 ! root     3322:                m68k_incpc_normal (2);
        !          3323:                m68k_handle_trap(opcode & 0xFFF);
        !          3324:                fill_prefetch ();
1.1.1.4   root     3325:                return 4;
                   3326:        }
                   3327: #endif
1.1.1.7 ! root     3328: #endif
1.1.1.4   root     3329: 
                   3330:        if ((opcode & 0xF000) == 0xF000) {
1.1.1.7 ! root     3331: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3332:                if (warned < 20) {
1.1.1.7 ! root     3333:                        write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
1.1.1.4   root     3334:                        warned++;
                   3335:                }
1.1.1.7 ! root     3336: #endif
        !          3337:                Exception (0xB);
1.1.1.4   root     3338:                //activate_debugger ();
                   3339:                return 4;
                   3340:        }
                   3341:        if ((opcode & 0xF000) == 0xA000) {
1.1.1.7 ! root     3342: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3343:                if (warned < 20) {
1.1.1.7 ! root     3344:                        write_log(_T("A-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x28));
1.1.1.4   root     3345:                        warned++;
                   3346:                }
1.1.1.7 ! root     3347: #endif
        !          3348:                Exception (0xA);
1.1.1.4   root     3349:                //activate_debugger();
                   3350:                return 4;
                   3351:        }
                   3352:        if (warned < 20) {
1.1.1.7 ! root     3353:                write_log (_T("Illegal instruction: %04x at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x10));
1.1.1.4   root     3354:                warned++;
                   3355:                //activate_debugger();
                   3356:        }
                   3357: 
1.1.1.7 ! root     3358:        Exception (4);
1.1.1.4   root     3359:        return 4;
                   3360: }
                   3361: 
                   3362: #ifdef CPUEMU_0
                   3363: 
1.1.1.7 ! root     3364: static bool mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
1.1.1.4   root     3365: {
1.1.1.7 ! root     3366:        int mode = (opcode >> 3) & 7;
        !          3367:        int rreg = opcode & 7;
        !          3368:        int preg = (next >> 10) & 31;
        !          3369:        int rw = (next >> 9) & 1;
        !          3370:        int fd = (next >> 8) & 1;
        !          3371:        const TCHAR *reg = NULL;
        !          3372:        uae_u32 otc = fake_tc_030;
        !          3373:        int siz;
        !          3374: 
        !          3375:        // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
        !          3376:        if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode == 6 || (mode == 7 && rreg > 1)) {
1.1.1.4   root     3377:                op_illg (opcode);
1.1.1.7 ! root     3378:                return true;
1.1.1.4   root     3379:        }
1.1.1.5   root     3380: 
1.1.1.7 ! root     3381:        switch (preg)
        !          3382:        {
        !          3383:        case 0x10: // TC
        !          3384:                reg = _T("TC");
        !          3385:                siz = 4;
        !          3386:                if (rw)
        !          3387:                        x_put_long (extra, fake_tc_030);
        !          3388:                else
        !          3389:                        fake_tc_030 = x_get_long (extra);
        !          3390:                break;
        !          3391:        case 0x12: // SRP
        !          3392:                reg = _T("SRP");
        !          3393:                siz = 8;
        !          3394:                if (rw) {
        !          3395:                        x_put_long (extra, fake_srp_030 >> 32);
        !          3396:                        x_put_long (extra + 4, (uae_u32)fake_srp_030);
        !          3397:                } else {
        !          3398:                        fake_srp_030 = (uae_u64)x_get_long (extra) << 32;
        !          3399:                        fake_srp_030 |= x_get_long (extra + 4);
        !          3400:                }
        !          3401:                break;
        !          3402:        case 0x13: // CRP
        !          3403:                reg = _T("CRP");
        !          3404:                siz = 8;
        !          3405:                if (rw) {
        !          3406:                        x_put_long (extra, fake_crp_030 >> 32);
        !          3407:                        x_put_long (extra + 4, (uae_u32)fake_crp_030);
        !          3408:                } else {
        !          3409:                        fake_crp_030 = (uae_u64)x_get_long (extra) << 32;
        !          3410:                        fake_crp_030 |= x_get_long (extra + 4);
        !          3411:                }
        !          3412:                break;
        !          3413:        case 0x18: // MMUSR
        !          3414:                reg = _T("MMUSR");
        !          3415:                siz = 2;
        !          3416:                if (rw)
        !          3417:                        x_put_word (extra, fake_mmusr_030);
        !          3418:                else
        !          3419:                        fake_mmusr_030 = x_get_word (extra);
        !          3420:                break;
        !          3421:        case 0x02: // TT0
        !          3422:                reg = _T("TT0");
        !          3423:                siz = 4;
        !          3424:                if (rw)
        !          3425:                        x_put_long (extra, fake_tt0_030);
        !          3426:                else
        !          3427:                        fake_tt0_030 = x_get_long (extra);
        !          3428:                break;
        !          3429:        case 0x03: // TT1
        !          3430:                reg = _T("TT1");
        !          3431:                siz = 4;
        !          3432:                if (rw)
        !          3433:                        x_put_long (extra, fake_tt1_030);
        !          3434:                else
        !          3435:                        fake_tt1_030 = x_get_long (extra);
        !          3436:                break;
        !          3437:        }
1.1.1.4   root     3438: 
1.1.1.7 ! root     3439:        if (!reg) {
        !          3440:                op_illg (opcode);
        !          3441:                return true;
1.1.1.4   root     3442:        }
                   3443: #if MMUOP_DEBUG > 0
1.1.1.7 ! root     3444:        {
        !          3445:                uae_u32 val;
        !          3446:                if (siz == 8) {
        !          3447:                        uae_u32 val2 = x_get_long (extra);
        !          3448:                        val = x_get_long (extra + 4);
        !          3449:                        if (rw)
        !          3450:                                write_log (_T("PMOVE %s,%08X%08X"), reg, val2, val);
        !          3451:                        else
        !          3452:                                write_log (_T("PMOVE %08X%08X,%s"), val2, val, reg);
        !          3453:                } else {
        !          3454:                        if (siz == 4)
        !          3455:                                val = x_get_long (extra);
        !          3456:                        else
        !          3457:                                val = x_get_word (extra);
        !          3458:                        if (rw)
        !          3459:                                write_log (_T("PMOVE %s,%08X"), reg, val);
        !          3460:                        else
        !          3461:                                write_log (_T("PMOVE %08X,%s"), val, reg);
1.1.1.4   root     3462:                }
1.1.1.7 ! root     3463:                write_log (_T(" PC=%08X\n"), pc);
        !          3464:        }
1.1.1.4   root     3465: #endif
1.1.1.7 ! root     3466: #ifndef WINUAE_FOR_HATARI
        !          3467:        if ((currprefs.cs_mbdmac & 1) && currprefs.mbresmem_low_size > 0) {
        !          3468:                if (otc != fake_tc_030) {
        !          3469:                        a3000_fakekick (fake_tc_030 & 0x80000000);
1.1.1.4   root     3470:                }
                   3471:        }
                   3472: #endif
1.1.1.7 ! root     3473:        return false;
1.1.1.4   root     3474: }
                   3475: 
1.1.1.7 ! root     3476: static bool mmu_op30fake_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          3477: {
        !          3478: #if MMUOP_DEBUG > 0
        !          3479:        TCHAR tmp[10];
        !          3480: 
        !          3481:        tmp[0] = 0;
        !          3482:        if ((next >> 8) & 1)
        !          3483:                _stprintf (tmp, _T(",A%d"), (next >> 4) & 15);
        !          3484:        write_log (_T("PTEST%c %02X,%08X,#%X%s PC=%08X\n"),
        !          3485:                ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
1.1.1.4   root     3486: #endif
1.1.1.7 ! root     3487:        fake_mmusr_030 = 0;
        !          3488:        return false;
        !          3489: }
1.1.1.4   root     3490: 
1.1.1.7 ! root     3491: static bool mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          3492: {
        !          3493:        int mode = (opcode >> 3) & 7;
        !          3494:        int rreg = opcode & 7;
        !          3495:        int flushmode = (next >> 10) & 7;
        !          3496:        int fc = next & 31;
        !          3497:        int mask = (next >> 5) & 3;
        !          3498:        TCHAR fname[100];
        !          3499: 
        !          3500:        switch (flushmode)
        !          3501:        {
        !          3502:        case 6:
        !          3503:                // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
        !          3504:                if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode == 6 || (mode == 7 && rreg > 1)) {
        !          3505:                        op_illg (opcode);
        !          3506:                        return true;
        !          3507:                }
        !          3508:                _stprintf (fname, _T("FC=%x MASK=%x EA=%08x"), fc, mask, 0);
        !          3509:                break;
        !          3510:        case 4:
        !          3511:                _stprintf (fname, _T("FC=%x MASK=%x"), fc, mask);
        !          3512:                break;
        !          3513:        case 1:
        !          3514:                _tcscpy (fname, _T("ALL"));
        !          3515:                break;
        !          3516:        default:
        !          3517:                op_illg (opcode);
        !          3518:                return true;
        !          3519:        }
        !          3520: #if MMUOP_DEBUG > 0
        !          3521:        write_log (_T("PFLUSH %s PC=%08X\n"), fname, pc);
        !          3522: #endif
        !          3523:        return false;
        !          3524: }
        !          3525: 
        !          3526: // 68030 (68851) MMU instructions only
        !          3527: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
        !          3528: {
        !          3529:        if (currprefs.mmu_model) {
        !          3530:                if (extra & 0x8000) {
        !          3531:                        return mmu_op30_ptest (pc, opcode, extra, extraa);
        !          3532:                } else if ((extra&0xE000)==0x2000 && (extra & 0x1C00)) {
        !          3533:                        return mmu_op30_pflush (pc, opcode, extra, extraa);
        !          3534:                } else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00)) {
        !          3535:                return mmu_op30_pload (pc, opcode, extra, extraa);
        !          3536:                } else {
        !          3537:                        return mmu_op30_pmove (pc, opcode, extra, extraa);
        !          3538:                }
        !          3539:                return false;
        !          3540:        }
        !          3541: 
        !          3542:        int type = extra >> 13;
        !          3543: 
        !          3544:        switch (type)
        !          3545:        {
        !          3546:        case 0:
        !          3547:        case 2:
        !          3548:        case 3:
        !          3549:                return mmu_op30fake_pmove (pc, opcode, extra, extraa);
        !          3550:        break;
        !          3551:        case 1:
        !          3552:                return mmu_op30fake_pflush (pc, opcode, extra, extraa);
        !          3553:        break;
        !          3554:        case 4:
        !          3555:                return mmu_op30fake_ptest (pc, opcode, extra, extraa);
        !          3556:        break;
        !          3557:        default:
        !          3558:                op_illg (opcode);
        !          3559:                return true;
        !          3560:        break;
        !          3561:        }
        !          3562: }
        !          3563: 
        !          3564: // 68040+ MMU instructions only
        !          3565: void mmu_op (uae_u32 opcode, uae_u32 extra)
        !          3566: {
        !          3567:        if (currprefs.mmu_model) {
        !          3568:                mmu_op_real (opcode, extra);
        !          3569:                return;
        !          3570:        }
        !          3571: #if MMUOP_DEBUG > 1
        !          3572:        write_log (_T("mmu_op %04X PC=%08X\n"), opcode, m68k_getpc ());
        !          3573: #endif
        !          3574:        if ((opcode & 0xFE0) == 0x0500) {
        !          3575:                /* PFLUSH */
        !          3576:                regs.mmusr = 0;
        !          3577: #if MMUOP_DEBUG > 0
        !          3578:                write_log (_T("PFLUSH\n"));
        !          3579: #endif
        !          3580:                return;
        !          3581:        } else if ((opcode & 0x0FD8) == 0x548) {
        !          3582:                if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
        !          3583:                        /* PTEST */
        !          3584: #if MMUOP_DEBUG > 0
        !          3585:                        write_log (_T("PTEST\n"));
        !          3586: #endif
        !          3587:                        return;
        !          3588:                }
        !          3589:        } else if ((opcode & 0x0FB8) == 0x588) {
        !          3590:                /* PLPA */
        !          3591:                if (currprefs.cpu_model == 68060) {
        !          3592: #if MMUOP_DEBUG > 0
        !          3593:                        write_log (_T("PLPA\n"));
        !          3594: #endif
        !          3595:                        return;
        !          3596:                }
        !          3597:        }
        !          3598: #if MMUOP_DEBUG > 0
        !          3599:        write_log (_T("Unknown MMU OP %04X\n"), opcode);
        !          3600: #endif
        !          3601:        m68k_setpc_normal (m68k_getpc () - 2);
        !          3602:        op_illg (opcode);
        !          3603: }
        !          3604: 
        !          3605: #endif
        !          3606: 
        !          3607: static uaecptr last_trace_ad = 0;
1.1.1.4   root     3608: 
                   3609: static void do_trace (void)
                   3610: {
                   3611:        if (regs.t0 && currprefs.cpu_model >= 68020) {
                   3612:                uae_u16 opcode;
                   3613:                /* should also include TRAP, CHK, SR modification FPcc */
                   3614:                /* probably never used so why bother */
                   3615:                /* We can afford this to be inefficient... */
1.1.1.7 ! root     3616:                m68k_setpc_normal (m68k_getpc ());
        !          3617:                fill_prefetch ();
1.1.1.4   root     3618:                opcode = x_get_word (regs.pc);
                   3619:                if (opcode == 0x4e73                    /* RTE */
                   3620:                        || opcode == 0x4e74             /* RTD */
                   3621:                        || opcode == 0x4e75             /* RTS */
                   3622:                        || opcode == 0x4e77             /* RTR */
                   3623:                        || opcode == 0x4e76             /* TRAPV */
                   3624:                        || (opcode & 0xffc0) == 0x4e80  /* JSR */
                   3625:                        || (opcode & 0xffc0) == 0x4ec0  /* JMP */
                   3626:                        || (opcode & 0xff00) == 0x6100  /* BSR */
                   3627:                        || ((opcode & 0xf000) == 0x6000 /* Bcc */
                   3628:                        && cctrue ((opcode >> 8) & 0xf))
                   3629:                        || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
                   3630:                        && !cctrue ((opcode >> 8) & 0xf)
                   3631:                        && (uae_s16)m68k_dreg (regs, opcode & 7) != 0))
                   3632:                {
                   3633:                        last_trace_ad = m68k_getpc ();
                   3634:                        unset_special (SPCFLAG_TRACE);
                   3635:                        set_special (SPCFLAG_DOTRACE);
                   3636:                }
                   3637:        } else if (regs.t1) {
                   3638:                last_trace_ad = m68k_getpc ();
                   3639:                unset_special (SPCFLAG_TRACE);
                   3640:                set_special (SPCFLAG_DOTRACE);
                   3641:        }
                   3642: }
                   3643: 
1.1.1.7 ! root     3644: static void check_uae_int_request(void)
        !          3645: {
        !          3646: #ifndef WINUAE_FOR_HATARI
        !          3647:        if (uae_int_requested || uaenet_int_requested) {
        !          3648:                if ((uae_int_requested & 0x00ff) || uaenet_int_requested)
        !          3649:                        INTREQ_f(0x8000 | 0x0008);
        !          3650:                if (uae_int_requested & 0xff00)
        !          3651:                        INTREQ_f(0x8000 | 0x2000);
        !          3652:                set_special(SPCFLAG_INT);
        !          3653:        }
        !          3654: #endif
        !          3655: }
1.1.1.4   root     3656: 
1.1.1.7 ! root     3657: void cpu_sleep_millis(int ms)
1.1.1.4   root     3658: {
1.1.1.7 ! root     3659: #ifndef WINUAE_FOR_HATARI
        !          3660: #ifdef WITH_PPC
        !          3661:        int state = ppc_state;
        !          3662:        if (state)
        !          3663:                uae_ppc_spinlock_release();
        !          3664: #endif
        !          3665:        sleep_millis_main(ms);
        !          3666: #ifdef WITH_PPC
        !          3667:        if (state)
        !          3668:                uae_ppc_spinlock_get();
        !          3669: #endif
        !          3670: #endif
        !          3671: }
        !          3672: 
        !          3673: #define PPC_HALTLOOP_SCANLINES 25
        !          3674: // ppc_cpu_idle
        !          3675: // 0 = busy
        !          3676: // 1-9 = wait, levels
        !          3677: // 10 = max wait
        !          3678: 
        !          3679: static bool haltloop(void)
        !          3680: {
        !          3681: #ifndef WINUAE_FOR_HATARI
        !          3682: #ifdef WITH_PPC
        !          3683:        if (regs.halted < 0) {
        !          3684:                int rpt_end = 0;
        !          3685:                int ovpos = vpos;
        !          3686: 
        !          3687:                while (regs.halted) {
        !          3688:                        int vsynctimeline = vsynctimebase / (maxvpos_display + 1);
        !          3689:                        int lines;
        !          3690:                        int rpt_scanline = read_processor_time();
        !          3691:                        int rpt_end = rpt_scanline + vsynctimeline;
        !          3692: 
        !          3693:                        // See expansion handling.
        !          3694:                        // Dialog must be opened from main thread.
        !          3695:                        if (regs.halted == -2) {
        !          3696:                                regs.halted = -1;
        !          3697:                                notify_user (NUMSG_UAEBOOTROM_PPC);
        !          3698:                        }
        !          3699: 
        !          3700:                        if (currprefs.ppc_cpu_idle) {
        !          3701: 
        !          3702:                                int maxlines = 100 - (currprefs.ppc_cpu_idle - 1) * 10;
        !          3703:                                int i;
        !          3704: 
        !          3705:                                event_wait = false;
        !          3706:                                for (i = 0; i < ev_max; i++) {
        !          3707:                                        if (i == ev_hsync)
        !          3708:                                                continue;
        !          3709:                                        if (i == ev_audio)
        !          3710:                                                continue;
        !          3711:                                        if (!eventtab[i].active)
        !          3712:                                                continue;
        !          3713:                                        if (eventtab[i].evtime - currcycle < maxlines * maxhpos * CYCLE_UNIT)
        !          3714:                                                break;
        !          3715:                                }
        !          3716:                                if (currprefs.ppc_cpu_idle >= 10 || (i == ev_max && vpos > 0 && vpos < maxvpos - maxlines)) {
        !          3717:                                        cpu_sleep_millis(1);
        !          3718:                                }
        !          3719:                                check_uae_int_request();
        !          3720:                                uae_ppc_execute_check();
        !          3721: 
        !          3722:                                lines = (read_processor_time() - rpt_scanline) / vsynctimeline + 1;
        !          3723: 
        !          3724:                        } else {
        !          3725: 
        !          3726:                                event_wait = true;
        !          3727:                                lines = 0;
        !          3728: 
        !          3729:                        }
        !          3730: 
        !          3731:                        if (lines > maxvpos / 2)
        !          3732:                                lines = maxvpos / 2;
        !          3733: 
        !          3734:                        while (lines-- >= 0) {
        !          3735:                                ovpos = vpos;
        !          3736:                                while (ovpos == vpos) {
        !          3737:                                        x_do_cycles(8 * CYCLE_UNIT);
        !          3738:                                        uae_ppc_execute_check();
        !          3739:                                        if (regs.spcflags & SPCFLAG_COPPER)
        !          3740:                                                do_copper();
        !          3741:                                        if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
        !          3742:                                                if (regs.spcflags & SPCFLAG_BRK) {
        !          3743:                                                        unset_special(SPCFLAG_BRK);
        !          3744: #ifdef DEBUGGER
        !          3745:                                                        if (debugging)
        !          3746:                                                                debug();
        !          3747: #endif
        !          3748:                                                }
        !          3749:                                                return true;
        !          3750:                                        }
        !          3751:                                }
        !          3752: 
        !          3753:                                // sync chipset with real time
        !          3754:                                for (;;) {
        !          3755:                                        check_uae_int_request();
        !          3756:                                        ppc_interrupt(intlev());
        !          3757:                                        uae_ppc_execute_check();
        !          3758:                                        if (event_wait)
        !          3759:                                                break;
        !          3760:                                        int d = read_processor_time() - rpt_end;
        !          3761:                                        if (d < -2 * vsynctimeline || d >= 0)
        !          3762:                                                break;
        !          3763:                                }
        !          3764:                        }
        !          3765: 
        !          3766: 
1.1.1.4   root     3767:                }
1.1.1.7 ! root     3768: 
        !          3769:        } else  {
1.1.1.4   root     3770: #endif
1.1.1.7 ! root     3771:                while (regs.halted) {
        !          3772:                        static int prevvpos;
        !          3773:                        if (vpos == 0 && prevvpos) {
        !          3774:                                prevvpos = 0;
        !          3775:                                cpu_sleep_millis(8);
        !          3776:                        }
        !          3777:                        if (vpos)
        !          3778:                                prevvpos = 1;
        !          3779:                        x_do_cycles(8 * CYCLE_UNIT);
        !          3780: 
        !          3781:                        if (regs.spcflags & SPCFLAG_COPPER)
        !          3782:                                do_copper();
        !          3783: 
        !          3784:                        if (regs.spcflags) {
        !          3785:                                if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
        !          3786:                                        return true;
        !          3787:                        }
        !          3788:                }
        !          3789: #ifdef WITH_PPC
1.1.1.4   root     3790:        }
1.1.1.7 ! root     3791: #endif
        !          3792: 
        !          3793:        return false;
        !          3794: #else
        !          3795:        /* In Hatari, we don't use the halt state, we do a reset */
        !          3796:        return false;
        !          3797: #endif
1.1.1.4   root     3798: }
                   3799: 
1.1.1.7 ! root     3800: #ifdef WITH_PPC
        !          3801: static bool uae_ppc_poll_check_halt(void)
1.1.1.4   root     3802: {
1.1.1.7 ! root     3803:        if (regs.halted) {
        !          3804:                if (haltloop())
        !          3805:                        return true;
1.1.1.4   root     3806:        }
1.1.1.7 ! root     3807:        return false;
1.1.1.4   root     3808: }
1.1.1.7 ! root     3809: #endif
1.1.1.4   root     3810: 
                   3811: 
1.1.1.7 ! root     3812: // handle interrupt delay (few cycles)
        !          3813: STATIC_INLINE bool time_for_interrupt (void)
1.1.1.4   root     3814: {
1.1.1.7 ! root     3815:        return regs.ipl > regs.intmask || regs.ipl == 7;
        !          3816: }
1.1.1.4   root     3817: 
1.1.1.7 ! root     3818: void doint (void)
        !          3819: {
        !          3820: #ifdef WITH_PPC
        !          3821:        if (ppc_state) {
        !          3822:                if (!ppc_interrupt(intlev()))
        !          3823:                        return;
1.1.1.4   root     3824:        }
1.1.1.7 ! root     3825: #endif
        !          3826:        if (m68k_interrupt_delay) {
        !          3827:                regs.ipl_pin = intlev ();
        !          3828:                unset_special (SPCFLAG_INT);
        !          3829:                return;
1.1.1.4   root     3830:        }
1.1.1.7 ! root     3831:        if (currprefs.cpu_compatible && currprefs.cpu_model < 68020)
        !          3832:                set_special (SPCFLAG_INT);
        !          3833:        else
        !          3834:                set_special (SPCFLAG_DOINT);
1.1.1.4   root     3835: }
                   3836: 
1.1.1.7 ! root     3837: #ifndef WINUAE_FOR_HATARI
        !          3838: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 1000)
        !          3839: #endif
1.1.1.4   root     3840: 
1.1.1.7 ! root     3841: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     3842: /*
                   3843:  * Handle special flags
                   3844:  */
                   3845: 
                   3846: static bool do_specialties_interrupt (int Pending)
                   3847: {
1.1.1.5   root     3848: #if ENABLE_DSP_EMU
                   3849:     /* Check for DSP int first (if enabled) (level 6) */
                   3850:     if (regs.spcflags & SPCFLAG_DSP) {
                   3851:        if (DSP_ProcessIRQ() == true)
                   3852:          return true;
                   3853:     }
                   3854: #endif
                   3855: 
                   3856:     /* Check for MFP ints (level 6) */
1.1.1.4   root     3857:     if (regs.spcflags & SPCFLAG_MFP) {
1.1.1.5   root     3858:        if (MFP_ProcessIRQ() == true)
1.1.1.4   root     3859:          return true;                                  /* MFP exception was generated, no higher interrupt can happen */
                   3860:     }
                   3861: 
                   3862:     /* No MFP int, check for VBL/HBL ints (levels 4/2) */
                   3863:     if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
                   3864:        int intr = intlev ();
                   3865:        /* SPCFLAG_DOINT will be enabled again in MakeFromSR to handle pending interrupts! */
                   3866: //     unset_special (SPCFLAG_DOINT);
                   3867:        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   3868:        if (intr != -1 && intr > regs.intmask) {
1.1.1.7 ! root     3869:            do_interrupt (intr);                        /* process the interrupt */
1.1.1.4   root     3870:            return true;
                   3871:        }
                   3872:     }
                   3873: 
                   3874:     return false;                                      /* no interrupt was found */
                   3875: }
1.1.1.7 ! root     3876: #endif
1.1.1.4   root     3877: 
1.1.1.7 ! root     3878: static int do_specialties (int cycles)
1.1.1.4   root     3879: {
1.1.1.7 ! root     3880:        if (regs.spcflags & SPCFLAG_MODE_CHANGE)
        !          3881:                return 1;
        !          3882:        
        !          3883: #ifndef WINUAE_FOR_HATARI
        !          3884:        if (regs.spcflags & SPCFLAG_CHECK) {
        !          3885:                if (regs.halted) {
        !          3886:                        if (haltloop())
        !          3887:                                return 1;
        !          3888:                }
        !          3889:                if (m68k_reset_delay) {
        !          3890:                        int vsynccnt = 60;
        !          3891:                        int vsyncstate = -1;
        !          3892:                        while (vsynccnt > 0 && !quit_program) {
        !          3893:                                x_do_cycles(8 * CYCLE_UNIT);
        !          3894:                                if (regs.spcflags & SPCFLAG_COPPER)
        !          3895:                                        do_copper();
        !          3896:                                if (timeframes != vsyncstate) {
        !          3897:                                        vsyncstate = timeframes;
        !          3898:                                        vsynccnt--;
        !          3899:                                }
        !          3900:                        }
        !          3901:                }
        !          3902:                m68k_reset_delay = 0;
        !          3903:                unset_special(SPCFLAG_CHECK);
        !          3904:        }
        !          3905: #endif
        !          3906: 
        !          3907: #ifdef ACTION_REPLAY
        !          3908: #ifdef ACTION_REPLAY_HRTMON
        !          3909:        if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
        !          3910:                int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size);
        !          3911:                /* exit from HRTMon? */
        !          3912:                if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
        !          3913:                        hrtmon_hide ();
        !          3914:                /* HRTMon breakpoint? (not via IRQ7) */
        !          3915:                if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt)
        !          3916:                        hrtmon_breakenter ();
        !          3917:                if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
        !          3918:                        hrtmon_enter ();
        !          3919:        }
        !          3920: #endif
        !          3921:        if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) {
        !          3922:                /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/
        !          3923:                /*      write_log (_T("PC:%p\n"), m68k_getpc ());*/
        !          3924: 
        !          3925:                if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
        !          3926:                        action_replay_enter ();
        !          3927:                if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom ()) {
        !          3928:                        action_replay_hide ();
        !          3929:                        unset_special (SPCFLAG_ACTION_REPLAY);
        !          3930:                }
        !          3931:                if (action_replay_flag == ACTION_REPLAY_WAIT_PC) {
        !          3932:                        /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/
        !          3933:                        if (m68k_getpc () == wait_for_pc) {
        !          3934:                                action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
        !          3935:                        }
        !          3936:                }
        !          3937:        }
        !          3938: #endif
        !          3939: 
        !          3940: #ifndef WINUAE_FOR_HATARI
        !          3941:        if (regs.spcflags & SPCFLAG_COPPER)
        !          3942:                do_copper ();
        !          3943: #endif
        !          3944: 
1.1.1.4   root     3945: #ifdef JIT
                   3946:        unset_special (SPCFLAG_END_COMPILE);   /* has done its job */
                   3947: #endif
                   3948: 
1.1.1.7 ! root     3949: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3950:        while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
                   3951:                int c = blitnasty ();
1.1.1.7 ! root     3952:                if (c < 0) {
        !          3953:                        break;
        !          3954:                } else if (c > 0) {
1.1.1.4   root     3955:                        cycles -= c * CYCLE_UNIT * 2;
                   3956:                        if (cycles < CYCLE_UNIT)
                   3957:                                cycles = 0;
1.1.1.7 ! root     3958:                } else {
1.1.1.4   root     3959:                        c = 4;
1.1.1.7 ! root     3960:                }
        !          3961:                x_do_cycles (c * CYCLE_UNIT);
1.1.1.4   root     3962:                if (regs.spcflags & SPCFLAG_COPPER)
                   3963:                        do_copper ();
1.1.1.7 ! root     3964: #ifdef WITH_PPC
        !          3965:                if (ppc_state)  {
        !          3966:                        if (uae_ppc_poll_check_halt())
        !          3967:                                return true;
        !          3968:                        uae_ppc_execute_check();
        !          3969:                }
        !          3970: #endif
1.1.1.4   root     3971:        }
                   3972: #endif
                   3973: 
1.1.1.7 ! root     3974: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     3975:        if (regs.spcflags & SPCFLAG_BUSERROR) {
                   3976:                /* We can not execute bus errors directly in the memory handler
                   3977:                * functions since the PC should point to the address of the next
                   3978:                * instruction, so we're executing the bus errors here: */
                   3979:                unset_special(SPCFLAG_BUSERROR);
1.1.1.7 ! root     3980:                Exception(2);
1.1.1.4   root     3981:        }
1.1.1.7 ! root     3982: #endif
1.1.1.4   root     3983: 
                   3984:        if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.7 ! root     3985:                Exception (9);
1.1.1.4   root     3986: 
1.1.1.7 ! root     3987: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3988:        if (regs.spcflags & SPCFLAG_TRAP) {
                   3989:                unset_special (SPCFLAG_TRAP);
1.1.1.7 ! root     3990:                Exception (3);
1.1.1.4   root     3991:        }
1.1.1.7 ! root     3992: #endif
        !          3993:        bool first = true;
        !          3994:        while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
        !          3995:        isstopped:
        !          3996: #ifndef WINUAE_FOR_HATARI
        !          3997:                check_uae_int_request();
        !          3998:                {
        !          3999:                        extern void bsdsock_fake_int_handler (void);
        !          4000:                        extern int volatile bsd_int_requested;
        !          4001:                        if (bsd_int_requested)
        !          4002:                                bsdsock_fake_int_handler ();
        !          4003:                }
        !          4004: #endif
        !          4005: 
        !          4006:                if (cpu_tracer > 0) {
        !          4007:                        cputrace.stopped = regs.stopped;
        !          4008:                        cputrace.intmask = regs.intmask;
        !          4009:                        cputrace.sr = regs.sr;
        !          4010:                        cputrace.state = 1;
        !          4011:                        cputrace.pc = m68k_getpc ();
        !          4012:                        cputrace.memoryoffset = 0;
        !          4013:                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
        !          4014:                        cputrace.readcounter = cputrace.writecounter = 0;
        !          4015:                }
        !          4016:                if (!first)
        !          4017:                        x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
1.1.1.4   root     4018: 
1.1.1.7 ! root     4019: #ifdef WINUAE_FOR_HATARI
        !          4020:                if (!first)
        !          4021:                {
        !          4022:                        if ( currprefs.cpu_cycle_exact )
        !          4023:                                M68000_AddCycles(2);
        !          4024:                        else                                            /* TODO [NP] : always do only M68000_AddCycles(2) ? */
        !          4025:                                M68000_AddCycles(4);
        !          4026:                }
1.1.1.4   root     4027: 
                   4028:                /* It is possible one or more ints happen at the same time */
1.1.1.5   root     4029:                /* We must process them during the same cpu cycle then choose the highest priority one */
                   4030:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
1.1.1.7 ! root     4031:                        CALL_VAR(PendingInterruptFunction);
1.1.1.5   root     4032:                if ( MFP_UpdateNeeded == true )
1.1.1.7 ! root     4033:                        MFP_UpdateIRQ ( 0 );
1.1.1.4   root     4034: 
1.1.1.5   root     4035:                /* Check is there's an interrupt to process (could be a delayed MFP interrupt) */
1.1.1.7 ! root     4036:                if (regs.spcflags & SPCFLAG_MFP) {
        !          4037:                        MFP_DelayIRQ ();                        /* Handle IRQ propagation */
        !          4038:                        M68000_Update_intlev ();                /* Refresh the list of pending interrupts */
1.1.1.5   root     4039:                }
1.1.1.7 ! root     4040: #endif
        !          4041:                first = false;
        !          4042: #ifndef WINUAE_FOR_HATARI
1.1.1.5   root     4043:                if (regs.spcflags & SPCFLAG_COPPER)
                   4044:                        do_copper ();
1.1.1.4   root     4045: #endif
                   4046: 
1.1.1.7 ! root     4047:                if (m68k_interrupt_delay) {
1.1.1.5   root     4048:                        ipl_fetch ();
                   4049:                        if (time_for_interrupt ()) {
1.1.1.7 ! root     4050:                                do_interrupt (regs.ipl);
1.1.1.5   root     4051:                        }
                   4052:                } else {
1.1.1.7 ! root     4053:                        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
        !          4054:                                int intr = intlev ();
        !          4055:                                unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
        !          4056: #ifdef WITH_PPC
        !          4057:                                bool m68kint = true;
        !          4058:                                if (ppc_state) {
        !          4059:                                        m68kint = ppc_interrupt(intr);
        !          4060:                                }
        !          4061:                                if (m68kint) {
1.1.1.4   root     4062: #endif
1.1.1.7 ! root     4063:                                        if (intr > 0 && intr > regs.intmask)
        !          4064:                                                do_interrupt (intr);
        !          4065: #ifdef WITH_PPC
        !          4066:                                }
        !          4067: #endif
        !          4068:                        }
1.1.1.5   root     4069:                }
1.1.1.7 ! root     4070: 
        !          4071:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
        !          4072:                        m68k_resumestopped();
1.1.1.5   root     4073:                        return 1;
                   4074:                }
1.1.1.4   root     4075: 
1.1.1.7 ! root     4076: #ifdef WITH_PPC
        !          4077:                if (ppc_state) {
        !          4078:                        uae_ppc_execute_check();
        !          4079:                        uae_ppc_poll_check_halt();
1.1.1.4   root     4080:                }
1.1.1.7 ! root     4081: #endif
        !          4082: 
1.1.1.4   root     4083:        }
                   4084: 
                   4085:        if (regs.spcflags & SPCFLAG_TRACE)
                   4086:                do_trace ();
                   4087: 
1.1.1.7 ! root     4088: #ifdef WINUAE_FOR_HATARI
        !          4089:        if (regs.spcflags & SPCFLAG_MFP) {
        !          4090:                MFP_DelayIRQ ();                        /* Handle IRQ propagation */
        !          4091:                M68000_Update_intlev ();                /* Refresh the list of pending interrupts */
        !          4092:        }
        !          4093: #endif
        !          4094: 
        !          4095:        if (m68k_interrupt_delay) {
1.1.1.4   root     4096:                if (time_for_interrupt ()) {
1.1.1.7 ! root     4097:                        do_interrupt (regs.ipl);
1.1.1.4   root     4098:                }
                   4099:        } else {
                   4100:                if (regs.spcflags & SPCFLAG_INT) {
                   4101:                        int intr = intlev ();
                   4102:                        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   4103:                        if (intr > 0 && (intr > regs.intmask || intr == 7))
1.1.1.7 ! root     4104:                                do_interrupt (intr);
1.1.1.4   root     4105:                }
                   4106:        }
                   4107: 
                   4108:        if (regs.spcflags & SPCFLAG_DOINT) {
                   4109:                unset_special (SPCFLAG_DOINT);
                   4110:                set_special (SPCFLAG_INT);
                   4111:        }
                   4112: 
1.1.1.7 ! root     4113: #ifdef WINUAE_FOR_HATARI
        !          4114:         if (regs.spcflags & SPCFLAG_DEBUGGER)
1.1.1.4   root     4115:                DebugCpu_Check();
1.1.1.7 ! root     4116: #endif
1.1.1.4   root     4117: 
1.1.1.7 ! root     4118:        if (regs.spcflags & SPCFLAG_BRK) {
        !          4119:                unset_special(SPCFLAG_BRK);
        !          4120: #ifdef DEBUGGER
        !          4121:                if (debugging) {
        !          4122:                        debug();
        !          4123:                        if (regs.stopped)
        !          4124:                                goto isstopped;
        !          4125:                }
        !          4126: #endif
        !          4127: #ifdef WINUAE_FOR_HATARI
        !          4128:                return 1;                       /* Exit the upper run_xxx() function */
        !          4129: #endif
1.1.1.4   root     4130:        }
1.1.1.7 ! root     4131: 
1.1.1.4   root     4132:        return 0;
                   4133: }
                   4134: 
                   4135: //static uae_u32 pcs[1000];
                   4136: 
1.1.1.7 ! root     4137: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4138: #if DEBUG_CD32CDTVIO
                   4139: 
                   4140: static uae_u32 cd32nextpc, cd32request;
                   4141: 
                   4142: static void out_cd32io2 (void)
                   4143: {
                   4144:        uae_u32 request = cd32request;
1.1.1.7 ! root     4145:        write_log (_T("%08x returned\n"), request);
        !          4146:        //write_log (_T("ACTUAL=%d ERROR=%d\n"), get_long (request + 32), get_byte (request + 31));
1.1.1.4   root     4147:        cd32nextpc = 0;
                   4148:        cd32request = 0;
                   4149: }
                   4150: 
                   4151: static void out_cd32io (uae_u32 pc)
                   4152: {
                   4153:        TCHAR out[100];
                   4154:        int ioreq = 0;
                   4155:        uae_u32 request = m68k_areg (regs, 1);
                   4156: 
                   4157:        if (pc == cd32nextpc) {
                   4158:                out_cd32io2 ();
                   4159:                return;
                   4160:        }
                   4161:        out[0] = 0;
                   4162:        switch (pc)
                   4163:        {
                   4164:        case 0xe57cc0:
                   4165:        case 0xf04c34:
1.1.1.7 ! root     4166:                _stprintf (out, _T("opendevice"));
1.1.1.4   root     4167:                break;
                   4168:        case 0xe57ce6:
                   4169:        case 0xf04c56:
1.1.1.7 ! root     4170:                _stprintf (out, _T("closedevice"));
1.1.1.4   root     4171:                break;
                   4172:        case 0xe57e44:
                   4173:        case 0xf04f2c:
1.1.1.7 ! root     4174:                _stprintf (out, _T("beginio"));
1.1.1.4   root     4175:                ioreq = 1;
                   4176:                break;
                   4177:        case 0xe57ef2:
                   4178:        case 0xf0500e:
1.1.1.7 ! root     4179:                _stprintf (out, _T("abortio"));
1.1.1.4   root     4180:                ioreq = -1;
                   4181:                break;
                   4182:        }
                   4183:        if (out[0] == 0)
                   4184:                return;
                   4185:        if (cd32request)
1.1.1.7 ! root     4186:                write_log (_T("old request still not returned!\n"));
1.1.1.4   root     4187:        cd32request = request;
                   4188:        cd32nextpc = get_long (m68k_areg (regs, 7));
1.1.1.7 ! root     4189:        write_log (_T("%s A1=%08X\n"), out, request);
1.1.1.4   root     4190:        if (ioreq) {
                   4191:                static int cnt = 0;
                   4192:                int cmd = get_word (request + 28);
                   4193: #if 0
1.1.1.7 ! root     4194:                if (cmd == 33) {
        !          4195:                        uaecptr data = get_long (request + 40);
        !          4196:                        write_log (_T("CD_CONFIG:\n"));
        !          4197:                        for (int i = 0; i < 16; i++) {
        !          4198:                                write_log (_T("%08X=%08X\n"), get_long (data), get_long (data + 4));
        !          4199:                                data += 8;
        !          4200:                        }
        !          4201:                }
        !          4202: #endif
        !          4203: #if 0
1.1.1.4   root     4204:                if (cmd == 37) {
                   4205:                        cnt--;
                   4206:                        if (cnt <= 0)
                   4207:                                activate_debugger ();
                   4208:                }
                   4209: #endif
1.1.1.7 ! root     4210:                write_log (_T("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n"),
        !          4211:                        cmd, get_long (request + 40),
        !          4212:                        get_long (request + 36), get_long (request + 44), M68K_GETPC);
1.1.1.4   root     4213:        }
                   4214:        if (ioreq < 0)
                   4215:                ;//activate_debugger ();
                   4216: }
                   4217: 
1.1.1.7 ! root     4218: #endif
        !          4219: #endif
        !          4220: 
        !          4221: static void bus_error(void)
        !          4222: {
        !          4223:        TRY (prb2) {
        !          4224:                Exception (2);
        !          4225:        } CATCH (prb2) {
        !          4226:                cpu_halt (1);
        !          4227:        } ENDTRY
        !          4228: }
1.1.1.4   root     4229: 
                   4230: #ifndef CPUEMU_11
                   4231: 
                   4232: static void m68k_run_1 (void)
                   4233: {
                   4234: }
                   4235: 
                   4236: #else
                   4237: 
                   4238: /* It's really sad to have two almost identical functions for this, but we
                   4239: do it all for performance... :(
                   4240: This version emulates 68000's prefetch "cache" */
                   4241: static void m68k_run_1 (void)
                   4242: {
                   4243:        struct regstruct *r = &regs;
1.1.1.7 ! root     4244:        bool exit = false;
        !          4245: printf ( "run_1\n" );
1.1.1.4   root     4246: 
1.1.1.7 ! root     4247:        while (!exit) {
        !          4248:                TRY (prb) {
        !          4249:                        while (!exit) {
        !          4250:                                r->opcode = r->ir;
        !          4251: 
        !          4252:                                count_instr (r->opcode);
        !          4253: 
        !          4254: #ifdef WINUAE_FOR_HATARI
        !          4255:                                //m68k_dumpstate_file(stderr, NULL);
        !          4256:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          4257:                                {
        !          4258:                                        int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4   root     4259: 
1.1.1.7 ! root     4260:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4   root     4261: 
1.1.1.7 ! root     4262:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          4263:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          4264:                                }
        !          4265: #endif
1.1.1.4   root     4266: 
1.1.1.7 ! root     4267: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4268: #if DEBUG_CD32CDTVIO
1.1.1.7 ! root     4269:                                out_cd32io (m68k_getpc ());
        !          4270: #endif
1.1.1.4   root     4271: #endif
                   4272: 
                   4273: #if 0
1.1.1.7 ! root     4274:                                int pc = m68k_getpc ();
        !          4275:                                if (pc == 0xdff002)
        !          4276:                                        write_log (_T("hip\n"));
        !          4277:                                if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
        !          4278:                                        memmove (pcs + 1, pcs, 998 * 4);
        !          4279:                                        pcs[0] = pc;
        !          4280:                                        //write_log (_T("%08X-%04X "), pc, r->opcode);
        !          4281:                                }
1.1.1.4   root     4282: #endif
1.1.1.7 ! root     4283:                                do_cycles (cpu_cycles);
        !          4284:                                r->instruction_pc = m68k_getpc ();
        !          4285:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
        !          4286:                                cpu_cycles = adjust_cycles (cpu_cycles);
        !          4287: 
        !          4288: #ifdef WINUAE_FOR_HATARI
        !          4289:                                M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT);
        !          4290: 
        !          4291:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          4292:                                        /* Add some extra cycles to simulate a wait state */
        !          4293:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          4294:                                        M68000_AddCycles(nWaitStateCycles);
        !          4295:                                        nWaitStateCycles = 0;
        !          4296:                                }
1.1.1.5   root     4297: 
1.1.1.7 ! root     4298:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          4299:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          4300:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          4301:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          4302:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          4303:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          4304:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          4305:                                if ( MFP_UpdateNeeded == true )
        !          4306:                                        MFP_UpdateIRQ ( 0 );
        !          4307: #endif
1.1.1.4   root     4308: 
1.1.1.7 ! root     4309:                                if (r->spcflags) {
        !          4310:                                        if (do_specialties (cpu_cycles))
        !          4311:                                                exit = true;
        !          4312:                                }
        !          4313:                                regs.ipl = regs.ipl_pin;
        !          4314:                                if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010))
        !          4315:                                        exit = true;
        !          4316:                        }
        !          4317:                } CATCH (prb) {
        !          4318:                        bus_error();
        !          4319:                        if (r->spcflags) {
        !          4320:                                if (do_specialties(cpu_cycles))
        !          4321:                                        exit = true;
        !          4322:                        }
        !          4323:                        regs.ipl = regs.ipl_pin;
        !          4324:                } ENDTRY
        !          4325:        }
        !          4326: }
1.1.1.4   root     4327: 
                   4328: #endif /* CPUEMU_11 */
                   4329: 
1.1.1.7 ! root     4330: #ifndef CPUEMU_13
1.1.1.4   root     4331: 
                   4332: static void m68k_run_1_ce (void)
                   4333: {
                   4334: }
                   4335: 
                   4336: #else
                   4337: 
                   4338: /* cycle-exact m68k_run () */
                   4339: 
                   4340: static void m68k_run_1_ce (void)
                   4341: {
                   4342:        struct regstruct *r = &regs;
1.1.1.7 ! root     4343:        bool first = true;
        !          4344:        bool exit = false;
        !          4345: printf ( "run_1_ce\n" );
        !          4346: 
        !          4347:        while (!exit) {
        !          4348:                TRY (prb) {
        !          4349:                        if (first) {
        !          4350:                                if (cpu_tracer < 0) {
        !          4351:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
        !          4352:                                        r->ir = cputrace.ir;
        !          4353:                                        r->irc = cputrace.irc;
        !          4354:                                        r->sr = cputrace.sr;
        !          4355:                                        r->usp = cputrace.usp;
        !          4356:                                        r->isp = cputrace.isp;
        !          4357:                                        r->intmask = cputrace.intmask;
        !          4358:                                        r->stopped = cputrace.stopped;
        !          4359:                                        m68k_setpc (cputrace.pc);
        !          4360:                                        if (!r->stopped) {
        !          4361:                                                if (cputrace.state > 1) {
        !          4362:                                                        write_log (_T("CPU TRACE: EXCEPTION %d\n"), cputrace.state);
        !          4363:                                                        Exception (cputrace.state);
        !          4364:                                                } else if (cputrace.state == 1) {
        !          4365:                                                        write_log (_T("CPU TRACE: %04X\n"), cputrace.opcode);
        !          4366:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
        !          4367:                                                }
        !          4368:                                        } else {
        !          4369:                                                write_log (_T("CPU TRACE: STOPPED\n"));
        !          4370:                                        }
        !          4371:                                        if (r->stopped)
        !          4372:                                                set_special (SPCFLAG_STOP);
        !          4373:                                        set_cpu_tracer (false);
        !          4374:                                        goto cont;
        !          4375:                                }
        !          4376:                                set_cpu_tracer (false);
        !          4377:                                first = false;
        !          4378:                        }
1.1.1.4   root     4379: 
1.1.1.7 ! root     4380:                        while (!exit) {
        !          4381:                                r->opcode = r->ir;
1.1.1.4   root     4382: 
1.1.1.7 ! root     4383: #ifdef WINUAE_FOR_HATARI
        !          4384:                                //m68k_dumpstate_file(stderr, NULL);
        !          4385:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          4386:                                {
        !          4387:                                        int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4   root     4388: 
1.1.1.7 ! root     4389:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4   root     4390: 
1.1.1.7 ! root     4391:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          4392:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          4393:                                }
        !          4394: #endif
        !          4395: 
        !          4396: #ifndef WINUAE_FOR_HATARI
        !          4397: #if DEBUG_CD32CDTVIO
        !          4398:                                out_cd32io (m68k_getpc ());
        !          4399: #endif
        !          4400: #endif
        !          4401:                                if (cpu_tracer) {
        !          4402:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
        !          4403:                                        cputrace.opcode = r->opcode;
        !          4404:                                        cputrace.ir = r->ir;
        !          4405:                                        cputrace.irc = r->irc;
        !          4406:                                        cputrace.sr = r->sr;
        !          4407:                                        cputrace.usp = r->usp;
        !          4408:                                        cputrace.isp = r->isp;
        !          4409:                                        cputrace.intmask = r->intmask;
        !          4410:                                        cputrace.stopped = r->stopped;
        !          4411:                                        cputrace.state = 1;
        !          4412:                                        cputrace.pc = m68k_getpc ();
        !          4413:                                        cputrace.startcycles = get_cycles ();
        !          4414:                                        cputrace.memoryoffset = 0;
        !          4415:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
        !          4416:                                        cputrace.readcounter = cputrace.writecounter = 0;
        !          4417:                                }
        !          4418: 
        !          4419: #ifndef WINUAE_FOR_HATARI
        !          4420:                                if (inputrecord_debug & 4) {
        !          4421:                                        if (input_record > 0)
        !          4422:                                                inprec_recorddebug_cpu (1);
        !          4423:                                        else if (input_play > 0)
        !          4424:                                                inprec_playdebug_cpu (1);
        !          4425:                                }
        !          4426: #endif
        !          4427: 
        !          4428: #ifdef WINUAE_FOR_HATARI
        !          4429:                                currcycle = 0;
        !          4430: #endif
        !          4431: 
        !          4432:                                r->instruction_pc = m68k_getpc ();
        !          4433:                                (*cpufunctbl[r->opcode])(r->opcode);
        !          4434:                                wait_memory_cycles();                   // TODO NP : ici, ou plus bas ?
        !          4435: #ifdef WINUAE_FOR_HATARI
        !          4436: //fprintf ( stderr, "cyc_1ce %d\n" , currcycle );
        !          4437:                                /* HACK for Hatari: Adding cycles should of course not be done
        !          4438:                                * here in CE mode (so this should be removed later), but until
        !          4439:                                * we're really there, this helps to get this mode running
        !          4440:                                * at least to a basic extend! */
        !          4441:                                M68000_AddCyclesWithPairing(currcycle * 2 / CYCLE_UNIT);
        !          4442: 
        !          4443:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          4444:                                        /* Add some extra cycles to simulate a wait state */
        !          4445:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          4446:                                        M68000_AddCycles(nWaitStateCycles);
        !          4447:                                        nWaitStateCycles = 0;
        !          4448:                                }
        !          4449: 
        !          4450:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          4451:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          4452:                                if ( MFP_UpdateNeeded == true )
        !          4453:                                        MFP_UpdateIRQ ( 0 );
        !          4454: #endif
        !          4455: 
        !          4456:                                if (cpu_tracer) {
        !          4457:                                        cputrace.state = 0;
        !          4458:                                }
        !          4459: cont:
        !          4460:                                if (cputrace.needendcycles) {
        !          4461:                                        cputrace.needendcycles = 0;
        !          4462:                                        write_log (_T("STARTCYCLES=%08x ENDCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
        !          4463: #ifndef WINUAE_FOR_HATARI
        !          4464:                                        log_dma_record ();
        !          4465: #endif
        !          4466:                                }
        !          4467: 
        !          4468:                                if (r->spcflags || time_for_interrupt ()) {
        !          4469:                                        if (do_specialties (0))
        !          4470:                                                exit = true;
        !          4471:                                }
        !          4472: 
        !          4473:                                if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68010)
        !          4474:                                        exit = true;
        !          4475:                        }
        !          4476:                } CATCH (prb) {
        !          4477:                        bus_error();
        !          4478:                        if (r->spcflags || time_for_interrupt()) {
        !          4479:                                if (do_specialties(0))
        !          4480:                                        exit = true;
        !          4481:                        }
        !          4482:                } ENDTRY
        !          4483:        }
        !          4484: }
        !          4485: 
        !          4486: #endif
        !          4487: 
        !          4488: #ifdef CPUEMU_20
        !          4489: // emulate simple prefetch
        !          4490: static uae_u16 get_word_020_prefetchf (uae_u32 pc)
        !          4491: {
        !          4492:        if (pc == regs.prefetch020addr) {
        !          4493:                uae_u16 v = regs.prefetch020[0];
        !          4494:                regs.prefetch020[0] = regs.prefetch020[1];
        !          4495:                regs.prefetch020[1] = regs.prefetch020[2];
        !          4496:                regs.prefetch020[2] = x_get_word (pc + 6);
        !          4497:                regs.prefetch020addr += 2;
        !          4498:                return v;
        !          4499:        } else if (pc == regs.prefetch020addr + 2) {
        !          4500:                uae_u16 v = regs.prefetch020[1];
        !          4501:                regs.prefetch020[0] = regs.prefetch020[2];
        !          4502:                regs.prefetch020[1] = x_get_word (pc + 4);
        !          4503:                regs.prefetch020[2] = x_get_word (pc + 6);
        !          4504:                regs.prefetch020addr = pc + 2;
        !          4505:                return v;
        !          4506:        } else if (pc == regs.prefetch020addr + 4) {
        !          4507:                uae_u16 v = regs.prefetch020[2];
        !          4508:                regs.prefetch020[0] = x_get_word (pc + 2);
        !          4509:                regs.prefetch020[1] = x_get_word (pc + 4);
        !          4510:                regs.prefetch020[2] = x_get_word (pc + 6);
        !          4511:                regs.prefetch020addr = pc + 2;
        !          4512:                return v;
        !          4513:        } else {
        !          4514:                regs.prefetch020addr = pc + 2;
        !          4515:                regs.prefetch020[0] = x_get_word (pc + 2);
        !          4516:                regs.prefetch020[1] = x_get_word (pc + 4);
        !          4517:                regs.prefetch020[2] = x_get_word (pc + 6);
        !          4518:                return x_get_word (pc);
1.1.1.4   root     4519:        }
                   4520: }
                   4521: #endif
                   4522: 
                   4523: #ifdef JIT  /* Completely different run_2 replacement */
                   4524: 
                   4525: void do_nothing (void)
                   4526: {
                   4527:        /* What did you expect this to do? */
                   4528:        do_cycles (0);
                   4529:        /* I bet you didn't expect *that* ;-) */
                   4530: }
                   4531: 
                   4532: void exec_nostats (void)
                   4533: {
                   4534:        struct regstruct *r = &regs;
                   4535: 
                   4536:        for (;;)
                   4537:        {
1.1.1.7 ! root     4538:                if (currprefs.cpu_compatible) {
        !          4539:                        r->opcode = get_word_020_prefetchf(m68k_getpc());
        !          4540:                } else {
        !          4541:                        r->opcode = x_get_iword(0);
        !          4542:                }
        !          4543:                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
        !          4544:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4   root     4545:                do_cycles (cpu_cycles);
                   4546: 
1.1.1.7 ! root     4547: #ifdef WITH_PPC
        !          4548:                if (ppc_state)
        !          4549:                        ppc_interrupt(intlev());
        !          4550: #endif
        !          4551: #ifdef WINUAE_FOR_HATARI
        !          4552:                if (end_block(r->opcode) || r->spcflags)
        !          4553: #else
        !          4554: 
        !          4555:                if (end_block(r->opcode) || r->spcflags || uae_int_requested || uaenet_int_requested)
        !          4556: #endif
1.1.1.4   root     4557:                        return; /* We will deal with the spcflags in the caller */
                   4558:        }
                   4559: }
                   4560: 
                   4561: void execute_normal (void)
                   4562: {
                   4563:        struct regstruct *r = &regs;
                   4564:        int blocklen;
                   4565:        cpu_history pc_hist[MAXRUN];
                   4566:        int total_cycles;
                   4567: 
                   4568:        if (check_for_cache_miss ())
                   4569:                return;
                   4570: 
                   4571:        total_cycles = 0;
                   4572:        blocklen = 0;
                   4573:        start_pc_p = r->pc_oldp;
                   4574:        start_pc = r->pc;
                   4575:        for (;;) {
                   4576:                /* Take note: This is the do-it-normal loop */
1.1.1.7 ! root     4577:                regs.instruction_pc = m68k_getpc ();
        !          4578:                if (currprefs.cpu_compatible) {
        !          4579:                        r->opcode = get_word_020_prefetchf (regs.instruction_pc);
        !          4580:                } else {
        !          4581:                        r->opcode = x_get_iword(0);
        !          4582:                }
1.1.1.4   root     4583: 
                   4584:                special_mem = DISTRUST_CONSISTENT_MEM;
                   4585:                pc_hist[blocklen].location = (uae_u16*)r->pc_p;
                   4586: 
1.1.1.7 ! root     4587:                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
        !          4588:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4   root     4589:                do_cycles (cpu_cycles);
                   4590:                total_cycles += cpu_cycles;
                   4591:                pc_hist[blocklen].specmem = special_mem;
                   4592:                blocklen++;
1.1.1.7 ! root     4593: #ifdef WINUAE_FOR_HATARI
        !          4594:                if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags) {
        !          4595: #else
        !          4596:                if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested || uaenet_int_requested) {
        !          4597: #endif
1.1.1.4   root     4598:                        compile_block (pc_hist, blocklen, total_cycles);
                   4599:                        return; /* We will deal with the spcflags in the caller */
                   4600:                }
                   4601:                /* No need to check regs.spcflags, because if they were set,
                   4602:                we'd have ended up inside that "if" */
1.1.1.7 ! root     4603: 
        !          4604: #ifdef WITH_PPC
        !          4605:                if (ppc_state)
        !          4606:                        ppc_interrupt(intlev());
        !          4607: #endif
1.1.1.4   root     4608:        }
                   4609: }
                   4610: 
                   4611: typedef void compiled_handler (void);
                   4612: 
                   4613: static void m68k_run_jit (void)
                   4614: {
1.1.1.7 ! root     4615: printf ( "run_jit\n" );
1.1.1.4   root     4616:        for (;;) {
1.1.1.7 ! root     4617: #ifdef WINUAE_FOR_HATARI
        !          4618:                //m68k_dumpstate_file(stderr, NULL);
1.1.1.4   root     4619:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   4620:                {
                   4621:                        int FrameCycles, HblCounterVideo, LineCycles;
                   4622:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   4623:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.7 ! root     4624:                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4   root     4625:                }
1.1.1.7 ! root     4626: #endif
1.1.1.4   root     4627: 
                   4628:                ((compiled_handler*)(pushall_call_handler))();
                   4629:                /* Whenever we return from that, we should check spcflags */
1.1.1.7 ! root     4630: #ifndef WINUAE_FOR_HATARI
        !          4631:                check_uae_int_request();
        !          4632: #endif
1.1.1.4   root     4633:                if (regs.spcflags) {
                   4634:                        if (do_specialties (0)) {
                   4635:                                return;
                   4636:                        }
                   4637:                }
                   4638:        }
                   4639: }
                   4640: #endif /* JIT */
                   4641: 
                   4642: #ifndef CPUEMU_0
                   4643: 
                   4644: static void m68k_run_2 (void)
                   4645: {
                   4646: }
                   4647: 
                   4648: #else
                   4649: 
1.1.1.7 ! root     4650: static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full)
1.1.1.4   root     4651: {
                   4652:        struct mnemolookup *lookup;
                   4653:        struct instr *dp;
                   4654:        uae_u32 addr;
                   4655:        int fault;
                   4656: 
                   4657:        if (cpufunctbl[opcode] == op_illg_1)
                   4658:                opcode = 0x4AFC;
                   4659:        dp = table68k + opcode;
                   4660:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   4661:                ;
                   4662:        fault = 0;
                   4663:        TRY(prb) {
                   4664:                addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0);
                   4665:        } CATCH (prb) {
                   4666:                fault = 1;
                   4667:        } ENDTRY
                   4668:        if (!fault) {
1.1.1.7 ! root     4669:                TCHAR buf[100];
        !          4670:                if (full)
        !          4671:                        write_log (_T("mmufixup=%d %04x %04x\n"), mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
        !          4672:                m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0);
        !          4673:                write_log (_T("%s\n"), buf);
        !          4674:                if (full)
        !          4675:                        m68k_dumpstate (NULL);
        !          4676:        }
        !          4677: }
        !          4678: 
        !          4679: void cpu_halt (int id)
        !          4680: {
        !          4681: #ifndef WINUAE_FOR_HATARI
        !          4682:        // id < 0: m68k halted, PPC active.
        !          4683:        // id > 0: emulation halted.
        !          4684:        if (!regs.halted) {
        !          4685:                write_log (_T("CPU halted: reason = %d PC=%08x\n"), id, M68K_GETPC);
        !          4686:                regs.halted = id;
        !          4687:                gui_data.cpu_halted = id;
        !          4688:                gui_led(LED_CPU, 0, -1);
        !          4689:                if (id >= 0) {
        !          4690:                        regs.intmask = 7;
        !          4691:                        MakeSR ();
        !          4692:                        audio_deactivate ();
        !          4693:                }
        !          4694:                set_special(SPCFLAG_CHECK);
        !          4695:        }
        !          4696: 
        !          4697: #else
        !          4698:        Dialog_HaltDlg();
        !          4699: #endif
        !          4700: }
        !          4701: 
        !          4702: #ifdef CPUEMU_33
        !          4703: /* [NP] TODO : use 68060 in Hatari ? with DSP ? */
        !          4704: /* MMU 68060  */
        !          4705: static void m68k_run_mmu060 (void)
        !          4706: {
        !          4707:        struct flag_struct f;
        !          4708:        int halt = 0;
        !          4709: printf ( "run_mmu060\n" );
        !          4710: 
        !          4711:        while (!halt) {
        !          4712:                TRY (prb) {
        !          4713:                        for (;;) {
        !          4714:                                f.cznv = regflags.cznv;
        !          4715:                                f.x = regflags.x;
        !          4716:                                regs.instruction_pc = m68k_getpc ();
        !          4717: 
        !          4718:                                do_cycles (cpu_cycles);
        !          4719: 
        !          4720:                                mmu_opcode = -1;
        !          4721:                                mmu060_state = 0;
        !          4722:                                mmu_opcode = regs.opcode = x_prefetch (0);
        !          4723:                                mmu060_state = 1;
        !          4724: 
        !          4725:                                count_instr (regs.opcode);
        !          4726:                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
        !          4727: 
        !          4728:                                cpu_cycles = adjust_cycles (cpu_cycles);
        !          4729: 
        !          4730:                                if (regs.spcflags) {
        !          4731:                                        if (do_specialties (cpu_cycles))
        !          4732:                                                return;
        !          4733:                                }
        !          4734:                        }
        !          4735:                } CATCH (prb) {
        !          4736: 
        !          4737:                        m68k_setpci (regs.instruction_pc);
        !          4738:                        regflags.cznv = f.cznv;
        !          4739:                        regflags.x = f.x;
        !          4740: 
        !          4741:                        if (mmufixup[0].reg >= 0) {
        !          4742:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
        !          4743:                                mmufixup[0].reg = -1;
        !          4744:                        }
        !          4745:                        if (mmufixup[1].reg >= 0) {
        !          4746:                                m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
        !          4747:                                mmufixup[1].reg = -1;
        !          4748:                        }
        !          4749: 
        !          4750:                        TRY (prb2) {
        !          4751:                                Exception (prb);
        !          4752:                        } CATCH (prb2) {
        !          4753:                                halt = 1;
        !          4754:                        } ENDTRY
        !          4755:                } ENDTRY
1.1.1.4   root     4756:        }
1.1.1.7 ! root     4757:        cpu_halt(halt);
1.1.1.4   root     4758: }
1.1.1.7 ! root     4759: 
1.1.1.4   root     4760: #endif
                   4761: 
1.1.1.7 ! root     4762: #ifdef CPUEMU_31
1.1.1.4   root     4763: 
                   4764: /* Aranym MMU 68040  */
                   4765: static void m68k_run_mmu040 (void)
                   4766: {
1.1.1.7 ! root     4767:        struct flag_struct f;
        !          4768:        int halt = 0;
        !          4769: printf ( "run_mmu040\n" );
        !          4770: 
        !          4771:        while (!halt) {
        !          4772:                TRY (prb) {
        !          4773:                        for (;;) {
        !          4774: #ifdef WINUAE_FOR_HATARI
        !          4775:                                //m68k_dumpstate_file(stderr, NULL);
        !          4776:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          4777:                                {
        !          4778:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          4779:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          4780:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          4781:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          4782:                                }
        !          4783: #endif
        !          4784:                                f.cznv = regflags.cznv;
        !          4785:                                f.x = regflags.x;
        !          4786:                                mmu_restart = true;
        !          4787:                                regs.instruction_pc = m68k_getpc ();
        !          4788: 
        !          4789:                                do_cycles (cpu_cycles);
        !          4790: 
        !          4791:                                mmu_opcode = -1;
        !          4792:                                mmu_opcode = regs.opcode = x_prefetch (0);
        !          4793:                                count_instr (regs.opcode);
        !          4794:                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
        !          4795:                                cpu_cycles = adjust_cycles (cpu_cycles);
        !          4796: 
        !          4797: #ifdef WINUAE_FOR_HATARI
        !          4798:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
        !          4799: 
        !          4800:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          4801:                                        /* Add some extra cycles to simulate a wait state */
        !          4802:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          4803:                                        M68000_AddCycles(nWaitStateCycles);
        !          4804:                                        nWaitStateCycles = 0;
        !          4805:                                }
1.1.1.4   root     4806: 
1.1.1.7 ! root     4807:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          4808:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          4809:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          4810:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          4811:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          4812:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          4813:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          4814:                                if ( MFP_UpdateNeeded == true )
        !          4815:                                        MFP_UpdateIRQ ( 0 );
        !          4816: #endif
1.1.1.4   root     4817: 
1.1.1.7 ! root     4818:                                if (regs.spcflags) {
        !          4819:                                        if (do_specialties (cpu_cycles))
        !          4820:                                                return;
1.1.1.4   root     4821:                                }
1.1.1.7 ! root     4822: 
        !          4823: #ifdef WINUAE_FOR_HATARI
        !          4824:                                /* Run DSP 56k code if necessary */
        !          4825:                                if (bDspEnabled) {
        !          4826:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
        !          4827:                                }
        !          4828: #endif
1.1.1.4   root     4829:                        }
1.1.1.7 ! root     4830:                } CATCH (prb) {
        !          4831: 
        !          4832:                        if (mmu_restart) {
        !          4833:                                /* restore state if instruction restart */
        !          4834:                                regflags.cznv = f.cznv;
        !          4835:                                regflags.x = f.x;
        !          4836:                                m68k_setpci (regs.instruction_pc);
1.1.1.4   root     4837:                        }
1.1.1.7 ! root     4838: 
        !          4839:                        if (mmufixup[0].reg >= 0) {
        !          4840:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
        !          4841:                                mmufixup[0].reg = -1;
1.1.1.4   root     4842:                        }
1.1.1.7 ! root     4843: 
        !          4844:                        TRY (prb2) {
        !          4845:                                Exception (prb);
        !          4846:                        } CATCH (prb2) {
        !          4847:                                halt = 1;
        !          4848:                        } ENDTRY
        !          4849:                } ENDTRY
        !          4850:        }
        !          4851:        cpu_halt(halt);
        !          4852: }
        !          4853: 
        !          4854: #endif
        !          4855: 
        !          4856: #ifdef CPUEMU_32
        !          4857: 
        !          4858: // Previous MMU 68030
        !          4859: static void m68k_run_mmu030 (void)
        !          4860: {
        !          4861:        struct flag_struct f;
        !          4862:        int halt = 0;
        !          4863: printf ( "run_mmu030\n" );
        !          4864: 
        !          4865:        mmu030_opcode_stageb = -1;
        !          4866:        mmu030_fake_prefetch = -1;
        !          4867:        while(!halt) {
        !          4868:                TRY (prb) {
        !          4869:                        for (;;) {
        !          4870:                                int cnt;
        !          4871: insretry:
        !          4872: #ifdef WINUAE_FOR_HATARI
        !          4873:                                //m68k_dumpstate_file(stderr, NULL);
        !          4874:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          4875:                                {
        !          4876:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          4877:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          4878:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          4879:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4   root     4880:                                }
                   4881: #endif
1.1.1.7 ! root     4882:                                regs.instruction_pc = m68k_getpc ();
        !          4883:                                f.cznv = regflags.cznv;
        !          4884:                                f.x = regflags.x;
        !          4885: 
        !          4886:                                mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
        !          4887:                                mmu030_opcode = -1;
        !          4888:                                if (mmu030_fake_prefetch >= 0) {
        !          4889:                                        regs.opcode = mmu030_fake_prefetch;
        !          4890:                                        // use fake prefetch opcode only if mapping changed
        !          4891:                                        uaecptr new_addr = mmu030_translate(regs.instruction_pc, regs.s != 0, false, false);
        !          4892:                                        if (mmu030_fake_prefetch_addr != new_addr) {
        !          4893:                                                regs.opcode = mmu030_fake_prefetch;
        !          4894:                                                write_log(_T("MMU030 fake prefetch remap: %04x, %08x -> %08x\n"), mmu030_fake_prefetch, mmu030_fake_prefetch_addr, new_addr);
        !          4895:                                        } else {
        !          4896:                                                if (mmu030_opcode_stageb < 0) {
        !          4897:                                                        regs.opcode = x_prefetch (0);
        !          4898:                                                } else {
        !          4899:                                                        regs.opcode = mmu030_opcode_stageb;
        !          4900:                                                        mmu030_opcode_stageb = -1;
        !          4901:                                                }
        !          4902:                                        }
        !          4903:                                        mmu030_fake_prefetch = -1;
        !          4904:                                } else if (mmu030_opcode_stageb < 0) {
        !          4905:                                        regs.opcode = x_prefetch (0);
        !          4906:                                } else {
        !          4907:                                        regs.opcode = mmu030_opcode_stageb;
        !          4908:                                        mmu030_opcode_stageb = -1;
        !          4909:                                }
        !          4910: 
        !          4911:                                mmu030_opcode = regs.opcode;
        !          4912:                                mmu030_ad[0].done = false;
        !          4913: 
        !          4914:                                cnt = 50;
        !          4915:                                for (;;) {
        !          4916:                                        regs.opcode = mmu030_opcode;
        !          4917:                                        mmu030_idx = 0;
        !          4918:                                        count_instr (regs.opcode);
        !          4919:                                        do_cycles (cpu_cycles);
        !          4920:                                        mmu030_retry = false;
        !          4921: 
        !          4922:                                        cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
        !          4923:                                        cnt--; // so that we don't get in infinite loop if things go horribly wrong
        !          4924:                                        if (!mmu030_retry)
        !          4925:                                                break;
        !          4926:                                        if (cnt < 0) {
        !          4927:                                                cpu_halt (9);
        !          4928:                                                break;
        !          4929:                                        }
        !          4930:                                        if (mmu030_retry && mmu030_opcode == -1)
        !          4931:                                                goto insretry; // urgh
        !          4932:                                }
1.1.1.4   root     4933: 
1.1.1.7 ! root     4934:                                mmu030_opcode = -1;
1.1.1.4   root     4935: 
1.1.1.7 ! root     4936:                                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4   root     4937: 
1.1.1.7 ! root     4938: #ifdef WINUAE_FOR_HATARI
        !          4939:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4   root     4940: 
1.1.1.7 ! root     4941:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          4942:                                        /* Add some extra cycles to simulate a wait state */
        !          4943:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          4944:                                        M68000_AddCycles(nWaitStateCycles);
        !          4945:                                        nWaitStateCycles = 0;
        !          4946:                                }
        !          4947: 
        !          4948:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          4949:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          4950:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          4951:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          4952:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
1.1.1.5   root     4953:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   4954:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   4955:                                if ( MFP_UpdateNeeded == true )
                   4956:                                        MFP_UpdateIRQ ( 0 );
1.1.1.7 ! root     4957: #endif
        !          4958:                                if (regs.spcflags) {
        !          4959:                                        if (do_specialties (cpu_cycles))
        !          4960:                                                return;
        !          4961:                                }
1.1.1.4   root     4962: 
1.1.1.7 ! root     4963: #ifdef WINUAE_FOR_HATARI
        !          4964:                                /* Run DSP 56k code if necessary */
        !          4965:                                if (bDspEnabled) {
        !          4966:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
        !          4967:                                }
        !          4968: #endif
1.1.1.4   root     4969:                        }
1.1.1.7 ! root     4970:                } CATCH (prb) {
        !          4971: 
        !          4972:                        regflags.cznv = f.cznv;
        !          4973:                        regflags.x = f.x;
1.1.1.4   root     4974: 
1.1.1.7 ! root     4975:                        m68k_setpci (regs.instruction_pc);
        !          4976: 
        !          4977:                        if (mmufixup[0].reg >= 0) {
        !          4978:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
        !          4979:                                mmufixup[0].reg = -1;
1.1.1.4   root     4980:                        }
                   4981:                        if (mmufixup[1].reg >= 0) {
                   4982:                                m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
                   4983:                                mmufixup[1].reg = -1;
                   4984:                        }
1.1.1.7 ! root     4985: 
        !          4986:                        TRY (prb2) {
        !          4987:                                Exception (prb);
        !          4988:                        } CATCH (prb2) {
        !          4989:                                halt = 1;
        !          4990:                        } ENDTRY
        !          4991:                } ENDTRY
        !          4992:        }
        !          4993:        cpu_halt (halt);
        !          4994: }
        !          4995: 
        !          4996: #endif
        !          4997: 
        !          4998: 
        !          4999: /* "cycle exact" 68040/060 */
        !          5000: 
        !          5001: static void m68k_run_3ce (void)
        !          5002: {
        !          5003:        struct regstruct *r = &regs;
        !          5004:        bool exit = false;
        !          5005: printf ( "run_3ce\n" );
        !          5006: 
        !          5007:        while (!exit) {
        !          5008:                TRY(prb) {
        !          5009:                        while (!exit) {
        !          5010: #ifdef WINUAE_FOR_HATARI
        !          5011:                                //m68k_dumpstate_file(stderr, NULL);
        !          5012:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          5013:                                {
        !          5014:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          5015:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          5016:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          5017:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          5018:                                }
        !          5019: #endif
        !          5020:                                r->instruction_pc = m68k_getpc();
        !          5021:                                r->opcode = get_iword_cache_040(0);
        !          5022:                                // "prefetch"
        !          5023:                                if (regs.cacr & 0x8000)
        !          5024:                                        fill_icache040(r->instruction_pc + 16);
        !          5025: 
        !          5026:                                (*cpufunctbl[r->opcode])(r->opcode);
        !          5027: 
        !          5028: #ifdef WINUAE_FOR_HATARI
        !          5029: //fprintf ( stderr, "cyc_3ce %d\n" , currcycle );
        !          5030:                                M68000_AddCycles(currcycle * 2 / CYCLE_UNIT);
        !          5031: 
        !          5032:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          5033:                                        /* Add some extra cycles to simulate a wait state */
        !          5034:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          5035:                                        M68000_AddCycles(nWaitStateCycles);
        !          5036:                                        nWaitStateCycles = 0;
        !          5037:                                }
        !          5038: 
        !          5039:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          5040:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          5041:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          5042:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          5043:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          5044:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          5045:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          5046:                                if ( MFP_UpdateNeeded == true )
        !          5047:                                        MFP_UpdateIRQ ( 0 );
        !          5048: #endif
        !          5049:                                if (r->spcflags) {
        !          5050:                                        if (do_specialties (0))
        !          5051:                                                exit = true;
        !          5052:                                }
        !          5053: 
        !          5054: #ifdef WINUAE_FOR_HATARI
        !          5055:                                /* Run DSP 56k code if necessary */
        !          5056:                                if (bDspEnabled) {
        !          5057:                                        DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
1.1.1.4   root     5058:                                }
1.1.1.7 ! root     5059: #endif
1.1.1.4   root     5060:                        }
1.1.1.7 ! root     5061:                } CATCH(prb) {
        !          5062:                        bus_error();
        !          5063:                        if (r->spcflags) {
        !          5064:                                if (do_specialties(0))
        !          5065:                                        exit = true;
        !          5066:                        }
        !          5067:                } ENDTRY
        !          5068:        }
        !          5069: }
1.1.1.4   root     5070: 
1.1.1.7 ! root     5071: /* "prefetch" 68040/060 */
1.1.1.4   root     5072: 
1.1.1.7 ! root     5073: static void m68k_run_3p(void)
        !          5074: {
        !          5075:        struct regstruct *r = &regs;
        !          5076:        bool exit = false;
        !          5077:        int cycles;
        !          5078: printf ( "run_3p\n" );
        !          5079: 
        !          5080:        while (!exit)  {
        !          5081:                TRY(prb) {
        !          5082:                        while (!exit) {
        !          5083: #ifdef WINUAE_FOR_HATARI
        !          5084:                                //m68k_dumpstate_file(stderr, NULL);
        !          5085:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          5086:                                {
        !          5087:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          5088:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          5089:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          5090:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          5091:                                }
        !          5092: #endif
        !          5093:                                r->instruction_pc = m68k_getpc();
        !          5094:                                r->opcode = get_iword_cache_040(0);
        !          5095:                                // "prefetch"
        !          5096:                                if (regs.cacr & 0x8000)
        !          5097:                                        fill_icache040(r->instruction_pc + 16);
        !          5098: 
        !          5099:                                (*cpufunctbl[r->opcode])(r->opcode);
        !          5100: 
        !          5101:                                cpu_cycles = 1 * CYCLE_UNIT;
        !          5102:                                cycles = adjust_cycles(cpu_cycles);
        !          5103:                                do_cycles(cycles);
        !          5104: #ifdef WINUAE_FOR_HATARI
        !          5105:                                M68000_AddCycles(cycles * 2 / CYCLE_UNIT);
        !          5106: 
        !          5107:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          5108:                                        /* Add some extra cycles to simulate a wait state */
        !          5109:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          5110:                                        M68000_AddCycles(nWaitStateCycles);
        !          5111:                                        nWaitStateCycles = 0;
        !          5112:                                }
1.1.1.4   root     5113: 
1.1.1.7 ! root     5114:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          5115:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          5116:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          5117:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          5118:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          5119:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          5120:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          5121:                                if ( MFP_UpdateNeeded == true )
        !          5122:                                        MFP_UpdateIRQ ( 0 );
        !          5123: #endif
        !          5124: 
        !          5125:                                if (r->spcflags) {
        !          5126:                                        if (do_specialties(0))
        !          5127:                                                exit = true;
        !          5128:                                }
        !          5129: 
        !          5130: #ifdef WINUAE_FOR_HATARI
        !          5131:                                /* Run DSP 56k code if necessary */
        !          5132:                                if (bDspEnabled) {
        !          5133:                                        DSP_Run(2 * cycles * 2 / CYCLE_UNIT);
        !          5134:                                }
        !          5135: #endif
        !          5136:                        }
        !          5137:                } CATCH(prb) {
        !          5138:                        bus_error();
        !          5139:                        if (r->spcflags) {
        !          5140:                                if (do_specialties(0))
        !          5141:                                        exit = true;
        !          5142:                        }
        !          5143:                } ENDTRY
        !          5144:        }
1.1.1.4   root     5145: }
                   5146: 
                   5147: /* "cycle exact" 68020/030  */
1.1.1.7 ! root     5148: 
        !          5149: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp);
1.1.1.4   root     5150: static void m68k_run_2ce (void)
                   5151: {
                   5152:        struct regstruct *r = &regs;
1.1.1.7 ! root     5153:        bool exit = false;
        !          5154:        bool first = true;
        !          5155: printf ( "run_2ce\n" );
        !          5156: 
        !          5157:        while (!exit) {
        !          5158:                TRY(prb) {
        !          5159:                        if (first) {
        !          5160:                                if (cpu_tracer < 0) {
        !          5161:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
        !          5162:                                        r->ir = cputrace.ir;
        !          5163:                                        r->irc = cputrace.irc;
        !          5164:                                        r->sr = cputrace.sr;
        !          5165:                                        r->usp = cputrace.usp;
        !          5166:                                        r->isp = cputrace.isp;
        !          5167:                                        r->intmask = cputrace.intmask;
        !          5168:                                        r->stopped = cputrace.stopped;
        !          5169: 
        !          5170:                                        r->msp = cputrace.msp;
        !          5171:                                        r->vbr = cputrace.vbr;
        !          5172:                                        r->caar = cputrace.caar;
        !          5173:                                        r->cacr = cputrace.cacr;
        !          5174:                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
        !          5175:                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
        !          5176:                                        r->prefetch020addr = cputrace.prefetch020addr;
        !          5177:                                        memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
        !          5178:                                        memcpy (&caches020, &cputrace.caches020, sizeof caches020);
        !          5179: 
        !          5180:                                        m68k_setpc (cputrace.pc);
        !          5181:                                        if (!r->stopped) {
        !          5182:                                                if (cputrace.state > 1)
        !          5183:                                                        Exception (cputrace.state);
        !          5184:                                                else if (cputrace.state == 1)
        !          5185:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
        !          5186:                                        }
        !          5187:                                        if (regs.stopped)
        !          5188:                                                set_special (SPCFLAG_STOP);
        !          5189:                                        set_cpu_tracer (false);
        !          5190:                                        goto cont;
        !          5191:                                }
        !          5192:                                set_cpu_tracer (false);
        !          5193:                                first = false;
        !          5194:                        }
1.1.1.4   root     5195: 
1.1.1.7 ! root     5196:                        while (!exit) {
        !          5197:                                static int prevopcode;
        !          5198: #ifdef WINUAE_FOR_HATARI
        !          5199:                                //m68k_dumpstate_file(stderr, NULL);
        !          5200:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          5201:                                {
        !          5202:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          5203:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          5204:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          5205:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          5206: #if 0
        !          5207: // logs to debug data cache issues
        !          5208: struct cache030 *c1 ,*c2;
        !          5209:         int lws1, lws2;
        !          5210:         uae_u32 tag1, tag2;
        !          5211: c1 = getcache030 (dcaches030, (uaecptr)0x27ece, &tag1, &lws1);
        !          5212: c2 = getcache030 (dcaches030, (uaecptr)0x7f8192+4, &tag2, &lws2);
        !          5213: fprintf ( stderr , "cache valid %d tag1 %x lws1 %x ctag %x data %x mem=%x\n" , c1->valid[lws1] , tag1 , lws1 , c1->tag , c1->data[lws1] , get_long(0x27ece) );
        !          5214: //fprintf ( stderr , "cache valid %d tag2 %x lws2 %x ctag %x data %x mem=%x\n" , c2->valid[lws2] , tag2 , lws2 , c2->tag , c2->data[lws2] , get_long(0x7f8192+4) );
        !          5215: #endif
        !          5216:                                }
1.1.1.4   root     5217: 
1.1.1.7 ! root     5218:                                currcycle = 0;
        !          5219: #endif
        !          5220:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     5221: 
1.1.1.7 ! root     5222:                                if (regs.irc == 0xfffb) {
        !          5223:                                        gui_message (_T("OPCODE %04X HAS FAULTY PREFETCH! PC=%08X"), prevopcode, r->instruction_pc);
        !          5224:                                }
1.1.1.4   root     5225: 
1.1.1.7 ! root     5226:                                //write_log (_T("%x %04x\n"), r->instruction_pc, regs.irc);
1.1.1.4   root     5227: 
1.1.1.7 ! root     5228:                                r->opcode = regs.irc;
        !          5229:                                prevopcode = r->opcode;
        !          5230:                                regs.irc = 0xfffb;
1.1.1.4   root     5231: 
1.1.1.7 ! root     5232:                                //write_log (_T("%08x %04x\n"), r->instruction_pc, opcode);
1.1.1.5   root     5233: 
1.1.1.7 ! root     5234: #ifndef WINUAE_FOR_HATARI
        !          5235: #if DEBUG_CD32CDTVIO
        !          5236:                                out_cd32io (r->instruction_pc);
        !          5237: #endif
        !          5238: #endif
1.1.1.4   root     5239: 
1.1.1.7 ! root     5240:                                if (cpu_tracer) {
1.1.1.4   root     5241: 
1.1.1.7 ! root     5242: #if CPUTRACE_DEBUG
        !          5243:                                        validate_trace ();
        !          5244: #endif
        !          5245:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
        !          5246:                                        cputrace.opcode = r->opcode;
        !          5247:                                        cputrace.ir = r->ir;
        !          5248:                                        cputrace.irc = r->irc;
        !          5249:                                        cputrace.sr = r->sr;
        !          5250:                                        cputrace.usp = r->usp;
        !          5251:                                        cputrace.isp = r->isp;
        !          5252:                                        cputrace.intmask = r->intmask;
        !          5253:                                        cputrace.stopped = r->stopped;
        !          5254:                                        cputrace.state = 1;
        !          5255:                                        cputrace.pc = m68k_getpc ();
        !          5256: 
        !          5257:                                        cputrace.msp = r->msp;
        !          5258:                                        cputrace.vbr = r->vbr;
        !          5259:                                        cputrace.caar = r->caar;
        !          5260:                                        cputrace.cacr = r->cacr;
        !          5261:                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
        !          5262:                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
        !          5263:                                        cputrace.prefetch020addr = r->prefetch020addr;
        !          5264:                                        memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
        !          5265:                                        memcpy (&cputrace.caches020, &caches020, sizeof caches020);
        !          5266: 
        !          5267:                                        cputrace.memoryoffset = 0;
        !          5268:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
        !          5269:                                        cputrace.readcounter = cputrace.writecounter = 0;
        !          5270:                                }
1.1.1.4   root     5271: 
1.1.1.7 ! root     5272: #ifndef WINUAE_FOR_HATARI
        !          5273:                                if (inputrecord_debug & 4) {
        !          5274:                                        if (input_record > 0)
        !          5275:                                                inprec_recorddebug_cpu (1);
        !          5276:                                        else if (input_play > 0)
        !          5277:                                                inprec_playdebug_cpu (1);
        !          5278:                                }
        !          5279: #endif
1.1.1.4   root     5280: 
1.1.1.7 ! root     5281:                                (*cpufunctbl[r->opcode])(r->opcode);
        !          5282:                
        !          5283:                                wait_memory_cycles();
        !          5284: 
        !          5285: #ifdef WINUAE_FOR_HATARI
        !          5286: //fprintf ( stderr, "cyc_2ce %d\n" , currcycle );
        !          5287:                                M68000_AddCycles(currcycle * 2 / CYCLE_UNIT);
        !          5288: 
        !          5289:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          5290:                                        /* Add some extra cycles to simulate a wait state */
        !          5291:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          5292:                                        M68000_AddCycles(nWaitStateCycles);
        !          5293:                                        nWaitStateCycles = 0;
        !          5294:                                }
1.1.1.4   root     5295: 
1.1.1.7 ! root     5296:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          5297:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          5298:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          5299:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          5300:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          5301:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          5302:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          5303:                                if ( MFP_UpdateNeeded == true )
        !          5304:                                        MFP_UpdateIRQ ( 0 );
        !          5305: #endif
1.1.1.4   root     5306: 
1.1.1.7 ! root     5307: cont:
        !          5308:                                if (r->spcflags || time_for_interrupt ()) {
        !          5309:                                        if (do_specialties (0))
        !          5310:                                                exit = true;
        !          5311:                                }
1.1.1.4   root     5312: 
1.1.1.7 ! root     5313: #ifdef WINUAE_FOR_HATARI
        !          5314:                                /* Run DSP 56k code if necessary */
        !          5315:                                if (bDspEnabled) {
        !          5316: //fprintf ( stderr, "dsp cyc_2ce %d\n" , currcycle );
        !          5317:                                        DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
        !          5318:                                }
        !          5319: #endif
1.1.1.4   root     5320: 
1.1.1.7 ! root     5321:                                regs.ipl = regs.ipl_pin;
1.1.1.4   root     5322: 
1.1.1.7 ! root     5323:                        }
        !          5324:                } CATCH(prb) {
        !          5325:                        bus_error();
        !          5326:                        if (r->spcflags || time_for_interrupt()) {
        !          5327:                                if (do_specialties(0)) {
        !          5328:                                        exit = true;
        !          5329:                                        regs.ipl = regs.ipl_pin;
        !          5330:                                }
        !          5331:                        }
        !          5332:                } ENDTRY
1.1.1.4   root     5333:        }
                   5334: }
                   5335: 
1.1.1.7 ! root     5336: #ifdef CPUEMU_20
        !          5337: 
        !          5338: // full prefetch 020 (more compatible)
1.1.1.4   root     5339: static void m68k_run_2p (void)
                   5340: {
                   5341:        struct regstruct *r = &regs;
1.1.1.7 ! root     5342:        bool exit = false;
        !          5343: printf ( "run_2p\n" );
1.1.1.4   root     5344: 
1.1.1.7 ! root     5345:        while (!exit) {
        !          5346:                TRY(prb) {
        !          5347:                        while (!exit) {
        !          5348: #ifdef WINUAE_FOR_HATARI
        !          5349:                                //m68k_dumpstate_file(stderr, NULL);
        !          5350:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          5351:                                {
        !          5352:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          5353:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          5354:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          5355:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          5356:                                }
        !          5357: #endif
        !          5358:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     5359: 
1.1.1.7 ! root     5360: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5361: #if DEBUG_CD32CDTVIO
1.1.1.7 ! root     5362:                                out_cd32io (m68k_getpc ());
        !          5363: #endif
1.1.1.4   root     5364: #endif
                   5365: 
1.1.1.7 ! root     5366:                                x_do_cycles (cpu_cycles);
1.1.1.4   root     5367: 
1.1.1.7 ! root     5368:                                r->opcode = regs.irc;
        !          5369:                                count_instr (r->opcode);
1.1.1.4   root     5370: 
1.1.1.7 ! root     5371:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
        !          5372:                                cpu_cycles = adjust_cycles (cpu_cycles);
        !          5373: #ifdef WINUAE_FOR_HATARI
        !          5374:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4   root     5375: 
1.1.1.7 ! root     5376:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          5377:                                        /* Add some extra cycles to simulate a wait state */
        !          5378:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          5379:                                        M68000_AddCycles(nWaitStateCycles);
        !          5380:                                        nWaitStateCycles = 0;
        !          5381:                                }
1.1.1.4   root     5382: 
1.1.1.7 ! root     5383:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          5384:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          5385:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          5386:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          5387:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          5388:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          5389:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          5390:                                if ( MFP_UpdateNeeded == true )
        !          5391:                                        MFP_UpdateIRQ ( 0 );
        !          5392: #endif
1.1.1.4   root     5393: 
1.1.1.7 ! root     5394:                                if (r->spcflags) {
        !          5395:                                        if (do_specialties (cpu_cycles))
        !          5396:                                                exit = true;
        !          5397:                                }
        !          5398: 
        !          5399: #ifdef WINUAE_FOR_HATARI
        !          5400:                                /* Run DSP 56k code if necessary */
        !          5401:                                if (bDspEnabled) {
        !          5402:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
        !          5403:                                }
        !          5404: #endif
        !          5405: 
        !          5406:                                ipl_fetch ();
        !          5407:                        }
        !          5408:                } CATCH(prb) {
        !          5409:                        bus_error();
        !          5410:                        if (r->spcflags) {
        !          5411:                                if (do_specialties(cpu_cycles))
        !          5412:                                        exit = true;;
        !          5413:                        }
        !          5414:                        ipl_fetch();
        !          5415:                } ENDTRY
1.1.1.4   root     5416:        }
                   5417: }
                   5418: 
1.1.1.7 ! root     5419: #endif
1.1.1.4   root     5420: 
                   5421: //static int used[65536];
                   5422: 
                   5423: /* Same thing, but don't use prefetch to get opcode.  */
                   5424: static void m68k_run_2 (void)
                   5425: {
1.1.1.7 ! root     5426: //     static int done;
1.1.1.4   root     5427:        struct regstruct *r = &regs;
1.1.1.7 ! root     5428:        bool exit = false;
        !          5429: printf ( "run_2\n" );
1.1.1.4   root     5430: 
1.1.1.7 ! root     5431:        while (!exit) {
        !          5432:                TRY(prb) {
        !          5433:                        while (!exit) {
        !          5434: #ifdef WINUAE_FOR_HATARI
        !          5435:                                //m68k_dumpstate_file(stderr, NULL);
        !          5436:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          5437:                                {
        !          5438:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          5439:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          5440:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          5441:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
        !          5442:                                }
        !          5443: #endif
        !          5444:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     5445: 
1.1.1.7 ! root     5446:                                r->opcode = x_get_iword(0);
        !          5447:                                count_instr (r->opcode);
1.1.1.4   root     5448: 
1.1.1.7 ! root     5449:                                do_cycles (cpu_cycles);
1.1.1.5   root     5450: 
1.1.1.7 ! root     5451:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
        !          5452:                                cpu_cycles = adjust_cycles (cpu_cycles);
        !          5453: #ifdef WINUAE_FOR_HATARI
        !          5454: //fprintf ( stderr , "cyc_2 %d\n" , cpu_cycles );
        !          5455:                                M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT);
        !          5456: 
        !          5457:                                if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !          5458:                                        /* Add some extra cycles to simulate a wait state */
        !          5459:                                        unset_special(SPCFLAG_EXTRA_CYCLES);
        !          5460:                                        M68000_AddCycles(nWaitStateCycles);
        !          5461:                                        nWaitStateCycles = 0;
        !          5462:                                }
1.1.1.4   root     5463: 
1.1.1.7 ! root     5464:                                /* We can have several interrupts at the same time before the next CPU instruction */
        !          5465:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          5466:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          5467:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          5468:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          5469:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          5470:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          5471:                                if ( MFP_UpdateNeeded == true )
        !          5472:                                        MFP_UpdateIRQ ( 0 );
        !          5473: #endif
1.1.1.4   root     5474: 
1.1.1.7 ! root     5475:                                if (r->spcflags) {
        !          5476:                                        if (do_specialties (cpu_cycles))
        !          5477:                                                exit = true;
        !          5478:                                }
        !          5479: 
        !          5480: #ifdef WINUAE_FOR_HATARI
        !          5481:                                /* Run DSP 56k code if necessary */
        !          5482:                                if (bDspEnabled) {
        !          5483:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
        !          5484:                                }
        !          5485: #endif
        !          5486:                        }
        !          5487:                } CATCH(prb) {
        !          5488:                        bus_error();
        !          5489:                        if (r->spcflags) {
        !          5490:                                if (do_specialties(cpu_cycles))
        !          5491:                                        exit = true;
        !          5492:                        }
        !          5493:                } ENDTRY
1.1.1.4   root     5494:        }
                   5495: }
                   5496: 
                   5497: /* fake MMU 68k  */
                   5498: static void m68k_run_mmu (void)
                   5499: {
1.1.1.7 ! root     5500: printf ( "run_mmu\n" );
1.1.1.4   root     5501:        for (;;) {
1.1.1.7 ! root     5502: #ifdef WINUAE_FOR_HATARI
        !          5503:                //m68k_dumpstate_file(stderr, NULL);
1.1.1.4   root     5504:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   5505:                {
                   5506:                        int FrameCycles, HblCounterVideo, LineCycles;
                   5507:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   5508:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.7 ! root     5509:                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4   root     5510:                }
1.1.1.7 ! root     5511: #endif
        !          5512:                regs.opcode = get_iiword (0);
1.1.1.4   root     5513:                do_cycles (cpu_cycles);
                   5514:                mmu_backup_regs = regs;
1.1.1.7 ! root     5515:                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
        !          5516:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4   root     5517:                if (mmu_triggered)
                   5518:                        mmu_do_hit ();
                   5519:                if (regs.spcflags) {
                   5520:                        if (do_specialties (cpu_cycles))
                   5521:                                return;
                   5522:                }
                   5523:        }
                   5524: }
                   5525: 
                   5526: #endif /* CPUEMU_0 */
                   5527: 
                   5528: int in_m68k_go = 0;
                   5529: 
                   5530: static void exception2_handle (uaecptr addr, uaecptr fault)
                   5531: {
                   5532:        last_addr_for_exception_3 = addr;
                   5533:        last_fault_for_exception_3 = fault;
                   5534:        last_writeaccess_for_exception_3 = 0;
                   5535:        last_instructionaccess_for_exception_3 = 0;
1.1.1.7 ! root     5536:        Exception (2);
        !          5537: }
        !          5538: 
        !          5539: static bool cpu_hardreset, cpu_keyboardreset;
        !          5540: 
        !          5541: bool is_hardreset(void)
        !          5542: {
        !          5543:        return cpu_hardreset;
        !          5544: }
        !          5545: bool is_keyboardreset(void)
        !          5546: {
        !          5547:        return  cpu_keyboardreset;
1.1.1.4   root     5548: }
                   5549: 
                   5550: void m68k_go (int may_quit)
                   5551: {
1.1.1.7 ! root     5552: #ifndef WINUAE_FOR_HATARI
        !          5553:        int hardboot = 1;
        !          5554:        int startup = 1;
        !          5555: #endif
        !          5556: 
1.1.1.4   root     5557:        if (in_m68k_go || !may_quit) {
1.1.1.7 ! root     5558:                write_log (_T("Bug! m68k_go is not reentrant.\n"));
1.1.1.4   root     5559:                abort ();
                   5560:        }
                   5561: 
                   5562:        reset_frame_rate_hack ();
                   5563:        update_68k_cycles ();
1.1.1.7 ! root     5564: #ifndef WINUAE_FOR_HATARI
        !          5565:        start_cycles = 0;
        !          5566: #endif
        !          5567: 
        !          5568:        set_cpu_tracer (false);
1.1.1.4   root     5569: 
1.1.1.7 ! root     5570:        cpu_prefs_changed_flag = 0;
1.1.1.4   root     5571:        in_m68k_go++;
                   5572:        for (;;) {
                   5573:                void (*run_func)(void);
                   5574: 
1.1.1.7 ! root     5575: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     5576:                /* Exit hatari ? */
                   5577:                if (bQuitProgram == true)
                   5578:                        break;
1.1.1.7 ! root     5579: #endif
        !          5580: 
        !          5581:                cputrace.state = -1;
        !          5582: 
        !          5583: #ifndef WINUAE_FOR_HATARI
        !          5584:                if (currprefs.inprecfile[0] && input_play) {
        !          5585:                        inprec_open (currprefs.inprecfile, NULL);
        !          5586:                        changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0;
        !          5587:                        quit_program = UAE_RESET;
        !          5588:                }
        !          5589:                if (input_play || input_record)
        !          5590:                        inprec_startup ();
        !          5591: 
        !          5592:                if (quit_program > 0) {
        !          5593:                        int restored = 0;
        !          5594:                        cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD;
        !          5595:                        cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0;
        !          5596: 
        !          5597:                        if (quit_program == UAE_QUIT)
        !          5598:                                break;
        !          5599: 
        !          5600:                        hsync_counter = 0;
        !          5601:                        vsync_counter = 0;
        !          5602:                        quit_program = 0;
        !          5603:                        hardboot = 0;
        !          5604: 
        !          5605: #ifdef SAVESTATE
        !          5606:                        if (savestate_state == STATE_DORESTORE)
        !          5607:                                savestate_state = STATE_RESTORE;
        !          5608:                        if (savestate_state == STATE_RESTORE)
        !          5609:                                restore_state (savestate_fname);
        !          5610:                        else if (savestate_state == STATE_REWIND)
        !          5611:                                savestate_rewind ();
        !          5612: #endif
        !          5613: #ifndef WINUAE_FOR_HATARI
        !          5614:                        set_cycles (start_cycles);
        !          5615: #endif
        !          5616:                        custom_reset (cpu_hardreset != 0, cpu_keyboardreset);
        !          5617:                        m68k_reset2 (cpu_hardreset != 0);
        !          5618:                        if (cpu_hardreset) {
        !          5619:                                memory_clear ();
        !          5620:                                write_log (_T("hardreset, memory cleared\n"));
        !          5621:                        }
        !          5622:                        cpu_hardreset = false;
        !          5623: #ifdef SAVESTATE
        !          5624:                        /* We may have been restoring state, but we're done now.  */
        !          5625:                        if (isrestore ()) {
        !          5626:                                if (debug_dma) {
        !          5627:                                        record_dma_reset ();
        !          5628:                                        record_dma_reset ();
        !          5629:                                }
        !          5630:                                savestate_restore_finish ();
        !          5631:                                memory_map_dump ();
        !          5632:                                if (currprefs.mmu_model == 68030) {
        !          5633:                                        mmu030_decode_tc (tc_030);
        !          5634:                                } else if (currprefs.mmu_model >= 68040) {
        !          5635:                                        mmu_set_tc (regs.tcr);
        !          5636:                                }
        !          5637:                                startup = 1;
        !          5638:                                restored = 1;
        !          5639:                        }
        !          5640: #endif
        !          5641:                        if (currprefs.produce_sound == 0)
        !          5642:                                eventtab[ev_audio].active = 0;
        !          5643:                        m68k_setpc_normal (regs.pc);
        !          5644:                        check_prefs_changed_audio ();
        !          5645: 
        !          5646:                        if (!restored || hsync_counter == 0)
        !          5647:                                savestate_check ();
        !          5648:                        if (input_record == INPREC_RECORD_START)
        !          5649:                                input_record = INPREC_RECORD_NORMAL;
        !          5650:                        statusline_clear();
        !          5651:                } else {
        !          5652:                        if (input_record == INPREC_RECORD_START) {
        !          5653:                                input_record = INPREC_RECORD_NORMAL;
        !          5654:                                savestate_init ();
        !          5655:                                hsync_counter = 0;
        !          5656:                                vsync_counter = 0;
        !          5657:                                savestate_check ();
        !          5658:                        }
        !          5659:                }
        !          5660: 
        !          5661:                if (changed_prefs.inprecfile[0] && input_record)
        !          5662:                        inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
        !          5663: #endif
        !          5664: 
        !          5665:                set_cpu_tracer (false);
1.1.1.4   root     5666: 
                   5667: #ifdef DEBUGGER
                   5668:                if (debugging)
                   5669:                        debug ();
                   5670: #endif
1.1.1.7 ! root     5671: /* [NP] TODO : allow changing cpu on the fly ? */
        !          5672: #ifndef WINUAE_FOR_HATARI
        !          5673:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
        !          5674:                        if (cpu_prefs_changed_flag & 1) {
        !          5675:                                uaecptr pc = m68k_getpc();
        !          5676:                                prefs_changed_cpu();
        !          5677:                                build_cpufunctbl();
        !          5678:                                m68k_setpc_normal(pc);
        !          5679:                                fill_prefetch();
        !          5680:                        }
        !          5681:                        if (cpu_prefs_changed_flag & 2) {
        !          5682:                                fixup_cpu(&changed_prefs);
        !          5683:                                currprefs.m68k_speed = changed_prefs.m68k_speed;
        !          5684:                                currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
        !          5685:                                update_68k_cycles();
        !          5686:                        }
        !          5687:                        cpu_prefs_changed_flag = 0;
        !          5688:                }
        !          5689: #else
        !          5690:                /* [NP] : in Hatari, build_cpufunctbl() is called directly from check_prefs_changed_cpu2() */
        !          5691:                /* so we just need to set PC here */
        !          5692:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
        !          5693:                        if (cpu_prefs_changed_flag & 1) {
        !          5694: printf ( "cpu change %d\n" , cpu_prefs_changed_flag );
        !          5695:                                uaecptr pc = m68k_getpc();
        !          5696:                                m68k_setpc_normal(pc);
        !          5697:                                fill_prefetch();
1.1.1.4   root     5698:                        }
1.1.1.7 ! root     5699:                        cpu_prefs_changed_flag = 0;
1.1.1.4   root     5700:                }
1.1.1.7 ! root     5701: #endif
1.1.1.4   root     5702: 
1.1.1.7 ! root     5703:                set_x_funcs();
        !          5704: #ifndef WINUAE_FOR_HATARI
        !          5705:                if (startup) {
        !          5706:                        custom_prepare ();
        !          5707:                        protect_roms (true);
1.1.1.4   root     5708:                }
1.1.1.7 ! root     5709:                startup = 0;
        !          5710:                event_wait = true;
1.1.1.4   root     5711: #endif
1.1.1.7 ! root     5712:                unset_special(SPCFLAG_MODE_CHANGE);
1.1.1.4   root     5713: 
1.1.1.7 ! root     5714:                if (regs.halted) {
        !          5715:                        cpu_halt (regs.halted);
        !          5716:                        if (regs.halted < 0) {
        !          5717:                                haltloop();
        !          5718:                                continue;
        !          5719:                        }
        !          5720:                }
        !          5721: 
        !          5722: #if 0
1.1.1.4   root     5723:                if (mmu_enabled && !currprefs.cachesize) {
                   5724:                        run_func = m68k_run_mmu;
                   5725:                } else {
1.1.1.7 ! root     5726: #endif
        !          5727:                        run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010 ? m68k_run_1_ce :
        !          5728:                                currprefs.cpu_compatible && currprefs.cpu_model <= 68010 ? m68k_run_1 :
1.1.1.4   root     5729: #ifdef JIT
                   5730:                                currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
                   5731: #endif
1.1.1.7 ! root     5732:                                currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
        !          5733:                                currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
        !          5734:                                currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
        !          5735: 
        !          5736:                                currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
1.1.1.4   root     5737:                                currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
1.1.1.7 ! root     5738: 
        !          5739:                                currprefs.cpu_model <= 68020 && currprefs.cpu_compatible ? m68k_run_2p :
        !          5740:                                currprefs.cpu_model == 68030 && currprefs.cpu_compatible ? m68k_run_2p :
        !          5741:                                currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
        !          5742: 
        !          5743:                                m68k_run_2;
        !          5744: #if 0
1.1.1.4   root     5745:                }
1.1.1.7 ! root     5746: #endif
        !          5747:                run_func();
        !          5748: printf ( "exit m68k_run\n" );
1.1.1.4   root     5749:        }
1.1.1.7 ! root     5750: #ifndef WINUAE_FOR_HATARI
        !          5751:        protect_roms (false);
        !          5752: #endif
1.1.1.4   root     5753:        in_m68k_go--;
                   5754: }
                   5755: 
                   5756: #if 0
                   5757: static void m68k_verify (uaecptr addr, uaecptr *nextpc)
                   5758: {
1.1.1.7 ! root     5759:        uae_u16 opcode, val;
1.1.1.4   root     5760:        struct instr *dp;
                   5761: 
                   5762:        opcode = get_iword_1 (0);
                   5763:        last_op_for_exception_3 = opcode;
                   5764:        m68kpc_offset = 2;
                   5765: 
                   5766:        if (cpufunctbl[opcode] == op_illg_1) {
                   5767:                opcode = 0x4AFC;
                   5768:        }
                   5769:        dp = table68k + opcode;
                   5770: 
                   5771:        if (dp->suse) {
                   5772:                if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
                   5773:                        Exception (3, 0);
                   5774:                        return;
                   5775:                }
                   5776:        }
                   5777:        if (dp->duse) {
                   5778:                if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
                   5779:                        Exception (3, 0);
                   5780:                        return;
                   5781:                }
                   5782:        }
                   5783: }
                   5784: #endif
                   5785: 
                   5786: static const TCHAR *ccnames[] =
1.1.1.7 ! root     5787: {
        !          5788:        _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
        !          5789:        _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
        !          5790: };
        !          5791: static const TCHAR *fpccnames[] =
        !          5792: {
        !          5793:        _T("F"),
        !          5794:        _T("EQ"),
        !          5795:        _T("OGT"),
        !          5796:        _T("OGE"),
        !          5797:        _T("OLT"),
        !          5798:        _T("OLE"),
        !          5799:        _T("OGL"),
        !          5800:        _T("OR"),
        !          5801:        _T("UN"),
        !          5802:        _T("UEQ"),
        !          5803:        _T("UGT"),
        !          5804:        _T("UGE"),
        !          5805:        _T("ULT"),
        !          5806:        _T("ULE"),
        !          5807:        _T("NE"),
        !          5808:        _T("T"),
        !          5809:        _T("SF"),
        !          5810:        _T("SEQ"),
        !          5811:        _T("GT"),
        !          5812:        _T("GE"),
        !          5813:        _T("LT"),
        !          5814:        _T("LE"),
        !          5815:        _T("GL"),
        !          5816:        _T("GLE"),
        !          5817:        _T("NGLE"),
        !          5818:        _T("NGL"),
        !          5819:        _T("NLE"),
        !          5820:        _T("NLT"),
        !          5821:        _T("NGE"),
        !          5822:        _T("NGT"),
        !          5823:        _T("SNE"),
        !          5824:        _T("ST")
        !          5825: };
        !          5826: static const TCHAR *fpuopcodes[] =
        !          5827: {
        !          5828:        _T("FMOVE"),
        !          5829:        _T("FINT"),
        !          5830:        _T("FSINH"),
        !          5831:        _T("FINTRZ"),
        !          5832:        _T("FSQRT"),
        !          5833:        NULL,
        !          5834:        _T("FLOGNP1"),
        !          5835:        NULL,
        !          5836:        _T("FETOXM1"),
        !          5837:        _T("FTANH"),
        !          5838:        _T("FATAN"),
        !          5839:        NULL,
        !          5840:        _T("FASIN"),
        !          5841:        _T("FATANH"),
        !          5842:        _T("FSIN"),
        !          5843:        _T("FTAN"),
        !          5844:        _T("FETOX"),    // 0x10
        !          5845:        _T("FTWOTOX"),
        !          5846:        _T("FTENTOX"),
        !          5847:        NULL,
        !          5848:        _T("FLOGN"),
        !          5849:        _T("FLOG10"),
        !          5850:        _T("FLOG2"),
        !          5851:        NULL,
        !          5852:        _T("FABS"),
        !          5853:        _T("FCOSH"),
        !          5854:        _T("FNEG"),
        !          5855:        NULL,
        !          5856:        _T("FACOS"),
        !          5857:        _T("FCOS"),
        !          5858:        _T("FGETEXP"),
        !          5859:        _T("FGETMAN"),
        !          5860:        _T("FDIV"),             // 0x20
        !          5861:        _T("FMOD"),
        !          5862:        _T("FADD"),
        !          5863:        _T("FMUL"),
        !          5864:        _T("FSGLDIV"),
        !          5865:        _T("FREM"),
        !          5866:        _T("FSCALE"),
        !          5867:        _T("FSGLMUL"),
        !          5868:        _T("FSUB"),
        !          5869:        NULL,
        !          5870:        NULL,
        !          5871:        NULL,
        !          5872:        NULL,
        !          5873:        NULL,
        !          5874:        NULL,
        !          5875:        NULL,
        !          5876:        _T("FSINCOS"),  // 0x30
        !          5877:        _T("FSINCOS"),
        !          5878:        _T("FSINCOS"),
        !          5879:        _T("FSINCOS"),
        !          5880:        _T("FSINCOS"),
        !          5881:        _T("FSINCOS"),
        !          5882:        _T("FSINCOS"),
        !          5883:        _T("FSINCOS"),
        !          5884:        _T("FCMP"),
        !          5885:        NULL,
        !          5886:        _T("FTST"),
        !          5887:        NULL,
        !          5888:        NULL,
        !          5889:        NULL,
        !          5890:        NULL,
        !          5891:        NULL
        !          5892: };
        !          5893: 
        !          5894: static const TCHAR *movemregs[] =
        !          5895: {
        !          5896:        _T("D0"),
        !          5897:        _T("D1"),
        !          5898:        _T("D2"),
        !          5899:        _T("D3"),
        !          5900:        _T("D4"),
        !          5901:        _T("D5"),
        !          5902:        _T("D6"),
        !          5903:        _T("D7"),
        !          5904:        _T("A0"),
        !          5905:        _T("A1"),
        !          5906:        _T("A2"),
        !          5907:        _T("A3"),
        !          5908:        _T("A4"),
        !          5909:        _T("A5"),
        !          5910:        _T("A6"),
        !          5911:        _T("A7"),
        !          5912:        _T("FP0"),
        !          5913:        _T("FP1"),
        !          5914:        _T("FP2"),
        !          5915:        _T("FP3"),
        !          5916:        _T("FP4"),
        !          5917:        _T("FP5"),
        !          5918:        _T("FP6"),
        !          5919:        _T("FP7"),
        !          5920:        _T("FPCR"),
        !          5921:        _T("FPSR"),
        !          5922:        _T("FPIAR")
        !          5923: };
1.1.1.4   root     5924: 
1.1.1.7 ! root     5925: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
1.1.1.4   root     5926: {
                   5927:        TCHAR *p = out + _tcslen (out);
                   5928:        if (*prevreg < 0) {
                   5929:                *prevreg = reg;
                   5930:                *lastreg = reg;
                   5931:                return;
                   5932:        }
1.1.1.7 ! root     5933:        if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
        !          5934:                _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
1.1.1.4   root     5935:                p = p + _tcslen (p);
                   5936:                if ((*lastreg) + 2 == reg) {
1.1.1.7 ! root     5937:                        _stprintf (p, _T("/%s"), movemregs[*prevreg]);
1.1.1.4   root     5938:                } else if ((*lastreg) != (*prevreg)) {
1.1.1.7 ! root     5939:                        _stprintf (p, _T("-%s"), movemregs[*prevreg]);
1.1.1.4   root     5940:                }
                   5941:                *lastreg = reg;
                   5942:                *first = 0;
                   5943:        }
                   5944:        *prevreg = reg;
                   5945: }
                   5946: 
1.1.1.7 ! root     5947: static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode)
1.1.1.4   root     5948: {
                   5949:        unsigned int dmask, amask;
                   5950:        int prevreg = -1, lastreg = -1, first = 1;
1.1.1.7 ! root     5951:        int i;
1.1.1.4   root     5952: 
1.1.1.7 ! root     5953:        if (mode == Apdi && !fpmode) {
        !          5954:                uae_u8 dmask2;
        !          5955:                uae_u8 amask2;
        !          5956:                
        !          5957:                amask2 = mask & 0xff;
        !          5958:                dmask2 = (mask >> 8) & 0xff;
1.1.1.4   root     5959:                dmask = 0;
                   5960:                amask = 0;
                   5961:                for (i = 0; i < 8; i++) {
                   5962:                        if (dmask2 & (1 << i))
                   5963:                                dmask |= 1 << (7 - i);
                   5964:                        if (amask2 & (1 << i))
                   5965:                                amask |= 1 << (7 - i);
                   5966:                }
                   5967:        } else {
                   5968:                dmask = mask & 0xff;
                   5969:                amask = (mask >> 8) & 0xff;
1.1.1.7 ! root     5970:                if (fpmode == 1 && mode != Apdi) {
        !          5971:                        uae_u8 dmask2 = dmask;
        !          5972:                        dmask = 0;
        !          5973:                        for (i = 0; i < 8; i++) {
        !          5974:                                if (dmask2 & (1 << i))
        !          5975:                                        dmask |= 1 << (7 - i);
        !          5976:                        }
        !          5977:                }
        !          5978:        }
        !          5979:        if (fpmode) {
        !          5980:                while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
        !          5981:        } else {
        !          5982:                while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
        !          5983:                while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
1.1.1.4   root     5984:        }
1.1.1.7 ! root     5985:        addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
1.1.1.4   root     5986: }
                   5987: 
1.1.1.7 ! root     5988: static const TCHAR *fpsizes[] = {
        !          5989:        _T("L"),
        !          5990:        _T("S"),
        !          5991:        _T("X"),
        !          5992:        _T("P"),
        !          5993:        _T("W"),
        !          5994:        _T("D"),
        !          5995:        _T("B"),
        !          5996:        _T("P")
        !          5997: };
        !          5998: static const int fpsizeconv[] = {
        !          5999:        sz_long,
        !          6000:        sz_single,
        !          6001:        sz_extended,
        !          6002:        sz_packed,
        !          6003:        sz_word,
        !          6004:        sz_double,
        !          6005:        sz_byte,
        !          6006:        sz_packed
        !          6007: };
        !          6008: 
1.1.1.4   root     6009: static void disasm_size (TCHAR *instrname, struct instr *dp)
                   6010: {
1.1.1.7 ! root     6011:        if (dp->unsized) {
        !          6012:                _tcscat(instrname, _T(" "));
        !          6013:                return;
1.1.1.4   root     6014:        }
                   6015:        switch (dp->size)
                   6016:        {
                   6017:        case sz_byte:
1.1.1.7 ! root     6018:                _tcscat (instrname, _T(".B "));
1.1.1.4   root     6019:                break;
                   6020:        case sz_word:
1.1.1.7 ! root     6021:                _tcscat (instrname, _T(".W "));
1.1.1.4   root     6022:                break;
                   6023:        case sz_long:
1.1.1.7 ! root     6024:                _tcscat (instrname, _T(".L "));
1.1.1.4   root     6025:                break;
                   6026:        default:
1.1.1.7 ! root     6027:                _tcscat (instrname, _T(" "));
1.1.1.4   root     6028:                break;
                   6029:        }
                   6030: }
                   6031: 
1.1.1.7 ! root     6032: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
1.1.1.4   root     6033: {
1.1.1.7 ! root     6034:        uae_u32 seaddr2;
        !          6035:        uae_u32 deaddr2;
1.1.1.4   root     6036: 
1.1.1.7 ! root     6037:        if (buf)
        !          6038:                memset (buf, 0, bufsize * sizeof (TCHAR));
1.1.1.4   root     6039:        if (!table68k)
                   6040:                return;
                   6041:        while (cnt-- > 0) {
                   6042:                TCHAR instrname[100], *ccpt;
                   6043:                int i;
                   6044:                uae_u32 opcode;
1.1.1.7 ! root     6045:                uae_u16 extra;
1.1.1.4   root     6046:                struct mnemolookup *lookup;
                   6047:                struct instr *dp;
1.1.1.7 ! root     6048:                uaecptr oldpc;
        !          6049:                uaecptr m68kpc_illg = 0;
        !          6050:                bool illegal = false;
        !          6051: 
        !          6052:                seaddr2 = deaddr2 = 0;
        !          6053:                oldpc = pc;
        !          6054:                opcode = get_word_debug (pc);
        !          6055:                extra = get_word_debug (pc + 2);
        !          6056:                if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
        !          6057:                        m68kpc_illg = pc + 2;
        !          6058:                        illegal = TRUE;
        !          6059:                }
1.1.1.4   root     6060: 
1.1.1.7 ! root     6061:                dp = table68k + opcode;
        !          6062:                if (dp->mnemo == i_ILLG) {
        !          6063:                        illegal = FALSE;
1.1.1.4   root     6064:                        opcode = 0x4AFC;
1.1.1.7 ! root     6065:                        dp = table68k + opcode;
1.1.1.4   root     6066:                }
                   6067:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   6068:                        ;
                   6069: 
1.1.1.7 ! root     6070:                buf = buf_out (buf, &bufsize, _T("%08X "), pc);
1.1.1.4   root     6071: 
1.1.1.7 ! root     6072:                pc += 2;
        !          6073:                
        !          6074:                if (lookup->friendlyname)
1.1.1.4   root     6075:                        _tcscpy (instrname, lookup->friendlyname);
                   6076:                else
                   6077:                        _tcscpy (instrname, lookup->name);
1.1.1.7 ! root     6078:                ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4   root     6079:                if (ccpt != 0) {
1.1.1.7 ! root     6080:                        if ((opcode & 0xf000) == 0xf000)
        !          6081:                                _tcscpy (ccpt, fpccnames[extra & 0x1f]);
        !          6082:                        else
        !          6083:                                _tcsncpy (ccpt, ccnames[dp->cc], 2);
1.1.1.4   root     6084:                }
                   6085:                disasm_size (instrname, dp);
                   6086: 
                   6087:                if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
1.1.1.7 ! root     6088:                        uae_u16 imm = extra;
1.1.1.4   root     6089:                        uae_u16 creg = imm & 0x0fff;
                   6090:                        uae_u16 r = imm >> 12;
                   6091:                        TCHAR regs[16];
1.1.1.7 ! root     6092:                        const TCHAR *cname = _T("?");
1.1.1.4   root     6093:                        int i;
                   6094:                        for (i = 0; m2cregs[i].regname; i++) {
                   6095:                                if (m2cregs[i].regno == creg)
                   6096:                                        break;
                   6097:                        }
1.1.1.7 ! root     6098:                        _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
1.1.1.4   root     6099:                        if (m2cregs[i].regname)
                   6100:                                cname = m2cregs[i].regname;
                   6101:                        if (lookup->mnemo == i_MOVE2C) {
                   6102:                                _tcscat (instrname, regs);
1.1.1.7 ! root     6103:                                _tcscat (instrname, _T(","));
1.1.1.4   root     6104:                                _tcscat (instrname, cname);
                   6105:                        } else {
                   6106:                                _tcscat (instrname, cname);
1.1.1.7 ! root     6107:                                _tcscat (instrname, _T(","));
1.1.1.4   root     6108:                                _tcscat (instrname, regs);
                   6109:                        }
1.1.1.7 ! root     6110:                        pc += 2;
1.1.1.4   root     6111:                } else if (lookup->mnemo == i_MVMEL) {
1.1.1.7 ! root     6112:                        uae_u16 mask = extra;
        !          6113:                        pc += 2;
        !          6114:                        pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          6115:                        _tcscat (instrname, _T(","));
        !          6116:                        movemout (instrname, mask, dp->dmode, 0);
1.1.1.4   root     6117:                } else if (lookup->mnemo == i_MVMLE) {
1.1.1.7 ! root     6118:                        uae_u16 mask = extra;
        !          6119:                        pc += 2;
        !          6120:                        movemout(instrname, mask, dp->dmode, 0);
        !          6121:                        _tcscat(instrname, _T(","));
        !          6122:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          6123:                } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
        !          6124:                        TCHAR *p;
        !          6125:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
        !          6126:                        extra = get_word_debug(pc);
        !          6127:                        pc += 2;
        !          6128:                        p = instrname + _tcslen(instrname);
        !          6129:                        if (extra & 0x0400)
        !          6130:                                _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
        !          6131:                        else
        !          6132:                                _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
        !          6133:                } else if (lookup->mnemo == i_MOVES) {
        !          6134:                        TCHAR *p;
        !          6135:                        pc += 2;
        !          6136:                        if (!(extra & 0x1000)) {
        !          6137:                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
        !          6138:                                p = instrname + _tcslen(instrname);
        !          6139:                                _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
        !          6140:                        } else {
        !          6141:                                p = instrname + _tcslen(instrname);
        !          6142:                                _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
        !          6143:                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
        !          6144:                        }
        !          6145:                } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
        !          6146:                                   lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
        !          6147:                                   lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
        !          6148:                                   lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
        !          6149:                        TCHAR *p;
        !          6150:                        int reg = -1;
        !          6151: 
        !          6152:                        pc += 2;
        !          6153:                        p = instrname + _tcslen(instrname);
        !          6154:                        if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
        !          6155:                                reg = (extra >> 12) & 7;
        !          6156:                        if (lookup->mnemo == i_BFINS)
        !          6157:                                _stprintf(p, _T("D%d,"), reg);
        !          6158:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
        !          6159:                        _tcscat(instrname, _T(" {"));
        !          6160:                        p = instrname + _tcslen(instrname);
        !          6161:                        if (extra & 0x0800)
        !          6162:                                _stprintf(p, _T("D%d"), (extra >> 6) & 7);
        !          6163:                        else
        !          6164:                                _stprintf(p, _T("%d"), (extra >> 6) & 31);
        !          6165:                        _tcscat(instrname, _T(":"));
        !          6166:                        p = instrname + _tcslen(instrname);
        !          6167:                        if (extra & 0x0020)
        !          6168:                                _stprintf(p, _T("D%d"), extra & 7);
        !          6169:                        else
        !          6170:                                _stprintf(p, _T("%d"), extra  & 31);
        !          6171:                        _tcscat(instrname, _T("}"));
        !          6172:                        p = instrname + _tcslen(instrname);
        !          6173:                        if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
        !          6174:                                _stprintf(p, _T(",D%d"), reg);
        !          6175:                } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
        !          6176:                        lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
        !          6177:                        if ((opcode & 0xc0) == 0xc0)
        !          6178:                                _tcscat(instrname, _T("BC"));
        !          6179:                        else if (opcode & 0x80)
        !          6180:                                _tcscat(instrname, _T("IC"));
        !          6181:                        else if (opcode & 0x40)
        !          6182:                                _tcscat(instrname, _T("DC"));
        !          6183:                        else
        !          6184:                                _tcscat(instrname, _T("?"));
        !          6185:                        if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
        !          6186:                                TCHAR *p = instrname + _tcslen(instrname);
        !          6187:                                _stprintf(p, _T(",(A%d)"), opcode & 7);
        !          6188:                        }
        !          6189:                } else if (lookup->mnemo == i_FPP) {
        !          6190:                        TCHAR *p;
        !          6191:                        int ins = extra & 0x3f;
        !          6192:                        int size = (extra >> 10) & 7;
        !          6193: 
        !          6194:                        pc += 2;
        !          6195:                        if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
        !          6196:                                fpdata fp;
        !          6197:                                if (fpu_get_constant(&fp, extra))
        !          6198: #if USE_LONG_DOUBLE
        !          6199:                                        _stprintf(instrname, _T("FMOVECR.X #%Le,FP%d"), fp.fp, (extra >> 7) & 7);
        !          6200: #else
        !          6201:                                        _stprintf(instrname, _T("FMOVECR.X #%e,FP%d"), fp.fp, (extra >> 7) & 7);
        !          6202: #endif
        !          6203:                                else
        !          6204:                                        _stprintf(instrname, _T("FMOVECR.X #?,FP%d"), (extra >> 7) & 7);
        !          6205:                        } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
        !          6206:                                int dr = (extra >> 13) & 1;
        !          6207:                                int mode;
        !          6208:                                int dreg = (extra >> 4) & 7;
        !          6209:                                int regmask, fpmode;
        !          6210:                                
        !          6211:                                if (extra & 0x4000) {
        !          6212:                                        mode = (extra >> 11) & 3;
        !          6213:                                        regmask = extra & 0xff;  // FMOVEM FPx
        !          6214:                                        fpmode = 1;
        !          6215:                                        _tcscpy(instrname, _T("FMOVEM.X "));
        !          6216:                                } else {
        !          6217:                                        mode = 0;
        !          6218:                                        regmask = (extra >> 10) & 7;  // FMOVEM control
        !          6219:                                        fpmode = 2;
        !          6220:                                        _tcscpy(instrname, _T("FMOVEM.L "));
        !          6221:                                        if (regmask == 1 || regmask == 2 || regmask == 4)
        !          6222:                                                _tcscpy(instrname, _T("FMOVE.L "));
        !          6223:                                }
        !          6224:                                p = instrname + _tcslen(instrname);
        !          6225:                                if (dr) {
        !          6226:                                        if (mode & 1)
        !          6227:                                                _stprintf(instrname, _T("D%d"), dreg);
        !          6228:                                        else
        !          6229:                                                movemout(instrname, regmask, dp->dmode, fpmode);
        !          6230:                                        _tcscat(instrname, _T(","));
        !          6231:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          6232:                                } else {
        !          6233:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
        !          6234:                                        _tcscat(instrname, _T(","));
        !          6235:                                        p = instrname + _tcslen(instrname);
        !          6236:                                        if (mode & 1)
        !          6237:                                                _stprintf(p, _T("D%d"), dreg);
        !          6238:                                        else
        !          6239:                                                movemout(p, regmask, dp->dmode, fpmode);
        !          6240:                                }
        !          6241:                        } else {
        !          6242:                                if (fpuopcodes[ins])
        !          6243:                                        _tcscpy(instrname, fpuopcodes[ins]);
        !          6244:                                else
        !          6245:                                        _tcscpy(instrname, _T("F?"));
        !          6246: 
        !          6247:                                if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
        !          6248:                                        int kfactor = extra & 0x7f;
        !          6249:                                        _tcscpy(instrname, _T("FMOVE."));
        !          6250:                                        _tcscat(instrname, fpsizes[size]);
        !          6251:                                        _tcscat(instrname, _T(" "));
        !          6252:                                        p = instrname + _tcslen(instrname);
        !          6253:                                        _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
        !          6254:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
        !          6255:                                        p = instrname + _tcslen(instrname);
        !          6256:                                        if (size == 7) {
        !          6257:                                                _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
        !          6258:                                        } else if (kfactor) {
        !          6259:                                                if (kfactor & 0x40)
        !          6260:                                                        kfactor |= ~0x3f;
        !          6261:                                                _stprintf(p, _T(" {%d}"), kfactor);
        !          6262:                                        }
        !          6263:                                } else {
        !          6264:                                        if (extra & 0x4000) { // source is EA
        !          6265:                                                _tcscat(instrname, _T("."));
        !          6266:                                                _tcscat(instrname, fpsizes[size]);
        !          6267:                                                _tcscat(instrname, _T(" "));
        !          6268:                                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
        !          6269:                                        } else { // source is FPx
        !          6270:                                                p = instrname + _tcslen(instrname);
        !          6271:                                                _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
        !          6272:                                        }
        !          6273:                                        p = instrname + _tcslen(instrname);
        !          6274:                                        if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
        !          6275:                                                _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
        !          6276:                                        if (ins >= 0x30 && ins < 0x38) { // FSINCOS
        !          6277:                                                p = instrname + _tcslen(instrname);
        !          6278:                                                _stprintf(p, _T(",FP%d"), extra & 7);
        !          6279:                                        }
        !          6280:                                }
        !          6281:                        }
        !          6282:                } else if ((opcode & 0xf000) == 0xa000) {
        !          6283:                        _tcscpy(instrname, _T("A-LINE"));
1.1.1.4   root     6284:                } else {
                   6285:                        if (dp->suse) {
1.1.1.7 ! root     6286:                                pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
1.1.1.4   root     6287:                        }
                   6288:                        if (dp->suse && dp->duse)
1.1.1.7 ! root     6289:                                _tcscat (instrname, _T(","));
1.1.1.4   root     6290:                        if (dp->duse) {
1.1.1.7 ! root     6291:                                pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
1.1.1.4   root     6292:                        }
                   6293:                }
                   6294: 
1.1.1.7 ! root     6295:                for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) {
        !          6296:                        buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
1.1.1.4   root     6297:                }
                   6298:                while (i++ < 5)
1.1.1.7 ! root     6299:                        buf = buf_out (buf, &bufsize, _T("     "));
1.1.1.4   root     6300: 
1.1.1.7 ! root     6301:                if (illegal)
        !          6302:                        buf = buf_out (buf, &bufsize, _T("[ "));
        !          6303:                buf = buf_out (buf, &bufsize, instrname);
        !          6304:                if (illegal)
        !          6305:                        buf = buf_out (buf, &bufsize, _T(" ]"));
1.1.1.4   root     6306: 
                   6307:                if (ccpt != 0) {
1.1.1.7 ! root     6308:                        uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
1.1.1.4   root     6309:                        if (deaddr)
1.1.1.7 ! root     6310:                                *deaddr = pc;
        !          6311:                        if ((opcode & 0xf000) == 0xf000) {
        !          6312:                                if (fpp_cond(dp->cc)) {
        !          6313:                                        buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
        !          6314:                                } else {
        !          6315:                                        buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
        !          6316:                                }
        !          6317:                        } else {
        !          6318:                                if (cctrue (dp->cc)) {
        !          6319:                                        buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
        !          6320:                                } else {
        !          6321:                                        buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
        !          6322:                                }
        !          6323:                        }
1.1.1.4   root     6324:                } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
                   6325:                        if (deaddr)
1.1.1.7 ! root     6326:                                *deaddr = pc;
        !          6327:                        buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
1.1.1.4   root     6328:                }
1.1.1.7 ! root     6329:                buf = buf_out (buf, &bufsize, _T("\n"));
        !          6330: 
        !          6331:                if (illegal)
        !          6332:                        pc =  m68kpc_illg;
1.1.1.4   root     6333:        }
                   6334:        if (nextpc)
1.1.1.7 ! root     6335:                *nextpc = pc;
        !          6336:        if (seaddr)
        !          6337:                *seaddr = seaddr2;
        !          6338:        if (deaddr)
        !          6339:                *deaddr = deaddr2;
1.1.1.4   root     6340: }
                   6341: 
1.1.1.7 ! root     6342: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
        !          6343: {
        !          6344:        TCHAR *buf;
        !          6345: 
        !          6346:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
        !          6347:        if (!buf)
        !          6348:                return;
        !          6349:        m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
        !          6350:        xfree (buf);
        !          6351: }
        !          6352: void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.4   root     6353: {
1.1.1.7 ! root     6354:        TCHAR *buf;
        !          6355: 
        !          6356:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
        !          6357:        if (!buf)
        !          6358:                return;
        !          6359:        m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
        !          6360:        console_out_f (_T("%s"), buf);
        !          6361:        xfree (buf);
1.1.1.4   root     6362: }
1.1.1.7 ! root     6363: void m68k_disasm_file (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.4   root     6364: {
1.1.1.7 ! root     6365:        TCHAR *buf;
        !          6366: 
        !          6367:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
        !          6368:        if (!buf)
        !          6369:                return;
        !          6370:        console_out_FILE = f;
        !          6371:        m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
        !          6372:        f_out (f, _T("%s"), buf);
        !          6373:        xfree (buf);
        !          6374:        console_out_FILE = NULL;
1.1.1.4   root     6375: }
                   6376: 
                   6377: /*************************************************************
                   6378: Disasm the m68kcode at the given address into instrname
                   6379: and instrcode
                   6380: *************************************************************/
                   6381: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
                   6382: {
                   6383:        TCHAR *ccpt;
                   6384:        uae_u32 opcode;
                   6385:        struct mnemolookup *lookup;
                   6386:        struct instr *dp;
1.1.1.7 ! root     6387:        uaecptr pc, oldpc;
1.1.1.4   root     6388: 
1.1.1.7 ! root     6389:        pc = oldpc = addr;
        !          6390:        opcode = get_word_debug (pc);
1.1.1.4   root     6391:        if (cpufunctbl[opcode] == op_illg_1) {
                   6392:                opcode = 0x4AFC;
                   6393:        }
                   6394:        dp = table68k + opcode;
                   6395:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
                   6396: 
1.1.1.7 ! root     6397:        pc += 2;
1.1.1.4   root     6398: 
                   6399:        _tcscpy (instrname, lookup->name);
1.1.1.7 ! root     6400:        ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4   root     6401:        if (ccpt != 0) {
                   6402:                _tcsncpy (ccpt, ccnames[dp->cc], 2);
                   6403:        }
                   6404:        switch (dp->size){
1.1.1.7 ! root     6405:        case sz_byte: _tcscat (instrname, _T(".B ")); break;
        !          6406:        case sz_word: _tcscat (instrname, _T(".W ")); break;
        !          6407:        case sz_long: _tcscat (instrname, _T(".L ")); break;
        !          6408:        default: _tcscat (instrname, _T("   ")); break;
1.1.1.4   root     6409:        }
                   6410: 
                   6411:        if (dp->suse) {
1.1.1.7 ! root     6412:                pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
1.1.1.4   root     6413:        }
                   6414:        if (dp->suse && dp->duse)
1.1.1.7 ! root     6415:                _tcscat (instrname, _T(","));
1.1.1.4   root     6416:        if (dp->duse) {
1.1.1.7 ! root     6417:                pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
1.1.1.4   root     6418:        }
                   6419:        if (instrcode)
                   6420:        {
                   6421:                int i;
1.1.1.7 ! root     6422:                for (i = 0; i < (int)(pc - oldpc) / 2; i++)
1.1.1.4   root     6423:                {
1.1.1.7 ! root     6424:                        _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
1.1.1.4   root     6425:                        instrcode += _tcslen (instrcode);
                   6426:                }
                   6427:        }
                   6428:        if (nextpc)
1.1.1.7 ! root     6429:                *nextpc = pc;
1.1.1.4   root     6430: }
                   6431: 
                   6432: struct cpum2c m2cregs[] = {
1.1.1.7 ! root     6433:        { 0, _T("SFC") },
        !          6434:        { 1, _T("DFC") },
        !          6435:        { 2, _T("CACR") },
        !          6436:        { 3, _T("TC") },
        !          6437:        { 4, _T("ITT0") },
        !          6438:        { 5, _T("ITT1") },
        !          6439:        { 6, _T("DTT0") },
        !          6440:        { 7, _T("DTT1") },
        !          6441:        { 8, _T("BUSC") },
        !          6442:        { 0x800, _T("USP") },
        !          6443:        { 0x801, _T("VBR") },
        !          6444:        { 0x802, _T("CAAR") },
        !          6445:        { 0x803, _T("MSP") },
        !          6446:        { 0x804, _T("ISP") },
        !          6447:        { 0x805, _T("MMUS") },
        !          6448:        { 0x806, _T("URP") },
        !          6449:        { 0x807, _T("SRP") },
        !          6450:        { 0x808, _T("PCR") },
        !          6451:     { -1, NULL }
1.1.1.4   root     6452: };
                   6453: 
1.1.1.7 ! root     6454: void m68k_dumpstate_2 (uaecptr pc, uaecptr *nextpc)
1.1.1.4   root     6455: {
                   6456:        int i, j;
                   6457: 
                   6458:        for (i = 0; i < 8; i++){
1.1.1.7 ! root     6459:                console_out_f (_T("  D%d %08X "), i, m68k_dreg (regs, i));
        !          6460:                if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4   root     6461:        }
                   6462:        for (i = 0; i < 8; i++){
1.1.1.7 ! root     6463:                console_out_f (_T("  A%d %08X "), i, m68k_areg (regs, i));
        !          6464:                if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4   root     6465:        }
                   6466:        if (regs.s == 0)
                   6467:                regs.usp = m68k_areg (regs, 7);
                   6468:        if (regs.s && regs.m)
                   6469:                regs.msp = m68k_areg (regs, 7);
                   6470:        if (regs.s && regs.m == 0)
                   6471:                regs.isp = m68k_areg (regs, 7);
                   6472:        j = 2;
1.1.1.7 ! root     6473:        console_out_f (_T("USP  %08X ISP  %08X "), regs.usp, regs.isp);
1.1.1.4   root     6474:        for (i = 0; m2cregs[i].regno>= 0; i++) {
                   6475:                if (!movec_illg (m2cregs[i].regno)) {
1.1.1.7 ! root     6476:                        if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
1.1.1.4   root     6477:                                continue;
                   6478:                        if (j > 0 && (j % 4) == 0)
1.1.1.7 ! root     6479:                                console_out_f (_T("\n"));
        !          6480:                        console_out_f (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
1.1.1.4   root     6481:                        j++;
                   6482:                }
                   6483:        }
                   6484:        if (j > 0)
1.1.1.7 ! root     6485:                console_out_f (_T("\n"));
        !          6486:                console_out_f (_T("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n"),
1.1.1.4   root     6487:                regs.t1, regs.t0, regs.s, regs.m,
                   6488:                GET_XFLG (), GET_NFLG (), GET_ZFLG (),
                   6489:                GET_VFLG (), GET_CFLG (),
                   6490:                regs.intmask, regs.stopped);
                   6491: #ifdef FPUEMU
                   6492:        if (currprefs.fpu_model) {
                   6493:                uae_u32 fpsr;
                   6494:                for (i = 0; i < 8; i++){
1.1.1.7 ! root     6495:                        console_out_f (_T("FP%d: %g "), i, regs.fp[i].fp);
1.1.1.4   root     6496:                        if ((i & 3) == 3)
1.1.1.7 ! root     6497:                                console_out_f (_T("\n"));
1.1.1.4   root     6498:                }
1.1.1.7 ! root     6499:                fpsr = fpp_get_fpsr ();
        !          6500:                console_out_f (_T("FPSR: %04X FPCR: %08x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
        !          6501:                        fpsr, regs.fpcr, regs.fpiar,
1.1.1.4   root     6502:                        (fpsr & 0x8000000) != 0,
                   6503:                        (fpsr & 0x4000000) != 0,
                   6504:                        (fpsr & 0x2000000) != 0,
                   6505:                        (fpsr & 0x1000000) != 0);
                   6506:        }
                   6507: #endif
1.1.1.7 ! root     6508:        if (currprefs.mmu_model == 68030) {
        !          6509: #ifndef WINUAE_FOR_HATARI
        !          6510:                console_out_f (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
        !          6511: #else
        !          6512:                console_out_f (_T("SRP: %"PRIX64" CRP: %"PRIX64"\n"), srp_030, crp_030);
        !          6513: #endif
        !          6514:                console_out_f (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
        !          6515:        }
1.1.1.4   root     6516:        if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
                   6517:                struct instr *dp;
                   6518:                struct mnemolookup *lookup1, *lookup2;
                   6519:                dp = table68k + regs.irc;
                   6520:                for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
                   6521:                dp = table68k + regs.ir;
                   6522:                for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
1.1.1.7 ! root     6523:                console_out_f (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
1.1.1.4   root     6524:        }
                   6525: 
1.1.1.7 ! root     6526:        if (pc != 0xffffffff) {
        !          6527:                m68k_disasm (pc, nextpc, 1);
        !          6528:                if (nextpc)
        !          6529:                        console_out_f (_T("Next PC: %08x\n"), *nextpc);
        !          6530:        }
        !          6531: }
        !          6532: void m68k_dumpstate (uaecptr *nextpc)
        !          6533: {
        !          6534:        m68k_dumpstate_2 (m68k_getpc (), nextpc);
        !          6535: }
        !          6536: #ifdef WINUAE_FOR_HATARI
        !          6537: void m68k_dumpstate_file (FILE *f, uaecptr *nextpc)
        !          6538: {
        !          6539:        console_out_FILE = f;
        !          6540:        m68k_dumpstate_2 (m68k_getpc (), nextpc);
        !          6541:        console_out_FILE = NULL;
        !          6542: }
        !          6543: #endif
        !          6544: void m68k_dumpcache (void)
        !          6545: {
        !          6546:        int i , j;
        !          6547: 
        !          6548:        if (!currprefs.cpu_compatible)
        !          6549:                return;
        !          6550:        if (currprefs.cpu_model == 68020) {
        !          6551:                for (i = 0; i < CACHELINES020; i += 4) {
        !          6552:                        for (j = 0; j < 4; j++) {
        !          6553:                                int s = i + j;
        !          6554:                                uaecptr addr;
        !          6555:                                struct cache020 *c = &caches020[s];
        !          6556:                                addr = c->tag & ~1;
        !          6557:                                addr |= s << 2;
        !          6558:                                console_out_f (_T("%08X:%08X%c "), addr, c->data, c->valid ? '*' : ' ');
        !          6559:                        }
        !          6560:                        console_out_f (_T("\n"));
        !          6561:                }
        !          6562:        } else if (currprefs.cpu_model == 68030) {
        !          6563:                for (i = 0; i < CACHELINES030; i++) {
        !          6564:                        struct cache030 *c = &icaches030[i];
        !          6565:                        uaecptr addr;
        !          6566:                        addr = c->tag & ~1;
        !          6567:                        addr |= i << 4;
        !          6568:                        console_out_f (_T("%08X: "), addr);
        !          6569:                        for (j = 0; j < 4; j++) {
        !          6570:                                console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
        !          6571:                        }
        !          6572:                        console_out_f (_T("\n"));
        !          6573:                }
        !          6574:        }
1.1.1.4   root     6575: }
                   6576: 
                   6577: #ifdef SAVESTATE
                   6578: 
                   6579: /* CPU save/restore code */
                   6580: 
                   6581: #define CPUTYPE_EC 1
                   6582: #define CPUMODE_HALT 1
                   6583: 
                   6584: uae_u8 *restore_cpu (uae_u8 *src)
                   6585: {
1.1.1.7 ! root     6586:        int i, j , flags, model;
1.1.1.4   root     6587:        uae_u32 l;
                   6588: 
1.1.1.7 ! root     6589:        currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 ();
1.1.1.4   root     6590:        flags = restore_u32 ();
                   6591:        changed_prefs.address_space_24 = 0;
                   6592:        if (flags & CPUTYPE_EC)
                   6593:                changed_prefs.address_space_24 = 1;
                   6594:        currprefs.address_space_24 = changed_prefs.address_space_24;
                   6595:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                   6596:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
                   6597:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
                   6598:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
                   6599:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
                   6600:        for (i = 0; i < 15; i++)
                   6601:                regs.regs[i] = restore_u32 ();
                   6602:        regs.pc = restore_u32 ();
                   6603:        regs.irc = restore_u16 ();
                   6604:        regs.ir = restore_u16 ();
                   6605:        regs.usp = restore_u32 ();
                   6606:        regs.isp = restore_u32 ();
                   6607:        regs.sr = restore_u16 ();
1.1.1.7 ! root     6608: printf ( "restore %x %x %x\n" , regs.usp , regs.isp , regs.sr );
1.1.1.4   root     6609:        l = restore_u32 ();
                   6610:        if (l & CPUMODE_HALT) {
                   6611:                regs.stopped = 1;
                   6612:        } else {
                   6613:                regs.stopped = 0;
                   6614:        }
                   6615:        if (model >= 68010) {
                   6616:                regs.dfc = restore_u32 ();
                   6617:                regs.sfc = restore_u32 ();
                   6618:                regs.vbr = restore_u32 ();
                   6619:        }
                   6620:        if (model >= 68020) {
                   6621:                regs.caar = restore_u32 ();
                   6622:                regs.cacr = restore_u32 ();
                   6623:                regs.msp = restore_u32 ();
                   6624:        }
                   6625:        if (model >= 68030) {
1.1.1.7 ! root     6626:                crp_030 = fake_crp_030 = restore_u64 ();
        !          6627:                srp_030 = fake_srp_030 = restore_u64 ();
        !          6628:                tt0_030 = fake_tt0_030 = restore_u32 ();
        !          6629:                tt1_030 = fake_tt1_030 = restore_u32 ();
        !          6630:                tc_030 = fake_tc_030 = restore_u32 ();
        !          6631:                mmusr_030 = fake_mmusr_030 = restore_u16 ();
1.1.1.4   root     6632:        }
                   6633:        if (model >= 68040) {
                   6634:                regs.itt0 = restore_u32 ();
                   6635:                regs.itt1 = restore_u32 ();
                   6636:                regs.dtt0 = restore_u32 ();
                   6637:                regs.dtt1 = restore_u32 ();
                   6638:                regs.tcr = restore_u32 ();
                   6639:                regs.urp = restore_u32 ();
                   6640:                regs.srp = restore_u32 ();
                   6641:        }
                   6642:        if (model >= 68060) {
                   6643:                regs.buscr = restore_u32 ();
                   6644:                regs.pcr = restore_u32 ();
                   6645:        }
                   6646:        if (flags & 0x80000000) {
                   6647:                int khz = restore_u32 ();
                   6648:                restore_u32 ();
                   6649:                if (khz > 0 && khz < 800000)
                   6650:                        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
                   6651:        }
1.1.1.7 ! root     6652:        set_cpu_caches (true);
        !          6653:        if (flags & 0x40000000) {
        !          6654:                if (model == 68020) {
        !          6655:                        for (i = 0; i < CACHELINES020; i++) {
        !          6656:                                caches020[i].data = restore_u32 ();
        !          6657:                                caches020[i].tag = restore_u32 ();
        !          6658:                                caches020[i].valid = restore_u8 () != 0;
        !          6659:                        }
        !          6660:                        regs.prefetch020addr = restore_u32 ();
        !          6661:                        regs.cacheholdingaddr020 = restore_u32 ();
        !          6662:                        regs.cacheholdingdata020 = restore_u32 ();
        !          6663:                        if (flags & 0x20000000) {
        !          6664:                                // 2.7.0 new
        !          6665:                                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6666:                                        regs.prefetch020[i] = restore_u32 ();
        !          6667:                        } else {
        !          6668:                                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6669:                                        regs.prefetch020[i] = restore_u16 ();
        !          6670:                        }
        !          6671:                } else if (model == 68030) {
        !          6672:                        for (i = 0; i < CACHELINES030; i++) {
        !          6673:                                for (j = 0; j < 4; j++) {
        !          6674:                                        icaches030[i].data[j] = restore_u32 ();
        !          6675:                                        icaches030[i].valid[j] = restore_u8 () != 0;
        !          6676:                                }
        !          6677:                                icaches030[i].tag = restore_u32 ();
        !          6678:                        }
        !          6679:                        for (i = 0; i < CACHELINES030; i++) {
        !          6680:                                for (j = 0; j < 4; j++) {
        !          6681:                                        dcaches030[i].data[j] = restore_u32 ();
        !          6682:                                        dcaches030[i].valid[j] = restore_u8 () != 0;
        !          6683:                                }
        !          6684:                                dcaches030[i].tag = restore_u32 ();
        !          6685:                        }
        !          6686:                        regs.prefetch020addr = restore_u32 ();
        !          6687:                        regs.cacheholdingaddr020 = restore_u32 ();
        !          6688:                        regs.cacheholdingdata020 = restore_u32 ();
        !          6689:                        for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6690:                                regs.prefetch020[i] = restore_u32 ();
        !          6691:                } else if (model == 68040) {
        !          6692:                        if (flags & 0x8000000) {
        !          6693:                                for (i = 0; i < CACHESETS040; i++) {
        !          6694:                                        for (j = 0; j < CACHELINES040; j++) {
        !          6695:                                                icaches040[i].data[j][0] = restore_u32();
        !          6696:                                                icaches040[i].data[j][1] = restore_u32();
        !          6697:                                                icaches040[i].data[j][2] = restore_u32();
        !          6698:                                                icaches040[i].data[j][3] = restore_u32();
        !          6699:                                                icaches040[i].tag[j] = restore_u32();
        !          6700:                                                icaches040[i].valid[j] = restore_u16() & 1;
        !          6701:                                        }
        !          6702:                                }
        !          6703:                                regs.prefetch020addr = restore_u32();
        !          6704:                                regs.cacheholdingaddr020 = restore_u32();
        !          6705:                                regs.cacheholdingdata020 = restore_u32();
        !          6706:                                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6707:                                        regs.prefetch020[i] = restore_u32();
        !          6708:                        }
        !          6709:                }
        !          6710:                if (model >= 68020) {
        !          6711:                        regs.ce020memcycles = restore_u32 ();
        !          6712:                        restore_u32 ();
        !          6713:                }
        !          6714:        }
        !          6715:        if (flags & 0x10000000) {
        !          6716:                regs.chipset_latch_rw = restore_u32 ();
        !          6717:                regs.chipset_latch_read = restore_u32 ();
        !          6718:                regs.chipset_latch_write = restore_u32 ();
        !          6719:        }
        !          6720: 
        !          6721:        m68k_reset_sr();
        !          6722: 
        !          6723:        write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
        !          6724:                model / 1000, flags & 1 ? _T("EC") : _T(""), model % 1000, regs.pc);
1.1.1.4   root     6725: 
                   6726:        return src;
                   6727: }
                   6728: 
1.1.1.7 ! root     6729: static void fill_prefetch_quick (void)
        !          6730: {
        !          6731:        if (currprefs.cpu_model >= 68020) {
        !          6732:                fill_prefetch ();
        !          6733:                return;
        !          6734:        }
        !          6735:        // old statefile compatibility, this needs to done,
        !          6736:        // even in 68000 cycle-exact mode
        !          6737:        regs.ir = get_word (m68k_getpc ());
        !          6738:        regs.irc = get_word (m68k_getpc () + 2);
        !          6739: }
        !          6740: 
1.1.1.4   root     6741: void restore_cpu_finish (void)
                   6742: {
                   6743:        init_m68k ();
1.1.1.7 ! root     6744:        m68k_setpc_normal (regs.pc);
1.1.1.4   root     6745:        doint ();
1.1.1.7 ! root     6746:        fill_prefetch_quick ();
        !          6747: printf ( "SR %x %x %x %x\n" , regs.sr , regs.isp , regs.usp , regs.regs[15] );
        !          6748: #ifndef WINUAE_FOR_HATARI
        !          6749:        set_cycles (start_cycles);
        !          6750:        events_schedule ();
        !          6751: #endif
1.1.1.4   root     6752:        if (regs.stopped)
                   6753:                set_special (SPCFLAG_STOP);
                   6754:        //activate_debugger ();
                   6755: }
                   6756: 
1.1.1.7 ! root     6757: uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
1.1.1.4   root     6758: {
1.1.1.7 ! root     6759:        uae_u8 *dstbak, *dst;
        !          6760:        int i;
1.1.1.4   root     6761: 
1.1.1.7 ! root     6762:        if (cputrace.state <= 0)
        !          6763:                return NULL;
1.1.1.4   root     6764: 
1.1.1.7 ! root     6765:        if (dstptr)
        !          6766:                dstbak = dst = dstptr;
        !          6767:        else
        !          6768:                dstbak = dst = xmalloc (uae_u8, 1000);
        !          6769: 
        !          6770:        save_u32 (2 | 4 | 8);
        !          6771:        save_u16 (cputrace.opcode);
        !          6772:        for (i = 0; i < 16; i++)
        !          6773:                save_u32 (cputrace.regs[i]);
        !          6774:        save_u32 (cputrace.pc);
        !          6775:        save_u16 (cputrace.irc);
        !          6776:        save_u16 (cputrace.ir);
        !          6777:        save_u32 (cputrace.usp);
        !          6778:        save_u32 (cputrace.isp);
        !          6779:        save_u16 (cputrace.sr);
        !          6780:        save_u16 (cputrace.intmask);
        !          6781:        save_u16 ((cputrace.stopped ? 1 : 0) | (regs.stopped ? 2 : 0));
        !          6782:        save_u16 (cputrace.state);
        !          6783:        save_u32 (cputrace.cyclecounter);
        !          6784:        save_u32 (cputrace.cyclecounter_pre);
        !          6785:        save_u32 (cputrace.cyclecounter_post);
        !          6786:        save_u32 (cputrace.readcounter);
        !          6787:        save_u32 (cputrace.writecounter);
        !          6788:        save_u32 (cputrace.memoryoffset);
        !          6789:        write_log (_T("CPUT SAVE: PC=%08x C=%08X %08x %08x %08x %d %d %d\n"),
        !          6790:                cputrace.pc, cputrace.startcycles,
        !          6791:                cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
        !          6792:                cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset);
        !          6793:        for (i = 0; i < cputrace.memoryoffset; i++) {
        !          6794:                save_u32 (cputrace.ctm[i].addr);
        !          6795:                save_u32 (cputrace.ctm[i].data);
        !          6796:                save_u32 (cputrace.ctm[i].mode);
        !          6797:                write_log (_T("CPUT%d: %08x %08x %08x\n"), i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode);
        !          6798:        }
        !          6799:        save_u32 (cputrace.startcycles);
        !          6800: 
        !          6801:        if (currprefs.cpu_model == 68020) {
        !          6802:                for (i = 0; i < CACHELINES020; i++) {
        !          6803:                        save_u32 (cputrace.caches020[i].data);
        !          6804:                        save_u32 (cputrace.caches020[i].tag);
        !          6805:                        save_u8 (cputrace.caches020[i].valid ? 1 : 0);
        !          6806:                }
        !          6807:                save_u32 (cputrace.prefetch020addr);
        !          6808:                save_u32 (cputrace.cacheholdingaddr020);
        !          6809:                save_u32 (cputrace.cacheholdingdata020);
        !          6810:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6811:                        save_u16 (cputrace.prefetch020[i]);
        !          6812:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6813:                        save_u32 (cputrace.prefetch020[i]);
        !          6814:        }
        !          6815: 
        !          6816:        *len = dst - dstbak;
        !          6817:        cputrace.needendcycles = 1;
        !          6818:        return dstbak;
        !          6819: }
        !          6820: 
        !          6821: uae_u8 *restore_cpu_trace (uae_u8 *src)
        !          6822: {
        !          6823:        int i;
        !          6824: 
        !          6825:        cpu_tracer = 0;
        !          6826:        cputrace.state = 0;
        !          6827:        uae_u32 v = restore_u32 ();
        !          6828:        if (!(v & 2))
        !          6829:                return src;
        !          6830:        cputrace.opcode = restore_u16 ();
        !          6831:        for (i = 0; i < 16; i++)
        !          6832:                cputrace.regs[i] = restore_u32 ();
        !          6833:        cputrace.pc = restore_u32 ();
        !          6834:        cputrace.irc = restore_u16 ();
        !          6835:        cputrace.ir = restore_u16 ();
        !          6836:        cputrace.usp = restore_u32 ();
        !          6837:        cputrace.isp = restore_u32 ();
        !          6838:        cputrace.sr = restore_u16 ();
        !          6839:        cputrace.intmask = restore_u16 ();
        !          6840:        cputrace.stopped = restore_u16 ();
        !          6841:        cputrace.state = restore_u16 ();
        !          6842:        cputrace.cyclecounter = restore_u32 ();
        !          6843:        cputrace.cyclecounter_pre = restore_u32 ();
        !          6844:        cputrace.cyclecounter_post = restore_u32 ();
        !          6845:        cputrace.readcounter = restore_u32 ();
        !          6846:        cputrace.writecounter = restore_u32 ();
        !          6847:        cputrace.memoryoffset = restore_u32 ();
        !          6848:        for (i = 0; i < cputrace.memoryoffset; i++) {
        !          6849:                cputrace.ctm[i].addr = restore_u32 ();
        !          6850:                cputrace.ctm[i].data = restore_u32 ();
        !          6851:                cputrace.ctm[i].mode = restore_u32 ();
        !          6852:        }
        !          6853:        cputrace.startcycles = restore_u32 ();
        !          6854: 
        !          6855:        if (v & 4) {
        !          6856:                if (currprefs.cpu_model == 68020) {
        !          6857:                        for (i = 0; i < CACHELINES020; i++) {
        !          6858:                                cputrace.caches020[i].data = restore_u32 ();
        !          6859:                                cputrace.caches020[i].tag = restore_u32 ();
        !          6860:                                cputrace.caches020[i].valid = restore_u8 () != 0;
        !          6861:                        }
        !          6862:                        cputrace.prefetch020addr = restore_u32 ();
        !          6863:                        cputrace.cacheholdingaddr020 = restore_u32 ();
        !          6864:                        cputrace.cacheholdingdata020 = restore_u32 ();
        !          6865:                        for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6866:                                cputrace.prefetch020[i] = restore_u16 ();
        !          6867:                        if (v & 8) {
        !          6868:                                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          6869:                                        cputrace.prefetch020[i] = restore_u32 ();
        !          6870:                        }
        !          6871:                }
        !          6872:        }
        !          6873: 
        !          6874:        cputrace.needendcycles = 1;
        !          6875:        if (v && cputrace.state) {
        !          6876:                if (currprefs.cpu_model > 68000) {
        !          6877:                        if (v & 4)
        !          6878:                                cpu_tracer = -1;
        !          6879:                        // old format?
        !          6880:                        if ((v & (4 | 8)) != (4 | 8))
        !          6881:                                cpu_tracer = 0;
        !          6882:                } else {
        !          6883:                        cpu_tracer = -1;
        !          6884:                }
        !          6885:        }
        !          6886: 
        !          6887:        return src;
        !          6888: }
        !          6889: 
        !          6890: uae_u8 *restore_cpu_extra (uae_u8 *src)
        !          6891: {
        !          6892:        restore_u32 ();
        !          6893:        uae_u32 flags = restore_u32 ();
        !          6894: 
        !          6895:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
        !          6896:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
        !          6897:        currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
        !          6898:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
        !          6899:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
        !          6900:        //currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
        !          6901: 
        !          6902:        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
        !          6903:        if (flags & 4)
1.1.1.4   root     6904:                currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
1.1.1.7 ! root     6905:        if (flags & 16)
        !          6906:                currprefs.m68k_speed = changed_prefs.m68k_speed = (flags >> 24) * CYCLE_UNIT;
1.1.1.4   root     6907: 
                   6908:        currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
                   6909:        currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
                   6910: 
                   6911:        return src;
                   6912: }
                   6913: 
                   6914: uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
                   6915: {
                   6916:        uae_u8 *dstbak, *dst;
                   6917:        uae_u32 flags;
                   6918: 
                   6919:        if (dstptr)
                   6920:                dstbak = dst = dstptr;
                   6921:        else
                   6922:                dstbak = dst = xmalloc (uae_u8, 1000);
                   6923:        save_u32 (0); // version
                   6924:        flags = 0;
                   6925:        flags |= currprefs.cpu_cycle_exact ? 1 : 0;
                   6926:        flags |= currprefs.cpu_compatible ? 2 : 0;
                   6927:        flags |= currprefs.m68k_speed < 0 ? 4 : 0;
                   6928:        flags |= currprefs.cachesize > 0 ? 8 : 0;
1.1.1.7 ! root     6929:        flags |= currprefs.m68k_speed > 0 ? 16 : 0;
        !          6930:        if (currprefs.m68k_speed > 0)
        !          6931:                flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24;
1.1.1.4   root     6932:        save_u32 (flags);
                   6933:        save_u32 (currprefs.cpu_frequency);
                   6934:        save_u32 (currprefs.cpu_clock_multiplier);
                   6935:        save_u8 (currprefs.cpu060_revision);
                   6936:        save_u8 (currprefs.fpu_revision);
                   6937:        *len = dst - dstbak;
                   6938:        return dstbak;
                   6939: }
                   6940: 
                   6941: uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                   6942: {
                   6943:        uae_u8 *dstbak, *dst;
1.1.1.7 ! root     6944:        int model, i, j, khz;
1.1.1.4   root     6945: 
                   6946:        if (dstptr)
                   6947:                dstbak = dst = dstptr;
                   6948:        else
                   6949:                dstbak = dst = xmalloc (uae_u8, 1000);
                   6950:        model = currprefs.cpu_model;
                   6951:        save_u32 (model);                                       /* MODEL */
1.1.1.7 ! root     6952:        save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 |(currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
1.1.1.4   root     6953:        for (i = 0;i < 15; i++)
                   6954:                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
                   6955:        save_u32 (m68k_getpc ());                       /* PC */
                   6956:        save_u16 (regs.irc);                            /* prefetch */
                   6957:        save_u16 (regs.ir);                                     /* instruction prefetch */
                   6958:        MakeSR ();
                   6959:        save_u32 (!regs.s ? regs.regs[15] : regs.usp);  /* USP */
                   6960:        save_u32 (regs.s ? regs.regs[15] : regs.isp);   /* ISP */
                   6961:        save_u16 (regs.sr);                                                             /* SR/CCR */
                   6962:        save_u32 (regs.stopped ? CPUMODE_HALT : 0);             /* flags */
                   6963:        if (model >= 68010) {
                   6964:                save_u32 (regs.dfc);                    /* DFC */
                   6965:                save_u32 (regs.sfc);                    /* SFC */
                   6966:                save_u32 (regs.vbr);                    /* VBR */
                   6967:        }
                   6968:        if (model >= 68020) {
                   6969:                save_u32 (regs.caar);                   /* CAAR */
                   6970:                save_u32 (regs.cacr);                   /* CACR */
                   6971:                save_u32 (regs.msp);                    /* MSP */
                   6972:        }
                   6973:        if (model >= 68030) {
1.1.1.7 ! root     6974:                if (currprefs.mmu_model) {
        !          6975:                        save_u64 (crp_030);                             /* CRP */
        !          6976:                        save_u64 (srp_030);                             /* SRP */
        !          6977:                        save_u32 (tt0_030);                             /* TT0/AC0 */
        !          6978:                        save_u32 (tt1_030);                             /* TT1/AC1 */
        !          6979:                        save_u32 (tc_030);                              /* TCR */
        !          6980:                        save_u16 (mmusr_030);                   /* MMUSR/ACUSR */
        !          6981:                } else {
        !          6982:                        save_u64 (fake_crp_030);                /* CRP */
        !          6983:                        save_u64 (fake_srp_030);                /* SRP */
        !          6984:                        save_u32 (fake_tt0_030);                /* TT0/AC0 */
        !          6985:                        save_u32 (fake_tt1_030);                /* TT1/AC1 */
        !          6986:                        save_u32 (fake_tc_030);                 /* TCR */
        !          6987:                        save_u16 (fake_mmusr_030);              /* MMUSR/ACUSR */
        !          6988:                }
1.1.1.4   root     6989:        }
                   6990:        if (model >= 68040) {
                   6991:                save_u32 (regs.itt0);                   /* ITT0 */
                   6992:                save_u32 (regs.itt1);                   /* ITT1 */
                   6993:                save_u32 (regs.dtt0);                   /* DTT0 */
                   6994:                save_u32 (regs.dtt1);                   /* DTT1 */
                   6995:                save_u32 (regs.tcr);                    /* TCR */
                   6996:                save_u32 (regs.urp);                    /* URP */
                   6997:                save_u32 (regs.srp);                    /* SRP */
                   6998:        }
                   6999:        if (model >= 68060) {
                   7000:                save_u32 (regs.buscr);                  /* BUSCR */
                   7001:                save_u32 (regs.pcr);                    /* PCR */
                   7002:        }
                   7003:        khz = -1;
                   7004:        if (currprefs.m68k_speed == 0) {
                   7005:                khz = currprefs.ntscmode ? 715909 : 709379;
                   7006:                if (currprefs.cpu_model >= 68020)
                   7007:                        khz *= 2;
                   7008:        }
                   7009:        save_u32 (khz); // clock rate in KHz: -1 = fastest possible
                   7010:        save_u32 (0); // spare
1.1.1.7 ! root     7011:        if (model == 68020) {
        !          7012:                for (i = 0; i < CACHELINES020; i++) {
        !          7013:                        save_u32 (caches020[i].data);
        !          7014:                        save_u32 (caches020[i].tag);
        !          7015:                        save_u8 (caches020[i].valid ? 1 : 0);
        !          7016:                }
        !          7017:                save_u32 (regs.prefetch020addr);
        !          7018:                save_u32 (regs.cacheholdingaddr020);
        !          7019:                save_u32 (regs.cacheholdingdata020);
        !          7020:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          7021:                        save_u32 (regs.prefetch020[i]);
        !          7022:        } else if (model == 68030) {
        !          7023:                for (i = 0; i < CACHELINES030; i++) {
        !          7024:                        for (j = 0; j < 4; j++) {
        !          7025:                                save_u32 (icaches030[i].data[j]);
        !          7026:                                save_u8 (icaches030[i].valid[j] ? 1 : 0);
        !          7027:                        }
        !          7028:                        save_u32 (icaches030[i].tag);
        !          7029:                }
        !          7030:                for (i = 0; i < CACHELINES030; i++) {
        !          7031:                        for (j = 0; j < 4; j++) {
        !          7032:                                save_u32 (dcaches030[i].data[j]);
        !          7033:                                save_u8 (dcaches030[i].valid[j] ? 1 : 0);
        !          7034:                        }
        !          7035:                        save_u32 (dcaches030[i].tag);
        !          7036:                }
        !          7037:                save_u32 (regs.prefetch020addr);
        !          7038:                save_u32 (regs.cacheholdingaddr020);
        !          7039:                save_u32 (regs.cacheholdingdata020);
        !          7040:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          7041:                        save_u32 (regs.prefetch020[i]);
        !          7042:        } else if (model >= 68040) {
        !          7043:                for (i = 0; i < CACHESETS040; i++) {
        !          7044:                        for (j = 0; j < CACHELINES040; j++) {
        !          7045:                                save_u32(icaches040[i].data[j][0]);
        !          7046:                                save_u32(icaches040[i].data[j][1]);
        !          7047:                                save_u32(icaches040[i].data[j][2]);
        !          7048:                                save_u32(icaches040[i].data[j][3]);
        !          7049:                                save_u32(icaches040[i].tag[j]);
        !          7050:                                save_u16(icaches040[i].valid[j] ? 1 : 0);
        !          7051:                        }
        !          7052:                }
        !          7053:                save_u32(regs.prefetch020addr);
        !          7054:                save_u32(regs.cacheholdingaddr020);
        !          7055:                save_u32(regs.cacheholdingdata020);
        !          7056:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
        !          7057:                        save_u32(regs.prefetch020[i]);
        !          7058:        }
        !          7059:        if (currprefs.cpu_model >= 68020) {
        !          7060:                save_u32 (regs.ce020memcycles);
        !          7061:                save_u32 (0);
        !          7062:        }
        !          7063:        save_u32 (regs.chipset_latch_rw);
        !          7064:        save_u32 (regs.chipset_latch_read);
        !          7065:        save_u32 (regs.chipset_latch_write);
1.1.1.4   root     7066:        *len = dst - dstbak;
                   7067:        return dstbak;
                   7068: }
                   7069: 
                   7070: uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
                   7071: {
                   7072:        uae_u8 *dstbak, *dst;
                   7073:        int model;
                   7074: 
                   7075:        model = currprefs.mmu_model;
1.1.1.7 ! root     7076: #ifndef WINUAE_FOR_HATARI
        !          7077:         /* Under Hatari, we save all MMU variables, even if mmu_model==0 */
        !          7078:        if (model != 68030 && model != 68040 && model != 68060)
1.1.1.4   root     7079:                return NULL;
1.1.1.7 ! root     7080: #endif
1.1.1.4   root     7081:        if (dstptr)
                   7082:                dstbak = dst = dstptr;
                   7083:        else
                   7084:                dstbak = dst = xmalloc (uae_u8, 1000);
                   7085:        save_u32 (model);       /* MODEL */
1.1.1.7 ! root     7086:        save_u32 (0);           /* FLAGS */
1.1.1.4   root     7087:        *len = dst - dstbak;
                   7088:        return dstbak;
                   7089: }
                   7090: 
                   7091: uae_u8 *restore_mmu (uae_u8 *src)
                   7092: {
                   7093:        int flags, model;
                   7094: 
                   7095:        changed_prefs.mmu_model = model = restore_u32 ();
                   7096:        flags = restore_u32 ();
1.1.1.7 ! root     7097:        write_log (_T("MMU: %d\n"), model);
1.1.1.4   root     7098:        return src;
                   7099: }
                   7100: 
                   7101: #endif /* SAVESTATE */
                   7102: 
1.1.1.7 ! root     7103: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
1.1.1.4   root     7104: {
                   7105:        if (currprefs.cpu_model >= 68040)
                   7106:                addr &= ~1;
1.1.1.7 ! root     7107:        if (currprefs.cpu_model >= 68020) {
        !          7108:                if (pc == 0xffffffff)
        !          7109:                        last_addr_for_exception_3 = regs.instruction_pc;
        !          7110:                else
        !          7111:                        last_addr_for_exception_3 = pc;
        !          7112:        } else if (pc == 0xffffffff) {
        !          7113:                last_addr_for_exception_3 = m68k_getpc ();
        !          7114:                if (plus2)
        !          7115:                        last_addr_for_exception_3 += 2;
        !          7116:        } else {
        !          7117:                last_addr_for_exception_3 = pc;
        !          7118:        }
        !          7119:        last_fault_for_exception_3 = addr;
1.1.1.4   root     7120:        last_op_for_exception_3 = opcode;
                   7121:        last_writeaccess_for_exception_3 = writeaccess;
                   7122:        last_instructionaccess_for_exception_3 = instructionaccess;
1.1.1.7 ! root     7123:        last_notinstruction_for_exception_3 = notinstruction;
        !          7124:        Exception (3);
        !          7125: #if EXCEPTION3_DEBUGGER
        !          7126:        activate_debugger();
        !          7127: #endif
1.1.1.4   root     7128: }
                   7129: 
1.1.1.7 ! root     7130: void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
1.1.1.4   root     7131: {
1.1.1.7 ! root     7132:        exception3f (opcode, addr, true, false, true, 0xffffffff, false);
1.1.1.4   root     7133: }
1.1.1.7 ! root     7134: void exception3_read(uae_u32 opcode, uaecptr addr)
        !          7135: {
        !          7136:        exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
        !          7137: }
        !          7138: void exception3_write(uae_u32 opcode, uaecptr addr)
        !          7139: {
        !          7140:        exception3f (opcode, addr, true, 0, false, 0xffffffff, false);
        !          7141: }
        !          7142: void exception3i (uae_u32 opcode, uaecptr addr)
        !          7143: {
        !          7144:        exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
        !          7145: }
        !          7146: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
1.1.1.4   root     7147: {
1.1.1.7 ! root     7148:        exception3f (opcode, addr, w, i, false, pc, true);
1.1.1.4   root     7149: }
                   7150: 
1.1.1.7 ! root     7151: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
1.1.1.4   root     7152: {
1.1.1.7 ! root     7153:        if (currprefs.mmu_model) {
        !          7154:                if (currprefs.mmu_model == 68030) {
        !          7155:                        uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
        !          7156:                        mmu030_page_fault (addr, read, flags, fc);
        !          7157:                } else {
        !          7158:                        mmu_bus_error (addr, fc, read == false, size, false, 0, true);
        !          7159:                }
        !          7160:        } else {
        !          7161:                last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
        !          7162:                last_fault_for_exception_3 = addr;
        !          7163:                last_writeaccess_for_exception_3 = read == 0;
        !          7164:                last_instructionaccess_for_exception_3 = (fc & 1) == 0;
        !          7165:                last_op_for_exception_3 = regs.opcode;
        !          7166:                last_notinstruction_for_exception_3 = exception_in_exception != 0;
        !          7167:                THROW(2);
        !          7168:        }
1.1.1.4   root     7169: }
                   7170: 
                   7171: void cpureset (void)
                   7172: {
1.1.1.7 ! root     7173:     /* RESET hasn't increased PC yet, 1 word offset */
1.1.1.4   root     7174:        uaecptr pc;
1.1.1.7 ! root     7175: #ifndef WINUAE_FOR_HATARI
        !          7176:        uaecptr ksboot = 0xf80002 - 2;
1.1.1.4   root     7177:        uae_u16 ins;
1.1.1.7 ! root     7178: #endif
        !          7179:        addrbank *ab;
1.1.1.4   root     7180: 
1.1.1.7 ! root     7181:        m68k_reset_delay = currprefs.reset_delay;
        !          7182:        set_special(SPCFLAG_CHECK);
        !          7183: #ifndef WINUAE_FOR_HATARI
        !          7184:        send_internalevent(INTERNALEVENT_CPURESET);
        !          7185:        if ((currprefs.cpu_compatible || currprefs.cpu_cycle_exact) && currprefs.cpu_model <= 68020) {
        !          7186:                custom_reset (false, false);
1.1.1.4   root     7187:                return;
                   7188:        }
1.1.1.7 ! root     7189: #endif
        !          7190:        pc = m68k_getpc () + 2;
        !          7191:        ab = &get_mem_bank (pc);
        !          7192:        if (ab->check (pc, 2)) {
        !          7193:                write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name);
        !          7194: #ifndef WINUAE_FOR_HATARI
        !          7195:                ins = get_word (pc);
        !          7196:                custom_reset (false, false);
        !          7197:                // did memory disappear under us?
        !          7198:                if (ab == &get_mem_bank (pc))
        !          7199:                        return;
        !          7200:                // it did
        !          7201:                if ((ins & ~7) == 0x4ed0) {
        !          7202:                        int reg = ins & 7;
        !          7203:                        uae_u32 addr = m68k_areg (regs, reg);
        !          7204:                        if (addr < 0x80000)
        !          7205:                                addr += 0xf80000;
        !          7206:                        write_log (_T("reset/jmp (ax) combination at %08x emulated -> %x\n"), pc, addr);
        !          7207:                        m68k_setpc_normal (addr - 2);
1.1.1.4   root     7208:                        return;
                   7209:                }
1.1.1.7 ! root     7210: #else
        !          7211:                customreset ();         /* From hatari-glue.c */
        !          7212:                return;
        !          7213: #endif
        !          7214:        }
        !          7215:        // the best we can do, jump directly to ROM entrypoint
        !          7216:        // (which is probably what program wanted anyway)
        !          7217: #ifndef WINUAE_FOR_HATARI
        !          7218:        write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2);
        !          7219:        custom_reset (false, false);
        !          7220:        m68k_setpc_normal (ksboot);
        !          7221: #else
        !          7222:        write_log (_T("CPU Reset PC=%x (%s), invalid memory\n"), pc, ab->name);
        !          7223:        customreset ();                 /* From hatari-glue.c */
        !          7224: #endif
1.1.1.4   root     7225: }
                   7226: 
                   7227: 
                   7228: void m68k_setstopped (void)
                   7229: {
                   7230:        regs.stopped = 1;
                   7231:        /* A traced STOP instruction drops through immediately without
                   7232:        actually stopping.  */
                   7233:        if ((regs.spcflags & SPCFLAG_DOTRACE) == 0)
                   7234:                set_special (SPCFLAG_STOP);
                   7235:        else
                   7236:                m68k_resumestopped ();
                   7237: }
                   7238: 
                   7239: void m68k_resumestopped (void)
                   7240: {
                   7241:        if (!regs.stopped)
                   7242:                return;
                   7243:        regs.stopped = 0;
                   7244:        if (currprefs.cpu_cycle_exact) {
                   7245:                if (currprefs.cpu_model == 68000)
1.1.1.7 ! root     7246:                        x_do_cycles (6 * cpucycleunit);
1.1.1.4   root     7247:        }
1.1.1.7 ! root     7248:        fill_prefetch ();
1.1.1.4   root     7249:        unset_special (SPCFLAG_STOP);
                   7250: }
                   7251: 
                   7252: // this one is really simple and easy
1.1.1.7 ! root     7253: static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr))
1.1.1.4   root     7254: {
                   7255:        int index;
                   7256:        uae_u32 tag;
                   7257:        uae_u32 data;
                   7258:        struct cache020 *c;
                   7259: 
                   7260:        addr &= ~3;
1.1.1.7 ! root     7261:        if (regs.cacheholdingaddr020 == addr)
        !          7262:                return;
1.1.1.4   root     7263:        index = (addr >> 2) & (CACHELINES020 - 1);
                   7264:        tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
                   7265:        c = &caches020[index];
                   7266:        if (c->valid && c->tag == tag) {
                   7267:                // cache hit
1.1.1.7 ! root     7268:                regs.cacheholdingaddr020 = addr;
        !          7269:                regs.cacheholdingdata020 = c->data;
        !          7270: #ifdef WINUAE_FOR_HATARI
        !          7271:                CpuInstruction.I_Cache_hit++;
        !          7272: #endif
1.1.1.4   root     7273:                return;
                   7274:        }
                   7275:        // cache miss
1.1.1.7 ! root     7276:        // Prefetch apparently can be queued by bus controller
        !          7277:        // even if bus controller is currently processing
        !          7278:        // previous data access.
        !          7279:        // Other combinations are not possible.
        !          7280:        if (!regs.ce020memcycle_data)
        !          7281:                regs.ce020memcycles = 0;
        !          7282:        regs.ce020memcycle_data = false;
        !          7283:        unsigned long cycs = get_cycles ();
        !          7284:        data = fetch (addr);
        !          7285:        // add as available "free" internal CPU time.
        !          7286:        cycs = get_cycles () - cycs;
        !          7287:        regs.ce020memcycles += cycs;
1.1.1.4   root     7288:        if (!(regs.cacr & 2)) {
                   7289:                c->tag = tag;
                   7290:                c->valid = !!(regs.cacr & 1);
                   7291:                c->data = data;
                   7292:        }
1.1.1.7 ! root     7293:        regs.cacheholdingaddr020 = addr;
        !          7294:        regs.cacheholdingdata020 = data;
        !          7295: #ifdef WINUAE_FOR_HATARI
        !          7296:        CpuInstruction.I_Cache_miss++;
        !          7297: #endif
1.1.1.4   root     7298: }
                   7299: 
1.1.1.7 ! root     7300: #if MORE_ACCURATE_68020_PIPELINE
        !          7301: #define PIPELINE_DEBUG 0
        !          7302: #if PIPELINE_DEBUG
        !          7303: static uae_u16 pipeline_opcode;
        !          7304: #endif
        !          7305: static void pipeline_020(uae_u16 w, uaecptr pc)
1.1.1.4   root     7306: {
1.1.1.7 ! root     7307:        if (regs.pipeline_pos < 0)
        !          7308:                return;
        !          7309:        if (regs.pipeline_pos > 0) {
        !          7310:                // handle annoying 68020+ addressing modes
        !          7311:                if (regs.pipeline_pos == regs.pipeline_r8[0]) {
        !          7312:                        regs.pipeline_r8[0] = 0;
        !          7313:                        if (w & 0x100) {
        !          7314:                                int extra = 0;
        !          7315:                                if ((w & 0x30) == 0x20)
        !          7316:                                        extra += 2;
        !          7317:                                if ((w & 0x30) == 0x30)
        !          7318:                                        extra += 4;
        !          7319:                                if ((w & 0x03) == 0x02)
        !          7320:                                        extra += 2;
        !          7321:                                if ((w & 0x03) == 0x03)
        !          7322:                                        extra += 4;
        !          7323:                                regs.pipeline_pos += extra;
        !          7324:                        }
        !          7325:                        return;
        !          7326:                }
        !          7327:                if (regs.pipeline_pos == regs.pipeline_r8[1]) {
        !          7328:                        regs.pipeline_r8[1] = 0;
        !          7329:                        if (w & 0x100) {
        !          7330:                                int extra = 0;
        !          7331:                                if ((w & 0x30) == 0x20)
        !          7332:                                        extra += 2;
        !          7333:                                if ((w & 0x30) == 0x30)
        !          7334:                                        extra += 4;
        !          7335:                                if ((w & 0x03) == 0x02)
        !          7336:                                        extra += 2;
        !          7337:                                if ((w & 0x03) == 0x03)
        !          7338:                                        extra += 4;
        !          7339:                                regs.pipeline_pos += extra;
1.1.1.4   root     7340:                        }
1.1.1.7 ! root     7341:                        return;
        !          7342:                }
        !          7343:        }
        !          7344:        if (regs.pipeline_pos > 2) {
        !          7345:                regs.pipeline_pos -= 2;
        !          7346:                // If stop set, prefetches stop 1 word early.
        !          7347:                if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2)
        !          7348:                        regs.pipeline_stop = -1;
        !          7349:                return;
        !          7350:        }
        !          7351:        if (regs.pipeline_stop) {
        !          7352:                regs.pipeline_stop = -1;
        !          7353:                return;
        !          7354:        }
        !          7355: #if PIPELINE_DEBUG
        !          7356:        pipeline_opcode = w;
        !          7357: #endif
        !          7358:        regs.pipeline_r8[0] = cpudatatbl[w].disp020[0];
        !          7359:        regs.pipeline_r8[1] = cpudatatbl[w].disp020[1];
        !          7360:        regs.pipeline_pos = cpudatatbl[w].length;
        !          7361: #if PIPELINE_DEBUG
        !          7362:        if (!regs.pipeline_pos) {
        !          7363:                write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
        !          7364:        }
        !          7365: #endif
        !          7366:        int branch = cpudatatbl[w].branch;
        !          7367:        if (regs.pipeline_pos > 0 && branch) {
        !          7368:                // Short branches (Bcc.s) still do one more prefetch.
        !          7369: #if 0
        !          7370:                // RTS and other unconditional single opcode instruction stop immediately.
        !          7371:                if (branch == 2) {
        !          7372:                        // Immediate stop
        !          7373:                        regs.pipeline_stop = -1;
        !          7374:                } else {
        !          7375:                        // Stop 1 word early than normally
        !          7376:                        regs.pipeline_stop = 1;
1.1.1.4   root     7377:                }
1.1.1.7 ! root     7378: #else
        !          7379:                regs.pipeline_stop = 1;
        !          7380: #endif
1.1.1.4   root     7381:        }
                   7382: }
                   7383: 
1.1.1.7 ! root     7384: // Not exactly right, requires logic analyzer checks.
        !          7385: void continue_ce020_prefetch(void)
1.1.1.4   root     7386: {
1.1.1.7 ! root     7387:        fill_prefetch_020();
1.1.1.4   root     7388: }
1.1.1.7 ! root     7389: void continue_020_prefetch(void)
1.1.1.4   root     7390: {
1.1.1.7 ! root     7391:        fill_prefetch_020();
1.1.1.4   root     7392: }
1.1.1.7 ! root     7393: #endif
1.1.1.4   root     7394: 
1.1.1.7 ! root     7395: uae_u32 get_word_ce020_prefetch (int o)
1.1.1.4   root     7396: {
1.1.1.7 ! root     7397:        uae_u32 pc = m68k_getpc () + o;
        !          7398:        uae_u32 v;
1.1.1.4   root     7399: 
1.1.1.7 ! root     7400:        if (pc & 2) {
        !          7401:                v = regs.prefetch020[0] & 0xffff;
        !          7402: #if MORE_ACCURATE_68020_PIPELINE
        !          7403:                pipeline_020(regs.prefetch020[1], pc );
        !          7404: #endif
        !          7405:                regs.prefetch020[0] = regs.prefetch020[1];
        !          7406:                // branch instruction detected in pipeline: stop fetches until branch executed.
        !          7407:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
        !          7408:                        fill_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020);
        !          7409:                        regs.prefetch020[1] = regs.cacheholdingdata020;
1.1.1.4   root     7410:                }
1.1.1.7 ! root     7411:                regs.db = regs.prefetch020[0] >> 16;
        !          7412:        } else {
        !          7413:                v = regs.prefetch020[0] >> 16;
        !          7414: #if MORE_ACCURATE_68020_PIPELINE
        !          7415:                pipeline_020(regs.prefetch020[1] >> 16, pc);
1.1.1.4   root     7416: #endif
1.1.1.7 ! root     7417:                regs.db = regs.prefetch020[1] >> 16;
1.1.1.4   root     7418:        }
1.1.1.7 ! root     7419:        do_cycles_ce020_internal (2);
        !          7420:        return v;
1.1.1.4   root     7421: }
                   7422: 
1.1.1.7 ! root     7423: uae_u32 get_word_020_prefetch (int o)
1.1.1.4   root     7424: {
1.1.1.7 ! root     7425:        uae_u32 pc = m68k_getpc () + o;
        !          7426:        uae_u32 v;
1.1.1.4   root     7427: 
1.1.1.7 ! root     7428:        if (pc & 2) {
        !          7429:                v = regs.prefetch020[0] & 0xffff;
        !          7430: #if MORE_ACCURATE_68020_PIPELINE
        !          7431:                pipeline_020(regs.prefetch020[1], pc);
        !          7432: #endif
        !          7433:                regs.prefetch020[0] = regs.prefetch020[1];
        !          7434:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
        !          7435:                        fill_icache020 (pc + 2 + 4, get_longi);
        !          7436:                        regs.prefetch020[1] = regs.cacheholdingdata020;
        !          7437:                }
        !          7438:                regs.db = regs.prefetch020[0] >> 16;
        !          7439:        } else {
        !          7440:                v = regs.prefetch020[0] >> 16;
        !          7441: #if MORE_ACCURATE_68020_PIPELINE
        !          7442:                pipeline_020(regs.prefetch020[1] >> 16, pc);
        !          7443: #endif
        !          7444:                regs.db = regs.prefetch020[0];
        !          7445:        }
        !          7446: //if ( ( v & 0xffff ) != ( get_word(pc) & 0xffff ) )
        !          7447: //  fprintf ( stderr , "prefetch mismatch pc=%x prefetch=%x != mem=%x, i-cache error ?\n" , pc , v&0xffff , get_word(pc)&0xffff );
        !          7448:        return v;
        !          7449: }
1.1.1.4   root     7450: 
1.1.1.7 ! root     7451: // these are also used by 68030.
1.1.1.4   root     7452: 
1.1.1.7 ! root     7453: #define RESET_CE020_CYCLES \
        !          7454:        regs.ce020memcycles = 0; \
        !          7455:        regs.ce020memcycle_data = true;
        !          7456: #define STORE_CE020_CYCLES \
        !          7457:        unsigned long cycs = get_cycles ()
        !          7458: #define ADD_CE020_CYCLES \
        !          7459:        regs.ce020memcycles += get_cycles () - cycs
1.1.1.4   root     7460: 
1.1.1.7 ! root     7461: uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
        !          7462: {
        !          7463:        uae_u32 v;
        !          7464:        RESET_CE020_CYCLES;
        !          7465:        STORE_CE020_CYCLES;
        !          7466:        switch (ce_banktype[addr >> 16])
        !          7467:        {
        !          7468:        case CE_MEMBANK_CHIP16:
        !          7469:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          7470:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          7471:                break;
        !          7472:        case CE_MEMBANK_CHIP32:
        !          7473:                if ((addr & 3) != 0) {
        !          7474:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          7475:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          7476:                } else {
        !          7477:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
        !          7478:                }
        !          7479:                break;
        !          7480:        case CE_MEMBANK_FAST32:
        !          7481:                v = get_long (addr);
        !          7482:                if ((addr & 3) != 0)
        !          7483:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7484:                else
        !          7485:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7486:                break;
        !          7487:        case CE_MEMBANK_FAST16:
        !          7488:                v = get_long (addr);
        !          7489:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7490:                break;
        !          7491:        default:
        !          7492:                v = get_long (addr);
        !          7493:                break;
        !          7494:        }
        !          7495:        ADD_CE020_CYCLES;
        !          7496:        return v;
        !          7497: }
        !          7498: 
        !          7499: uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
        !          7500: {
        !          7501:        uae_u32 v;
        !          7502:        switch (ce_banktype[addr >> 16])
        !          7503:        {
        !          7504:        case CE_MEMBANK_CHIP16:
        !          7505:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          7506:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          7507:                break;
        !          7508:        case CE_MEMBANK_CHIP32:
        !          7509:                if ((addr & 3) != 0) {
        !          7510:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          7511:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          7512:                } else {
        !          7513:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
        !          7514:                }
        !          7515:                break;
        !          7516:        case CE_MEMBANK_FAST32:
        !          7517:                v = get_longi (addr);
        !          7518:                if ((addr & 3) != 0)
        !          7519:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7520:                else
        !          7521:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7522:                break;
        !          7523:        case CE_MEMBANK_FAST16:
        !          7524:                v = get_longi (addr);
        !          7525:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7526:                break;
        !          7527:        default:
        !          7528:                v = get_longi (addr);
        !          7529:                break;
        !          7530:        }
        !          7531:        return v;
        !          7532: }
        !          7533: 
        !          7534: uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
        !          7535: {
        !          7536:        uae_u32 v;
        !          7537:        RESET_CE020_CYCLES;
        !          7538:        STORE_CE020_CYCLES;
        !          7539:        switch (ce_banktype[addr >> 16])
        !          7540:        {
        !          7541:        case CE_MEMBANK_CHIP16:
        !          7542:        case CE_MEMBANK_CHIP32:
        !          7543:                if ((addr & 3) == 3) {
        !          7544:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
        !          7545:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
        !          7546:                } else {
        !          7547:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
        !          7548:                }
        !          7549:                break;
        !          7550:        case CE_MEMBANK_FAST16:
        !          7551:        case CE_MEMBANK_FAST32:
        !          7552:                v = get_word (addr);
        !          7553:                if ((addr & 3) == 3)
        !          7554:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7555:                else
        !          7556:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7557:                 break;
        !          7558:        default:
        !          7559:                 v = get_word (addr);
        !          7560:                break;
        !          7561:        }
        !          7562:        ADD_CE020_CYCLES;
        !          7563:        return v;
        !          7564: }
        !          7565: 
        !          7566: uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
        !          7567: {
        !          7568:        uae_u32 v;
        !          7569:        RESET_CE020_CYCLES;
        !          7570:        STORE_CE020_CYCLES;
        !          7571:        switch (ce_banktype[addr >> 16])
        !          7572:        {
        !          7573:        case CE_MEMBANK_CHIP16:
        !          7574:        case CE_MEMBANK_CHIP32:
        !          7575:                v = wait_cpu_cycle_read_ce020 (addr, 0);
        !          7576:                break;
        !          7577:        case CE_MEMBANK_FAST16:
        !          7578:        case CE_MEMBANK_FAST32:
        !          7579:                v = get_byte (addr);
        !          7580:                do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7581:                break;
        !          7582:        default:
        !          7583:                v = get_byte (addr);
        !          7584:                break;
        !          7585:        }
        !          7586:        ADD_CE020_CYCLES;
        !          7587:        return v;
        !          7588: }
        !          7589: 
        !          7590: void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
        !          7591: {
        !          7592:        RESET_CE020_CYCLES;
        !          7593:        STORE_CE020_CYCLES;
        !          7594:        switch (ce_banktype[addr >> 16])
        !          7595:        {
        !          7596:        case CE_MEMBANK_CHIP16:
        !          7597:        case CE_MEMBANK_CHIP32:
        !          7598:                wait_cpu_cycle_write_ce020 (addr, 0, v);
        !          7599:                break;
        !          7600:        case CE_MEMBANK_FAST16:
        !          7601:        case CE_MEMBANK_FAST32:
        !          7602:                put_byte (addr, v);
        !          7603:                do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7604:                break;
        !          7605:        default:
        !          7606:                put_byte (addr, v);
        !          7607:        break;
1.1.1.4   root     7608:        }
1.1.1.7 ! root     7609:        ADD_CE020_CYCLES;
        !          7610: }
        !          7611: 
        !          7612: void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
        !          7613: {
        !          7614:        RESET_CE020_CYCLES;
        !          7615:        STORE_CE020_CYCLES;
        !          7616:        switch (ce_banktype[addr >> 16])
        !          7617:        {
        !          7618:        case CE_MEMBANK_CHIP16:
        !          7619:        case CE_MEMBANK_CHIP32:
        !          7620:                if ((addr & 3) == 3) {
        !          7621:                        wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
        !          7622:                        wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
        !          7623:                } else {
        !          7624:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
        !          7625:                }
        !          7626:                break;
        !          7627:        case CE_MEMBANK_FAST16:
        !          7628:        case CE_MEMBANK_FAST32:
        !          7629:                put_word (addr, v);
        !          7630:                if ((addr & 3) == 3)
        !          7631:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7632:                else
        !          7633:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7634:                break;
        !          7635:        default:
        !          7636:                put_word (addr, v);
        !          7637:        break;
        !          7638:        }
        !          7639:        ADD_CE020_CYCLES;
        !          7640: }
        !          7641: 
        !          7642: void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
        !          7643: {
        !          7644:        RESET_CE020_CYCLES;
        !          7645:        STORE_CE020_CYCLES;
        !          7646:        switch (ce_banktype[addr >> 16])
        !          7647:        {
        !          7648:        case CE_MEMBANK_CHIP16:
        !          7649:                wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
        !          7650:                wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
        !          7651:                break;
        !          7652:        case CE_MEMBANK_CHIP32:
        !          7653:                if ((addr & 3) == 3) {
        !          7654:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
        !          7655:                        wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
        !          7656:                } else {
        !          7657:                        wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
        !          7658:                }
        !          7659:                break;
        !          7660:        case CE_MEMBANK_FAST32:
        !          7661:                put_long (addr, v);
        !          7662:                if ((addr & 3) != 0)
        !          7663:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7664:                else
        !          7665:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          7666:                break;
        !          7667:        case CE_MEMBANK_FAST16:
        !          7668:                put_long (addr, v);
        !          7669:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          7670:                break;
        !          7671:        default:
        !          7672:                put_long (addr, v);
        !          7673:                break;
        !          7674:        }
        !          7675:        ADD_CE020_CYCLES;
        !          7676: }
        !          7677: 
        !          7678: 
        !          7679: // 68030 caches aren't so simple as 68020 cache..
        !          7680: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
        !          7681: {
        !          7682:        int index, lws;
        !          7683:        uae_u32 tag;
        !          7684:        struct cache030 *c;
        !          7685: 
        !          7686:        addr &= ~3;
        !          7687:        index = (addr >> 4) & (CACHELINES030 - 1);
        !          7688:        tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
        !          7689:        lws = (addr >> 2) & 3;
        !          7690:        c = &cp[index];
        !          7691:        *tagp = tag;
        !          7692:        *lwsp = lws;
        !          7693:        return c;
        !          7694: }
        !          7695: 
        !          7696: STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
        !          7697: {
        !          7698:        if (c->tag != tag)
        !          7699:                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
        !          7700:        c->tag = tag;
        !          7701:        c->valid[lws] = true;
        !          7702:        c->data[lws] = val;
        !          7703: }
        !          7704: 
        !          7705: static void fill_icache030 (uae_u32 addr)
        !          7706: {
        !          7707:        int lws;
        !          7708:        uae_u32 tag;
        !          7709:        uae_u32 data;
        !          7710:        struct cache030 *c;
        !          7711: //fprintf ( stderr , "fill ica %x\n" , addr );
        !          7712: 
        !          7713:        addr &= ~3;
        !          7714:        if (regs.cacheholdingaddr020 == addr)
        !          7715:                return;
        !          7716:        c = getcache030 (icaches030, addr, &tag, &lws);
        !          7717:        if (c->valid[lws] && c->tag == tag) {
        !          7718:                // cache hit
        !          7719:                regs.cacheholdingaddr020 = addr;
        !          7720:                regs.cacheholdingdata020 = c->data[lws];
        !          7721: //fprintf ( stderr , "fill ica %x -> hit %x\n" , addr , regs.cacheholdingdata020 );
        !          7722: #ifdef WINUAE_FOR_HATARI
        !          7723:                CpuInstruction.I_Cache_hit++;
1.1.1.4   root     7724: #endif
1.1.1.7 ! root     7725:                return;
        !          7726:        }
        !          7727: 
        !          7728:        // cache miss
        !          7729:        if (currprefs.cpu_cycle_exact) {
        !          7730:                if (!regs.ce020memcycle_data)
        !          7731:                        regs.ce020memcycles = 0;
        !          7732:                regs.ce020memcycle_data = false;
        !          7733:                unsigned long cycs = get_cycles ();
        !          7734:                data = mem_access_delay_longi_read_ce020 (addr);
        !          7735:                // add as available "free" internal CPU time.
        !          7736:                cycs = get_cycles () - cycs;
        !          7737:                regs.ce020memcycles += cycs;
        !          7738:        } else {
        !          7739:                data = get_longi (addr);
        !          7740:        }
        !          7741:        if ((regs.cacr & 3) == 1) { // not frozen and enabled
        !          7742: //fprintf ( stderr , "fill ica %x -> update %x\n" , addr , data );
        !          7743:                update_cache030 (c, data, tag, lws);
        !          7744:        }
        !          7745:        if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
        !          7746: //fprintf ( stderr , "fill ica %x -> burst %x\n" , addr , data );
        !          7747:                // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
        !          7748:                c->data[1] = get_longi (addr + 4);
        !          7749:                c->data[2] = get_longi (addr + 8);
        !          7750:                c->data[3] = get_longi (addr + 12);
        !          7751:                if (currprefs.cpu_cycle_exact)
        !          7752:                        do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
        !          7753:                c->valid[1] = c->valid[2] = c->valid[3] = true;
        !          7754:        }
        !          7755:        regs.cacheholdingaddr020 = addr;
        !          7756:        regs.cacheholdingdata020 = data;
        !          7757: //fprintf ( stderr , "fill ica %x -> miss %x\n" , addr , regs.cacheholdingdata020 );
        !          7758: #ifdef WINUAE_FOR_HATARI
        !          7759:        CpuInstruction.I_Cache_miss++;
        !          7760: #endif
        !          7761: }
        !          7762: 
        !          7763: STATIC_INLINE bool cancache030 (uaecptr addr)
        !          7764: {
        !          7765: //return false;
        !          7766:        return ce_cachable[addr >> 16] != 0;
        !          7767: }
        !          7768: 
        !          7769: // and finally the worst part, 68030 data cache..
        !          7770: static void write_dcache030x (uaecptr addr, uae_u32 val, int size)
        !          7771: {
        !          7772:        struct cache030 *c1, *c2;
        !          7773:        int lws1, lws2;
        !          7774:        uae_u32 tag1, tag2;
        !          7775:        int aligned = addr & 3;
        !          7776:        int wa = regs.cacr & 0x2000;
        !          7777:        int hit;
        !          7778: 
        !          7779:        if (!(regs.cacr & 0x100)) // data cache disabled?
        !          7780:                return;
        !          7781:        if (!cancache030 (addr))
        !          7782:                return;
        !          7783: 
        !          7784:        c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
1.1.1.4   root     7785: 
                   7786:        // easy one
1.1.1.7 ! root     7787:        if (size == 2 && aligned == 0 && wa == 1) {
1.1.1.4   root     7788:                update_cache030 (c1, val, tag1, lws1);
1.1.1.7 ! root     7789: //fprintf ( stderr , "write cache1 %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x ctag %x data %x\n", addr, val, size, tag1, lws1, tag2, lws2, c1->tag , c1->data[lws1] );
1.1.1.4   root     7790:                return;
                   7791:        }
1.1.1.7 ! root     7792: 
        !          7793:        hit = ( c1->tag == tag1 && c1->valid[lws1] );
        !          7794:        if ( hit || wa ) {
        !          7795:                if (size == 2) {
        !          7796:                        if (hit) {
        !          7797:                                c1->data[lws1] &= ~(0xffffffff >> (aligned * 8));
        !          7798:                                c1->data[lws1] |= val >> (aligned * 8);
        !          7799:                        }
        !          7800:                        else
        !          7801:                                c1->valid[lws1] = false;
        !          7802:                } else if (size == 1) {
        !          7803:                        if (hit) {
        !          7804:                                c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8));
        !          7805:                                c1->data[lws1] |= (val<<16) >> (aligned * 8);
        !          7806:                        }
        !          7807:                        else
        !          7808:                                c1->valid[lws1] = false;
        !          7809:                } else if (size == 0) {
        !          7810:                        if (hit) {
        !          7811:                                c1->data[lws1] &= ~(0xff000000 >> (aligned * 8));
        !          7812:                                c1->data[lws1] |= (val<<24) >> (aligned * 8);
        !          7813:                        }
        !          7814:                        else
        !          7815:                                c1->valid[lws1] = false;
        !          7816:                }
        !          7817:        }
        !          7818: 
        !          7819:        // do we need to update a 2nd cache entry ?
        !          7820:        if ( (size == 0) || (size == 1 && aligned <= 2) || (size == 2 && aligned == 0) )
        !          7821:                return;
        !          7822: 
1.1.1.4   root     7823:        c2 = getcache030 (dcaches030, addr + 4, &tag2, &lws2);
1.1.1.7 ! root     7824: //fprintf ( stderr , "write cache2 %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x ctag %x data %x\n", addr, val, size, tag1, lws1, tag2, lws2, c2->tag , c2->data[lws2] );
        !          7825:        hit = ( c2->tag == tag2 && c2->valid[lws2] );
        !          7826:        if ( hit || wa ) {
        !          7827:                if (size == 2) {
        !          7828:                        if (hit) {
        !          7829:                                c2->data[lws2] &= 0xffffffff >> (aligned * 8);
        !          7830:                                c2->data[lws2] |= val << ((4 - aligned) * 8);
        !          7831:                        }
        !          7832:                        else
        !          7833:                                c2->valid[lws2] = false;
        !          7834:                } else if (size == 1) {
        !          7835:                        if (hit) {
        !          7836:                                c2->data[lws2] &= 0x00ffffff;
        !          7837:                                c2->data[lws2] |= val << 24;
        !          7838:                        }
        !          7839:                        else
        !          7840:                                c2->valid[lws2] = false;
1.1.1.4   root     7841:                }
                   7842:        }
                   7843: }
                   7844: 
1.1.1.7 ! root     7845: void write_dcache030(uaecptr addr, uae_u32 v, int size)
        !          7846: {
        !          7847: //fprintf ( stderr , "write dcache %x %x %d\n" , addr , v , size );
        !          7848:        write_dcache030x(addr, v, size);
        !          7849:        if (currprefs.cpu_cycle_exact) {
        !          7850:                if (size == 2)
        !          7851:                        mem_access_delay_long_write_ce020(addr, v);
        !          7852:                else if (size == 1)
        !          7853:                        mem_access_delay_word_write_ce020(addr, v);
        !          7854:                else
        !          7855:                        mem_access_delay_byte_write_ce020(addr, v);
        !          7856:        } else {
        !          7857:                if (size == 2)
        !          7858:                        put_long(addr, v);
        !          7859:                else if (size == 1)
        !          7860:                        put_word(addr, v);
        !          7861:                else
        !          7862:                        put_byte(addr, v);
        !          7863:        }
        !          7864: }
        !          7865: 
        !          7866: // [HATARI] Define next line to check for 68030 data cache mismatch after every write
        !          7867: //#define WINUAE_FOR_HATARI_DEBUG_CACHE
        !          7868: #ifdef WINUAE_FOR_HATARI_DEBUG_CACHE
        !          7869: uae_u32 read_dcache030_0 (uaecptr addr, int size);
        !          7870: uae_u32 read_dcache030 (uaecptr addr, int size)
        !          7871: {
        !          7872:   uae_u32 v;
        !          7873: 
        !          7874:   v = read_dcache030_0 ( addr , size );
        !          7875:   if (!(regs.cacr & 0x100) || !cancache030 (addr))
        !          7876:     return v;
        !          7877:   if ( ( ( size==2 ) && ( v != get_long ( addr ) ) )
        !          7878:     || ( ( size==1 ) && ( (v&0xffff) != (get_word ( addr ) & 0xffff) ) )
        !          7879:     || ( ( size==0 ) && ( (v&0xff) != (get_byte ( addr ) & 0xff ) ) ) )
        !          7880:     fprintf ( stderr , "d-cache mismatch pc=%x addr=%x size=%d cache=%x != mem=%x, d-cache error ?\n" , m68k_getpc(), addr, size, v , get_long(addr) );
        !          7881:   return v;
        !          7882: }
        !          7883: uae_u32 read_dcache030_0 (uaecptr addr, int size)
        !          7884: #else
1.1.1.4   root     7885: uae_u32 read_dcache030 (uaecptr addr, int size)
1.1.1.7 ! root     7886: #endif
1.1.1.4   root     7887: {
                   7888:        struct cache030 *c1, *c2;
                   7889:        int lws1, lws2;
                   7890:        uae_u32 tag1, tag2;
                   7891:        int aligned = addr & 3;
                   7892:        uae_u32 v1, v2;
                   7893: 
1.1.1.7 ! root     7894:        if (!(regs.cacr & 0x100) || !cancache030 (addr)) { // data cache disabled?
        !          7895:                if (currprefs.cpu_cycle_exact) {
        !          7896:                        if (size == 2)
        !          7897:                                return mem_access_delay_long_read_ce020 (addr);
        !          7898:                        else if (size == 1)
        !          7899:                                return mem_access_delay_word_read_ce020 (addr);
        !          7900:                        else
        !          7901:                                return mem_access_delay_byte_read_ce020 (addr);
        !          7902:                } else {
        !          7903:                        if (size == 2)
        !          7904:                                return get_long (addr);
        !          7905:                        else if (size == 1)
        !          7906:                                return get_word (addr);
        !          7907:                        else
        !          7908:                                return get_byte (addr);
        !          7909:                }
1.1.1.4   root     7910:        }
                   7911:        c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
                   7912:        addr &= ~3;
                   7913:        if (!c1->valid[lws1] || c1->tag != tag1) {
1.1.1.7 ! root     7914:                v1 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
1.1.1.4   root     7915:                update_cache030 (c1, v1, tag1, lws1);
1.1.1.7 ! root     7916: //fprintf ( stderr , "read cache %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x ref %x\n", addr, v1, size, tag1, lws1, tag2, lws2 , get_long (0x1f81ec) );
        !          7917: #ifdef WINUAE_FOR_HATARI
        !          7918:                CpuInstruction.D_Cache_miss++;
        !          7919: #endif
1.1.1.4   root     7920:        } else {
                   7921:                v1 = c1->data[lws1];
1.1.1.7 ! root     7922: #ifndef WINUAE_FOR_HATARI
        !          7923:                if (uae_boot_rom_type > 0) {
        !          7924:                        // this check and fix is needed for UAE filesystem handler because it runs in host side and in
        !          7925:                        // separate thread. No way to access via cache without locking that would cause major slowdown
        !          7926:                        // and unneeded complexity
        !          7927:                        uae_u32 tv = get_long(addr);
        !          7928:                        if (tv != v1) {
        !          7929:                                write_log(_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
        !          7930:                                        size, aligned, addr, tv, v1, tag1, lws1, M68K_GETPC);
        !          7931:                                v1 = tv;
        !          7932:                        }
1.1.1.4   root     7933:                }
1.1.1.7 ! root     7934: #else
        !          7935:                CpuInstruction.D_Cache_hit++;
        !          7936: #endif
1.1.1.4   root     7937:        }
1.1.1.7 ! root     7938: 
1.1.1.4   root     7939:        // only one long fetch needed?
                   7940:        if (size == 0) {
                   7941:                v1 >>= (3 - aligned) * 8;
                   7942:                return v1;
                   7943:        } else if (size == 1 && aligned <= 2) {
                   7944:                v1 >>= (2 - aligned) * 8;
                   7945:                return v1;
                   7946:        } else if (size == 2 && aligned == 0) {
1.1.1.7 ! root     7947:                if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
        !          7948:                        // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
        !          7949:                        c1->data[1] = get_long (addr + 4);
        !          7950:                        c1->data[2] = get_long (addr + 8);
        !          7951:                        c1->data[3] = get_long (addr + 12);
        !          7952:                        do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c1->data[3]);
        !          7953:                        c1->valid[1] = c1->valid[2] = c1->valid[3] = true;
        !          7954:                }
1.1.1.4   root     7955:                return v1;
                   7956:        }
1.1.1.7 ! root     7957:        // no, need another one
1.1.1.4   root     7958:        addr += 4;
                   7959:        c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
                   7960:        if (!c2->valid[lws2] || c2->tag != tag2) {
1.1.1.7 ! root     7961:                v2 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
1.1.1.4   root     7962:                update_cache030 (c2, v2, tag2, lws2);
1.1.1.7 ! root     7963: //fprintf ( stderr , "read cache %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x\n", addr, v1, size, tag1, lws1, tag2, lws2 );
        !          7964: #ifdef WINUAE_FOR_HATARI
        !          7965:                CpuInstruction.D_Cache_miss++;
        !          7966: #endif
1.1.1.4   root     7967:        } else {
                   7968:                v2 = c2->data[lws2];
1.1.1.7 ! root     7969: #ifndef WINUAE_FOR_HATARI
        !          7970:                if (uae_boot_rom_type > 0) {
        !          7971:                        uae_u32 tv = get_long(addr);
        !          7972:                        if (tv != v2) {
        !          7973:                                write_log (_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
        !          7974:                                        size, aligned, addr, get_long (addr), v2, tag2, lws2, M68K_GETPC);
        !          7975:                                v2 = tv;
        !          7976:                        }
1.1.1.4   root     7977:                }
1.1.1.7 ! root     7978: #else
        !          7979:                CpuInstruction.D_Cache_hit++;
        !          7980: #endif
        !          7981:        } 
        !          7982: 
1.1.1.4   root     7983:        if (size == 1 && aligned == 3)
                   7984:                return (v1 << 8) | (v2 >> 24);
                   7985:        else if (size == 2 && aligned == 1)
                   7986:                return (v1 << 8) | (v2 >> 24);
                   7987:        else if (size == 2 && aligned == 2)
                   7988:                return (v1 << 16) | (v2 >> 16);
                   7989:        else if (size == 2 && aligned == 3)
                   7990:                return (v1 << 24) | (v2 >> 8);
                   7991: 
1.1.1.7 ! root     7992:        write_log (_T("dcache030 weirdness!?\n"));
1.1.1.4   root     7993:        return 0;
                   7994: }
                   7995: 
                   7996: uae_u32 get_word_ce030_prefetch (int o)
                   7997: {
                   7998:        uae_u32 pc = m68k_getpc () + o;
1.1.1.7 ! root     7999:        uae_u32 v;
1.1.1.4   root     8000: 
1.1.1.7 ! root     8001:        if (pc & 2) {
        !          8002:                v = regs.prefetch020[0] & 0xffff;
        !          8003: #if MORE_ACCURATE_68020_PIPELINE
        !          8004:                pipeline_020(regs.prefetch020[1], pc);
        !          8005: #endif
        !          8006:                regs.prefetch020[0] = regs.prefetch020[1];
        !          8007:                // branch instruction detected in pipeline: stop fetches until branch executed.
        !          8008:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
        !          8009:                        fill_icache030 (pc + 2 + 4);
        !          8010:                        regs.prefetch020[1] = regs.cacheholdingdata020;
        !          8011:                }
        !          8012:        } else {
        !          8013:                v = regs.prefetch020[0] >> 16;
        !          8014: #if MORE_ACCURATE_68020_PIPELINE
        !          8015:                pipeline_020(regs.prefetch020[1] >> 16, pc);
        !          8016: #endif
        !          8017:        }
        !          8018:        do_cycles_ce020_internal (2);
        !          8019:        return v;
        !          8020: }
        !          8021: 
        !          8022: uae_u32 get_word_030_prefetch(int o)
        !          8023: {
        !          8024:        uae_u32 pc = m68k_getpc() + o;
        !          8025:        uae_u32 v;
        !          8026: 
        !          8027:        if (pc & 2) {
        !          8028:                v = regs.prefetch020[0] & 0xffff;
        !          8029: #if MORE_ACCURATE_68020_PIPELINE
        !          8030:                pipeline_020(regs.prefetch020[1], pc);
        !          8031: #endif
        !          8032:                regs.prefetch020[0] = regs.prefetch020[1];
        !          8033:                // branch instruction detected in pipeline: stop fetches until branch executed.
        !          8034:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
        !          8035:                        fill_icache030(pc + 2 + 4);
        !          8036:                        regs.prefetch020[1] = regs.cacheholdingdata020;
        !          8037:                }
        !          8038:        } else {
        !          8039:                v = regs.prefetch020[0] >> 16;
        !          8040: #if MORE_ACCURATE_68020_PIPELINE
        !          8041:                pipeline_020(regs.prefetch020[1] >> 16, pc);
        !          8042: #endif
        !          8043:        }
        !          8044:        return v;
        !          8045: }
        !          8046: 
        !          8047: uae_u32 get_word_icache030(uaecptr addr)
        !          8048: {
        !          8049:        fill_icache030(addr);
        !          8050:        return regs.cacheholdingdata020 >> ((addr & 2) ? 0 : 16);
        !          8051: }
        !          8052: uae_u32 get_long_icache030(uaecptr addr)
        !          8053: {
        !          8054:        uae_u32 v;
        !          8055:        fill_icache030(addr);
        !          8056:        if ((addr & 2) == 0)
        !          8057:                return regs.cacheholdingdata020;
        !          8058:        v = regs.cacheholdingdata020 << 16;
        !          8059:        fill_icache030(addr + 4);
        !          8060:        v |= regs.cacheholdingdata020 >> 16;
        !          8061:        return v;
        !          8062: }
        !          8063: 
        !          8064: uae_u32 fill_icache040(uae_u32 addr)
        !          8065: {
        !          8066:        int index, i, lws;
        !          8067:        uae_u32 tag;
        !          8068:        struct cache040 *c;
        !          8069:        int line;
        !          8070: 
        !          8071:        if (!(regs.cacr & 0x8000)) {
        !          8072:                uae_u32 addr2 = addr & ~15;
        !          8073:                lws = (addr >> 2) & 3;
        !          8074:                addr &= ~3;
        !          8075:                if (regs.prefetch020addr == addr2)
        !          8076:                        return regs.prefetch020[lws];
        !          8077:                regs.prefetch020addr = addr2;
        !          8078:                if (currprefs.cpu_cycle_exact) {
        !          8079:                        regs.prefetch020[0] = mem_access_delay_longi_read_ce020(addr2 +  0);
        !          8080:                        regs.prefetch020[1] = mem_access_delay_longi_read_ce020(addr2 +  4);
        !          8081:                        regs.prefetch020[2] = mem_access_delay_longi_read_ce020(addr2 +  8);
        !          8082:                        regs.prefetch020[3] = mem_access_delay_longi_read_ce020(addr2 + 12);
        !          8083:                } else {
        !          8084:                        regs.prefetch020[0] = get_longi(addr2 +  0);
        !          8085:                        regs.prefetch020[1] = get_longi(addr2 +  4);
        !          8086:                        regs.prefetch020[2] = get_longi(addr2 +  8);
        !          8087:                        regs.prefetch020[3] = get_longi(addr2 + 12);
        !          8088:                        x_do_cycles(4 * cpucycleunit);
        !          8089:                }
        !          8090:                return regs.prefetch020[lws];
        !          8091:        }
        !          8092: 
        !          8093:        index = (addr >> 4) & (CACHESETS040 - 1);
        !          8094:        tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
        !          8095:        lws = (addr >> 2) & 3;
        !          8096:        addr &= ~15;
        !          8097:        c = &icaches040[index];
        !          8098:        for (i = 0; i < CACHELINES040; i++) {
        !          8099:                if (c->valid[i] && c->tag[i] == tag) {
        !          8100:                        // cache hit
        !          8101:                        icachelinecnt++;
        !          8102:                        x_do_cycles(1 * cpucycleunit);
        !          8103: #ifdef WINUAE_FOR_HATARI
        !          8104:                        CpuInstruction.I_Cache_hit++;
        !          8105: #endif
        !          8106:                        return c->data[i][lws];
        !          8107:                }
        !          8108:        }
        !          8109:        // cache miss
        !          8110:        if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
        !          8111:                line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
        !          8112:        }
        !          8113:        else {
        !          8114:                for (line = 0; line < CACHELINES040; line++) {
        !          8115:                        if (c->valid[line] == false)
        !          8116:                                break;
        !          8117:                }
        !          8118:        }
        !          8119:        c->tag[line] = tag;
        !          8120:        c->valid[line] = true;
        !          8121:        if (currprefs.cpu_cycle_exact) {
        !          8122:                c->data[line][0] = mem_access_delay_longi_read_ce020(addr +  0);
        !          8123:                c->data[line][1] = mem_access_delay_longi_read_ce020(addr +  4);
        !          8124:                c->data[line][2] = mem_access_delay_longi_read_ce020(addr +  8);
        !          8125:                c->data[line][3] = mem_access_delay_longi_read_ce020(addr + 12);
        !          8126:        } else {
        !          8127:                c->data[line][0] = get_longi(addr +  0);
        !          8128:                c->data[line][1] = get_longi(addr +  4);
        !          8129:                c->data[line][2] = get_longi(addr +  8);
        !          8130:                c->data[line][3] = get_longi(addr + 12);
        !          8131:                x_do_cycles(4 * cpucycleunit);
        !          8132:        }
        !          8133: #ifdef WINUAE_FOR_HATARI
        !          8134:        CpuInstruction.I_Cache_miss++;
        !          8135: #endif
        !          8136:        return c->data[line][lws];
        !          8137: }
        !          8138: 
        !          8139: #if 0
        !          8140: static bool is_dcache040(uae_u32 addr)
        !          8141: {
        !          8142:        int index, i, lws;
        !          8143:        uae_u32 tag;
        !          8144:        struct cache040 *c;
        !          8145: 
        !          8146:        addr &= ~15;
        !          8147:        index = (addr >> 4) & (CACHESETS040 - 1);
        !          8148:        tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
        !          8149:        lws = (addr >> 2) & 3;
        !          8150:        c = &dcaches040[index];
        !          8151:        for (i = 0; i < CACHELINES040; i++) {
        !          8152:                if (c->valid[i] && c->tag[i] == tag) {
        !          8153:                        return true;
        !          8154:                }
        !          8155:        }
        !          8156:        return false;
        !          8157: }
        !          8158: 
        !          8159: uae_u32 read_dcache040(uae_u32 addr)
        !          8160: {
        !          8161:        int index, i, lws;
        !          8162:        uae_u32 tag;
        !          8163:        struct cache040 *c;
        !          8164:        int line;
        !          8165: 
        !          8166:        addr &= ~15;
        !          8167:        index = (addr >> 4) & (CACHESETS040 - 1);
        !          8168:        tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
        !          8169:        lws = (addr >> 2) & 3;
        !          8170:        c = &dcaches040[index];
        !          8171:        for (i = 0; i < CACHELINES040; i++) {
        !          8172:                if (c->valid[i] && c->tag[i] == tag) {
        !          8173:                        // cache hit
        !          8174:                        dcachelinecnt++;
        !          8175:                        return c->data[i][lws];
        !          8176:                }
        !          8177:        }
        !          8178:        // cache miss
        !          8179:        if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
        !          8180:                line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
        !          8181:                for (i = 0; i < 4; i++) {
        !          8182:                        if (c->dirty[line][i]) {
        !          8183:                                c->dirty[line][i] = false;
        !          8184:                                mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
        !          8185:                        }
        !          8186:                }
        !          8187:        }
        !          8188:        else {
        !          8189:                for (line = 0; line < CACHELINES040; line++) {
        !          8190:                        if (c->valid[line] == false)
        !          8191:                                break;
        !          8192:                }
        !          8193:        }
        !          8194:        c->tag[line] = tag;
        !          8195:        c->valid[line] = true;
        !          8196:        c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
        !          8197:        c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
        !          8198:        c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
        !          8199:        c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
        !          8200:        regs.cacheholdingaddr020 = addr;
        !          8201: }
        !          8202: 
        !          8203: void write_dcache040(uae_u32 addr, uae_u32 val)
        !          8204: {
        !          8205:        int index, i, lws;
        !          8206:        uae_u32 tag;
        !          8207:        struct cache040 *c;
        !          8208:        int line;
        !          8209: 
        !          8210:        addr &= ~15;
        !          8211:        index = (addr >> 4) & (CACHESETS040 - 1);
        !          8212:        tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
        !          8213:        lws = (addr >> 2) & 3;
        !          8214:        c = &dcaches040[index];
        !          8215:        for (i = 0; i < CACHELINES040; i++) {
        !          8216:                if (c->valid[i] && c->tag[i] == tag) {
        !          8217:                        // cache hit
        !          8218:                        dcachelinecnt++;
        !          8219:                        c->data[i][lws] = val;
        !          8220:                        mem_access_delay_long_write_ce020(addr + i * 4, c->data[i][lws]);
        !          8221:                        //c->dirty[i][lws] = true;
        !          8222:                }
        !          8223:        }
        !          8224: #if 0
        !          8225:        // cache miss
        !          8226:        if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
        !          8227:                line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
        !          8228:                for (i = 0; i < 4; i++) {
        !          8229:                        if (c->dirty[line][i]) {
        !          8230:                                c->dirty[line][i] = false;
        !          8231:                                mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
1.1.1.4   root     8232:                        }
                   8233:                }
                   8234:        }
1.1.1.7 ! root     8235:        else {
        !          8236:                for (line = 0; line < CACHELINES040; line++) {
        !          8237:                        if (c->valid[line] == false)
        !          8238:                                break;
        !          8239:                }
        !          8240:        }
        !          8241:        c->tag[line] = tag;
        !          8242:        c->valid[line] = true;
        !          8243:        c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
        !          8244:        c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
        !          8245:        c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
        !          8246:        c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
        !          8247:        c->data[line][lws] = val;
        !          8248:        c->dirty[line][lws] = true;
        !          8249: #endif
        !          8250: }
        !          8251: #endif
        !          8252: 
        !          8253: // really unoptimized
        !          8254: uae_u32 get_word_icache040(uaecptr addr)
        !          8255: {
        !          8256:        uae_u32 v = fill_icache040(addr);
        !          8257:        return v >> ((addr & 2) ? 0 : 16);
        !          8258: }
        !          8259: uae_u32 get_long_icache040(uaecptr addr)
        !          8260: {
        !          8261:        uae_u32 v1, v2;
        !          8262:        v1 = fill_icache040(addr);
        !          8263:        if ((addr & 2) == 0)
        !          8264:                return v1;
        !          8265:        v2 = fill_icache040(addr + 4);
        !          8266:        return (v2 >> 16) | (v1 << 16);
        !          8267: }
        !          8268: uae_u32 get_ilong_cache_040(int o)
        !          8269: {
        !          8270:        return get_long_icache040(m68k_getpci() + o);
        !          8271: }
        !          8272: uae_u32 get_iword_cache_040(int o)
        !          8273: {
        !          8274:        return get_word_icache040(m68k_getpci() + o);
        !          8275: }
        !          8276: 
        !          8277: STATIC_INLINE bool nocache040(uaecptr addr)
        !          8278: {
        !          8279:        if (!currprefs.cpu_cycle_exact)
        !          8280:                return false;
        !          8281:        if (!(regs.cacr & 0x80000000))
        !          8282:                return true;
        !          8283:        if (addr >= 0xd80000 && addr < 0xc00000)
        !          8284:                return true;
        !          8285:        if (addr >= 0xe80000 && addr < 0xf00000)
        !          8286:                return true;
        !          8287:        return false;
        !          8288: }
        !          8289: 
        !          8290: void put_long_cache_040(uaecptr addr, uae_u32 v)
        !          8291: {
        !          8292: #if 1
        !          8293:        if (nocache040(addr))
        !          8294:                mem_access_delay_long_write_ce020(addr, v);
        !          8295:        else
        !          8296:                put_long(addr, v);
        !          8297: #else
        !          8298:        if ((addr & 2) == 0) {
        !          8299:                if (is_dcache040(addr))
        !          8300:                        write_dcache040(addr, v);
        !          8301:                else if (currprefs.cpu_cycle_exact)
        !          8302:                        mem_access_delay_long_write_ce020(addr, v);
        !          8303:                else
        !          8304:                        put_long(addr, v);
        !          8305:        } else {
        !          8306:                uae_u32 vp;
        !          8307:                if (is_dcache040(addr)) {
        !          8308:                        vp = read_dcache040(addr);
        !          8309:                        vp &= 0xffff0000;
        !          8310:                        vp |= v >> 16;
        !          8311:                        write_dcache040(addr, vp);
        !          8312:                } else if (currprefs.cpu_cycle_exact) {
        !          8313:                        mem_access_delay_word_write_ce020(addr + 0, v >> 16);
        !          8314:                } else {
        !          8315:                        put_word(addr + 0, v >> 16);
        !          8316:                }
        !          8317:                if (is_dcache040(addr + 4)) {
        !          8318:                        vp = read_dcache040(addr + 4);
        !          8319:                        vp &= 0x0000ffff;
        !          8320:                        vp |= v << 16;
        !          8321:                        write_dcache040(addr + 4, vp);
        !          8322:                } else if (currprefs.cpu_cycle_exact) {
        !          8323:                        mem_access_delay_word_write_ce020(addr + 2, v);
        !          8324:                } else {
        !          8325:                        put_word(addr + 2, v);
        !          8326:                }
        !          8327:        }
        !          8328: #endif
        !          8329: }
        !          8330: void put_word_cache_040(uaecptr addr, uae_u32 v)
        !          8331: {
        !          8332: #if 1
        !          8333:        if (nocache040(addr))
        !          8334:                mem_access_delay_word_write_ce020(addr, v);
        !          8335:        else
        !          8336:                put_word(addr, v);
        !          8337: #else
        !          8338:        if (is_dcache040(addr)) {
        !          8339:                uae_u32 vp;
        !          8340:                vp = read_dcache040(addr);
        !          8341:                if (addr & 2) {
        !          8342:                        vp &= 0xffff0000;
        !          8343:                        vp |= v & 0xffff;
        !          8344:                } else {
        !          8345:                        vp &= 0x0000ffff;
        !          8346:                        vp |= v << 16;
        !          8347:                }
        !          8348:                write_dcache040(addr, vp);
        !          8349:        } else if (currprefs.cpu_cycle_exact) {
        !          8350:                mem_access_delay_word_write_ce020(addr, v);
        !          8351:        } else {
        !          8352:                put_word(addr, v);
        !          8353:        }
        !          8354: #endif
        !          8355: }
        !          8356: void put_byte_cache_040(uaecptr addr, uae_u32 v)
        !          8357: {
        !          8358: #if 1
        !          8359:        if (nocache040(addr))
        !          8360:                mem_access_delay_byte_write_ce020(addr, v);
        !          8361:        else
        !          8362:                put_byte(addr, v);
        !          8363: #else
        !          8364:        if (is_dcache040(addr)) {
        !          8365:                uae_u32 vp;
        !          8366:                uae_u32 mask = 0xff000000 >> (addr & 3);
        !          8367:                vp = read_dcache040(addr);
        !          8368:                vp &= ~mask;
        !          8369:                vp |= (v << (3 - (addr & 3))) & mask;
        !          8370:                write_dcache040(addr, vp);
        !          8371:        } else if (currprefs.cpu_cycle_exact) {
        !          8372:                mem_access_delay_byte_write_ce020(addr, v);
        !          8373:        } else {
        !          8374:                put_byte(addr, v);
        !          8375:        }
        !          8376: #endif
1.1.1.4   root     8377: }
                   8378: 
1.1.1.7 ! root     8379: uae_u32 get_long_cache_040(uaecptr addr)
        !          8380: {
        !          8381: #if 1
        !          8382:        if (nocache040(addr))
        !          8383:                return mem_access_delay_long_read_ce020(addr);
        !          8384:        else
        !          8385:                return get_long(addr);
        !          8386: #else
        !          8387:        uae_u32 v1, v2;
        !          8388:        v1 = read_dcache040(addr);
        !          8389:        if ((addr & 2) == 0)
        !          8390:                return v1;
        !          8391:        v2 = read_dcache040(addr + 4);
        !          8392:        return (v2 >> 16) | (v1 << 16);
        !          8393: #endif
        !          8394: }
        !          8395: uae_u32 get_word_cache_040(uaecptr addr)
        !          8396: {
        !          8397: #if 1
        !          8398:        if (nocache040(addr))
        !          8399:                return mem_access_delay_word_read_ce020(addr);
        !          8400:        else
        !          8401:                return get_word(addr);
        !          8402: #else
        !          8403:        uae_u32 v = read_dcache040(addr);
        !          8404:        return v >> ((addr & 2) ? 0 : 16);
        !          8405: #endif
        !          8406: }
        !          8407: uae_u32 get_byte_cache_040(uaecptr addr)
        !          8408: {
        !          8409: #if 1
        !          8410:        if (nocache040(addr))
        !          8411:                return mem_access_delay_byte_read_ce020(addr);
        !          8412:        else
        !          8413:                return get_byte(addr);
        !          8414: #else
        !          8415:        uae_u32 v = read_dcache040(addr);
        !          8416:        return v >> (8 * (3 - (addr & 3)));
        !          8417: #endif
        !          8418: }
        !          8419: uae_u32 next_iword_cache040(void)
        !          8420: {
        !          8421:        uae_u32 r = get_word_icache040(m68k_getpci());
        !          8422:        m68k_incpci(2);
        !          8423:        return r;
        !          8424: }
        !          8425: uae_u32 next_ilong_cache040(void)
        !          8426: {
        !          8427:        uae_u32 r = get_long_icache040(m68k_getpci());
        !          8428:        m68k_incpci(4);
        !          8429:        return r;
        !          8430: }
1.1.1.4   root     8431: 
                   8432: void flush_dcache (uaecptr addr, int size)
                   8433: {
                   8434:        int i;
1.1.1.7 ! root     8435:        if (!currprefs.cpu_cycle_exact && !currprefs.cpu_compatible)
1.1.1.4   root     8436:                return;
                   8437:        if (currprefs.cpu_model >= 68030) {
                   8438:                for (i = 0; i < CACHELINES030; i++) {
                   8439:                        dcaches030[i].valid[0] = 0;
                   8440:                        dcaches030[i].valid[1] = 0;
                   8441:                        dcaches030[i].valid[2] = 0;
                   8442:                        dcaches030[i].valid[3] = 0;
                   8443:                }
                   8444:        }
                   8445: }
                   8446: 
1.1.1.7 ! root     8447: #ifdef WINUAE_FOR_HATARI
        !          8448: void flush_instr_cache (uaecptr addr, int size)
1.1.1.4   root     8449: {
1.1.1.7 ! root     8450:        int i;
        !          8451:        if (!currprefs.cpu_cycle_exact && !currprefs.cpu_compatible)
        !          8452:                return;
        !          8453:        if (currprefs.cpu_model == 68020) {
        !          8454:                for (i = 0; i < CACHELINES020; i++)
        !          8455:                        caches020[i].valid = 0;
        !          8456:        }
        !          8457:        else if (currprefs.cpu_model == 68030) {
        !          8458:                for (i = 0; i < CACHELINES030; i++) {
        !          8459:                        icaches030[i].valid[0] = 0;
        !          8460:                        icaches030[i].valid[1] = 0;
        !          8461:                        icaches030[i].valid[2] = 0;
        !          8462:                        icaches030[i].valid[3] = 0;
        !          8463:                }
        !          8464:        }
        !          8465:        else if (currprefs.cpu_model >= 68040) {
        !          8466:                icachelinecnt = 0;
        !          8467:                dcachelinecnt = 0;
        !          8468:                for (i = 0; i < CACHESETS040; i++) {
        !          8469:                        icaches040[i].valid[0] = 0;
        !          8470:                        icaches040[i].valid[1] = 0;
        !          8471:                        icaches040[i].valid[2] = 0;
        !          8472:                        icaches040[i].valid[3] = 0;
        !          8473:                }
        !          8474:        }
1.1.1.4   root     8475: }
1.1.1.7 ! root     8476: #endif
1.1.1.4   root     8477: 
1.1.1.7 ! root     8478: void fill_prefetch_030 (void)
1.1.1.4   root     8479: {
1.1.1.7 ! root     8480:        uaecptr pc = m68k_getpc ();
        !          8481:        uaecptr pc2 = pc;
        !          8482:        pc &= ~3;
        !          8483:        regs.pipeline_pos = 0;
        !          8484:        regs.pipeline_stop = 0;
1.1.1.4   root     8485: 
1.1.1.7 ! root     8486:        fill_icache030 (pc);
        !          8487:        if (currprefs.cpu_cycle_exact)
        !          8488:                do_cycles_ce020_internal(2);
        !          8489:        regs.prefetch020[0] = regs.cacheholdingdata020;
        !          8490: 
        !          8491:        fill_icache030 (pc + 4);
        !          8492:        if (currprefs.cpu_cycle_exact)
        !          8493:                do_cycles_ce020_internal(2);
        !          8494:        regs.prefetch020[1] = regs.cacheholdingdata020;
        !          8495: 
        !          8496: #if MORE_ACCURATE_68020_PIPELINE
        !          8497:        if (pc2 & 2) {
        !          8498:                pipeline_020(regs.prefetch020[0], pc);
        !          8499:                pipeline_020(regs.prefetch020[1] >> 16, pc);
        !          8500:        } else {
        !          8501:                pipeline_020(regs.prefetch020[0] >> 16, pc);
        !          8502:                pipeline_020(regs.prefetch020[0], pc);
1.1.1.4   root     8503:        }
1.1.1.7 ! root     8504: #endif
1.1.1.4   root     8505: 
1.1.1.7 ! root     8506:        if (currprefs.cpu_cycle_exact)
        !          8507:                regs.irc = get_word_ce030_prefetch (0);
        !          8508:        else
        !          8509:                regs.irc = get_word_030_prefetch(0);
1.1.1.4   root     8510: }
                   8511: 
1.1.1.7 ! root     8512: void fill_prefetch_020 (void)
1.1.1.4   root     8513: {
1.1.1.7 ! root     8514:        uaecptr pc = m68k_getpc ();
        !          8515:        uaecptr pc2 = pc;
        !          8516:        pc &= ~3;
        !          8517:        uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
        !          8518:        regs.pipeline_pos = 0;
        !          8519:        regs.pipeline_stop = 0;
        !          8520:        regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
        !          8521: 
        !          8522:        fill_icache020 (pc, fetch);
        !          8523:        if (currprefs.cpu_cycle_exact)
        !          8524:                do_cycles_ce020_internal(2);
        !          8525:        regs.prefetch020[0] = regs.cacheholdingdata020;
        !          8526: 
        !          8527:        fill_icache020 (pc + 4, fetch);
        !          8528:        if (currprefs.cpu_cycle_exact)
        !          8529:                do_cycles_ce020_internal(2);
        !          8530:        regs.prefetch020[1] = regs.cacheholdingdata020;
        !          8531: 
        !          8532: #if MORE_ACCURATE_68020_PIPELINE
        !          8533:        if (pc2 & 2) {
        !          8534:                pipeline_020(regs.prefetch020[0], pc);
        !          8535:                pipeline_020(regs.prefetch020[1] >> 16, pc);
        !          8536:        } else {
        !          8537:                pipeline_020(regs.prefetch020[0] >> 16, pc);
        !          8538:                pipeline_020(regs.prefetch020[0], pc);
        !          8539:        }
        !          8540: #endif
        !          8541: 
        !          8542:        if (currprefs.cpu_cycle_exact)
        !          8543:                regs.irc = get_word_ce020_prefetch (0);
        !          8544:        else
        !          8545:                regs.irc = get_word_020_prefetch (0);
1.1.1.4   root     8546: }
                   8547: 
1.1.1.7 ! root     8548: void fill_prefetch (void)
1.1.1.4   root     8549: {
1.1.1.7 ! root     8550:        regs.pipeline_pos = 0;
        !          8551:        if (currprefs.cachesize)
        !          8552:                return;
        !          8553:        if (!currprefs.cpu_compatible)
        !          8554:                return;
        !          8555:        if (currprefs.cpu_model >= 68040) {
        !          8556:                if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) {
        !          8557:                        fill_icache040(m68k_getpc() + 16);
        !          8558:                        fill_icache040(m68k_getpc());
        !          8559:                }
        !          8560:        } else if (currprefs.cpu_model == 68020) {
        !          8561:                fill_prefetch_020 ();
        !          8562:        } else if (currprefs.cpu_model == 68030) {
        !          8563:                fill_prefetch_030 ();
        !          8564:        } else if (currprefs.cpu_model <= 68010) {
        !          8565:                uaecptr pc = m68k_getpc ();
        !          8566:                regs.ir = x_get_word (pc);
        !          8567:                regs.irc = x_get_word (pc + 2);
        !          8568:        }
1.1.1.4   root     8569: }
1.1.1.7 ! root     8570: 

unix.superglobalmegacorp.com

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