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

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: 
1.1.1.9 ! root       14: #define VALIDATE_68030_DATACACHE 0
        !            15: #define VALIDATE_68040_DATACACHE 0
        !            16: #define DISABLE_68040_COPYBACK 0
        !            17: 
1.1.1.7   root       18: #define MORE_ACCURATE_68020_PIPELINE 1
1.1.1.4   root       19: 
1.1.1.8   root       20: #include <inttypes.h>          /* Needed for PRIX64 */
                     21: 
1.1.1.5   root       22: #include "main.h"
1.1.1.4   root       23: #include "compat.h"
1.1.1.7   root       24: 
1.1.1.4   root       25: #include "sysconfig.h"
                     26: #include "sysdeps.h"
1.1.1.7   root       27: 
1.1.1.4   root       28: #include "hatari-glue.h"
1.1.1.7   root       29: 
1.1.1.4   root       30: #include "options_cpu.h"
                     31: #include "events.h"
                     32: #include "memory.h"
1.1.1.7   root       33: #include "custom.h"
1.1.1.4   root       34: #include "newcpu.h"
                     35: #include "cpummu.h"
1.1.1.5   root       36: #include "cpummu030.h"
1.1.1.4   root       37: #include "cpu_prefetch.h"
1.1.1.7   root       38: #include "savestate.h"
1.1.1.9 ! root       39: #include "fpp.h"
1.1.1.7   root       40: #ifdef WINUAE_FOR_HATARI
                     41: #include "debug.h"
                     42: #endif
                     43: 
                     44: #include "m68000.h"
1.1.1.4   root       45: #include "reset.h"
                     46: #include "cycInt.h"
                     47: #include "mfp.h"
                     48: #include "tos.h"
                     49: #include "vdi.h"
                     50: #include "cart.h"
                     51: #include "dialog.h"
                     52: #include "bios.h"
                     53: #include "xbios.h"
                     54: #include "screen.h"
                     55: #include "video.h"
                     56: #include "options.h"
                     57: #include "dsp.h"
                     58: #include "log.h"
                     59: #include "debugui.h"
                     60: #include "debugcpu.h"
1.1.1.5   root       61: #include "stMemory.h"
1.1.1.9 ! root       62: #include "blitter.h"
1.1.1.4   root       63: 
                     64: 
                     65: #ifdef JIT
                     66: #include "jit/compemu.h"
                     67: #include <signal.h>
                     68: #else
                     69: /* Need to have these somewhere */
1.1.1.8   root       70: //#ifndef WINUAE_FOR_HATARI
                     71: bool check_prefs_changed_comp (bool checkonly) { return false; }
                     72: //#endif
1.1.1.7   root       73: #endif
1.1.1.4   root       74: 
                     75: /* Opcode of faulting instruction */
                     76: static uae_u16 last_op_for_exception_3;
                     77: /* PC at fault time */
                     78: static uaecptr last_addr_for_exception_3;
                     79: /* Address that generated the exception */
                     80: static uaecptr last_fault_for_exception_3;
                     81: /* read (0) or write (1) access */
1.1.1.7   root       82: static bool last_writeaccess_for_exception_3;
1.1.1.4   root       83: /* instruction (1) or data (0) access */
1.1.1.7   root       84: static bool last_instructionaccess_for_exception_3;
                     85: /* not instruction */
                     86: static bool last_notinstruction_for_exception_3;
                     87: /* set when writing exception stack frame */
                     88: static int exception_in_exception;
                     89: 
1.1.1.4   root       90: int mmu_enabled, mmu_triggered;
                     91: int cpu_cycles;
1.1.1.7   root       92: int bus_error_offset;
                     93: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root       94: static int baseclock;
1.1.1.7   root       95: #endif
                     96: int m68k_pc_indirect;
                     97: bool m68k_interrupt_delay;
                     98: static bool m68k_reset_delay;
1.1.1.9 ! root       99: 
        !           100: static int cacheisets04060, cacheisets04060mask, cacheitag04060mask;
        !           101: static int cachedsets04060, cachedsets04060mask, cachedtag04060mask;
        !           102: 
1.1.1.7   root      103: static int cpu_prefs_changed_flag;
                    104: 
1.1.1.4   root      105: int cpucycleunit;
1.1.1.7   root      106: int cpu_tracer;
1.1.1.4   root      107: 
                    108: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
                    109: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
                    110: 
                    111: int movem_index1[256];
                    112: int movem_index2[256];
                    113: int movem_next[256];
                    114: 
                    115: cpuop_func *cpufunctbl[65536];
                    116: 
1.1.1.7   root      117: struct cputbl_data
                    118: {
                    119:        uae_s16 length;
                    120:        uae_s8 disp020[2];
                    121:        uae_u8 branch;
                    122: };
                    123: static struct cputbl_data cpudatatbl[65536];
1.1.1.5   root      124: 
1.1.1.4   root      125: struct mmufixup mmufixup[2];
                    126: 
                    127: #define COUNT_INSTRS 0
                    128: #define MC68060_PCR   0x04300000
                    129: #define MC68EC060_PCR 0x04310000
                    130: 
1.1.1.7   root      131: static uae_u64 fake_srp_030, fake_crp_030;
                    132: static uae_u32 fake_tt0_030, fake_tt1_030, fake_tc_030;
                    133: static uae_u16 fake_mmusr_030;
1.1.1.4   root      134: 
                    135: static struct cache020 caches020[CACHELINES020];
                    136: static struct cache030 icaches030[CACHELINES030];
                    137: static struct cache030 dcaches030[CACHELINES030];
1.1.1.9 ! root      138: static int icachelinecnt, icachehalfline;
        !           139: static int dcachelinecnt;
        !           140: static struct cache040 icaches040[CACHESETS060];
        !           141: static struct cache040 dcaches040[CACHESETS060];
        !           142: static int cache_lastline; 
1.1.1.7   root      143: 
1.1.1.8   root      144: static int fallback_cpu_model, fallback_mmu_model, fallback_fpu_model;
1.1.1.9 ! root      145: static bool fallback_cpu_compatible, fallback_cpu_address_space_24;
1.1.1.8   root      146: static struct regstruct fallback_regs;
                    147: static int fallback_new_cpu_model;
1.1.1.7   root      148: 
                    149: #ifdef WINUAE_FOR_HATARI
                    150: int OpcodeFamily;
                    151: int BusCyclePenalty = 0;
1.1.1.4   root      152: 
1.1.1.7   root      153: FILE *console_out_FILE = NULL;
1.1.1.9 ! root      154: 
        !           155: int uae_quit_program = 0;                      /* from main.cpp */
1.1.1.7   root      156: #endif
1.1.1.4   root      157: 
                    158: 
                    159: #if COUNT_INSTRS
                    160: static unsigned long int instrcount[65536];
                    161: static uae_u16 opcodenums[65536];
                    162: 
                    163: static int compfn (const void *el1, const void *el2)
                    164: {
                    165:        return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
                    166: }
                    167: 
                    168: static TCHAR *icountfilename (void)
                    169: {
                    170:        TCHAR *name = getenv ("INSNCOUNT");
                    171:        if (name)
                    172:                return name;
                    173:        return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
                    174: }
                    175: 
                    176: void dump_counts (void)
                    177: {
                    178:        FILE *f = fopen (icountfilename (), "w");
                    179:        unsigned long int total;
                    180:        int i;
                    181: 
1.1.1.7   root      182:        write_log (_T("Writing instruction count file...\n"));
1.1.1.4   root      183:        for (i = 0; i < 65536; i++) {
                    184:                opcodenums[i] = i;
                    185:                total += instrcount[i];
                    186:        }
                    187:        qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
                    188: 
                    189:        fprintf (f, "Total: %lu\n", total);
                    190:        for (i=0; i < 65536; i++) {
                    191:                unsigned long int cnt = instrcount[opcodenums[i]];
                    192:                struct instr *dp;
                    193:                struct mnemolookup *lookup;
                    194:                if (!cnt)
                    195:                        break;
                    196:                dp = table68k + opcodenums[i];
                    197:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                    198:                        ;
                    199:                fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
                    200:        }
                    201:        fclose (f);
                    202: }
                    203: #else
                    204: void dump_counts (void)
                    205: {
                    206: }
                    207: #endif
                    208: 
1.1.1.7   root      209: /*
                    210: 
                    211:  ok, all this to "record" current instruction state
                    212:  for later 100% cycle-exact restoring
                    213: 
                    214:  */
                    215: 
                    216: static uae_u32 (*x2_prefetch)(int);
                    217: static uae_u32 (*x2_prefetch_long)(int);
                    218: static uae_u32 (*x2_next_iword)(void);
                    219: static uae_u32 (*x2_next_ilong)(void);
                    220: static uae_u32 (*x2_get_ilong)(int);
                    221: static uae_u32 (*x2_get_iword)(int);
                    222: static uae_u32 (*x2_get_ibyte)(int);
                    223: static uae_u32 (*x2_get_long)(uaecptr);
                    224: static uae_u32 (*x2_get_word)(uaecptr);
                    225: static uae_u32 (*x2_get_byte)(uaecptr);
                    226: static void (*x2_put_long)(uaecptr,uae_u32);
                    227: static void (*x2_put_word)(uaecptr,uae_u32);
                    228: static void (*x2_put_byte)(uaecptr,uae_u32);
                    229: static void (*x2_do_cycles)(unsigned long);
                    230: static void (*x2_do_cycles_pre)(unsigned long);
                    231: static void (*x2_do_cycles_post)(unsigned long, uae_u32);
1.1.1.4   root      232: 
                    233: uae_u32 (*x_prefetch)(int);
                    234: uae_u32 (*x_next_iword)(void);
                    235: uae_u32 (*x_next_ilong)(void);
1.1.1.7   root      236: uae_u32 (*x_get_ilong)(int);
                    237: uae_u32 (*x_get_iword)(int);
                    238: uae_u32 (*x_get_ibyte)(int);
1.1.1.4   root      239: uae_u32 (*x_get_long)(uaecptr);
                    240: uae_u32 (*x_get_word)(uaecptr);
                    241: uae_u32 (*x_get_byte)(uaecptr);
                    242: void (*x_put_long)(uaecptr,uae_u32);
                    243: void (*x_put_word)(uaecptr,uae_u32);
                    244: void (*x_put_byte)(uaecptr,uae_u32);
                    245: 
1.1.1.7   root      246: uae_u32 (*x_cp_next_iword)(void);
                    247: uae_u32 (*x_cp_next_ilong)(void);
                    248: uae_u32 (*x_cp_get_long)(uaecptr);
                    249: uae_u32 (*x_cp_get_word)(uaecptr);
                    250: uae_u32 (*x_cp_get_byte)(uaecptr);
                    251: void (*x_cp_put_long)(uaecptr,uae_u32);
                    252: void (*x_cp_put_word)(uaecptr,uae_u32);
                    253: void (*x_cp_put_byte)(uaecptr,uae_u32);
                    254: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
                    255: 
                    256: void (*x_do_cycles)(unsigned long);
                    257: void (*x_do_cycles_pre)(unsigned long);
                    258: void (*x_do_cycles_post)(unsigned long, uae_u32);
                    259: 
                    260: uae_u32(*x_phys_get_iword)(uaecptr);
                    261: uae_u32(*x_phys_get_ilong)(uaecptr);
                    262: uae_u32(*x_phys_get_byte)(uaecptr);
                    263: uae_u32(*x_phys_get_word)(uaecptr);
                    264: uae_u32(*x_phys_get_long)(uaecptr);
                    265: void(*x_phys_put_byte)(uaecptr, uae_u32);
                    266: void(*x_phys_put_word)(uaecptr, uae_u32);
                    267: void(*x_phys_put_long)(uaecptr, uae_u32);
                    268: 
                    269: static void set_x_cp_funcs(void)
                    270: {
                    271:        x_cp_put_long = x_put_long;
                    272:        x_cp_put_word = x_put_word;
                    273:        x_cp_put_byte = x_put_byte;
                    274:        x_cp_get_long = x_get_long;
                    275:        x_cp_get_word = x_get_word;
                    276:        x_cp_get_byte = x_get_byte;
                    277:        x_cp_next_iword = x_next_iword;
                    278:        x_cp_next_ilong = x_next_ilong;
                    279:        x_cp_get_disp_ea_020 = x_get_disp_ea_020;
                    280: 
                    281:        if (currprefs.mmu_model == 68030) {
1.1.1.9 ! root      282:                if (currprefs.cpu_compatible) {
        !           283:                        x_cp_put_long = put_long_mmu030c_state;
        !           284:                        x_cp_put_word = put_word_mmu030c_state;
        !           285:                        x_cp_put_byte = put_byte_mmu030c_state;
        !           286:                        x_cp_get_long = get_long_mmu030c_state;
        !           287:                        x_cp_get_word = get_word_mmu030c_state;
        !           288:                        x_cp_get_byte = get_byte_mmu030c_state;
        !           289:                        x_cp_next_iword = next_iword_mmu030c_state;
        !           290:                        x_cp_next_ilong = next_ilong_mmu030c_state;
        !           291:                        x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030c;
        !           292:                } else {
        !           293:                        x_cp_put_long = put_long_mmu030_state;
        !           294:                        x_cp_put_word = put_word_mmu030_state;
        !           295:                        x_cp_put_byte = put_byte_mmu030_state;
        !           296:                        x_cp_get_long = get_long_mmu030_state;
        !           297:                        x_cp_get_word = get_word_mmu030_state;
        !           298:                        x_cp_get_byte = get_byte_mmu030_state;
        !           299:                        x_cp_next_iword = next_iword_mmu030_state;
        !           300:                        x_cp_next_ilong = next_ilong_mmu030_state;
        !           301:                        x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
        !           302:                }
1.1.1.7   root      303:        }
                    304: }
                    305: 
                    306: static struct cputracestruct cputrace;
                    307: 
                    308: #if CPUTRACE_DEBUG
                    309: static void validate_trace (void)
                    310: {
                    311:        for (int i = 0; i < cputrace.memoryoffset; i++) {
                    312:                struct cputracememory *ctm = &cputrace.ctm[i];
                    313:                if (ctm->data == 0xdeadf00d) {
                    314:                        write_log (_T("unfinished write operation %d %08x\n"), i, ctm->addr);
                    315:                }
                    316:        }
                    317: }
                    318: #endif
                    319: 
                    320: static void debug_trace (void)
                    321: {
                    322:        if (cputrace.writecounter > 10000 || cputrace.readcounter > 10000)
                    323:                write_log (_T("cputrace.readcounter=%d cputrace.writecounter=%d\n"), cputrace.readcounter, cputrace.writecounter);
                    324: }
                    325: 
                    326: STATIC_INLINE void clear_trace (void)
                    327: {
                    328: #if CPUTRACE_DEBUG
                    329:        validate_trace ();
                    330: #endif
1.1.1.9 ! root      331:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE)
        !           332:                return;
1.1.1.7   root      333:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
1.1.1.9 ! root      334:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE) {
        !           335:                write_log(_T("CPUTRACE overflow, stopping tracing.\n"));
        !           336:                return;
        !           337:        }
1.1.1.7   root      338:        ctm->mode = 0;
                    339:        cputrace.cyclecounter = 0;
                    340:        cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                    341: }
                    342: static void set_trace (uaecptr addr, int accessmode, int size)
                    343: {
                    344: #if CPUTRACE_DEBUG
                    345:        validate_trace ();
                    346: #endif
1.1.1.9 ! root      347:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE)
        !           348:                return;
1.1.1.7   root      349:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
1.1.1.9 ! root      350:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE) {
        !           351:                write_log(_T("CPUTRACE overflow, stopping tracing.\n"));
        !           352:                return;
        !           353:        }
1.1.1.7   root      354:        ctm->addr = addr;
                    355:        ctm->data = 0xdeadf00d;
                    356:        ctm->mode = accessmode | (size << 4);
                    357:        cputrace.cyclecounter_pre = -1;
                    358:        if (accessmode == 1)
                    359:                cputrace.writecounter++;
                    360:        else
                    361:                cputrace.readcounter++;
                    362:        debug_trace ();
                    363: }
                    364: static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size)
                    365: {
                    366:        if (cputrace.memoryoffset < 1) {
                    367: #if CPUTRACE_DEBUG
                    368:                write_log (_T("add_trace memoryoffset=%d!\n"), cputrace.memoryoffset);
                    369: #endif
                    370:                return;
                    371:        }
                    372:        int mode = accessmode | (size << 4);
                    373:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
                    374:        ctm->addr = addr;
                    375:        ctm->data = val;
                    376:        if (!ctm->mode) {
                    377:                ctm->mode = mode;
                    378:                if (accessmode == 1)
                    379:                        cputrace.writecounter++;
                    380:                else
                    381:                        cputrace.readcounter++;
                    382:        }
                    383:        debug_trace ();
                    384:        cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                    385: }
                    386: 
                    387: 
                    388: static void check_trace2 (void)
                    389: {
                    390:        if (cputrace.readcounter || cputrace.writecounter ||
                    391:                cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
                    392:                write_log (_T("CPU tracer invalid state during playback!\n"));
                    393: }
                    394: 
                    395: static bool check_trace (void)
                    396: {
                    397:        if (!cpu_tracer)
                    398:                return true;
                    399:        if (!cputrace.readcounter && !cputrace.writecounter && !cputrace.cyclecounter) {
                    400:                if (cpu_tracer != -2) {
                    401:                        write_log (_T("CPU trace: dma_cycle() enabled. %08x %08x NOW=%08lx\n"),
                    402:                                cputrace.cyclecounter_pre, cputrace.cyclecounter_post, get_cycles ());
                    403:                        cpu_tracer = -2; // dma_cycle() allowed to work now
                    404:                }
                    405:        }
                    406:        if (cputrace.readcounter || cputrace.writecounter ||
                    407:                cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
                    408:                return false;
                    409:        x_prefetch = x2_prefetch;
                    410:        x_get_ilong = x2_get_ilong;
                    411:        x_get_iword = x2_get_iword;
                    412:        x_get_ibyte = x2_get_ibyte;
                    413:        x_next_iword = x2_next_iword;
                    414:        x_next_ilong = x2_next_ilong;
                    415:        x_put_long = x2_put_long;
                    416:        x_put_word = x2_put_word;
                    417:        x_put_byte = x2_put_byte;
                    418:        x_get_long = x2_get_long;
                    419:        x_get_word = x2_get_word;
                    420:        x_get_byte = x2_get_byte;
                    421:        x_do_cycles = x2_do_cycles;
                    422:        x_do_cycles_pre = x2_do_cycles_pre;
                    423:        x_do_cycles_post = x2_do_cycles_post;
                    424:        set_x_cp_funcs();
                    425:        write_log (_T("CPU tracer playback complete. STARTCYCLES=%08x NOWCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
                    426:        cputrace.needendcycles = 1;
                    427:        cpu_tracer = 0;
                    428:        return true;
                    429: }
                    430: 
                    431: static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data)
                    432: {
                    433:        int mode = accessmode | (size << 4);
                    434:        int i;
                    435:        for (i = 0; i < cputrace.memoryoffset; i++) {
                    436:                struct cputracememory *ctm = &cputrace.ctm[i];
                    437:                if (ctm->addr == addr && ctm->mode == mode) {
                    438:                        ctm->mode = 0;
                    439:                        write_log (_T("CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d (%08lx)\n"),
                    440:                                i, cputrace.pc, addr, ctm->data, accessmode, size,
                    441:                                cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
                    442:                                cputrace.readcounter, cputrace.writecounter, get_cycles ());
                    443:                        if (accessmode == 1)
                    444:                                cputrace.writecounter--;
                    445:                        else
                    446:                                cputrace.readcounter--;
                    447:                        if (cputrace.writecounter == 0 && cputrace.readcounter == 0) {
                    448:                                if (cputrace.cyclecounter_post) {
                    449:                                        int c = cputrace.cyclecounter_post;
                    450:                                        cputrace.cyclecounter_post = 0;
                    451:                                        x_do_cycles (c);
                    452:                                } else if (cputrace.cyclecounter_pre) {
                    453:                                        check_trace ();
                    454:                                        *data = ctm->data;
                    455:                                        return true; // argh, need to rerun the memory access..
                    456:                                }
                    457:                        }
                    458:                        check_trace ();
                    459:                        *data = ctm->data;
                    460:                        return false;
                    461:                }
                    462:        }
                    463:        if (cputrace.cyclecounter_post) {
                    464:                int c = cputrace.cyclecounter_post;
                    465:                cputrace.cyclecounter_post = 0;
                    466:                check_trace ();
                    467:                check_trace2 ();
                    468:                x_do_cycles (c);
                    469:                return false;
                    470:        }
                    471:        gui_message (_T("CPU trace: GET %08x %d %d NOT FOUND!\n"), addr, accessmode, size);
                    472:        check_trace ();
                    473:        *data = 0;
                    474:        return false;
                    475: }
                    476: 
                    477: static uae_u32 cputracefunc_x_prefetch (int o)
                    478: {
                    479:        uae_u32 pc = m68k_getpc ();
                    480:        set_trace (pc + o, 2, 2);
                    481:        uae_u32 v = x2_prefetch (o);
                    482:        add_trace (pc + o, v, 2, 2);
                    483:        return v;
                    484: }
                    485: static uae_u32 cputracefunc2_x_prefetch (int o)
                    486: {
                    487:        uae_u32 v;
                    488:        if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
                    489:                v = x2_prefetch (o);
                    490:                check_trace2 ();
                    491:        }
                    492:        return v;
                    493: }
                    494: 
                    495: static uae_u32 cputracefunc_x_next_iword (void)
                    496: {
                    497:        uae_u32 pc = m68k_getpc ();
                    498:        set_trace (pc, 2, 2);
                    499:        uae_u32 v = x2_next_iword ();
                    500:        add_trace (pc, v, 2, 2);
                    501:        return v;
                    502: }
                    503: static uae_u32 cputracefunc_x_next_ilong (void)
                    504: {
                    505:        uae_u32 pc = m68k_getpc ();
                    506:        set_trace (pc, 2, 4);
                    507:        uae_u32 v = x2_next_ilong ();
                    508:        add_trace (pc, v, 2, 4);
                    509:        return v;
                    510: }
                    511: static uae_u32 cputracefunc2_x_next_iword (void)
                    512: {
                    513:        uae_u32 v;
                    514:        if (get_trace (m68k_getpc (), 2, 2, &v)) {
                    515:                v = x2_next_iword ();
                    516:                check_trace2 ();
                    517:        }
                    518:        return v;
                    519: }
                    520: static uae_u32 cputracefunc2_x_next_ilong (void)
                    521: {
                    522:        uae_u32 v;
                    523:        if (get_trace (m68k_getpc (), 2, 4, &v)) {
                    524:                v = x2_next_ilong ();
                    525:                check_trace2 ();
                    526:        }
                    527:        return v;
                    528: }
                    529: 
                    530: static uae_u32 cputracefunc_x_get_ilong (int o)
                    531: {
                    532:        uae_u32 pc = m68k_getpc ();
                    533:        set_trace (pc + o, 2, 4);
                    534:        uae_u32 v = x2_get_ilong (o);
                    535:        add_trace (pc + o, v, 2, 4);
                    536:        return v;
                    537: }
                    538: static uae_u32 cputracefunc_x_get_iword (int o)
                    539: {
                    540:        uae_u32 pc = m68k_getpc ();
                    541:        set_trace (pc + o, 2, 2);
                    542:        uae_u32 v = x2_get_iword (o);
                    543:        add_trace (pc + o, v, 2, 2);
                    544:        return v;
                    545: }
                    546: static uae_u32 cputracefunc_x_get_ibyte (int o)
                    547: {
                    548:        uae_u32 pc = m68k_getpc ();
                    549:        set_trace (pc + o, 2, 1);
                    550:        uae_u32 v = x2_get_ibyte (o);
                    551:        add_trace (pc + o, v, 2, 1);
                    552:        return v;
                    553: }
                    554: static uae_u32 cputracefunc2_x_get_ilong (int o)
                    555: {
                    556:        uae_u32 v;
                    557:        if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
                    558:                v = x2_get_ilong (o);
                    559:                check_trace2 ();
                    560:        }
                    561:        return v;
                    562: }
                    563: static uae_u32 cputracefunc2_x_get_iword (int o)
                    564: {
                    565:        uae_u32 v;
                    566:        if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
                    567:                v = x2_get_iword (o);
                    568:                check_trace2 ();
                    569:        }
                    570:        return v;
                    571: }
                    572: static uae_u32 cputracefunc2_x_get_ibyte (int o)
                    573: {
                    574:        uae_u32 v;
                    575:        if (get_trace (m68k_getpc () + o, 2, 1, &v)) {
                    576:                v = x2_get_ibyte (o);
                    577:                check_trace2 ();
                    578:        }
                    579:        return v;
                    580: }
                    581: 
                    582: static uae_u32 cputracefunc_x_get_long (uaecptr o)
                    583: {
                    584:        set_trace (o, 0, 4);
                    585:        uae_u32 v = x2_get_long (o);
                    586:        add_trace (o, v, 0, 4);
                    587:        return v;
                    588: }
                    589: static uae_u32 cputracefunc_x_get_word (uaecptr o)
                    590: {
                    591:        set_trace (o, 0, 2);
                    592:        uae_u32 v = x2_get_word (o);
                    593:        add_trace (o, v, 0, 2);
                    594:        return v;
                    595: }
                    596: static uae_u32 cputracefunc_x_get_byte (uaecptr o)
                    597: {
                    598:        set_trace (o, 0, 1);
                    599:        uae_u32 v = x2_get_byte (o);
                    600:        add_trace (o, v, 0, 1);
                    601:        return v;
                    602: }
                    603: static uae_u32 cputracefunc2_x_get_long (uaecptr o)
                    604: {
                    605:        uae_u32 v;
                    606:        if (get_trace (o, 0, 4, &v)) {
                    607:                v = x2_get_long (o);
                    608:                check_trace2 ();
                    609:        }
                    610:        return v;
                    611: }
                    612: static uae_u32 cputracefunc2_x_get_word (uaecptr o)
                    613: {
                    614:        uae_u32 v;
                    615:        if (get_trace (o, 0, 2, &v)) {
                    616:                v = x2_get_word (o);
                    617:                check_trace2 ();
                    618:        }
                    619:        return v;
                    620: }
                    621: static uae_u32 cputracefunc2_x_get_byte (uaecptr o)
                    622: {
                    623:        uae_u32 v;
                    624:        if (get_trace (o, 0, 1, &v)) {
                    625:                v = x2_get_byte (o);
                    626:                check_trace2 ();
                    627:        }
                    628:        return v;
                    629: }
                    630: 
                    631: static void cputracefunc_x_put_long (uaecptr o, uae_u32 val)
                    632: {
                    633:        clear_trace ();
                    634:        add_trace (o, val, 1, 4);
                    635:        x2_put_long (o, val);
                    636: }
                    637: static void cputracefunc_x_put_word (uaecptr o, uae_u32 val)
                    638: {
                    639:        clear_trace ();
                    640:        add_trace (o, val, 1, 2);
                    641:        x2_put_word (o, val);
                    642: }
                    643: static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val)
                    644: {
                    645:        clear_trace ();
                    646:        add_trace (o, val, 1, 1);
                    647:        x2_put_byte (o, val);
                    648: }
                    649: static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val)
                    650: {
                    651:        uae_u32 v;
                    652:        if (get_trace (o, 1, 4, &v)) {
                    653:                x2_put_long (o, val);
                    654:                check_trace2 ();
                    655:        }
                    656:        if (v != val)
                    657:                write_log (_T("cputracefunc2_x_put_long %d <> %d\n"), v, val);
                    658: }
                    659: static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val)
                    660: {
                    661:        uae_u32 v;
                    662:        if (get_trace (o, 1, 2, &v)) {
                    663:                x2_put_word (o, val);
                    664:                check_trace2 ();
                    665:        }
                    666:        if (v != val)
                    667:                write_log (_T("cputracefunc2_x_put_word %d <> %d\n"), v, val);
                    668: }
                    669: static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val)
                    670: {
                    671:        uae_u32 v;
                    672:        if (get_trace (o, 1, 1, &v)) {
                    673:                x2_put_byte (o, val);
                    674:                check_trace2 ();
                    675:        }
                    676:        if (v != val)
                    677:                write_log (_T("cputracefunc2_x_put_byte %d <> %d\n"), v, val);
                    678: }
                    679: 
                    680: static void cputracefunc_x_do_cycles (unsigned long cycles)
                    681: {
                    682:        while (cycles >= CYCLE_UNIT) {
                    683:                cputrace.cyclecounter += CYCLE_UNIT;
                    684:                cycles -= CYCLE_UNIT;
                    685:                x2_do_cycles (CYCLE_UNIT);
                    686:        }
                    687:        if (cycles > 0) {
                    688:                cputrace.cyclecounter += cycles;
                    689:                x2_do_cycles (cycles);
                    690:        }
                    691: }
                    692: 
                    693: static void cputracefunc2_x_do_cycles (unsigned long cycles)
                    694: {
                    695:        if (cputrace.cyclecounter > (long)cycles) {
                    696:                cputrace.cyclecounter -= cycles;
                    697:                return;
                    698:        }
                    699:        cycles -= cputrace.cyclecounter;
                    700:        cputrace.cyclecounter = 0;
                    701:        check_trace ();
                    702:        x_do_cycles = x2_do_cycles;
                    703:        if (cycles > 0)
                    704:                x_do_cycles (cycles);
                    705: }
                    706: 
                    707: static void cputracefunc_x_do_cycles_pre (unsigned long cycles)
                    708: {
                    709:        cputrace.cyclecounter_post = 0;
                    710:        cputrace.cyclecounter_pre = 0;
                    711:        while (cycles >= CYCLE_UNIT) {
                    712:                cycles -= CYCLE_UNIT;
                    713:                cputrace.cyclecounter_pre += CYCLE_UNIT;
                    714:                x2_do_cycles (CYCLE_UNIT);
                    715:        }
                    716:        if (cycles > 0) {
                    717:                x2_do_cycles (cycles);
                    718:                cputrace.cyclecounter_pre += cycles;
                    719:        }
                    720:        cputrace.cyclecounter_pre = 0;
                    721: }
                    722: // cyclecounter_pre = how many cycles we need to SWALLOW
                    723: // -1 = rerun whole access
                    724: static void cputracefunc2_x_do_cycles_pre (unsigned long cycles)
                    725: {
                    726:        if (cputrace.cyclecounter_pre == -1) {
                    727:                cputrace.cyclecounter_pre = 0;
                    728:                check_trace ();
                    729:                check_trace2 ();
                    730:                x_do_cycles (cycles);
                    731:                return;
                    732:        }
                    733:        if (cputrace.cyclecounter_pre > (long)cycles) {
                    734:                cputrace.cyclecounter_pre -= cycles;
                    735:                return;
                    736:        }
                    737:        cycles -= cputrace.cyclecounter_pre;
                    738:        cputrace.cyclecounter_pre = 0;
                    739:        check_trace ();
                    740:        if (cycles > 0)
                    741:                x_do_cycles (cycles);
                    742: }
                    743: 
                    744: static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v)
                    745: {
                    746:        if (cputrace.memoryoffset < 1) {
                    747: #if CPUTRACE_DEBUG
                    748:                write_log (_T("cputracefunc_x_do_cycles_post memoryoffset=%d!\n"), cputrace.memoryoffset);
                    749: #endif
                    750:                return;
                    751:        }
                    752:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
                    753:        ctm->data = v;
                    754:        cputrace.cyclecounter_post = cycles;
                    755:        cputrace.cyclecounter_pre = 0;
                    756:        while (cycles >= CYCLE_UNIT) {
                    757:                cycles -= CYCLE_UNIT;
                    758:                cputrace.cyclecounter_post -= CYCLE_UNIT;
                    759:                x2_do_cycles (CYCLE_UNIT);
                    760:        }
                    761:        if (cycles > 0) {
                    762:                cputrace.cyclecounter_post -= cycles;
                    763:                x2_do_cycles (cycles);
                    764:        }
                    765:        cputrace.cyclecounter_post = 0;
                    766: }
                    767: // cyclecounter_post = how many cycles we need to WAIT
                    768: static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v)
                    769: {
                    770:        uae_u32 c;
                    771:        if (cputrace.cyclecounter_post) {
                    772:                c = cputrace.cyclecounter_post;
                    773:                cputrace.cyclecounter_post = 0;
                    774:        } else {
                    775:                c = cycles;
                    776:        }
                    777:        check_trace ();
                    778:        if (c > 0)
                    779:                x_do_cycles (c);
                    780: }
                    781: 
                    782: static void do_cycles_post (unsigned long cycles, uae_u32 v)
                    783: {
                    784:        do_cycles (cycles);
                    785: }
                    786: static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
                    787: {
                    788:        do_cycles_ce (cycles);
                    789: }
                    790: static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
                    791: {
                    792: #ifndef WINUAE_FOR_HATARI
                    793:        do_cycles_ce020 (cycles);
                    794: #else
                    795:        do_cycles_ce020_long (cycles);
                    796: #endif
                    797: }
                    798: 
1.1.1.9 ! root      799: static uae_u8 dcache_check_nommu(uaecptr addr, bool write, uae_u32 size)
        !           800: {
        !           801:        return ce_cachable[addr >> 16];
        !           802: }
        !           803: 
        !           804: static void mem_access_delay_long_write_ce030_cicheck(uaecptr addr, uae_u32 v)
        !           805: {
        !           806:        mem_access_delay_long_write_ce020(addr, v);
        !           807:        mmu030_cache_state = ce_cachable[addr >> 16];
        !           808: }
        !           809: static void mem_access_delay_word_write_ce030_cicheck(uaecptr addr, uae_u32 v)
        !           810: {
        !           811:        mem_access_delay_word_write_ce020(addr, v);
        !           812:        mmu030_cache_state = ce_cachable[addr >> 16];
        !           813: }
        !           814: static void mem_access_delay_byte_write_ce030_cicheck(uaecptr addr, uae_u32 v)
        !           815: {
        !           816:        mem_access_delay_byte_write_ce020(addr, v);
        !           817:        mmu030_cache_state = ce_cachable[addr >> 16];
        !           818: }
        !           819: 
        !           820: static void put_long030_cicheck(uaecptr addr, uae_u32 v)
        !           821: {
        !           822:        put_long(addr, v);
        !           823:        mmu030_cache_state = ce_cachable[addr >> 16];
        !           824: }
        !           825: static void put_word030_cicheck(uaecptr addr, uae_u32 v)
        !           826: {
        !           827:        put_word(addr, v);
        !           828:        mmu030_cache_state = ce_cachable[addr >> 16];
        !           829: }
        !           830: static void put_byte030_cicheck(uaecptr addr, uae_u32 v)
        !           831: {
        !           832:        put_byte(addr, v);
        !           833:        mmu030_cache_state = ce_cachable[addr >> 16];
        !           834: }
        !           835: 
        !           836: static uae_u32 (*icache_fetch)(uaecptr);
        !           837: static uae_u32 (*dcache_lget)(uaecptr);
        !           838: static uae_u32 (*dcache_wget)(uaecptr);
        !           839: static uae_u32 (*dcache_bget)(uaecptr);
        !           840: static uae_u8 (*dcache_check)(uaecptr, bool, uae_u32);
        !           841: static void (*dcache_lput)(uaecptr, uae_u32);
        !           842: static void (*dcache_wput)(uaecptr, uae_u32);
        !           843: static void (*dcache_bput)(uaecptr, uae_u32);
        !           844: 
        !           845: uae_u32(*read_data_030_bget)(uaecptr);
        !           846: uae_u32(*read_data_030_wget)(uaecptr);
        !           847: uae_u32(*read_data_030_lget)(uaecptr);
        !           848: void(*write_data_030_bput)(uaecptr,uae_u32);
        !           849: void(*write_data_030_wput)(uaecptr,uae_u32);
        !           850: void(*write_data_030_lput)(uaecptr,uae_u32);
        !           851: 
        !           852: uae_u32(*read_data_030_fc_bget)(uaecptr, uae_u32);
        !           853: uae_u32(*read_data_030_fc_wget)(uaecptr, uae_u32);
        !           854: uae_u32(*read_data_030_fc_lget)(uaecptr, uae_u32);
        !           855: void(*write_data_030_fc_bput)(uaecptr, uae_u32, uae_u32);
        !           856: void(*write_data_030_fc_wput)(uaecptr, uae_u32, uae_u32);
        !           857: void(*write_data_030_fc_lput)(uaecptr, uae_u32, uae_u32);
        !           858: 
        !           859:  
        !           860:  static void set_x_ifetches(void)
1.1.1.7   root      861: {
                    862:        if (m68k_pc_indirect) {
                    863:                if (currprefs.cachesize) {
                    864:                        // indirect via addrbank
                    865:                        x_get_ilong = get_iilong_jit;
                    866:                        x_get_iword = get_iiword_jit;
                    867:                        x_get_ibyte = get_iibyte_jit;
                    868:                        x_next_iword = next_iiword_jit;
                    869:                        x_next_ilong = next_iilong_jit;
                    870:                } else {
                    871:                        // indirect via addrbank
                    872:                        x_get_ilong = get_iilong;
                    873:                        x_get_iword = get_iiword;
                    874:                        x_get_ibyte = get_iibyte;
                    875:                        x_next_iword = next_iiword;
                    876:                        x_next_ilong = next_iilong;
                    877:                }
                    878:        } else {
                    879:                // direct to memory
                    880:                x_get_ilong = get_dilong;
                    881:                x_get_iword = get_diword;
                    882:                x_get_ibyte = get_dibyte;
                    883:                x_next_iword = next_diword;
                    884:                x_next_ilong = next_dilong;
                    885:        }
                    886: }
                    887: 
1.1.1.9 ! root      888: 
        !           889: #ifdef WINUAE_FOR_HATARI
        !           890: 
        !           891: void (*x_do_cycles_hatari_blitter_save)(unsigned long);
        !           892: void (*x_do_cycles_pre_hatari_blitter_save)(unsigned long);
        !           893: void (*x_do_cycles_post_hatari_blitter_save)(unsigned long, uae_u32);
        !           894: 
        !           895: static void do_cycles_ce_post_hatari_blitter (unsigned long cycles, uae_u32 v)
        !           896: {
        !           897:        do_cycles_ce_hatari_blitter (cycles);
        !           898: }
        !           899: 
        !           900: void set_x_funcs_hatari_blitter (int flag)
        !           901: {
        !           902:        if ( flag == 0 )
        !           903:        {
        !           904: //fprintf ( stderr , "restore blitter x_funcs\n" );
        !           905:                /* disable blitter, restore functions if needed */
        !           906:                if ( x_do_cycles_hatari_blitter_save )
        !           907:                {
        !           908:                        x_do_cycles                     = x_do_cycles_hatari_blitter_save;
        !           909:                        x_do_cycles_pre                 = x_do_cycles_pre_hatari_blitter_save;
        !           910:                        x_do_cycles_post                = x_do_cycles_post_hatari_blitter_save;
        !           911:                }
        !           912:        }
        !           913:        else
        !           914:        {
        !           915: //fprintf ( stderr , "save/set blitter x_funcs\n" );
        !           916:                /* save current functions */
        !           917:                x_do_cycles_hatari_blitter_save         = x_do_cycles;
        !           918:                x_do_cycles_pre_hatari_blitter_save     = x_do_cycles_pre;
        !           919:                x_do_cycles_post_hatari_blitter_save    = x_do_cycles_post;
        !           920: 
        !           921:                /* set blitter specific functions */
        !           922:                x_do_cycles                             = do_cycles_ce_hatari_blitter;
        !           923:                x_do_cycles_pre                         = do_cycles_ce_hatari_blitter;
        !           924:                x_do_cycles_post                        = do_cycles_ce_post_hatari_blitter;
        !           925:        }
        !           926: }
        !           927: 
        !           928: #endif
        !           929: 
1.1.1.7   root      930: // indirect memory access functions
1.1.1.4   root      931: static void set_x_funcs (void)
                    932: {
1.1.1.7   root      933:        if (currprefs.mmu_model) {
                    934:                if (currprefs.cpu_model == 68060) {
1.1.1.9 ! root      935: 
1.1.1.7   root      936:                        x_prefetch = get_iword_mmu060;
                    937:                        x_get_ilong = get_ilong_mmu060;
                    938:                        x_get_iword = get_iword_mmu060;
                    939:                        x_get_ibyte = get_ibyte_mmu060;
                    940:                        x_next_iword = next_iword_mmu060;
                    941:                        x_next_ilong = next_ilong_mmu060;
                    942:                        x_put_long = put_long_mmu060;
                    943:                        x_put_word = put_word_mmu060;
                    944:                        x_put_byte = put_byte_mmu060;
                    945:                        x_get_long = get_long_mmu060;
                    946:                        x_get_word = get_word_mmu060;
                    947:                        x_get_byte = get_byte_mmu060;
1.1.1.9 ! root      948: 
1.1.1.7   root      949:                } else if (currprefs.cpu_model == 68040) {
1.1.1.9 ! root      950: 
1.1.1.7   root      951:                        x_prefetch = get_iword_mmu040;
                    952:                        x_get_ilong = get_ilong_mmu040;
                    953:                        x_get_iword = get_iword_mmu040;
                    954:                        x_get_ibyte = get_ibyte_mmu040;
                    955:                        x_next_iword = next_iword_mmu040;
                    956:                        x_next_ilong = next_ilong_mmu040;
                    957:                        x_put_long = put_long_mmu040;
                    958:                        x_put_word = put_word_mmu040;
                    959:                        x_put_byte = put_byte_mmu040;
                    960:                        x_get_long = get_long_mmu040;
                    961:                        x_get_word = get_word_mmu040;
                    962:                        x_get_byte = get_byte_mmu040;
1.1.1.9 ! root      963: 
1.1.1.7   root      964:                } else {
1.1.1.9 ! root      965: 
        !           966:                        if (currprefs.cpu_memory_cycle_exact) {
        !           967:                                x_prefetch = get_iword_mmu030c_state;
        !           968:                                x_get_ilong = get_ilong_mmu030c_state;
        !           969:                                x_get_iword = get_iword_mmu030c_state;
        !           970:                                x_get_ibyte = NULL;
        !           971:                                x_next_iword = next_iword_mmu030c_state;
        !           972:                                x_next_ilong = next_ilong_mmu030c_state;
        !           973:                                x_do_cycles = do_cycles;
        !           974:                                x_do_cycles_pre = do_cycles;
        !           975:                                x_do_cycles_post = do_cycles_post;
        !           976:                        } else if (currprefs.cpu_compatible) {
        !           977:                                x_prefetch = get_iword_mmu030c_state;
        !           978:                                x_get_ilong = get_ilong_mmu030c_state;
        !           979:                                x_get_iword = get_iword_mmu030c_state;
        !           980:                                x_get_ibyte = NULL;
        !           981:                                x_next_iword = next_iword_mmu030c_state;
        !           982:                                x_next_ilong = next_ilong_mmu030c_state;
        !           983:                                x_do_cycles = do_cycles;
        !           984:                                x_do_cycles_pre = do_cycles;
        !           985:                                x_do_cycles_post = do_cycles_post;
        !           986:                        } else {
        !           987:                                x_prefetch = get_iword_mmu030;
        !           988:                                x_get_ilong = get_ilong_mmu030;
        !           989:                                x_get_iword = get_iword_mmu030;
        !           990:                                x_get_ibyte = get_ibyte_mmu030;
        !           991:                                x_next_iword = next_iword_mmu030;
        !           992:                                x_next_ilong = next_ilong_mmu030;
        !           993:                        }
1.1.1.7   root      994:                        x_put_long = put_long_mmu030;
                    995:                        x_put_word = put_word_mmu030;
                    996:                        x_put_byte = put_byte_mmu030;
                    997:                        x_get_long = get_long_mmu030;
                    998:                        x_get_word = get_word_mmu030;
                    999:                        x_get_byte = get_byte_mmu030;
1.1.1.9 ! root     1000:                        if (currprefs.cpu_data_cache) {
        !          1001:                                x_put_long = put_long_dc030;
        !          1002:                                x_put_word = put_word_dc030;
        !          1003:                                x_put_byte = put_byte_dc030;
        !          1004:                                x_get_long = get_long_dc030;
        !          1005:                                x_get_word = get_word_dc030;
        !          1006:                                x_get_byte = get_byte_dc030;
        !          1007:                        }
        !          1008: 
1.1.1.7   root     1009:                }
                   1010:                x_do_cycles = do_cycles;
                   1011:                x_do_cycles_pre = do_cycles;
                   1012:                x_do_cycles_post = do_cycles_post;
1.1.1.4   root     1013:        } else if (currprefs.cpu_model < 68020) {
1.1.1.7   root     1014:                // 68000/010
                   1015:                if (currprefs.cpu_cycle_exact) {
                   1016:                        x_prefetch = get_word_ce000_prefetch;
                   1017:                        x_get_ilong = NULL;
                   1018:                        x_get_iword = get_wordi_ce000;
                   1019:                        x_get_ibyte = NULL;
                   1020:                        x_next_iword = NULL;
                   1021:                        x_next_ilong = NULL;
                   1022:                        x_put_long = put_long_ce000;
                   1023:                        x_put_word = put_word_ce000;
                   1024:                        x_put_byte = put_byte_ce000;
                   1025:                        x_get_long = get_long_ce000;
                   1026:                        x_get_word = get_word_ce000;
                   1027:                        x_get_byte = get_byte_ce000;
                   1028:                        x_do_cycles = do_cycles_ce;
                   1029:                        x_do_cycles_pre = do_cycles_ce;
                   1030:                        x_do_cycles_post = do_cycles_ce_post;
1.1.1.8   root     1031:                } else if (currprefs.cpu_memory_cycle_exact) {
                   1032:                        // cpu_memory_cycle_exact + cpu_compatible
                   1033:                        x_prefetch = get_word_000_prefetch;
                   1034:                        x_get_ilong = NULL;
                   1035:                        x_get_iword = get_iiword;
                   1036:                        x_get_ibyte = get_iibyte;
                   1037:                        x_next_iword = NULL;
                   1038:                        x_next_ilong = NULL;
                   1039:                        x_put_long = put_long_ce000;
                   1040:                        x_put_word = put_word_ce000;
                   1041:                        x_put_byte = put_byte_ce000;
                   1042:                        x_get_long = get_long_ce000;
                   1043:                        x_get_word = get_word_ce000;
                   1044:                        x_get_byte = get_byte_ce000;
                   1045:                        x_do_cycles = do_cycles;
                   1046:                        x_do_cycles_pre = do_cycles;
                   1047:                        x_do_cycles_post = do_cycles_post;
1.1.1.7   root     1048:                } else if (currprefs.cpu_compatible) {
1.1.1.8   root     1049:                        // cpu_compatible only
                   1050:                        x_prefetch = get_word_000_prefetch;
1.1.1.7   root     1051:                        x_get_ilong = NULL;
                   1052:                        x_get_iword = get_iiword;
                   1053:                        x_get_ibyte = get_iibyte;
                   1054:                        x_next_iword = NULL;
                   1055:                        x_next_ilong = NULL;
                   1056:                        x_put_long = put_long;
                   1057:                        x_put_word = put_word;
                   1058:                        x_put_byte = put_byte;
                   1059:                        x_get_long = get_long;
                   1060:                        x_get_word = get_word;
                   1061:                        x_get_byte = get_byte;
                   1062:                        x_do_cycles = do_cycles;
                   1063:                        x_do_cycles_pre = do_cycles;
                   1064:                        x_do_cycles_post = do_cycles_post;
                   1065:                } else {
                   1066:                        x_prefetch = NULL;
                   1067:                        x_get_ilong = get_dilong;
                   1068:                        x_get_iword = get_diword;
                   1069:                        x_get_ibyte = get_dibyte;
                   1070:                        x_next_iword = next_diword;
                   1071:                        x_next_ilong = next_dilong;
                   1072:                        x_put_long = put_long;
                   1073:                        x_put_word = put_word;
                   1074:                        x_put_byte = put_byte;
                   1075:                        x_get_long = get_long;
                   1076:                        x_get_word = get_word;
                   1077:                        x_get_byte = get_byte;
                   1078:                        x_do_cycles = do_cycles;
                   1079:                        x_do_cycles_pre = do_cycles;
                   1080:                        x_do_cycles_post = do_cycles_post;
                   1081:                }
                   1082:        } else if (!currprefs.cpu_cycle_exact) {
                   1083:                // 68020+ no ce
1.1.1.8   root     1084:                if (currprefs.cpu_memory_cycle_exact) {
                   1085:                        // cpu_memory_cycle_exact + cpu_compatible
                   1086:                        if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
                   1087:                                x_prefetch = get_word_020_prefetch;
                   1088:                                x_get_ilong = get_long_020_prefetch;
                   1089:                                x_get_iword = get_word_020_prefetch;
                   1090:                                x_get_ibyte = NULL;
                   1091:                                x_next_iword = next_iword_020_prefetch;
                   1092:                                x_next_ilong = next_ilong_020_prefetch;
                   1093:                                x_put_long = put_long_ce020;
                   1094:                                x_put_word = put_word_ce020;
                   1095:                                x_put_byte = put_byte_ce020;
                   1096:                                x_get_long = get_long_ce020;
                   1097:                                x_get_word = get_word_ce020;
                   1098:                                x_get_byte = get_byte_ce020;
                   1099:                                x_do_cycles = do_cycles;
                   1100:                                x_do_cycles_pre = do_cycles;
                   1101:                                x_do_cycles_post = do_cycles_post;
                   1102:                        } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
                   1103:                                x_prefetch = get_word_030_prefetch;
                   1104:                                x_get_ilong = get_long_030_prefetch;
                   1105:                                x_get_iword = get_word_030_prefetch;
                   1106:                                x_get_ibyte = NULL;
                   1107:                                x_next_iword = next_iword_030_prefetch;
                   1108:                                x_next_ilong = next_ilong_030_prefetch;
                   1109:                                x_put_long = put_long_ce030;
                   1110:                                x_put_word = put_word_ce030;
                   1111:                                x_put_byte = put_byte_ce030;
                   1112:                                x_get_long = get_long_ce030;
                   1113:                                x_get_word = get_word_ce030;
                   1114:                                x_get_byte = get_byte_ce030;
                   1115:                                x_do_cycles = do_cycles;
                   1116:                                x_do_cycles_pre = do_cycles;
                   1117:                                x_do_cycles_post = do_cycles_post;
                   1118:                        } else if (currprefs.cpu_model < 68040) {
                   1119:                                // JIT or 68030+ does not have real prefetch only emulation
                   1120:                                x_prefetch = NULL;
                   1121:                                set_x_ifetches();
                   1122:                                x_put_long = put_long;
                   1123:                                x_put_word = put_word;
                   1124:                                x_put_byte = put_byte;
                   1125:                                x_get_long = get_long;
                   1126:                                x_get_word = get_word;
                   1127:                                x_get_byte = get_byte;
                   1128:                                x_do_cycles = do_cycles;
                   1129:                                x_do_cycles_pre = do_cycles;
                   1130:                                x_do_cycles_post = do_cycles_post;
                   1131:                        } else {
                   1132:                                // 68040+ (same as below)
                   1133:                                x_prefetch = NULL;
                   1134:                                x_get_ilong = get_ilong_cache_040;
                   1135:                                x_get_iword = get_iword_cache_040;
                   1136:                                x_get_ibyte = NULL;
                   1137:                                x_next_iword = next_iword_cache040;
                   1138:                                x_next_ilong = next_ilong_cache040;
1.1.1.9 ! root     1139:                                if (currprefs.cpu_data_cache) {
        !          1140:                                        x_put_long = put_long_cache_040;
        !          1141:                                        x_put_word = put_word_cache_040;
        !          1142:                                        x_put_byte = put_byte_cache_040;
        !          1143:                                        x_get_long = get_long_cache_040;
        !          1144:                                        x_get_word = get_word_cache_040;
        !          1145:                                        x_get_byte = get_byte_cache_040;
        !          1146:                                } else {
        !          1147:                                        x_get_byte = mem_access_delay_byte_read_c040;
        !          1148:                                        x_get_word = mem_access_delay_word_read_c040;
        !          1149:                                        x_get_long = mem_access_delay_long_read_c040;
        !          1150:                                        x_put_byte = mem_access_delay_byte_write_c040;
        !          1151:                                        x_put_word = mem_access_delay_word_write_c040;
        !          1152:                                        x_put_long = mem_access_delay_long_write_c040;
        !          1153:                                }
1.1.1.8   root     1154:                                x_do_cycles = do_cycles;
                   1155:                                x_do_cycles_pre = do_cycles;
                   1156:                                x_do_cycles_post = do_cycles_post;
                   1157:                        }
                   1158:                } else if (currprefs.cpu_compatible) {
                   1159:                        // cpu_compatible only
1.1.1.7   root     1160:                        if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
1.1.1.8   root     1161:                                x_prefetch = get_word_020_prefetch;
1.1.1.7   root     1162:                                x_get_ilong = get_long_020_prefetch;
                   1163:                                x_get_iword = get_word_020_prefetch;
                   1164:                                x_get_ibyte = NULL;
                   1165:                                x_next_iword = next_iword_020_prefetch;
                   1166:                                x_next_ilong = next_ilong_020_prefetch;
                   1167:                                x_put_long = put_long;
                   1168:                                x_put_word = put_word;
                   1169:                                x_put_byte = put_byte;
                   1170:                                x_get_long = get_long;
                   1171:                                x_get_word = get_word;
                   1172:                                x_get_byte = get_byte;
                   1173:                                x_do_cycles = do_cycles;
                   1174:                                x_do_cycles_pre = do_cycles;
                   1175:                                x_do_cycles_post = do_cycles_post;
                   1176:                        } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
1.1.1.9 ! root     1177:                                x_prefetch = get_word_030_prefetch;
1.1.1.7   root     1178:                                x_get_ilong = get_long_030_prefetch;
                   1179:                                x_get_iword = get_word_030_prefetch;
                   1180:                                x_get_ibyte = NULL;
                   1181:                                x_next_iword = next_iword_030_prefetch;
                   1182:                                x_next_ilong = next_ilong_030_prefetch;
1.1.1.9 ! root     1183:                                x_put_long = put_long_030;
        !          1184:                                x_put_word = put_word_030;
        !          1185:                                x_put_byte = put_byte_030;
        !          1186:                                x_get_long = get_long_030;
        !          1187:                                x_get_word = get_word_030;
        !          1188:                                x_get_byte = get_byte_030;
1.1.1.7   root     1189:                                x_do_cycles = do_cycles;
                   1190:                                x_do_cycles_pre = do_cycles;
                   1191:                                x_do_cycles_post = do_cycles_post;
                   1192:                        } else if (currprefs.cpu_model < 68040) {
                   1193:                                // JIT or 68030+ does not have real prefetch only emulation
                   1194:                                x_prefetch = NULL;
                   1195:                                set_x_ifetches();
                   1196:                                x_put_long = put_long;
                   1197:                                x_put_word = put_word;
                   1198:                                x_put_byte = put_byte;
                   1199:                                x_get_long = get_long;
                   1200:                                x_get_word = get_word;
                   1201:                                x_get_byte = get_byte;
                   1202:                                x_do_cycles = do_cycles;
                   1203:                                x_do_cycles_pre = do_cycles;
                   1204:                                x_do_cycles_post = do_cycles_post;
                   1205:                        } else {
                   1206:                                x_prefetch = NULL;
                   1207:                                x_get_ilong = get_ilong_cache_040;
                   1208:                                x_get_iword = get_iword_cache_040;
                   1209:                                x_get_ibyte = NULL;
                   1210:                                x_next_iword = next_iword_cache040;
                   1211:                                x_next_ilong = next_ilong_cache040;
1.1.1.9 ! root     1212:                                if (currprefs.cpu_data_cache) {
        !          1213:                                        x_put_long = put_long_cache_040;
        !          1214:                                        x_put_word = put_word_cache_040;
        !          1215:                                        x_put_byte = put_byte_cache_040;
        !          1216:                                        x_get_long = get_long_cache_040;
        !          1217:                                        x_get_word = get_word_cache_040;
        !          1218:                                        x_get_byte = get_byte_cache_040;
        !          1219:                                } else {
        !          1220:                                        x_put_long = put_long;
        !          1221:                                        x_put_word = put_word;
        !          1222:                                        x_put_byte = put_byte;
        !          1223:                                        x_get_long = get_long;
        !          1224:                                        x_get_word = get_word;
        !          1225:                                        x_get_byte = get_byte;
        !          1226:                                }
1.1.1.7   root     1227:                                x_do_cycles = do_cycles;
                   1228:                                x_do_cycles_pre = do_cycles;
                   1229:                                x_do_cycles_post = do_cycles_post;
                   1230:                        }
                   1231:                } else {
                   1232:                        x_prefetch = NULL;
                   1233:                        set_x_ifetches();
1.1.1.8   root     1234:                        if (currprefs.cachesize) {
                   1235:                                x_put_long = put_long_jit;
                   1236:                                x_put_word = put_word_jit;
                   1237:                                x_put_byte = put_byte_jit;
                   1238:                                x_get_long = get_long_jit;
                   1239:                                x_get_word = get_word_jit;
                   1240:                                x_get_byte = get_byte_jit;
                   1241:                        } else {
                   1242:                                x_put_long = put_long;
                   1243:                                x_put_word = put_word;
                   1244:                                x_put_byte = put_byte;
                   1245:                                x_get_long = get_long;
                   1246:                                x_get_word = get_word;
                   1247:                                x_get_byte = get_byte;
                   1248:                        }
1.1.1.7   root     1249:                        x_do_cycles = do_cycles;
                   1250:                        x_do_cycles_pre = do_cycles;
                   1251:                        x_do_cycles_post = do_cycles_post;
                   1252:                }
                   1253:                // 68020+ cycle exact
1.1.1.4   root     1254:        } else if (currprefs.cpu_model == 68020) {
                   1255:                x_prefetch = get_word_ce020_prefetch;
1.1.1.7   root     1256:                x_get_ilong = get_long_ce020_prefetch;
                   1257:                x_get_iword = get_word_ce020_prefetch;
                   1258:                x_get_ibyte = NULL;
1.1.1.4   root     1259:                x_next_iword = next_iword_020ce;
                   1260:                x_next_ilong = next_ilong_020ce;
                   1261:                x_put_long = put_long_ce020;
                   1262:                x_put_word = put_word_ce020;
                   1263:                x_put_byte = put_byte_ce020;
                   1264:                x_get_long = get_long_ce020;
                   1265:                x_get_word = get_word_ce020;
                   1266:                x_get_byte = get_byte_ce020;
1.1.1.7   root     1267: #ifndef WINUAE_FOR_HATARI
                   1268:                x_do_cycles = do_cycles_ce020;
                   1269:                x_do_cycles_pre = do_cycles_ce020;
                   1270:                x_do_cycles_post = do_cycles_ce020_post;
                   1271: #else
                   1272:                x_do_cycles = do_cycles_ce020_long;
                   1273:                x_do_cycles_pre = do_cycles_ce020_long;
                   1274:                x_do_cycles_post = do_cycles_ce020_post;
                   1275: #endif
                   1276:        } else if (currprefs.cpu_model == 68030) {
1.1.1.4   root     1277:                x_prefetch = get_word_ce030_prefetch;
1.1.1.7   root     1278:                x_get_ilong = get_long_ce030_prefetch;
                   1279:                x_get_iword = get_word_ce030_prefetch;
                   1280:                x_get_ibyte = NULL;
1.1.1.4   root     1281:                x_next_iword = next_iword_030ce;
                   1282:                x_next_ilong = next_ilong_030ce;
1.1.1.9 ! root     1283:                if (currprefs.cpu_data_cache) {
        !          1284:                        x_put_long = put_long_dc030;
        !          1285:                        x_put_word = put_word_dc030;
        !          1286:                        x_put_byte = put_byte_dc030;
        !          1287:                        x_get_long = get_long_dc030;
        !          1288:                        x_get_word = get_word_dc030;
        !          1289:                        x_get_byte = get_byte_dc030;
        !          1290:                } else {
        !          1291:                        x_put_long = put_long_ce030;
        !          1292:                        x_put_word = put_word_ce030;
        !          1293:                        x_put_byte = put_byte_ce030;
        !          1294:                        x_get_long = get_long_ce030;
        !          1295:                        x_get_word = get_word_ce030;
        !          1296:                        x_get_byte = get_byte_ce030;
        !          1297:                }
1.1.1.7   root     1298: #ifndef WINUAE_FOR_HATARI
                   1299:                x_do_cycles = do_cycles_ce020;
                   1300:                x_do_cycles_pre = do_cycles_ce020;
                   1301:                x_do_cycles_post = do_cycles_ce020_post;
                   1302: #else
                   1303:                x_do_cycles = do_cycles_ce020_long;
                   1304:                x_do_cycles_pre = do_cycles_ce020_long;
                   1305:                x_do_cycles_post = do_cycles_ce020_post;
                   1306: #endif
                   1307:        } else if (currprefs.cpu_model >= 68040) {
                   1308:                x_prefetch = NULL;
                   1309:                x_get_ilong = get_ilong_cache_040;
                   1310:                x_get_iword = get_iword_cache_040;
                   1311:                x_get_ibyte = NULL;
                   1312:                x_next_iword = next_iword_cache040;
                   1313:                x_next_ilong = next_ilong_cache040;
1.1.1.9 ! root     1314:                if (currprefs.cpu_data_cache) {
        !          1315:                        x_put_long = put_long_cache_040;
        !          1316:                        x_put_word = put_word_cache_040;
        !          1317:                        x_put_byte = put_byte_cache_040;
        !          1318:                        x_get_long = get_long_cache_040;
        !          1319:                        x_get_word = get_word_cache_040;
        !          1320:                        x_get_byte = get_byte_cache_040;
        !          1321:                } else {
        !          1322:                        x_get_byte = mem_access_delay_byte_read_c040;
        !          1323:                        x_get_word = mem_access_delay_word_read_c040;
        !          1324:                        x_get_long = mem_access_delay_long_read_c040;
        !          1325:                        x_put_byte = mem_access_delay_byte_write_c040;
        !          1326:                        x_put_word = mem_access_delay_word_write_c040;
        !          1327:                        x_put_long = mem_access_delay_long_write_c040;
        !          1328:                }
1.1.1.7   root     1329: #ifndef WINUAE_FOR_HATARI
                   1330:                x_do_cycles = do_cycles_ce020;
                   1331:                x_do_cycles_pre = do_cycles_ce020;
                   1332:                x_do_cycles_post = do_cycles_ce020_post;
                   1333: #else
                   1334:                x_do_cycles = do_cycles_ce020_long;
                   1335:                x_do_cycles_pre = do_cycles_ce020_long;
                   1336:                x_do_cycles_post = do_cycles_ce020_post;
                   1337: #endif
                   1338:        }
                   1339:        x2_prefetch = x_prefetch;
                   1340:        x2_get_ilong = x_get_ilong;
                   1341:        x2_get_iword = x_get_iword;
                   1342:        x2_get_ibyte = x_get_ibyte;
                   1343:        x2_next_iword = x_next_iword;
                   1344:        x2_next_ilong = x_next_ilong;
                   1345:        x2_put_long = x_put_long;
                   1346:        x2_put_word = x_put_word;
                   1347:        x2_put_byte = x_put_byte;
                   1348:        x2_get_long = x_get_long;
                   1349:        x2_get_word = x_get_word;
                   1350:        x2_get_byte = x_get_byte;
                   1351:        x2_do_cycles = x_do_cycles;
                   1352:        x2_do_cycles_pre = x_do_cycles_pre;
                   1353:        x2_do_cycles_post = x_do_cycles_post;
                   1354: 
                   1355:        if (cpu_tracer > 0) {
                   1356:                x_prefetch = cputracefunc_x_prefetch;
                   1357:                x_get_ilong = cputracefunc_x_get_ilong;
                   1358:                x_get_iword = cputracefunc_x_get_iword;
                   1359:                x_get_ibyte = cputracefunc_x_get_ibyte;
                   1360:                x_next_iword = cputracefunc_x_next_iword;
                   1361:                x_next_ilong = cputracefunc_x_next_ilong;
                   1362:                x_put_long = cputracefunc_x_put_long;
                   1363:                x_put_word = cputracefunc_x_put_word;
                   1364:                x_put_byte = cputracefunc_x_put_byte;
                   1365:                x_get_long = cputracefunc_x_get_long;
                   1366:                x_get_word = cputracefunc_x_get_word;
                   1367:                x_get_byte = cputracefunc_x_get_byte;
                   1368:                x_do_cycles = cputracefunc_x_do_cycles;
                   1369:                x_do_cycles_pre = cputracefunc_x_do_cycles_pre;
                   1370:                x_do_cycles_post = cputracefunc_x_do_cycles_post;
                   1371:        } else if (cpu_tracer < 0) {
                   1372:                if (!check_trace ()) {
                   1373:                        x_prefetch = cputracefunc2_x_prefetch;
                   1374:                        x_get_ilong = cputracefunc2_x_get_ilong;
                   1375:                        x_get_iword = cputracefunc2_x_get_iword;
                   1376:                        x_get_ibyte = cputracefunc2_x_get_ibyte;
                   1377:                        x_next_iword = cputracefunc2_x_next_iword;
                   1378:                        x_next_ilong = cputracefunc2_x_next_ilong;
                   1379:                        x_put_long = cputracefunc2_x_put_long;
                   1380:                        x_put_word = cputracefunc2_x_put_word;
                   1381:                        x_put_byte = cputracefunc2_x_put_byte;
                   1382:                        x_get_long = cputracefunc2_x_get_long;
                   1383:                        x_get_word = cputracefunc2_x_get_word;
                   1384:                        x_get_byte = cputracefunc2_x_get_byte;
                   1385:                        x_do_cycles = cputracefunc2_x_do_cycles;
                   1386:                        x_do_cycles_pre = cputracefunc2_x_do_cycles_pre;
                   1387:                        x_do_cycles_post = cputracefunc2_x_do_cycles_post;
                   1388:                }
                   1389:        }
                   1390: 
                   1391:        set_x_cp_funcs();
                   1392:        mmu_set_funcs();
                   1393:        mmu030_set_funcs();
                   1394: 
1.1.1.9 ! root     1395:        dcache_lput = put_long;
        !          1396:        dcache_wput = put_word;
        !          1397:        dcache_bput = put_byte;
        !          1398:        dcache_lget = get_long;
        !          1399:        dcache_wget = get_word;
        !          1400:        dcache_bget = get_byte;
        !          1401:        dcache_check = dcache_check_nommu;
        !          1402: 
        !          1403:        icache_fetch = get_longi;
        !          1404:        if (currprefs.cpu_cycle_exact) {
        !          1405:                icache_fetch = mem_access_delay_longi_read_ce020;
        !          1406:        }
        !          1407:        if (currprefs.cpu_model >= 68040 && currprefs.cpu_memory_cycle_exact) {
        !          1408:                icache_fetch = mem_access_delay_longi_read_c040;
        !          1409:                dcache_bget = mem_access_delay_byte_read_c040;
        !          1410:                dcache_wget = mem_access_delay_word_read_c040;
        !          1411:                dcache_lget = mem_access_delay_long_read_c040;
        !          1412:                dcache_bput = mem_access_delay_byte_write_c040;
        !          1413:                dcache_wput = mem_access_delay_word_write_c040;
        !          1414:                dcache_lput = mem_access_delay_long_write_c040;
        !          1415:        }
        !          1416: 
        !          1417:        if (currprefs.cpu_model == 68030) {
        !          1418: 
        !          1419:                if (currprefs.cpu_data_cache) {
        !          1420:                        read_data_030_bget = read_dcache030_mmu_bget;
        !          1421:                        read_data_030_wget = read_dcache030_mmu_wget;
        !          1422:                        read_data_030_lget = read_dcache030_mmu_lget;
        !          1423:                        write_data_030_bput = write_dcache030_mmu_bput;
        !          1424:                        write_data_030_wput = write_dcache030_mmu_wput;
        !          1425:                        write_data_030_lput = write_dcache030_mmu_lput;
        !          1426: 
        !          1427:                        read_data_030_fc_bget = read_dcache030_bget;
        !          1428:                        read_data_030_fc_wget = read_dcache030_wget;
        !          1429:                        read_data_030_fc_lget = read_dcache030_lget;
        !          1430:                        write_data_030_fc_bput = write_dcache030_bput;
        !          1431:                        write_data_030_fc_wput = write_dcache030_wput;
        !          1432:                        write_data_030_fc_lput = write_dcache030_lput;
        !          1433:                } else {
        !          1434:                        read_data_030_bget = dcache_bget;
        !          1435:                        read_data_030_wget = dcache_wget;
        !          1436:                        read_data_030_lget = dcache_lget;
        !          1437:                        write_data_030_bput = dcache_bput;
        !          1438:                        write_data_030_wput = dcache_wput;
        !          1439:                        write_data_030_lput = dcache_lput;
        !          1440: 
        !          1441:                        read_data_030_fc_bget = mmu030_get_fc_byte;
        !          1442:                        read_data_030_fc_wget = mmu030_get_fc_word;
        !          1443:                        read_data_030_fc_lget = mmu030_get_fc_long;
        !          1444:                        write_data_030_fc_bput = mmu030_put_fc_byte;
        !          1445:                        write_data_030_fc_wput = mmu030_put_fc_word;
        !          1446:                        write_data_030_fc_lput = mmu030_put_fc_long;
        !          1447:                }
        !          1448: 
        !          1449:                if (currprefs.mmu_model) {
        !          1450:                        if (currprefs.cpu_compatible) {
        !          1451:                                icache_fetch = uae_mmu030_get_ilong_fc;
        !          1452:                        } else {
        !          1453:                                icache_fetch = uae_mmu030_get_ilong;
        !          1454:                        }
        !          1455:                        dcache_lput = uae_mmu030_put_long;
        !          1456:                        dcache_wput = uae_mmu030_put_word;
        !          1457:                        dcache_bput = uae_mmu030_put_byte;
        !          1458:                        dcache_lget = uae_mmu030_get_long;
        !          1459:                        dcache_wget = uae_mmu030_get_word;
        !          1460:                        dcache_bget = uae_mmu030_get_byte;
        !          1461:                        if (currprefs.cpu_data_cache) {
        !          1462:                                read_data_030_bget = read_dcache030_mmu_bget;
        !          1463:                                read_data_030_wget = read_dcache030_mmu_wget;
        !          1464:                                read_data_030_lget = read_dcache030_mmu_lget;
        !          1465:                                write_data_030_bput = write_dcache030_mmu_bput;
        !          1466:                                write_data_030_wput = write_dcache030_mmu_wput;
        !          1467:                                write_data_030_lput = write_dcache030_mmu_lput;
        !          1468:                                dcache_lput = uae_mmu030_put_long_fc;
        !          1469:                                dcache_wput = uae_mmu030_put_word_fc;
        !          1470:                                dcache_bput = uae_mmu030_put_byte_fc;
        !          1471:                                dcache_lget = uae_mmu030_get_long_fc;
        !          1472:                                dcache_wget = uae_mmu030_get_word_fc;
        !          1473:                                dcache_bget = uae_mmu030_get_byte_fc;
        !          1474:                                dcache_check = uae_mmu030_check_fc;
        !          1475:                        } else {
        !          1476:                                read_data_030_bget = uae_mmu030_get_byte;
        !          1477:                                read_data_030_wget = uae_mmu030_get_word;
        !          1478:                                read_data_030_lget = uae_mmu030_get_long;
        !          1479:                                write_data_030_bput = uae_mmu030_put_byte;
        !          1480:                                write_data_030_wput = uae_mmu030_put_word;
        !          1481:                                write_data_030_lput = uae_mmu030_put_long;
        !          1482:                        }
        !          1483:                } else if (currprefs.cpu_memory_cycle_exact) {
        !          1484:                        icache_fetch = mem_access_delay_longi_read_ce020;
        !          1485:                        dcache_lget = mem_access_delay_long_read_ce020;
        !          1486:                        dcache_wget = mem_access_delay_word_read_ce020;
        !          1487:                        dcache_bget = mem_access_delay_byte_read_ce020;
        !          1488:                        if (currprefs.cpu_data_cache) {
        !          1489:                                dcache_lput = mem_access_delay_long_write_ce030_cicheck;
        !          1490:                                dcache_wput = mem_access_delay_word_write_ce030_cicheck;
        !          1491:                                dcache_bput = mem_access_delay_byte_write_ce030_cicheck;
        !          1492:                        } else {
        !          1493:                                dcache_lput = mem_access_delay_long_write_ce020;
        !          1494:                                dcache_wput = mem_access_delay_word_write_ce020;
        !          1495:                                dcache_bput = mem_access_delay_byte_write_ce020;
        !          1496:                        }
        !          1497:                } else if (currprefs.cpu_data_cache) {
        !          1498:                        dcache_lput = put_long030_cicheck;
        !          1499:                        dcache_wput = put_word030_cicheck;
        !          1500:                        dcache_bput = put_byte030_cicheck;
        !          1501:                        if (currprefs.cpu_data_cache) {
        !          1502:                                dcache_lput = mem_access_delay_long_write_ce030_cicheck;
        !          1503:                                dcache_wput = mem_access_delay_word_write_ce030_cicheck;
        !          1504:                                dcache_bput = mem_access_delay_byte_write_ce030_cicheck;
        !          1505:                        } else {
        !          1506:                                dcache_lput = mem_access_delay_long_write_ce020;
        !          1507:                                dcache_wput = mem_access_delay_word_write_ce020;
        !          1508:                                dcache_bput = mem_access_delay_byte_write_ce020;
        !          1509:                        }
        !          1510:                } else if (currprefs.cpu_data_cache) {
        !          1511:                        dcache_lput = put_long030_cicheck;
        !          1512:                        dcache_wput = put_word030_cicheck;
        !          1513:                        dcache_bput = put_byte030_cicheck;
        !          1514:                }
        !          1515:        }
1.1.1.7   root     1516: }
                   1517: 
                   1518: bool can_cpu_tracer (void)
                   1519: {
1.1.1.8   root     1520:        return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_memory_cycle_exact;
1.1.1.7   root     1521: }
                   1522: 
                   1523: bool is_cpu_tracer (void)
                   1524: {
                   1525:        return cpu_tracer > 0;
                   1526: }
                   1527: bool set_cpu_tracer (bool state)
                   1528: {
                   1529:        if (cpu_tracer < 0)
                   1530:                return false;
                   1531:        int old = cpu_tracer;
                   1532: #ifndef WINUAE_FOR_HATARI
                   1533:        if (input_record)
                   1534:                state = true;
                   1535: #endif
                   1536:        cpu_tracer = 0;
                   1537:        if (state && can_cpu_tracer ()) {
                   1538:                cpu_tracer = 1;
                   1539:                set_x_funcs ();
                   1540:                if (old != cpu_tracer)
                   1541:                        write_log (_T("CPU tracer enabled\n"));
1.1.1.4   root     1542:        }
1.1.1.7   root     1543:        if (old > 0 && state == false) {
                   1544:                set_x_funcs ();
                   1545:                write_log (_T("CPU tracer disabled\n"));
                   1546:        }
                   1547:        return is_cpu_tracer ();
1.1.1.4   root     1548: }
                   1549: 
1.1.1.9 ! root     1550: void invalidate_cpu_data_caches(void)
        !          1551: {
        !          1552:        int i,j;
        !          1553: 
        !          1554:        if (currprefs.cpu_model == 68030) {
        !          1555:                for (i = 0; i < CACHELINES030; i++) {
        !          1556:                        dcaches030[i].valid[0] = 0;
        !          1557:                        dcaches030[i].valid[1] = 0;
        !          1558:                        dcaches030[i].valid[2] = 0;
        !          1559:                        dcaches030[i].valid[3] = 0;
        !          1560:                }
        !          1561:        } else if (currprefs.cpu_model >= 68040) {
        !          1562:                dcachelinecnt = 0;
        !          1563:                for (i = 0; i < CACHESETS060; i++) {
        !          1564:                        for (j = 0; j < CACHELINES040; j++) {
        !          1565:                                dcaches040[i].valid[j] = false;
        !          1566:                        }
        !          1567:                }
        !          1568:        }
        !          1569: }
        !          1570: 
1.1.1.7   root     1571: void flush_cpu_caches(bool force)
1.1.1.4   root     1572: {
1.1.1.8   root     1573:        bool doflush = currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact;
1.1.1.9 ! root     1574:        int i,j;
1.1.1.4   root     1575: 
                   1576:        if (currprefs.cpu_model == 68020) {
1.1.1.9 ! root     1577:                if ((regs.cacr & 0x08) || force) { // clear instr cache
1.1.1.4   root     1578:                        for (i = 0; i < CACHELINES020; i++)
                   1579:                                caches020[i].valid = 0;
1.1.1.7   root     1580:                        regs.cacr &= ~0x08;
1.1.1.4   root     1581:                }
                   1582:                if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7   root     1583:                        caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
1.1.1.4   root     1584:                        regs.cacr &= ~0x04;
                   1585:                }
                   1586:        } else if (currprefs.cpu_model == 68030) {
1.1.1.9 ! root     1587:                if ((regs.cacr & 0x08) || force) { // clear instr cache
1.1.1.7   root     1588:                        if (doflush) {
                   1589:                                for (i = 0; i < CACHELINES030; i++) {
                   1590:                                        icaches030[i].valid[0] = 0;
                   1591:                                        icaches030[i].valid[1] = 0;
                   1592:                                        icaches030[i].valid[2] = 0;
                   1593:                                        icaches030[i].valid[3] = 0;
                   1594:                                }
1.1.1.4   root     1595:                        }
1.1.1.7   root     1596:                        regs.cacr &= ~0x08;
1.1.1.4   root     1597:                }
                   1598:                if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7   root     1599:                        icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4   root     1600:                        regs.cacr &= ~0x04;
                   1601:                }
1.1.1.9 ! root     1602:                if ((regs.cacr & 0x800) || force) { // clear data cache
1.1.1.7   root     1603:                        if (doflush) {
                   1604:                                for (i = 0; i < CACHELINES030; i++) {
                   1605:                                        dcaches030[i].valid[0] = 0;
                   1606:                                        dcaches030[i].valid[1] = 0;
                   1607:                                        dcaches030[i].valid[2] = 0;
                   1608:                                        dcaches030[i].valid[3] = 0;
                   1609:                                }
1.1.1.4   root     1610:                        }
                   1611:                        regs.cacr &= ~0x800;
                   1612:                }
                   1613:                if (regs.cacr & 0x400) { // clear entry in data cache
1.1.1.7   root     1614:                        dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4   root     1615:                        regs.cacr &= ~0x400;
                   1616:                }
1.1.1.7   root     1617:        } else if (currprefs.cpu_model >= 68040) {
1.1.1.9 ! root     1618:                if (doflush && force) {
        !          1619:                        mmu_flush_cache();
        !          1620:                        icachelinecnt = 0;
        !          1621:                        icachehalfline = 0;
        !          1622:                        for (i = 0; i < CACHESETS060; i++) {
        !          1623:                                for (j = 0; j < CACHELINES040; j++) {
        !          1624:                                        icaches040[i].valid[j] = false;
        !          1625:                                }
        !          1626:                        }
        !          1627:                }
        !          1628:        }
        !          1629: }
        !          1630: 
        !          1631: #if VALIDATE_68040_DATACACHE > 1
        !          1632: static void validate_dcache040(void)
        !          1633: {
        !          1634:        int i,j,k;
        !          1635: 
        !          1636:        for (i = 0; i < cachedsets04060; i++) {
        !          1637:                struct cache040 *c = &dcaches040[i];
        !          1638:                for (j = 0; j < CACHELINES040; j++) {
        !          1639:                        if (c->valid[j]) {
        !          1640:                                uae_u32 addr = (c->tag[j] & cachedtag04060mask) | (i << 4);
        !          1641:                                if (addr < 0x200000 || (addr >= 0xd80000 && addr < 0xe00000) || (addr >= 0xe80000 && addr < 0xf00000) || (addr >= 0xa00000 && addr < 0xc00000)) {
        !          1642:                                        write_log(_T("Chip RAM or IO address cached! %08x\n"), addr);
        !          1643:                                }
        !          1644:                                for (k = 0; k < 4; k++) {
        !          1645:                                        if (!c->dirty[j][k]) {
        !          1646:                                                uae_u32 v = get_long(addr + k * 4);
        !          1647:                                                if (v != c->data[j][k]) {
        !          1648:                                                        write_log(_T("Address %08x data cache mismatch %08x != %08x\n"), addr, v, c->data[j][k]);
        !          1649:                                                }
        !          1650:                                        }
        !          1651:                                }
        !          1652:                        }
        !          1653:                }
        !          1654:        }
        !          1655: }
        !          1656: #endif
        !          1657: 
        !          1658: static void dcache040_push_line(int index, int line, bool writethrough, bool invalidate)
        !          1659: {
        !          1660:        struct cache040 *c = &dcaches040[index];
        !          1661:        int i;
        !          1662: 
        !          1663: #if VALIDATE_68040_DATACACHE
        !          1664:        if (!c->valid[line]) {
        !          1665:                write_log("dcache040_push_line pushing invalid line!\n");
        !          1666:        }
        !          1667: #endif
        !          1668:        if (c->gdirty[line]) {
        !          1669:                uae_u32 addr = (c->tag[line] & cachedtag04060mask) | (index << 4);
        !          1670:                for (i = 0; i < 4; i++) {
        !          1671:                        if (c->dirty[line][i] || (!writethrough && currprefs.cpu_model == 68060)) {
        !          1672:                                dcache_lput(addr + i * 4, c->data[line][i]);
        !          1673:                                c->dirty[line][i] = false;
1.1.1.4   root     1674:                        }
                   1675:                }
1.1.1.9 ! root     1676:                c->gdirty[line] = false;
1.1.1.4   root     1677:        }
1.1.1.9 ! root     1678:        if (invalidate)
        !          1679:                c->valid[line] = false;
        !          1680: 
        !          1681: #if VALIDATE_68040_DATACACHE > 1
        !          1682:        validate_dcache040();
        !          1683: #endif
1.1.1.4   root     1684: }
                   1685: 
1.1.1.7   root     1686: void flush_cpu_caches_040(uae_u16 opcode)
1.1.1.4   root     1687: {
1.1.1.9 ! root     1688:        // 0 (1) = data, 1 (2) = instruction
1.1.1.7   root     1689:        int cache = (opcode >> 6) & 3;
1.1.1.9 ! root     1690:        int scope = (opcode >> 3) & 3;
        !          1691:        int areg = opcode & 7;
        !          1692:        uaecptr addr = m68k_areg(regs, areg);
        !          1693:        bool push = (opcode & 0x20) != 0;
        !          1694:        bool pushinv = (regs.cacr & 0x01000000) == 0; // 68060 DPI
        !          1695:        int i;
        !          1696:        uae_u32 k, j;
        !          1697: 
        !          1698: #if VALIDATE_68040_DATACACHE
        !          1699:        write_log(_T("push %d %d %d %08x %d %d\n"), cache, scope, areg, addr, push, pushinv);
        !          1700: #endif
        !          1701: 
        !          1702:        if (cache & 2)
        !          1703:                regs.prefetch020addr = 0xffffffff;
        !          1704:        for (k = 0; k < 2; k++) {
        !          1705:                if (cache & (1 << k)) {
        !          1706:                        if (scope == 3) {
        !          1707:                                // all
        !          1708:                                if (!k) {
        !          1709:                                        // data
        !          1710:                                        for (i = 0; i < cachedsets04060; i++) {
        !          1711:                                                struct cache040 *c = &dcaches040[i];
        !          1712:                                                for (j = 0; j < CACHELINES040; j++) {
        !          1713:                                                        if (c->valid[j]) {
        !          1714:                                                                if (push) {
        !          1715:                                                                        dcache040_push_line(i, j, false, pushinv);
        !          1716:                                                                } else {
        !          1717:                                                                        c->valid[j] = false;
        !          1718:                                                                }
        !          1719:                                                        }
        !          1720:                                                }
        !          1721:                                        }
        !          1722:                                        dcachelinecnt = 0;
        !          1723:                                } else {
        !          1724:                                        // instruction
        !          1725:                                        flush_cpu_caches(true);
        !          1726:                                }
        !          1727:                        } else {
        !          1728:                                uae_u32 pagesize;
        !          1729:                                if (scope == 2) {
        !          1730:                                        // page
        !          1731:                                        pagesize = mmu_pagesize_8k ? 8192 : 4096;
        !          1732:                                } else {
        !          1733:                                        // line
        !          1734:                                        pagesize = 16;
        !          1735:                                }
        !          1736:                                addr &= ~(pagesize - 1);
        !          1737:                                for (j = 0; j < pagesize; j += 16, addr += 16) {
        !          1738:                                        int index;
        !          1739:                                        uae_u32 tag;
        !          1740:                                        uae_u32 tagmask;
        !          1741:                                        struct cache040 *c;
        !          1742:                                        if (k) {
        !          1743:                                                tagmask = cacheitag04060mask;
        !          1744:                                                index = (addr >> 4) & cacheisets04060mask;
        !          1745:                                                c = &icaches040[index];
        !          1746:                                        } else {
        !          1747:                                                tagmask = cachedtag04060mask;
        !          1748:                                                index = (addr >> 4) & cachedsets04060mask;
        !          1749:                                                c = &dcaches040[index];
        !          1750:                                        }
        !          1751:                                        tag = addr & tagmask;
        !          1752:                                        for (i = 0; i < CACHELINES040; i++) {
        !          1753:                                                if (c->valid[i] && c->tag[i] == tag) {
        !          1754:                                                        if (push) {
        !          1755:                                                                dcache040_push_line(index, i, false, pushinv);
        !          1756:                                                        } else {
        !          1757:                                                                c->valid[i] = false;
        !          1758:                                                        }
        !          1759:                                                }
        !          1760:                                        }
        !          1761:                                }
        !          1762:                        }
        !          1763:                }
        !          1764:        }
        !          1765:        mmu_flush_cache();
1.1.1.4   root     1766: }
                   1767: 
1.1.1.7   root     1768: void set_cpu_caches (bool flush)
1.1.1.4   root     1769: {
1.1.1.7   root     1770:        regs.prefetch020addr = 0xffffffff;
                   1771:        regs.cacheholdingaddr020 = 0xffffffff;
1.1.1.9 ! root     1772:        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
        !          1773: 
        !          1774:        // 68060 FIC 1/2 instruction cache
        !          1775:        cacheisets04060 = currprefs.cpu_model == 68060 && !(regs.cacr & 0x00002000) ? CACHESETS060 : CACHESETS040;
        !          1776:        cacheisets04060mask = cacheisets04060 - 1;
        !          1777:        cacheitag04060mask = ~((cacheisets04060 << 4) - 1);
        !          1778:        // 68060 FOC 1/2 data cache
        !          1779:        cachedsets04060 = currprefs.cpu_model == 68060 && !(regs.cacr & 0x08000000) ? CACHESETS060 : CACHESETS040;
        !          1780:        cachedsets04060mask = cachedsets04060 - 1;
        !          1781:        cachedtag04060mask = ~((cachedsets04060 << 4) - 1);
        !          1782:        cache_lastline = 0;
1.1.1.4   root     1783: 
1.1.1.7   root     1784: #ifdef JIT
                   1785:        if (currprefs.cachesize) {
                   1786:                if (currprefs.cpu_model < 68040) {
                   1787:                        set_cache_state (regs.cacr & 1);
                   1788:                        if (regs.cacr & 0x08) {
1.1.1.9 ! root     1789:                                flush_icache (3);
1.1.1.7   root     1790:                        }
                   1791:                } else {
                   1792:                        set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
                   1793:                }
                   1794:        }
                   1795: #endif
                   1796:        flush_cpu_caches(flush);
                   1797: }
                   1798: 
                   1799: STATIC_INLINE void count_instr (unsigned int opcode)
                   1800: {
                   1801: }
                   1802: 
                   1803: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
                   1804: {
                   1805:        op_illg (opcode);
                   1806:        return 4;
                   1807: }
                   1808: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
                   1809: {
                   1810:        if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
                   1811:                op_illg (opcode);
                   1812:        else
                   1813:                op_unimpl (opcode);
                   1814:        return 4;
                   1815: }
                   1816: 
1.1.1.9 ! root     1817: // generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mmu+more compatible, mmu+mc+ce
        !          1818: static const struct cputbl *cputbls[6][8] =
1.1.1.7   root     1819: {
                   1820:        // 68000
1.1.1.9 ! root     1821:        { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL, NULL, NULL },
1.1.1.7   root     1822:        // 68010
1.1.1.9 ! root     1823:        { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL, NULL, NULL },
1.1.1.7   root     1824:        // 68020
1.1.1.9 ! root     1825:        { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL, NULL, NULL },
1.1.1.7   root     1826:        // 68030
1.1.1.9 ! root     1827:        { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff, op_smalltbl_34_ff, op_smalltbl_35_ff },
1.1.1.7   root     1828:        // 68040
1.1.1.9 ! root     1829:        { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff, op_smalltbl_31_ff, op_smalltbl_31_ff },
1.1.1.7   root     1830:        // 68060
1.1.1.9 ! root     1831:        { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff, op_smalltbl_33_ff, op_smalltbl_33_ff }
1.1.1.7   root     1832: };
                   1833: 
                   1834: static void build_cpufunctbl (void)
1.1.1.4   root     1835: {
                   1836:        int i, opcnt;
                   1837:        unsigned long opcode;
                   1838:        const struct cputbl *tbl = 0;
1.1.1.7   root     1839:        int lvl, mode;
1.1.1.4   root     1840: 
1.1.1.7   root     1841:        if (!currprefs.cachesize) {
1.1.1.9 ! root     1842:                if (currprefs.mmu_model) {
        !          1843:                        if (currprefs.cpu_cycle_exact)
        !          1844:                                mode = 7;
        !          1845:                        else if (currprefs.cpu_compatible)
        !          1846:                                mode = 6;
        !          1847:                        else
        !          1848:                                mode = 5;
        !          1849:                } else if (currprefs.cpu_cycle_exact) {
1.1.1.8   root     1850:                        mode = 4;
1.1.1.9 ! root     1851:                } else if (currprefs.cpu_compatible) {
1.1.1.8   root     1852:                        mode = 3;
1.1.1.9 ! root     1853:                } else {
1.1.1.7   root     1854:                        mode = 0;
1.1.1.9 ! root     1855:                }
1.1.1.7   root     1856:                m68k_pc_indirect = mode != 0 ? 1 : 0;
                   1857:        } else {
1.1.1.8   root     1858:                mode = 1;
1.1.1.7   root     1859:                m68k_pc_indirect = 0;
                   1860:                if (currprefs.comptrustbyte) {
1.1.1.8   root     1861:                        mode = 2;
1.1.1.7   root     1862:                        m68k_pc_indirect = -1;
                   1863:                }
1.1.1.4   root     1864:        }
1.1.1.7   root     1865:        lvl = (currprefs.cpu_model - 68000) / 10;
                   1866:        if (lvl == 6)
                   1867:                lvl = 5;
1.1.1.9 ! root     1868: fprintf ( stderr , "cpu table lvl=%d , mode=%d\n" , lvl , mode );
1.1.1.7   root     1869:        tbl = cputbls[lvl][mode];
1.1.1.4   root     1870: 
1.1.1.7   root     1871:        if (tbl == NULL) {
                   1872:                write_log (_T("no CPU emulation cores available CPU=%d!"), currprefs.cpu_model);
1.1.1.4   root     1873:                abort ();
                   1874:        }
                   1875: 
                   1876:        for (opcode = 0; opcode < 65536; opcode++)
                   1877:                cpufunctbl[opcode] = op_illg_1;
                   1878:        for (i = 0; tbl[i].handler != NULL; i++) {
                   1879:                opcode = tbl[i].opcode;
                   1880:                cpufunctbl[opcode] = tbl[i].handler;
1.1.1.7   root     1881:                cpudatatbl[opcode].length = tbl[i].length;
                   1882:                cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
                   1883:                cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
                   1884:                cpudatatbl[opcode].branch = tbl[i].branch;
1.1.1.4   root     1885:        }
                   1886: 
                   1887:        /* hack fpu to 68000/68010 mode */
                   1888:        if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                   1889:                tbl = op_smalltbl_3_ff;
                   1890:                for (i = 0; tbl[i].handler != NULL; i++) {
1.1.1.7   root     1891:                        if ((tbl[i].opcode & 0xfe00) == 0xf200) {
1.1.1.4   root     1892:                                cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1.1.1.7   root     1893:                                cpudatatbl[tbl[i].opcode].length = tbl[i].length;
                   1894:                                cpudatatbl[tbl[i].opcode].disp020[0] = tbl[i].disp020[0];
                   1895:                                cpudatatbl[tbl[i].opcode].disp020[1] = tbl[i].disp020[1];
                   1896:                                cpudatatbl[tbl[i].opcode].branch = tbl[i].branch;
                   1897:                        }
1.1.1.4   root     1898:                }
                   1899:        }
1.1.1.7   root     1900: 
1.1.1.4   root     1901:        opcnt = 0;
                   1902:        for (opcode = 0; opcode < 65536; opcode++) {
                   1903:                cpuop_func *f;
1.1.1.7   root     1904:                struct instr *table = &table68k[opcode];
                   1905: 
                   1906:                if (table->mnemo == i_ILLG)
                   1907:                        continue;               
                   1908: 
                   1909:                /* unimplemented opcode? */
                   1910:                if (table->unimpclev > 0 && lvl >= table->unimpclev) {
1.1.1.8   root     1911:                        if (currprefs.cpu_model == 68060) {
                   1912:                                // remove unimplemented integer instructions
                   1913:                                // unimpclev == 5: not implemented in 68060,
                   1914:                                // generates unimplemented instruction exception.
                   1915:                                if (currprefs.int_no_unimplemented && table->unimpclev == 5) {
                   1916:                                        cpufunctbl[opcode] = op_unimpl_1;
                   1917:                                        continue;
                   1918:                                }
                   1919:                                // remove unimplemented instruction that were removed in previous models,
                   1920:                                // generates normal illegal instruction exception.
                   1921:                                // unimplclev < 5: instruction was removed in 68040 or previous model.
                   1922:                                // clev=4: implemented in 68040 or later. unimpclev=5: not in 68060
                   1923:                                if (table->unimpclev < 5 || (table->clev == 4 && table->unimpclev == 5)) {
1.1.1.7   root     1924:                                        cpufunctbl[opcode] = op_illg_1;
                   1925:                                        continue;
                   1926:                                }
1.1.1.8   root     1927:                        } else {
                   1928:                                cpufunctbl[opcode] = op_illg_1;
                   1929:                                continue;
1.1.1.7   root     1930:                        }
                   1931:                }
1.1.1.4   root     1932: 
                   1933:                if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                   1934:                        /* more hack fpu to 68000/68010 mode */
1.1.1.7   root     1935:                        if (table->clev > lvl && (opcode & 0xfe00) != 0xf200)
1.1.1.4   root     1936:                                continue;
1.1.1.7   root     1937:                } else if (table->clev > lvl) {
1.1.1.4   root     1938:                        continue;
                   1939:                }
                   1940: 
1.1.1.7   root     1941:                if (table->handler != -1) {
                   1942:                        int idx = table->handler;
1.1.1.4   root     1943:                        f = cpufunctbl[idx];
                   1944:                        if (f == op_illg_1)
                   1945:                                abort ();
                   1946:                        cpufunctbl[opcode] = f;
1.1.1.7   root     1947:                        memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
1.1.1.4   root     1948:                        opcnt++;
                   1949:                }
                   1950:        }
1.1.1.7   root     1951:        write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
1.1.1.4   root     1952:                opcnt, lvl,
1.1.1.8   root     1953:                currprefs.cpu_cycle_exact ? -2 : currprefs.cpu_memory_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24);
1.1.1.4   root     1954: #ifdef JIT
1.1.1.8   root     1955:        write_log(_T("JIT: &countdown =  %p\n"), &countdown);
                   1956:        write_log(_T("JIT: &build_comp = %p\n"), &build_comp);
1.1.1.4   root     1957:        build_comp ();
                   1958: #endif
1.1.1.7   root     1959: 
1.1.1.9 ! root     1960:        write_log(_T("CPU=%d, FPU=%d%s, MMU=%d, JIT%s=%d."),
        !          1961:                currprefs.cpu_model,
        !          1962:                currprefs.fpu_model, currprefs.fpu_model ? (currprefs.fpu_softfloat ? _T(" (softfloat)") : _T(" (host)")) : _T(""),
        !          1963:                currprefs.mmu_model,
        !          1964:                currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
        !          1965:                currprefs.cachesize);
1.1.1.7   root     1966: 
                   1967:        regs.address_space_mask = 0xffffffff;
                   1968: #ifndef WINUAE_FOR_HATARI
                   1969:        if (currprefs.cpu_compatible) {
                   1970:                if (currprefs.address_space_24 && currprefs.cpu_model >= 68040)
                   1971:                        currprefs.address_space_24 = false;
                   1972:        }
                   1973: #else
                   1974:        /* Hatari : don't force address_space_24=0 for 68030, as the Falcon has a 68030 LC with only 24 bits */
                   1975:        /* TODO ? Force address_space_24=0 for 68040 ? */
                   1976: #endif
                   1977:        m68k_interrupt_delay = false;
                   1978:        if (currprefs.cpu_cycle_exact) {
                   1979:                if (tbl == op_smalltbl_14_ff || tbl == op_smalltbl_13_ff || tbl == op_smalltbl_21_ff || tbl == op_smalltbl_23_ff)
                   1980:                        m68k_interrupt_delay = true;
                   1981:        }
                   1982: 
                   1983:        if (currprefs.cpu_cycle_exact) {
                   1984:                if (currprefs.cpu_model == 68000)
                   1985:                        write_log(_T(" prefetch and cycle-exact"));
                   1986:                else
                   1987:                        write_log(_T(" ~cycle-exact"));
1.1.1.8   root     1988:        } else if (currprefs.cpu_memory_cycle_exact) {
                   1989:                        write_log(_T(" ~memory-cycle-exact"));
1.1.1.7   root     1990:        } else if (currprefs.cpu_compatible) {
                   1991:                if (currprefs.cpu_model <= 68020) {
                   1992:                        write_log(_T(" prefetch"));
                   1993:                } else {
                   1994:                        write_log(_T(" fake prefetch"));
1.1.1.5   root     1995:                }
1.1.1.4   root     1996:        }
1.1.1.7   root     1997:        if (currprefs.m68k_speed < 0)
                   1998:                write_log(_T(" fast"));
                   1999:        if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
                   2000:                write_log(_T(" no unimplemented integer instructions"));
                   2001:        }
                   2002:        if (currprefs.fpu_no_unimplemented && currprefs.fpu_model) {
                   2003:                write_log(_T(" no unimplemented floating point instructions"));
                   2004:        }
                   2005:        if (currprefs.address_space_24) {
                   2006:                regs.address_space_mask = 0x00ffffff;
                   2007:                write_log(_T(" 24-bit"));
                   2008:        }
                   2009:        write_log(_T("\n"));
1.1.1.4   root     2010: 
1.1.1.7   root     2011:        set_cpu_caches (true);
1.1.1.4   root     2012: }
                   2013: 
1.1.1.7   root     2014: #define CYCLES_DIV 8192
                   2015: static unsigned long cycles_mult;
1.1.1.4   root     2016: 
                   2017: static void update_68k_cycles (void)
                   2018: {
1.1.1.7   root     2019:        cycles_mult = 0;
1.1.1.9 ! root     2020: #ifdef WINUAE_FOR_HATARI
        !          2021:        Log_Printf(LOG_DEBUG, "update cyc speed %d throttle %f clock_mult %d\n", currprefs.m68k_speed, currprefs.m68k_speed_throttle, changed_prefs.cpu_clock_multiplier);
        !          2022: #else  /* Don't adjust cycles_mult in Hatari and ignore m68k_speed (forced to 0) */
1.1.1.7   root     2023:        if (currprefs.m68k_speed >= 0 && !currprefs.cpu_cycle_exact) {
                   2024:                if (currprefs.m68k_speed_throttle < 0) {
                   2025:                        cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
                   2026:                } else if (currprefs.m68k_speed_throttle > 0) {
                   2027:                        cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
                   2028:                }
                   2029:        }
                   2030:        if (currprefs.m68k_speed == 0) {
                   2031:                if (currprefs.cpu_model >= 68040) {
                   2032:                        if (!cycles_mult)
                   2033:                                cycles_mult = CYCLES_DIV / 8;
                   2034:                        else
                   2035:                                cycles_mult /= 8;
                   2036:                } else if (currprefs.cpu_model >= 68020) {
                   2037:                        if (!cycles_mult)
                   2038:                                cycles_mult = CYCLES_DIV / 4;
                   2039:                        else
                   2040:                                cycles_mult /= 4;
                   2041:                }
1.1.1.4   root     2042:        }
1.1.1.7   root     2043: #endif
                   2044: 
1.1.1.4   root     2045:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
                   2046:        currprefs.cpu_frequency = changed_prefs.cpu_frequency;
                   2047: 
1.1.1.7   root     2048: #ifndef WINUAE_FOR_HATARI
                   2049:        baseclock = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) * 8;
                   2050: #endif
1.1.1.4   root     2051:        cpucycleunit = CYCLE_UNIT / 2;
                   2052:        if (currprefs.cpu_clock_multiplier) {
                   2053:                if (currprefs.cpu_clock_multiplier >= 256) {
                   2054:                        cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
                   2055:                } else {
                   2056:                        cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
                   2057:                }
1.1.1.7   root     2058:                if (currprefs.cpu_model >= 68040)
                   2059:                        cpucycleunit /= 2;
                   2060: #ifndef WINUAE_FOR_HATARI              /* [NP] TODO : handle any cpu frequency, not just mulltiplier ? */
1.1.1.4   root     2061:        } else if (currprefs.cpu_frequency) {
                   2062:                cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
1.1.1.7   root     2063: #endif
                   2064:        } else if (currprefs.cpu_cycle_exact && currprefs.cpu_clock_multiplier == 0) {
                   2065:                if (currprefs.cpu_model >= 68040) {
                   2066:                        cpucycleunit = CYCLE_UNIT / 16;
                   2067:                } if (currprefs.cpu_model == 68030) {
                   2068:                        cpucycleunit = CYCLE_UNIT / 8;
                   2069:                } else if (currprefs.cpu_model == 68020) {
                   2070:                        cpucycleunit = CYCLE_UNIT / 4;
                   2071:                } else {
                   2072:                        cpucycleunit = CYCLE_UNIT / 2;
                   2073:                }
1.1.1.4   root     2074:        }
                   2075:        if (cpucycleunit < 1)
                   2076:                cpucycleunit = 1;
                   2077:        if (currprefs.cpu_cycle_exact)
1.1.1.7   root     2078:                write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
                   2079: write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
                   2080: #ifndef WINUAE_FOR_HATARI
                   2081:        set_config_changed ();
                   2082: #endif
1.1.1.4   root     2083: }
                   2084: 
                   2085: static void prefs_changed_cpu (void)
                   2086: {
                   2087:        fixup_cpu (&changed_prefs);
1.1.1.8   root     2088:        check_prefs_changed_comp(false);
1.1.1.4   root     2089:        currprefs.cpu_model = changed_prefs.cpu_model;
                   2090:        currprefs.fpu_model = changed_prefs.fpu_model;
1.1.1.9 ! root     2091:        if (currprefs.mmu_model != changed_prefs.mmu_model) {
        !          2092:                int oldmmu = currprefs.mmu_model;
        !          2093:                currprefs.mmu_model = changed_prefs.mmu_model;
        !          2094:                if (currprefs.mmu_model >= 68040) {
        !          2095:                        uae_u32 tcr = regs.tcr;
        !          2096:                        mmu_reset();
        !          2097:                        mmu_set_tc(tcr);
        !          2098:                        mmu_set_super(regs.s != 0);
        !          2099:                        mmu_tt_modified();
        !          2100:                } else if (currprefs.mmu_model == 68030) {
        !          2101:                        mmu030_reset(-1);
        !          2102:                        mmu030_flush_atc_all();
        !          2103:                        tc_030 = fake_tc_030;
        !          2104:                        tt0_030 = fake_tt0_030;
        !          2105:                        tt1_030 = fake_tt1_030;
        !          2106:                        srp_030 = fake_srp_030;
        !          2107:                        crp_030 = fake_crp_030;
        !          2108:                        mmu030_decode_tc(tc_030, false);
        !          2109:                } else if (oldmmu == 68030) {
        !          2110:                        fake_tc_030 = tc_030;
        !          2111:                        fake_tt0_030 = tt0_030;
        !          2112:                        fake_tt1_030 = tt1_030;
        !          2113:                        fake_srp_030 = srp_030;
        !          2114:                        fake_crp_030 = crp_030;
        !          2115:                }
        !          2116:        }
        !          2117:        currprefs.mmu_ec = changed_prefs.mmu_ec;
        !          2118:        if (currprefs.cpu_compatible != changed_prefs.cpu_compatible) {
        !          2119:                currprefs.cpu_compatible = changed_prefs.cpu_compatible;
        !          2120:                flush_cpu_caches(true);
        !          2121:                invalidate_cpu_data_caches();
        !          2122:        }
        !          2123:        if (currprefs.cpu_data_cache != changed_prefs.cpu_data_cache) {
        !          2124:                currprefs.cpu_data_cache = changed_prefs.cpu_data_cache;
        !          2125:                invalidate_cpu_data_caches();
        !          2126:        }
1.1.1.8   root     2127:        currprefs.address_space_24 = changed_prefs.address_space_24;
1.1.1.4   root     2128:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1.1.1.8   root     2129:        currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact;
1.1.1.7   root     2130:        currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented;
                   2131:        currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented;
1.1.1.9 ! root     2132:        currprefs.fpu_softfloat = changed_prefs.fpu_softfloat;
1.1.1.7   root     2133:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
1.1.1.4   root     2134: }
                   2135: 
1.1.1.7   root     2136: static int check_prefs_changed_cpu2(void)
1.1.1.4   root     2137: {
1.1.1.7   root     2138:        int changed = 0;
1.1.1.4   root     2139: 
                   2140: #ifdef JIT
1.1.1.8   root     2141:        changed = check_prefs_changed_comp(true) ? 1 : 0;
1.1.1.4   root     2142: #endif
                   2143:        if (changed
                   2144:                || currprefs.cpu_model != changed_prefs.cpu_model
                   2145:                || currprefs.fpu_model != changed_prefs.fpu_model
                   2146:                || currprefs.mmu_model != changed_prefs.mmu_model
1.1.1.9 ! root     2147:                || currprefs.mmu_ec != changed_prefs.mmu_ec
        !          2148:                || currprefs.cpu_data_cache != changed_prefs.cpu_data_cache
1.1.1.8   root     2149:                || currprefs.address_space_24 != changed_prefs.address_space_24  /* WINUAE_FOR_HATARI */
1.1.1.7   root     2150:                || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
                   2151:                || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
1.1.1.4   root     2152:                || currprefs.cpu_compatible != changed_prefs.cpu_compatible
1.1.1.8   root     2153:                || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact
1.1.1.9 ! root     2154:                || currprefs.cpu_memory_cycle_exact != changed_prefs.cpu_memory_cycle_exact
        !          2155:                || currprefs.fpu_softfloat != changed_prefs.fpu_softfloat) {
1.1.1.7   root     2156:                        cpu_prefs_changed_flag |= 1;
                   2157: #ifdef WINUAE_FOR_HATARI
                   2158:                        /* When changing CPU prefs in Hatari we reset the emulation, */
                   2159:                        /* so new cpu table should be built now, not in m68k_go() */
                   2160: //                     uaecptr pc = m68k_getpc();
                   2161:                        prefs_changed_cpu();
                   2162:                        build_cpufunctbl();
1.1.1.9 ! root     2163:                        set_x_funcs();          // [NP] TODO : really handle cpu change in m68k_go(), not during cpu instruction, too risky to keep a consistent state !!
1.1.1.7   root     2164: // done in m68k_go :
                   2165: //                     m68k_setpc_normal(pc);
                   2166: //                     fill_prefetch();
                   2167: #endif
1.1.1.4   root     2168:        }
                   2169:        if (changed
                   2170:                || currprefs.m68k_speed != changed_prefs.m68k_speed
1.1.1.7   root     2171:                || currprefs.m68k_speed_throttle != changed_prefs.m68k_speed_throttle
1.1.1.4   root     2172:                || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
1.1.1.7   root     2173:                || currprefs.reset_delay != changed_prefs.reset_delay
1.1.1.4   root     2174:                || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
1.1.1.7   root     2175:                        cpu_prefs_changed_flag |= 2;
1.1.1.4   root     2176:        }
1.1.1.7   root     2177:        return cpu_prefs_changed_flag;
                   2178: }
1.1.1.4   root     2179: 
1.1.1.7   root     2180: void check_prefs_changed_cpu(void)
                   2181: {
1.1.1.8   root     2182: #ifndef WINUAE_FOR_HATARI      /* [NP] TODO : handle cpu change on the fly ? */
1.1.1.7   root     2183:        if (!config_changed)
                   2184:                return;
1.1.1.8   root     2185: #endif
1.1.1.4   root     2186: 
1.1.1.7   root     2187:        currprefs.cpu_idle = changed_prefs.cpu_idle;
                   2188:        currprefs.ppc_cpu_idle = changed_prefs.ppc_cpu_idle;
                   2189:        currprefs.reset_delay = changed_prefs.reset_delay;
                   2190: 
                   2191:        if (check_prefs_changed_cpu2()) {
                   2192:                set_special(SPCFLAG_MODE_CHANGE);
                   2193:                reset_frame_rate_hack();
                   2194:        }
1.1.1.4   root     2195: }
                   2196: 
                   2197: void init_m68k (void)
                   2198: {
                   2199:        int i;
                   2200: 
                   2201:        prefs_changed_cpu ();
                   2202:        update_68k_cycles ();
                   2203: 
                   2204:        for (i = 0 ; i < 256 ; i++) {
                   2205:                int j;
                   2206:                for (j = 0 ; j < 8 ; j++) {
                   2207:                        if (i & (1 << j)) break;
                   2208:                }
                   2209:                movem_index1[i] = j;
1.1.1.7   root     2210:                movem_index2[i] = 7 - j;
1.1.1.4   root     2211:                movem_next[i] = i & (~(1 << j));
                   2212:        }
                   2213: 
                   2214: #if COUNT_INSTRS
                   2215:        {
                   2216:                FILE *f = fopen (icountfilename (), "r");
                   2217:                memset (instrcount, 0, sizeof instrcount);
                   2218:                if (f) {
                   2219:                        uae_u32 opcode, count, total;
                   2220:                        TCHAR name[20];
1.1.1.7   root     2221:                        write_log (_T("Reading instruction count file...\n"));
1.1.1.4   root     2222:                        fscanf (f, "Total: %lu\n", &total);
1.1.1.7   root     2223:                        while (fscanf (f, "%x: %lu %s\n", &opcode, &count, name) == 3) {
1.1.1.4   root     2224:                                instrcount[opcode] = count;
                   2225:                        }
                   2226:                        fclose (f);
                   2227:                }
                   2228:        }
                   2229: #endif
                   2230: 
                   2231:        read_table68k ();
                   2232:        do_merges ();
                   2233: 
1.1.1.7   root     2234:        write_log (_T("%d CPU functions\n"), nr_cpuop_funcs);
1.1.1.4   root     2235: 
1.1.1.9 ! root     2236: #ifdef WINUAE_FOR_HATARI
        !          2237:        /* Hatari : TODO remove these 2 lines as in winuae 3.4.0 */
        !          2238:        /* and do it only in m68k_go by setting uae_quit_program=UAE_RESET */
1.1.1.4   root     2239:        build_cpufunctbl ();
                   2240:        set_x_funcs ();
                   2241: #endif
                   2242: }
                   2243: 
                   2244: struct regstruct regs, mmu_backup_regs;
                   2245: struct flag_struct regflags;
1.1.1.7   root     2246: static int m68kpc_offset;
1.1.1.4   root     2247: 
1.1.1.9 ! root     2248: static const TCHAR *fpsizes[] = {
        !          2249:        _T("L"),
        !          2250:        _T("S"),
        !          2251:        _T("X"),
        !          2252:        _T("P"),
        !          2253:        _T("W"),
        !          2254:        _T("D"),
        !          2255:        _T("B"),
        !          2256:        _T("P")
        !          2257: };
        !          2258: static const int fpsizeconv[] = {
        !          2259:        sz_long,
        !          2260:        sz_single,
        !          2261:        sz_extended,
        !          2262:        sz_packed,
        !          2263:        sz_word,
        !          2264:        sz_double,
        !          2265:        sz_byte,
        !          2266:        sz_packed
        !          2267: };
        !          2268: static const int datasizes[] = {
        !          2269:        1,
        !          2270:        2,
        !          2271:        4,
        !          2272:        4,
        !          2273:        8,
        !          2274:        12,
        !          2275:        12
        !          2276: };
        !          2277: 
        !          2278: static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size)
        !          2279: {
        !          2280:        struct mnemolookup *lookup;
        !          2281:        struct instr *table = &table68k[opcode];
        !          2282: 
        !          2283:        for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++)
        !          2284:                ;
        !          2285:        if (!(lookup->flags & 1))
        !          2286:                return;
        !          2287:        buffer += _tcslen(buffer);
        !          2288:        if (debug_safe_addr(addr, datasizes[size])) {
        !          2289:                bool cached = false;
        !          2290:                switch (size)
        !          2291:                {
        !          2292:                        case sz_byte:
        !          2293:                        {
        !          2294:                                uae_u8 v = get_byte_cache_debug(addr, &cached);
        !          2295:                                uae_u8 v2 = v;
        !          2296:                                if (cached)
        !          2297:                                        v2 = get_byte_debug(addr);
        !          2298:                                if (v != v2) {
        !          2299:                                        _stprintf(buffer, _T(" [%02x:%02x]"), v, v2);
        !          2300:                                } else {
        !          2301:                                        _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v);
        !          2302:                                }
        !          2303:                        }
        !          2304:                        break;
        !          2305:                        case sz_word:
        !          2306:                        {
        !          2307:                                uae_u16 v = get_word_cache_debug(addr, &cached);
        !          2308:                                uae_u16 v2 = v;
        !          2309:                                if (cached)
        !          2310:                                        v2 = get_word_debug(addr);
        !          2311:                                if (v != v2) {
        !          2312:                                        _stprintf(buffer, _T(" [%04x:%04x]"), v, v2);
        !          2313:                                } else {
        !          2314:                                        _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v);
        !          2315:                                }
        !          2316:                        }
        !          2317:                        break;
        !          2318:                        case sz_long:
        !          2319:                        {
        !          2320:                                uae_u32 v = get_long_cache_debug(addr, &cached);
        !          2321:                                uae_u32 v2 = v;
        !          2322:                                if (cached)
        !          2323:                                        v2 = get_long_debug(addr);
        !          2324:                                if (v != v2) {
        !          2325:                                        _stprintf(buffer, _T(" [%08x:%08x]"), v, v2);
        !          2326:                                } else {
        !          2327:                                        _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v);
        !          2328:                                }
        !          2329:                        }
        !          2330:                        break;
        !          2331:                        case sz_single:
        !          2332:                        {
        !          2333:                                fpdata fp;
        !          2334:                                fpp_to_single(&fp, get_long_debug(addr));
        !          2335:                                _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
        !          2336:                        }
        !          2337:                        break;
        !          2338:                        case sz_double:
        !          2339:                        {
        !          2340:                                fpdata fp;
        !          2341:                                fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4));
        !          2342:                                _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
        !          2343:                        }
        !          2344:                        break;
        !          2345:                        case sz_extended:
        !          2346:                        {
        !          2347:                                fpdata fp;
        !          2348:                                fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
        !          2349:                                _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
        !          2350:                                break;
        !          2351:                        }
        !          2352:                        case sz_packed:
        !          2353:                                _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
        !          2354:                                break;
        !          2355:                }
        !          2356:        }
        !          2357: }
1.1.1.4   root     2358: 
1.1.1.7   root     2359: 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     2360: {
                   2361:        uae_u16 dp;
                   2362:        uae_s8 disp8;
                   2363:        uae_s16 disp16;
                   2364:        int r;
                   2365:        uae_u32 dispreg;
1.1.1.7   root     2366:        uaecptr addr = pc;
1.1.1.4   root     2367:        uae_s32 offset = 0;
                   2368:        TCHAR buffer[80];
                   2369: 
                   2370:        switch (mode){
                   2371:        case Dreg:
1.1.1.7   root     2372:                _stprintf (buffer, _T("D%d"), reg);
1.1.1.4   root     2373:                break;
                   2374:        case Areg:
1.1.1.7   root     2375:                _stprintf (buffer, _T("A%d"), reg);
1.1.1.4   root     2376:                break;
                   2377:        case Aind:
1.1.1.7   root     2378:                _stprintf (buffer, _T("(A%d)"), reg);
1.1.1.4   root     2379:                addr = regs.regs[reg + 8];
1.1.1.9 ! root     2380:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2381:                break;
                   2382:        case Aipi:
1.1.1.7   root     2383:                _stprintf (buffer, _T("(A%d)+"), reg);
1.1.1.4   root     2384:                addr = regs.regs[reg + 8];
1.1.1.9 ! root     2385:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2386:                break;
                   2387:        case Apdi:
1.1.1.7   root     2388:                _stprintf (buffer, _T("-(A%d)"), reg);
1.1.1.4   root     2389:                addr = regs.regs[reg + 8];
1.1.1.9 ! root     2390:                showea_val(buffer, opcode, addr - datasizes[size], size);
1.1.1.4   root     2391:                break;
                   2392:        case Ad16:
                   2393:                {
                   2394:                        TCHAR offtxt[80];
1.1.1.7   root     2395:                        disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4   root     2396:                        if (disp16 < 0)
1.1.1.7   root     2397:                                _stprintf (offtxt, _T("-$%04x"), -disp16);
1.1.1.4   root     2398:                        else
1.1.1.7   root     2399:                                _stprintf (offtxt, _T("$%04x"), disp16);
1.1.1.4   root     2400:                        addr = m68k_areg (regs, reg) + disp16;
1.1.1.7   root     2401:                        _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr);
1.1.1.9 ! root     2402:                        showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2403:                }
                   2404:                break;
                   2405:        case Ad8r:
1.1.1.7   root     2406:                dp = get_iword_debug (pc); pc += 2;
1.1.1.4   root     2407:                disp8 = dp & 0xFF;
                   2408:                r = (dp & 0x7000) >> 12;
                   2409:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   2410:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   2411:                dispreg <<= (dp >> 9) & 3;
                   2412: 
                   2413:                if (dp & 0x100) {
                   2414:                        uae_s32 outer = 0, disp = 0;
                   2415:                        uae_s32 base = m68k_areg (regs, reg);
                   2416:                        TCHAR name[10];
1.1.1.7   root     2417:                        _stprintf (name, _T("A%d, "), reg);
1.1.1.4   root     2418:                        if (dp & 0x80) { base = 0; name[0] = 0; }
                   2419:                        if (dp & 0x40) dispreg = 0;
1.1.1.7   root     2420:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                   2421:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     2422:                        base += disp;
                   2423: 
1.1.1.7   root     2424:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                   2425:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     2426: 
                   2427:                        if (!(dp & 4)) base += dispreg;
1.1.1.7   root     2428:                        if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1.1.1.4   root     2429:                        if (dp & 4) base += dispreg;
                   2430: 
                   2431:                        addr = base + outer;
1.1.1.7   root     2432:                        _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1.1.1.4   root     2433:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                   2434:                                1 << ((dp >> 9) & 3),
1.1.1.7   root     2435:                                disp, outer, addr);
1.1.1.4   root     2436:                } else {
                   2437:                        addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.7   root     2438:                        _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg,
1.1.1.4   root     2439:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1.1.1.7   root     2440:                                1 << ((dp >> 9) & 3), disp8, addr);
1.1.1.4   root     2441:                }
1.1.1.9 ! root     2442:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2443:                break;
                   2444:        case PC16:
1.1.1.7   root     2445:                disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4   root     2446:                addr += (uae_s16)disp16;
1.1.1.7   root     2447:                _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
1.1.1.9 ! root     2448:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2449:                break;
                   2450:        case PC8r:
1.1.1.7   root     2451:                dp = get_iword_debug (pc); pc += 2;
1.1.1.4   root     2452:                disp8 = dp & 0xFF;
                   2453:                r = (dp & 0x7000) >> 12;
                   2454:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   2455:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   2456:                dispreg <<= (dp >> 9) & 3;
                   2457: 
                   2458:                if (dp & 0x100) {
                   2459:                        uae_s32 outer = 0, disp = 0;
                   2460:                        uae_s32 base = addr;
                   2461:                        TCHAR name[10];
1.1.1.7   root     2462:                        _stprintf (name, _T("PC, "));
1.1.1.4   root     2463:                        if (dp & 0x80) { base = 0; name[0] = 0; }
                   2464:                        if (dp & 0x40) dispreg = 0;
1.1.1.7   root     2465:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                   2466:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     2467:                        base += disp;
                   2468: 
1.1.1.7   root     2469:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                   2470:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1.1.1.4   root     2471: 
                   2472:                        if (!(dp & 4)) base += dispreg;
1.1.1.7   root     2473:                        if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1.1.1.4   root     2474:                        if (dp & 4) base += dispreg;
                   2475: 
                   2476:                        addr = base + outer;
1.1.1.7   root     2477:                        _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1.1.1.4   root     2478:                                dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                   2479:                                1 << ((dp >> 9) & 3),
1.1.1.7   root     2480:                                disp, outer, addr);
1.1.1.4   root     2481:                } else {
                   2482:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.7   root     2483:                        _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D',
1.1.1.4   root     2484:                                (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
1.1.1.7   root     2485:                                disp8, addr);
1.1.1.4   root     2486:                }
1.1.1.9 ! root     2487:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2488:                break;
                   2489:        case absw:
1.1.1.7   root     2490:                addr = (uae_s32)(uae_s16)get_iword_debug (pc);
1.1.1.9 ! root     2491:                _stprintf (buffer, _T("$%04x"), (uae_u16)addr);
1.1.1.7   root     2492:                pc += 2;
1.1.1.9 ! root     2493:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2494:                break;
                   2495:        case absl:
1.1.1.7   root     2496:                addr = get_ilong_debug (pc);
                   2497:                _stprintf (buffer, _T("$%08x"), addr);
                   2498:                pc += 4;
1.1.1.9 ! root     2499:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2500:                break;
                   2501:        case imm:
                   2502:                switch (size){
                   2503:                case sz_byte:
1.1.1.7   root     2504:                        _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
                   2505:                        pc += 2;
1.1.1.4   root     2506:                        break;
                   2507:                case sz_word:
1.1.1.7   root     2508:                        _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
                   2509:                        pc += 2;
1.1.1.4   root     2510:                        break;
                   2511:                case sz_long:
1.1.1.7   root     2512:                        _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
                   2513:                        pc += 4;
                   2514:                        break;
                   2515:                case sz_single:
                   2516:                        {
                   2517:                                fpdata fp;
1.1.1.9 ! root     2518:                                fpp_to_single(&fp, get_ilong_debug(pc));
        !          2519:                                _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
1.1.1.7   root     2520:                                pc += 4;
                   2521:                        }
                   2522:                        break;
                   2523:                case sz_double:
                   2524:                        {
                   2525:                                fpdata fp;
1.1.1.9 ! root     2526:                                fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
        !          2527:                                _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
1.1.1.7   root     2528:                                pc += 8;
                   2529:                        }
                   2530:                        break;
                   2531:                case sz_extended:
                   2532:                {
                   2533:                        fpdata fp;
1.1.1.9 ! root     2534:                        fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
        !          2535:                        _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
1.1.1.7   root     2536:                        pc += 12;
                   2537:                        break;
                   2538:                }
                   2539:                case sz_packed:
                   2540:                        _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
                   2541:                        pc += 12;
1.1.1.4   root     2542:                        break;
                   2543:                default:
                   2544:                        break;
                   2545:                }
                   2546:                break;
                   2547:        case imm0:
1.1.1.7   root     2548:                offset = (uae_s32)(uae_s8)get_iword_debug (pc);
                   2549:                _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
                   2550:                addr = pc + 2 + offset;
                   2551:                pc += 2;
1.1.1.4   root     2552:                break;
                   2553:        case imm1:
1.1.1.7   root     2554:                offset = (uae_s32)(uae_s16)get_iword_debug (pc);
1.1.1.4   root     2555:                buffer[0] = 0;
1.1.1.7   root     2556:                _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
                   2557:                addr = pc + offset;
                   2558:                pc += 2;
1.1.1.4   root     2559:                break;
                   2560:        case imm2:
1.1.1.7   root     2561:                offset = (uae_s32)get_ilong_debug (pc);
                   2562:                _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
                   2563:                addr = pc + offset;
                   2564:                pc += 4;
1.1.1.4   root     2565:                break;
                   2566:        case immi:
                   2567:                offset = (uae_s32)(uae_s8)(reg & 0xff);
1.1.1.9 ! root     2568:                _stprintf (buffer, _T("#$%02x"), (uae_u8)offset);
1.1.1.7   root     2569:                addr = pc + offset;
1.1.1.4   root     2570:                break;
                   2571:        default:
                   2572:                break;
                   2573:        }
                   2574:        if (buf == 0)
1.1.1.7   root     2575:                f_out (f, _T("%s"), buffer);
1.1.1.4   root     2576:        else
                   2577:                _tcscat (buf, buffer);
                   2578:        if (eaddr)
                   2579:                *eaddr = addr;
1.1.1.7   root     2580:        return pc;
1.1.1.4   root     2581: }
                   2582: 
                   2583: #if 0
                   2584: /* The plan is that this will take over the job of exception 3 handling -
                   2585: * the CPU emulation functions will just do a longjmp to m68k_go whenever
                   2586: * they hit an odd address. */
                   2587: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
                   2588: {
                   2589:        uae_u16 dp;
                   2590:        uae_s8 disp8;
                   2591:        uae_s16 disp16;
                   2592:        int r;
                   2593:        uae_u32 dispreg;
                   2594:        uaecptr addr;
                   2595:        uae_s32 offset = 0;
                   2596: 
                   2597:        switch (mode){
                   2598:        case Dreg:
                   2599:                *val = m68k_dreg (regs, reg);
                   2600:                return 1;
                   2601:        case Areg:
                   2602:                *val = m68k_areg (regs, reg);
                   2603:                return 1;
                   2604: 
                   2605:        case Aind:
                   2606:        case Aipi:
                   2607:                addr = m68k_areg (regs, reg);
                   2608:                break;
                   2609:        case Apdi:
                   2610:                addr = m68k_areg (regs, reg);
                   2611:                break;
                   2612:        case Ad16:
                   2613:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   2614:                addr = m68k_areg (regs, reg) + (uae_s16)disp16;
                   2615:                break;
                   2616:        case Ad8r:
                   2617:                addr = m68k_areg (regs, reg);
                   2618: d8r_common:
                   2619:                dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   2620:                disp8 = dp & 0xFF;
                   2621:                r = (dp & 0x7000) >> 12;
                   2622:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   2623:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   2624:                dispreg <<= (dp >> 9) & 3;
                   2625: 
                   2626:                if (dp & 0x100) {
                   2627:                        uae_s32 outer = 0, disp = 0;
                   2628:                        uae_s32 base = addr;
                   2629:                        if (dp & 0x80) base = 0;
                   2630:                        if (dp & 0x40) dispreg = 0;
                   2631:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                   2632:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
                   2633:                        base += disp;
                   2634: 
                   2635:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                   2636:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
                   2637: 
                   2638:                        if (!(dp & 4)) base += dispreg;
                   2639:                        if (dp & 3) base = get_long (base);
                   2640:                        if (dp & 4) base += dispreg;
                   2641: 
                   2642:                        addr = base + outer;
                   2643:                } else {
                   2644:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
                   2645:                }
                   2646:                break;
                   2647:        case PC16:
                   2648:                addr = m68k_getpc () + m68kpc_offset;
                   2649:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   2650:                addr += (uae_s16)disp16;
                   2651:                break;
                   2652:        case PC8r:
                   2653:                addr = m68k_getpc () + m68kpc_offset;
                   2654:                goto d8r_common;
                   2655:        case absw:
                   2656:                addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                   2657:                m68kpc_offset += 2;
                   2658:                break;
                   2659:        case absl:
                   2660:                addr = get_ilong_1 (m68kpc_offset);
                   2661:                m68kpc_offset += 4;
                   2662:                break;
                   2663:        case imm:
                   2664:                switch (size){
                   2665:                case sz_byte:
                   2666:                        *val = get_iword_1 (m68kpc_offset) & 0xff;
                   2667:                        m68kpc_offset += 2;
                   2668:                        break;
                   2669:                case sz_word:
                   2670:                        *val = get_iword_1 (m68kpc_offset) & 0xffff;
                   2671:                        m68kpc_offset += 2;
                   2672:                        break;
                   2673:                case sz_long:
                   2674:                        *val = get_ilong_1 (m68kpc_offset);
                   2675:                        m68kpc_offset += 4;
                   2676:                        break;
                   2677:                default:
                   2678:                        break;
                   2679:                }
                   2680:                return 1;
                   2681:        case imm0:
                   2682:                *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
                   2683:                m68kpc_offset += 2;
                   2684:                return 1;
                   2685:        case imm1:
                   2686:                *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                   2687:                m68kpc_offset += 2;
                   2688:                return 1;
                   2689:        case imm2:
                   2690:                *val = get_ilong_1 (m68kpc_offset);
                   2691:                m68kpc_offset += 4;
                   2692:                return 1;
                   2693:        case immi:
                   2694:                *val = (uae_s32)(uae_s8)(reg & 0xff);
                   2695:                return 1;
                   2696:        default:
                   2697:                addr = 0;
                   2698:                break;
                   2699:        }
                   2700:        if ((addr & 1) == 0)
                   2701:                return 1;
                   2702: 
                   2703:        last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
                   2704:        last_fault_for_exception_3 = addr;
                   2705:        last_writeaccess_for_exception_3 = 0;
                   2706:        last_instructionaccess_for_exception_3 = 0;
                   2707:        return 0;
                   2708: }
                   2709: #endif
                   2710: 
                   2711: int get_cpu_model (void)
                   2712: {
                   2713:        return currprefs.cpu_model;
                   2714: }
                   2715: 
1.1.1.7   root     2716: #ifndef WINUAE_FOR_HATARI
                   2717: STATIC_INLINE int in_rom (uaecptr pc)
1.1.1.4   root     2718: {
1.1.1.7   root     2719:        return (munge24 (pc) & 0xFFF80000) == 0xF80000;
1.1.1.4   root     2720: }
                   2721: 
1.1.1.7   root     2722: STATIC_INLINE int in_rtarea (uaecptr pc)
1.1.1.4   root     2723: {
1.1.1.9 ! root     2724:        return (munge24 (pc) & 0xFFFF0000) == rtarea_base && (uae_boot_rom_type || currprefs.uaeboard > 0);
1.1.1.4   root     2725: }
1.1.1.7   root     2726: #endif
1.1.1.4   root     2727: 
1.1.1.7   root     2728: STATIC_INLINE void wait_memory_cycles (void)
1.1.1.4   root     2729: {
1.1.1.7   root     2730:        if (regs.memory_waitstate_cycles) {
                   2731:                x_do_cycles(regs.memory_waitstate_cycles);
                   2732:                regs.memory_waitstate_cycles = 0;
1.1.1.4   root     2733:        }
1.1.1.7   root     2734:        if (regs.ce020extracycles >= 16) {
                   2735:                regs.ce020extracycles = 0;
                   2736:                x_do_cycles(4 * CYCLE_UNIT);
1.1.1.4   root     2737:        }
                   2738: }
                   2739: 
1.1.1.7   root     2740: STATIC_INLINE int adjust_cycles (int cycles)
1.1.1.4   root     2741: {
1.1.1.7   root     2742:        int mc = regs.memory_waitstate_cycles;
                   2743:        regs.memory_waitstate_cycles = 0;
                   2744:        if (currprefs.m68k_speed < 0 || cycles_mult == 0)
                   2745:                return cycles + mc;
                   2746:        cycles *= cycles_mult;
                   2747:        cycles /= CYCLES_DIV;
                   2748:        return cycles + mc;
1.1.1.4   root     2749: }
                   2750: 
1.1.1.9 ! root     2751: void m68k_cancel_idle(void)
        !          2752: {
        !          2753: #ifndef WINUAE_FOR_HATARI
        !          2754:        cpu_last_stop_vpos = -1;
        !          2755: #endif
        !          2756: }
        !          2757: 
1.1.1.8   root     2758: static void m68k_set_stop(void)
                   2759: {
                   2760:        if (regs.stopped)
                   2761:                return;
                   2762:        regs.stopped = 1;
                   2763:        set_special(SPCFLAG_STOP);
                   2764: #ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     2765:        if (cpu_last_stop_vpos >= 0) {
        !          2766:                cpu_last_stop_vpos = vpos;
        !          2767:        }
1.1.1.8   root     2768: #endif
                   2769: }
                   2770: 
                   2771: static void m68k_unset_stop(void)
                   2772: {
                   2773:        regs.stopped = 0;
                   2774:        unset_special(SPCFLAG_STOP);
                   2775: #ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     2776:        if (cpu_last_stop_vpos >= 0) {
        !          2777:                cpu_stopped_lines += vpos - cpu_last_stop_vpos;
        !          2778:                cpu_last_stop_vpos = vpos;
        !          2779:        }
1.1.1.8   root     2780: #endif
                   2781: }
                   2782: 
1.1.1.9 ! root     2783: static void activate_trace(void)
        !          2784: {
        !          2785:        unset_special (SPCFLAG_TRACE);
        !          2786:        set_special (SPCFLAG_DOTRACE);
        !          2787: }
        !          2788: 
        !          2789: void REGPARAM2 MakeSR (void)
1.1.1.4   root     2790: {
                   2791:        regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
                   2792:                | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
                   2793:                | (GET_XFLG () << 4) | (GET_NFLG () << 3)
                   2794:                | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
                   2795:                |  GET_CFLG ());
                   2796: }
                   2797: 
1.1.1.8   root     2798: static void SetSR (uae_u16 sr)
1.1.1.4   root     2799: {
1.1.1.7   root     2800:        regs.sr &= 0xff00;
                   2801:        regs.sr |= sr;
1.1.1.4   root     2802: 
                   2803:        SET_XFLG ((regs.sr >> 4) & 1);
                   2804:        SET_NFLG ((regs.sr >> 3) & 1);
                   2805:        SET_ZFLG ((regs.sr >> 2) & 1);
                   2806:        SET_VFLG ((regs.sr >> 1) & 1);
                   2807:        SET_CFLG (regs.sr & 1);
1.1.1.7   root     2808: }
                   2809: 
1.1.1.9 ! root     2810: static void MakeFromSR_x(int t0trace)
1.1.1.7   root     2811: {
                   2812:        int oldm = regs.m;
                   2813:        int olds = regs.s;
1.1.1.9 ! root     2814:        int oldt0 = regs.t0;
        !          2815:        int oldt1 = regs.t1;
1.1.1.7   root     2816: 
                   2817:        SET_XFLG ((regs.sr >> 4) & 1);
                   2818:        SET_NFLG ((regs.sr >> 3) & 1);
                   2819:        SET_ZFLG ((regs.sr >> 2) & 1);
                   2820:        SET_VFLG ((regs.sr >> 1) & 1);
                   2821:        SET_CFLG (regs.sr & 1);
                   2822:        if (regs.t1 == ((regs.sr >> 15) & 1) &&
                   2823:                regs.t0 == ((regs.sr >> 14) & 1) &&
                   2824:                regs.s  == ((regs.sr >> 13) & 1) &&
1.1.1.4   root     2825:                regs.m  == ((regs.sr >> 12) & 1) &&
                   2826:                regs.intmask == ((regs.sr >> 8) & 7))
                   2827:                return;
                   2828:        regs.t1 = (regs.sr >> 15) & 1;
                   2829:        regs.t0 = (regs.sr >> 14) & 1;
                   2830:        regs.s  = (regs.sr >> 13) & 1;
                   2831:        regs.m  = (regs.sr >> 12) & 1;
                   2832:        regs.intmask = (regs.sr >> 8) & 7;
                   2833:        if (currprefs.cpu_model >= 68020) {
                   2834:                /* 68060 does not have MSP but does have M-bit.. */
                   2835:                if (currprefs.cpu_model >= 68060)
                   2836:                        regs.msp = regs.isp;
                   2837:                if (olds != regs.s) {
                   2838:                        if (olds) {
                   2839:                                if (oldm)
                   2840:                                        regs.msp = m68k_areg (regs, 7);
                   2841:                                else
                   2842:                                        regs.isp = m68k_areg (regs, 7);
                   2843:                                m68k_areg (regs, 7) = regs.usp;
                   2844:                        } else {
                   2845:                                regs.usp = m68k_areg (regs, 7);
                   2846:                                m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
                   2847:                        }
                   2848:                } else if (olds && oldm != regs.m) {
                   2849:                        if (oldm) {
                   2850:                                regs.msp = m68k_areg (regs, 7);
                   2851:                                m68k_areg (regs, 7) = regs.isp;
                   2852:                        } else {
                   2853:                                regs.isp = m68k_areg (regs, 7);
                   2854:                                m68k_areg (regs, 7) = regs.msp;
                   2855:                        }
                   2856:                }
                   2857:                if (currprefs.cpu_model >= 68060)
                   2858:                        regs.t0 = 0;
                   2859:        } else {
                   2860:                regs.t0 = regs.m = 0;
                   2861:                if (olds != regs.s) {
                   2862:                        if (olds) {
                   2863:                                regs.isp = m68k_areg (regs, 7);
                   2864:                                m68k_areg (regs, 7) = regs.usp;
                   2865:                        } else {
                   2866:                                regs.usp = m68k_areg (regs, 7);
                   2867:                                m68k_areg (regs, 7) = regs.isp;
                   2868:                        }
                   2869:                }
                   2870:        }
                   2871:        if (currprefs.mmu_model)
                   2872:                mmu_set_super (regs.s != 0);
                   2873: 
                   2874:        doint ();
1.1.1.9 ! root     2875:        if (regs.t1 || regs.t0) {
1.1.1.4   root     2876:                set_special (SPCFLAG_TRACE);
1.1.1.9 ! root     2877:        } else {
1.1.1.4   root     2878:                /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
                   2879:                SR-modifying instructions (including STOP).  */
                   2880:                unset_special (SPCFLAG_TRACE);
1.1.1.9 ! root     2881:        }
        !          2882:        // Stop SR-modification does not generate T0
        !          2883:        // If this SR modification set Tx bit, no trace until next instruction.
        !          2884:        if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) {
        !          2885:                // Always trace if Tx bits were already set, even if this SR modification cleared them.
        !          2886:                activate_trace();
        !          2887:        }
        !          2888: }
        !          2889: 
        !          2890: void REGPARAM2 MakeFromSR_T0(void)
        !          2891: {
        !          2892:        MakeFromSR_x(1);
        !          2893: }
        !          2894: void REGPARAM2 MakeFromSR(void)
        !          2895: {
        !          2896:        MakeFromSR_x(0);
1.1.1.4   root     2897: }
                   2898: 
1.1.1.8   root     2899: static void exception_check_trace (int nr)
1.1.1.4   root     2900: {
                   2901:        unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                   2902:        if (regs.t1 && !regs.t0) {
                   2903:                /* trace stays pending if exception is div by zero, chk,
                   2904:                * trapv or trap #x
                   2905:                */
                   2906:                if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
                   2907:                        set_special (SPCFLAG_DOTRACE);
                   2908:        }
1.1.1.8   root     2909:        regs.t1 = regs.t0 = 0;
1.1.1.4   root     2910: }
                   2911: 
                   2912: static void exception_debug (int nr)
                   2913: {
1.1.1.7   root     2914: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     2915:        if (unlikely(ExceptionDebugMask & EXCEPT_NOHANDLER) && STMemory_ReadLong(regs.vbr + 4*nr) == 0) {
                   2916:                fprintf(stderr,"Uninitialized exception handler #%i!\n", nr);
                   2917:                DebugUI(REASON_CPU_EXCEPTION);
                   2918:        } else {
                   2919:                DebugUI_Exceptions(nr, M68K_GETPC);
                   2920:        }
1.1.1.9 ! root     2921: #else
        !          2922: #ifdef DEBUGGER
        !          2923:        if (!exception_debugging)
        !          2924:                return;
        !          2925:        console_out_f (_T("Exception %d, PC=%08X\n"), nr, M68K_GETPC);
        !          2926: #endif
1.1.1.7   root     2927: #endif
1.1.1.4   root     2928: }
                   2929: 
1.1.1.7   root     2930: #ifdef CPUEMU_13
1.1.1.4   root     2931: 
                   2932: /* cycle-exact exception handler, 68000 only */
                   2933: 
                   2934: /*
                   2935: 
                   2936: Address/Bus Error:
                   2937: 
1.1.1.7   root     2938: - 8 idle cycles
1.1.1.4   root     2939: - write PC low word
                   2940: - write SR
                   2941: - write PC high word
                   2942: - write instruction word
                   2943: - write fault address low word
                   2944: - write status code
                   2945: - write fault address high word
                   2946: - 2 idle cycles
                   2947: - read exception address high word
                   2948: - read exception address low word
                   2949: - prefetch
                   2950: - 2 idle cycles
                   2951: - prefetch
                   2952: 
                   2953: Division by Zero:
                   2954: 
1.1.1.7   root     2955: - 8 idle cycles
1.1.1.4   root     2956: - write PC low word
                   2957: - write SR
                   2958: - write PC high word
                   2959: - read exception address high word
                   2960: - read exception address low word
                   2961: - prefetch
                   2962: - 2 idle cycles
                   2963: - prefetch
                   2964: 
                   2965: Traps:
                   2966: 
1.1.1.7   root     2967: - 4 idle cycles
1.1.1.4   root     2968: - write PC low word
                   2969: - write SR
                   2970: - write PC high word
                   2971: - read exception address high word
                   2972: - read exception address low word
                   2973: - prefetch
                   2974: - 2 idle cycles
                   2975: - prefetch
                   2976: 
                   2977: TrapV:
                   2978: 
1.1.1.7   root     2979: (- normal prefetch done by TRAPV)
1.1.1.4   root     2980: - write PC low word
                   2981: - write SR
                   2982: - write PC high word
                   2983: - read exception address high word
                   2984: - read exception address low word
                   2985: - prefetch
                   2986: - 2 idle cycles
                   2987: - prefetch
                   2988: 
                   2989: CHK:
                   2990: 
1.1.1.7   root     2991: - 8 idle cycles
1.1.1.4   root     2992: - write PC low word
                   2993: - write SR
                   2994: - write PC high word
                   2995: - read exception address high word
                   2996: - read exception address low word
                   2997: - prefetch
                   2998: - 2 idle cycles
                   2999: - prefetch
                   3000: 
                   3001: Illegal Instruction:
1.1.1.7   root     3002: Privilege violation:
1.1.1.8   root     3003: Trace:
1.1.1.7   root     3004: Line A:
                   3005: Line F:
1.1.1.4   root     3006: 
1.1.1.7   root     3007: - 4 idle cycles
1.1.1.4   root     3008: - write PC low word
                   3009: - write SR
                   3010: - write PC high word
                   3011: - read exception address high word
                   3012: - read exception address low word
                   3013: - prefetch
                   3014: - 2 idle cycles
                   3015: - prefetch
                   3016: 
1.1.1.7   root     3017: Interrupt:
1.1.1.4   root     3018: 
                   3019: - 6 idle cycles
                   3020: - write PC low word
                   3021: - read exception number byte from (0xfffff1 | (interrupt number << 1))
                   3022: - 4 idle cycles
                   3023: - write SR
                   3024: - write PC high word
                   3025: - read exception address high word
                   3026: - read exception address low word
                   3027: - prefetch
                   3028: - 2 idle cycles
                   3029: - prefetch
                   3030: 
                   3031: */
                   3032: 
1.1.1.7   root     3033: static int iack_cycle(int nr)
                   3034: {
                   3035:        int vector;
                   3036: 
                   3037: #ifndef WINUAE_FOR_HATARI
                   3038:        if (1) {
                   3039:                // non-autovectored
                   3040:                vector = x_get_byte(0x00fffff1 | ((nr - 24) << 1));
                   3041:                if (currprefs.cpu_cycle_exact)
                   3042:                        x_do_cycles(4 * cpucycleunit);
                   3043:        } else {
                   3044:                // autovectored
                   3045: 
                   3046:        }
                   3047: #else
                   3048:        int iack_start = CPU_IACK_CYCLES_START;
                   3049:        int e_cycles;
1.1.1.8   root     3050:        int cycle_exact = currprefs.cpu_cycle_exact && !currprefs.mmu_model;
1.1.1.7   root     3051: 
                   3052:        /* In cycle exact mode, the cycles before reaching IACK are already counted */
1.1.1.8   root     3053:        if (cycle_exact)
1.1.1.7   root     3054:                iack_start = 0;
                   3055: 
                   3056:        /* Pending bits / vector number can change before the end of the IACK sequence. */
                   3057:        /* We need to handle MFP/DSP and HBL/VBL cases for this. */
                   3058:        /* - Level 6 (MFP/DSP) use vectored interrupts */
                   3059:        /* - Level 2 (HBL) and 4 (VBL) use auto-vectored interrupts and require sync with E-clock */
                   3060:        vector = nr;
                   3061:        if ( nr == 30 )                                                         /* MFP or DSP */
                   3062:         {
                   3063:                vector = -1;
                   3064:                if (bDspEnabled)                                                /* Check DSP first */
                   3065:                {
                   3066:                        /* TODO : For DSP, we just get the vector, we don't add IACK cycles */
                   3067:                        vector = DSP_ProcessIACK ();
                   3068:                }
                   3069: 
                   3070:                if ( vector < 0 )                                               /* No DSP, check MFP */
                   3071:                {
1.1.1.8   root     3072:                        if (cycle_exact)
                   3073:                        {
                   3074:                                x_do_cycles ( ( iack_start + CPU_IACK_CYCLES_MFP ) * cpucycleunit );
                   3075:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   3076:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3077:                                currcycle=0;
                   3078:                        }
                   3079:                        else
                   3080:                                M68000_AddCycles ( iack_start + CPU_IACK_CYCLES_MFP );
                   3081: 
1.1.1.7   root     3082:                        CPU_IACK = true;
                   3083:                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3084:                                CALL_VAR(PendingInterruptFunction);
                   3085:                        vector = MFP_ProcessIACK ( nr );
                   3086:                        CPU_IACK = false;
                   3087:                }
1.1.1.8   root     3088: 
                   3089:                if ( vector >= 0 )                                              /* We have a valid vector for level 6 */
                   3090:                {
                   3091:                        /* If a DSP IRQ is pending, we don't clear level 6 pending bit, else the DSP IRQ */
                   3092:                        /* will never be processed. If there's no DSP IRQ, we clear level 6 pending bit now */
                   3093:                        /* and if there's a lower MFP pending int, level 6 will be set again at the next instruction */
                   3094:                        if ( DSP_GetHREQ() == 0 )
                   3095:                                pendingInterrupts &= ~( 1 << 6 );
                   3096:                }
1.1.1.7   root     3097:        }
                   3098:        else if ( ( nr == 26 ) || ( nr == 28 ) )                                /* HBL / VBL */
                   3099:        {
1.1.1.8   root     3100:                if (cycle_exact)
                   3101:                {
                   3102:                        /* In CE mode, iack_start = 0, no need to call x_do_cycles() */
                   3103:                        //x_do_cycles ( ( iack_start + CPU_IACK_CYCLES_VIDEO_CE + e_cycles ) * cpucycleunit );
                   3104:                        /* Flush all CE cycles so far before calling M68000_WaitEClock() */
                   3105:                        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3106:                        currcycle = 0;
                   3107:                }
                   3108:                else
                   3109:                        M68000_AddCycles ( iack_start );
                   3110: 
1.1.1.7   root     3111:                e_cycles = M68000_WaitEClock ();
1.1.1.8   root     3112: //             fprintf ( stderr , "wait e clock %d\n" , e_cycles);
                   3113: 
                   3114:                if (cycle_exact)
                   3115:                {
                   3116:                        x_do_cycles ( ( e_cycles + CPU_IACK_CYCLES_VIDEO_CE ) * cpucycleunit );
                   3117:                        /* Flush all CE cycles so far to update PendingInterruptCount */
                   3118:                        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3119:                        currcycle = 0;
                   3120:                }
                   3121:                else
                   3122:                        M68000_AddCycles ( e_cycles + CPU_IACK_CYCLES_VIDEO_CE );
1.1.1.7   root     3123: 
                   3124:                CPU_IACK = true;
                   3125:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3126:                        CALL_VAR(PendingInterruptFunction);
                   3127:                if ( MFP_UpdateNeeded == true )
                   3128:                        MFP_UpdateIRQ ( 0 );                                    /* update MFP's state if some internal timers related to MFP expired */
1.1.1.8   root     3129:                pendingInterrupts &= ~( 1 << ( nr - 24 ) );                     /* clear HBL or VBL pending bit (even if an MFP timer occurred during IACK) */
1.1.1.7   root     3130:                CPU_IACK = false;
                   3131:        }
                   3132: 
                   3133:        /* TODO If there was no DSP and no MFP IRQ, then we have a spurious interrupt */
                   3134:        /* In that case, we use vector 24 and we jump to $60 */
                   3135:        if ( vector < 0 )
                   3136:        {
                   3137:        }
1.1.1.8   root     3138: 
                   3139:        /* Add 4 idle cycles for CE mode. For non-CE mode, this will be counted in add_approximate_exception_cycles() */
                   3140:        if (cycle_exact)
                   3141:                x_do_cycles( 4 * cpucycleunit );
1.1.1.7   root     3142: #endif
                   3143:        return vector;
                   3144: }
                   3145: 
                   3146: static void Exception_ce000 (int nr)
1.1.1.4   root     3147: {
                   3148:        uae_u32 currpc = m68k_getpc (), newpc;
                   3149:        int sv = regs.s;
1.1.1.7   root     3150:        int start, interrupt;
                   3151:        int vector_nr = nr;
1.1.1.4   root     3152: 
1.1.1.8   root     3153: //fprintf ( stderr , "ex in %d %ld %ld\n" , nr , currcycle , CyclesGlobalClockCounter );
1.1.1.7   root     3154:        start = 6;
1.1.1.4   root     3155:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.7   root     3156:        if (!interrupt) {
                   3157:                start = 8;
                   3158:                if (nr == 7) // TRAPV
                   3159:                        start = 0;
                   3160:                else if (nr >= 32 && nr < 32 + 16) // TRAP #x
                   3161:                        start = 4;
1.1.1.8   root     3162:                else if (nr == 4 || nr == 8 || nr == 9 || nr == 10 || nr == 11) // ILLG, PRIV, TRACE, LINEA, LINEF
1.1.1.7   root     3163:                        start = 4;
                   3164:        }
1.1.1.4   root     3165: 
                   3166:        if (start)
1.1.1.7   root     3167:                x_do_cycles (start * cpucycleunit);
1.1.1.4   root     3168: 
1.1.1.7   root     3169: #ifdef WINUAE_FOR_HATARI
                   3170:        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",
                   3171:                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);
                   3172: #endif
1.1.1.4   root     3173:        exception_debug (nr);
                   3174:        MakeSR ();
                   3175: 
                   3176:        if (!regs.s) {
                   3177:                regs.usp = m68k_areg (regs, 7);
                   3178:                m68k_areg (regs, 7) = regs.isp;
                   3179:                regs.s = 1;
                   3180:        }
                   3181:        if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
1.1.1.7   root     3182:                if ((m68k_areg(regs, 7) & 1) || exception_in_exception < 0) {
1.1.1.8   root     3183:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3184:                        return;
                   3185:                }
1.1.1.4   root     3186:                uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   3187:                mode |= last_writeaccess_for_exception_3 ? 0 : 16;
1.1.1.7   root     3188:                mode |= last_notinstruction_for_exception_3 ? 8 : 0;
                   3189:                // undocumented bits seem to contain opcode
                   3190:                mode |= last_op_for_exception_3 & ~31;
1.1.1.4   root     3191:                m68k_areg (regs, 7) -= 14;
1.1.1.7   root     3192:                exception_in_exception = -1;
                   3193:                x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
                   3194:                x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
                   3195:                x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
                   3196:                x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
                   3197:                x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
                   3198:                x_put_word (m68k_areg (regs, 7) + 0, mode);
                   3199:                x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
                   3200:                x_do_cycles (2 * cpucycleunit);
1.1.1.8   root     3201: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     3202:                write_log (_T("Exception %d (%04x %x) at %x -> %x!\n"),
                   3203:                        nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug (4 * nr));
1.1.1.8   root     3204: #else
                   3205:                if (nr != 2 || last_fault_for_exception_3 != 0xff8a00 || currpc < TosAddress || currpc > TosAddress + TosSize)
                   3206:                        fprintf(stderr,"%s Error at address $%x, PC=$%x addr_e3=%x op_e3=%x\n", nr==2?"Bus":"Address",
                   3207:                                last_fault_for_exception_3, currpc, last_addr_for_exception_3 , last_op_for_exception_3);
1.1.1.7   root     3208: #endif
1.1.1.4   root     3209:                goto kludge_me_do;
                   3210:        }
1.1.1.7   root     3211:        if (currprefs.cpu_model == 68010) {
                   3212:                // 68010 creates only format 0 and 8 stack frames
                   3213:                m68k_areg (regs, 7) -= 8;
                   3214:                if (m68k_areg(regs, 7) & 1) {
                   3215:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
                   3216:                        return;
                   3217:                }
                   3218:                exception_in_exception = 1;
                   3219:                x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
                   3220:                if (interrupt)
                   3221:                        vector_nr = iack_cycle(nr);
                   3222:                x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
                   3223:                x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
                   3224:                x_put_word (m68k_areg (regs, 7) + 6, vector_nr * 4);
                   3225:        } else {
                   3226:                m68k_areg (regs, 7) -= 6;
                   3227:                if (m68k_areg(regs, 7) & 1) {
                   3228:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
                   3229:                        return;
                   3230:                }
                   3231:                exception_in_exception = 1;
                   3232:                x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
1.1.1.8   root     3233: //fprintf ( stderr , "ex iack1 %d %ld\n" , nr , currcycle );
1.1.1.7   root     3234:                if (interrupt)
                   3235:                        vector_nr = iack_cycle(nr);
1.1.1.8   root     3236: //fprintf ( stderr , "ex iack2 %d %ld\n" , nr , currcycle );
1.1.1.7   root     3237:                x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
                   3238:                x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
1.1.1.4   root     3239:        }
                   3240: kludge_me_do:
1.1.1.7   root     3241:        newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
                   3242:        newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
                   3243:        exception_in_exception = 0;
1.1.1.4   root     3244:        if (newpc & 1) {
                   3245:                if (nr == 2 || nr == 3)
1.1.1.8   root     3246:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3247:                else
1.1.1.7   root     3248:                        exception3_notinstruction(regs.ir, newpc);
1.1.1.4   root     3249:                return;
                   3250:        }
                   3251:        m68k_setpc (newpc);
1.1.1.7   root     3252:        regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
                   3253:        x_do_cycles (2 * cpucycleunit);
1.1.1.8   root     3254: #ifdef WINUAE_FOR_HATARI
                   3255:        /* [NP] IPL should be updated just before the last x_get_word for irc */
                   3256:        /* (4 cycles before end of exception), so we need to add 2 cycles now */
                   3257:        /* to be aligned on 4 cycles (else the 2 cycles will be added in x_get_word */
                   3258:        /* and IPL will be updated 2 cycles too soon) */
                   3259:        x_do_cycles (2 * cpucycleunit);
                   3260:        /* Add all cycles needed for the exception so far */
                   3261:        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3262:        currcycle = 0;
                   3263:        /* Update IPL / interrupts state, in case a new interrupt happened during this exception */
                   3264:        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3265:                CALL_VAR(PendingInterruptFunction);
                   3266: #endif
                   3267:        regs.ipl_pin = intlev();
                   3268:        ipl_fetch();
1.1.1.7   root     3269:        regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2
1.1.1.4   root     3270: #ifdef JIT
                   3271:        set_special (SPCFLAG_END_COMPILE);
                   3272: #endif
1.1.1.8   root     3273:        exception_check_trace (nr);
1.1.1.7   root     3274: 
                   3275: //fprintf ( stderr , "ex out %d %ld\n" , nr , currcycle );
                   3276: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     3277:        /* Add all cycles needed for the exception */
                   3278:        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3279:        currcycle = 0;
1.1.1.7   root     3280: #endif
                   3281: }
                   3282: #endif
                   3283: 
                   3284: static uae_u32 exception_pc (int nr)
                   3285: {
                   3286:        // bus error, address error, illegal instruction, privilege violation, a-line, f-line
                   3287:        if (nr == 2 || nr == 3 || nr == 4 || nr == 8 || nr == 10 || nr == 11)
                   3288:                return regs.instruction_pc;
                   3289:        return m68k_getpc ();
                   3290: }
                   3291: 
                   3292: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
                   3293: {
                   3294:     int i;
                   3295:    
                   3296: #if 0
                   3297:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
                   3298:         write_log(_T("Building exception stack frame (format %X)\n"), format);
                   3299:     }
                   3300: #endif
                   3301: 
1.1.1.9 ! root     3302:        switch (format) {
1.1.1.7   root     3303:         case 0x0: // four word stack frame
                   3304:         case 0x1: // throwaway four word stack frame
                   3305:             break;
                   3306:         case 0x2: // six word stack frame
                   3307:             m68k_areg (regs, 7) -= 4;
                   3308:             x_put_long (m68k_areg (regs, 7), oldpc);
                   3309:             break;
1.1.1.9 ! root     3310:                case 0x3: // floating point post-instruction stack frame (68040)
        !          3311:                        m68k_areg (regs, 7) -= 4;
        !          3312:                        x_put_long (m68k_areg (regs, 7), regs.fp_ea);
        !          3313:                        break;
        !          3314:                case 0x7: // access error stack frame (68040)
1.1.1.7   root     3315: 
                   3316:                        for (i = 3; i >= 0; i--) {
                   3317:                                // WB1D/PD0,PD1,PD2,PD3
                   3318:                 m68k_areg (regs, 7) -= 4;
                   3319:                 x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
                   3320:                        }
                   3321: 
                   3322:             m68k_areg (regs, 7) -= 4;
                   3323:             x_put_long (m68k_areg (regs, 7), 0); // WB1A
                   3324:                        m68k_areg (regs, 7) -= 4;
                   3325:             x_put_long (m68k_areg (regs, 7), 0); // WB2D
                   3326:             m68k_areg (regs, 7) -= 4;
                   3327:             x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
                   3328:                        m68k_areg (regs, 7) -= 4;
                   3329:             x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
                   3330:             m68k_areg (regs, 7) -= 4;
                   3331:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
                   3332: 
                   3333:                        m68k_areg (regs, 7) -= 4;
                   3334:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
                   3335:             
                   3336:                        m68k_areg (regs, 7) -= 2;
                   3337:             x_put_word (m68k_areg (regs, 7), 0);
                   3338:             m68k_areg (regs, 7) -= 2;
                   3339:             x_put_word (m68k_areg (regs, 7), regs.wb2_status);
                   3340:             regs.wb2_status = 0;
                   3341:             m68k_areg (regs, 7) -= 2;
                   3342:             x_put_word (m68k_areg (regs, 7), regs.wb3_status);
                   3343:             regs.wb3_status = 0;
                   3344: 
                   3345:                        m68k_areg (regs, 7) -= 2;
                   3346:                        x_put_word (m68k_areg (regs, 7), ssw);
                   3347:             m68k_areg (regs, 7) -= 4;
                   3348:             x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
                   3349:             break;
                   3350:         case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
                   3351:             m68k_areg (regs, 7) -= 4;
1.1.1.9 ! root     3352:             x_put_long (m68k_areg (regs, 7), regs.fp_ea);
1.1.1.7   root     3353:             m68k_areg (regs, 7) -= 4;
1.1.1.9 ! root     3354:                        x_put_long (m68k_areg (regs, 7), regs.fp_opword);
        !          3355:                        m68k_areg (regs, 7) -= 4;
1.1.1.7   root     3356:             x_put_long (m68k_areg (regs, 7), oldpc);
                   3357:             break;
                   3358:         case 0x8: // bus and address error stack frame (68010)
                   3359:             write_log(_T("Exception stack frame format %X not implemented\n"), format);
                   3360:             return;
                   3361:         case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
1.1.1.9 ! root     3362:                        // or 68060 bus access fault stack frame
1.1.1.7   root     3363:                        m68k_areg (regs, 7) -= 4;
1.1.1.9 ! root     3364:                        x_put_long (m68k_areg (regs, 7), ssw);
1.1.1.7   root     3365:                        m68k_areg (regs, 7) -= 4;
1.1.1.9 ! root     3366:                        x_put_long (m68k_areg (regs, 7), oldpc);
1.1.1.7   root     3367:                        break;
                   3368:                case 0xB: // long bus cycle fault stack frame (68020, 68030)
                   3369:                        // We always use B frame because it is easier to emulate,
                   3370:                        // our PC always points at start of instruction but A frame assumes
                   3371:                        // it is + 2 and handling this properly is not easy.
                   3372:                        // Store state information to internal register space
                   3373:                        for (i = 0; i < mmu030_idx + 1; i++) {
                   3374:                                m68k_areg (regs, 7) -= 4;
                   3375:                                x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
                   3376:                        }
                   3377:                        while (i < 9) {
                   3378:                                uae_u32 v = 0;
                   3379:                                m68k_areg (regs, 7) -= 4;
                   3380:                                // mmu030_idx is always small enough if instruction is FMOVEM.
                   3381:                                if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
                   3382:                                        if (i == 7)
                   3383:                                                v = mmu030_fmovem_store[0];
                   3384:                                        else if (i == 8)
                   3385:                                                v = mmu030_fmovem_store[1];
                   3386:                                }
                   3387:                                x_put_long (m68k_areg (regs, 7), v);
                   3388:                                i++;
                   3389:                        }
                   3390:                         // version & internal information (We store index here)
                   3391:                        m68k_areg (regs, 7) -= 2;
                   3392:                        x_put_word (m68k_areg (regs, 7), mmu030_idx);
                   3393:                        // 3* internal registers
                   3394:                        m68k_areg (regs, 7) -= 2;
                   3395:                        x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
                   3396:                        m68k_areg (regs, 7) -= 2;
                   3397:                        x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
                   3398:                        m68k_areg (regs, 7) -= 2;
                   3399:                        x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
                   3400:                        // data input buffer = fault address
                   3401:                        m68k_areg (regs, 7) -= 4;
                   3402:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3403:                        // 2xinternal
1.1.1.9 ! root     3404:                        {
        !          3405:                                uae_u32 ps = (regs.prefetch020_valid[0] ? 1 : 0) | (regs.prefetch020_valid[1] ? 2 : 0) | (regs.prefetch020_valid[2] ? 4 : 0);
        !          3406:                                ps |= ((regs.pipeline_r8[0] & 7) << 8);
        !          3407:                                ps |= ((regs.pipeline_r8[1] & 7) << 11);
        !          3408:                                ps |= ((regs.pipeline_pos & 15) << 16);
        !          3409:                                ps |= ((regs.pipeline_stop & 15) << 20);
        !          3410:                                if (mmu030_opcode == -1)
        !          3411:                                        ps |= 1 << 31;
        !          3412:                                m68k_areg (regs, 7) -= 4;
        !          3413:                                x_put_long (m68k_areg (regs, 7), ps);
        !          3414:                        }
1.1.1.7   root     3415:                        // stage b address
                   3416:                        m68k_areg (regs, 7) -= 4;
                   3417:                        x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
                   3418:                        // 2xinternal
                   3419:                        m68k_areg (regs, 7) -= 4;
                   3420:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
                   3421:                /* fall through */
                   3422:                case 0xA: // short bus cycle fault stack frame (68020, 68030)
                   3423:                        m68k_areg (regs, 7) -= 4;
                   3424:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
                   3425:                        m68k_areg (regs, 7) -= 4;
                   3426:                         // Data output buffer = value that was going to be written
                   3427:                        x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
                   3428:                        m68k_areg (regs, 7) -= 4;
1.1.1.9 ! root     3429:                        x_put_long (m68k_areg (regs, 7), (mmu030_opcode & 0xffff) | (regs.prefetch020[0] << 16));  // Internal register (opcode storage)
1.1.1.7   root     3430:                        m68k_areg (regs, 7) -= 4;
                   3431:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
                   3432:                        m68k_areg (regs, 7) -= 2;
1.1.1.9 ! root     3433:                        x_put_word (m68k_areg (regs, 7), regs.prefetch020[2]);  // Instr. pipe stage B
1.1.1.7   root     3434:                        m68k_areg (regs, 7) -= 2;
1.1.1.9 ! root     3435:                        x_put_word (m68k_areg (regs, 7), regs.prefetch020[1]);  // Instr. pipe stage C
1.1.1.7   root     3436:                        m68k_areg (regs, 7) -= 2;
                   3437:                        x_put_word (m68k_areg (regs, 7), ssw);
                   3438:                        m68k_areg (regs, 7) -= 2;
                   3439:                        x_put_word (m68k_areg (regs, 7), 0);  // Internal register
                   3440:                        break;
                   3441:                default:
                   3442:             write_log(_T("Unknown exception stack frame format: %X\n"), format);
                   3443:             return;
                   3444:     }
                   3445:     m68k_areg (regs, 7) -= 2;
                   3446:     x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
                   3447:     m68k_areg (regs, 7) -= 4;
                   3448:     x_put_long (m68k_areg (regs, 7), currpc);
                   3449:     m68k_areg (regs, 7) -= 2;
                   3450:     x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.4   root     3451: }
1.1.1.7   root     3452: 
1.1.1.9 ! root     3453: static void Exception_build_stack_frame_common (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr)
        !          3454: {
        !          3455:        if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
        !          3456:                Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
        !          3457:        } else if (nr == 60 || nr == 61) {
        !          3458:                Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
        !          3459:        } else if (nr >= 48 && nr <= 55) {
        !          3460:                if (regs.fpu_exp_pre) {
        !          3461:                        if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
        !          3462:                                Exception_build_stack_frame(regs.fp_ea, regs.instruction_pc, 0, nr, 0x2);
        !          3463:                        } else {
        !          3464:                                Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0);
        !          3465:                        }
        !          3466:                } else { /* post-instruction */
        !          3467:                        if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
        !          3468:                                Exception_build_stack_frame(regs.fp_ea, currpc, 0, nr, 0x2);
        !          3469:                        } else {
        !          3470:                                Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x3);
        !          3471:                        }
        !          3472:                }
        !          3473:        } else if (nr == 11 && regs.fp_unimp_ins) {
        !          3474:                regs.fp_unimp_ins = false;
        !          3475:                if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2))) ||
        !          3476:                        (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
        !          3477:                        Exception_build_stack_frame(regs.fp_ea, currpc, regs.instruction_pc, nr, 0x4);
        !          3478:                } else {
        !          3479:                        Exception_build_stack_frame(regs.fp_ea, currpc, regs.mmu_ssw, nr, 0x2);
        !          3480:                }
        !          3481:        } else {
        !          3482:                Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
        !          3483:        }
        !          3484: }
1.1.1.7   root     3485: 
                   3486: // 68030 MMU
                   3487: static void Exception_mmu030 (int nr, uaecptr oldpc)
                   3488: {
                   3489:     uae_u32 currpc = m68k_getpc (), newpc;
                   3490:        int interrupt;
                   3491: 
                   3492:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.4   root     3493: 
1.1.1.7   root     3494: #ifdef WINUAE_FOR_HATARI
                   3495:        if (interrupt)
                   3496:                nr = iack_cycle(nr);
                   3497: #endif
                   3498: 
                   3499: #ifdef WINUAE_FOR_HATARI
                   3500:        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",
                   3501:                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);
                   3502: #endif
                   3503:     exception_debug (nr);
                   3504:     MakeSR ();
                   3505:     
                   3506:     if (!regs.s) {
                   3507:         regs.usp = m68k_areg (regs, 7);
                   3508:         m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
                   3509:         regs.s = 1;
                   3510:         mmu_set_super (1);
                   3511:     }
                   3512:  
                   3513: #if 0
                   3514:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
                   3515:         write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
                   3516:                    nr, currpc, oldpc, regs.mmu_fault_addr);
                   3517:     }
                   3518: #endif
                   3519: 
1.1.1.9 ! root     3520:     newpc = x_get_long (regs.vbr + 4 * nr);
        !          3521: 
1.1.1.7   root     3522: #if 0
1.1.1.9 ! root     3523:        write_log (_T("Exception %d -> %08x\n"), nr, newpc);
1.1.1.7   root     3524: #endif
                   3525: 
                   3526:        if (regs.m && interrupt) { /* M + Interrupt */
                   3527:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                   3528:                MakeSR ();
                   3529:                regs.m = 0;
                   3530:                regs.msp = m68k_areg (regs, 7);
                   3531:                m68k_areg (regs, 7) = regs.isp;
                   3532:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
                   3533:     } else if (nr == 2) {
                   3534:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr,  0xB);
                   3535:     } else if (nr == 3) {
                   3536:                regs.mmu_fault_addr = last_fault_for_exception_3;
                   3537:                mmu030_state[0] = mmu030_state[1] = 0;
                   3538:                mmu030_data_buffer = 0;
                   3539:         Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr,  0xA);
1.1.1.9 ! root     3540:        } else {
        !          3541:                Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
        !          3542:        }
        !          3543: 
1.1.1.7   root     3544:        if (newpc & 1) {
                   3545:                if (nr == 2 || nr == 3)
1.1.1.8   root     3546:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3547:                else
                   3548:                        exception3_read(regs.ir, newpc);
                   3549:                return;
                   3550:        }
                   3551:        m68k_setpci (newpc);
                   3552:        fill_prefetch ();
1.1.1.8   root     3553:        exception_check_trace (nr);
1.1.1.7   root     3554: }
                   3555: 
                   3556: // 68040/060 MMU
1.1.1.4   root     3557: static void Exception_mmu (int nr, uaecptr oldpc)
                   3558: {
                   3559:        uae_u32 currpc = m68k_getpc (), newpc;
1.1.1.7   root     3560:        int interrupt;
1.1.1.4   root     3561: 
1.1.1.7   root     3562:        interrupt = nr >= 24 && nr < 24 + 8;
                   3563: 
1.1.1.9 ! root     3564:        // exception vector fetch and exception stack frame
        !          3565:        // operations don't allocate new cachelines
        !          3566:        cache_default_data |= CACHE_DISABLE_ALLOCATE;
        !          3567: 
1.1.1.7   root     3568: #ifdef WINUAE_FOR_HATARI
                   3569:        if (interrupt)
                   3570:                nr = iack_cycle(nr);
                   3571: #endif
                   3572: 
                   3573: #ifdef WINUAE_FOR_HATARI
                   3574:        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",
                   3575:                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);
                   3576: #endif
1.1.1.4   root     3577:        exception_debug (nr);
                   3578:        MakeSR ();
                   3579: 
                   3580:        if (!regs.s) {
                   3581:                regs.usp = m68k_areg (regs, 7);
1.1.1.8   root     3582:                if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) {
1.1.1.4   root     3583:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7   root     3584:                } else {
1.1.1.4   root     3585:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.7   root     3586:                }
1.1.1.4   root     3587:                regs.s = 1;
                   3588:                mmu_set_super (1);
                   3589:        }
1.1.1.8   root     3590: 
1.1.1.7   root     3591:        newpc = x_get_long (regs.vbr + 4 * nr);
                   3592: #if 0
                   3593:        write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
                   3594: #endif
1.1.1.5   root     3595: 
1.1.1.7   root     3596:        if (nr == 2) { // bus error
                   3597:         //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
                   3598:         if (currprefs.mmu_model == 68040)
                   3599:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
                   3600:                else
1.1.1.9 ! root     3601:                        Exception_build_stack_frame(regs.mmu_fault_addr, currpc, regs.mmu_fslw, nr, 0x4);
1.1.1.7   root     3602:        } else if (nr == 3) { // address error
                   3603:         Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
                   3604:                write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * nr));
                   3605:        } else if (regs.m && interrupt) { /* M + Interrupt */
1.1.1.8   root     3606:                Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                   3607:                MakeSR();
                   3608:                regs.m = 0;
                   3609:                if (currprefs.cpu_model < 68060) {
                   3610:                        regs.msp = m68k_areg(regs, 7);
                   3611:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
                   3612:                }
1.1.1.4   root     3613:        } else {
1.1.1.9 ! root     3614:                Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
1.1.1.4   root     3615:        }
1.1.1.7   root     3616:     
1.1.1.4   root     3617:        if (newpc & 1) {
                   3618:                if (nr == 2 || nr == 3)
1.1.1.8   root     3619:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3620:                else
1.1.1.7   root     3621:                        exception3_read(regs.ir, newpc);
1.1.1.4   root     3622:                return;
                   3623:        }
1.1.1.9 ! root     3624: 
        !          3625:        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
        !          3626: 
1.1.1.7   root     3627:        m68k_setpci (newpc);
                   3628:        fill_prefetch ();
1.1.1.8   root     3629:        exception_check_trace (nr);
1.1.1.4   root     3630: }
                   3631: 
1.1.1.7   root     3632: static void add_approximate_exception_cycles(int nr)
1.1.1.4   root     3633: {
1.1.1.7   root     3634:        int cycles;
                   3635: 
                   3636:        if (currprefs.cpu_model > 68000)
                   3637:                return;
                   3638: #ifndef WINUAE_FOR_HATARI
                   3639:        if (nr >= 24 && nr <= 31) {
                   3640:                /* Interrupts */
                   3641:                cycles = 44 + 4; 
                   3642: #else
                   3643:        if ( nr >= 24 && nr <= 31 ) {
1.1.1.8   root     3644:                /* Atari's specific interrupts take 56 cycles instead of 44 due to iack sequence */
                   3645:                /* We must subtract CPU_IACK_CYCLES_START cycles already counted into iack_cycle() */
1.1.1.7   root     3646:                if ( nr == 30 )                                 /* MFP/DSP */
1.1.1.8   root     3647:                        cycles = 44-CPU_IACK_CYCLES_START;
1.1.1.7   root     3648:                else if ( nr == 28 )                            /* VBL */
1.1.1.8   root     3649:                        cycles = 44-CPU_IACK_CYCLES_START;
1.1.1.7   root     3650:                else if ( nr == 26 )                            /* HBL */
1.1.1.8   root     3651:                        cycles = 44-CPU_IACK_CYCLES_START;
1.1.1.7   root     3652:                else
1.1.1.8   root     3653:                        cycles = 44+4;                          /* Other interrupts (not used in Atari machines) */
1.1.1.7   root     3654: #endif
                   3655:        } else if (nr >= 32 && nr <= 47) {
                   3656:                /* Trap (total is 34, but cpuemux.c already adds 4) */ 
                   3657:                cycles = 34 -4;
                   3658:        } else {
                   3659:                switch (nr)
                   3660:                {
                   3661:                        case 2: cycles = 50; break;             /* Bus error */
                   3662:                        case 3: cycles = 50; break;             /* Address error */
                   3663:                        case 4: cycles = 34; break;             /* Illegal instruction */
                   3664:                        case 5: cycles = 38; break;             /* Division by zero */
                   3665:                        case 6: cycles = 40; break;             /* CHK */
                   3666:                        case 7: cycles = 34; break;             /* TRAPV */
                   3667:                        case 8: cycles = 34; break;             /* Privilege violation */
                   3668:                        case 9: cycles = 34; break;             /* Trace */
                   3669:                        case 10: cycles = 34; break;    /* Line-A */
                   3670:                        case 11: cycles = 34; break;    /* Line-F */
                   3671:                        default:
                   3672:                        cycles = 4;
                   3673:                        break;
                   3674:                }
                   3675:        }
                   3676: #ifdef WINUAE_FOR_HATARI
                   3677:        M68000_AddCycles ( cycles );
                   3678: #endif
                   3679:        cycles = adjust_cycles(cycles * CYCLE_UNIT / 2);
                   3680:        x_do_cycles(cycles);
                   3681: }
                   3682: 
                   3683: static void Exception_normal (int nr)
                   3684: {
1.1.1.9 ! root     3685:        uae_u32 newpc;
        !          3686:        uae_u32 currpc = m68k_getpc();
        !          3687:        uae_u32 nextpc;
1.1.1.4   root     3688:        int sv = regs.s;
1.1.1.7   root     3689:        int interrupt;
                   3690:        int vector_nr = nr;
                   3691: 
1.1.1.9 ! root     3692:        cache_default_data |= CACHE_DISABLE_ALLOCATE;
        !          3693: 
1.1.1.7   root     3694:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.4   root     3695: 
1.1.1.7   root     3696: #ifndef WINUAE_FOR_HATARI
                   3697:        if (interrupt && currprefs.cpu_model <= 68010)
                   3698: #else
                   3699:        if (interrupt)
1.1.1.4   root     3700: #endif
1.1.1.7   root     3701:                vector_nr = iack_cycle(nr);
1.1.1.4   root     3702: 
                   3703:        exception_debug (nr);
                   3704:        MakeSR ();
                   3705: 
                   3706:        if (!regs.s) {
                   3707:                regs.usp = m68k_areg (regs, 7);
1.1.1.8   root     3708:                if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) {
1.1.1.4   root     3709:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7   root     3710:                } else {
1.1.1.4   root     3711:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.7   root     3712:                }
1.1.1.4   root     3713:                regs.s = 1;
                   3714:                if (currprefs.mmu_model)
                   3715:                        mmu_set_super (regs.s != 0);
                   3716:        }
1.1.1.7   root     3717: 
1.1.1.8   root     3718:        if ((m68k_areg(regs, 7) & 1) && currprefs.cpu_model < 68020) {
1.1.1.7   root     3719:                if (nr == 2 || nr == 3)
1.1.1.8   root     3720:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3721:                else
                   3722:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7));
                   3723:                return;
                   3724:        }
                   3725:        if ((nr == 2 || nr == 3) && exception_in_exception < 0) {
1.1.1.8   root     3726:                cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3727:                return;
                   3728:        }
                   3729: 
1.1.1.8   root     3730: #ifndef WINUAE_FOR_HATARI
                   3731:        if (!currprefs.cpu_compatible) {
                   3732:                addrbank *ab = &get_mem_bank(m68k_areg(regs, 7) - 4);
                   3733:                // Not plain RAM check because some CPU type tests that
                   3734:                // don't need to return set stack to ROM..
                   3735:                if (!ab || ab == &dummy_bank || (ab->flags & ABFLAG_IO)) {
                   3736:                        cpu_halt(CPU_HALT_SSP_IN_NON_EXISTING_ADDRESS);
                   3737:                        return;
                   3738:                }
                   3739:        }
                   3740: #endif
                   3741:        
1.1.1.9 ! root     3742:        bool used_exception_build_stack_frame = false;
        !          3743: 
1.1.1.7   root     3744:        if (currprefs.cpu_model > 68000) {
1.1.1.9 ! root     3745:                uae_u32 oldpc = regs.instruction_pc;
        !          3746:                nextpc = exception_pc (nr);
1.1.1.7   root     3747: #ifdef WINUAE_FOR_HATARI
                   3748:                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",
                   3749:                        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);
                   3750: #endif
                   3751:                if (nr == 2 || nr == 3) {
                   3752:                        int i;
1.1.1.4   root     3753:                        if (currprefs.cpu_model >= 68040) {
                   3754:                                if (nr == 2) {
                   3755:                                        if (currprefs.mmu_model) {
1.1.1.7   root     3756:                                                // 68040 mmu bus error
1.1.1.4   root     3757:                                                for (i = 0 ; i < 7 ; i++) {
                   3758:                                                        m68k_areg (regs, 7) -= 4;
                   3759:                                                        x_put_long (m68k_areg (regs, 7), 0);
                   3760:                                                }
                   3761:                                                m68k_areg (regs, 7) -= 4;
                   3762:                                                x_put_long (m68k_areg (regs, 7), regs.wb3_data);
                   3763:                                                m68k_areg (regs, 7) -= 4;
                   3764:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3765:                                                m68k_areg (regs, 7) -= 4;
                   3766:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3767:                                                m68k_areg (regs, 7) -= 2;
                   3768:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3769:                                                m68k_areg (regs, 7) -= 2;
                   3770:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3771:                                                m68k_areg (regs, 7) -= 2;
                   3772:                                                x_put_word (m68k_areg (regs, 7), regs.wb3_status);
                   3773:                                                regs.wb3_status = 0;
                   3774:                                                m68k_areg (regs, 7) -= 2;
                   3775:                                                x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
                   3776:                                                m68k_areg (regs, 7) -= 4;
                   3777:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3778: 
                   3779:                                                m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3780:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4   root     3781:                                                m68k_areg (regs, 7) -= 4;
1.1.1.7   root     3782:                                                x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     3783:                                                m68k_areg (regs, 7) -= 2;
                   3784:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.7   root     3785:                                                newpc = x_get_long (regs.vbr + 4 * vector_nr);
1.1.1.4   root     3786:                                                if (newpc & 1) {
                   3787:                                                        if (nr == 2 || nr == 3)
1.1.1.8   root     3788:                                                                cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3789:                                                        else
1.1.1.7   root     3790:                                                                exception3_read(regs.ir, newpc);
1.1.1.4   root     3791:                                                        return;
                   3792:                                                }
                   3793:                                                m68k_setpc (newpc);
                   3794: #ifdef JIT
                   3795:                                                set_special (SPCFLAG_END_COMPILE);
                   3796: #endif
1.1.1.8   root     3797:                                                exception_check_trace (nr);
1.1.1.4   root     3798:                                                return;
                   3799: 
                   3800:                                        } else {
                   3801: 
1.1.1.7   root     3802:                                                // 68040 bus error (not really, some garbage?)
1.1.1.4   root     3803:                                                for (i = 0 ; i < 18 ; i++) {
                   3804:                                                        m68k_areg (regs, 7) -= 2;
                   3805:                                                        x_put_word (m68k_areg (regs, 7), 0);
                   3806:                                                }
                   3807:                                                m68k_areg (regs, 7) -= 4;
                   3808:                                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   3809:                                                m68k_areg (regs, 7) -= 2;
                   3810:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3811:                                                m68k_areg (regs, 7) -= 2;
                   3812:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3813:                                                m68k_areg (regs, 7) -= 2;
                   3814:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3815:                                                m68k_areg (regs, 7) -= 2;
                   3816:                                                x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
                   3817:                                                m68k_areg (regs, 7) -= 4;
                   3818:                                                x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
                   3819:                                                m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3820:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4   root     3821:                                                m68k_areg (regs, 7) -= 4;
1.1.1.7   root     3822:                                                x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     3823:                                                m68k_areg (regs, 7) -= 2;
                   3824:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
                   3825:                                                goto kludge_me_do;
                   3826: 
                   3827:                                        }
                   3828: 
                   3829:                                } else {
                   3830:                                        m68k_areg (regs, 7) -= 4;
                   3831:                                        x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   3832:                                        m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3833:                                        x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
1.1.1.4   root     3834:                                }
                   3835:                        } else {
1.1.1.7   root     3836:                                // 68020 address error
1.1.1.4   root     3837:                                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   3838:                                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
                   3839:                                ssw |= 0x20;
                   3840:                                for (i = 0 ; i < 36; i++) {
                   3841:                                        m68k_areg (regs, 7) -= 2;
                   3842:                                        x_put_word (m68k_areg (regs, 7), 0);
                   3843:                                }
                   3844:                                m68k_areg (regs, 7) -= 4;
                   3845:                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   3846:                                m68k_areg (regs, 7) -= 2;
                   3847:                                x_put_word (m68k_areg (regs, 7), 0);
                   3848:                                m68k_areg (regs, 7) -= 2;
                   3849:                                x_put_word (m68k_areg (regs, 7), 0);
                   3850:                                m68k_areg (regs, 7) -= 2;
                   3851:                                x_put_word (m68k_areg (regs, 7), 0);
                   3852:                                m68k_areg (regs, 7) -= 2;
                   3853:                                x_put_word (m68k_areg (regs, 7), ssw);
                   3854:                                m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3855:                                x_put_word (m68k_areg (regs, 7), 0xb000 + vector_nr * 4);
1.1.1.4   root     3856:                        }
1.1.1.7   root     3857:                        write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, regs.instruction_pc, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
                   3858:                } else if (regs.m && interrupt) { /* M + Interrupt */
1.1.1.4   root     3859:                        m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3860:                        x_put_word (m68k_areg (regs, 7), vector_nr * 4);
1.1.1.8   root     3861:                        if (currprefs.cpu_model < 68060) {
                   3862:                                m68k_areg (regs, 7) -= 4;
                   3863:                                x_put_long (m68k_areg (regs, 7), currpc);
                   3864:                                m68k_areg (regs, 7) -= 2;
                   3865:                                x_put_word (m68k_areg (regs, 7), regs.sr);
                   3866:                                regs.sr |= (1 << 13);
                   3867:                                regs.msp = m68k_areg(regs, 7);
                   3868:                                regs.m = 0;
                   3869:                                m68k_areg(regs, 7) = regs.isp;
                   3870:                                m68k_areg (regs, 7) -= 2;
                   3871:                                x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
                   3872:                        }
1.1.1.4   root     3873:                } else {
1.1.1.9 ! root     3874:                        Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
        !          3875:                        used_exception_build_stack_frame = true;
1.1.1.7   root     3876:                }
1.1.1.9 ! root     3877:        } else {
1.1.1.7   root     3878:                add_approximate_exception_cycles(nr);
1.1.1.9 ! root     3879:                nextpc = m68k_getpc ();
1.1.1.7   root     3880: #ifdef WINUAE_FOR_HATARI
                   3881:                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",
                   3882:                        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);
                   3883: #endif
                   3884:                if (nr == 2 || nr == 3) {
                   3885:                        // 68000 address error
                   3886:                        uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   3887:                        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
                   3888:                        mode |= last_notinstruction_for_exception_3 ? 8 : 0;
                   3889:                        // undocumented bits seem to contain opcode
                   3890:                        mode |= last_op_for_exception_3 & ~31;
                   3891:                        m68k_areg (regs, 7) -= 14;
                   3892:                        exception_in_exception = -1;
                   3893:                        x_put_word (m68k_areg (regs, 7) + 0, mode);
                   3894:                        x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
                   3895:                        x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
                   3896:                        x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
                   3897:                        x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
1.1.1.8   root     3898: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     3899:                        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));
1.1.1.8   root     3900: #else
                   3901:                        if (nr != 2 || last_fault_for_exception_3 != 0xff8a00 || currpc < TosAddress || currpc > TosAddress + TosSize)
                   3902:                                fprintf(stderr,"%s Error at address $%x, PC=$%x addr_e3=%x op_e3=%x\n", nr==2?"Bus":"Address",
                   3903:                                        last_fault_for_exception_3, currpc, last_addr_for_exception_3 , last_op_for_exception_3);
1.1.1.7   root     3904: #endif
                   3905:                        goto kludge_me_do;
1.1.1.4   root     3906:                }
                   3907:        }
1.1.1.9 ! root     3908:        if (!used_exception_build_stack_frame) {
        !          3909:                m68k_areg (regs, 7) -= 4;
        !          3910:                x_put_long (m68k_areg (regs, 7), nextpc);
        !          3911:                m68k_areg (regs, 7) -= 2;
        !          3912:                x_put_word (m68k_areg (regs, 7), regs.sr);
        !          3913:        }
1.1.1.8   root     3914:        if (currprefs.cpu_model == 68060 && interrupt) {
                   3915:                regs.m = 0;
                   3916:        }
1.1.1.4   root     3917: kludge_me_do:
1.1.1.7   root     3918:        newpc = x_get_long (regs.vbr + 4 * vector_nr);
                   3919:        exception_in_exception = 0;
1.1.1.4   root     3920:        if (newpc & 1) {
                   3921:                if (nr == 2 || nr == 3)
1.1.1.8   root     3922:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3923:                else
1.1.1.7   root     3924:                        exception3_notinstruction(regs.ir, newpc);
1.1.1.4   root     3925:                return;
                   3926:        }
                   3927:        m68k_setpc (newpc);
1.1.1.9 ! root     3928:        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
1.1.1.8   root     3929: #ifdef WINUAE_FOR_HATARI
                   3930:        /* Update IPL / interrupts state, in case a new interrupt happened during this exception */
                   3931:        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3932:                CALL_VAR(PendingInterruptFunction);
                   3933: #endif
1.1.1.4   root     3934: #ifdef JIT
                   3935:        set_special (SPCFLAG_END_COMPILE);
                   3936: #endif
1.1.1.7   root     3937:        fill_prefetch ();
1.1.1.8   root     3938:        exception_check_trace (nr);
1.1.1.4   root     3939: }
                   3940: 
1.1.1.7   root     3941: // address = format $2 stack frame address field
                   3942: static void ExceptionX (int nr, uaecptr address)
1.1.1.4   root     3943: {
1.1.1.7   root     3944:        regs.exception = nr;
                   3945:        if (cpu_tracer) {
                   3946:                cputrace.state = nr;
1.1.1.6   root     3947:        }
                   3948: 
1.1.1.8   root     3949: #ifdef WINUAE_FOR_HATARI
                   3950:        /* Handle Hatari GEM and BIOS traps */
                   3951:        if (nr == 0x22) {
                   3952:                /* Intercept VDI & AES exceptions (Trap #2) */
                   3953:                if (bVdiAesIntercept && VDI_AES_Entry()) {
                   3954:                        /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
                   3955:                         * This will call OpCode_VDI() after completion of Trap call!
                   3956:                         * Used to modify specific VDI return vectors contents. */
                   3957:                        VDI_OldPC = m68k_getpc();
                   3958:                        m68k_setpc(CART_VDI_OPCODE_ADDR);
                   3959:                }
                   3960:        }
                   3961:        else if (nr == 0x2d) {
                   3962:                /* Intercept BIOS (Trap #13) calls */
                   3963:                if (Bios()) {
                   3964:                        fill_prefetch ();
                   3965:                        regs.exception = 0;
                   3966:                        return;
                   3967:                }
                   3968:        }
                   3969:        else if (nr == 0x2e) {
                   3970:                /* Intercept XBIOS (Trap #14) calls */
                   3971:                if (XBios()) {
                   3972:                        fill_prefetch ();
                   3973:                        regs.exception = 0;
                   3974:                        return;
                   3975:                }
                   3976:        }
                   3977: #endif
                   3978: 
1.1.1.7   root     3979: #ifdef JIT
                   3980:        if (currprefs.cachesize)
                   3981:                regs.instruction_pc = address == -1 ? m68k_getpc () : address;
                   3982: #endif
                   3983: #ifdef CPUEMU_13
                   3984:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010)
                   3985:                Exception_ce000 (nr);
1.1.1.4   root     3986:        else
                   3987: #endif
1.1.1.7   root     3988:                if (currprefs.mmu_model) {
                   3989:                        if (currprefs.cpu_model == 68030)
                   3990:                                Exception_mmu030 (nr, m68k_getpc ());
                   3991:                        else
                   3992:                                Exception_mmu (nr, m68k_getpc ());
                   3993:                } else {
                   3994:                        Exception_normal (nr);
                   3995:                }
1.1.1.4   root     3996: 
1.1.1.7   root     3997: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     3998:        if (debug_illegal && !in_rom (M68K_GETPC)) {
                   3999:                if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
1.1.1.7   root     4000:                        write_log (_T("Exception %d breakpoint\n"), nr);
1.1.1.4   root     4001:                        activate_debugger ();
                   4002:                }
                   4003:        }
                   4004: #endif
1.1.1.7   root     4005:        regs.exception = 0;
                   4006:        if (cpu_tracer) {
                   4007:                cputrace.state = 0;
                   4008:        }
                   4009: }
                   4010: 
1.1.1.9 ! root     4011: void REGPARAM2 Exception_cpu(int nr)
        !          4012: {
        !          4013:        bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
        !          4014:        ExceptionX (nr, -1);
        !          4015:        // check T0 trace
        !          4016:        if (t0) {
        !          4017:                activate_trace();
        !          4018:        }
        !          4019: }
1.1.1.7   root     4020: void REGPARAM2 Exception (int nr)
                   4021: {
                   4022:        ExceptionX (nr, -1);
                   4023: }
                   4024: void REGPARAM2 ExceptionL (int nr, uaecptr address)
                   4025: {
                   4026:        ExceptionX (nr, address);
1.1.1.4   root     4027: }
                   4028: 
1.1.1.9 ! root     4029: static void bus_error(void)
        !          4030: {
        !          4031:        TRY (prb2) {
        !          4032:                Exception (2);
        !          4033:        } CATCH (prb2) {
        !          4034:                cpu_halt (CPU_HALT_BUS_ERROR_DOUBLE_FAULT);
        !          4035:        } ENDTRY
        !          4036: }
        !          4037: 
1.1.1.7   root     4038: static void do_interrupt (int nr)
1.1.1.4   root     4039: {
1.1.1.7   root     4040: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4041:        if (debug_dma)
                   4042:                record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
1.1.1.7   root     4043: 
                   4044:        if (inputrecord_debug & 2) {
                   4045:                if (input_record > 0)
                   4046:                        inprec_recorddebug_cpu (2);
                   4047:                else if (input_play > 0)
                   4048:                        inprec_playdebug_cpu (2);
                   4049:        }
1.1.1.4   root     4050: #endif
                   4051: 
1.1.1.8   root     4052:        m68k_unset_stop();
1.1.1.4   root     4053:        assert (nr < 8 && nr >= 0);
                   4054: 
1.1.1.8   root     4055:        for (;;) {
                   4056:                Exception (nr + 24);
                   4057:                regs.intmask = nr;
                   4058:                if (!currprefs.cpu_compatible || currprefs.cpu_model == 68060)
                   4059:                        break;
                   4060:                if (m68k_interrupt_delay)
                   4061:                        nr = regs.ipl;
                   4062:                else
                   4063:                        nr = intlev();
                   4064:                if (nr <= 0 || regs.intmask >= nr)
                   4065:                        break;
                   4066:        }
1.1.1.4   root     4067: 
                   4068:        doint ();
                   4069: }
                   4070: 
                   4071: void NMI (void)
                   4072: {
1.1.1.7   root     4073:        do_interrupt (7);
1.1.1.4   root     4074: }
                   4075: 
1.1.1.7   root     4076: static void m68k_reset_sr(void)
1.1.1.4   root     4077: {
1.1.1.7   root     4078:        SET_XFLG ((regs.sr >> 4) & 1);
                   4079:        SET_NFLG ((regs.sr >> 3) & 1);
                   4080:        SET_ZFLG ((regs.sr >> 2) & 1);
                   4081:        SET_VFLG ((regs.sr >> 1) & 1);
                   4082:        SET_CFLG (regs.sr & 1);
                   4083:        regs.t1 = (regs.sr >> 15) & 1;
                   4084:        regs.t0 = (regs.sr >> 14) & 1;
                   4085:        regs.s  = (regs.sr >> 13) & 1;
                   4086:        regs.m  = (regs.sr >> 12) & 1;
                   4087:        regs.intmask = (regs.sr >> 8) & 7;
                   4088:        /* set stack pointer */
                   4089:        if (regs.s)
                   4090:                m68k_areg (regs, 7) = regs.isp;
                   4091:        else
                   4092:                m68k_areg (regs, 7) = regs.usp;
1.1.1.4   root     4093: }
                   4094: 
1.1.1.7   root     4095: static void m68k_reset2(bool hardreset)
1.1.1.4   root     4096: {
1.1.1.7   root     4097:        uae_u32 v;
1.1.1.4   root     4098: 
1.1.1.7   root     4099:        regs.halted = 0;
                   4100: #ifndef WINUAE_FOR_HATARI
                   4101:        gui_data.cpu_halted = 0;
                   4102:        gui_led (LED_CPU, 0, -1);
1.1.1.4   root     4103: #endif
                   4104: 
1.1.1.7   root     4105:        regs.spcflags = 0;
                   4106:        m68k_reset_delay = 0;
                   4107:        regs.ipl = regs.ipl_pin = 0;
1.1.1.4   root     4108: 
1.1.1.7   root     4109: #ifdef SAVESTATE
                   4110:        if (isrestore ()) {
                   4111:                m68k_reset_sr();
                   4112:                m68k_setpc_normal (regs.pc);
1.1.1.4   root     4113:                return;
                   4114:        } else {
1.1.1.7   root     4115:                m68k_reset_delay = currprefs.reset_delay;
                   4116:                set_special(SPCFLAG_CHECK);
1.1.1.4   root     4117:        }
                   4118: #endif
1.1.1.7   root     4119:        regs.s = 1;
                   4120: #ifndef WINUAE_FOR_HATARI
                   4121:        if (currprefs.cpuboard_type) {
1.1.1.8   root     4122:                uaecptr stack;
1.1.1.7   root     4123:                v = cpuboard_get_reset_pc(&stack);
                   4124:                m68k_areg (regs, 7) = stack;
1.1.1.4   root     4125:        } else {
1.1.1.7   root     4126:                v = get_long (4);
                   4127:                m68k_areg (regs, 7) = get_long (0);
1.1.1.8   root     4128:        }
1.1.1.4   root     4129: #else
1.1.1.7   root     4130:        v = get_long (4);
                   4131:        m68k_areg (regs, 7) = get_long (0);
1.1.1.4   root     4132: #endif
1.1.1.8   root     4133: 
1.1.1.7   root     4134:        m68k_setpc_normal(v);
1.1.1.4   root     4135:        regs.m = 0;
                   4136:        regs.stopped = 0;
                   4137:        regs.t1 = 0;
                   4138:        regs.t0 = 0;
                   4139:        SET_ZFLG (0);
                   4140:        SET_XFLG (0);
                   4141:        SET_CFLG (0);
                   4142:        SET_VFLG (0);
                   4143:        SET_NFLG (0);
                   4144:        regs.intmask = 7;
                   4145:        regs.vbr = regs.sfc = regs.dfc = 0;
                   4146:        regs.irc = 0xffff;
                   4147: #ifdef FPUEMU
                   4148:        fpu_reset ();
                   4149: #endif
                   4150:        regs.caar = regs.cacr = 0;
                   4151:        regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
                   4152:        regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
1.1.1.7   root     4153:        mmu_tt_modified (); 
1.1.1.4   root     4154:        if (currprefs.cpu_model == 68020) {
                   4155:                regs.cacr |= 8;
1.1.1.7   root     4156:                set_cpu_caches (false);
1.1.1.4   root     4157:        }
                   4158: 
                   4159:        mmufixup[0].reg = -1;
                   4160:        mmufixup[1].reg = -1;
1.1.1.9 ! root     4161:        mmu030_cache_state = CACHE_ENABLE_ALL;
        !          4162:        mmu_cache_state = CACHE_ENABLE_ALL;
        !          4163:        if (currprefs.cpu_model >= 68040) {
        !          4164:                set_cpu_caches(false);
        !          4165:        }
1.1.1.7   root     4166:        if (currprefs.mmu_model >= 68040) {
                   4167:                mmu_reset ();
                   4168:                mmu_set_tc (regs.tcr);
                   4169:                mmu_set_super (regs.s != 0);
                   4170:        } else if (currprefs.mmu_model == 68030) {
                   4171:                mmu030_reset (hardreset || regs.halted);
                   4172:        } else {
                   4173: #ifndef WINUAE_FOR_HATARI
                   4174:                a3000_fakekick (0);
                   4175: #endif
                   4176:                /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
                   4177:                fake_tc_030 &= ~0x80000000;
                   4178:                fake_tt0_030 &= ~0x80000000;
                   4179:                fake_tt1_030 &= ~0x80000000;
                   4180:                if (hardreset || regs.halted) {
                   4181:                        fake_srp_030 = fake_crp_030 = 0;
                   4182:                        fake_tt0_030 = fake_tt1_030 = fake_tc_030 = 0;
1.1.1.5   root     4183:                }
1.1.1.7   root     4184:                fake_mmusr_030 = 0;
1.1.1.4   root     4185:        }
                   4186: 
                   4187:        /* 68060 FPU is not compatible with 68040,
                   4188:        * 68060 accelerators' boot ROM disables the FPU
                   4189:        */
                   4190:        regs.pcr = 0;
                   4191:        if (currprefs.cpu_model == 68060) {
                   4192:                regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
                   4193:                regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
1.1.1.7   root     4194: #ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     4195:                if (currprefs.fpu_model == 0 || kickstart_rom)
1.1.1.7   root     4196:                        regs.pcr |= 2; /* disable FPU */
                   4197: #endif
                   4198:        }
1.1.1.9 ! root     4199: //     regs.ce020memcycles = 0;
        !          4200:        regs.ce020startcycle = regs.ce020endcycle = 0;
1.1.1.7   root     4201:        fill_prefetch ();
                   4202: }
1.1.1.8   root     4203: 
1.1.1.7   root     4204: void m68k_reset(void)
                   4205: {
                   4206:        m68k_reset2(false);
                   4207: }
                   4208: 
1.1.1.8   root     4209: #ifndef WINUAE_FOR_HATARI
                   4210: void cpu_change(int newmodel)
                   4211: {
                   4212:        if (newmodel == currprefs.cpu_model)
                   4213:                return;
                   4214:        fallback_new_cpu_model = newmodel;
                   4215:        cpu_halt(CPU_HALT_ACCELERATOR_CPU_FALLBACK);
                   4216: }
1.1.1.7   root     4217: 
1.1.1.8   root     4218: void cpu_fallback(int mode)
1.1.1.7   root     4219: {
1.1.1.8   root     4220:        int fallbackmodel;
                   4221:        if (currprefs.chipset_mask & CSMASK_AGA) {
                   4222:                fallbackmodel = 68020;
                   4223:        } else {
                   4224:                fallbackmodel = 68000;
                   4225:        }
                   4226:        if (mode < 0) {
                   4227:                if (currprefs.cpu_model > fallbackmodel) {
                   4228:                        cpu_change(fallbackmodel);
                   4229:                } else if (fallback_new_cpu_model) {
                   4230:                        cpu_change(fallback_new_cpu_model);
                   4231:                }
                   4232:        } else if (mode == 0) {
                   4233:                cpu_change(fallbackmodel);
                   4234:        } else if (mode) {
                   4235:                if (fallback_cpu_model) {
                   4236:                        cpu_change(fallback_cpu_model);
                   4237:                }
1.1.1.4   root     4238:        }
1.1.1.8   root     4239: }
                   4240: 
                   4241: static void cpu_do_fallback(void)
                   4242: {
                   4243:        bool fallbackmode = false;
                   4244:        if ((fallback_new_cpu_model < 68020 && !(currprefs.chipset_mask & CSMASK_AGA)) || (fallback_new_cpu_model == 68020 && (currprefs.chipset_mask & CSMASK_AGA))) {
                   4245:                // -> 68000/68010 or 68EC020
                   4246:                fallback_cpu_model = currprefs.cpu_model;
                   4247:                fallback_fpu_model = currprefs.fpu_model;
                   4248:                fallback_mmu_model = currprefs.mmu_model;
                   4249:                fallback_cpu_compatible = currprefs.cpu_compatible;
                   4250:                fallback_cpu_address_space_24 = currprefs.address_space_24;
                   4251:                changed_prefs.cpu_model = currprefs.cpu_model_fallback && fallback_new_cpu_model <= 68020 ? currprefs.cpu_model_fallback : fallback_new_cpu_model;
                   4252:                changed_prefs.fpu_model = 0;
                   4253:                changed_prefs.mmu_model = 0;
                   4254:                changed_prefs.cpu_compatible = true;
                   4255:                changed_prefs.address_space_24 = true;
                   4256:                memcpy(&fallback_regs, &regs, sizeof(struct regstruct));
                   4257:                fallback_regs.pc = M68K_GETPC;
                   4258:                fallbackmode = true;
                   4259:        } else {
                   4260:                // -> 68020+
                   4261:                changed_prefs.cpu_model = fallback_cpu_model;
                   4262:                changed_prefs.fpu_model = fallback_fpu_model;
                   4263:                changed_prefs.mmu_model = fallback_mmu_model;
                   4264:                changed_prefs.cpu_compatible = fallback_cpu_compatible;
                   4265:                changed_prefs.address_space_24 = fallback_cpu_address_space_24;
                   4266:                fallback_cpu_model = 0;
                   4267:        }
                   4268:        init_m68k();
                   4269:        m68k_reset2(false);
                   4270:        if (!fallbackmode) {
                   4271:                // restore original 68020+
                   4272:                memcpy(&regs, &fallback_regs, sizeof(regs));
                   4273:                restore_banks();
                   4274:                memory_restore();
                   4275:                memory_map_dump();
                   4276:                m68k_setpc(fallback_regs.pc);
                   4277:        } else {
1.1.1.9 ! root     4278:                // 68000/010/EC020
1.1.1.8   root     4279:                memory_restore();
                   4280:                expansion_cpu_fallback();
                   4281:                memory_map_dump();
                   4282:        }
                   4283: }
                   4284: 
                   4285: static void m68k_reset_restore(void)
                   4286: {
                   4287:        // hardreset and 68000/68020 fallback mode? Restore original mode.
                   4288:        if (fallback_cpu_model) {
                   4289:                fallback_new_cpu_model = fallback_cpu_model;
                   4290:                fallback_regs.pc = 0;
                   4291:                cpu_do_fallback();
                   4292:        }
                   4293: }
                   4294: #endif
                   4295:  
                   4296: void REGPARAM2 op_unimpl (uae_u16 opcode)
                   4297: {
                   4298:        static int warned;
                   4299:        if (warned < 20) {
                   4300:                write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
                   4301:                warned++;
                   4302:        }
                   4303:        ExceptionL (61, regs.instruction_pc);
1.1.1.4   root     4304: }
                   4305: 
1.1.1.7   root     4306: uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
1.1.1.4   root     4307: {
                   4308:        uaecptr pc = m68k_getpc ();
                   4309:        static int warned;
                   4310: 
1.1.1.7   root     4311: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4312:        int inrom = in_rom (pc);
                   4313:        int inrt = in_rtarea (pc);
                   4314: 
1.1.1.9 ! root     4315:        if ((opcode == 0x4afc || opcode == 0xfc4a) && !valid_address(pc, 4) && valid_address(pc - 4, 4)) {
        !          4316:                // PC fell off the end of RAM
        !          4317:                bus_error();
        !          4318:                return 4;
        !          4319:        }
        !          4320: 
1.1.1.4   root     4321:        if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
                   4322:                m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
1.1.1.7   root     4323:                m68k_incpc_normal (2);
                   4324:                fill_prefetch ();
1.1.1.4   root     4325:                return 4;
                   4326:        }
                   4327: 
1.1.1.7   root     4328:        if (opcode == 0x4E7B && inrom) {
                   4329:                if (get_long (0x10) == 0) {
                   4330:                        notify_user (NUMSG_KS68020);
                   4331:                        uae_restart (-1, NULL);
1.1.1.8   root     4332:                        m68k_setstopped();
                   4333:                        return 4;
1.1.1.7   root     4334:                }
1.1.1.4   root     4335:        }
                   4336: 
                   4337: #ifdef AUTOCONFIG
1.1.1.7   root     4338:        if (opcode == 0xFF0D && inrt) {
                   4339:                /* User-mode STOP replacement */
                   4340:                m68k_setstopped ();
                   4341:                return 4;
1.1.1.4   root     4342:        }
                   4343: 
                   4344:        if ((opcode & 0xF000) == 0xA000 && inrt) {
                   4345:                /* Calltrap. */
1.1.1.7   root     4346:                m68k_incpc_normal (2);
                   4347:                m68k_handle_trap(opcode & 0xFFF);
                   4348:                fill_prefetch ();
1.1.1.4   root     4349:                return 4;
                   4350:        }
                   4351: #endif
1.1.1.7   root     4352: #endif
1.1.1.4   root     4353: 
                   4354:        if ((opcode & 0xF000) == 0xF000) {
1.1.1.7   root     4355: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4356:                if (warned < 20) {
1.1.1.7   root     4357:                        write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
1.1.1.4   root     4358:                        warned++;
                   4359:                }
1.1.1.7   root     4360: #endif
                   4361:                Exception (0xB);
1.1.1.4   root     4362:                //activate_debugger ();
                   4363:                return 4;
                   4364:        }
                   4365:        if ((opcode & 0xF000) == 0xA000) {
1.1.1.7   root     4366: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4367:                if (warned < 20) {
1.1.1.7   root     4368:                        write_log(_T("A-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x28));
1.1.1.4   root     4369:                        warned++;
                   4370:                }
1.1.1.7   root     4371: #endif
                   4372:                Exception (0xA);
1.1.1.4   root     4373:                //activate_debugger();
                   4374:                return 4;
                   4375:        }
                   4376:        if (warned < 20) {
1.1.1.7   root     4377:                write_log (_T("Illegal instruction: %04x at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x10));
1.1.1.4   root     4378:                warned++;
                   4379:                //activate_debugger();
                   4380:        }
                   4381: 
1.1.1.7   root     4382:        Exception (4);
1.1.1.4   root     4383:        return 4;
                   4384: }
                   4385: 
                   4386: #ifdef CPUEMU_0
                   4387: 
1.1.1.9 ! root     4388: static bool mmu_op30_invea(uae_u32 opcode)
1.1.1.4   root     4389: {
1.1.1.9 ! root     4390:        int eamode = (opcode >> 3) & 7;
1.1.1.7   root     4391:        int rreg = opcode & 7;
1.1.1.9 ! root     4392: 
        !          4393:        // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
        !          4394:        if (eamode == 0 || eamode == 1 || eamode == 3 || eamode == 4 || eamode == 6 || (eamode == 7 && rreg > 1))
        !          4395:                return true;
        !          4396:        return false;
        !          4397: }
        !          4398: 
        !          4399: static bool mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          4400: {
1.1.1.7   root     4401:        int preg = (next >> 10) & 31;
                   4402:        int rw = (next >> 9) & 1;
                   4403:        int fd = (next >> 8) & 1;
1.1.1.9 ! root     4404:        int unused = (next & 0xff);
1.1.1.7   root     4405:        const TCHAR *reg = NULL;
1.1.1.8   root     4406: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     4407:        uae_u32 otc = fake_tc_030;
1.1.1.8   root     4408: #endif
1.1.1.7   root     4409:        int siz;
                   4410: 
1.1.1.9 ! root     4411:        if (mmu_op30_invea(opcode))
        !          4412:                return true;
        !          4413:        // unused low 8 bits must be zeroed
        !          4414:        if (unused)
        !          4415:                return true;
        !          4416:        // read and fd set?
        !          4417:        if (rw && fd)
1.1.1.7   root     4418:                return true;
1.1.1.5   root     4419: 
1.1.1.7   root     4420:        switch (preg)
                   4421:        {
                   4422:        case 0x10: // TC
                   4423:                reg = _T("TC");
                   4424:                siz = 4;
                   4425:                if (rw)
                   4426:                        x_put_long (extra, fake_tc_030);
                   4427:                else
                   4428:                        fake_tc_030 = x_get_long (extra);
                   4429:                break;
                   4430:        case 0x12: // SRP
                   4431:                reg = _T("SRP");
                   4432:                siz = 8;
                   4433:                if (rw) {
                   4434:                        x_put_long (extra, fake_srp_030 >> 32);
                   4435:                        x_put_long (extra + 4, (uae_u32)fake_srp_030);
                   4436:                } else {
                   4437:                        fake_srp_030 = (uae_u64)x_get_long (extra) << 32;
                   4438:                        fake_srp_030 |= x_get_long (extra + 4);
                   4439:                }
                   4440:                break;
                   4441:        case 0x13: // CRP
                   4442:                reg = _T("CRP");
                   4443:                siz = 8;
                   4444:                if (rw) {
                   4445:                        x_put_long (extra, fake_crp_030 >> 32);
                   4446:                        x_put_long (extra + 4, (uae_u32)fake_crp_030);
                   4447:                } else {
                   4448:                        fake_crp_030 = (uae_u64)x_get_long (extra) << 32;
                   4449:                        fake_crp_030 |= x_get_long (extra + 4);
                   4450:                }
                   4451:                break;
                   4452:        case 0x18: // MMUSR
1.1.1.9 ! root     4453:                if (fd) {
        !          4454:                        // FD must be always zero when MMUSR read or write
        !          4455:                        return true;
        !          4456:                }
1.1.1.7   root     4457:                reg = _T("MMUSR");
                   4458:                siz = 2;
                   4459:                if (rw)
                   4460:                        x_put_word (extra, fake_mmusr_030);
                   4461:                else
                   4462:                        fake_mmusr_030 = x_get_word (extra);
                   4463:                break;
                   4464:        case 0x02: // TT0
                   4465:                reg = _T("TT0");
                   4466:                siz = 4;
                   4467:                if (rw)
                   4468:                        x_put_long (extra, fake_tt0_030);
                   4469:                else
                   4470:                        fake_tt0_030 = x_get_long (extra);
                   4471:                break;
                   4472:        case 0x03: // TT1
                   4473:                reg = _T("TT1");
                   4474:                siz = 4;
                   4475:                if (rw)
                   4476:                        x_put_long (extra, fake_tt1_030);
                   4477:                else
                   4478:                        fake_tt1_030 = x_get_long (extra);
                   4479:                break;
                   4480:        }
1.1.1.4   root     4481: 
1.1.1.9 ! root     4482:        if (!reg)
1.1.1.7   root     4483:                return true;
1.1.1.9 ! root     4484: 
1.1.1.4   root     4485: #if MMUOP_DEBUG > 0
1.1.1.7   root     4486:        {
                   4487:                uae_u32 val;
                   4488:                if (siz == 8) {
                   4489:                        uae_u32 val2 = x_get_long (extra);
                   4490:                        val = x_get_long (extra + 4);
                   4491:                        if (rw)
                   4492:                                write_log (_T("PMOVE %s,%08X%08X"), reg, val2, val);
                   4493:                        else
                   4494:                                write_log (_T("PMOVE %08X%08X,%s"), val2, val, reg);
                   4495:                } else {
                   4496:                        if (siz == 4)
                   4497:                                val = x_get_long (extra);
                   4498:                        else
                   4499:                                val = x_get_word (extra);
                   4500:                        if (rw)
                   4501:                                write_log (_T("PMOVE %s,%08X"), reg, val);
                   4502:                        else
                   4503:                                write_log (_T("PMOVE %08X,%s"), val, reg);
1.1.1.4   root     4504:                }
1.1.1.7   root     4505:                write_log (_T(" PC=%08X\n"), pc);
                   4506:        }
1.1.1.4   root     4507: #endif
1.1.1.7   root     4508: #ifndef WINUAE_FOR_HATARI
                   4509:        if ((currprefs.cs_mbdmac & 1) && currprefs.mbresmem_low_size > 0) {
                   4510:                if (otc != fake_tc_030) {
                   4511:                        a3000_fakekick (fake_tc_030 & 0x80000000);
1.1.1.4   root     4512:                }
                   4513:        }
                   4514: #endif
1.1.1.7   root     4515:        return false;
1.1.1.4   root     4516: }
                   4517: 
1.1.1.7   root     4518: static bool mmu_op30fake_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
                   4519: {
1.1.1.9 ! root     4520:        int eamode = (opcode >> 3) & 7;
        !          4521:        int rreg = opcode & 7;
        !          4522:     int level = (next&0x1C00)>>10;
        !          4523:     int a = (next >> 8) & 1;
        !          4524: 
        !          4525:        if (mmu_op30_invea(opcode))
        !          4526:                return true;
        !          4527:     if (!level && a)
        !          4528:                return true;
        !          4529: 
1.1.1.7   root     4530: #if MMUOP_DEBUG > 0
                   4531:        TCHAR tmp[10];
                   4532: 
                   4533:        tmp[0] = 0;
                   4534:        if ((next >> 8) & 1)
                   4535:                _stprintf (tmp, _T(",A%d"), (next >> 4) & 15);
                   4536:        write_log (_T("PTEST%c %02X,%08X,#%X%s PC=%08X\n"),
                   4537:                ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
1.1.1.4   root     4538: #endif
1.1.1.7   root     4539:        fake_mmusr_030 = 0;
                   4540:        return false;
                   4541: }
1.1.1.4   root     4542: 
1.1.1.9 ! root     4543: static bool mmu_op30fake_pload (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          4544: {
        !          4545:        int unused = (next & (0x100 | 0x80 | 0x40 | 0x20));
        !          4546: 
        !          4547:        if (mmu_op30_invea(opcode))
        !          4548:                return true;
        !          4549:        if (unused)
        !          4550:                return true;
        !          4551:        write_log(_T("PLOAD\n"));
        !          4552:        return false;
        !          4553: }
        !          4554: 
1.1.1.7   root     4555: static bool mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
                   4556: {
1.1.1.9 ! root     4557:        int flushmode = (next >> 8) & 31;
1.1.1.7   root     4558:        int fc = next & 31;
                   4559:        int mask = (next >> 5) & 3;
1.1.1.9 ! root     4560:        int fc_bits = next & 0x7f;
1.1.1.7   root     4561:        TCHAR fname[100];
                   4562: 
                   4563:        switch (flushmode)
                   4564:        {
1.1.1.9 ! root     4565:        case 0x00:
        !          4566:                return mmu_op30fake_pload(pc, opcode, next, extra);
        !          4567:        case 0x18:
        !          4568:                if (mmu_op30_invea(opcode))
1.1.1.7   root     4569:                        return true;
                   4570:                _stprintf (fname, _T("FC=%x MASK=%x EA=%08x"), fc, mask, 0);
                   4571:                break;
1.1.1.9 ! root     4572:        case 0x10:
1.1.1.7   root     4573:                _stprintf (fname, _T("FC=%x MASK=%x"), fc, mask);
                   4574:                break;
1.1.1.9 ! root     4575:        case 0x04:
        !          4576:                if (fc_bits)
        !          4577:                        return true;
1.1.1.7   root     4578:                _tcscpy (fname, _T("ALL"));
                   4579:                break;
                   4580:        default:
                   4581:                return true;
                   4582:        }
                   4583: #if MMUOP_DEBUG > 0
                   4584:        write_log (_T("PFLUSH %s PC=%08X\n"), fname, pc);
                   4585: #endif
                   4586:        return false;
                   4587: }
                   4588: 
                   4589: // 68030 (68851) MMU instructions only
                   4590: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
                   4591: {
                   4592:        int type = extra >> 13;
1.1.1.9 ! root     4593:        bool fline = false;
1.1.1.7   root     4594: 
                   4595:        switch (type)
                   4596:        {
                   4597:        case 0:
                   4598:        case 2:
                   4599:        case 3:
1.1.1.9 ! root     4600:                if (currprefs.mmu_model)
        !          4601:                        fline = mmu_op30_pmove (pc, opcode, extra, extraa); 
        !          4602:                else
        !          4603:                        fline = mmu_op30fake_pmove (pc, opcode, extra, extraa);
1.1.1.7   root     4604:        break;
                   4605:        case 1:
1.1.1.9 ! root     4606:                if (currprefs.mmu_model)
        !          4607:                        fline = mmu_op30_pflush (pc, opcode, extra, extraa); 
        !          4608:                else
        !          4609:                        fline = mmu_op30fake_pflush (pc, opcode, extra, extraa);
1.1.1.7   root     4610:        break;
                   4611:        case 4:
1.1.1.9 ! root     4612:                if (currprefs.mmu_model)
        !          4613:                        fline = mmu_op30_ptest (pc, opcode, extra, extraa);
        !          4614:                else
        !          4615:                        fline = mmu_op30fake_ptest (pc, opcode, extra, extraa);
1.1.1.7   root     4616:        break;
                   4617:        }
1.1.1.9 ! root     4618:        if (fline) {
        !          4619:                m68k_setpc(pc);
        !          4620:                op_illg(opcode);
        !          4621:        }
        !          4622:        return fline;   
        !          4623: }
        !          4624: 
        !          4625: /* check if an address matches a ttr */
        !          4626: static int fake_mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super)
        !          4627: {
        !          4628:        if (ttr & MMU_TTR_BIT_ENABLED)  {       /* TTR enabled */
        !          4629:                uae_u8 msb, mask;
        !          4630: 
        !          4631:                msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24;
        !          4632:                mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16;
        !          4633: 
        !          4634:                if (!(msb & ~mask)) {
        !          4635: 
        !          4636:                        if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) {
        !          4637:                                if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) {
        !          4638:                                        return TTR_NO_MATCH;
        !          4639:                                }
        !          4640:                        }
        !          4641: 
        !          4642:                        return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH;
        !          4643:                }
        !          4644:        }
        !          4645:        return TTR_NO_MATCH;
        !          4646: }
        !          4647: 
        !          4648: static int fake_mmu_match_ttr(uaecptr addr, bool super, bool data)
        !          4649: {
        !          4650:        int res;
        !          4651: 
        !          4652:        if (data) {
        !          4653:                res = fake_mmu_do_match_ttr(regs.dtt0, addr, super);
        !          4654:                if (res == TTR_NO_MATCH)
        !          4655:                        res = fake_mmu_do_match_ttr(regs.dtt1, addr, super);
        !          4656:        } else {
        !          4657:                res = fake_mmu_do_match_ttr(regs.itt0, addr, super);
        !          4658:                if (res == TTR_NO_MATCH)
        !          4659:                        res = fake_mmu_do_match_ttr(regs.itt1, addr, super);
        !          4660:        }
        !          4661:        return res;
1.1.1.7   root     4662: }
                   4663: 
                   4664: // 68040+ MMU instructions only
                   4665: void mmu_op (uae_u32 opcode, uae_u32 extra)
                   4666: {
                   4667:        if (currprefs.mmu_model) {
                   4668:                mmu_op_real (opcode, extra);
                   4669:                return;
                   4670:        }
                   4671: #if MMUOP_DEBUG > 1
                   4672:        write_log (_T("mmu_op %04X PC=%08X\n"), opcode, m68k_getpc ());
                   4673: #endif
                   4674:        if ((opcode & 0xFE0) == 0x0500) {
                   4675:                /* PFLUSH */
                   4676:                regs.mmusr = 0;
                   4677: #if MMUOP_DEBUG > 0
                   4678:                write_log (_T("PFLUSH\n"));
                   4679: #endif
                   4680:                return;
1.1.1.9 ! root     4681:        } else if ((opcode & 0x0FD8) == 0x0548) {
1.1.1.7   root     4682:                if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
                   4683:                        /* PTEST */
1.1.1.9 ! root     4684:                        int regno = opcode & 7;
        !          4685:                        uae_u32 addr = m68k_areg(regs, regno);
        !          4686:                        bool write = (opcode & 32) == 0;
        !          4687:                        bool super = (regs.dfc & 4) != 0;
        !          4688:                        bool data = (regs.dfc & 3) != 2;
        !          4689: 
        !          4690:                        regs.mmusr = 0;
        !          4691:                        if (fake_mmu_match_ttr(addr, super, data) != TTR_NO_MATCH) {
        !          4692:                                regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
        !          4693:                        }
        !          4694:                        regs.mmusr |= addr & 0xfffff000;
1.1.1.7   root     4695: #if MMUOP_DEBUG > 0
1.1.1.9 ! root     4696:                        write_log (_T("PTEST%c %08x\n"), write ? 'W' : 'R', addr);
1.1.1.7   root     4697: #endif
                   4698:                        return;
                   4699:                }
1.1.1.9 ! root     4700:        } else if ((opcode & 0x0FB8) == 0x0588) {
1.1.1.7   root     4701:                /* PLPA */
                   4702:                if (currprefs.cpu_model == 68060) {
1.1.1.9 ! root     4703:                        int regno = opcode & 7;
        !          4704:                        uae_u32 addr = m68k_areg (regs, regno);
        !          4705:                        int write = (opcode & 0x40) == 0;
        !          4706:                        bool data = (regs.dfc & 3) != 2;
        !          4707:                        bool super = (regs.dfc & 4) != 0;
        !          4708: 
        !          4709:                        if (fake_mmu_match_ttr(addr, super, data) == TTR_NO_MATCH) {
        !          4710:                                m68k_areg (regs, regno) = addr;
        !          4711:                        }
1.1.1.7   root     4712: #if MMUOP_DEBUG > 0
                   4713:                        write_log (_T("PLPA\n"));
                   4714: #endif
                   4715:                        return;
                   4716:                }
                   4717:        }
                   4718: #if MMUOP_DEBUG > 0
                   4719:        write_log (_T("Unknown MMU OP %04X\n"), opcode);
                   4720: #endif
                   4721:        m68k_setpc_normal (m68k_getpc () - 2);
                   4722:        op_illg (opcode);
                   4723: }
                   4724: 
                   4725: #endif
                   4726: 
1.1.1.4   root     4727: static void do_trace (void)
                   4728: {
                   4729:        if (regs.t0 && currprefs.cpu_model >= 68020) {
1.1.1.9 ! root     4730:                // this is obsolete
        !          4731:                return;
        !          4732:        }
        !          4733:        if (regs.t1) {
        !          4734:                activate_trace();
1.1.1.4   root     4735:        }
                   4736: }
                   4737: 
1.1.1.8   root     4738: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     4739: static void check_uae_int_request(void)
                   4740: {
1.1.1.8   root     4741:        if (uae_int_requested) {
                   4742:                bool irq = false;
                   4743:                if (uae_int_requested & 0x00ff) {
1.1.1.7   root     4744:                        INTREQ_f(0x8000 | 0x0008);
1.1.1.8   root     4745:                        irq = true;
                   4746:                }
                   4747:                if (uae_int_requested & 0xff00) {
1.1.1.7   root     4748:                        INTREQ_f(0x8000 | 0x2000);
1.1.1.8   root     4749:                        irq = true;
                   4750:                }
                   4751:                if (uae_int_requested & 0xff0000) {
                   4752:                        if (!cpuboard_is_ppcboard_irq())
                   4753:                                atomic_and(&uae_int_requested, ~0x010000);
                   4754:                }
                   4755:                if (irq)
                   4756:                        doint();
1.1.1.7   root     4757:        }
1.1.1.8   root     4758: }
                   4759: #endif
                   4760: 
                   4761: void execute_other_cpu_single(void)
                   4762: {
                   4763: #ifdef WITH_X86
                   4764:        if (!x86_turbo_on)
                   4765:                return;
                   4766:        x86_bridge_execute_until(0);
1.1.1.7   root     4767: #endif
                   4768: }
1.1.1.4   root     4769: 
1.1.1.8   root     4770: bool execute_other_cpu(int until)
1.1.1.4   root     4771: {
1.1.1.8   root     4772: #ifdef WITH_X86
                   4773:        if (!x86_turbo_on)
                   4774:                return false;
                   4775:        if (!until)
                   4776:                until++;
                   4777:        x86_bridge_execute_until(until);
                   4778: #endif
                   4779:        return true;
                   4780: }
                   4781: 
                   4782: int cpu_sleep_millis(int ms)
                   4783: {
                   4784:        int ret = 0;
                   4785: #ifdef WITH_THREADED_CPU
                   4786:        cpu_semaphore_release();
                   4787: #endif
1.1.1.7   root     4788: #ifdef WITH_PPC
                   4789:        int state = ppc_state;
                   4790:        if (state)
                   4791:                uae_ppc_spinlock_release();
                   4792: #endif
1.1.1.8   root     4793: #ifdef WITH_X86
                   4794:        if (x86_turbo_on) {
                   4795:                execute_other_cpu(read_processor_time() + vsynctimebase / 20);
                   4796:        } else {
                   4797:                ret = sleep_millis_main(ms);
                   4798:        }
                   4799: #endif
1.1.1.7   root     4800: #ifdef WITH_PPC
                   4801:        if (state)
                   4802:                uae_ppc_spinlock_get();
                   4803: #endif
1.1.1.8   root     4804: #ifdef WITH_THREADED_CPU
                   4805:        cpu_semaphore_get();
1.1.1.7   root     4806: #endif
1.1.1.8   root     4807:        return ret;
1.1.1.7   root     4808: }
                   4809: 
                   4810: #define PPC_HALTLOOP_SCANLINES 25
                   4811: // ppc_cpu_idle
                   4812: // 0 = busy
                   4813: // 1-9 = wait, levels
                   4814: // 10 = max wait
                   4815: 
1.1.1.8   root     4816: #ifndef WINUAE_FOR_HATARI
                   4817: static bool haltloop_do(int vsynctimeline, int rpt_end, int lines)
                   4818: {
                   4819:        int ovpos = vpos;
                   4820:        while (lines-- >= 0) {
                   4821:                ovpos = vpos;
                   4822:                while (ovpos == vpos) {
                   4823:                        x_do_cycles(8 * CYCLE_UNIT);
                   4824:                        unset_special(SPCFLAG_UAEINT);
                   4825:                        check_uae_int_request();
                   4826: #ifdef WITH_PPC
                   4827:                        ppc_interrupt(intlev());
                   4828:                        uae_ppc_execute_check();
                   4829: #endif
                   4830:                        if (regs.spcflags & SPCFLAG_COPPER)
                   4831:                                do_copper();
                   4832:                        if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
                   4833:                                if (regs.spcflags & SPCFLAG_BRK) {
                   4834:                                        unset_special(SPCFLAG_BRK);
                   4835:        #ifdef DEBUGGER
                   4836:                                        if (debugging)
                   4837:                                                debug();
                   4838:        #endif
                   4839:                                }
                   4840:                                return true;
                   4841:                        }
                   4842:                }
                   4843: 
                   4844:                // sync chipset with real time
                   4845:                for (;;) {
                   4846:                        check_uae_int_request();
                   4847: #ifdef WITH_PPC
                   4848:                        ppc_interrupt(intlev());
                   4849:                        uae_ppc_execute_check();
                   4850: #endif
                   4851:                        if (event_wait)
                   4852:                                break;
                   4853:                        int d = read_processor_time() - rpt_end;
                   4854:                        if (d < -2 * vsynctimeline || d >= 0)
                   4855:                                break;
                   4856:                }
                   4857:        }
                   4858:        return false;
                   4859: }
                   4860: #endif
                   4861: 
1.1.1.7   root     4862: static bool haltloop(void)
                   4863: {
                   4864: #ifndef WINUAE_FOR_HATARI
                   4865: #ifdef WITH_PPC
                   4866:        if (regs.halted < 0) {
                   4867:                int rpt_end = 0;
                   4868:                int ovpos = vpos;
                   4869: 
                   4870:                while (regs.halted) {
                   4871:                        int vsynctimeline = vsynctimebase / (maxvpos_display + 1);
                   4872:                        int lines;
                   4873:                        int rpt_scanline = read_processor_time();
                   4874:                        int rpt_end = rpt_scanline + vsynctimeline;
                   4875: 
                   4876:                        // See expansion handling.
                   4877:                        // Dialog must be opened from main thread.
                   4878:                        if (regs.halted == -2) {
                   4879:                                regs.halted = -1;
                   4880:                                notify_user (NUMSG_UAEBOOTROM_PPC);
                   4881:                        }
                   4882: 
                   4883:                        if (currprefs.ppc_cpu_idle) {
                   4884: 
                   4885:                                int maxlines = 100 - (currprefs.ppc_cpu_idle - 1) * 10;
                   4886:                                int i;
                   4887: 
                   4888:                                event_wait = false;
                   4889:                                for (i = 0; i < ev_max; i++) {
                   4890:                                        if (i == ev_hsync)
                   4891:                                                continue;
                   4892:                                        if (i == ev_audio)
                   4893:                                                continue;
                   4894:                                        if (!eventtab[i].active)
                   4895:                                                continue;
                   4896:                                        if (eventtab[i].evtime - currcycle < maxlines * maxhpos * CYCLE_UNIT)
                   4897:                                                break;
                   4898:                                }
                   4899:                                if (currprefs.ppc_cpu_idle >= 10 || (i == ev_max && vpos > 0 && vpos < maxvpos - maxlines)) {
                   4900:                                        cpu_sleep_millis(1);
                   4901:                                }
                   4902:                                check_uae_int_request();
                   4903:                                uae_ppc_execute_check();
                   4904: 
                   4905:                                lines = (read_processor_time() - rpt_scanline) / vsynctimeline + 1;
                   4906: 
                   4907:                        } else {
                   4908: 
                   4909:                                event_wait = true;
                   4910:                                lines = 0;
                   4911: 
                   4912:                        }
                   4913: 
                   4914:                        if (lines > maxvpos / 2)
                   4915:                                lines = maxvpos / 2;
                   4916: 
1.1.1.8   root     4917:                        if (haltloop_do(vsynctimeline, rpt_end, lines))
                   4918:                                return true;
1.1.1.7   root     4919: 
1.1.1.4   root     4920:                }
1.1.1.7   root     4921: 
                   4922:        } else  {
1.1.1.4   root     4923: #endif
1.1.1.7   root     4924:                while (regs.halted) {
                   4925:                        static int prevvpos;
                   4926:                        if (vpos == 0 && prevvpos) {
                   4927:                                prevvpos = 0;
                   4928:                                cpu_sleep_millis(8);
                   4929:                        }
                   4930:                        if (vpos)
                   4931:                                prevvpos = 1;
                   4932:                        x_do_cycles(8 * CYCLE_UNIT);
                   4933: 
                   4934:                        if (regs.spcflags & SPCFLAG_COPPER)
                   4935:                                do_copper();
                   4936: 
                   4937:                        if (regs.spcflags) {
                   4938:                                if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
                   4939:                                        return true;
                   4940:                        }
                   4941:                }
                   4942: #ifdef WITH_PPC
1.1.1.4   root     4943:        }
1.1.1.7   root     4944: #endif
                   4945: 
                   4946:        return false;
                   4947: #else
                   4948:        /* In Hatari, we don't use the halt state, we do a reset */
                   4949:        return false;
                   4950: #endif
1.1.1.4   root     4951: }
                   4952: 
1.1.1.7   root     4953: #ifdef WITH_PPC
                   4954: static bool uae_ppc_poll_check_halt(void)
1.1.1.4   root     4955: {
1.1.1.7   root     4956:        if (regs.halted) {
                   4957:                if (haltloop())
                   4958:                        return true;
1.1.1.4   root     4959:        }
1.1.1.7   root     4960:        return false;
1.1.1.4   root     4961: }
1.1.1.7   root     4962: #endif
1.1.1.4   root     4963: 
                   4964: 
1.1.1.7   root     4965: // handle interrupt delay (few cycles)
                   4966: STATIC_INLINE bool time_for_interrupt (void)
1.1.1.4   root     4967: {
1.1.1.7   root     4968:        return regs.ipl > regs.intmask || regs.ipl == 7;
                   4969: }
1.1.1.4   root     4970: 
1.1.1.7   root     4971: void doint (void)
                   4972: {
                   4973: #ifdef WITH_PPC
                   4974:        if (ppc_state) {
                   4975:                if (!ppc_interrupt(intlev()))
                   4976:                        return;
1.1.1.4   root     4977:        }
1.1.1.7   root     4978: #endif
1.1.1.8   root     4979: //fprintf ( stderr , "doint1 %d ipl=%x ipl_pin=%x intmask=%x spcflags=%x\n" , m68k_interrupt_delay,regs.ipl, regs.ipl_pin , regs.intmask, regs.spcflags );
1.1.1.7   root     4980:        if (m68k_interrupt_delay) {
                   4981:                regs.ipl_pin = intlev ();
                   4982:                unset_special (SPCFLAG_INT);
1.1.1.8   root     4983: //fprintf ( stderr , "doint2 %d ipl=%x ipl_pin=%x intmask=%x spcflags=%x\n" , m68k_interrupt_delay,regs.ipl, regs.ipl_pin , regs.intmask, regs.spcflags );
1.1.1.7   root     4984:                return;
1.1.1.4   root     4985:        }
1.1.1.7   root     4986:        if (currprefs.cpu_compatible && currprefs.cpu_model < 68020)
                   4987:                set_special (SPCFLAG_INT);
                   4988:        else
                   4989:                set_special (SPCFLAG_DOINT);
1.1.1.4   root     4990: }
                   4991: 
                   4992: 
1.1.1.7   root     4993: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     4994: /*
                   4995:  * Handle special flags
                   4996:  */
                   4997: 
                   4998: static bool do_specialties_interrupt (int Pending)
                   4999: {
1.1.1.5   root     5000: #if ENABLE_DSP_EMU
                   5001:     /* Check for DSP int first (if enabled) (level 6) */
                   5002:     if (regs.spcflags & SPCFLAG_DSP) {
                   5003:        if (DSP_ProcessIRQ() == true)
                   5004:          return true;
                   5005:     }
                   5006: #endif
                   5007: 
                   5008:     /* Check for MFP ints (level 6) */
1.1.1.4   root     5009:     if (regs.spcflags & SPCFLAG_MFP) {
1.1.1.5   root     5010:        if (MFP_ProcessIRQ() == true)
1.1.1.4   root     5011:          return true;                                  /* MFP exception was generated, no higher interrupt can happen */
                   5012:     }
                   5013: 
                   5014:     /* No MFP int, check for VBL/HBL ints (levels 4/2) */
                   5015:     if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
                   5016:        int intr = intlev ();
                   5017:        /* SPCFLAG_DOINT will be enabled again in MakeFromSR to handle pending interrupts! */
                   5018: //     unset_special (SPCFLAG_DOINT);
                   5019:        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   5020:        if (intr != -1 && intr > regs.intmask) {
1.1.1.7   root     5021:            do_interrupt (intr);                        /* process the interrupt */
1.1.1.4   root     5022:            return true;
                   5023:        }
                   5024:     }
                   5025: 
                   5026:     return false;                                      /* no interrupt was found */
                   5027: }
1.1.1.7   root     5028: #endif
1.1.1.4   root     5029: 
1.1.1.7   root     5030: static int do_specialties (int cycles)
1.1.1.4   root     5031: {
1.1.1.7   root     5032:        if (regs.spcflags & SPCFLAG_MODE_CHANGE)
                   5033:                return 1;
                   5034:        
                   5035: #ifndef WINUAE_FOR_HATARI
                   5036:        if (regs.spcflags & SPCFLAG_CHECK) {
                   5037:                if (regs.halted) {
1.1.1.8   root     5038:                        if (regs.halted == CPU_HALT_ACCELERATOR_CPU_FALLBACK) {
                   5039:                                return 1;
                   5040:                        }
                   5041:                        unset_special(SPCFLAG_CHECK);
1.1.1.7   root     5042:                        if (haltloop())
                   5043:                                return 1;
                   5044:                }
                   5045:                if (m68k_reset_delay) {
                   5046:                        int vsynccnt = 60;
                   5047:                        int vsyncstate = -1;
                   5048:                        while (vsynccnt > 0 && !quit_program) {
                   5049:                                x_do_cycles(8 * CYCLE_UNIT);
                   5050:                                if (regs.spcflags & SPCFLAG_COPPER)
                   5051:                                        do_copper();
                   5052:                                if (timeframes != vsyncstate) {
                   5053:                                        vsyncstate = timeframes;
                   5054:                                        vsynccnt--;
                   5055:                                }
                   5056:                        }
                   5057:                }
                   5058:                m68k_reset_delay = 0;
                   5059:                unset_special(SPCFLAG_CHECK);
                   5060:        }
                   5061: #endif
                   5062: 
                   5063: #ifdef ACTION_REPLAY
                   5064: #ifdef ACTION_REPLAY_HRTMON
                   5065:        if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
                   5066:                int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size);
                   5067:                /* exit from HRTMon? */
                   5068:                if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
                   5069:                        hrtmon_hide ();
                   5070:                /* HRTMon breakpoint? (not via IRQ7) */
                   5071:                if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt)
                   5072:                        hrtmon_breakenter ();
                   5073:                if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
                   5074:                        hrtmon_enter ();
                   5075:        }
                   5076: #endif
                   5077:        if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) {
                   5078:                /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/
                   5079:                /*      write_log (_T("PC:%p\n"), m68k_getpc ());*/
                   5080: 
                   5081:                if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
                   5082:                        action_replay_enter ();
                   5083:                if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom ()) {
                   5084:                        action_replay_hide ();
                   5085:                        unset_special (SPCFLAG_ACTION_REPLAY);
                   5086:                }
                   5087:                if (action_replay_flag == ACTION_REPLAY_WAIT_PC) {
                   5088:                        /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/
                   5089:                        if (m68k_getpc () == wait_for_pc) {
                   5090:                                action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
                   5091:                        }
                   5092:                }
                   5093:        }
                   5094: #endif
                   5095: 
                   5096: #ifndef WINUAE_FOR_HATARI
                   5097:        if (regs.spcflags & SPCFLAG_COPPER)
                   5098:                do_copper ();
                   5099: #endif
                   5100: 
1.1.1.4   root     5101: #ifdef JIT
                   5102:        unset_special (SPCFLAG_END_COMPILE);   /* has done its job */
                   5103: #endif
                   5104: 
1.1.1.7   root     5105: #ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     5106:        while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && ((currprefs.waiting_blits && currprefs.cpu_model >= 68020) || !currprefs.blitter_cycle_exact)) {
1.1.1.4   root     5107:                int c = blitnasty ();
1.1.1.7   root     5108:                if (c < 0) {
                   5109:                        break;
                   5110:                } else if (c > 0) {
1.1.1.4   root     5111:                        cycles -= c * CYCLE_UNIT * 2;
                   5112:                        if (cycles < CYCLE_UNIT)
                   5113:                                cycles = 0;
1.1.1.7   root     5114:                } else {
1.1.1.4   root     5115:                        c = 4;
1.1.1.7   root     5116:                }
                   5117:                x_do_cycles (c * CYCLE_UNIT);
1.1.1.4   root     5118:                if (regs.spcflags & SPCFLAG_COPPER)
                   5119:                        do_copper ();
1.1.1.7   root     5120: #ifdef WITH_PPC
                   5121:                if (ppc_state)  {
                   5122:                        if (uae_ppc_poll_check_halt())
                   5123:                                return true;
                   5124:                        uae_ppc_execute_check();
                   5125:                }
                   5126: #endif
1.1.1.4   root     5127:        }
                   5128: #endif
                   5129: 
1.1.1.7   root     5130: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     5131:        if (regs.spcflags & SPCFLAG_BUSERROR) {
                   5132:                /* We can not execute bus errors directly in the memory handler
                   5133:                * functions since the PC should point to the address of the next
                   5134:                * instruction, so we're executing the bus errors here: */
                   5135:                unset_special(SPCFLAG_BUSERROR);
1.1.1.7   root     5136:                Exception(2);
1.1.1.4   root     5137:        }
1.1.1.7   root     5138: #endif
1.1.1.4   root     5139: 
                   5140:        if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.7   root     5141:                Exception (9);
1.1.1.4   root     5142: 
1.1.1.7   root     5143: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5144:        if (regs.spcflags & SPCFLAG_TRAP) {
                   5145:                unset_special (SPCFLAG_TRAP);
1.1.1.7   root     5146:                Exception (3);
1.1.1.4   root     5147:        }
1.1.1.7   root     5148: #endif
1.1.1.9 ! root     5149:        if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) {
        !          5150:                // 68000/68010 undocumented special case:
        !          5151:                // if STOP clears S-bit and T was not set:
        !          5152:                // cause privilege violation exception, PC pointing to following instruction.
        !          5153:                // If T was set before STOP: STOP works as documented.
        !          5154:                m68k_unset_stop();
        !          5155:                Exception(8);
        !          5156:        }
        !          5157: 
1.1.1.7   root     5158:        bool first = true;
                   5159:        while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
1.1.1.8   root     5160: //fprintf ( stderr , "stop wait %d %ld %ld\n" , currcycle , CyclesGlobalClockCounter );
                   5161:        isstopped:
1.1.1.9 ! root     5162: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     5163:                check_uae_int_request();
                   5164:                {
                   5165:                        if (bsd_int_requested)
                   5166:                                bsdsock_fake_int_handler ();
                   5167:                }
                   5168: #endif
                   5169: 
                   5170:                if (cpu_tracer > 0) {
                   5171:                        cputrace.stopped = regs.stopped;
                   5172:                        cputrace.intmask = regs.intmask;
                   5173:                        cputrace.sr = regs.sr;
                   5174:                        cputrace.state = 1;
                   5175:                        cputrace.pc = m68k_getpc ();
                   5176:                        cputrace.memoryoffset = 0;
                   5177:                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   5178:                        cputrace.readcounter = cputrace.writecounter = 0;
                   5179:                }
                   5180:                if (!first)
                   5181:                        x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
1.1.1.4   root     5182: 
1.1.1.7   root     5183: #ifdef WINUAE_FOR_HATARI
                   5184:                if (!first)
                   5185:                {
1.1.1.8   root     5186:                        if (currprefs.cpu_cycle_exact && !currprefs.mmu_model)
                   5187:                        {
                   5188:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   5189:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   5190:                                currcycle = 0;
                   5191:                        }
                   5192:                        else
1.1.1.7   root     5193:                                M68000_AddCycles(4);
                   5194:                }
1.1.1.4   root     5195: 
                   5196:                /* It is possible one or more ints happen at the same time */
1.1.1.5   root     5197:                /* We must process them during the same cpu cycle then choose the highest priority one */
                   5198:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
1.1.1.7   root     5199:                        CALL_VAR(PendingInterruptFunction);
1.1.1.5   root     5200:                if ( MFP_UpdateNeeded == true )
1.1.1.7   root     5201:                        MFP_UpdateIRQ ( 0 );
1.1.1.4   root     5202: 
1.1.1.5   root     5203:                /* Check is there's an interrupt to process (could be a delayed MFP interrupt) */
1.1.1.7   root     5204:                if (regs.spcflags & SPCFLAG_MFP) {
                   5205:                        MFP_DelayIRQ ();                        /* Handle IRQ propagation */
                   5206:                        M68000_Update_intlev ();                /* Refresh the list of pending interrupts */
1.1.1.5   root     5207:                }
1.1.1.7   root     5208: #endif
                   5209:                first = false;
                   5210: #ifndef WINUAE_FOR_HATARI
1.1.1.5   root     5211:                if (regs.spcflags & SPCFLAG_COPPER)
                   5212:                        do_copper ();
1.1.1.4   root     5213: #endif
                   5214: 
1.1.1.7   root     5215:                if (m68k_interrupt_delay) {
1.1.1.5   root     5216:                        ipl_fetch ();
                   5217:                        if (time_for_interrupt ()) {
1.1.1.7   root     5218:                                do_interrupt (regs.ipl);
1.1.1.5   root     5219:                        }
                   5220:                } else {
1.1.1.7   root     5221:                        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
                   5222:                                int intr = intlev ();
                   5223:                                unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   5224: #ifdef WITH_PPC
                   5225:                                bool m68kint = true;
                   5226:                                if (ppc_state) {
                   5227:                                        m68kint = ppc_interrupt(intr);
                   5228:                                }
                   5229:                                if (m68kint) {
1.1.1.4   root     5230: #endif
1.1.1.7   root     5231:                                        if (intr > 0 && intr > regs.intmask)
                   5232:                                                do_interrupt (intr);
                   5233: #ifdef WITH_PPC
                   5234:                                }
                   5235: #endif
                   5236:                        }
1.1.1.5   root     5237:                }
1.1.1.7   root     5238: 
                   5239:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
                   5240:                        m68k_resumestopped();
1.1.1.5   root     5241:                        return 1;
                   5242:                }
1.1.1.4   root     5243: 
1.1.1.7   root     5244: #ifdef WITH_PPC
                   5245:                if (ppc_state) {
                   5246:                        uae_ppc_execute_check();
                   5247:                        uae_ppc_poll_check_halt();
1.1.1.4   root     5248:                }
1.1.1.7   root     5249: #endif
                   5250: 
1.1.1.4   root     5251:        }
                   5252: 
                   5253:        if (regs.spcflags & SPCFLAG_TRACE)
                   5254:                do_trace ();
                   5255: 
1.1.1.8   root     5256: #ifndef WINUAE_FOR_HATARI
                   5257:        if (regs.spcflags & SPCFLAG_UAEINT) {
                   5258:                check_uae_int_request();
                   5259:                unset_special(SPCFLAG_UAEINT);
                   5260:        }
                   5261: #endif
                   5262: 
1.1.1.7   root     5263: #ifdef WINUAE_FOR_HATARI
                   5264:        if (regs.spcflags & SPCFLAG_MFP) {
                   5265:                MFP_DelayIRQ ();                        /* Handle IRQ propagation */
                   5266:                M68000_Update_intlev ();                /* Refresh the list of pending interrupts */
                   5267:        }
                   5268: #endif
                   5269: 
1.1.1.8   root     5270: //fprintf ( stderr , "dospec1 %d %d spcflags=%x ipl=%x ipl_pin=%x intmask=%x\n" , m68k_interrupt_delay,time_for_interrupt() , regs.spcflags , regs.ipl , regs.ipl_pin, regs.intmask );
1.1.1.7   root     5271:        if (m68k_interrupt_delay) {
1.1.1.4   root     5272:                if (time_for_interrupt ()) {
1.1.1.7   root     5273:                        do_interrupt (regs.ipl);
1.1.1.4   root     5274:                }
                   5275:        } else {
                   5276:                if (regs.spcflags & SPCFLAG_INT) {
                   5277:                        int intr = intlev ();
                   5278:                        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   5279:                        if (intr > 0 && (intr > regs.intmask || intr == 7))
1.1.1.7   root     5280:                                do_interrupt (intr);
1.1.1.4   root     5281:                }
                   5282:        }
                   5283: 
1.1.1.8   root     5284: //fprintf ( stderr , "dospec2 %d %d spcflags=%x ipl=%x ipl_pin=%x intmask=%x\n" , m68k_interrupt_delay,time_for_interrupt() , regs.spcflags , regs.ipl , regs.ipl_pin, regs.intmask );
1.1.1.4   root     5285:        if (regs.spcflags & SPCFLAG_DOINT) {
                   5286:                unset_special (SPCFLAG_DOINT);
                   5287:                set_special (SPCFLAG_INT);
                   5288:        }
1.1.1.8   root     5289: //fprintf ( stderr , "dospec3 %d %d spcflags=%x ipl=%x ipl_pin=%x intmask=%x\n" , m68k_interrupt_delay,time_for_interrupt() , regs.spcflags , regs.ipl , regs.ipl_pin, regs.intmask );
1.1.1.4   root     5290: 
1.1.1.7   root     5291: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     5292:        if (regs.spcflags & SPCFLAG_DEBUGGER)
1.1.1.4   root     5293:                DebugCpu_Check();
1.1.1.7   root     5294: #endif
1.1.1.4   root     5295: 
1.1.1.7   root     5296:        if (regs.spcflags & SPCFLAG_BRK) {
                   5297:                unset_special(SPCFLAG_BRK);
                   5298: #ifdef DEBUGGER
                   5299:                if (debugging) {
                   5300:                        debug();
                   5301:                        if (regs.stopped)
                   5302:                                goto isstopped;
                   5303:                }
                   5304: #endif
                   5305: #ifdef WINUAE_FOR_HATARI
                   5306:                return 1;                       /* Exit the upper run_xxx() function */
                   5307: #endif
1.1.1.4   root     5308:        }
1.1.1.7   root     5309: 
1.1.1.4   root     5310:        return 0;
                   5311: }
                   5312: 
                   5313: //static uae_u32 pcs[1000];
                   5314: 
1.1.1.7   root     5315: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5316: #if DEBUG_CD32CDTVIO
                   5317: 
                   5318: static uae_u32 cd32nextpc, cd32request;
                   5319: 
                   5320: static void out_cd32io2 (void)
                   5321: {
                   5322:        uae_u32 request = cd32request;
1.1.1.7   root     5323:        write_log (_T("%08x returned\n"), request);
                   5324:        //write_log (_T("ACTUAL=%d ERROR=%d\n"), get_long (request + 32), get_byte (request + 31));
1.1.1.4   root     5325:        cd32nextpc = 0;
                   5326:        cd32request = 0;
                   5327: }
                   5328: 
                   5329: static void out_cd32io (uae_u32 pc)
                   5330: {
                   5331:        TCHAR out[100];
                   5332:        int ioreq = 0;
                   5333:        uae_u32 request = m68k_areg (regs, 1);
                   5334: 
                   5335:        if (pc == cd32nextpc) {
                   5336:                out_cd32io2 ();
                   5337:                return;
                   5338:        }
                   5339:        out[0] = 0;
                   5340:        switch (pc)
                   5341:        {
                   5342:        case 0xe57cc0:
                   5343:        case 0xf04c34:
1.1.1.7   root     5344:                _stprintf (out, _T("opendevice"));
1.1.1.4   root     5345:                break;
                   5346:        case 0xe57ce6:
                   5347:        case 0xf04c56:
1.1.1.7   root     5348:                _stprintf (out, _T("closedevice"));
1.1.1.4   root     5349:                break;
                   5350:        case 0xe57e44:
                   5351:        case 0xf04f2c:
1.1.1.7   root     5352:                _stprintf (out, _T("beginio"));
1.1.1.4   root     5353:                ioreq = 1;
                   5354:                break;
                   5355:        case 0xe57ef2:
                   5356:        case 0xf0500e:
1.1.1.7   root     5357:                _stprintf (out, _T("abortio"));
1.1.1.4   root     5358:                ioreq = -1;
                   5359:                break;
                   5360:        }
                   5361:        if (out[0] == 0)
                   5362:                return;
                   5363:        if (cd32request)
1.1.1.7   root     5364:                write_log (_T("old request still not returned!\n"));
1.1.1.4   root     5365:        cd32request = request;
                   5366:        cd32nextpc = get_long (m68k_areg (regs, 7));
1.1.1.7   root     5367:        write_log (_T("%s A1=%08X\n"), out, request);
1.1.1.4   root     5368:        if (ioreq) {
                   5369:                static int cnt = 0;
                   5370:                int cmd = get_word (request + 28);
                   5371: #if 0
1.1.1.7   root     5372:                if (cmd == 33) {
                   5373:                        uaecptr data = get_long (request + 40);
                   5374:                        write_log (_T("CD_CONFIG:\n"));
                   5375:                        for (int i = 0; i < 16; i++) {
                   5376:                                write_log (_T("%08X=%08X\n"), get_long (data), get_long (data + 4));
                   5377:                                data += 8;
                   5378:                        }
                   5379:                }
                   5380: #endif
                   5381: #if 0
1.1.1.4   root     5382:                if (cmd == 37) {
                   5383:                        cnt--;
                   5384:                        if (cnt <= 0)
                   5385:                                activate_debugger ();
                   5386:                }
                   5387: #endif
1.1.1.7   root     5388:                write_log (_T("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n"),
                   5389:                        cmd, get_long (request + 40),
                   5390:                        get_long (request + 36), get_long (request + 44), M68K_GETPC);
1.1.1.4   root     5391:        }
                   5392:        if (ioreq < 0)
                   5393:                ;//activate_debugger ();
                   5394: }
                   5395: 
1.1.1.7   root     5396: #endif
                   5397: #endif
                   5398: 
1.1.1.4   root     5399: #ifndef CPUEMU_11
                   5400: 
                   5401: static void m68k_run_1 (void)
                   5402: {
                   5403: }
                   5404: 
                   5405: #else
                   5406: 
                   5407: /* It's really sad to have two almost identical functions for this, but we
                   5408: do it all for performance... :(
                   5409: This version emulates 68000's prefetch "cache" */
                   5410: static void m68k_run_1 (void)
                   5411: {
                   5412:        struct regstruct *r = &regs;
1.1.1.7   root     5413:        bool exit = false;
1.1.1.8   root     5414: 
                   5415:        Log_Printf(LOG_DEBUG, "m68k_run_1\n");
1.1.1.4   root     5416: 
1.1.1.7   root     5417:        while (!exit) {
                   5418:                TRY (prb) {
                   5419:                        while (!exit) {
                   5420:                                r->opcode = r->ir;
                   5421: 
                   5422:                                count_instr (r->opcode);
                   5423: 
                   5424: #ifdef WINUAE_FOR_HATARI
                   5425:                                //m68k_dumpstate_file(stderr, NULL);
                   5426:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   5427:                                {
                   5428:                                        int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4   root     5429: 
1.1.1.7   root     5430:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4   root     5431: 
1.1.1.7   root     5432:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   5433:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   5434:                                }
                   5435: #endif
1.1.1.4   root     5436: 
1.1.1.7   root     5437: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5438: #if DEBUG_CD32CDTVIO
1.1.1.7   root     5439:                                out_cd32io (m68k_getpc ());
                   5440: #endif
1.1.1.4   root     5441: #endif
                   5442: 
                   5443: #if 0
1.1.1.7   root     5444:                                int pc = m68k_getpc ();
                   5445:                                if (pc == 0xdff002)
                   5446:                                        write_log (_T("hip\n"));
                   5447:                                if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
                   5448:                                        memmove (pcs + 1, pcs, 998 * 4);
                   5449:                                        pcs[0] = pc;
                   5450:                                        //write_log (_T("%08X-%04X "), pc, r->opcode);
                   5451:                                }
1.1.1.4   root     5452: #endif
1.1.1.7   root     5453:                                do_cycles (cpu_cycles);
                   5454:                                r->instruction_pc = m68k_getpc ();
                   5455:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   5456:                                cpu_cycles = adjust_cycles (cpu_cycles);
                   5457: 
                   5458: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     5459:                                /* Also add some extra cycles to simulate some wait state */
                   5460:                                /* TODO  [NP] do this in all m68k_run_xx() */
                   5461:                                M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT + WaitStateCycles);
                   5462:                                WaitStateCycles = 0;
1.1.1.5   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:                                regs.ipl = regs.ipl_pin;
                   5480:                                if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010))
                   5481:                                        exit = true;
                   5482:                        }
                   5483:                } CATCH (prb) {
                   5484:                        bus_error();
                   5485:                        if (r->spcflags) {
                   5486:                                if (do_specialties(cpu_cycles))
                   5487:                                        exit = true;
                   5488:                        }
                   5489:                        regs.ipl = regs.ipl_pin;
                   5490:                } ENDTRY
                   5491:        }
                   5492: }
1.1.1.4   root     5493: 
                   5494: #endif /* CPUEMU_11 */
                   5495: 
1.1.1.7   root     5496: #ifndef CPUEMU_13
1.1.1.4   root     5497: 
                   5498: static void m68k_run_1_ce (void)
                   5499: {
                   5500: }
                   5501: 
                   5502: #else
                   5503: 
                   5504: /* cycle-exact m68k_run () */
                   5505: 
                   5506: static void m68k_run_1_ce (void)
                   5507: {
                   5508:        struct regstruct *r = &regs;
1.1.1.7   root     5509:        bool first = true;
                   5510:        bool exit = false;
1.1.1.8   root     5511: 
                   5512:        Log_Printf(LOG_DEBUG, "m68k_run_1_ce\n");
1.1.1.7   root     5513: 
                   5514:        while (!exit) {
                   5515:                TRY (prb) {
                   5516:                        if (first) {
                   5517:                                if (cpu_tracer < 0) {
                   5518:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                   5519:                                        r->ir = cputrace.ir;
                   5520:                                        r->irc = cputrace.irc;
                   5521:                                        r->sr = cputrace.sr;
                   5522:                                        r->usp = cputrace.usp;
                   5523:                                        r->isp = cputrace.isp;
                   5524:                                        r->intmask = cputrace.intmask;
                   5525:                                        r->stopped = cputrace.stopped;
                   5526:                                        m68k_setpc (cputrace.pc);
                   5527:                                        if (!r->stopped) {
                   5528:                                                if (cputrace.state > 1) {
                   5529:                                                        write_log (_T("CPU TRACE: EXCEPTION %d\n"), cputrace.state);
                   5530:                                                        Exception (cputrace.state);
                   5531:                                                } else if (cputrace.state == 1) {
                   5532:                                                        write_log (_T("CPU TRACE: %04X\n"), cputrace.opcode);
                   5533:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                   5534:                                                }
                   5535:                                        } else {
                   5536:                                                write_log (_T("CPU TRACE: STOPPED\n"));
                   5537:                                        }
                   5538:                                        if (r->stopped)
                   5539:                                                set_special (SPCFLAG_STOP);
                   5540:                                        set_cpu_tracer (false);
                   5541:                                        goto cont;
                   5542:                                }
                   5543:                                set_cpu_tracer (false);
                   5544:                                first = false;
                   5545:                        }
1.1.1.4   root     5546: 
1.1.1.7   root     5547:                        while (!exit) {
                   5548:                                r->opcode = r->ir;
1.1.1.4   root     5549: 
1.1.1.7   root     5550: #ifdef WINUAE_FOR_HATARI
                   5551:                                //m68k_dumpstate_file(stderr, NULL);
                   5552:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   5553:                                {
                   5554:                                        int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4   root     5555: 
1.1.1.7   root     5556:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4   root     5557: 
1.1.1.8   root     5558: //fprintf ( stderr , "clock %ld\n" , CyclesGlobalClockCounter );
1.1.1.7   root     5559:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   5560:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   5561:                                }
                   5562: #endif
                   5563: 
                   5564: #ifndef WINUAE_FOR_HATARI
                   5565: #if DEBUG_CD32CDTVIO
                   5566:                                out_cd32io (m68k_getpc ());
                   5567: #endif
                   5568: #endif
                   5569:                                if (cpu_tracer) {
                   5570:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
                   5571:                                        cputrace.opcode = r->opcode;
                   5572:                                        cputrace.ir = r->ir;
                   5573:                                        cputrace.irc = r->irc;
                   5574:                                        cputrace.sr = r->sr;
                   5575:                                        cputrace.usp = r->usp;
                   5576:                                        cputrace.isp = r->isp;
                   5577:                                        cputrace.intmask = r->intmask;
                   5578:                                        cputrace.stopped = r->stopped;
                   5579:                                        cputrace.state = 1;
                   5580:                                        cputrace.pc = m68k_getpc ();
                   5581:                                        cputrace.startcycles = get_cycles ();
                   5582:                                        cputrace.memoryoffset = 0;
                   5583:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   5584:                                        cputrace.readcounter = cputrace.writecounter = 0;
                   5585:                                }
                   5586: 
                   5587: #ifndef WINUAE_FOR_HATARI
                   5588:                                if (inputrecord_debug & 4) {
                   5589:                                        if (input_record > 0)
                   5590:                                                inprec_recorddebug_cpu (1);
                   5591:                                        else if (input_play > 0)
                   5592:                                                inprec_playdebug_cpu (1);
                   5593:                                }
                   5594: #endif
                   5595: 
                   5596: #ifdef WINUAE_FOR_HATARI
                   5597:                                currcycle = 0;
                   5598: #endif
                   5599: 
                   5600:                                r->instruction_pc = m68k_getpc ();
                   5601:                                (*cpufunctbl[r->opcode])(r->opcode);
                   5602:                                wait_memory_cycles();                   // TODO NP : ici, ou plus bas ?
                   5603: #ifdef WINUAE_FOR_HATARI
                   5604: //fprintf ( stderr, "cyc_1ce %d\n" , currcycle );
1.1.1.8   root     5605:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   5606:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   5607:                                currcycle = 0;
1.1.1.7   root     5608: 
                   5609:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   5610:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   5611:                                if ( MFP_UpdateNeeded == true )
                   5612:                                        MFP_UpdateIRQ ( 0 );
                   5613: #endif
                   5614: 
                   5615:                                if (cpu_tracer) {
                   5616:                                        cputrace.state = 0;
                   5617:                                }
                   5618: cont:
                   5619:                                if (cputrace.needendcycles) {
                   5620:                                        cputrace.needendcycles = 0;
                   5621:                                        write_log (_T("STARTCYCLES=%08x ENDCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
                   5622: #ifndef WINUAE_FOR_HATARI
                   5623:                                        log_dma_record ();
                   5624: #endif
                   5625:                                }
                   5626: 
                   5627:                                if (r->spcflags || time_for_interrupt ()) {
                   5628:                                        if (do_specialties (0))
                   5629:                                                exit = true;
                   5630:                                }
                   5631: 
                   5632:                                if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68010)
                   5633:                                        exit = true;
                   5634:                        }
                   5635:                } CATCH (prb) {
                   5636:                        bus_error();
                   5637:                        if (r->spcflags || time_for_interrupt()) {
                   5638:                                if (do_specialties(0))
                   5639:                                        exit = true;
                   5640:                        }
                   5641:                } ENDTRY
                   5642:        }
                   5643: }
                   5644: 
                   5645: #endif
                   5646: 
1.1.1.8   root     5647: #if defined(CPUEMU_20) && defined(JIT)
1.1.1.7   root     5648: // emulate simple prefetch
                   5649: static uae_u16 get_word_020_prefetchf (uae_u32 pc)
                   5650: {
                   5651:        if (pc == regs.prefetch020addr) {
                   5652:                uae_u16 v = regs.prefetch020[0];
                   5653:                regs.prefetch020[0] = regs.prefetch020[1];
                   5654:                regs.prefetch020[1] = regs.prefetch020[2];
                   5655:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5656:                regs.prefetch020addr += 2;
                   5657:                return v;
                   5658:        } else if (pc == regs.prefetch020addr + 2) {
                   5659:                uae_u16 v = regs.prefetch020[1];
                   5660:                regs.prefetch020[0] = regs.prefetch020[2];
                   5661:                regs.prefetch020[1] = x_get_word (pc + 4);
                   5662:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5663:                regs.prefetch020addr = pc + 2;
                   5664:                return v;
                   5665:        } else if (pc == regs.prefetch020addr + 4) {
                   5666:                uae_u16 v = regs.prefetch020[2];
                   5667:                regs.prefetch020[0] = x_get_word (pc + 2);
                   5668:                regs.prefetch020[1] = x_get_word (pc + 4);
                   5669:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5670:                regs.prefetch020addr = pc + 2;
                   5671:                return v;
                   5672:        } else {
                   5673:                regs.prefetch020addr = pc + 2;
                   5674:                regs.prefetch020[0] = x_get_word (pc + 2);
                   5675:                regs.prefetch020[1] = x_get_word (pc + 4);
                   5676:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5677:                return x_get_word (pc);
1.1.1.4   root     5678:        }
                   5679: }
                   5680: #endif
                   5681: 
1.1.1.8   root     5682: #ifdef WITH_THREADED_CPU
                   5683: static volatile int cpu_thread_active;
                   5684: 
                   5685: #define SPINLOCK_DEBUG 0
                   5686: static volatile int m68k_spinlock_cnt;
                   5687: static volatile long m68k_spinlock_waiting;
                   5688: #ifdef _WIN32
                   5689: #define CRITICAL_SECTION_SPIN_COUNT 5000
                   5690: static CRITICAL_SECTION m68k_cs1;
                   5691: static bool m68k_cs_initialized;
                   5692: static DWORD m68k_cs_owner;
                   5693: #else
                   5694: #include <glib.h>
                   5695: static GMutex mutex;
                   5696: #endif
                   5697: 
                   5698: static int do_specialties_thread(void)
                   5699: {
                   5700:        if (regs.spcflags & SPCFLAG_MODE_CHANGE)
                   5701:                return 1;
                   5702: 
                   5703:        if (regs.spcflags & SPCFLAG_CHECK) {
                   5704:                if (regs.halted) {
                   5705:                        if (haltloop())
                   5706:                                return 1;
                   5707:                }
                   5708:                if (m68k_reset_delay) {
                   5709:                        int vsynccnt = 60;
                   5710:                        int vsyncstate = -1;
                   5711:                        while (vsynccnt > 0) {
                   5712:                                int vp = vpos;
                   5713:                                while (vp == vpos) {
                   5714:                                        sleep_millis(1);
                   5715:                                }
                   5716:                                vsynccnt--;
                   5717:                        }
                   5718:                }
                   5719:                m68k_reset_delay = 0;
                   5720:                unset_special(SPCFLAG_CHECK);
                   5721:        }
                   5722:        
                   5723: #ifdef JIT
                   5724:        unset_special(SPCFLAG_END_COMPILE);   /* has done its job */
                   5725: #endif
                   5726: 
                   5727:        if (regs.spcflags & SPCFLAG_DOTRACE)
                   5728:                Exception(9);
                   5729: 
                   5730:        if (regs.spcflags & SPCFLAG_TRAP) {
                   5731:                unset_special(SPCFLAG_TRAP);
                   5732:                Exception(3);
                   5733:        }
                   5734:        bool first = true;
                   5735:        while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
                   5736:                if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
                   5737:                        int intr = intlev();
                   5738:                        unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
                   5739:                        if (intr > 0 && intr > regs.intmask)
                   5740:                                do_interrupt(intr);
                   5741:                }
                   5742: 
                   5743:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
                   5744:                        m68k_resumestopped();
                   5745:                        return 1;
                   5746:                }
                   5747:        }
                   5748: 
                   5749:        if (regs.spcflags & SPCFLAG_TRACE)
                   5750:                do_trace();
                   5751: 
                   5752:        if (regs.spcflags & SPCFLAG_INT) {
                   5753:                int intr = intlev();
                   5754:                unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
                   5755:                if (intr > 0 && (intr > regs.intmask || intr == 7))
                   5756:                        do_interrupt(intr);
                   5757:        }
                   5758: 
                   5759:        if (regs.spcflags & SPCFLAG_DOINT) {
                   5760:                unset_special(SPCFLAG_DOINT);
                   5761:                set_special(SPCFLAG_INT);
                   5762:        }
                   5763: 
                   5764:        if (regs.spcflags & SPCFLAG_BRK) {
                   5765:                return 1;
                   5766:        }
                   5767: 
                   5768:        return 0;
                   5769: }
                   5770: 
                   5771: void cpu_semaphore_get(void)
                   5772: {
                   5773:        if (!currprefs.cpu_thread)
                   5774:                return;
                   5775:        DWORD tid = GetCurrentThreadId();
                   5776: 
                   5777:        if (tid == m68k_cs_owner) {
                   5778:                m68k_spinlock_cnt++;
                   5779:                return;
                   5780:        }
                   5781: 
                   5782: #ifdef _WIN32
                   5783:        _InterlockedIncrement(&m68k_spinlock_waiting);
                   5784:        EnterCriticalSection(&m68k_cs1);
                   5785:        _InterlockedDecrement(&m68k_spinlock_waiting);
                   5786:        m68k_cs_owner = tid;
                   5787:        m68k_spinlock_cnt++;
                   5788: #else
                   5789:        g_mutex_lock(&mutex); // FIXME
                   5790: #endif
                   5791: }
                   5792: void cpu_semaphore_release(void)
                   5793: {
                   5794:        if (!currprefs.cpu_thread)
                   5795:                return;
                   5796: #ifdef _WIN32
                   5797:        m68k_spinlock_cnt--;
                   5798:        if (m68k_spinlock_cnt == 0) {
                   5799:                m68k_cs_owner = 0;
                   5800:                LeaveCriticalSection(&m68k_cs1);
                   5801:        }
                   5802: #else
                   5803:        g_mutex_unlock(&mutex); // FIXME
                   5804: #endif
                   5805: }
                   5806: 
                   5807: static void init_cpu_thread(void)
                   5808: {
                   5809:        if (!currprefs.cpu_thread)
                   5810:                return;
                   5811: #ifdef _WIN32
                   5812:        if (m68k_cs_initialized) {
                   5813:                DeleteCriticalSection(&m68k_cs1);
                   5814:        }
                   5815:        InitializeCriticalSectionAndSpinCount(&m68k_cs1, CRITICAL_SECTION_SPIN_COUNT);
                   5816: #endif
                   5817: }
                   5818: 
                   5819: static void run_cpu_thread(void *(*f)(void *))
                   5820: {
                   5821:        cpu_thread_active = 0;
                   5822: #if SPINLOCK_DEBUG
                   5823:        m68k_spinlock_cnt = 0;
                   5824: #endif
                   5825:        m68k_cs_initialized = true;
                   5826:        if (uae_start_thread(_T("cpu"), f, NULL, NULL)) {
                   5827:                while (!cpu_thread_active) {
                   5828:                        sleep_millis(1);
                   5829:                }
                   5830:                while (!(regs.spcflags & SPCFLAG_MODE_CHANGE)) {
                   5831: 
                   5832:                        cpu_semaphore_get();
                   5833:                        frame_time_t c = read_processor_time();
                   5834:                        while (cpu_thread_active) {
                   5835:                                int vsynctimeperline = vsynctimebase / (maxvpos_display + 1);
                   5836: 
                   5837:                                int vp = vpos;
                   5838:                                while ((int)read_processor_time() - (int)c > -vsynctimebase / 10) {
                   5839:                                        if (vp != vpos) {
                   5840:                                                vp = vpos;
                   5841:                                                if (vpos + 1 == maxvpos + lof_store) {
                   5842:                                                        c = read_processor_time();
                   5843:                                                }
                   5844:                                                c += vsynctimeperline;
                   5845:                                        }
                   5846:                                        cycles_do_special();
                   5847:                                        do_cycles(maxhpos / 2 * CYCLE_UNIT);
                   5848:                                        if (regs.spcflags & SPCFLAG_COPPER) {
                   5849:                                                do_copper();
                   5850:                                        }
                   5851: #ifndef WINUAE_FOR_HATARI
                   5852:                                        check_uae_int_request();
                   5853: #endif
                   5854:                                        int w = m68k_spinlock_waiting;
                   5855:                                        if (w) {
                   5856:                                                cpu_semaphore_release();
                   5857:                                                while (m68k_spinlock_waiting == w);
                   5858:                                                cpu_semaphore_get();
                   5859:                                        }
                   5860:                                }
                   5861:                                cpu_semaphore_release();
                   5862:                                sleep_millis(1);
                   5863:                                cpu_semaphore_get();
                   5864:                                while ((int)read_processor_time() - (int)c < 0) {
                   5865: #ifndef WINUAE_FOR_HATARI
                   5866:                                        check_uae_int_request();
                   5867: #endif
                   5868:                                        int w = m68k_spinlock_waiting;
                   5869:                                        if (w) {
                   5870:                                                cpu_semaphore_release();
                   5871:                                                while (m68k_spinlock_waiting == w);
                   5872:                                                cpu_semaphore_get();
                   5873:                                        }
                   5874:                                }
                   5875:                        }
                   5876:                        cpu_semaphore_release();
                   5877: 
                   5878:                        unset_special(SPCFLAG_BRK);
                   5879: #ifdef DEBUGGER
                   5880:                        if (debugging) {
                   5881:                                debug();
                   5882:                        }
                   5883: #endif
                   5884:                }
                   5885:        }
                   5886: }
                   5887: #endif
                   5888: 
1.1.1.4   root     5889: #ifdef JIT  /* Completely different run_2 replacement */
                   5890: 
                   5891: void do_nothing (void)
                   5892: {
1.1.1.8   root     5893:        if (!currprefs.cpu_thread) {
                   5894:                /* What did you expect this to do? */
                   5895:                do_cycles (0);
                   5896:                /* I bet you didn't expect *that* ;-) */
                   5897:        }
1.1.1.4   root     5898: }
                   5899: 
                   5900: void exec_nostats (void)
                   5901: {
                   5902:        struct regstruct *r = &regs;
                   5903: 
                   5904:        for (;;)
                   5905:        {
1.1.1.7   root     5906:                if (currprefs.cpu_compatible) {
                   5907:                        r->opcode = get_word_020_prefetchf(m68k_getpc());
                   5908:                } else {
                   5909:                        r->opcode = x_get_iword(0);
                   5910:                }
                   5911:                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   5912:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.8   root     5913: 
                   5914:                if (!currprefs.cpu_thread) {
                   5915:                        do_cycles (cpu_cycles);
1.1.1.4   root     5916: 
1.1.1.7   root     5917: #ifdef WITH_PPC
1.1.1.8   root     5918:                        if (ppc_state)
                   5919:                                ppc_interrupt(intlev());
1.1.1.7   root     5920: #endif
1.1.1.8   root     5921:                }
1.1.1.7   root     5922: #ifdef WINUAE_FOR_HATARI
                   5923:                if (end_block(r->opcode) || r->spcflags)
                   5924: #else
                   5925: 
1.1.1.8   root     5926:                if (end_block(r->opcode) || r->spcflags || uae_int_requested)
1.1.1.7   root     5927: #endif
1.1.1.4   root     5928:                        return; /* We will deal with the spcflags in the caller */
                   5929:        }
                   5930: }
                   5931: 
                   5932: void execute_normal (void)
                   5933: {
                   5934:        struct regstruct *r = &regs;
                   5935:        int blocklen;
                   5936:        cpu_history pc_hist[MAXRUN];
                   5937:        int total_cycles;
                   5938: 
                   5939:        if (check_for_cache_miss ())
                   5940:                return;
                   5941: 
                   5942:        total_cycles = 0;
                   5943:        blocklen = 0;
                   5944:        start_pc_p = r->pc_oldp;
                   5945:        start_pc = r->pc;
                   5946:        for (;;) {
                   5947:                /* Take note: This is the do-it-normal loop */
1.1.1.7   root     5948:                regs.instruction_pc = m68k_getpc ();
                   5949:                if (currprefs.cpu_compatible) {
                   5950:                        r->opcode = get_word_020_prefetchf (regs.instruction_pc);
                   5951:                } else {
                   5952:                        r->opcode = x_get_iword(0);
                   5953:                }
1.1.1.4   root     5954: 
                   5955:                special_mem = DISTRUST_CONSISTENT_MEM;
                   5956:                pc_hist[blocklen].location = (uae_u16*)r->pc_p;
                   5957: 
1.1.1.7   root     5958:                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
1.1.1.8   root     5959:                cpu_cycles = adjust_cycles(cpu_cycles);
                   5960:                if (!currprefs.cpu_thread) {
                   5961:                        do_cycles (cpu_cycles);
                   5962:                }
1.1.1.4   root     5963:                total_cycles += cpu_cycles;
                   5964:                pc_hist[blocklen].specmem = special_mem;
                   5965:                blocklen++;
1.1.1.7   root     5966: #ifdef WINUAE_FOR_HATARI
                   5967:                if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags) {
                   5968: #else
1.1.1.8   root     5969:                if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested) {
1.1.1.7   root     5970: #endif
1.1.1.4   root     5971:                        compile_block (pc_hist, blocklen, total_cycles);
                   5972:                        return; /* We will deal with the spcflags in the caller */
                   5973:                }
                   5974:                /* No need to check regs.spcflags, because if they were set,
                   5975:                we'd have ended up inside that "if" */
1.1.1.7   root     5976: 
                   5977: #ifdef WITH_PPC
                   5978:                if (ppc_state)
                   5979:                        ppc_interrupt(intlev());
                   5980: #endif
1.1.1.4   root     5981:        }
                   5982: }
                   5983: 
                   5984: typedef void compiled_handler (void);
                   5985: 
1.1.1.8   root     5986: #ifdef WITH_THREADED_CPU
                   5987: static void *cpu_thread_run_jit(void *v)
1.1.1.4   root     5988: {
1.1.1.8   root     5989:        cpu_thread_active = 1;
                   5990:        for (;;) {
                   5991:                ((compiled_handler*)(pushall_call_handler))();
                   5992:                /* Whenever we return from that, we should check spcflags */
                   5993:                if (regs.spcflags) {
                   5994:                        if (do_specialties_thread()) {
                   5995:                                break;
                   5996:                        }
                   5997:                }
                   5998:        }
                   5999:        cpu_thread_active = 0;
                   6000:        return 0;
                   6001: }
                   6002: #endif
                   6003: 
                   6004: static void m68k_run_jit(void)
                   6005: {
                   6006:        Log_Printf(LOG_DEBUG, "m68k_run_jit\n");
                   6007: #ifdef WITH_THREADED_CPU
                   6008:        if (currprefs.cpu_thread) {
                   6009:                run_cpu_thread(cpu_thread_run_jit);
                   6010:                return;
                   6011:        }
                   6012: #endif
                   6013: 
1.1.1.4   root     6014:        for (;;) {
1.1.1.7   root     6015: #ifdef WINUAE_FOR_HATARI
                   6016:                //m68k_dumpstate_file(stderr, NULL);
1.1.1.4   root     6017:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6018:                {
                   6019:                        int FrameCycles, HblCounterVideo, LineCycles;
                   6020:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6021:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.7   root     6022:                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4   root     6023:                }
1.1.1.7   root     6024: #endif
1.1.1.4   root     6025: 
                   6026:                ((compiled_handler*)(pushall_call_handler))();
                   6027:                /* Whenever we return from that, we should check spcflags */
1.1.1.7   root     6028: #ifndef WINUAE_FOR_HATARI
                   6029:                check_uae_int_request();
                   6030: #endif
1.1.1.4   root     6031:                if (regs.spcflags) {
                   6032:                        if (do_specialties (0)) {
                   6033:                                return;
                   6034:                        }
                   6035:                }
                   6036:        }
                   6037: }
                   6038: #endif /* JIT */
                   6039: 
                   6040: #ifndef CPUEMU_0
                   6041: 
                   6042: static void m68k_run_2 (void)
                   6043: {
                   6044: }
                   6045: 
                   6046: #else
                   6047: 
1.1.1.7   root     6048: static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full)
1.1.1.4   root     6049: {
                   6050:        struct mnemolookup *lookup;
                   6051:        struct instr *dp;
                   6052:        uae_u32 addr;
                   6053:        int fault;
                   6054: 
                   6055:        if (cpufunctbl[opcode] == op_illg_1)
                   6056:                opcode = 0x4AFC;
                   6057:        dp = table68k + opcode;
                   6058:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   6059:                ;
                   6060:        fault = 0;
                   6061:        TRY(prb) {
1.1.1.9 ! root     6062:                addr = mmu_translate (pc, 0, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0, sz_word);
1.1.1.4   root     6063:        } CATCH (prb) {
                   6064:                fault = 1;
                   6065:        } ENDTRY
                   6066:        if (!fault) {
1.1.1.7   root     6067:                TCHAR buf[100];
                   6068:                if (full)
                   6069:                        write_log (_T("mmufixup=%d %04x %04x\n"), mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
                   6070:                m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0);
                   6071:                write_log (_T("%s\n"), buf);
                   6072:                if (full)
                   6073:                        m68k_dumpstate (NULL);
                   6074:        }
                   6075: }
                   6076: 
1.1.1.9 ! root     6077: static void check_halt(void)
        !          6078: {
        !          6079:        if (regs.halted)
        !          6080:                do_specialties (0);
        !          6081: }
        !          6082: 
1.1.1.7   root     6083: void cpu_halt (int id)
                   6084: {
                   6085: #ifndef WINUAE_FOR_HATARI
                   6086:        // id < 0: m68k halted, PPC active.
                   6087:        // id > 0: emulation halted.
                   6088:        if (!regs.halted) {
                   6089:                write_log (_T("CPU halted: reason = %d PC=%08x\n"), id, M68K_GETPC);
                   6090:                regs.halted = id;
                   6091:                gui_data.cpu_halted = id;
                   6092:                gui_led(LED_CPU, 0, -1);
                   6093:                if (id >= 0) {
                   6094:                        regs.intmask = 7;
                   6095:                        MakeSR ();
                   6096:                        audio_deactivate ();
                   6097:                }
                   6098:        }
1.1.1.9 ! root     6099:        set_special(SPCFLAG_CHECK);
1.1.1.7   root     6100: #else
                   6101:        Dialog_HaltDlg();
                   6102: #endif
                   6103: }
                   6104: 
                   6105: #ifdef CPUEMU_33
                   6106: /* [NP] TODO : use 68060 in Hatari ? with DSP ? */
                   6107: /* MMU 68060  */
                   6108: static void m68k_run_mmu060 (void)
                   6109: {
                   6110:        struct flag_struct f;
                   6111:        int halt = 0;
1.1.1.8   root     6112: 
1.1.1.9 ! root     6113:        check_halt();
1.1.1.8   root     6114: #ifdef WINUAE_FOR_HATARI
                   6115:        Log_Printf(LOG_DEBUG,  "m68k_run_mmu060\n");
                   6116: #endif
1.1.1.7   root     6117: 
                   6118:        while (!halt) {
                   6119:                TRY (prb) {
                   6120:                        for (;;) {
1.1.1.8   root     6121: #ifdef WINUAE_FOR_HATARI
                   6122:                                //m68k_dumpstate_file(stderr, NULL);
                   6123:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6124:                                {
                   6125:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6126:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6127:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6128:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   6129:                                }
                   6130: #endif
1.1.1.7   root     6131:                                f.cznv = regflags.cznv;
                   6132:                                f.x = regflags.x;
                   6133:                                regs.instruction_pc = m68k_getpc ();
                   6134: 
                   6135:                                do_cycles (cpu_cycles);
                   6136: 
                   6137:                                mmu_opcode = -1;
                   6138:                                mmu060_state = 0;
                   6139:                                mmu_opcode = regs.opcode = x_prefetch (0);
                   6140:                                mmu060_state = 1;
                   6141: 
                   6142:                                count_instr (regs.opcode);
                   6143:                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   6144: 
                   6145:                                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.8   root     6146: #ifdef WINUAE_FOR_HATARI
                   6147:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.7   root     6148: 
1.1.1.8   root     6149:                                if ( WaitStateCycles ) {
                   6150:                                        /* Add some extra cycles to simulate a wait state */
                   6151:                                        M68000_AddCycles(WaitStateCycles);
                   6152:                                        WaitStateCycles = 0;
                   6153:                                }
                   6154: 
                   6155:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6156:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6157:                                if ( MFP_UpdateNeeded == true )
                   6158:                                        MFP_UpdateIRQ ( 0 );
                   6159: #endif
1.1.1.7   root     6160:                                if (regs.spcflags) {
                   6161:                                        if (do_specialties (cpu_cycles))
                   6162:                                                return;
                   6163:                                }
1.1.1.8   root     6164: #ifdef WINUAE_FOR_HATARI
                   6165:                                /* Run DSP 56k code if necessary */
                   6166:                                if (bDspEnabled) {
                   6167:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
                   6168: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
                   6169:                                }
                   6170: #endif
1.1.1.7   root     6171:                        }
                   6172:                } CATCH (prb) {
                   6173: 
                   6174:                        m68k_setpci (regs.instruction_pc);
                   6175:                        regflags.cznv = f.cznv;
                   6176:                        regflags.x = f.x;
                   6177: 
                   6178:                        if (mmufixup[0].reg >= 0) {
                   6179:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                   6180:                                mmufixup[0].reg = -1;
                   6181:                        }
                   6182:                        if (mmufixup[1].reg >= 0) {
                   6183:                                m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
                   6184:                                mmufixup[1].reg = -1;
                   6185:                        }
                   6186: 
                   6187:                        TRY (prb2) {
                   6188:                                Exception (prb);
                   6189:                        } CATCH (prb2) {
                   6190:                                halt = 1;
                   6191:                        } ENDTRY
                   6192:                } ENDTRY
1.1.1.4   root     6193:        }
1.1.1.7   root     6194:        cpu_halt(halt);
1.1.1.4   root     6195: }
1.1.1.7   root     6196: 
1.1.1.4   root     6197: #endif
                   6198: 
1.1.1.7   root     6199: #ifdef CPUEMU_31
1.1.1.4   root     6200: 
                   6201: /* Aranym MMU 68040  */
                   6202: static void m68k_run_mmu040 (void)
                   6203: {
1.1.1.7   root     6204:        struct flag_struct f;
                   6205:        int halt = 0;
1.1.1.8   root     6206: 
1.1.1.9 ! root     6207:        check_halt();
1.1.1.8   root     6208: #ifdef WINUAE_FOR_HATARI
                   6209:        Log_Printf(LOG_DEBUG,  "m68k_run_mmu040\n");
                   6210: #endif
1.1.1.7   root     6211: 
                   6212:        while (!halt) {
                   6213:                TRY (prb) {
                   6214:                        for (;;) {
                   6215: #ifdef WINUAE_FOR_HATARI
                   6216:                                //m68k_dumpstate_file(stderr, NULL);
                   6217:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6218:                                {
                   6219:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6220:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6221:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6222:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   6223:                                }
                   6224: #endif
                   6225:                                f.cznv = regflags.cznv;
                   6226:                                f.x = regflags.x;
                   6227:                                mmu_restart = true;
                   6228:                                regs.instruction_pc = m68k_getpc ();
                   6229: 
                   6230:                                do_cycles (cpu_cycles);
                   6231: 
                   6232:                                mmu_opcode = -1;
                   6233:                                mmu_opcode = regs.opcode = x_prefetch (0);
                   6234:                                count_instr (regs.opcode);
                   6235:                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   6236:                                cpu_cycles = adjust_cycles (cpu_cycles);
                   6237: 
                   6238: #ifdef WINUAE_FOR_HATARI
                   6239:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
                   6240: 
1.1.1.8   root     6241:                                if ( WaitStateCycles ) {
1.1.1.7   root     6242:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     6243:                                        M68000_AddCycles(WaitStateCycles);
                   6244:                                        WaitStateCycles = 0;
1.1.1.7   root     6245:                                }
1.1.1.4   root     6246: 
1.1.1.7   root     6247:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6248:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6249:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6250:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6251:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6252:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6253:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6254:                                if ( MFP_UpdateNeeded == true )
                   6255:                                        MFP_UpdateIRQ ( 0 );
                   6256: #endif
1.1.1.4   root     6257: 
1.1.1.7   root     6258:                                if (regs.spcflags) {
                   6259:                                        if (do_specialties (cpu_cycles))
                   6260:                                                return;
1.1.1.4   root     6261:                                }
1.1.1.7   root     6262: 
                   6263: #ifdef WINUAE_FOR_HATARI
                   6264:                                /* Run DSP 56k code if necessary */
                   6265:                                if (bDspEnabled) {
                   6266:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     6267: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     6268:                                }
                   6269: #endif
1.1.1.4   root     6270:                        }
1.1.1.7   root     6271:                } CATCH (prb) {
                   6272: 
                   6273:                        if (mmu_restart) {
                   6274:                                /* restore state if instruction restart */
                   6275:                                regflags.cznv = f.cznv;
                   6276:                                regflags.x = f.x;
                   6277:                                m68k_setpci (regs.instruction_pc);
1.1.1.4   root     6278:                        }
1.1.1.7   root     6279: 
                   6280:                        if (mmufixup[0].reg >= 0) {
                   6281:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                   6282:                                mmufixup[0].reg = -1;
1.1.1.4   root     6283:                        }
1.1.1.7   root     6284: 
                   6285:                        TRY (prb2) {
                   6286:                                Exception (prb);
                   6287:                        } CATCH (prb2) {
                   6288:                                halt = 1;
                   6289:                        } ENDTRY
                   6290:                } ENDTRY
                   6291:        }
                   6292:        cpu_halt(halt);
                   6293: }
                   6294: 
                   6295: #endif
                   6296: 
                   6297: #ifdef CPUEMU_32
                   6298: 
                   6299: // Previous MMU 68030
                   6300: static void m68k_run_mmu030 (void)
                   6301: {
                   6302:        struct flag_struct f;
                   6303:        int halt = 0;
1.1.1.8   root     6304: 
                   6305: #ifdef WINUAE_FOR_HATARI
                   6306:        Log_Printf(LOG_DEBUG,  "m68k_run_mmu030\n");
                   6307: #endif
1.1.1.7   root     6308: 
                   6309:        mmu030_opcode_stageb = -1;
                   6310:        mmu030_fake_prefetch = -1;
1.1.1.9 ! root     6311:        check_halt();
1.1.1.7   root     6312:        while(!halt) {
                   6313:                TRY (prb) {
                   6314:                        for (;;) {
                   6315:                                int cnt;
                   6316: insretry:
                   6317: #ifdef WINUAE_FOR_HATARI
                   6318:                                //m68k_dumpstate_file(stderr, NULL);
                   6319:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6320:                                {
                   6321:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6322:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6323:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6324:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4   root     6325:                                }
                   6326: #endif
1.1.1.7   root     6327:                                regs.instruction_pc = m68k_getpc ();
                   6328:                                f.cznv = regflags.cznv;
                   6329:                                f.x = regflags.x;
                   6330: 
                   6331:                                mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
                   6332:                                mmu030_opcode = -1;
                   6333:                                if (mmu030_fake_prefetch >= 0) {
                   6334:                                        // use fake prefetch opcode only if mapping changed
                   6335:                                        uaecptr new_addr = mmu030_translate(regs.instruction_pc, regs.s != 0, false, false);
                   6336:                                        if (mmu030_fake_prefetch_addr != new_addr) {
                   6337:                                                regs.opcode = mmu030_fake_prefetch;
1.1.1.8   root     6338:                                                write_log(_T("MMU030 fake prefetch remap: %04x, %08x -> %08x\n"), mmu030_fake_prefetch, mmu030_fake_prefetch_addr, new_addr); 
1.1.1.7   root     6339:                                        } else {
                   6340:                                                if (mmu030_opcode_stageb < 0) {
                   6341:                                                        regs.opcode = x_prefetch (0);
                   6342:                                                } else {
                   6343:                                                        regs.opcode = mmu030_opcode_stageb;
                   6344:                                                        mmu030_opcode_stageb = -1;
                   6345:                                                }
                   6346:                                        }
                   6347:                                        mmu030_fake_prefetch = -1;
                   6348:                                } else if (mmu030_opcode_stageb < 0) {
1.1.1.9 ! root     6349:                                        if (currprefs.cpu_compatible)
        !          6350:                                                regs.opcode = regs.irc;
        !          6351:                                        else
        !          6352:                                                regs.opcode = x_prefetch (0);
1.1.1.7   root     6353:                                } else {
                   6354:                                        regs.opcode = mmu030_opcode_stageb;
                   6355:                                        mmu030_opcode_stageb = -1;
                   6356:                                }
                   6357: 
                   6358:                                mmu030_opcode = regs.opcode;
                   6359:                                mmu030_ad[0].done = false;
                   6360: 
                   6361:                                cnt = 50;
                   6362:                                for (;;) {
1.1.1.9 ! root     6363:                                        regs.opcode = regs.irc = mmu030_opcode;
1.1.1.7   root     6364:                                        mmu030_idx = 0;
1.1.1.9 ! root     6365: 
1.1.1.7   root     6366:                                        mmu030_retry = false;
                   6367: 
1.1.1.9 ! root     6368:                                        if (!currprefs.cpu_cycle_exact) {
        !          6369: 
        !          6370:                                                count_instr (regs.opcode);
        !          6371:                                                do_cycles (cpu_cycles);
        !          6372: 
        !          6373:                                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
        !          6374: 
        !          6375:                                        } else {
        !          6376: #ifdef WINUAE_FOR_HATARI
        !          6377:                                                currcycle = 0;
        !          6378: #endif
        !          6379:                                                (*cpufunctbl[regs.opcode])(regs.opcode);
        !          6380: 
        !          6381:                                                wait_memory_cycles();
        !          6382:                                        }
        !          6383: 
1.1.1.7   root     6384:                                        cnt--; // so that we don't get in infinite loop if things go horribly wrong
                   6385:                                        if (!mmu030_retry)
                   6386:                                                break;
                   6387:                                        if (cnt < 0) {
1.1.1.8   root     6388:                                                cpu_halt (CPU_HALT_CPU_STUCK);
1.1.1.7   root     6389:                                                break;
                   6390:                                        }
                   6391:                                        if (mmu030_retry && mmu030_opcode == -1)
                   6392:                                                goto insretry; // urgh
                   6393:                                }
1.1.1.4   root     6394: 
1.1.1.7   root     6395:                                mmu030_opcode = -1;
1.1.1.4   root     6396: 
1.1.1.9 ! root     6397:                                if (!currprefs.cpu_cycle_exact) {
1.1.1.4   root     6398: 
1.1.1.9 ! root     6399:                                        cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.7   root     6400: #ifdef WINUAE_FOR_HATARI
1.1.1.9 ! root     6401:                                        M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4   root     6402: 
1.1.1.9 ! root     6403:                                        if ( WaitStateCycles ) {
        !          6404:                                                /* Add some extra cycles to simulate a wait state */
        !          6405:                                                M68000_AddCycles(WaitStateCycles);
        !          6406:                                                WaitStateCycles = 0;
        !          6407:                                        }
1.1.1.7   root     6408: 
1.1.1.9 ! root     6409:                                        /* We can have several interrupts at the same time before the next CPU instruction */
        !          6410:                                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          6411:                                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          6412:                                        /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          6413:                                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          6414:                                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          6415:                                                CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          6416:                                        if ( MFP_UpdateNeeded == true )
        !          6417:                                                MFP_UpdateIRQ ( 0 );
1.1.1.7   root     6418: #endif
1.1.1.9 ! root     6419:                                        if (regs.spcflags) {
        !          6420:                                                if (do_specialties (cpu_cycles))
        !          6421:                                                        return;
        !          6422:                                        }
1.1.1.7   root     6423: #ifdef WINUAE_FOR_HATARI
                   6424:                                /* Run DSP 56k code if necessary */
                   6425:                                if (bDspEnabled) {
                   6426:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     6427: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     6428:                                }
                   6429: #endif
                   6430: 
1.1.1.9 ! root     6431:                                } else {
        !          6432: 
        !          6433: #ifdef WINUAE_FOR_HATARI
        !          6434: //fprintf ( stderr, "cyc_2ce %d\n" , currcycle );
        !          6435:                                        /* Flush all CE cycles so far to update PendingInterruptCount */
        !          6436:                                        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
        !          6437: //                                     currcycle = 0;  // FIXME : uncomment this when using DSP_CyclesGlobalClockCounter in DSP_Run
        !          6438: 
        !          6439:                                        /* We can have several interrupts at the same time before the next CPU instruction */
        !          6440:                                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
        !          6441:                                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
        !          6442:                                        /* and prevent exiting the STOP state when calling do_specialties() after. */
        !          6443:                                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
        !          6444:                                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
        !          6445:                                                CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
        !          6446:                                        if ( MFP_UpdateNeeded == true )
        !          6447:                                                MFP_UpdateIRQ ( 0 );
        !          6448: #endif
        !          6449: 
        !          6450:                                        if (regs.spcflags || time_for_interrupt ()) {
        !          6451:                                                if (do_specialties (0))
        !          6452:                                                        return;
        !          6453:                                        }
        !          6454: 
        !          6455: #ifdef WINUAE_FOR_HATARI
        !          6456:                                        /* Run DSP 56k code if necessary */
        !          6457:                                        if (bDspEnabled) {
        !          6458: //fprintf ( stderr, "dsp cyc_2ce %d\n" , currcycle );
        !          6459:                                                DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
        !          6460: //fprintf ( stderr, "dsp cyc_2ce %d - %d\n" , currcycle * 2 / CYCLE_UNIT , (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) );
        !          6461: //                                             DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
        !          6462:                                        }
        !          6463: #endif
        !          6464: 
        !          6465:                                        regs.ipl = regs.ipl_pin;
        !          6466: 
        !          6467:                                }
        !          6468: 
        !          6469:                        }
        !          6470: 
        !          6471:                } CATCH (prb) {
        !          6472: 
        !          6473:                        if (mmu030_opcode == -1 && currprefs.cpu_compatible) {
        !          6474:                                // full prefetch fill access fault
        !          6475:                                // TODO: this should create shorter A-frame
        !          6476:                                mmufixup[0].reg = -1;
        !          6477:                                mmufixup[1].reg = -1;
        !          6478:                        } else {
        !          6479:                                regflags.cznv = f.cznv;
        !          6480:                                regflags.x = f.x;
        !          6481: 
        !          6482:                                if (mmufixup[0].reg >= 0) {
        !          6483:                                        m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
        !          6484:                                        mmufixup[0].reg = -1;
        !          6485:                                }
        !          6486:                                if (mmufixup[1].reg >= 0) {
        !          6487:                                        m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
        !          6488:                                        mmufixup[1].reg = -1;
        !          6489:                                }
        !          6490:                        }
        !          6491: 
        !          6492:                        m68k_setpci (regs.instruction_pc);
        !          6493: 
        !          6494:                        TRY (prb2) {
        !          6495:                                Exception (prb);
        !          6496:                        } CATCH (prb2) {
        !          6497:                                halt = 1;
        !          6498:                        } ENDTRY
        !          6499:                } ENDTRY
        !          6500:        }
        !          6501:        cpu_halt (halt);
        !          6502: }
1.1.1.7   root     6503: 
                   6504: #endif
                   6505: 
                   6506: 
                   6507: /* "cycle exact" 68040/060 */
                   6508: 
                   6509: static void m68k_run_3ce (void)
                   6510: {
                   6511:        struct regstruct *r = &regs;
                   6512:        bool exit = false;
1.1.1.8   root     6513: 
                   6514:        Log_Printf(LOG_DEBUG, "m68k_run_3ce\n");
1.1.1.7   root     6515: 
                   6516:        while (!exit) {
                   6517:                TRY(prb) {
                   6518:                        while (!exit) {
                   6519: #ifdef WINUAE_FOR_HATARI
                   6520:                                //m68k_dumpstate_file(stderr, NULL);
                   6521:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6522:                                {
                   6523:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6524:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6525:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6526:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   6527:                                }
1.1.1.8   root     6528:                                currcycle = CYCLE_UNIT / 2;     /* Assume at least 1 cycle per instruction */
1.1.1.7   root     6529: #endif
                   6530:                                r->instruction_pc = m68k_getpc();
                   6531:                                r->opcode = get_iword_cache_040(0);
                   6532:                                // "prefetch"
                   6533:                                if (regs.cacr & 0x8000)
                   6534:                                        fill_icache040(r->instruction_pc + 16);
                   6535: 
                   6536:                                (*cpufunctbl[r->opcode])(r->opcode);
                   6537: 
                   6538: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     6539: //fprintf ( stderr, "cyc_3ce %ld\n" , currcycle );
                   6540:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   6541:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   6542: //                             currcycle = 0;  // FIXME : uncomment this when using DSP_CyclesGlobalClockCounter in DSP_Run
1.1.1.7   root     6543: 
                   6544:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6545:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6546:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6547:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6548:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6549:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6550:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6551:                                if ( MFP_UpdateNeeded == true )
                   6552:                                        MFP_UpdateIRQ ( 0 );
                   6553: #endif
                   6554:                                if (r->spcflags) {
                   6555:                                        if (do_specialties (0))
                   6556:                                                exit = true;
                   6557:                                }
                   6558: 
                   6559: #ifdef WINUAE_FOR_HATARI
                   6560:                                /* Run DSP 56k code if necessary */
                   6561:                                if (bDspEnabled) {
                   6562:                                        DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
1.1.1.8   root     6563: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.4   root     6564:                                }
1.1.1.7   root     6565: #endif
1.1.1.4   root     6566:                        }
1.1.1.7   root     6567:                } CATCH(prb) {
                   6568:                        bus_error();
                   6569:                        if (r->spcflags) {
                   6570:                                if (do_specialties(0))
                   6571:                                        exit = true;
                   6572:                        }
                   6573:                } ENDTRY
                   6574:        }
                   6575: }
1.1.1.4   root     6576: 
1.1.1.7   root     6577: /* "prefetch" 68040/060 */
1.1.1.4   root     6578: 
1.1.1.7   root     6579: static void m68k_run_3p(void)
                   6580: {
                   6581:        struct regstruct *r = &regs;
                   6582:        bool exit = false;
                   6583:        int cycles;
1.1.1.8   root     6584: 
                   6585:        Log_Printf(LOG_DEBUG, "m68k_run_3p\n");
1.1.1.7   root     6586: 
                   6587:        while (!exit)  {
                   6588:                TRY(prb) {
                   6589:                        while (!exit) {
                   6590: #ifdef WINUAE_FOR_HATARI
                   6591:                                //m68k_dumpstate_file(stderr, NULL);
                   6592:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6593:                                {
                   6594:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6595:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6596:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6597:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   6598:                                }
                   6599: #endif
                   6600:                                r->instruction_pc = m68k_getpc();
                   6601:                                r->opcode = get_iword_cache_040(0);
                   6602:                                // "prefetch"
                   6603:                                if (regs.cacr & 0x8000)
                   6604:                                        fill_icache040(r->instruction_pc + 16);
                   6605: 
                   6606:                                (*cpufunctbl[r->opcode])(r->opcode);
                   6607: 
1.1.1.8   root     6608: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     6609:                                cpu_cycles = 1 * CYCLE_UNIT;
                   6610:                                cycles = adjust_cycles(cpu_cycles);
                   6611:                                do_cycles(cycles);
1.1.1.8   root     6612: #else
                   6613:                                cycles = cpu_cycles = CYCLE_UNIT / 2;
                   6614:                                M68000_AddCycles_CE(cycles * 2 / CYCLE_UNIT);
1.1.1.7   root     6615: 
1.1.1.8   root     6616:                                if ( WaitStateCycles ) {
1.1.1.7   root     6617:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     6618:                                        M68000_AddCycles(WaitStateCycles);
                   6619:                                        WaitStateCycles = 0;
1.1.1.7   root     6620:                                }
1.1.1.4   root     6621: 
1.1.1.7   root     6622:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6623:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6624:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6625:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6626:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6627:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6628:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6629:                                if ( MFP_UpdateNeeded == true )
                   6630:                                        MFP_UpdateIRQ ( 0 );
                   6631: #endif
                   6632: 
                   6633:                                if (r->spcflags) {
                   6634:                                        if (do_specialties(0))
                   6635:                                                exit = true;
                   6636:                                }
                   6637: 
                   6638: #ifdef WINUAE_FOR_HATARI
                   6639:                                /* Run DSP 56k code if necessary */
                   6640:                                if (bDspEnabled) {
                   6641:                                        DSP_Run(2 * cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     6642: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     6643:                                }
                   6644: #endif
                   6645:                        }
                   6646:                } CATCH(prb) {
                   6647:                        bus_error();
                   6648:                        if (r->spcflags) {
                   6649:                                if (do_specialties(0))
                   6650:                                        exit = true;
                   6651:                        }
                   6652:                } ENDTRY
                   6653:        }
1.1.1.4   root     6654: }
                   6655: 
                   6656: /* "cycle exact" 68020/030  */
1.1.1.7   root     6657: 
                   6658: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp);
1.1.1.4   root     6659: static void m68k_run_2ce (void)
                   6660: {
                   6661:        struct regstruct *r = &regs;
1.1.1.7   root     6662:        bool exit = false;
                   6663:        bool first = true;
1.1.1.8   root     6664: 
                   6665:        Log_Printf(LOG_DEBUG, "m68k_run_2ce\n");
1.1.1.7   root     6666: 
                   6667:        while (!exit) {
                   6668:                TRY(prb) {
                   6669:                        if (first) {
                   6670:                                if (cpu_tracer < 0) {
                   6671:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                   6672:                                        r->ir = cputrace.ir;
                   6673:                                        r->irc = cputrace.irc;
                   6674:                                        r->sr = cputrace.sr;
                   6675:                                        r->usp = cputrace.usp;
                   6676:                                        r->isp = cputrace.isp;
                   6677:                                        r->intmask = cputrace.intmask;
                   6678:                                        r->stopped = cputrace.stopped;
                   6679: 
                   6680:                                        r->msp = cputrace.msp;
                   6681:                                        r->vbr = cputrace.vbr;
                   6682:                                        r->caar = cputrace.caar;
                   6683:                                        r->cacr = cputrace.cacr;
                   6684:                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
                   6685:                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
                   6686:                                        r->prefetch020addr = cputrace.prefetch020addr;
1.1.1.9 ! root     6687:                                        memcpy(&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof(uae_u16));
        !          6688:                                        memcpy(&r->prefetch020_valid, &cputrace.prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
        !          6689:                                        memcpy(&caches020, &cputrace.caches020, sizeof caches020);
1.1.1.7   root     6690: 
                   6691:                                        m68k_setpc (cputrace.pc);
                   6692:                                        if (!r->stopped) {
                   6693:                                                if (cputrace.state > 1)
                   6694:                                                        Exception (cputrace.state);
                   6695:                                                else if (cputrace.state == 1)
                   6696:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                   6697:                                        }
                   6698:                                        if (regs.stopped)
                   6699:                                                set_special (SPCFLAG_STOP);
                   6700:                                        set_cpu_tracer (false);
                   6701:                                        goto cont;
                   6702:                                }
                   6703:                                set_cpu_tracer (false);
                   6704:                                first = false;
                   6705:                        }
1.1.1.4   root     6706: 
1.1.1.7   root     6707:                        while (!exit) {
1.1.1.8   root     6708: #if 0
1.1.1.7   root     6709:                                static int prevopcode;
1.1.1.8   root     6710: #endif
1.1.1.7   root     6711: #ifdef WINUAE_FOR_HATARI
                   6712:                                //m68k_dumpstate_file(stderr, NULL);
                   6713:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6714:                                {
                   6715:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6716:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6717:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6718:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   6719: #if 0
                   6720: // logs to debug data cache issues
                   6721: struct cache030 *c1 ,*c2;
                   6722:         int lws1, lws2;
                   6723:         uae_u32 tag1, tag2;
                   6724: c1 = getcache030 (dcaches030, (uaecptr)0x27ece, &tag1, &lws1);
                   6725: c2 = getcache030 (dcaches030, (uaecptr)0x7f8192+4, &tag2, &lws2);
                   6726: 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) );
                   6727: //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) );
                   6728: #endif
                   6729:                                }
1.1.1.4   root     6730: 
1.1.1.7   root     6731:                                currcycle = 0;
                   6732: #endif
                   6733:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     6734: 
1.1.1.8   root     6735: #if 0
1.1.1.7   root     6736:                                if (regs.irc == 0xfffb) {
                   6737:                                        gui_message (_T("OPCODE %04X HAS FAULTY PREFETCH! PC=%08X"), prevopcode, r->instruction_pc);
                   6738:                                }
1.1.1.8   root     6739: #endif
1.1.1.4   root     6740: 
1.1.1.7   root     6741:                                //write_log (_T("%x %04x\n"), r->instruction_pc, regs.irc);
1.1.1.4   root     6742: 
1.1.1.7   root     6743:                                r->opcode = regs.irc;
1.1.1.8   root     6744: #if 0
1.1.1.7   root     6745:                                prevopcode = r->opcode;
                   6746:                                regs.irc = 0xfffb;
1.1.1.8   root     6747: #endif
1.1.1.7   root     6748:                                //write_log (_T("%08x %04x\n"), r->instruction_pc, opcode);
1.1.1.5   root     6749: 
1.1.1.7   root     6750: #ifndef WINUAE_FOR_HATARI
                   6751: #if DEBUG_CD32CDTVIO
                   6752:                                out_cd32io (r->instruction_pc);
                   6753: #endif
                   6754: #endif
1.1.1.4   root     6755: 
1.1.1.7   root     6756:                                if (cpu_tracer) {
1.1.1.4   root     6757: 
1.1.1.7   root     6758: #if CPUTRACE_DEBUG
                   6759:                                        validate_trace ();
                   6760: #endif
                   6761:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
                   6762:                                        cputrace.opcode = r->opcode;
                   6763:                                        cputrace.ir = r->ir;
                   6764:                                        cputrace.irc = r->irc;
                   6765:                                        cputrace.sr = r->sr;
                   6766:                                        cputrace.usp = r->usp;
                   6767:                                        cputrace.isp = r->isp;
                   6768:                                        cputrace.intmask = r->intmask;
                   6769:                                        cputrace.stopped = r->stopped;
                   6770:                                        cputrace.state = 1;
                   6771:                                        cputrace.pc = m68k_getpc ();
                   6772: 
                   6773:                                        cputrace.msp = r->msp;
                   6774:                                        cputrace.vbr = r->vbr;
                   6775:                                        cputrace.caar = r->caar;
                   6776:                                        cputrace.cacr = r->cacr;
                   6777:                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
                   6778:                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
                   6779:                                        cputrace.prefetch020addr = r->prefetch020addr;
1.1.1.9 ! root     6780:                                        memcpy(&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
        !          6781:                                        memcpy(&cputrace.prefetch020_valid, &r->prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
        !          6782:                                        memcpy(&cputrace.caches020, &caches020, sizeof caches020);
1.1.1.7   root     6783: 
                   6784:                                        cputrace.memoryoffset = 0;
                   6785:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   6786:                                        cputrace.readcounter = cputrace.writecounter = 0;
                   6787:                                }
1.1.1.4   root     6788: 
1.1.1.7   root     6789: #ifndef WINUAE_FOR_HATARI
                   6790:                                if (inputrecord_debug & 4) {
                   6791:                                        if (input_record > 0)
                   6792:                                                inprec_recorddebug_cpu (1);
                   6793:                                        else if (input_play > 0)
                   6794:                                                inprec_playdebug_cpu (1);
                   6795:                                }
                   6796: #endif
1.1.1.4   root     6797: 
1.1.1.7   root     6798:                                (*cpufunctbl[r->opcode])(r->opcode);
                   6799:                
                   6800:                                wait_memory_cycles();
                   6801: 
1.1.1.8   root     6802: #ifdef WINUAE_FOR_HATARI
                   6803: //fprintf ( stderr, "cyc_2ce %d\n" , currcycle );
                   6804:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   6805:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   6806: //                             currcycle = 0;  // FIXME : uncomment this when using DSP_CyclesGlobalClockCounter in DSP_Run
1.1.1.4   root     6807: 
1.1.1.7   root     6808:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6809:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6810:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6811:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6812:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6813:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6814:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6815:                                if ( MFP_UpdateNeeded == true )
                   6816:                                        MFP_UpdateIRQ ( 0 );
                   6817: #endif
1.1.1.4   root     6818: 
1.1.1.9 ! root     6819:                cont:
1.1.1.7   root     6820:                                if (r->spcflags || time_for_interrupt ()) {
                   6821:                                        if (do_specialties (0))
                   6822:                                                exit = true;
                   6823:                                }
1.1.1.4   root     6824: 
1.1.1.7   root     6825: #ifdef WINUAE_FOR_HATARI
                   6826:                                /* Run DSP 56k code if necessary */
                   6827:                                if (bDspEnabled) {
                   6828: //fprintf ( stderr, "dsp cyc_2ce %d\n" , currcycle );
                   6829:                                        DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
1.1.1.8   root     6830: //fprintf ( stderr, "dsp cyc_2ce %d - %d\n" , currcycle * 2 / CYCLE_UNIT , (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) );
                   6831: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     6832:                                }
                   6833: #endif
1.1.1.4   root     6834: 
1.1.1.7   root     6835:                                regs.ipl = regs.ipl_pin;
1.1.1.4   root     6836: 
1.1.1.7   root     6837:                        }
                   6838:                } CATCH(prb) {
                   6839:                        bus_error();
                   6840:                        if (r->spcflags || time_for_interrupt()) {
1.1.1.9 ! root     6841:                                if (do_specialties(0))
1.1.1.7   root     6842:                                        exit = true;
                   6843:                        }
1.1.1.9 ! root     6844:                        regs.ipl = regs.ipl_pin;
1.1.1.7   root     6845:                } ENDTRY
1.1.1.4   root     6846:        }
                   6847: }
                   6848: 
1.1.1.7   root     6849: #ifdef CPUEMU_20
                   6850: 
                   6851: // full prefetch 020 (more compatible)
1.1.1.4   root     6852: static void m68k_run_2p (void)
                   6853: {
                   6854:        struct regstruct *r = &regs;
1.1.1.7   root     6855:        bool exit = false;
1.1.1.8   root     6856:        bool first = true;
                   6857: 
                   6858:        Log_Printf(LOG_DEBUG, "m68k_run_2p\n");
1.1.1.4   root     6859: 
1.1.1.7   root     6860:        while (!exit) {
                   6861:                TRY(prb) {
1.1.1.8   root     6862: 
                   6863:                        if (first) {
                   6864:                                if (cpu_tracer < 0) {
                   6865:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                   6866:                                        r->ir = cputrace.ir;
                   6867:                                        r->irc = cputrace.irc;
                   6868:                                        r->sr = cputrace.sr;
                   6869:                                        r->usp = cputrace.usp;
                   6870:                                        r->isp = cputrace.isp;
                   6871:                                        r->intmask = cputrace.intmask;
                   6872:                                        r->stopped = cputrace.stopped;
                   6873: 
                   6874:                                        r->msp = cputrace.msp;
                   6875:                                        r->vbr = cputrace.vbr;
                   6876:                                        r->caar = cputrace.caar;
                   6877:                                        r->cacr = cputrace.cacr;
                   6878:                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
                   6879:                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
                   6880:                                        r->prefetch020addr = cputrace.prefetch020addr;
1.1.1.9 ! root     6881:                                        memcpy(&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof(uae_u16));
        !          6882:                                        memcpy(&r->prefetch020_valid, &cputrace.prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
        !          6883:                                        memcpy(&caches020, &cputrace.caches020, sizeof caches020);
1.1.1.8   root     6884: 
                   6885:                                        m68k_setpc (cputrace.pc);
                   6886:                                        if (!r->stopped) {
                   6887:                                                if (cputrace.state > 1)
                   6888:                                                        Exception (cputrace.state);
                   6889:                                                else if (cputrace.state == 1)
                   6890:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                   6891:                                        }
                   6892:                                        if (regs.stopped)
                   6893:                                                set_special (SPCFLAG_STOP);
                   6894:                                        set_cpu_tracer (false);
                   6895:                                        goto cont;
                   6896:                                }
                   6897:                                set_cpu_tracer (false);
                   6898:                                first = false;
                   6899:                        }
                   6900: 
1.1.1.7   root     6901:                        while (!exit) {
                   6902: #ifdef WINUAE_FOR_HATARI
                   6903:                                //m68k_dumpstate_file(stderr, NULL);
                   6904:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6905:                                {
                   6906:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6907:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6908:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   6909:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   6910:                                }
                   6911: #endif
                   6912:                                r->instruction_pc = m68k_getpc ();
1.1.1.8   root     6913:                                r->opcode = regs.irc;
1.1.1.4   root     6914: 
1.1.1.7   root     6915: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     6916: #if DEBUG_CD32CDTVIO
1.1.1.7   root     6917:                                out_cd32io (m68k_getpc ());
                   6918: #endif
1.1.1.4   root     6919: #endif
                   6920: 
1.1.1.8   root     6921:                                if (cpu_tracer) {
1.1.1.4   root     6922: 
1.1.1.8   root     6923: #if CPUTRACE_DEBUG
                   6924:                                        validate_trace ();
                   6925: #endif
                   6926:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
                   6927:                                        cputrace.opcode = r->opcode;
                   6928:                                        cputrace.ir = r->ir;
                   6929:                                        cputrace.irc = r->irc;
                   6930:                                        cputrace.sr = r->sr;
                   6931:                                        cputrace.usp = r->usp;
                   6932:                                        cputrace.isp = r->isp;
                   6933:                                        cputrace.intmask = r->intmask;
                   6934:                                        cputrace.stopped = r->stopped;
                   6935:                                        cputrace.state = 1;
                   6936:                                        cputrace.pc = m68k_getpc ();
                   6937: 
                   6938:                                        cputrace.msp = r->msp;
                   6939:                                        cputrace.vbr = r->vbr;
                   6940:                                        cputrace.caar = r->caar;
                   6941:                                        cputrace.cacr = r->cacr;
                   6942:                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
                   6943:                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
                   6944:                                        cputrace.prefetch020addr = r->prefetch020addr;
1.1.1.9 ! root     6945:                                        memcpy(&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof(uae_u16));
        !          6946:                                        memcpy(&cputrace.prefetch020_valid, &r->prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
        !          6947:                                        memcpy(&cputrace.caches020, &caches020, sizeof caches020);
1.1.1.8   root     6948: 
                   6949:                                        cputrace.memoryoffset = 0;
                   6950:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   6951:                                        cputrace.readcounter = cputrace.writecounter = 0;
                   6952:                                }
                   6953: 
                   6954: #ifndef WINUAE_FOR_HATARI
                   6955:                                if (inputrecord_debug & 4) {
                   6956:                                        if (input_record > 0)
                   6957:                                                inprec_recorddebug_cpu (1);
                   6958:                                        else if (input_play > 0)
                   6959:                                                inprec_playdebug_cpu (1);
                   6960:                                }
                   6961: #endif
1.1.1.9 ! root     6962:                                if (currprefs.cpu_memory_cycle_exact) {
1.1.1.8   root     6963: 
1.1.1.9 ! root     6964:                                        (*cpufunctbl[r->opcode])(r->opcode);
        !          6965:                                        cpu_cycles = 0;
1.1.1.4   root     6966: 
1.1.1.9 ! root     6967:                                } else {
        !          6968: 
        !          6969:                                        x_do_cycles (cpu_cycles);
        !          6970: 
        !          6971:                                        cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
        !          6972:                                        cpu_cycles = adjust_cycles (cpu_cycles);
        !          6973: 
        !          6974:                                }
1.1.1.8   root     6975: cont:
1.1.1.7   root     6976: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     6977: //fprintf ( stderr , "waits %d %d %ld\n" , cpu_cycles*2/CYCLE_UNIT , WaitStateCycles , CyclesGlobalClockCounter );
1.1.1.7   root     6978:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4   root     6979: 
1.1.1.8   root     6980: //fprintf ( stderr , "waits %d %d %ld\n" , cpu_cycles*2/CYCLE_UNIT , WaitStateCycles , CyclesGlobalClockCounter );
                   6981:                                if ( WaitStateCycles ) {
1.1.1.7   root     6982:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     6983:                                        M68000_AddCycles(WaitStateCycles);
                   6984:                                        WaitStateCycles = 0;
1.1.1.7   root     6985:                                }
1.1.1.8   root     6986: //fprintf ( stderr , "waits %d %d %ld\n" , cpu_cycles*2/CYCLE_UNIT , WaitStateCycles , CyclesGlobalClockCounter );
1.1.1.4   root     6987: 
1.1.1.7   root     6988:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6989:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6990:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6991:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6992:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6993:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6994:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6995:                                if ( MFP_UpdateNeeded == true )
                   6996:                                        MFP_UpdateIRQ ( 0 );
                   6997: #endif
1.1.1.4   root     6998: 
1.1.1.7   root     6999:                                if (r->spcflags) {
                   7000:                                        if (do_specialties (cpu_cycles))
                   7001:                                                exit = true;
                   7002:                                }
                   7003: 
                   7004: #ifdef WINUAE_FOR_HATARI
                   7005:                                /* Run DSP 56k code if necessary */
                   7006:                                if (bDspEnabled) {
1.1.1.8   root     7007: //if ( DSP_CPU_FREQ_RATIO * ( (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) << nCpuFreqShift )  - 2 * cpu_cycles * 2 / CYCLE_UNIT >= 8 )
                   7008: //fprintf ( stderr , "dsp %d %d\n" , 2 * cpu_cycles * 2 / CYCLE_UNIT , DSP_CPU_FREQ_RATIO * ( (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) << nCpuFreqShift ) );
1.1.1.7   root     7009:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     7010: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     7011:                                }
                   7012: #endif
                   7013: 
                   7014:                                ipl_fetch ();
                   7015:                        }
                   7016:                } CATCH(prb) {
                   7017:                        bus_error();
                   7018:                        if (r->spcflags) {
                   7019:                                if (do_specialties(cpu_cycles))
1.1.1.8   root     7020:                                        exit = true;
1.1.1.7   root     7021:                        }
                   7022:                        ipl_fetch();
                   7023:                } ENDTRY
1.1.1.4   root     7024:        }
                   7025: }
                   7026: 
1.1.1.7   root     7027: #endif
1.1.1.4   root     7028: 
1.1.1.8   root     7029: #ifdef WITH_THREADED_CPU
                   7030: static void *cpu_thread_run_2(void *v)
                   7031: {
                   7032:        bool exit = false;
                   7033:        struct regstruct *r = &regs;
                   7034: 
                   7035:        cpu_thread_active = 1;
                   7036:        while (!exit) {
                   7037:                TRY(prb)
                   7038:                {
                   7039:                        while (!exit) {
                   7040:                                r->instruction_pc = m68k_getpc();
                   7041: 
                   7042:                                r->opcode = x_get_iword(0);
                   7043: 
                   7044:                                (*cpufunctbl[r->opcode])(r->opcode);
                   7045: 
                   7046:                                if (r->spcflags) {
                   7047:                                        if (do_specialties_thread())
                   7048:                                                exit = true;
                   7049:                                }
                   7050:                        }
                   7051:                } CATCH(prb)
                   7052:                {
                   7053:                        bus_error();
                   7054:                        if (r->spcflags) {
                   7055:                                if (do_specialties_thread())
                   7056:                                        exit = true;
                   7057:                        }
                   7058:                } ENDTRY
                   7059:        }
                   7060:        cpu_thread_active = 0;
                   7061:        return 0;
                   7062: }
                   7063: #endif
1.1.1.4   root     7064: 
                   7065: /* Same thing, but don't use prefetch to get opcode.  */
                   7066: static void m68k_run_2 (void)
                   7067: {
1.1.1.8   root     7068: #ifdef WITH_THREADED_CPU
                   7069:        if (currprefs.cpu_thread) {
                   7070:                run_cpu_thread(cpu_thread_run_2);
                   7071:                return;
                   7072:        }
                   7073: #endif
                   7074: 
1.1.1.4   root     7075:        struct regstruct *r = &regs;
1.1.1.7   root     7076:        bool exit = false;
1.1.1.8   root     7077: 
                   7078:        Log_Printf(LOG_DEBUG, "m68k_run_2\n");
1.1.1.4   root     7079: 
1.1.1.7   root     7080:        while (!exit) {
                   7081:                TRY(prb) {
                   7082:                        while (!exit) {
                   7083: #ifdef WINUAE_FOR_HATARI
                   7084:                                //m68k_dumpstate_file(stderr, NULL);
                   7085:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   7086:                                {
                   7087:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   7088:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   7089:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
                   7090:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
                   7091:                                }
                   7092: #endif
                   7093:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     7094: 
1.1.1.7   root     7095:                                r->opcode = x_get_iword(0);
                   7096:                                count_instr (r->opcode);
1.1.1.4   root     7097: 
1.1.1.7   root     7098:                                do_cycles (cpu_cycles);
1.1.1.5   root     7099: 
1.1.1.7   root     7100:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   7101:                                cpu_cycles = adjust_cycles (cpu_cycles);
                   7102: #ifdef WINUAE_FOR_HATARI
                   7103: //fprintf ( stderr , "cyc_2 %d\n" , cpu_cycles );
                   7104:                                M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT);
                   7105: 
1.1.1.8   root     7106:                                if ( WaitStateCycles ) {
1.1.1.7   root     7107:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     7108:                                        M68000_AddCycles(WaitStateCycles);
                   7109:                                        WaitStateCycles = 0;
1.1.1.7   root     7110:                                }
1.1.1.4   root     7111: 
1.1.1.7   root     7112:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   7113:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   7114:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   7115:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   7116:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   7117:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   7118:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   7119:                                if ( MFP_UpdateNeeded == true )
                   7120:                                        MFP_UpdateIRQ ( 0 );
                   7121: #endif
1.1.1.4   root     7122: 
1.1.1.7   root     7123:                                if (r->spcflags) {
                   7124:                                        if (do_specialties (cpu_cycles))
                   7125:                                                exit = true;
                   7126:                                }
                   7127: 
                   7128: #ifdef WINUAE_FOR_HATARI
                   7129:                                /* Run DSP 56k code if necessary */
                   7130:                                if (bDspEnabled) {
                   7131:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     7132: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     7133:                                }
                   7134: #endif
                   7135:                        }
                   7136:                } CATCH(prb) {
                   7137:                        bus_error();
                   7138:                        if (r->spcflags) {
                   7139:                                if (do_specialties(cpu_cycles))
                   7140:                                        exit = true;
                   7141:                        }
                   7142:                } ENDTRY
1.1.1.4   root     7143:        }
                   7144: }
                   7145: 
                   7146: /* fake MMU 68k  */
1.1.1.8   root     7147: #if 0
1.1.1.4   root     7148: static void m68k_run_mmu (void)
                   7149: {
                   7150:        for (;;) {
1.1.1.7   root     7151: #ifdef WINUAE_FOR_HATARI
                   7152:                //m68k_dumpstate_file(stderr, NULL);
1.1.1.4   root     7153:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   7154:                {
                   7155:                        int FrameCycles, HblCounterVideo, LineCycles;
                   7156:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   7157:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.7   root     7158:                        m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4   root     7159:                }
1.1.1.7   root     7160: #endif
                   7161:                regs.opcode = get_iiword (0);
1.1.1.4   root     7162:                do_cycles (cpu_cycles);
                   7163:                mmu_backup_regs = regs;
1.1.1.7   root     7164:                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   7165:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4   root     7166:                if (mmu_triggered)
                   7167:                        mmu_do_hit ();
                   7168:                if (regs.spcflags) {
                   7169:                        if (do_specialties (cpu_cycles))
                   7170:                                return;
                   7171:                }
                   7172:        }
                   7173: }
1.1.1.8   root     7174: #endif
1.1.1.4   root     7175: 
                   7176: #endif /* CPUEMU_0 */
                   7177: 
                   7178: int in_m68k_go = 0;
                   7179: 
1.1.1.8   root     7180: #if 0
1.1.1.4   root     7181: static void exception2_handle (uaecptr addr, uaecptr fault)
                   7182: {
                   7183:        last_addr_for_exception_3 = addr;
                   7184:        last_fault_for_exception_3 = fault;
                   7185:        last_writeaccess_for_exception_3 = 0;
                   7186:        last_instructionaccess_for_exception_3 = 0;
1.1.1.7   root     7187:        Exception (2);
                   7188: }
1.1.1.8   root     7189: #endif
1.1.1.7   root     7190: 
                   7191: static bool cpu_hardreset, cpu_keyboardreset;
                   7192: 
                   7193: bool is_hardreset(void)
                   7194: {
                   7195:        return cpu_hardreset;
                   7196: }
                   7197: bool is_keyboardreset(void)
                   7198: {
                   7199:        return  cpu_keyboardreset;
1.1.1.4   root     7200: }
                   7201: 
                   7202: void m68k_go (int may_quit)
                   7203: {
1.1.1.7   root     7204: #ifndef WINUAE_FOR_HATARI
                   7205:        int hardboot = 1;
                   7206:        int startup = 1;
                   7207: #endif
                   7208: 
1.1.1.8   root     7209: #ifdef WITH_THREADED_CPU
                   7210:        init_cpu_thread();
                   7211: #endif
1.1.1.4   root     7212:        if (in_m68k_go || !may_quit) {
1.1.1.7   root     7213:                write_log (_T("Bug! m68k_go is not reentrant.\n"));
1.1.1.4   root     7214:                abort ();
                   7215:        }
                   7216: 
                   7217:        reset_frame_rate_hack ();
                   7218:        update_68k_cycles ();
1.1.1.7   root     7219: #ifndef WINUAE_FOR_HATARI
                   7220:        start_cycles = 0;
                   7221: #endif
                   7222: 
                   7223:        set_cpu_tracer (false);
1.1.1.4   root     7224: 
1.1.1.7   root     7225:        cpu_prefs_changed_flag = 0;
1.1.1.4   root     7226:        in_m68k_go++;
                   7227:        for (;;) {
                   7228:                void (*run_func)(void);
                   7229: 
1.1.1.7   root     7230: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     7231:                /* Exit hatari ? */
                   7232:                if (bQuitProgram == true)
                   7233:                        break;
1.1.1.7   root     7234: #endif
                   7235: 
                   7236:                cputrace.state = -1;
                   7237: 
                   7238: #ifndef WINUAE_FOR_HATARI
1.1.1.8   root     7239:                if (regs.halted == CPU_HALT_ACCELERATOR_CPU_FALLBACK) {
                   7240:                        regs.halted = 0;
                   7241:                        cpu_do_fallback();
                   7242:                }
                   7243: 
1.1.1.7   root     7244:                if (currprefs.inprecfile[0] && input_play) {
                   7245:                        inprec_open (currprefs.inprecfile, NULL);
                   7246:                        changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0;
                   7247:                        quit_program = UAE_RESET;
                   7248:                }
                   7249:                if (input_play || input_record)
                   7250:                        inprec_startup ();
                   7251: 
                   7252:                if (quit_program > 0) {
                   7253:                        int restored = 0;
                   7254:                        cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD;
                   7255:                        cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0;
                   7256: 
                   7257:                        if (quit_program == UAE_QUIT)
                   7258:                                break;
                   7259: 
                   7260:                        hsync_counter = 0;
                   7261:                        vsync_counter = 0;
                   7262:                        quit_program = 0;
                   7263:                        hardboot = 0;
                   7264: 
                   7265: #ifdef SAVESTATE
                   7266:                        if (savestate_state == STATE_DORESTORE)
                   7267:                                savestate_state = STATE_RESTORE;
                   7268:                        if (savestate_state == STATE_RESTORE)
                   7269:                                restore_state (savestate_fname);
                   7270:                        else if (savestate_state == STATE_REWIND)
                   7271:                                savestate_rewind ();
                   7272: #endif
1.1.1.8   root     7273:                        if (cpu_hardreset)
                   7274:                                m68k_reset_restore();
                   7275:                        prefs_changed_cpu();
1.1.1.9 ! root     7276: #ifdef WINUAE_FOR_HATARI
        !          7277:                        fpu_modechange();               // NP TODO : use SPCFLAG_MODE_CHANGE below instead
1.1.1.7   root     7278: #endif
1.1.1.9 ! root     7279:                        build_cpufunctbl();
        !          7280:                        set_x_funcs();
        !          7281:                        set_cycles (start_cycles);
1.1.1.7   root     7282:                        custom_reset (cpu_hardreset != 0, cpu_keyboardreset);
                   7283:                        m68k_reset2 (cpu_hardreset != 0);
                   7284:                        if (cpu_hardreset) {
                   7285:                                memory_clear ();
                   7286:                                write_log (_T("hardreset, memory cleared\n"));
                   7287:                        }
                   7288:                        cpu_hardreset = false;
                   7289: #ifdef SAVESTATE
                   7290:                        /* We may have been restoring state, but we're done now.  */
                   7291:                        if (isrestore ()) {
                   7292:                                if (debug_dma) {
                   7293:                                        record_dma_reset ();
                   7294:                                        record_dma_reset ();
                   7295:                                }
                   7296:                                savestate_restore_finish ();
                   7297:                                memory_map_dump ();
                   7298:                                if (currprefs.mmu_model == 68030) {
1.1.1.9 ! root     7299:                                        mmu030_decode_tc (tc_030, true);
1.1.1.7   root     7300:                                } else if (currprefs.mmu_model >= 68040) {
                   7301:                                        mmu_set_tc (regs.tcr);
                   7302:                                }
                   7303:                                startup = 1;
                   7304:                                restored = 1;
                   7305:                        }
                   7306: #endif
                   7307:                        if (currprefs.produce_sound == 0)
                   7308:                                eventtab[ev_audio].active = 0;
                   7309:                        m68k_setpc_normal (regs.pc);
                   7310:                        check_prefs_changed_audio ();
                   7311: 
                   7312:                        if (!restored || hsync_counter == 0)
                   7313:                                savestate_check ();
                   7314:                        if (input_record == INPREC_RECORD_START)
                   7315:                                input_record = INPREC_RECORD_NORMAL;
                   7316:                        statusline_clear();
                   7317:                } else {
                   7318:                        if (input_record == INPREC_RECORD_START) {
                   7319:                                input_record = INPREC_RECORD_NORMAL;
                   7320:                                savestate_init ();
                   7321:                                hsync_counter = 0;
                   7322:                                vsync_counter = 0;
                   7323:                                savestate_check ();
                   7324:                        }
                   7325:                }
                   7326: 
                   7327:                if (changed_prefs.inprecfile[0] && input_record)
                   7328:                        inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
                   7329: #endif
                   7330: 
                   7331:                set_cpu_tracer (false);
1.1.1.4   root     7332: 
                   7333: #ifdef DEBUGGER
                   7334:                if (debugging)
                   7335:                        debug ();
                   7336: #endif
1.1.1.7   root     7337: /* [NP] TODO : allow changing cpu on the fly ? */
                   7338: #ifndef WINUAE_FOR_HATARI
                   7339:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
                   7340:                        if (cpu_prefs_changed_flag & 1) {
                   7341:                                uaecptr pc = m68k_getpc();
                   7342:                                prefs_changed_cpu();
1.1.1.9 ! root     7343:                                fpu_modechange();
1.1.1.7   root     7344:                                build_cpufunctbl();
                   7345:                                m68k_setpc_normal(pc);
                   7346:                                fill_prefetch();
                   7347:                        }
                   7348:                        if (cpu_prefs_changed_flag & 2) {
                   7349:                                fixup_cpu(&changed_prefs);
                   7350:                                currprefs.m68k_speed = changed_prefs.m68k_speed;
                   7351:                                currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
                   7352:                                update_68k_cycles();
                   7353:                        }
                   7354:                        cpu_prefs_changed_flag = 0;
                   7355:                }
                   7356: #else
                   7357:                /* [NP] : in Hatari, build_cpufunctbl() is called directly from check_prefs_changed_cpu2() */
                   7358:                /* so we just need to set PC here */
                   7359:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
                   7360:                        if (cpu_prefs_changed_flag & 1) {
                   7361: printf ( "cpu change %d\n" , cpu_prefs_changed_flag );
                   7362:                                uaecptr pc = m68k_getpc();
                   7363:                                m68k_setpc_normal(pc);
                   7364:                                fill_prefetch();
1.1.1.4   root     7365:                        }
1.1.1.7   root     7366:                        cpu_prefs_changed_flag = 0;
1.1.1.4   root     7367:                }
1.1.1.7   root     7368: #endif
1.1.1.4   root     7369: 
1.1.1.7   root     7370:                set_x_funcs();
                   7371: #ifndef WINUAE_FOR_HATARI
                   7372:                if (startup) {
                   7373:                        custom_prepare ();
                   7374:                        protect_roms (true);
1.1.1.4   root     7375:                }
1.1.1.7   root     7376:                startup = 0;
                   7377:                event_wait = true;
1.1.1.4   root     7378: #endif
1.1.1.7   root     7379:                unset_special(SPCFLAG_MODE_CHANGE);
1.1.1.4   root     7380: 
1.1.1.9 ! root     7381:                if (!regs.halted) {
        !          7382:                        // check that PC points to something that looks like memory.
        !          7383:                        uaecptr pc = m68k_getpc();
        !          7384: #ifndef WINUAE_FOR_HATARI
        !          7385:                        addrbank *ab = get_mem_bank_real(pc);
        !          7386: #else
        !          7387:                        addrbank *ab = &get_mem_bank(pc);
        !          7388: #endif
        !          7389:                        if (ab == NULL || ab == &dummy_bank || (!currprefs.cpu_compatible && !valid_address(pc, 2)) || (pc & 1)) {
        !          7390:                                cpu_halt(CPU_HALT_INVALID_START_ADDRESS);
        !          7391:                        }
        !          7392:                }
1.1.1.7   root     7393:                if (regs.halted) {
                   7394:                        cpu_halt (regs.halted);
                   7395:                        if (regs.halted < 0) {
                   7396:                                haltloop();
                   7397:                                continue;
                   7398:                        }
                   7399:                }
                   7400: 
                   7401: #if 0
1.1.1.4   root     7402:                if (mmu_enabled && !currprefs.cachesize) {
                   7403:                        run_func = m68k_run_mmu;
                   7404:                } else {
1.1.1.7   root     7405: #endif
                   7406:                        run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010 ? m68k_run_1_ce :
                   7407:                                currprefs.cpu_compatible && currprefs.cpu_model <= 68010 ? m68k_run_1 :
1.1.1.4   root     7408: #ifdef JIT
                   7409:                                currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
                   7410: #endif
1.1.1.7   root     7411:                                currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
                   7412:                                currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
                   7413:                                currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
                   7414: 
                   7415:                                currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
1.1.1.4   root     7416:                                currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
1.1.1.7   root     7417: 
                   7418:                                currprefs.cpu_model <= 68020 && currprefs.cpu_compatible ? m68k_run_2p :
                   7419:                                currprefs.cpu_model == 68030 && currprefs.cpu_compatible ? m68k_run_2p :
                   7420:                                currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
                   7421: 
                   7422:                                m68k_run_2;
                   7423: #if 0
1.1.1.4   root     7424:                }
1.1.1.7   root     7425: #endif
                   7426:                run_func();
1.1.1.8   root     7427:                Log_Printf(LOG_DEBUG, "exit m68k_run\n");
1.1.1.4   root     7428:        }
1.1.1.7   root     7429: #ifndef WINUAE_FOR_HATARI
                   7430:        protect_roms (false);
                   7431: #endif
1.1.1.4   root     7432:        in_m68k_go--;
                   7433: }
                   7434: 
                   7435: #if 0
                   7436: static void m68k_verify (uaecptr addr, uaecptr *nextpc)
                   7437: {
1.1.1.7   root     7438:        uae_u16 opcode, val;
1.1.1.4   root     7439:        struct instr *dp;
                   7440: 
                   7441:        opcode = get_iword_1 (0);
                   7442:        last_op_for_exception_3 = opcode;
                   7443:        m68kpc_offset = 2;
                   7444: 
                   7445:        if (cpufunctbl[opcode] == op_illg_1) {
                   7446:                opcode = 0x4AFC;
                   7447:        }
                   7448:        dp = table68k + opcode;
                   7449: 
                   7450:        if (dp->suse) {
                   7451:                if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
                   7452:                        Exception (3, 0);
                   7453:                        return;
                   7454:                }
                   7455:        }
                   7456:        if (dp->duse) {
                   7457:                if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
                   7458:                        Exception (3, 0);
                   7459:                        return;
                   7460:                }
                   7461:        }
                   7462: }
                   7463: #endif
                   7464: 
                   7465: static const TCHAR *ccnames[] =
1.1.1.7   root     7466: {
                   7467:        _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
                   7468:        _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
                   7469: };
                   7470: static const TCHAR *fpccnames[] =
                   7471: {
                   7472:        _T("F"),
                   7473:        _T("EQ"),
                   7474:        _T("OGT"),
                   7475:        _T("OGE"),
                   7476:        _T("OLT"),
                   7477:        _T("OLE"),
                   7478:        _T("OGL"),
                   7479:        _T("OR"),
                   7480:        _T("UN"),
                   7481:        _T("UEQ"),
                   7482:        _T("UGT"),
                   7483:        _T("UGE"),
                   7484:        _T("ULT"),
                   7485:        _T("ULE"),
                   7486:        _T("NE"),
                   7487:        _T("T"),
                   7488:        _T("SF"),
                   7489:        _T("SEQ"),
                   7490:        _T("GT"),
                   7491:        _T("GE"),
                   7492:        _T("LT"),
                   7493:        _T("LE"),
                   7494:        _T("GL"),
                   7495:        _T("GLE"),
                   7496:        _T("NGLE"),
                   7497:        _T("NGL"),
                   7498:        _T("NLE"),
                   7499:        _T("NLT"),
                   7500:        _T("NGE"),
                   7501:        _T("NGT"),
                   7502:        _T("SNE"),
                   7503:        _T("ST")
                   7504: };
                   7505: static const TCHAR *fpuopcodes[] =
                   7506: {
                   7507:        _T("FMOVE"),
                   7508:        _T("FINT"),
                   7509:        _T("FSINH"),
                   7510:        _T("FINTRZ"),
                   7511:        _T("FSQRT"),
                   7512:        NULL,
                   7513:        _T("FLOGNP1"),
                   7514:        NULL,
                   7515:        _T("FETOXM1"),
                   7516:        _T("FTANH"),
                   7517:        _T("FATAN"),
                   7518:        NULL,
                   7519:        _T("FASIN"),
                   7520:        _T("FATANH"),
                   7521:        _T("FSIN"),
                   7522:        _T("FTAN"),
                   7523:        _T("FETOX"),    // 0x10
                   7524:        _T("FTWOTOX"),
                   7525:        _T("FTENTOX"),
                   7526:        NULL,
                   7527:        _T("FLOGN"),
                   7528:        _T("FLOG10"),
                   7529:        _T("FLOG2"),
                   7530:        NULL,
                   7531:        _T("FABS"),
                   7532:        _T("FCOSH"),
                   7533:        _T("FNEG"),
                   7534:        NULL,
                   7535:        _T("FACOS"),
                   7536:        _T("FCOS"),
                   7537:        _T("FGETEXP"),
                   7538:        _T("FGETMAN"),
                   7539:        _T("FDIV"),             // 0x20
                   7540:        _T("FMOD"),
                   7541:        _T("FADD"),
                   7542:        _T("FMUL"),
                   7543:        _T("FSGLDIV"),
                   7544:        _T("FREM"),
                   7545:        _T("FSCALE"),
                   7546:        _T("FSGLMUL"),
                   7547:        _T("FSUB"),
                   7548:        NULL,
                   7549:        NULL,
                   7550:        NULL,
                   7551:        NULL,
                   7552:        NULL,
                   7553:        NULL,
                   7554:        NULL,
                   7555:        _T("FSINCOS"),  // 0x30
                   7556:        _T("FSINCOS"),
                   7557:        _T("FSINCOS"),
                   7558:        _T("FSINCOS"),
                   7559:        _T("FSINCOS"),
                   7560:        _T("FSINCOS"),
                   7561:        _T("FSINCOS"),
                   7562:        _T("FSINCOS"),
                   7563:        _T("FCMP"),
                   7564:        NULL,
                   7565:        _T("FTST"),
                   7566:        NULL,
                   7567:        NULL,
                   7568:        NULL,
                   7569:        NULL,
                   7570:        NULL
                   7571: };
                   7572: 
                   7573: static const TCHAR *movemregs[] =
                   7574: {
                   7575:        _T("D0"),
                   7576:        _T("D1"),
                   7577:        _T("D2"),
                   7578:        _T("D3"),
                   7579:        _T("D4"),
                   7580:        _T("D5"),
                   7581:        _T("D6"),
                   7582:        _T("D7"),
                   7583:        _T("A0"),
                   7584:        _T("A1"),
                   7585:        _T("A2"),
                   7586:        _T("A3"),
                   7587:        _T("A4"),
                   7588:        _T("A5"),
                   7589:        _T("A6"),
                   7590:        _T("A7"),
                   7591:        _T("FP0"),
                   7592:        _T("FP1"),
                   7593:        _T("FP2"),
                   7594:        _T("FP3"),
                   7595:        _T("FP4"),
                   7596:        _T("FP5"),
                   7597:        _T("FP6"),
                   7598:        _T("FP7"),
1.1.1.8   root     7599:        _T("FPIAR"),
1.1.1.7   root     7600:        _T("FPSR"),
1.1.1.8   root     7601:        _T("FPCR")
1.1.1.7   root     7602: };
1.1.1.4   root     7603: 
1.1.1.7   root     7604: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
1.1.1.4   root     7605: {
                   7606:        TCHAR *p = out + _tcslen (out);
                   7607:        if (*prevreg < 0) {
                   7608:                *prevreg = reg;
                   7609:                *lastreg = reg;
                   7610:                return;
                   7611:        }
1.1.1.7   root     7612:        if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
                   7613:                _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
1.1.1.4   root     7614:                p = p + _tcslen (p);
1.1.1.8   root     7615:                if (*lastreg != *prevreg) {
                   7616:                        if ((*lastreg) + 2 == reg) {
                   7617:                                _stprintf(p, _T("/%s"), movemregs[*prevreg]);
                   7618:                        } else if ((*lastreg) != (*prevreg)) {
                   7619:                                _stprintf(p, _T("-%s"), movemregs[*prevreg]);
                   7620:                        }
1.1.1.4   root     7621:                }
                   7622:                *lastreg = reg;
                   7623:                *first = 0;
                   7624:        }
                   7625:        *prevreg = reg;
                   7626: }
                   7627: 
1.1.1.7   root     7628: static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode)
1.1.1.4   root     7629: {
                   7630:        unsigned int dmask, amask;
                   7631:        int prevreg = -1, lastreg = -1, first = 1;
1.1.1.7   root     7632:        int i;
1.1.1.4   root     7633: 
1.1.1.7   root     7634:        if (mode == Apdi && !fpmode) {
                   7635:                uae_u8 dmask2;
                   7636:                uae_u8 amask2;
                   7637:                
                   7638:                amask2 = mask & 0xff;
                   7639:                dmask2 = (mask >> 8) & 0xff;
1.1.1.4   root     7640:                dmask = 0;
                   7641:                amask = 0;
                   7642:                for (i = 0; i < 8; i++) {
                   7643:                        if (dmask2 & (1 << i))
                   7644:                                dmask |= 1 << (7 - i);
                   7645:                        if (amask2 & (1 << i))
                   7646:                                amask |= 1 << (7 - i);
                   7647:                }
                   7648:        } else {
                   7649:                dmask = mask & 0xff;
                   7650:                amask = (mask >> 8) & 0xff;
1.1.1.7   root     7651:                if (fpmode == 1 && mode != Apdi) {
                   7652:                        uae_u8 dmask2 = dmask;
                   7653:                        dmask = 0;
                   7654:                        for (i = 0; i < 8; i++) {
                   7655:                                if (dmask2 & (1 << i))
                   7656:                                        dmask |= 1 << (7 - i);
                   7657:                        }
                   7658:                }
                   7659:        }
                   7660:        if (fpmode) {
                   7661:                while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
                   7662:        } else {
                   7663:                while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
                   7664:                while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
1.1.1.4   root     7665:        }
1.1.1.7   root     7666:        addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
1.1.1.4   root     7667: }
                   7668: 
                   7669: static void disasm_size (TCHAR *instrname, struct instr *dp)
                   7670: {
1.1.1.7   root     7671:        if (dp->unsized) {
                   7672:                _tcscat(instrname, _T(" "));
                   7673:                return;
1.1.1.4   root     7674:        }
                   7675:        switch (dp->size)
                   7676:        {
                   7677:        case sz_byte:
1.1.1.7   root     7678:                _tcscat (instrname, _T(".B "));
1.1.1.4   root     7679:                break;
                   7680:        case sz_word:
1.1.1.7   root     7681:                _tcscat (instrname, _T(".W "));
1.1.1.4   root     7682:                break;
                   7683:        case sz_long:
1.1.1.7   root     7684:                _tcscat (instrname, _T(".L "));
1.1.1.4   root     7685:                break;
                   7686:        default:
1.1.1.7   root     7687:                _tcscat (instrname, _T(" "));
1.1.1.4   root     7688:                break;
                   7689:        }
                   7690: }
                   7691: 
1.1.1.9 ! root     7692: static void asm_add_extensions(uae_u16 *data, int *dcntp, int mode, uae_u32 v, uae_u16 *ext, uaecptr pc, int size)
        !          7693: {
        !          7694:        int dcnt = *dcntp;
        !          7695:        if (mode < 0)
        !          7696:                return;
        !          7697:        if (mode == Ad16) {
        !          7698:                data[dcnt++] = v;
        !          7699:        }
        !          7700:        if (mode == PC16) {
        !          7701:                data[dcnt++] = v - (pc + 2);
        !          7702:        }
        !          7703:        if (mode == Ad8r || mode == PC8r) {
        !          7704:                data[dcnt++] = ext[0];
        !          7705:        }
        !          7706:        if (mode == absw) {
        !          7707:                data[dcnt++] = (uae_u16)v;
        !          7708:        }
        !          7709:        if (mode == absl) {
        !          7710:                data[dcnt++] = (uae_u16)(v >> 16);
        !          7711:                data[dcnt++] = (uae_u16)v;
        !          7712:        }
        !          7713:        if ((mode == imm && size == 0) || mode == imm0) {
        !          7714:                data[dcnt++] = (uae_u8)v;
        !          7715:        }
        !          7716:        if ((mode == imm && size == 1) || mode == imm1) {
        !          7717:                data[dcnt++] = (uae_u16)v;
        !          7718:        }
        !          7719:        if ((mode == imm && size == 2) || mode == imm2) {
        !          7720:                data[dcnt++] = (uae_u16)(v >> 16);
        !          7721:                data[dcnt++] = (uae_u16)v;
        !          7722:        }
        !          7723:        *dcntp = dcnt;
        !          7724: }
        !          7725: 
        !          7726: static int asm_isdreg(const TCHAR *s)
        !          7727: {
        !          7728:        if (s[0] == 'D' && s[1] >= '0' && s[1] <= '7')
        !          7729:                return s[1] - '0';
        !          7730:        return -1;
        !          7731: }
        !          7732: static int asm_isareg(const TCHAR *s)
        !          7733: {
        !          7734:        if (s[0] == 'A' && s[1] >= '0' && s[1] <= '7')
        !          7735:                return s[1] - '0';
        !          7736:        return -1;
        !          7737: }
        !          7738: static int asm_ispc(const TCHAR *s)
        !          7739: {
        !          7740:        if (s[0] == 'P' && s[1] == 'C')
        !          7741:                return 1;
        !          7742:        return 0;
        !          7743: }
        !          7744: 
        !          7745: static int asm_parse_mode(TCHAR *s, uae_u8 *reg, uae_u32 *v, uae_u16 *ext)
        !          7746: {
        !          7747:        TCHAR *ss = s;
        !          7748:        *reg = -1;
        !          7749:        *v = 0;
        !          7750:        *ext = 0;
        !          7751:        if (s[0] == 0)
        !          7752:                return -1;
        !          7753:        // Dn
        !          7754:        if (asm_isdreg(s) >= 0 && s[2] == 0) {
        !          7755:                *reg = asm_isdreg(s);
        !          7756:                return Dreg;
        !          7757:        }
        !          7758:        // An
        !          7759:        if (asm_isareg(s) >= 0 && s[2] == 0) {
        !          7760:                *reg = asm_isareg(s);
        !          7761:                return Areg;
        !          7762:        }
        !          7763:        // (An) and (An)+
        !          7764:        if (s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')') {
        !          7765:                *reg = asm_isareg(s + 1);
        !          7766:                if (s[4] == '+' && s[5] == 0)
        !          7767:                        return Aipi;
        !          7768:                if (s[4] == 0)
        !          7769:                        return Aind;
        !          7770:                return -1;
        !          7771:        }
        !          7772:        // -(An)
        !          7773:        if (s[0] == '-' && s[1] == '(' && asm_isareg(s + 2) >= 0 && s[4] == ')' && s[5] == 0) {
        !          7774:                *reg = asm_isareg(s + 2);
        !          7775:                return Apdi;
        !          7776:        }
        !          7777:        // Immediate
        !          7778:        if (s[0] == '#') {
        !          7779:                if (s[1] == '!') {
        !          7780:                        *v = _tstol(s + 2);
        !          7781:                } else {
        !          7782:                        TCHAR *endptr;
        !          7783:                        *v = _tcstol(s + 1, &endptr, 16);
        !          7784:                }
        !          7785:                return imm;
        !          7786:        }
        !          7787:        // Value
        !          7788:        if (s[0] == '!') {
        !          7789:                *v = _tstol(s + 1);
        !          7790:        } else {
        !          7791:                TCHAR *endptr;
        !          7792:                *v = _tcstol(s, &endptr, 16);
        !          7793:        }
        !          7794:        int dots = 0;
        !          7795:        unsigned int i;
        !          7796:        for (i = 0; i < _tcslen(s); i++) {
        !          7797:                if (s[i] == ',')
        !          7798:                        dots++;
        !          7799:        }
        !          7800:        while (*s != 0) {
        !          7801:                // d16(An)
        !          7802:                if (dots == 0 && s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')' && s[4] == 0) {
        !          7803:                        *reg = asm_isareg(s + 1);
        !          7804:                        return Ad16;
        !          7805:                }
        !          7806:                // d16(PC)
        !          7807:                if (dots == 0 && s[0] == '(' && asm_ispc(s + 1) && s[3] == ')' && s[4] == 0) {
        !          7808:                        *reg = 2;
        !          7809:                        return PC16;
        !          7810:                }
        !          7811:                // (d16,An) / (d16,PC)
        !          7812:                if (dots == 1 && s[0] == '(' && !asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
        !          7813:                        TCHAR *startptr, *endptr;
        !          7814:                        if (s[1] == '!') {
        !          7815:                                startptr = s + 2;
        !          7816:                                *v = _tcstol(startptr, &endptr, 10);
        !          7817:                        } else {
        !          7818:                                startptr = s + 1;
        !          7819:                                *v = _tcstol(startptr, &endptr, 16);
        !          7820:                        }
        !          7821:                        if (endptr == startptr || endptr[0] != ',')
        !          7822:                                return -1;
        !          7823:                        if (asm_ispc(endptr + 1) && endptr[3] == ')') {
        !          7824:                                *reg = 2;
        !          7825:                                return PC16;
        !          7826:                        }
        !          7827:                        if (asm_isareg(endptr + 1) >= 0 && endptr[3] == ')') {
        !          7828:                                *reg = asm_isareg(endptr + 1);
        !          7829:                                return Ad16;
        !          7830:                        }
        !          7831:                        return -1;
        !          7832:                }
        !          7833:                // Ad8r PC8r
        !          7834:                if (s[0] == '(') {
        !          7835:                        TCHAR *s2 = s;
        !          7836:                        if (!asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
        !          7837:                                if (dots != 2)
        !          7838:                                        return -1;
        !          7839:                                TCHAR *startptr, *endptr;
        !          7840:                                if (s[1] == '!') {
        !          7841:                                        startptr = s + 2;
        !          7842:                                        *v = _tcstol(startptr, &endptr, 10);
        !          7843:                                } else {
        !          7844:                                        startptr = s + 1;
        !          7845:                                        *v = _tcstol(startptr, &endptr, 16);
        !          7846:                                }
        !          7847:                                if (endptr == startptr || endptr[0] != ',')
        !          7848:                                        return -1;
        !          7849:                                s2 = endptr + 1;
        !          7850:                        } else if (((asm_isareg(s + 1) >= 0 || asm_ispc(s + 1)) && s[3] == ',') || (asm_isdreg(s + 4) >= 0 || asm_isareg(s + 4) >= 0)) {
        !          7851:                                if (dots != 1)
        !          7852:                                        return -1;
        !          7853:                                s2 = s + 1;
        !          7854:                        } else {
        !          7855:                                return -1;
        !          7856:                        }
        !          7857:                        uae_u8 reg2;
        !          7858:                        bool ispc = asm_ispc(s2);
        !          7859:                        if (ispc) {
        !          7860:                                *reg = 3;
        !          7861:                        } else {
        !          7862:                                *reg = asm_isareg(s2);
        !          7863:                        }
        !          7864:                        s2 += 2;
        !          7865:                        if (*s2 != ',')
        !          7866:                                return -1;
        !          7867:                        s2++;
        !          7868:                        if (asm_isdreg(s2) >= 0) {
        !          7869:                                reg2 = asm_isdreg(s2);
        !          7870:                        } else {
        !          7871:                                reg2 = asm_isareg(s2);
        !          7872:                                *ext |= 1 << 15;
        !          7873:                        }
        !          7874:                        s2 += 2;
        !          7875:                        *ext |= reg2 << 12;
        !          7876:                        *ext |= (*v) & 0xff;
        !          7877:                        if (s2[0] == '.' && s2[1] == 'W') {
        !          7878:                                s2 += 2;
        !          7879:                        } else if (s2[0] == '.' && s2[1] == 'L') {
        !          7880:                                *ext |= 1 << 11;
        !          7881:                                s2 += 2;
        !          7882:                        }
        !          7883:                        if (s2[0] == '*') {
        !          7884:                                TCHAR scale = s2[1];
        !          7885:                                if (scale == '2')
        !          7886:                                        *ext |= 1 << 9;
        !          7887:                                else if (scale == '4')
        !          7888:                                        *ext |= 2 << 9;
        !          7889:                                else if (scale == '8')
        !          7890:                                        *ext |= 3 << 9;
        !          7891:                                else
        !          7892:                                        return -1;
        !          7893:                                s2 += 2;
        !          7894:                        }
        !          7895:                        if (s2[0] == ')' && s2[1] == 0) {
        !          7896:                                return ispc ? PC8r : Ad8r;
        !          7897:                        }
        !          7898:                        return -1;
        !          7899:                }
        !          7900:                s++;
        !          7901:        }
        !          7902:        // abs.w
        !          7903:        if (s - ss > 2 && s[-2] == '.' && s[-1] == 'W') {
        !          7904:                *reg = 0;
        !          7905:                return absw;
        !          7906:        }
        !          7907:        // abs.l
        !          7908:        *reg = 1;
        !          7909:        return absl;
        !          7910: }
        !          7911: 
        !          7912: static TCHAR *asm_parse_parm(TCHAR *parm, TCHAR *out)
        !          7913: {
        !          7914:        TCHAR *p = parm;
        !          7915:        bool quote = false;
        !          7916: 
        !          7917:        for (;;) {
        !          7918:                if (*p == '(') {
        !          7919:                        quote = true;
        !          7920:                }
        !          7921:                if (*p == ')') {
        !          7922:                        if (!quote)
        !          7923:                                return NULL;
        !          7924:                        quote = false;
        !          7925:                }
        !          7926:                if ((*p == ',' || *p == 0) && !quote) {
        !          7927:                        TCHAR c = *p;
        !          7928:                        p[0] = 0;
        !          7929:                        _tcscpy(out, parm);
        !          7930:                        my_trim(out);
        !          7931:                        if (c)
        !          7932:                                p++;
        !          7933:                        return p;
        !          7934:                }
        !          7935:                p++;
        !          7936:        }
        !          7937: }
        !          7938: 
        !          7939: static bool m68k_asm_parse_movec(TCHAR *s, TCHAR *d)
        !          7940: {
        !          7941:        int i;
        !          7942:        for (i = 0; m2cregs[i].regname; i++) {
        !          7943:                if (!_tcscmp(s, m2cregs[i].regname)) {
        !          7944:                        uae_u16 v = m2cregs[i].regno;
        !          7945:                        if (asm_isareg(d) >= 0)
        !          7946:                                v |= 0x8000 | (asm_isareg(d) << 12);
        !          7947:                        else if (asm_isdreg(d) >= 0)
        !          7948:                                v |= (asm_isdreg(d) << 12);
        !          7949:                        else
        !          7950:                                return false;
        !          7951:                        _stprintf(s, _T("#%X"), v);
        !          7952:                        return true;
        !          7953:                }
        !          7954:        }
        !          7955:        return false;
        !          7956: }
        !          7957: 
        !          7958: static bool m68k_asm_parse_movem(TCHAR *s, int dir)
        !          7959: {
        !          7960:        TCHAR *d = s;
        !          7961:        uae_u16 regmask = 0;
        !          7962:        uae_u16 mask = dir ? 0x8000 : 0x0001;
        !          7963:        bool ret = false;
        !          7964:        while(*s) {
        !          7965:                int dreg = asm_isdreg(s);
        !          7966:                int areg = asm_isareg(s);
        !          7967:                if (dreg < 0 && areg < 0)
        !          7968:                        break;
        !          7969:                int reg = dreg >= 0 ? dreg : areg + 8;
        !          7970:                regmask |= dir ? (mask >> reg) : (mask << reg);
        !          7971:                s += 2;
        !          7972:                if (*s == 0) {
        !          7973:                        ret = true;
        !          7974:                        break;
        !          7975:                } else if (*s == '/') {
        !          7976:                        s++;
        !          7977:                        continue;
        !          7978:                } else if (*s == '-') {
        !          7979:                        s++;
        !          7980:                        int dreg2 = asm_isdreg(s);
        !          7981:                        int areg2 = asm_isareg(s);
        !          7982:                        if (dreg2 < 0 && areg2 < 0)
        !          7983:                                break;
        !          7984:                        int reg2 = dreg2 >= 0 ? dreg2 : areg2 + 8;
        !          7985:                        if (reg2 < reg)
        !          7986:                                break;
        !          7987:                        while (reg2 >= reg) {
        !          7988:                                regmask |= dir ? (mask >> reg) : (mask << reg);
        !          7989:                                reg++;
        !          7990:                        }
        !          7991:                        s += 2;
        !          7992:                        if (*s == 0) {
        !          7993:                                ret = true;
        !          7994:                                break;
        !          7995:                        }
        !          7996:                } else {
        !          7997:                        break;
        !          7998:                }
        !          7999:        }
        !          8000:        if (ret)
        !          8001:                _stprintf(d, _T("#%X"), regmask);
        !          8002:        return ret;
        !          8003: }
        !          8004: 
        !          8005: int m68k_asm(TCHAR *sline, uae_u16 *out, uaecptr pc)
        !          8006: {
        !          8007:        TCHAR *p;
        !          8008:        const TCHAR *cp1;
        !          8009:        TCHAR ins[256], parms[256];
        !          8010:        TCHAR line[256];
        !          8011:        TCHAR srcea[256], dstea[256];
        !          8012:        uae_u16 data[16], sexts[8], dexts[8];
        !          8013:        int dcnt = 0;
        !          8014:        int cc = -1;
        !          8015:        int quick = 0;
        !          8016:        bool immrelpc = false;
        !          8017: 
        !          8018:        if (_tcslen(sline) > 100)
        !          8019:                return -1;
        !          8020: 
        !          8021:        srcea[0] = dstea[0] = 0;
        !          8022:        parms[0] = 0;
        !          8023: 
        !          8024:        // strip all white space except first space
        !          8025:        p = line;
        !          8026:        bool firstsp = true;
        !          8027:        int i;
        !          8028:        for (i = 0; sline[i]; i++) {
        !          8029:                TCHAR c = sline[i];
        !          8030:                if (c == 32 && firstsp) {
        !          8031:                        firstsp = false;
        !          8032:                        *p++ = 32;
        !          8033:                }
        !          8034:                if (c <= 32)
        !          8035:                        continue;
        !          8036:                *p++ = c;
        !          8037:        }
        !          8038:        *p = 0;
        !          8039: 
        !          8040:        to_upper(line, _tcslen(line));
        !          8041: 
        !          8042:        p = line;
        !          8043:        while (*p && *p != ' ')
        !          8044:                p++;
        !          8045:        if (*p == ' ') {
        !          8046:                *p = 0;
        !          8047:                _tcscpy(parms, p + 1);
        !          8048:                my_trim(parms);
        !          8049:        }
        !          8050:        _tcscpy(ins, line);
        !          8051:        
        !          8052:        if (_tcslen(ins) == 0)
        !          8053:                return 0;
        !          8054: 
        !          8055:        int size = 1;
        !          8056:        int inssize = -1;
        !          8057:        cp1 = _tcschr(line, '.');
        !          8058:        if (cp1) {
        !          8059:                size = cp1[1];
        !          8060:                if (size == 'W')
        !          8061:                        size = 1;
        !          8062:                else if (size == 'L')
        !          8063:                        size = 2;
        !          8064:                else if (size == 'B')
        !          8065:                        size = 0;
        !          8066:                else
        !          8067:                        return 0;
        !          8068:                inssize = size;
        !          8069:                line[cp1 - line] = 0;
        !          8070:                _tcscpy(ins, line);
        !          8071:        }
        !          8072: 
        !          8073:        TCHAR *parmp = parms;
        !          8074:        parmp = asm_parse_parm(parmp, srcea);
        !          8075:        if (!parmp)
        !          8076:                return 0;
        !          8077:        if (srcea[0]) {
        !          8078:                parmp = asm_parse_parm(parmp, dstea);
        !          8079:                if (!parmp)
        !          8080:                        return 0;
        !          8081:        }
        !          8082: 
        !          8083:        int smode = -1;
        !          8084:        int dmode = -1;
        !          8085:        uae_u8 sreg = -1;
        !          8086:        uae_u8 dreg = -1;
        !          8087:        uae_u32 sval = 0;
        !          8088:        uae_u32 dval = 0;
        !          8089:        int ssize = -1;
        !          8090:        int dsize = -1;
        !          8091: 
        !          8092:        dmode = asm_parse_mode(dstea, &dreg, &dval, dexts);
        !          8093: 
        !          8094: 
        !          8095:        // Common alias
        !          8096:        if (!_tcscmp(ins, _T("BRA"))) {
        !          8097:                _tcscpy(ins, _T("BT"));
        !          8098:        } else if (!_tcscmp(ins, _T("BSR"))) {
        !          8099:                immrelpc = true;
        !          8100:        } else if (!_tcscmp(ins, _T("MOVEM"))) {
        !          8101:                if (dmode >= Aind && _tcschr(dstea, '-') == NULL && _tcschr(dstea, '/') == NULL) {
        !          8102:                        _tcscpy(ins, _T("MVMLE"));
        !          8103:                        if (!m68k_asm_parse_movem(srcea, dmode == Apdi))
        !          8104:                                return -1;
        !          8105:                } else {
        !          8106:                        TCHAR tmp[256];
        !          8107:                        _tcscpy(ins, _T("MVMEL"));
        !          8108:                        _tcscpy(tmp, srcea);
        !          8109:                        _tcscpy(srcea, dstea);
        !          8110:                        _tcscpy(dstea, tmp);
        !          8111:                        if (!m68k_asm_parse_movem(srcea, 0))
        !          8112:                                return -1;
        !          8113:                        dmode = asm_parse_mode(dstea, &dreg, &dval, dexts);
        !          8114:                }
        !          8115:        } else if (!_tcscmp(ins, _T("MOVEC"))) {
        !          8116:                if (dmode == Dreg || dmode == Areg) {
        !          8117:                        _tcscpy(ins, _T("MOVEC2"));
        !          8118:                        if (!m68k_asm_parse_movec(srcea, dstea))
        !          8119:                                return -1;
        !          8120:                } else {
        !          8121:                        TCHAR tmp[256];
        !          8122:                        _tcscpy(ins, _T("MOVE2C"));
        !          8123:                        _tcscpy(tmp, srcea);
        !          8124:                        _tcscpy(srcea, dstea);
        !          8125:                        dstea[0] = 0;
        !          8126:                        if (!m68k_asm_parse_movec(srcea, tmp))
        !          8127:                                return -1;
        !          8128:                }
        !          8129:                dmode = -1;
        !          8130:        }
        !          8131:        
        !          8132:        if (dmode == Areg) {
        !          8133:                int l = _tcslen(ins);
        !          8134:                if (l <= 2)
        !          8135:                        return -1;
        !          8136:                TCHAR last = ins[l- 1];
        !          8137:                if (last == 'Q') {
        !          8138:                        last = ins[l - 2];
        !          8139:                        if (last != 'A') {
        !          8140:                                ins[l - 1] = 'A';
        !          8141:                                ins[l] = 'Q';
        !          8142:                                ins[l + 1] = 0;
        !          8143:                        }
        !          8144:                } else if (last != 'A') {
        !          8145:                        _tcscat(ins, _T("A"));
        !          8146:                }
        !          8147:        }
        !          8148: 
        !          8149:        if (ins[_tcslen(ins) - 1] == 'Q') {
        !          8150:                quick = 1;
        !          8151:                ins[_tcslen(ins) - 1] = 0;
        !          8152:        }
        !          8153: 
        !          8154:        struct mnemolookup *lookup;
        !          8155:        for (lookup = lookuptab; lookup->name; lookup++) {
        !          8156:                if (!_tcscmp(ins, lookup->name))
        !          8157:                        break;
        !          8158:        }
        !          8159:        if (!lookup->name) {
        !          8160:                // Check cc variants
        !          8161:                bool fp = ins[0] == 'F';
        !          8162:                for (lookup = lookuptab; lookup->name; lookup++) {
        !          8163:                        const TCHAR *ccp = _tcsstr(lookup->name, _T("cc"));
        !          8164:                        if (ccp) {
        !          8165:                                TCHAR tmp[256];
        !          8166:                                int i;
        !          8167:                                for (i = 0; i < (fp ? 32 : 16); i++) {
        !          8168:                                        const TCHAR *ccname = fp ? fpccnames[i] : ccnames[i];
        !          8169:                                        _tcscpy(tmp, lookup->name);
        !          8170:                                        _tcscpy(tmp + (ccp - lookup->name), ccname);
        !          8171:                                        if (tmp[_tcslen(tmp) - 1] == ' ')
        !          8172:                                                tmp[_tcslen(tmp) - 1] = 0;
        !          8173:                                        if (!_tcscmp(tmp, ins)) {
        !          8174:                                                _tcscpy(ins, lookup->name);
        !          8175:                                                cc = i;
        !          8176:                                                // Bcc.B uses same encoding mode as MOVEQ
        !          8177:                                                if (size == 0) {
        !          8178:                                                        quick = 2;
        !          8179:                                                }
        !          8180:                                                immrelpc = true;
        !          8181:                                                break;
        !          8182:                                        }
        !          8183:                                }
        !          8184:                        }
        !          8185:                        if (cc >= 0)
        !          8186:                                break;
        !          8187:                }
        !          8188:        }
        !          8189: 
        !          8190:        if (!lookup->name)
        !          8191:                return 0;
        !          8192: 
        !          8193:        int mnemo = lookup->mnemo;
        !          8194: 
        !          8195:        int found = 0;
        !          8196:        int sizemask = 0;
        !          8197:        int tsize = size;
        !          8198:        int unsized = 0;
        !          8199: 
        !          8200:        int round;
        !          8201:        for (round = 0; round < 9; round++) {
        !          8202: 
        !          8203:                if (!found && round == 8)
        !          8204:                        return 0;
        !          8205: 
        !          8206:                if (round == 3) {
        !          8207:                        // Q is always LONG sized
        !          8208:                        if (quick == 1) {
        !          8209:                                tsize = 2;
        !          8210:                        }
        !          8211:                        bool isimm = srcea[0] == '#';
        !          8212:                        if (immrelpc && !isimm) {
        !          8213:                                TCHAR tmp[256];
        !          8214:                                _tcscpy(tmp, srcea);
        !          8215:                                srcea[0] = '#';
        !          8216:                                _tcscpy(srcea + 1, tmp);
        !          8217:                        }
        !          8218:                        smode = asm_parse_mode(srcea, &sreg, &sval, sexts);
        !          8219:                        if (immrelpc && !isimm) {
        !          8220:                                sval = sval - (pc + 2);
        !          8221:                        }
        !          8222:                        if (quick) {
        !          8223:                                smode = immi;
        !          8224:                                sreg = sval & 0xff;
        !          8225:                        }
        !          8226:                }
        !          8227: 
        !          8228:                if (round == 1) {
        !          8229:                        if (!quick && (sizemask == 1 || sizemask == 2 || sizemask == 4)) {
        !          8230:                                tsize = 0;
        !          8231:                                if (sizemask == 2)
        !          8232:                                        tsize = 1;
        !          8233:                                else if (sizemask == 4)
        !          8234:                                        tsize = 2;
        !          8235:                        } else {
        !          8236:                                continue;
        !          8237:                        }
        !          8238:                }
        !          8239:                if (round == 2 && !found) {
        !          8240:                        unsized = 1;
        !          8241:                }
        !          8242: 
        !          8243:                if (round == 4 && smode == imm) {
        !          8244:                        smode = imm0;
        !          8245:                } else if (round == 5 && smode == imm0) {
        !          8246:                        smode = imm1;
        !          8247:                } else if (round == 6 && smode == imm1) {
        !          8248:                        smode = imm2;
        !          8249:                } else if (round == 7 && smode == imm2) {
        !          8250:                        smode = immi;
        !          8251:                        sreg = sval & 0xff;
        !          8252:                } else if (round == 4) {
        !          8253:                        round += 5 - 1;
        !          8254:                }
        !          8255: 
        !          8256:                int opcode;
        !          8257:                for (opcode = 0; opcode < 65536; opcode++) {
        !          8258:                        struct instr *table = &table68k[opcode];
        !          8259:                        if (table->mnemo != mnemo)
        !          8260:                                continue;
        !          8261:                        if (cc >= 0 && table->cc != cc)
        !          8262:                                continue;
        !          8263: 
        !          8264: #if 0
        !          8265:                        if (round == 0) {
        !          8266:                                console_out_f(_T("%s OP=%04x S=%d SR=%d SM=%d SU=%d SP=%d DR=%d DM=%d DU=%d DP=%d SDU=%d\n"), lookup->name, opcode, table->size,
        !          8267:                                        table->sreg, table->smode, table->suse, table->spos,
        !          8268:                                        table->dreg, table->dmode, table->duse, table->dpos,
        !          8269:                                        table->sduse);
        !          8270:                        }
        !          8271: #endif
        !          8272: 
        !          8273:                        if (table->duse && !(table->dmode == dmode || (dmode >= imm && dmode <= imm2 && table->dmode >= imm && table->dmode <= imm2)))
        !          8274:                                continue;
        !          8275:                        if (round == 0) {
        !          8276:                                sizemask |= 1 << table->size;
        !          8277:                        }
        !          8278:                        if (unsized > 0 && !table->unsized) {
        !          8279:                                continue;
        !          8280:                        }
        !          8281: 
        !          8282:                        found++;
        !          8283: 
        !          8284:                        if (round >= 3) {
        !          8285: 
        !          8286:                                if (
        !          8287:                                        ((table->size == tsize || table->unsized)) &&
        !          8288:                                        ((!table->suse && smode < 0) || (table->suse && table->smode == smode)) &&
        !          8289:                                        ((!table->duse && dmode < 0) || (table->duse && (table->dmode == dmode || (dmode == imm && (table->dmode >= imm && table->dmode <= imm2))))) &&
        !          8290:                                        ((table->sreg == sreg || (table->smode >= absw && table->smode != immi))) &&
        !          8291:                                        ((table->dreg == dreg || table->dmode >= absw))
        !          8292:                                        )
        !          8293:                                {
        !          8294:                                        if (inssize >= 0 && tsize != inssize)
        !          8295:                                                continue;
        !          8296: 
        !          8297: 
        !          8298:                                        data[dcnt++] = opcode;
        !          8299:                                        asm_add_extensions(data, &dcnt, smode, sval, sexts, pc, tsize);
        !          8300:                                        if (smode >= 0)
        !          8301:                                                asm_add_extensions(data, &dcnt, dmode, dval, dexts, pc, tsize);
        !          8302:                                        int i;
        !          8303:                                        for (i = 0; i < dcnt; i++) {
        !          8304:                                                out[i] = data[i];
        !          8305:                                        }
        !          8306:                                        return dcnt;
        !          8307:                                }
        !          8308: 
        !          8309:                        }
        !          8310:                }
        !          8311:        }
        !          8312: 
        !          8313:        return 0;
        !          8314: }
        !          8315: 
1.1.1.7   root     8316: 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     8317: {
1.1.1.7   root     8318:        uae_u32 seaddr2;
                   8319:        uae_u32 deaddr2;
1.1.1.4   root     8320: 
1.1.1.7   root     8321:        if (buf)
                   8322:                memset (buf, 0, bufsize * sizeof (TCHAR));
1.1.1.4   root     8323:        if (!table68k)
                   8324:                return;
                   8325:        while (cnt-- > 0) {
                   8326:                TCHAR instrname[100], *ccpt;
                   8327:                int i;
                   8328:                uae_u32 opcode;
1.1.1.7   root     8329:                uae_u16 extra;
1.1.1.4   root     8330:                struct mnemolookup *lookup;
                   8331:                struct instr *dp;
1.1.1.7   root     8332:                uaecptr oldpc;
                   8333:                uaecptr m68kpc_illg = 0;
                   8334:                bool illegal = false;
                   8335: 
                   8336:                seaddr2 = deaddr2 = 0;
                   8337:                oldpc = pc;
                   8338:                opcode = get_word_debug (pc);
                   8339:                extra = get_word_debug (pc + 2);
                   8340:                if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
                   8341:                        m68kpc_illg = pc + 2;
                   8342:                        illegal = TRUE;
                   8343:                }
1.1.1.4   root     8344: 
1.1.1.7   root     8345:                dp = table68k + opcode;
                   8346:                if (dp->mnemo == i_ILLG) {
                   8347:                        illegal = FALSE;
1.1.1.4   root     8348:                        opcode = 0x4AFC;
1.1.1.7   root     8349:                        dp = table68k + opcode;
1.1.1.4   root     8350:                }
                   8351:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   8352:                        ;
                   8353: 
1.1.1.7   root     8354:                buf = buf_out (buf, &bufsize, _T("%08X "), pc);
1.1.1.4   root     8355: 
1.1.1.7   root     8356:                pc += 2;
                   8357:                
                   8358:                if (lookup->friendlyname)
1.1.1.4   root     8359:                        _tcscpy (instrname, lookup->friendlyname);
                   8360:                else
                   8361:                        _tcscpy (instrname, lookup->name);
1.1.1.7   root     8362:                ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4   root     8363:                if (ccpt != 0) {
1.1.1.7   root     8364:                        if ((opcode & 0xf000) == 0xf000)
                   8365:                                _tcscpy (ccpt, fpccnames[extra & 0x1f]);
                   8366:                        else
                   8367:                                _tcsncpy (ccpt, ccnames[dp->cc], 2);
1.1.1.4   root     8368:                }
                   8369:                disasm_size (instrname, dp);
                   8370: 
                   8371:                if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
1.1.1.7   root     8372:                        uae_u16 imm = extra;
1.1.1.4   root     8373:                        uae_u16 creg = imm & 0x0fff;
                   8374:                        uae_u16 r = imm >> 12;
                   8375:                        TCHAR regs[16];
1.1.1.7   root     8376:                        const TCHAR *cname = _T("?");
1.1.1.4   root     8377:                        int i;
                   8378:                        for (i = 0; m2cregs[i].regname; i++) {
                   8379:                                if (m2cregs[i].regno == creg)
                   8380:                                        break;
                   8381:                        }
1.1.1.7   root     8382:                        _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
1.1.1.4   root     8383:                        if (m2cregs[i].regname)
                   8384:                                cname = m2cregs[i].regname;
                   8385:                        if (lookup->mnemo == i_MOVE2C) {
                   8386:                                _tcscat (instrname, regs);
1.1.1.7   root     8387:                                _tcscat (instrname, _T(","));
1.1.1.4   root     8388:                                _tcscat (instrname, cname);
                   8389:                        } else {
                   8390:                                _tcscat (instrname, cname);
1.1.1.7   root     8391:                                _tcscat (instrname, _T(","));
1.1.1.4   root     8392:                                _tcscat (instrname, regs);
                   8393:                        }
1.1.1.7   root     8394:                        pc += 2;
1.1.1.4   root     8395:                } else if (lookup->mnemo == i_MVMEL) {
1.1.1.7   root     8396:                        uae_u16 mask = extra;
                   8397:                        pc += 2;
                   8398:                        pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8399:                        _tcscat (instrname, _T(","));
                   8400:                        movemout (instrname, mask, dp->dmode, 0);
1.1.1.4   root     8401:                } else if (lookup->mnemo == i_MVMLE) {
1.1.1.7   root     8402:                        uae_u16 mask = extra;
                   8403:                        pc += 2;
                   8404:                        movemout(instrname, mask, dp->dmode, 0);
                   8405:                        _tcscat(instrname, _T(","));
                   8406:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8407:                } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
                   8408:                        TCHAR *p;
                   8409:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8410:                        extra = get_word_debug(pc);
                   8411:                        pc += 2;
                   8412:                        p = instrname + _tcslen(instrname);
                   8413:                        if (extra & 0x0400)
                   8414:                                _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
                   8415:                        else
                   8416:                                _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
                   8417:                } else if (lookup->mnemo == i_MOVES) {
                   8418:                        TCHAR *p;
                   8419:                        pc += 2;
1.1.1.9 ! root     8420:                        if (!(extra & 0x0800)) {
1.1.1.7   root     8421:                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8422:                                p = instrname + _tcslen(instrname);
                   8423:                                _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                   8424:                        } else {
                   8425:                                p = instrname + _tcslen(instrname);
                   8426:                                _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                   8427:                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8428:                        }
                   8429:                } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
                   8430:                                   lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
                   8431:                                   lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
                   8432:                                   lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
                   8433:                        TCHAR *p;
                   8434:                        int reg = -1;
                   8435: 
                   8436:                        pc += 2;
                   8437:                        p = instrname + _tcslen(instrname);
                   8438:                        if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
                   8439:                                reg = (extra >> 12) & 7;
                   8440:                        if (lookup->mnemo == i_BFINS)
                   8441:                                _stprintf(p, _T("D%d,"), reg);
                   8442:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8443:                        _tcscat(instrname, _T(" {"));
                   8444:                        p = instrname + _tcslen(instrname);
                   8445:                        if (extra & 0x0800)
                   8446:                                _stprintf(p, _T("D%d"), (extra >> 6) & 7);
                   8447:                        else
                   8448:                                _stprintf(p, _T("%d"), (extra >> 6) & 31);
                   8449:                        _tcscat(instrname, _T(":"));
                   8450:                        p = instrname + _tcslen(instrname);
                   8451:                        if (extra & 0x0020)
                   8452:                                _stprintf(p, _T("D%d"), extra & 7);
                   8453:                        else
                   8454:                                _stprintf(p, _T("%d"), extra  & 31);
                   8455:                        _tcscat(instrname, _T("}"));
                   8456:                        p = instrname + _tcslen(instrname);
                   8457:                        if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
                   8458:                                _stprintf(p, _T(",D%d"), reg);
                   8459:                } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
                   8460:                        lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
                   8461:                        if ((opcode & 0xc0) == 0xc0)
                   8462:                                _tcscat(instrname, _T("BC"));
                   8463:                        else if (opcode & 0x80)
                   8464:                                _tcscat(instrname, _T("IC"));
                   8465:                        else if (opcode & 0x40)
                   8466:                                _tcscat(instrname, _T("DC"));
                   8467:                        else
                   8468:                                _tcscat(instrname, _T("?"));
                   8469:                        if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
                   8470:                                TCHAR *p = instrname + _tcslen(instrname);
                   8471:                                _stprintf(p, _T(",(A%d)"), opcode & 7);
                   8472:                        }
                   8473:                } else if (lookup->mnemo == i_FPP) {
                   8474:                        TCHAR *p;
                   8475:                        int ins = extra & 0x3f;
                   8476:                        int size = (extra >> 10) & 7;
                   8477: 
                   8478:                        pc += 2;
                   8479:                        if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
                   8480:                                fpdata fp;
1.1.1.9 ! root     8481:                                fpu_get_constant(&fp, extra);
        !          8482:                                _stprintf(instrname, _T("FMOVECR.X #0x%02x [%s],FP%d"), extra & 0x7f, fpp_print(&fp, 0), (extra >> 7) & 7);
1.1.1.7   root     8483:                        } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
                   8484:                                int dr = (extra >> 13) & 1;
                   8485:                                int mode;
                   8486:                                int dreg = (extra >> 4) & 7;
                   8487:                                int regmask, fpmode;
                   8488:                                
                   8489:                                if (extra & 0x4000) {
                   8490:                                        mode = (extra >> 11) & 3;
                   8491:                                        regmask = extra & 0xff;  // FMOVEM FPx
                   8492:                                        fpmode = 1;
                   8493:                                        _tcscpy(instrname, _T("FMOVEM.X "));
                   8494:                                } else {
                   8495:                                        mode = 0;
                   8496:                                        regmask = (extra >> 10) & 7;  // FMOVEM control
                   8497:                                        fpmode = 2;
                   8498:                                        _tcscpy(instrname, _T("FMOVEM.L "));
                   8499:                                        if (regmask == 1 || regmask == 2 || regmask == 4)
                   8500:                                                _tcscpy(instrname, _T("FMOVE.L "));
                   8501:                                }
                   8502:                                p = instrname + _tcslen(instrname);
                   8503:                                if (dr) {
                   8504:                                        if (mode & 1)
                   8505:                                                _stprintf(instrname, _T("D%d"), dreg);
                   8506:                                        else
                   8507:                                                movemout(instrname, regmask, dp->dmode, fpmode);
                   8508:                                        _tcscat(instrname, _T(","));
                   8509:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8510:                                } else {
                   8511:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8512:                                        _tcscat(instrname, _T(","));
                   8513:                                        p = instrname + _tcslen(instrname);
                   8514:                                        if (mode & 1)
                   8515:                                                _stprintf(p, _T("D%d"), dreg);
                   8516:                                        else
                   8517:                                                movemout(p, regmask, dp->dmode, fpmode);
                   8518:                                }
                   8519:                        } else {
                   8520:                                if (fpuopcodes[ins])
                   8521:                                        _tcscpy(instrname, fpuopcodes[ins]);
                   8522:                                else
                   8523:                                        _tcscpy(instrname, _T("F?"));
                   8524: 
                   8525:                                if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
                   8526:                                        int kfactor = extra & 0x7f;
                   8527:                                        _tcscpy(instrname, _T("FMOVE."));
                   8528:                                        _tcscat(instrname, fpsizes[size]);
                   8529:                                        _tcscat(instrname, _T(" "));
                   8530:                                        p = instrname + _tcslen(instrname);
                   8531:                                        _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
                   8532:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
                   8533:                                        p = instrname + _tcslen(instrname);
                   8534:                                        if (size == 7) {
                   8535:                                                _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
                   8536:                                        } else if (kfactor) {
                   8537:                                                if (kfactor & 0x40)
                   8538:                                                        kfactor |= ~0x3f;
                   8539:                                                _stprintf(p, _T(" {%d}"), kfactor);
                   8540:                                        }
                   8541:                                } else {
                   8542:                                        if (extra & 0x4000) { // source is EA
                   8543:                                                _tcscat(instrname, _T("."));
                   8544:                                                _tcscat(instrname, fpsizes[size]);
                   8545:                                                _tcscat(instrname, _T(" "));
                   8546:                                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
                   8547:                                        } else { // source is FPx
                   8548:                                                p = instrname + _tcslen(instrname);
                   8549:                                                _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
                   8550:                                        }
                   8551:                                        p = instrname + _tcslen(instrname);
                   8552:                                        if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
                   8553:                                                _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
                   8554:                                        if (ins >= 0x30 && ins < 0x38) { // FSINCOS
                   8555:                                                p = instrname + _tcslen(instrname);
                   8556:                                                _stprintf(p, _T(",FP%d"), extra & 7);
                   8557:                                        }
                   8558:                                }
                   8559:                        }
                   8560:                } else if ((opcode & 0xf000) == 0xa000) {
                   8561:                        _tcscpy(instrname, _T("A-LINE"));
1.1.1.4   root     8562:                } else {
                   8563:                        if (dp->suse) {
1.1.1.7   root     8564:                                pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
1.1.1.4   root     8565:                        }
                   8566:                        if (dp->suse && dp->duse)
1.1.1.7   root     8567:                                _tcscat (instrname, _T(","));
1.1.1.4   root     8568:                        if (dp->duse) {
1.1.1.7   root     8569:                                pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
1.1.1.4   root     8570:                        }
                   8571:                }
                   8572: 
1.1.1.7   root     8573:                for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) {
                   8574:                        buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
1.1.1.4   root     8575:                }
                   8576:                while (i++ < 5)
1.1.1.7   root     8577:                        buf = buf_out (buf, &bufsize, _T("     "));
1.1.1.4   root     8578: 
1.1.1.7   root     8579:                if (illegal)
                   8580:                        buf = buf_out (buf, &bufsize, _T("[ "));
                   8581:                buf = buf_out (buf, &bufsize, instrname);
                   8582:                if (illegal)
                   8583:                        buf = buf_out (buf, &bufsize, _T(" ]"));
1.1.1.4   root     8584: 
                   8585:                if (ccpt != 0) {
1.1.1.7   root     8586:                        uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
1.1.1.4   root     8587:                        if (deaddr)
1.1.1.7   root     8588:                                *deaddr = pc;
                   8589:                        if ((opcode & 0xf000) == 0xf000) {
                   8590:                                if (fpp_cond(dp->cc)) {
                   8591:                                        buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
                   8592:                                } else {
                   8593:                                        buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
                   8594:                                }
                   8595:                        } else {
                   8596:                                if (cctrue (dp->cc)) {
                   8597:                                        buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
                   8598:                                } else {
                   8599:                                        buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
                   8600:                                }
                   8601:                        }
1.1.1.4   root     8602:                } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
                   8603:                        if (deaddr)
1.1.1.7   root     8604:                                *deaddr = pc;
                   8605:                        buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
1.1.1.4   root     8606:                }
1.1.1.7   root     8607:                buf = buf_out (buf, &bufsize, _T("\n"));
                   8608: 
                   8609:                if (illegal)
                   8610:                        pc =  m68kpc_illg;
1.1.1.4   root     8611:        }
                   8612:        if (nextpc)
1.1.1.7   root     8613:                *nextpc = pc;
                   8614:        if (seaddr)
                   8615:                *seaddr = seaddr2;
                   8616:        if (deaddr)
                   8617:                *deaddr = deaddr2;
1.1.1.4   root     8618: }
                   8619: 
1.1.1.7   root     8620: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
                   8621: {
                   8622:        TCHAR *buf;
                   8623: 
                   8624:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
                   8625:        if (!buf)
                   8626:                return;
                   8627:        m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
                   8628:        xfree (buf);
                   8629: }
                   8630: void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.4   root     8631: {
1.1.1.7   root     8632:        TCHAR *buf;
                   8633: 
                   8634:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
                   8635:        if (!buf)
                   8636:                return;
                   8637:        m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
                   8638:        console_out_f (_T("%s"), buf);
                   8639:        xfree (buf);
1.1.1.4   root     8640: }
1.1.1.7   root     8641: void m68k_disasm_file (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.4   root     8642: {
1.1.1.7   root     8643:        TCHAR *buf;
                   8644: 
                   8645:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
                   8646:        if (!buf)
                   8647:                return;
                   8648:        console_out_FILE = f;
                   8649:        m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
                   8650:        f_out (f, _T("%s"), buf);
                   8651:        xfree (buf);
                   8652:        console_out_FILE = NULL;
1.1.1.4   root     8653: }
                   8654: 
                   8655: /*************************************************************
                   8656: Disasm the m68kcode at the given address into instrname
                   8657: and instrcode
                   8658: *************************************************************/
                   8659: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
                   8660: {
                   8661:        TCHAR *ccpt;
                   8662:        uae_u32 opcode;
                   8663:        struct mnemolookup *lookup;
                   8664:        struct instr *dp;
1.1.1.7   root     8665:        uaecptr pc, oldpc;
1.1.1.4   root     8666: 
1.1.1.7   root     8667:        pc = oldpc = addr;
                   8668:        opcode = get_word_debug (pc);
1.1.1.4   root     8669:        if (cpufunctbl[opcode] == op_illg_1) {
                   8670:                opcode = 0x4AFC;
                   8671:        }
                   8672:        dp = table68k + opcode;
                   8673:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
                   8674: 
1.1.1.7   root     8675:        pc += 2;
1.1.1.4   root     8676: 
                   8677:        _tcscpy (instrname, lookup->name);
1.1.1.7   root     8678:        ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4   root     8679:        if (ccpt != 0) {
                   8680:                _tcsncpy (ccpt, ccnames[dp->cc], 2);
                   8681:        }
                   8682:        switch (dp->size){
1.1.1.7   root     8683:        case sz_byte: _tcscat (instrname, _T(".B ")); break;
                   8684:        case sz_word: _tcscat (instrname, _T(".W ")); break;
                   8685:        case sz_long: _tcscat (instrname, _T(".L ")); break;
                   8686:        default: _tcscat (instrname, _T("   ")); break;
1.1.1.4   root     8687:        }
                   8688: 
                   8689:        if (dp->suse) {
1.1.1.7   root     8690:                pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
1.1.1.4   root     8691:        }
                   8692:        if (dp->suse && dp->duse)
1.1.1.7   root     8693:                _tcscat (instrname, _T(","));
1.1.1.4   root     8694:        if (dp->duse) {
1.1.1.7   root     8695:                pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
1.1.1.4   root     8696:        }
                   8697:        if (instrcode)
                   8698:        {
                   8699:                int i;
1.1.1.7   root     8700:                for (i = 0; i < (int)(pc - oldpc) / 2; i++)
1.1.1.4   root     8701:                {
1.1.1.7   root     8702:                        _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
1.1.1.4   root     8703:                        instrcode += _tcslen (instrcode);
                   8704:                }
                   8705:        }
                   8706:        if (nextpc)
1.1.1.7   root     8707:                *nextpc = pc;
1.1.1.4   root     8708: }
                   8709: 
                   8710: struct cpum2c m2cregs[] = {
1.1.1.7   root     8711:        { 0, _T("SFC") },
                   8712:        { 1, _T("DFC") },
                   8713:        { 2, _T("CACR") },
                   8714:        { 3, _T("TC") },
                   8715:        { 4, _T("ITT0") },
                   8716:        { 5, _T("ITT1") },
                   8717:        { 6, _T("DTT0") },
                   8718:        { 7, _T("DTT1") },
                   8719:        { 8, _T("BUSC") },
                   8720:        { 0x800, _T("USP") },
                   8721:        { 0x801, _T("VBR") },
                   8722:        { 0x802, _T("CAAR") },
                   8723:        { 0x803, _T("MSP") },
                   8724:        { 0x804, _T("ISP") },
                   8725:        { 0x805, _T("MMUS") },
                   8726:        { 0x806, _T("URP") },
                   8727:        { 0x807, _T("SRP") },
                   8728:        { 0x808, _T("PCR") },
                   8729:     { -1, NULL }
1.1.1.4   root     8730: };
                   8731: 
1.1.1.7   root     8732: void m68k_dumpstate_2 (uaecptr pc, uaecptr *nextpc)
1.1.1.4   root     8733: {
                   8734:        int i, j;
                   8735: 
                   8736:        for (i = 0; i < 8; i++){
1.1.1.7   root     8737:                console_out_f (_T("  D%d %08X "), i, m68k_dreg (regs, i));
                   8738:                if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4   root     8739:        }
                   8740:        for (i = 0; i < 8; i++){
1.1.1.7   root     8741:                console_out_f (_T("  A%d %08X "), i, m68k_areg (regs, i));
                   8742:                if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4   root     8743:        }
                   8744:        if (regs.s == 0)
                   8745:                regs.usp = m68k_areg (regs, 7);
                   8746:        if (regs.s && regs.m)
                   8747:                regs.msp = m68k_areg (regs, 7);
                   8748:        if (regs.s && regs.m == 0)
                   8749:                regs.isp = m68k_areg (regs, 7);
                   8750:        j = 2;
1.1.1.7   root     8751:        console_out_f (_T("USP  %08X ISP  %08X "), regs.usp, regs.isp);
1.1.1.4   root     8752:        for (i = 0; m2cregs[i].regno>= 0; i++) {
                   8753:                if (!movec_illg (m2cregs[i].regno)) {
1.1.1.7   root     8754:                        if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
1.1.1.4   root     8755:                                continue;
                   8756:                        if (j > 0 && (j % 4) == 0)
1.1.1.7   root     8757:                                console_out_f (_T("\n"));
                   8758:                        console_out_f (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
1.1.1.4   root     8759:                        j++;
                   8760:                }
                   8761:        }
                   8762:        if (j > 0)
1.1.1.7   root     8763:                console_out_f (_T("\n"));
                   8764:                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     8765:                regs.t1, regs.t0, regs.s, regs.m,
                   8766:                GET_XFLG (), GET_NFLG (), GET_ZFLG (),
                   8767:                GET_VFLG (), GET_CFLG (),
                   8768:                regs.intmask, regs.stopped);
                   8769: #ifdef FPUEMU
                   8770:        if (currprefs.fpu_model) {
                   8771:                uae_u32 fpsr;
1.1.1.9 ! root     8772:                for (i = 0; i < 8; i++) {
        !          8773:                        if (!(i & 1))
        !          8774:                                console_out_f(_T("%d: "), i);
        !          8775:                        console_out_f (_T("%s "), fpp_print(&regs.fp[i], -1));
        !          8776:                        console_out_f (_T("%s "), fpp_print(&regs.fp[i], 0));
        !          8777:                        if (i & 1)
1.1.1.7   root     8778:                                console_out_f (_T("\n"));
1.1.1.4   root     8779:                }
1.1.1.7   root     8780:                fpsr = fpp_get_fpsr ();
1.1.1.9 ! root     8781:                console_out_f (_T("FPSR: %08X FPCR: %08x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
1.1.1.7   root     8782:                        fpsr, regs.fpcr, regs.fpiar,
1.1.1.4   root     8783:                        (fpsr & 0x8000000) != 0,
                   8784:                        (fpsr & 0x4000000) != 0,
                   8785:                        (fpsr & 0x2000000) != 0,
                   8786:                        (fpsr & 0x1000000) != 0);
                   8787:        }
                   8788: #endif
1.1.1.7   root     8789:        if (currprefs.mmu_model == 68030) {
                   8790: #ifndef WINUAE_FOR_HATARI
                   8791:                console_out_f (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
1.1.1.8   root     8792: #else          /* Use PRIX64 since MinGW on Windows does not know about %llx (?) */
                   8793:                console_out_f (_T("SRP: %"PRIX64" CRP: %"PRIX64"\n"), (uint64_t)srp_030, (uint64_t)crp_030);
1.1.1.7   root     8794: #endif
                   8795:                console_out_f (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
                   8796:        }
1.1.1.9 ! root     8797:        if (currprefs.cpu_compatible) {
        !          8798:                if (currprefs.cpu_model == 68000) {
        !          8799:                        struct instr *dp;
        !          8800:                        struct mnemolookup *lookup1, *lookup2;
        !          8801:                        dp = table68k + regs.irc;
        !          8802:                        for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++)
        !          8803:                                ;
        !          8804:                        dp = table68k + regs.ir;
        !          8805:                        for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++)
        !          8806:                                ;
        !          8807:                        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);
        !          8808:                } else if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
        !          8809:                        console_out_f (_T("Prefetch %08x %08x (%d) %04x (%d) %04x (%d) %04x (%d)\n"),
        !          8810:                                regs.cacheholdingaddr020, regs.cacheholdingdata020, regs.cacheholdingdata_valid,
        !          8811:                                regs.prefetch020[0], regs.prefetch020_valid[0],
        !          8812:                                regs.prefetch020[1], regs.prefetch020_valid[1],
        !          8813:                                regs.prefetch020[2], regs.prefetch020_valid[2]);
        !          8814:                }
1.1.1.4   root     8815:        }
                   8816: 
1.1.1.7   root     8817:        if (pc != 0xffffffff) {
                   8818:                m68k_disasm (pc, nextpc, 1);
                   8819:                if (nextpc)
                   8820:                        console_out_f (_T("Next PC: %08x\n"), *nextpc);
                   8821:        }
                   8822: }
                   8823: void m68k_dumpstate (uaecptr *nextpc)
                   8824: {
                   8825:        m68k_dumpstate_2 (m68k_getpc (), nextpc);
                   8826: }
                   8827: #ifdef WINUAE_FOR_HATARI
                   8828: void m68k_dumpstate_file (FILE *f, uaecptr *nextpc)
                   8829: {
                   8830:        console_out_FILE = f;
                   8831:        m68k_dumpstate_2 (m68k_getpc (), nextpc);
                   8832:        console_out_FILE = NULL;
                   8833: }
                   8834: #endif
1.1.1.9 ! root     8835: void m68k_dumpcache (bool dc)
1.1.1.7   root     8836: {
                   8837:        int i , j;
                   8838: 
                   8839:        if (!currprefs.cpu_compatible)
                   8840:                return;
                   8841:        if (currprefs.cpu_model == 68020) {
                   8842:                for (i = 0; i < CACHELINES020; i += 4) {
                   8843:                        for (j = 0; j < 4; j++) {
                   8844:                                int s = i + j;
                   8845:                                uaecptr addr;
1.1.1.9 ! root     8846:                                int fc;
1.1.1.7   root     8847:                                struct cache020 *c = &caches020[s];
1.1.1.9 ! root     8848:                                fc = c->tag & 1;
1.1.1.7   root     8849:                                addr = c->tag & ~1;
                   8850:                                addr |= s << 2;
1.1.1.9 ! root     8851:                                console_out_f (_T("%08X%c:%08X%c"), addr, fc ? 'S' : 'U', c->data, c->valid ? '*' : ' ');
1.1.1.7   root     8852:                        }
                   8853:                        console_out_f (_T("\n"));
                   8854:                }
                   8855:        } else if (currprefs.cpu_model == 68030) {
                   8856:                for (i = 0; i < CACHELINES030; i++) {
1.1.1.9 ! root     8857:                        struct cache030 *c = dc ? &dcaches030[i] : &icaches030[i];
        !          8858:                        int fc;
1.1.1.7   root     8859:                        uaecptr addr;
1.1.1.9 ! root     8860:                        if (!dc) {
        !          8861:                                fc = (c->tag & 1) ? 6 : 2;
        !          8862:                        } else {
        !          8863:                                fc = c->fc;
        !          8864:                        }
1.1.1.7   root     8865:                        addr = c->tag & ~1;
                   8866:                        addr |= i << 4;
1.1.1.9 ! root     8867:                        console_out_f (_T("%08X %d: "), addr, fc);
1.1.1.7   root     8868:                        for (j = 0; j < 4; j++) {
                   8869:                                console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
                   8870:                        }
                   8871:                        console_out_f (_T("\n"));
                   8872:                }
1.1.1.9 ! root     8873:        } else if (currprefs.cpu_model >= 68040) {
        !          8874:                uae_u32 tagmask = dc ? cachedtag04060mask : cacheitag04060mask;
        !          8875:                for (i = 0; i < cachedsets04060; i++) {
        !          8876:                        struct cache040 *c = dc ? &dcaches040[i] : &icaches040[i];
        !          8877:                        for (j = 0; j < CACHELINES040; j++) {
        !          8878:                                if (c->valid[j]) {
        !          8879:                                        uae_u32 addr = (c->tag[j] & tagmask) | (i << 4);
        !          8880:                                        write_log(_T("%02d:%d %08x = %08x%c %08x%c %08x%c %08x%c\n"),
        !          8881:                                                i, j, addr,
        !          8882:                                                c->data[j][0], c->dirty[j][0] ? '*' : ' ',
        !          8883:                                                c->data[j][1], c->dirty[j][1] ? '*' : ' ',
        !          8884:                                                c->data[j][2], c->dirty[j][2] ? '*' : ' ',
        !          8885:                                                c->data[j][3], c->dirty[j][3] ? '*' : ' ');
        !          8886:                                }
        !          8887:                        }
        !          8888:                }
1.1.1.7   root     8889:        }
1.1.1.4   root     8890: }
                   8891: 
                   8892: #ifdef SAVESTATE
                   8893: 
                   8894: /* CPU save/restore code */
                   8895: 
                   8896: #define CPUTYPE_EC 1
                   8897: #define CPUMODE_HALT 1
                   8898: 
                   8899: uae_u8 *restore_cpu (uae_u8 *src)
                   8900: {
1.1.1.7   root     8901:        int i, j , flags, model;
1.1.1.4   root     8902:        uae_u32 l;
                   8903: 
1.1.1.7   root     8904:        currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 ();
1.1.1.4   root     8905:        flags = restore_u32 ();
                   8906:        changed_prefs.address_space_24 = 0;
                   8907:        if (flags & CPUTYPE_EC)
                   8908:                changed_prefs.address_space_24 = 1;
                   8909:        currprefs.address_space_24 = changed_prefs.address_space_24;
                   8910:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                   8911:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1.1.1.8   root     8912:        currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact;
1.1.1.4   root     8913:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
                   8914:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
                   8915:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
                   8916:        for (i = 0; i < 15; i++)
                   8917:                regs.regs[i] = restore_u32 ();
                   8918:        regs.pc = restore_u32 ();
                   8919:        regs.irc = restore_u16 ();
                   8920:        regs.ir = restore_u16 ();
                   8921:        regs.usp = restore_u32 ();
                   8922:        regs.isp = restore_u32 ();
                   8923:        regs.sr = restore_u16 ();
1.1.1.7   root     8924: printf ( "restore %x %x %x\n" , regs.usp , regs.isp , regs.sr );
1.1.1.4   root     8925:        l = restore_u32 ();
                   8926:        if (l & CPUMODE_HALT) {
                   8927:                regs.stopped = 1;
                   8928:        } else {
                   8929:                regs.stopped = 0;
                   8930:        }
                   8931:        if (model >= 68010) {
                   8932:                regs.dfc = restore_u32 ();
                   8933:                regs.sfc = restore_u32 ();
                   8934:                regs.vbr = restore_u32 ();
                   8935:        }
                   8936:        if (model >= 68020) {
                   8937:                regs.caar = restore_u32 ();
                   8938:                regs.cacr = restore_u32 ();
                   8939:                regs.msp = restore_u32 ();
                   8940:        }
                   8941:        if (model >= 68030) {
1.1.1.7   root     8942:                crp_030 = fake_crp_030 = restore_u64 ();
                   8943:                srp_030 = fake_srp_030 = restore_u64 ();
                   8944:                tt0_030 = fake_tt0_030 = restore_u32 ();
                   8945:                tt1_030 = fake_tt1_030 = restore_u32 ();
                   8946:                tc_030 = fake_tc_030 = restore_u32 ();
                   8947:                mmusr_030 = fake_mmusr_030 = restore_u16 ();
1.1.1.4   root     8948:        }
                   8949:        if (model >= 68040) {
                   8950:                regs.itt0 = restore_u32 ();
                   8951:                regs.itt1 = restore_u32 ();
                   8952:                regs.dtt0 = restore_u32 ();
                   8953:                regs.dtt1 = restore_u32 ();
                   8954:                regs.tcr = restore_u32 ();
                   8955:                regs.urp = restore_u32 ();
                   8956:                regs.srp = restore_u32 ();
                   8957:        }
                   8958:        if (model >= 68060) {
                   8959:                regs.buscr = restore_u32 ();
                   8960:                regs.pcr = restore_u32 ();
                   8961:        }
                   8962:        if (flags & 0x80000000) {
                   8963:                int khz = restore_u32 ();
                   8964:                restore_u32 ();
                   8965:                if (khz > 0 && khz < 800000)
                   8966:                        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
                   8967:        }
1.1.1.7   root     8968:        set_cpu_caches (true);
                   8969:        if (flags & 0x40000000) {
                   8970:                if (model == 68020) {
                   8971:                        for (i = 0; i < CACHELINES020; i++) {
                   8972:                                caches020[i].data = restore_u32 ();
                   8973:                                caches020[i].tag = restore_u32 ();
                   8974:                                caches020[i].valid = restore_u8 () != 0;
                   8975:                        }
                   8976:                        regs.prefetch020addr = restore_u32 ();
                   8977:                        regs.cacheholdingaddr020 = restore_u32 ();
                   8978:                        regs.cacheholdingdata020 = restore_u32 ();
                   8979:                        if (flags & 0x20000000) {
1.1.1.9 ! root     8980:                                if (flags & 0x4000000) {
        !          8981:                                        // 3.6 new (back to 16 bits)
        !          8982:                                        for (i = 0; i < CPU_PIPELINE_MAX; i++) {
        !          8983:                                                uae_u32 v = restore_u32();
        !          8984:                                                regs.prefetch020[i] = v >> 16;
        !          8985:                                                regs.prefetch020_valid[i] = (v & 1) != 0;
        !          8986:                                        }
        !          8987:                                } else {
        !          8988:                                        // old
        !          8989:                                        uae_u32 v = restore_u32();
        !          8990:                                        regs.prefetch020[0] = v >> 16;
        !          8991:                                        regs.prefetch020[1] = (uae_u16)v;
        !          8992:                                        v = restore_u32();
        !          8993:                                        regs.prefetch020[2] = v >> 16;
        !          8994:                                        regs.prefetch020[3] = (uae_u16)v;
        !          8995:                                        restore_u32();
        !          8996:                                        restore_u32();
        !          8997:                                        regs.prefetch020_valid[0] = true;
        !          8998:                                        regs.prefetch020_valid[1] = true;
        !          8999:                                        regs.prefetch020_valid[2] = true;
        !          9000:                                        regs.prefetch020_valid[3] = true;
        !          9001:                                }
1.1.1.7   root     9002:                        }
                   9003:                } else if (model == 68030) {
                   9004:                        for (i = 0; i < CACHELINES030; i++) {
                   9005:                                for (j = 0; j < 4; j++) {
                   9006:                                        icaches030[i].data[j] = restore_u32 ();
                   9007:                                        icaches030[i].valid[j] = restore_u8 () != 0;
                   9008:                                }
                   9009:                                icaches030[i].tag = restore_u32 ();
                   9010:                        }
                   9011:                        for (i = 0; i < CACHELINES030; i++) {
                   9012:                                for (j = 0; j < 4; j++) {
                   9013:                                        dcaches030[i].data[j] = restore_u32 ();
                   9014:                                        dcaches030[i].valid[j] = restore_u8 () != 0;
                   9015:                                }
                   9016:                                dcaches030[i].tag = restore_u32 ();
                   9017:                        }
                   9018:                        regs.prefetch020addr = restore_u32 ();
                   9019:                        regs.cacheholdingaddr020 = restore_u32 ();
                   9020:                        regs.cacheholdingdata020 = restore_u32 ();
1.1.1.9 ! root     9021:                        if (flags & 0x4000000) {
        !          9022:                                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
        !          9023:                                        uae_u32 v = restore_u32();
        !          9024:                                        regs.prefetch020[i] = v >> 16;
        !          9025:                                        regs.prefetch020_valid[i] = (v & 1) != 0;
        !          9026:                                }
        !          9027:                        } else {
        !          9028:                                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
        !          9029:                                        regs.prefetch020[i] = restore_u32 ();
        !          9030:                                        regs.prefetch020_valid[i] = false;
        !          9031:                                }
        !          9032:                        }
        !          9033:                } else if (model == 68040) {
1.1.1.7   root     9034:                        if (flags & 0x8000000) {
1.1.1.9 ! root     9035:                                for (i = 0; i < ((model == 68060 && (flags & 0x4000000)) ? CACHESETS060 : CACHESETS040); i++) {
1.1.1.7   root     9036:                                        for (j = 0; j < CACHELINES040; j++) {
1.1.1.9 ! root     9037:                                                struct cache040 *c = &icaches040[i];
        !          9038:                                                c->data[j][0] = restore_u32();
        !          9039:                                                c->data[j][1] = restore_u32();
        !          9040:                                                c->data[j][2] = restore_u32();
        !          9041:                                                c->data[j][3] = restore_u32();
        !          9042:                                                c->tag[j] = restore_u32();
        !          9043:                                                c->valid[j] = restore_u16() & 1;
1.1.1.7   root     9044:                                        }
                   9045:                                }
                   9046:                                regs.prefetch020addr = restore_u32();
                   9047:                                regs.cacheholdingaddr020 = restore_u32();
                   9048:                                regs.cacheholdingdata020 = restore_u32();
                   9049:                                for (i = 0; i < CPU_PIPELINE_MAX; i++)
1.1.1.9 ! root     9050:                                        regs.prefetch040[i] = restore_u32();
        !          9051:                                if (flags & 0x4000000) {
        !          9052:                                        for (i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
        !          9053:                                                for (j = 0; j < CACHELINES040; j++) {
        !          9054:                                                        struct cache040 *c = &dcaches040[i];
        !          9055:                                                        c->data[j][0] = restore_u32();
        !          9056:                                                        c->data[j][1] = restore_u32();
        !          9057:                                                        c->data[j][2] = restore_u32();
        !          9058:                                                        c->data[j][3] = restore_u32();
        !          9059:                                                        c->tag[j] = restore_u32();
        !          9060:                                                        uae_u16 v = restore_u16();
        !          9061:                                                        c->valid[j] = (v & 1) != 0;
        !          9062:                                                        c->dirty[j][0] = (v & 0x10) != 0;
        !          9063:                                                        c->dirty[j][1] = (v & 0x20) != 0;
        !          9064:                                                        c->dirty[j][2] = (v & 0x40) != 0;
        !          9065:                                                        c->dirty[j][3] = (v & 0x80) != 0;
        !          9066:                                                        c->gdirty[j] = c->dirty[j][0] || c->dirty[j][1] || c->dirty[j][2] || c->dirty[j][3];
        !          9067:                                                }
        !          9068:                                        }
        !          9069:                                }
1.1.1.7   root     9070:                        }
                   9071:                }
                   9072:                if (model >= 68020) {
1.1.1.9 ! root     9073:                        restore_u32 (); // regs.ce020memcycles
        !          9074:                        regs.ce020startcycle = regs.ce020endcycle = 0;
1.1.1.7   root     9075:                        restore_u32 ();
                   9076:                }
                   9077:        }
                   9078:        if (flags & 0x10000000) {
                   9079:                regs.chipset_latch_rw = restore_u32 ();
                   9080:                regs.chipset_latch_read = restore_u32 ();
                   9081:                regs.chipset_latch_write = restore_u32 ();
                   9082:        }
                   9083: 
1.1.1.9 ! root     9084:        regs.pipeline_pos = -1;
        !          9085:        regs.pipeline_stop = 0;
        !          9086:        if (flags & 0x4000000 && currprefs.cpu_model == 68020) {
        !          9087:                regs.pipeline_pos = restore_u16();
        !          9088:                regs.pipeline_r8[0] = restore_u16();
        !          9089:                regs.pipeline_r8[1] = restore_u16();
        !          9090:                regs.pipeline_stop = restore_u16();
        !          9091:        }
        !          9092: 
1.1.1.7   root     9093:        m68k_reset_sr();
                   9094: 
                   9095:        write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
                   9096:                model / 1000, flags & 1 ? _T("EC") : _T(""), model % 1000, regs.pc);
1.1.1.4   root     9097: 
                   9098:        return src;
                   9099: }
                   9100: 
1.1.1.7   root     9101: static void fill_prefetch_quick (void)
                   9102: {
                   9103:        if (currprefs.cpu_model >= 68020) {
                   9104:                fill_prefetch ();
                   9105:                return;
                   9106:        }
                   9107:        // old statefile compatibility, this needs to done,
                   9108:        // even in 68000 cycle-exact mode
                   9109:        regs.ir = get_word (m68k_getpc ());
                   9110:        regs.irc = get_word (m68k_getpc () + 2);
                   9111: }
                   9112: 
1.1.1.4   root     9113: void restore_cpu_finish (void)
                   9114: {
                   9115:        init_m68k ();
1.1.1.7   root     9116:        m68k_setpc_normal (regs.pc);
1.1.1.4   root     9117:        doint ();
1.1.1.7   root     9118:        fill_prefetch_quick ();
                   9119: printf ( "SR %x %x %x %x\n" , regs.sr , regs.isp , regs.usp , regs.regs[15] );
                   9120: #ifndef WINUAE_FOR_HATARI
                   9121:        set_cycles (start_cycles);
                   9122:        events_schedule ();
                   9123: #endif
1.1.1.4   root     9124:        if (regs.stopped)
                   9125:                set_special (SPCFLAG_STOP);
                   9126:        //activate_debugger ();
                   9127: }
                   9128: 
1.1.1.7   root     9129: uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
1.1.1.4   root     9130: {
1.1.1.7   root     9131:        uae_u8 *dstbak, *dst;
                   9132:        int i;
1.1.1.4   root     9133: 
1.1.1.7   root     9134:        if (cputrace.state <= 0)
                   9135:                return NULL;
1.1.1.4   root     9136: 
1.1.1.7   root     9137:        if (dstptr)
                   9138:                dstbak = dst = dstptr;
                   9139:        else
1.1.1.8   root     9140:                dstbak = dst = xmalloc (uae_u8, 10000);
1.1.1.7   root     9141: 
1.1.1.9 ! root     9142:        save_u32 (2 | 4 | 16 | 32);
1.1.1.7   root     9143:        save_u16 (cputrace.opcode);
                   9144:        for (i = 0; i < 16; i++)
                   9145:                save_u32 (cputrace.regs[i]);
                   9146:        save_u32 (cputrace.pc);
                   9147:        save_u16 (cputrace.irc);
                   9148:        save_u16 (cputrace.ir);
                   9149:        save_u32 (cputrace.usp);
                   9150:        save_u32 (cputrace.isp);
                   9151:        save_u16 (cputrace.sr);
                   9152:        save_u16 (cputrace.intmask);
                   9153:        save_u16 ((cputrace.stopped ? 1 : 0) | (regs.stopped ? 2 : 0));
                   9154:        save_u16 (cputrace.state);
                   9155:        save_u32 (cputrace.cyclecounter);
                   9156:        save_u32 (cputrace.cyclecounter_pre);
                   9157:        save_u32 (cputrace.cyclecounter_post);
                   9158:        save_u32 (cputrace.readcounter);
                   9159:        save_u32 (cputrace.writecounter);
                   9160:        save_u32 (cputrace.memoryoffset);
                   9161:        write_log (_T("CPUT SAVE: PC=%08x C=%08X %08x %08x %08x %d %d %d\n"),
                   9162:                cputrace.pc, cputrace.startcycles,
                   9163:                cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
                   9164:                cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset);
                   9165:        for (i = 0; i < cputrace.memoryoffset; i++) {
                   9166:                save_u32 (cputrace.ctm[i].addr);
                   9167:                save_u32 (cputrace.ctm[i].data);
                   9168:                save_u32 (cputrace.ctm[i].mode);
                   9169:                write_log (_T("CPUT%d: %08x %08x %08x\n"), i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode);
                   9170:        }
                   9171:        save_u32 (cputrace.startcycles);
                   9172: 
                   9173:        if (currprefs.cpu_model == 68020) {
                   9174:                for (i = 0; i < CACHELINES020; i++) {
                   9175:                        save_u32 (cputrace.caches020[i].data);
                   9176:                        save_u32 (cputrace.caches020[i].tag);
                   9177:                        save_u8 (cputrace.caches020[i].valid ? 1 : 0);
                   9178:                }
                   9179:                save_u32 (cputrace.prefetch020addr);
                   9180:                save_u32 (cputrace.cacheholdingaddr020);
                   9181:                save_u32 (cputrace.cacheholdingdata020);
1.1.1.9 ! root     9182:                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.7   root     9183:                        save_u16 (cputrace.prefetch020[i]);
1.1.1.9 ! root     9184:                }
        !          9185:                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.7   root     9186:                        save_u32 (cputrace.prefetch020[i]);
1.1.1.9 ! root     9187:                }
        !          9188:                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
        !          9189:                        save_u8 (cputrace.prefetch020_valid[i]);
        !          9190:                }
        !          9191:                save_u16(cputrace.pipeline_pos);
        !          9192:                save_u16(cputrace.pipeline_r8[0]);
        !          9193:                save_u16(cputrace.pipeline_r8[1]);
        !          9194:                save_u16(cputrace.pipeline_stop);
1.1.1.7   root     9195:        }
                   9196: 
                   9197:        *len = dst - dstbak;
                   9198:        cputrace.needendcycles = 1;
                   9199:        return dstbak;
                   9200: }
                   9201: 
                   9202: uae_u8 *restore_cpu_trace (uae_u8 *src)
                   9203: {
                   9204:        int i;
                   9205: 
                   9206:        cpu_tracer = 0;
                   9207:        cputrace.state = 0;
                   9208:        uae_u32 v = restore_u32 ();
                   9209:        if (!(v & 2))
                   9210:                return src;
                   9211:        cputrace.opcode = restore_u16 ();
                   9212:        for (i = 0; i < 16; i++)
                   9213:                cputrace.regs[i] = restore_u32 ();
                   9214:        cputrace.pc = restore_u32 ();
                   9215:        cputrace.irc = restore_u16 ();
                   9216:        cputrace.ir = restore_u16 ();
                   9217:        cputrace.usp = restore_u32 ();
                   9218:        cputrace.isp = restore_u32 ();
                   9219:        cputrace.sr = restore_u16 ();
                   9220:        cputrace.intmask = restore_u16 ();
                   9221:        cputrace.stopped = restore_u16 ();
                   9222:        cputrace.state = restore_u16 ();
                   9223:        cputrace.cyclecounter = restore_u32 ();
                   9224:        cputrace.cyclecounter_pre = restore_u32 ();
                   9225:        cputrace.cyclecounter_post = restore_u32 ();
                   9226:        cputrace.readcounter = restore_u32 ();
                   9227:        cputrace.writecounter = restore_u32 ();
                   9228:        cputrace.memoryoffset = restore_u32 ();
                   9229:        for (i = 0; i < cputrace.memoryoffset; i++) {
                   9230:                cputrace.ctm[i].addr = restore_u32 ();
                   9231:                cputrace.ctm[i].data = restore_u32 ();
                   9232:                cputrace.ctm[i].mode = restore_u32 ();
                   9233:        }
                   9234:        cputrace.startcycles = restore_u32 ();
                   9235: 
                   9236:        if (v & 4) {
                   9237:                if (currprefs.cpu_model == 68020) {
                   9238:                        for (i = 0; i < CACHELINES020; i++) {
                   9239:                                cputrace.caches020[i].data = restore_u32 ();
                   9240:                                cputrace.caches020[i].tag = restore_u32 ();
                   9241:                                cputrace.caches020[i].valid = restore_u8 () != 0;
                   9242:                        }
                   9243:                        cputrace.prefetch020addr = restore_u32 ();
                   9244:                        cputrace.cacheholdingaddr020 = restore_u32 ();
                   9245:                        cputrace.cacheholdingdata020 = restore_u32 ();
1.1.1.9 ! root     9246:                        for (i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.7   root     9247:                                cputrace.prefetch020[i] = restore_u16 ();
1.1.1.9 ! root     9248:                        }
1.1.1.7   root     9249:                        if (v & 8) {
1.1.1.9 ! root     9250:                                // backwards compatibility
        !          9251:                                uae_u32 v = restore_u32();
        !          9252:                                cputrace.prefetch020[0] = v >> 16;
        !          9253:                                cputrace.prefetch020[1] = (uae_u16)v;
        !          9254:                                v = restore_u32();
        !          9255:                                cputrace.prefetch020[2] = v >> 16;
        !          9256:                                cputrace.prefetch020[3] = (uae_u16)v;
        !          9257:                                restore_u32();
        !          9258:                                restore_u32();
        !          9259:                                cputrace.prefetch020_valid[0] = true;
        !          9260:                                cputrace.prefetch020_valid[1] = true;
        !          9261:                                cputrace.prefetch020_valid[2] = true;
        !          9262:                                cputrace.prefetch020_valid[3] = true;
        !          9263: 
        !          9264:                                cputrace.prefetch020[0] = cputrace.prefetch020[1];
        !          9265:                                cputrace.prefetch020[1] = cputrace.prefetch020[2];
        !          9266:                                cputrace.prefetch020[2] = cputrace.prefetch020[3];
        !          9267:                                cputrace.prefetch020_valid[3] = false;
        !          9268:                        }
        !          9269:                        if (v & 16) {
        !          9270:                                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
        !          9271:                                        cputrace.prefetch020_valid[i] = restore_u8() != 0;
        !          9272:                                }
        !          9273:                        }
        !          9274:                        if (v & 32) {
        !          9275:                                cputrace.pipeline_pos = restore_u16();
        !          9276:                                cputrace.pipeline_r8[0] = restore_u16();
        !          9277:                                cputrace.pipeline_r8[1] = restore_u16();
        !          9278:                                cputrace.pipeline_stop = restore_u16();
1.1.1.7   root     9279:                        }
                   9280:                }
                   9281:        }
                   9282: 
                   9283:        cputrace.needendcycles = 1;
                   9284:        if (v && cputrace.state) {
                   9285:                if (currprefs.cpu_model > 68000) {
                   9286:                        if (v & 4)
                   9287:                                cpu_tracer = -1;
                   9288:                        // old format?
                   9289:                        if ((v & (4 | 8)) != (4 | 8))
                   9290:                                cpu_tracer = 0;
                   9291:                } else {
                   9292:                        cpu_tracer = -1;
                   9293:                }
                   9294:        }
                   9295: 
                   9296:        return src;
                   9297: }
                   9298: 
                   9299: uae_u8 *restore_cpu_extra (uae_u8 *src)
                   9300: {
                   9301:        restore_u32 ();
                   9302:        uae_u32 flags = restore_u32 ();
                   9303: 
                   9304:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
1.1.1.8   root     9305:        currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = currprefs.cpu_cycle_exact;
                   9306:        if ((flags & 32) && !(flags & 1))
                   9307:                currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = true;
1.1.1.7   root     9308:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
                   9309:        currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
                   9310:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
                   9311:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
                   9312:        //currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
                   9313: 
                   9314:        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
                   9315:        if (flags & 4)
1.1.1.4   root     9316:                currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
1.1.1.7   root     9317:        if (flags & 16)
                   9318:                currprefs.m68k_speed = changed_prefs.m68k_speed = (flags >> 24) * CYCLE_UNIT;
1.1.1.4   root     9319: 
                   9320:        currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
                   9321:        currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
                   9322: 
                   9323:        return src;
                   9324: }
                   9325: 
                   9326: uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
                   9327: {
                   9328:        uae_u8 *dstbak, *dst;
                   9329:        uae_u32 flags;
                   9330: 
                   9331:        if (dstptr)
                   9332:                dstbak = dst = dstptr;
                   9333:        else
                   9334:                dstbak = dst = xmalloc (uae_u8, 1000);
                   9335:        save_u32 (0); // version
                   9336:        flags = 0;
                   9337:        flags |= currprefs.cpu_cycle_exact ? 1 : 0;
                   9338:        flags |= currprefs.cpu_compatible ? 2 : 0;
                   9339:        flags |= currprefs.m68k_speed < 0 ? 4 : 0;
                   9340:        flags |= currprefs.cachesize > 0 ? 8 : 0;
1.1.1.7   root     9341:        flags |= currprefs.m68k_speed > 0 ? 16 : 0;
1.1.1.8   root     9342:        flags |= currprefs.cpu_memory_cycle_exact ? 32 : 0;
1.1.1.7   root     9343:        if (currprefs.m68k_speed > 0)
                   9344:                flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24;
1.1.1.4   root     9345:        save_u32 (flags);
                   9346:        save_u32 (currprefs.cpu_frequency);
                   9347:        save_u32 (currprefs.cpu_clock_multiplier);
                   9348:        save_u8 (currprefs.cpu060_revision);
                   9349:        save_u8 (currprefs.fpu_revision);
                   9350:        *len = dst - dstbak;
                   9351:        return dstbak;
                   9352: }
                   9353: 
                   9354: uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                   9355: {
                   9356:        uae_u8 *dstbak, *dst;
1.1.1.7   root     9357:        int model, i, j, khz;
1.1.1.4   root     9358: 
                   9359:        if (dstptr)
                   9360:                dstbak = dst = dstptr;
                   9361:        else
1.1.1.8   root     9362:                dstbak = dst = xmalloc (uae_u8, 1000 + 20000);
1.1.1.4   root     9363:        model = currprefs.cpu_model;
                   9364:        save_u32 (model);                                       /* MODEL */
1.1.1.9 ! root     9365:        save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 | 0x4000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
1.1.1.4   root     9366:        for (i = 0;i < 15; i++)
                   9367:                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
                   9368:        save_u32 (m68k_getpc ());                       /* PC */
                   9369:        save_u16 (regs.irc);                            /* prefetch */
                   9370:        save_u16 (regs.ir);                                     /* instruction prefetch */
                   9371:        MakeSR ();
                   9372:        save_u32 (!regs.s ? regs.regs[15] : regs.usp);  /* USP */
                   9373:        save_u32 (regs.s ? regs.regs[15] : regs.isp);   /* ISP */
                   9374:        save_u16 (regs.sr);                                                             /* SR/CCR */
                   9375:        save_u32 (regs.stopped ? CPUMODE_HALT : 0);             /* flags */
                   9376:        if (model >= 68010) {
                   9377:                save_u32 (regs.dfc);                    /* DFC */
                   9378:                save_u32 (regs.sfc);                    /* SFC */
                   9379:                save_u32 (regs.vbr);                    /* VBR */
                   9380:        }
                   9381:        if (model >= 68020) {
                   9382:                save_u32 (regs.caar);                   /* CAAR */
                   9383:                save_u32 (regs.cacr);                   /* CACR */
                   9384:                save_u32 (regs.msp);                    /* MSP */
                   9385:        }
                   9386:        if (model >= 68030) {
1.1.1.7   root     9387:                if (currprefs.mmu_model) {
                   9388:                        save_u64 (crp_030);                             /* CRP */
                   9389:                        save_u64 (srp_030);                             /* SRP */
                   9390:                        save_u32 (tt0_030);                             /* TT0/AC0 */
                   9391:                        save_u32 (tt1_030);                             /* TT1/AC1 */
                   9392:                        save_u32 (tc_030);                              /* TCR */
                   9393:                        save_u16 (mmusr_030);                   /* MMUSR/ACUSR */
                   9394:                } else {
                   9395:                        save_u64 (fake_crp_030);                /* CRP */
                   9396:                        save_u64 (fake_srp_030);                /* SRP */
                   9397:                        save_u32 (fake_tt0_030);                /* TT0/AC0 */
                   9398:                        save_u32 (fake_tt1_030);                /* TT1/AC1 */
                   9399:                        save_u32 (fake_tc_030);                 /* TCR */
                   9400:                        save_u16 (fake_mmusr_030);              /* MMUSR/ACUSR */
                   9401:                }
1.1.1.4   root     9402:        }
                   9403:        if (model >= 68040) {
                   9404:                save_u32 (regs.itt0);                   /* ITT0 */
                   9405:                save_u32 (regs.itt1);                   /* ITT1 */
                   9406:                save_u32 (regs.dtt0);                   /* DTT0 */
                   9407:                save_u32 (regs.dtt1);                   /* DTT1 */
                   9408:                save_u32 (regs.tcr);                    /* TCR */
                   9409:                save_u32 (regs.urp);                    /* URP */
                   9410:                save_u32 (regs.srp);                    /* SRP */
                   9411:        }
                   9412:        if (model >= 68060) {
                   9413:                save_u32 (regs.buscr);                  /* BUSCR */
                   9414:                save_u32 (regs.pcr);                    /* PCR */
                   9415:        }
                   9416:        khz = -1;
                   9417:        if (currprefs.m68k_speed == 0) {
                   9418:                khz = currprefs.ntscmode ? 715909 : 709379;
                   9419:                if (currprefs.cpu_model >= 68020)
                   9420:                        khz *= 2;
                   9421:        }
                   9422:        save_u32 (khz); // clock rate in KHz: -1 = fastest possible
                   9423:        save_u32 (0); // spare
1.1.1.7   root     9424:        if (model == 68020) {
                   9425:                for (i = 0; i < CACHELINES020; i++) {
                   9426:                        save_u32 (caches020[i].data);
                   9427:                        save_u32 (caches020[i].tag);
                   9428:                        save_u8 (caches020[i].valid ? 1 : 0);
                   9429:                }
                   9430:                save_u32 (regs.prefetch020addr);
                   9431:                save_u32 (regs.cacheholdingaddr020);
                   9432:                save_u32 (regs.cacheholdingdata020);
                   9433:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
1.1.1.9 ! root     9434:                        save_u32 ((regs.prefetch020[i] << 16) | (regs.prefetch020_valid[i] ? 1 : 0));
1.1.1.7   root     9435:        } else if (model == 68030) {
                   9436:                for (i = 0; i < CACHELINES030; i++) {
                   9437:                        for (j = 0; j < 4; j++) {
                   9438:                                save_u32 (icaches030[i].data[j]);
                   9439:                                save_u8 (icaches030[i].valid[j] ? 1 : 0);
                   9440:                        }
                   9441:                        save_u32 (icaches030[i].tag);
                   9442:                }
                   9443:                for (i = 0; i < CACHELINES030; i++) {
                   9444:                        for (j = 0; j < 4; j++) {
                   9445:                                save_u32 (dcaches030[i].data[j]);
                   9446:                                save_u8 (dcaches030[i].valid[j] ? 1 : 0);
                   9447:                        }
                   9448:                        save_u32 (dcaches030[i].tag);
                   9449:                }
                   9450:                save_u32 (regs.prefetch020addr);
                   9451:                save_u32 (regs.cacheholdingaddr020);
                   9452:                save_u32 (regs.cacheholdingdata020);
                   9453:                for (i = 0; i < CPU_PIPELINE_MAX; i++)
                   9454:                        save_u32 (regs.prefetch020[i]);
                   9455:        } else if (model >= 68040) {
1.1.1.9 ! root     9456:                for (i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
1.1.1.7   root     9457:                        for (j = 0; j < CACHELINES040; j++) {
1.1.1.9 ! root     9458:                                struct cache040 *c = &icaches040[i];
        !          9459:                                save_u32(c->data[j][0]);
        !          9460:                                save_u32(c->data[j][1]);
        !          9461:                                save_u32(c->data[j][2]);
        !          9462:                                save_u32(c->data[j][3]);
        !          9463:                                save_u32(c->tag[j]);
        !          9464:                                save_u16(c->valid[j] ? 1 : 0);
1.1.1.7   root     9465:                        }
                   9466:                }
                   9467:                save_u32(regs.prefetch020addr);
                   9468:                save_u32(regs.cacheholdingaddr020);
                   9469:                save_u32(regs.cacheholdingdata020);
1.1.1.9 ! root     9470:                for (i = 0; i < CPU_PIPELINE_MAX; i++) {
        !          9471:                        save_u32(regs.prefetch040[i]);
        !          9472:                }
        !          9473:                for (i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
        !          9474:                        for (j = 0; j < CACHELINES040; j++) {
        !          9475:                                struct cache040 *c = &dcaches040[i];
        !          9476:                                save_u32(c->data[j][0]);
        !          9477:                                save_u32(c->data[j][1]);
        !          9478:                                save_u32(c->data[j][2]);
        !          9479:                                save_u32(c->data[j][3]);
        !          9480:                                save_u32(c->tag[j]);
        !          9481:                                uae_u16 v = c->valid[j] ? 1 : 0;
        !          9482:                                v |= c->dirty[j][0] ? 0x10 : 0;
        !          9483:                                v |= c->dirty[j][1] ? 0x20 : 0;
        !          9484:                                v |= c->dirty[j][2] ? 0x40 : 0;
        !          9485:                                v |= c->dirty[j][3] ? 0x80 : 0;
        !          9486:                                save_u16(v);
        !          9487:                        }
        !          9488:                }
1.1.1.7   root     9489:        }
                   9490:        if (currprefs.cpu_model >= 68020) {
1.1.1.9 ! root     9491:                save_u32 (0); //save_u32 (regs.ce020memcycles);
1.1.1.7   root     9492:                save_u32 (0);
                   9493:        }
                   9494:        save_u32 (regs.chipset_latch_rw);
                   9495:        save_u32 (regs.chipset_latch_read);
                   9496:        save_u32 (regs.chipset_latch_write);
1.1.1.9 ! root     9497:        if (currprefs.cpu_model == 68020) {
        !          9498:                save_u16(regs.pipeline_pos);
        !          9499:                save_u16(regs.pipeline_r8[0]);
        !          9500:                save_u16(regs.pipeline_r8[1]);
        !          9501:                save_u16(regs.pipeline_stop);
        !          9502:        }
1.1.1.4   root     9503:        *len = dst - dstbak;
                   9504:        return dstbak;
                   9505: }
                   9506: 
                   9507: uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
                   9508: {
                   9509:        uae_u8 *dstbak, *dst;
                   9510:        int model;
                   9511: 
                   9512:        model = currprefs.mmu_model;
1.1.1.7   root     9513: #ifndef WINUAE_FOR_HATARI
1.1.1.8   root     9514:        /* Under Hatari, we save all MMU variables, even if mmu_model==0 */
1.1.1.7   root     9515:        if (model != 68030 && model != 68040 && model != 68060)
1.1.1.4   root     9516:                return NULL;
1.1.1.7   root     9517: #endif
1.1.1.4   root     9518:        if (dstptr)
                   9519:                dstbak = dst = dstptr;
                   9520:        else
                   9521:                dstbak = dst = xmalloc (uae_u8, 1000);
                   9522:        save_u32 (model);       /* MODEL */
1.1.1.7   root     9523:        save_u32 (0);           /* FLAGS */
1.1.1.4   root     9524:        *len = dst - dstbak;
                   9525:        return dstbak;
                   9526: }
                   9527: 
                   9528: uae_u8 *restore_mmu (uae_u8 *src)
                   9529: {
                   9530:        int flags, model;
                   9531: 
                   9532:        changed_prefs.mmu_model = model = restore_u32 ();
                   9533:        flags = restore_u32 ();
1.1.1.7   root     9534:        write_log (_T("MMU: %d\n"), model);
1.1.1.4   root     9535:        return src;
                   9536: }
                   9537: 
                   9538: #endif /* SAVESTATE */
                   9539: 
1.1.1.7   root     9540: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
1.1.1.4   root     9541: {
                   9542:        if (currprefs.cpu_model >= 68040)
                   9543:                addr &= ~1;
1.1.1.7   root     9544:        if (currprefs.cpu_model >= 68020) {
                   9545:                if (pc == 0xffffffff)
                   9546:                        last_addr_for_exception_3 = regs.instruction_pc;
                   9547:                else
                   9548:                        last_addr_for_exception_3 = pc;
                   9549:        } else if (pc == 0xffffffff) {
                   9550:                last_addr_for_exception_3 = m68k_getpc ();
                   9551:                if (plus2)
                   9552:                        last_addr_for_exception_3 += 2;
                   9553:        } else {
                   9554:                last_addr_for_exception_3 = pc;
                   9555:        }
                   9556:        last_fault_for_exception_3 = addr;
1.1.1.4   root     9557:        last_op_for_exception_3 = opcode;
                   9558:        last_writeaccess_for_exception_3 = writeaccess;
                   9559:        last_instructionaccess_for_exception_3 = instructionaccess;
1.1.1.7   root     9560:        last_notinstruction_for_exception_3 = notinstruction;
                   9561:        Exception (3);
                   9562: #if EXCEPTION3_DEBUGGER
                   9563:        activate_debugger();
                   9564: #endif
1.1.1.4   root     9565: }
                   9566: 
1.1.1.7   root     9567: void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
1.1.1.4   root     9568: {
1.1.1.7   root     9569:        exception3f (opcode, addr, true, false, true, 0xffffffff, false);
1.1.1.4   root     9570: }
1.1.1.7   root     9571: void exception3_read(uae_u32 opcode, uaecptr addr)
                   9572: {
                   9573:        exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
                   9574: }
                   9575: void exception3_write(uae_u32 opcode, uaecptr addr)
                   9576: {
                   9577:        exception3f (opcode, addr, true, 0, false, 0xffffffff, false);
                   9578: }
                   9579: void exception3i (uae_u32 opcode, uaecptr addr)
                   9580: {
                   9581:        exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
                   9582: }
                   9583: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
1.1.1.4   root     9584: {
1.1.1.7   root     9585:        exception3f (opcode, addr, w, i, false, pc, true);
1.1.1.4   root     9586: }
                   9587: 
1.1.1.7   root     9588: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
1.1.1.4   root     9589: {
1.1.1.7   root     9590:        if (currprefs.mmu_model) {
                   9591:                if (currprefs.mmu_model == 68030) {
                   9592:                        uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
                   9593:                        mmu030_page_fault (addr, read, flags, fc);
                   9594:                } else {
1.1.1.9 ! root     9595:                        mmu_bus_error (addr, 0, fc, read == false, size, 0, true);
1.1.1.7   root     9596:                }
                   9597:        } else {
                   9598:                last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
                   9599:                last_fault_for_exception_3 = addr;
                   9600:                last_writeaccess_for_exception_3 = read == 0;
                   9601:                last_instructionaccess_for_exception_3 = (fc & 1) == 0;
                   9602:                last_op_for_exception_3 = regs.opcode;
                   9603:                last_notinstruction_for_exception_3 = exception_in_exception != 0;
                   9604:                THROW(2);
                   9605:        }
1.1.1.4   root     9606: }
                   9607: 
                   9608: void cpureset (void)
                   9609: {
1.1.1.7   root     9610:     /* RESET hasn't increased PC yet, 1 word offset */
1.1.1.4   root     9611:        uaecptr pc;
1.1.1.7   root     9612: #ifndef WINUAE_FOR_HATARI
                   9613:        uaecptr ksboot = 0xf80002 - 2;
1.1.1.4   root     9614:        uae_u16 ins;
1.1.1.7   root     9615: #endif
                   9616:        addrbank *ab;
1.1.1.4   root     9617: 
1.1.1.7   root     9618:        m68k_reset_delay = currprefs.reset_delay;
                   9619:        set_special(SPCFLAG_CHECK);
                   9620: #ifndef WINUAE_FOR_HATARI
                   9621:        send_internalevent(INTERNALEVENT_CPURESET);
1.1.1.8   root     9622:        if ((currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) && currprefs.cpu_model <= 68020) {
1.1.1.7   root     9623:                custom_reset (false, false);
1.1.1.4   root     9624:                return;
                   9625:        }
1.1.1.7   root     9626: #endif
                   9627:        pc = m68k_getpc () + 2;
                   9628:        ab = &get_mem_bank (pc);
                   9629:        if (ab->check (pc, 2)) {
                   9630:                write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name);
                   9631: #ifndef WINUAE_FOR_HATARI
                   9632:                ins = get_word (pc);
                   9633:                custom_reset (false, false);
                   9634:                // did memory disappear under us?
                   9635:                if (ab == &get_mem_bank (pc))
                   9636:                        return;
                   9637:                // it did
                   9638:                if ((ins & ~7) == 0x4ed0) {
                   9639:                        int reg = ins & 7;
                   9640:                        uae_u32 addr = m68k_areg (regs, reg);
                   9641:                        if (addr < 0x80000)
                   9642:                                addr += 0xf80000;
                   9643:                        write_log (_T("reset/jmp (ax) combination at %08x emulated -> %x\n"), pc, addr);
                   9644:                        m68k_setpc_normal (addr - 2);
1.1.1.4   root     9645:                        return;
                   9646:                }
1.1.1.7   root     9647: #else
                   9648:                customreset ();         /* From hatari-glue.c */
                   9649:                return;
                   9650: #endif
                   9651:        }
                   9652:        // the best we can do, jump directly to ROM entrypoint
                   9653:        // (which is probably what program wanted anyway)
                   9654: #ifndef WINUAE_FOR_HATARI
                   9655:        write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2);
                   9656:        custom_reset (false, false);
                   9657:        m68k_setpc_normal (ksboot);
                   9658: #else
                   9659:        write_log (_T("CPU Reset PC=%x (%s), invalid memory\n"), pc, ab->name);
                   9660:        customreset ();                 /* From hatari-glue.c */
                   9661: #endif
1.1.1.4   root     9662: }
                   9663: 
                   9664: 
                   9665: void m68k_setstopped (void)
                   9666: {
                   9667:        /* A traced STOP instruction drops through immediately without
                   9668:        actually stopping.  */
1.1.1.8   root     9669:        if ((regs.spcflags & SPCFLAG_DOTRACE) == 0) {
                   9670:                m68k_set_stop();
                   9671:        } else {
1.1.1.4   root     9672:                m68k_resumestopped ();
1.1.1.8   root     9673:        }
1.1.1.4   root     9674: }
                   9675: 
                   9676: void m68k_resumestopped (void)
                   9677: {
                   9678:        if (!regs.stopped)
                   9679:                return;
1.1.1.8   root     9680:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000) {
                   9681:                x_do_cycles (6 * cpucycleunit);
1.1.1.4   root     9682:        }
1.1.1.7   root     9683:        fill_prefetch ();
1.1.1.8   root     9684:        m68k_unset_stop();
                   9685: }
                   9686: 
                   9687: 
                   9688: uae_u32 mem_access_delay_word_read (uaecptr addr)
                   9689: {
                   9690:        uae_u32 v;
                   9691: //#ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     9692:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     9693: #if 1
                   9694:        switch (ce_banktype[addr >> 16])
                   9695:        {
                   9696:        case CE_MEMBANK_CHIP16:
                   9697:        case CE_MEMBANK_CHIP32:
                   9698:                v = wait_cpu_cycle_read (addr, 1);
                   9699:                break;
                   9700:        case CE_MEMBANK_FAST16:
                   9701:        case CE_MEMBANK_FAST32:
                   9702:                v = get_word (addr);
                   9703:                x_do_cycles_post (4 * cpucycleunit, v);
                   9704:                break;
                   9705:        default:
                   9706:                v = get_word (addr);
                   9707:                break;
                   9708:        }
                   9709: #else
                   9710: //fprintf ( stderr , "word read mis %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   9711:        v = get_word (addr);
                   9712:        x_do_cycles_post (4 * cpucycleunit, v);
                   9713: #endif
                   9714:        regs.db = v;
1.1.1.9 ! root     9715:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 );         // WINUAE_FOR_HATARI
1.1.1.8   root     9716:        return v;
                   9717: }
                   9718: uae_u32 mem_access_delay_wordi_read (uaecptr addr)
                   9719: {
                   9720:        uae_u32 v;
                   9721: //#ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     9722:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     9723: #if 1
                   9724:        switch (ce_banktype[addr >> 16])
                   9725:        {
                   9726:        case CE_MEMBANK_CHIP16:
                   9727:        case CE_MEMBANK_CHIP32:
                   9728:                v = wait_cpu_cycle_read (addr, 2);
                   9729:                break;
                   9730:        case CE_MEMBANK_FAST16:
                   9731:        case CE_MEMBANK_FAST32:
                   9732:                v = get_wordi (addr);
                   9733:                x_do_cycles_post (4 * cpucycleunit, v);
                   9734:                break;
                   9735:        default:
                   9736:                v = get_wordi (addr);
                   9737:                break;
                   9738:        }
                   9739: #else
                   9740: //fprintf ( stderr , "wordi read mis %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   9741:        v = get_wordi (addr);
                   9742:        x_do_cycles_post (4 * cpucycleunit, v);
                   9743: #endif
                   9744:        regs.db = v;
1.1.1.9 ! root     9745:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 );         // WINUAE_FOR_HATARI
1.1.1.8   root     9746:        return v;
                   9747: }
                   9748: 
                   9749: uae_u32 mem_access_delay_byte_read (uaecptr addr)
                   9750: {
                   9751:        uae_u32  v;
                   9752: //#ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     9753:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     9754: #if 1
                   9755:        switch (ce_banktype[addr >> 16])
                   9756:        {
                   9757:        case CE_MEMBANK_CHIP16:
                   9758:        case CE_MEMBANK_CHIP32:
                   9759:                v = wait_cpu_cycle_read (addr, 0);
                   9760:                break;
                   9761:        case CE_MEMBANK_FAST16:
                   9762:        case CE_MEMBANK_FAST32:
                   9763:                v = get_byte (addr);
                   9764:                x_do_cycles_post (4 * cpucycleunit, v);
                   9765:                break;
                   9766:        default:
                   9767:                v = get_byte (addr);
                   9768:                break;
                   9769:        }
                   9770: #else
                   9771: //fprintf ( stderr , "byte read mis %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   9772:        v = get_byte (addr);
                   9773:        x_do_cycles_post (4 * cpucycleunit, v);
                   9774: #endif
                   9775:        regs.db = (v << 8) | v;
1.1.1.9 ! root     9776:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 );         // WINUAE_FOR_HATARI
1.1.1.8   root     9777:        return v;
                   9778: }
                   9779: void mem_access_delay_byte_write (uaecptr addr, uae_u32 v)
                   9780: {
                   9781:        regs.db = (v << 8)  | v;
                   9782: //#ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     9783:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     9784: #if 1
                   9785:        switch (ce_banktype[addr >> 16])
                   9786:        {
                   9787:        case CE_MEMBANK_CHIP16:
                   9788:        case CE_MEMBANK_CHIP32:
                   9789:                wait_cpu_cycle_write (addr, 0, v);
1.1.1.9 ! root     9790:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     9791:                return;
                   9792:        case CE_MEMBANK_FAST16:
                   9793:        case CE_MEMBANK_FAST32:
                   9794:                put_byte (addr, v);
                   9795:                x_do_cycles_post (4 * cpucycleunit, v);
1.1.1.9 ! root     9796:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     9797:                return;
                   9798:        }
                   9799:        put_byte (addr, v);
                   9800: #else
                   9801:        put_byte (addr, v);
                   9802:        x_do_cycles_post (4 * cpucycleunit, v);
                   9803: #endif
                   9804: }
                   9805: void mem_access_delay_word_write (uaecptr addr, uae_u32 v)
                   9806: {
                   9807: //#ifndef WINUAE_FOR_HATARI
1.1.1.9 ! root     9808:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     9809: #if 1
                   9810:        regs.db = v;
                   9811:        switch (ce_banktype[addr >> 16])
                   9812:        {
                   9813:        case CE_MEMBANK_CHIP16:
                   9814:        case CE_MEMBANK_CHIP32:
                   9815:                wait_cpu_cycle_write (addr, 1, v);
1.1.1.9 ! root     9816:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     9817:                return;
                   9818:        case CE_MEMBANK_FAST16:
                   9819:        case CE_MEMBANK_FAST32:
                   9820:                put_word (addr, v);
                   9821:                x_do_cycles_post (4 * cpucycleunit, v);
1.1.1.9 ! root     9822:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     9823:                return;
                   9824:        }
                   9825:        put_word (addr, v);
                   9826: #else
                   9827:        put_word (addr, v);
                   9828:        x_do_cycles_post (4 * cpucycleunit, v);
                   9829: #endif
1.1.1.4   root     9830: }
                   9831: 
1.1.1.9 ! root     9832: static void start_020_cycle(void)
        !          9833: {
        !          9834:        regs.ce020startcycle = get_cycles();
        !          9835: }
        !          9836: 
        !          9837: static void start_020_cycle_prefetch(bool opcode)
        !          9838: {
        !          9839:        regs.ce020startcycle = get_cycles();
        !          9840:        // back to back prefetch cycles require 2 extra cycles (maybe)
        !          9841:        if (opcode && regs.ce020startcycle == regs.ce020prefetchendcycle && currprefs.cpu_cycle_exact) {
        !          9842:                x_do_cycles(2 * cpucycleunit);
        !          9843:                regs.ce020startcycle = get_cycles();
        !          9844:        }
        !          9845: }
        !          9846: static void end_020_cycle(void)
        !          9847: {
        !          9848:        regs.ce020endcycle = get_cycles();
        !          9849: }
        !          9850: static void end_020_cycle_prefetch(bool opcode)
        !          9851: {
        !          9852:        regs.ce020endcycle = get_cycles();
        !          9853:        if (opcode) {
        !          9854:                regs.ce020prefetchendcycle = regs.ce020endcycle;
        !          9855:        } else {
        !          9856:                regs.ce020prefetchendcycle = regs.ce020startcycle;
        !          9857:        }
        !          9858: }
1.1.1.8   root     9859: 
1.1.1.4   root     9860: // this one is really simple and easy
1.1.1.9 ! root     9861: static void fill_icache020 (uae_u32 addr, bool opcode)
1.1.1.4   root     9862: {
                   9863:        int index;
                   9864:        uae_u32 tag;
                   9865:        uae_u32 data;
                   9866:        struct cache020 *c;
                   9867: 
1.1.1.9 ! root     9868:        regs.fc030 = (regs.s ? 4 : 0) | 2;
1.1.1.4   root     9869:        addr &= ~3;
1.1.1.7   root     9870:        if (regs.cacheholdingaddr020 == addr)
                   9871:                return;
1.1.1.4   root     9872:        index = (addr >> 2) & (CACHELINES020 - 1);
                   9873:        tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
                   9874:        c = &caches020[index];
1.1.1.9 ! root     9875:        if ((regs.cacr & 1) && c->valid && c->tag == tag) {
1.1.1.4   root     9876:                // cache hit
1.1.1.7   root     9877:                regs.cacheholdingaddr020 = addr;
                   9878:                regs.cacheholdingdata020 = c->data;
1.1.1.9 ! root     9879:                regs.cacheholdingdata_valid = true;
1.1.1.7   root     9880: #ifdef WINUAE_FOR_HATARI
                   9881:                CpuInstruction.I_Cache_hit++;
                   9882: #endif
1.1.1.4   root     9883:                return;
                   9884:        }
1.1.1.9 ! root     9885: 
1.1.1.4   root     9886:        // cache miss
1.1.1.9 ! root     9887: #if 0
1.1.1.7   root     9888:        // Prefetch apparently can be queued by bus controller
                   9889:        // even if bus controller is currently processing
                   9890:        // previous data access.
                   9891:        // Other combinations are not possible.
1.1.1.9 ! root     9892:        if (!regs.ce020memcycle_data) {
        !          9893:                if (regs.ce020memcycles > 0)
        !          9894:                        x_do_cycles (regs.ce020memcycles);
1.1.1.7   root     9895:                regs.ce020memcycles = 0;
1.1.1.9 ! root     9896:        }
        !          9897: #endif
        !          9898: 
        !          9899:        start_020_cycle_prefetch(opcode);
        !          9900:        data = icache_fetch(addr);
        !          9901:        end_020_cycle_prefetch(opcode);
        !          9902: 
        !          9903:        // enabled and not frozen
        !          9904:        if ((regs.cacr & 1) && !(regs.cacr & 2)) {
1.1.1.4   root     9905:                c->tag = tag;
1.1.1.9 ! root     9906:                c->valid = true;
1.1.1.4   root     9907:                c->data = data;
                   9908:        }
1.1.1.7   root     9909:        regs.cacheholdingaddr020 = addr;
                   9910:        regs.cacheholdingdata020 = data;
1.1.1.9 ! root     9911:        regs.cacheholdingdata_valid = true;
1.1.1.7   root     9912: #ifdef WINUAE_FOR_HATARI
                   9913:        CpuInstruction.I_Cache_miss++;
                   9914: #endif
1.1.1.4   root     9915: }
                   9916: 
1.1.1.7   root     9917: #if MORE_ACCURATE_68020_PIPELINE
                   9918: #define PIPELINE_DEBUG 0
                   9919: #if PIPELINE_DEBUG
                   9920: static uae_u16 pipeline_opcode;
                   9921: #endif
1.1.1.9 ! root     9922: static void pipeline_020(uaecptr pc)
1.1.1.4   root     9923: {
1.1.1.9 ! root     9924:        uae_u16 w = regs.prefetch020[1];
        !          9925:        if (regs.prefetch020_valid[1] == 0) {
        !          9926:                regs.pipeline_stop = -1;
        !          9927:                return;
        !          9928:        }
1.1.1.7   root     9929:        if (regs.pipeline_pos < 0)
                   9930:                return;
                   9931:        if (regs.pipeline_pos > 0) {
                   9932:                // handle annoying 68020+ addressing modes
                   9933:                if (regs.pipeline_pos == regs.pipeline_r8[0]) {
                   9934:                        regs.pipeline_r8[0] = 0;
                   9935:                        if (w & 0x100) {
                   9936:                                int extra = 0;
                   9937:                                if ((w & 0x30) == 0x20)
                   9938:                                        extra += 2;
                   9939:                                if ((w & 0x30) == 0x30)
                   9940:                                        extra += 4;
                   9941:                                if ((w & 0x03) == 0x02)
                   9942:                                        extra += 2;
                   9943:                                if ((w & 0x03) == 0x03)
                   9944:                                        extra += 4;
                   9945:                                regs.pipeline_pos += extra;
                   9946:                        }
                   9947:                        return;
                   9948:                }
                   9949:                if (regs.pipeline_pos == regs.pipeline_r8[1]) {
                   9950:                        regs.pipeline_r8[1] = 0;
                   9951:                        if (w & 0x100) {
                   9952:                                int extra = 0;
                   9953:                                if ((w & 0x30) == 0x20)
                   9954:                                        extra += 2;
                   9955:                                if ((w & 0x30) == 0x30)
                   9956:                                        extra += 4;
                   9957:                                if ((w & 0x03) == 0x02)
                   9958:                                        extra += 2;
                   9959:                                if ((w & 0x03) == 0x03)
                   9960:                                        extra += 4;
                   9961:                                regs.pipeline_pos += extra;
1.1.1.4   root     9962:                        }
1.1.1.7   root     9963:                        return;
                   9964:                }
                   9965:        }
                   9966:        if (regs.pipeline_pos > 2) {
                   9967:                regs.pipeline_pos -= 2;
                   9968:                // If stop set, prefetches stop 1 word early.
                   9969:                if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2)
                   9970:                        regs.pipeline_stop = -1;
                   9971:                return;
                   9972:        }
                   9973:        if (regs.pipeline_stop) {
                   9974:                regs.pipeline_stop = -1;
                   9975:                return;
                   9976:        }
                   9977: #if PIPELINE_DEBUG
                   9978:        pipeline_opcode = w;
                   9979: #endif
                   9980:        regs.pipeline_r8[0] = cpudatatbl[w].disp020[0];
                   9981:        regs.pipeline_r8[1] = cpudatatbl[w].disp020[1];
                   9982:        regs.pipeline_pos = cpudatatbl[w].length;
                   9983: #if PIPELINE_DEBUG
                   9984:        if (!regs.pipeline_pos) {
                   9985:                write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
                   9986:        }
                   9987: #endif
1.1.1.8   root     9988:        // illegal instructions, TRAP, TRAPV, A-line, F-line don't stop prefetches
1.1.1.7   root     9989:        int branch = cpudatatbl[w].branch;
                   9990:        if (regs.pipeline_pos > 0 && branch) {
                   9991:                // Short branches (Bcc.s) still do one more prefetch.
                   9992: #if 0
                   9993:                // RTS and other unconditional single opcode instruction stop immediately.
                   9994:                if (branch == 2) {
                   9995:                        // Immediate stop
                   9996:                        regs.pipeline_stop = -1;
                   9997:                } else {
                   9998:                        // Stop 1 word early than normally
                   9999:                        regs.pipeline_stop = 1;
1.1.1.4   root     10000:                }
1.1.1.7   root     10001: #else
                   10002:                regs.pipeline_stop = 1;
                   10003: #endif
1.1.1.4   root     10004:        }
                   10005: }
                   10006: 
1.1.1.7   root     10007: #endif
1.1.1.4   root     10008: 
1.1.1.9 ! root     10009: static uae_u32 get_word_ce020_prefetch_2 (int o, bool opcode)
1.1.1.4   root     10010: {
1.1.1.7   root     10011:        uae_u32 pc = m68k_getpc () + o;
                   10012:        uae_u32 v;
1.1.1.4   root     10013: 
1.1.1.9 ! root     10014:        v = regs.prefetch020[0];
        !          10015:        regs.prefetch020[0] = regs.prefetch020[1];
        !          10016:        regs.prefetch020[1] = regs.prefetch020[2];
1.1.1.7   root     10017: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9 ! root     10018:        pipeline_020(pc);
1.1.1.7   root     10019: #endif
1.1.1.9 ! root     10020:        if (pc & 2) {
1.1.1.7   root     10021:                // branch instruction detected in pipeline: stop fetches until branch executed.
                   10022:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
1.1.1.9 ! root     10023:                        fill_icache020 (pc + 2 + 4, opcode);
1.1.1.4   root     10024:                }
1.1.1.9 ! root     10025:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     10026:        } else {
1.1.1.9 ! root     10027:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.4   root     10028:        }
1.1.1.7   root     10029:        do_cycles_ce020_internal (2);
1.1.1.9 ! root     10030:        regs.db = regs.prefetch020[0];
1.1.1.7   root     10031:        return v;
1.1.1.4   root     10032: }
                   10033: 
1.1.1.9 ! root     10034: uae_u32 get_word_ce020_prefetch (int o)
        !          10035: {
        !          10036:        return get_word_ce020_prefetch_2(o, false);
        !          10037: }
        !          10038: 
        !          10039: uae_u32 get_word_ce020_prefetch_opcode (int o)
        !          10040: {
        !          10041:        return get_word_ce020_prefetch_2(o, true);
        !          10042: }
        !          10043: 
1.1.1.7   root     10044: uae_u32 get_word_020_prefetch (int o)
1.1.1.4   root     10045: {
1.1.1.7   root     10046:        uae_u32 pc = m68k_getpc () + o;
                   10047:        uae_u32 v;
1.1.1.4   root     10048: 
1.1.1.9 ! root     10049:        v = regs.prefetch020[0];
        !          10050:        regs.prefetch020[0] = regs.prefetch020[1];
        !          10051:        regs.prefetch020[1] = regs.prefetch020[2];
1.1.1.7   root     10052: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9 ! root     10053:        pipeline_020(pc);
1.1.1.7   root     10054: #endif
1.1.1.9 ! root     10055:        if (pc & 2) {
        !          10056:                // branch instruction detected in pipeline: stop fetches until branch executed.
1.1.1.7   root     10057:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
1.1.1.9 ! root     10058:                        fill_icache020 (pc + 2 + 4, false);
1.1.1.7   root     10059:                }
1.1.1.9 ! root     10060:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     10061:        } else {
1.1.1.9 ! root     10062:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.7   root     10063:        }
1.1.1.9 ! root     10064:        regs.db = regs.prefetch020[0];
1.1.1.7   root     10065: //if ( ( v & 0xffff ) != ( get_word(pc) & 0xffff ) )
                   10066: //  fprintf ( stderr , "prefetch mismatch pc=%x prefetch=%x != mem=%x, i-cache error ?\n" , pc , v&0xffff , get_word(pc)&0xffff );
                   10067:        return v;
                   10068: }
1.1.1.4   root     10069: 
1.1.1.7   root     10070: // these are also used by 68030.
1.1.1.4   root     10071: 
1.1.1.9 ! root     10072: #if 0
1.1.1.7   root     10073: #define RESET_CE020_CYCLES \
                   10074:        regs.ce020memcycles = 0; \
                   10075:        regs.ce020memcycle_data = true;
                   10076: #define STORE_CE020_CYCLES \
                   10077:        unsigned long cycs = get_cycles ()
                   10078: #define ADD_CE020_CYCLES \
                   10079:        regs.ce020memcycles += get_cycles () - cycs
1.1.1.9 ! root     10080: #endif
1.1.1.4   root     10081: 
1.1.1.7   root     10082: uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
                   10083: {
                   10084:        uae_u32 v;
1.1.1.9 ! root     10085: //fprintf ( stderr , "long read ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
        !          10086:        start_020_cycle();
1.1.1.7   root     10087:        switch (ce_banktype[addr >> 16])
                   10088:        {
                   10089:        case CE_MEMBANK_CHIP16:
                   10090:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   10091:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   10092:                break;
                   10093:        case CE_MEMBANK_CHIP32:
                   10094:                if ((addr & 3) != 0) {
                   10095:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   10096:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   10097:                } else {
                   10098:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
                   10099:                }
                   10100:                break;
                   10101:        case CE_MEMBANK_FAST32:
                   10102:                v = get_long (addr);
                   10103:                if ((addr & 3) != 0)
                   10104:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10105:                else
                   10106:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10107:                break;
                   10108:        case CE_MEMBANK_FAST16:
                   10109:                v = get_long (addr);
                   10110:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10111:                break;
                   10112:        default:
                   10113:                v = get_long (addr);
                   10114:                break;
                   10115:        }
1.1.1.9 ! root     10116: //fprintf ( stderr , "long read2 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
        !          10117:        end_020_cycle();
        !          10118: //fprintf ( stderr , "long read3 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
1.1.1.7   root     10119:        return v;
                   10120: }
                   10121: 
                   10122: uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
                   10123: {
                   10124:        uae_u32 v;
                   10125:        switch (ce_banktype[addr >> 16])
                   10126:        {
                   10127:        case CE_MEMBANK_CHIP16:
1.1.1.8   root     10128:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 2) << 16;
                   10129:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 2) <<  0;
1.1.1.7   root     10130:                break;
                   10131:        case CE_MEMBANK_CHIP32:
                   10132:                if ((addr & 3) != 0) {
1.1.1.8   root     10133:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 2) << 16;
                   10134:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 2) <<  0;
1.1.1.7   root     10135:                } else {
1.1.1.8   root     10136:                        v = wait_cpu_cycle_read_ce020 (addr, -2);
1.1.1.7   root     10137:                }
                   10138:                break;
                   10139:        case CE_MEMBANK_FAST32:
                   10140:                v = get_longi (addr);
                   10141:                if ((addr & 3) != 0)
                   10142:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10143:                else
                   10144:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10145:                break;
                   10146:        case CE_MEMBANK_FAST16:
                   10147:                v = get_longi (addr);
                   10148:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10149:                break;
                   10150:        default:
                   10151:                v = get_longi (addr);
                   10152:                break;
                   10153:        }
                   10154:        return v;
                   10155: }
                   10156: 
1.1.1.9 ! root     10157: uae_u32 mem_access_delay_wordi_read_ce020 (uaecptr addr)
        !          10158: {
        !          10159:        uae_u32 v;
        !          10160:        start_020_cycle();
        !          10161:        switch (ce_banktype[addr >> 16])
        !          10162:        {
        !          10163:        case CE_MEMBANK_CHIP16:
        !          10164:        case CE_MEMBANK_CHIP32:
        !          10165:                if ((addr & 3) == 3) {
        !          10166:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
        !          10167:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
        !          10168:                } else {
        !          10169:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
        !          10170:                }
        !          10171:                break;
        !          10172:        case CE_MEMBANK_FAST16:
        !          10173:        case CE_MEMBANK_FAST32:
        !          10174:                v = get_wordi (addr);
        !          10175:                if ((addr & 3) == 3)
        !          10176:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          10177:                else
        !          10178:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
        !          10179:                 break;
        !          10180:        default:
        !          10181:                 v = get_wordi (addr);
        !          10182:                break;
        !          10183:        }
        !          10184:        end_020_cycle();
        !          10185:        return v;
        !          10186: }
        !          10187: 
1.1.1.7   root     10188: uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
                   10189: {
                   10190:        uae_u32 v;
1.1.1.9 ! root     10191:        start_020_cycle();
1.1.1.7   root     10192:        switch (ce_banktype[addr >> 16])
                   10193:        {
                   10194:        case CE_MEMBANK_CHIP16:
                   10195:        case CE_MEMBANK_CHIP32:
                   10196:                if ((addr & 3) == 3) {
                   10197:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
                   10198:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
                   10199:                } else {
                   10200:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
                   10201:                }
                   10202:                break;
                   10203:        case CE_MEMBANK_FAST16:
                   10204:        case CE_MEMBANK_FAST32:
                   10205:                v = get_word (addr);
                   10206:                if ((addr & 3) == 3)
                   10207:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10208:                else
                   10209:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10210:                 break;
                   10211:        default:
                   10212:                 v = get_word (addr);
                   10213:                break;
                   10214:        }
1.1.1.9 ! root     10215:        end_020_cycle();
1.1.1.7   root     10216:        return v;
                   10217: }
                   10218: 
                   10219: uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
                   10220: {
                   10221:        uae_u32 v;
1.1.1.9 ! root     10222:        start_020_cycle();
1.1.1.7   root     10223:        switch (ce_banktype[addr >> 16])
                   10224:        {
                   10225:        case CE_MEMBANK_CHIP16:
                   10226:        case CE_MEMBANK_CHIP32:
                   10227:                v = wait_cpu_cycle_read_ce020 (addr, 0);
                   10228:                break;
                   10229:        case CE_MEMBANK_FAST16:
                   10230:        case CE_MEMBANK_FAST32:
                   10231:                v = get_byte (addr);
                   10232:                do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10233:                break;
                   10234:        default:
                   10235:                v = get_byte (addr);
                   10236:                break;
                   10237:        }
1.1.1.9 ! root     10238:        end_020_cycle();
1.1.1.7   root     10239:        return v;
                   10240: }
                   10241: 
                   10242: void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
                   10243: {
1.1.1.9 ! root     10244:        start_020_cycle();
1.1.1.7   root     10245:        switch (ce_banktype[addr >> 16])
                   10246:        {
                   10247:        case CE_MEMBANK_CHIP16:
                   10248:        case CE_MEMBANK_CHIP32:
                   10249:                wait_cpu_cycle_write_ce020 (addr, 0, v);
                   10250:                break;
                   10251:        case CE_MEMBANK_FAST16:
                   10252:        case CE_MEMBANK_FAST32:
                   10253:                put_byte (addr, v);
                   10254:                do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10255:                break;
                   10256:        default:
                   10257:                put_byte (addr, v);
                   10258:        break;
1.1.1.4   root     10259:        }
1.1.1.9 ! root     10260:        end_020_cycle();
1.1.1.7   root     10261: }
                   10262: 
                   10263: void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
                   10264: {
1.1.1.9 ! root     10265:        start_020_cycle();
1.1.1.7   root     10266:        switch (ce_banktype[addr >> 16])
                   10267:        {
                   10268:        case CE_MEMBANK_CHIP16:
                   10269:        case CE_MEMBANK_CHIP32:
                   10270:                if ((addr & 3) == 3) {
                   10271:                        wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
                   10272:                        wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
                   10273:                } else {
                   10274:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
                   10275:                }
                   10276:                break;
                   10277:        case CE_MEMBANK_FAST16:
                   10278:        case CE_MEMBANK_FAST32:
                   10279:                put_word (addr, v);
                   10280:                if ((addr & 3) == 3)
                   10281:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10282:                else
                   10283:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10284:                break;
                   10285:        default:
                   10286:                put_word (addr, v);
                   10287:        break;
                   10288:        }
1.1.1.9 ! root     10289:        end_020_cycle();
1.1.1.7   root     10290: }
                   10291: 
                   10292: void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
                   10293: {
1.1.1.9 ! root     10294:        start_020_cycle();
1.1.1.7   root     10295:        switch (ce_banktype[addr >> 16])
                   10296:        {
                   10297:        case CE_MEMBANK_CHIP16:
                   10298:                wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
                   10299:                wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
                   10300:                break;
                   10301:        case CE_MEMBANK_CHIP32:
                   10302:                if ((addr & 3) == 3) {
                   10303:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
                   10304:                        wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
                   10305:                } else {
                   10306:                        wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
                   10307:                }
                   10308:                break;
                   10309:        case CE_MEMBANK_FAST32:
                   10310:                put_long (addr, v);
                   10311:                if ((addr & 3) != 0)
                   10312:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10313:                else
                   10314:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10315:                break;
                   10316:        case CE_MEMBANK_FAST16:
                   10317:                put_long (addr, v);
                   10318:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10319:                break;
                   10320:        default:
                   10321:                put_long (addr, v);
                   10322:                break;
                   10323:        }
1.1.1.9 ! root     10324:        end_020_cycle();
1.1.1.7   root     10325: }
                   10326: 
                   10327: 
                   10328: // 68030 caches aren't so simple as 68020 cache..
1.1.1.9 ! root     10329: STATIC_INLINE struct cache030 *geticache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
1.1.1.7   root     10330: {
                   10331:        int index, lws;
                   10332:        uae_u32 tag;
                   10333:        struct cache030 *c;
                   10334: 
                   10335:        addr &= ~3;
                   10336:        index = (addr >> 4) & (CACHELINES030 - 1);
                   10337:        tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
                   10338:        lws = (addr >> 2) & 3;
                   10339:        c = &cp[index];
                   10340:        *tagp = tag;
                   10341:        *lwsp = lws;
1.1.1.9 ! root     10342: //fprintf ( stderr , "getcache addr=%x index=%x tag=%x lws=%x\n" , addr , index , tag , lws );
        !          10343:        return c;
        !          10344: }
        !          10345: 
        !          10346: STATIC_INLINE void update_icache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
        !          10347: {
        !          10348:        if (c->tag != tag)
        !          10349:                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
        !          10350:        c->tag = tag;
        !          10351:        c->valid[lws] = true;
        !          10352:        c->data[lws] = val;
        !          10353: }
        !          10354: 
        !          10355: STATIC_INLINE struct cache030 *getdcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
        !          10356: {
        !          10357:        int index, lws;
        !          10358:        uae_u32 tag;
        !          10359:        struct cache030 *c;
        !          10360: 
        !          10361:        addr &= ~3;
        !          10362:        index = (addr >> 4) & (CACHELINES030 - 1);
        !          10363:        tag = addr & ~((CACHELINES030 << 4) - 1);
        !          10364:        lws = (addr >> 2) & 3;
        !          10365:        c = &cp[index];
        !          10366:        *tagp = tag;
        !          10367:        *lwsp = lws;
1.1.1.7   root     10368:        return c;
                   10369: }
                   10370: 
1.1.1.9 ! root     10371: STATIC_INLINE void update_dcache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, uae_u8 fc, int lws)
1.1.1.7   root     10372: {
                   10373:        if (c->tag != tag)
                   10374:                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
                   10375:        c->tag = tag;
1.1.1.9 ! root     10376:        c->fc = fc;
1.1.1.7   root     10377:        c->valid[lws] = true;
                   10378:        c->data[lws] = val;
                   10379: }
                   10380: 
                   10381: static void fill_icache030 (uae_u32 addr)
                   10382: {
                   10383:        int lws;
                   10384:        uae_u32 tag;
                   10385:        uae_u32 data;
                   10386:        struct cache030 *c;
1.1.1.9 ! root     10387: //fprintf ( stderr , "fill icache030 %x %x %x\n" , addr , regs.cacr , regs.cacheholdingaddr020 );
1.1.1.7   root     10388: 
1.1.1.9 ! root     10389:        regs.fc030 = (regs.s ? 4 : 0) | 2;
1.1.1.7   root     10390:        addr &= ~3;
1.1.1.9 ! root     10391:        if (regs.cacheholdingaddr020 == addr || regs.cacheholdingdata_valid == 0)
1.1.1.7   root     10392:                return;
1.1.1.9 ! root     10393:        c = geticache030 (icaches030, addr, &tag, &lws);
        !          10394:        if ((regs.cacr & 1) && c->valid[lws] && c->tag == tag) {
1.1.1.7   root     10395:                // cache hit
                   10396:                regs.cacheholdingaddr020 = addr;
                   10397:                regs.cacheholdingdata020 = c->data[lws];
1.1.1.9 ! root     10398: //fprintf ( stderr , "fill ica %x -> hit %x %x\n" , addr , regs.cacheholdingdata020 , regs.cacr );
1.1.1.7   root     10399: #ifdef WINUAE_FOR_HATARI
                   10400:                CpuInstruction.I_Cache_hit++;
1.1.1.4   root     10401: #endif
1.1.1.7   root     10402:                return;
                   10403:        }
                   10404: 
1.1.1.9 ! root     10405:        TRY (prb2) {
        !          10406:                // cache miss
        !          10407:                if (currprefs.cpu_cycle_exact) {
        !          10408:                        regs.ce020memcycle_data = false;
        !          10409:                        start_020_cycle_prefetch(false);
        !          10410:                        data = icache_fetch(addr);
        !          10411:                        end_020_cycle_prefetch(false);
        !          10412:                } else {
        !          10413:                        data = icache_fetch(addr);
        !          10414:                }
        !          10415:        } CATCH (prb2) {
        !          10416:                // Bus error/MMU access fault: Delayed exception.
        !          10417:                regs.cacheholdingdata_valid = 0;
        !          10418:                regs.cacheholdingaddr020 = 0xffffffff;
        !          10419:                regs.cacheholdingdata020 = 0xffffffff;
        !          10420:                end_020_cycle_prefetch(false);
        !          10421:                return;
        !          10422:        } ENDTRY
        !          10423: 
        !          10424:        if (mmu030_cache_state & CACHE_ENABLE_INS) {
        !          10425:                if ((regs.cacr & 0x03) == 0x01) {
        !          10426:                        // instruction cache not frozen and enabled
1.1.1.7   root     10427: //fprintf ( stderr , "fill ica %x -> update %x\n" , addr , data );
1.1.1.9 ! root     10428:                        update_icache030 (c, data, tag, lws);
        !          10429:                }
        !          10430:                if ((mmu030_cache_state & CACHE_ENABLE_INS_BURST) && (regs.cacr & 0x11) == 0x11 && (c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1)) {
1.1.1.7   root     10431: //fprintf ( stderr , "fill ica %x -> burst %x\n" , addr , data );
1.1.1.9 ! root     10432:                        // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
        !          10433:                        int i;
        !          10434:                        for (i = 0; i < 4; i++) {
        !          10435:                                if (c->valid[i])
        !          10436:                                        break;
        !          10437:                        }
        !          10438:                        uaecptr baddr = addr & ~15;
        !          10439:                        if (currprefs.mmu_model) {
        !          10440:                                TRY (prb) {
        !          10441:                                        if (currprefs.cpu_cycle_exact)
        !          10442: #ifndef WINUAE_FOR_HATARI
        !          10443:                                                do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1));
        !          10444: #else
        !          10445:                                                do_cycles_ce020_long(3 * (CPU020_MEM_CYCLE - 1));
        !          10446: #endif
        !          10447:                                        int j;
        !          10448:                                        for (j = 0; j < 3; j++) {
        !          10449:                                                i++;
        !          10450:                                                i &= 3;
        !          10451:                                                c->data[i] = icache_fetch(baddr + i * 4);
        !          10452:                                                c->valid[i] = true;
        !          10453:                                        }
        !          10454:                                } CATCH (prb) {
        !          10455:                                        ; // abort burst fetch if bus error, do not report it.
        !          10456:                                } ENDTRY
        !          10457:                        } else {
        !          10458:                                int j;
        !          10459:                                for (j = 0; j < 3; j++) {
        !          10460:                                        i++;
        !          10461:                                        i &= 3;
        !          10462:                                        c->data[i] = icache_fetch(baddr + i * 4);
        !          10463:                                        c->valid[i] = true;
        !          10464:                                }
        !          10465:                                if (currprefs.cpu_cycle_exact)
        !          10466:                                        do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
        !          10467:                        }
        !          10468:                }
1.1.1.7   root     10469:        }
                   10470:        regs.cacheholdingaddr020 = addr;
                   10471:        regs.cacheholdingdata020 = data;
                   10472: //fprintf ( stderr , "fill ica %x -> miss %x\n" , addr , regs.cacheholdingdata020 );
                   10473: #ifdef WINUAE_FOR_HATARI
                   10474:        CpuInstruction.I_Cache_miss++;
                   10475: #endif
                   10476: }
                   10477: 
1.1.1.9 ! root     10478: #if VALIDATE_68030_DATACACHE
        !          10479: static void validate_dcache030(void)
1.1.1.7   root     10480: {
1.1.1.9 ! root     10481:        int i,j;
        !          10482:        for (i = 0; i < CACHELINES030; i++) {
        !          10483:                struct cache030 *c = &dcaches030[i];
        !          10484:                uae_u32 addr = c->tag & ~((CACHELINES030 << 4) - 1);
        !          10485:                addr |= i << 4;
        !          10486:                for (j = 0; j < 4; j++) {
        !          10487:                        if (c->valid[j]) {
        !          10488:                                uae_u32 v = get_long(addr);
        !          10489:                                if (v != c->data[j]) {
        !          10490:                                        write_log(_T("Address %08x data cache mismatch %08x != %08x\n"), addr, v, c->data[j]);
        !          10491:                                }
        !          10492:                        }
        !          10493:                        addr += 4;
        !          10494:                }
        !          10495:        }
1.1.1.7   root     10496: }
                   10497: 
1.1.1.9 ! root     10498: static void validate_dcache030_read(uae_u32 addr, uae_u32 ov, int size)
1.1.1.7   root     10499: {
1.1.1.9 ! root     10500:        uae_u32 ov2;
        !          10501:        if (size == 2) {
        !          10502:                ov2 = get_long(addr);
        !          10503:        } else if (size == 1) {
        !          10504:                ov2 = get_word(addr);
        !          10505:                ov &= 0xffff;
        !          10506:        } else {
        !          10507:                ov2 = get_byte(addr);
        !          10508:                ov &= 0xff;
1.1.1.4   root     10509:        }
1.1.1.9 ! root     10510:        if (ov2 != ov) {
        !          10511:                write_log(_T("Address read %08x data cache mismatch %08x != %08x\n"), addr, ov2, ov);
        !          10512:        }
        !          10513: }
        !          10514: #endif
1.1.1.7   root     10515: 
1.1.1.9 ! root     10516: // and finally the worst part, 68030 data cache..
        !          10517: static void write_dcache030x(uaecptr addr, uae_u32 val, uae_u32 size, uae_u32 fc)
        !          10518: {
        !          10519:        if (regs.cacr & 0x100) {
        !          10520:                static const uae_u32 mask[3] = { 0xff000000, 0xffff0000, 0xffffffff };
        !          10521:                struct cache030 *c1, *c2;
        !          10522:                int lws1, lws2;
        !          10523:                uae_u32 tag1, tag2;
        !          10524:                int aligned = addr & 3;
        !          10525:                int wa = regs.cacr & 0x2000;
        !          10526:                int width = 8 << size;
        !          10527:                int offset = 8 * aligned;
        !          10528:                int hit;
        !          10529: 
        !          10530:                c1 = getdcache030(dcaches030, addr, &tag1, &lws1);
        !          10531:                hit = c1->tag == tag1 && c1->fc == fc && c1->valid[lws1];
        !          10532: 
        !          10533:                // Write-allocate can create new valid cache entry if
        !          10534:                // long aligned long write and MMU CI is not active.
        !          10535:                // All writes ignore external CIIN signal.
        !          10536:                // CACHE_DISABLE_ALLOCATE = emulation only method to disable WA caching completely.
        !          10537: 
        !          10538:                if (width == 32 && offset == 0 && wa) {
        !          10539:                        if (!(mmu030_cache_state & CACHE_DISABLE_MMU) && !(mmu030_cache_state & CACHE_DISABLE_ALLOCATE)) {
        !          10540:                                update_dcache030(c1, val, tag1, fc, lws1);
        !          10541: //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] );
        !          10542: #if VALIDATE_68030_DATACACHE
        !          10543:                                validate_dcache030();
        !          10544: #endif
        !          10545:                        } else if (hit) {
        !          10546:                                // Does real 68030 do this if MMU cache inhibited?
1.1.1.7   root     10547:                                c1->valid[lws1] = false;
1.1.1.9 ! root     10548:                        }
        !          10549:                        return;
        !          10550:                }
        !          10551: 
        !          10552:                if (hit || wa) {
1.1.1.7   root     10553:                        if (hit) {
1.1.1.9 ! root     10554:                                uae_u32 val_left_aligned = val << (32 - width);
        !          10555:                                c1->data[lws1] &= ~(mask[size] >> offset);
        !          10556:                                c1->data[lws1] |= val_left_aligned >> offset;
        !          10557:                        } else {
1.1.1.7   root     10558:                                c1->valid[lws1] = false;
1.1.1.9 ! root     10559:                        }
        !          10560:                }
        !          10561: 
        !          10562:                // do we need to update a 2nd cache entry ?
        !          10563:                if (width + offset > 32) {
        !          10564:                        c2 = getdcache030(dcaches030, addr + 4, &tag2, &lws2);
        !          10565:                        hit = c2->tag == tag2 && c2->fc == fc && c2->valid[lws2];
        !          10566:                        if (hit || wa) {
        !          10567:                                if (hit) {
        !          10568:                                        c2->data[lws2] &= 0xffffffff >> (width + offset - 32);
        !          10569:                                        c2->data[lws2] |= val << (32 - (width + offset - 32));
        !          10570:                                } else {
        !          10571:                                        c2->valid[lws2] = false;
        !          10572:                                }
        !          10573:                        }
1.1.1.7   root     10574:                }
1.1.1.9 ! root     10575: #if VALIDATE_68030_DATACACHE
        !          10576:                validate_dcache030();
        !          10577: #endif
1.1.1.7   root     10578:        }
1.1.1.9 ! root     10579: }
1.1.1.7   root     10580: 
1.1.1.9 ! root     10581: void write_dcache030_bput(uaecptr addr, uae_u32 v,uae_u32 fc)
        !          10582: {
        !          10583: //fprintf ( stderr , "write dcache %x %x %d\n" , addr , v , size );
        !          10584:        regs.fc030 = fc;
        !          10585:        dcache_bput(addr, v);
        !          10586:        write_dcache030x(addr, v, 0, fc);
        !          10587: }
        !          10588: void write_dcache030_wput(uaecptr addr, uae_u32 v,uae_u32 fc)
        !          10589: {
        !          10590:        regs.fc030 = fc;
        !          10591:        dcache_wput(addr, v);
        !          10592:        write_dcache030x(addr, v, 1, fc);
        !          10593: }
        !          10594: void write_dcache030_lput(uaecptr addr, uae_u32 v,uae_u32 fc)
        !          10595: {
        !          10596:        regs.fc030 = fc;
        !          10597:        dcache_lput(addr, v);
        !          10598:        write_dcache030x(addr, v, 2, fc);
        !          10599: }
1.1.1.7   root     10600: 
1.1.1.9 ! root     10601: static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
        !          10602: {
        !          10603:        if ((c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1) && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
        !          10604:                // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
        !          10605:                int i;
        !          10606:                uaecptr baddr = addr & ~15;
        !          10607:                for (i = 0; i < 4; i++) {
        !          10608:                        if (c->valid[i])
        !          10609:                                break;
1.1.1.4   root     10610:                }
1.1.1.9 ! root     10611:                if (currprefs.mmu_model) {
        !          10612:                        TRY (prb) {
        !          10613:                                if (currprefs.cpu_cycle_exact)
        !          10614: #ifndef WINUAE_FOR_HATARI
        !          10615:                                        do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1));
        !          10616: #else
        !          10617:                                        do_cycles_ce020_long(3 * (CPU020_MEM_CYCLE - 1));
        !          10618: #endif
        !          10619:                                int j;
        !          10620:                                for (j = 0; j < 3; j++) {
        !          10621:                                        i++;
        !          10622:                                        i &= 3;
        !          10623:                                        c->data[i] = dcache_lget (baddr + i * 4);
        !          10624:                                        c->valid[i] = true;
        !          10625:                                }
        !          10626:                        } CATCH (prb) {
        !          10627:                                ; // abort burst fetch if bus error
        !          10628:                        } ENDTRY
        !          10629:                } else {
        !          10630:                        int j;
        !          10631:                        for (j = 0; j < 3; j++) {
        !          10632:                                i++;
        !          10633:                                i &= 3;
        !          10634:                                c->data[i] = dcache_lget (baddr + i * 4);
        !          10635:                                c->valid[i] = true;
        !          10636:                        }
        !          10637:                        if (currprefs.cpu_cycle_exact)
        !          10638:                                do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[i]);
        !          10639:                }
        !          10640: #if VALIDATE_68030_DATACACHE
        !          10641:                validate_dcache030();
        !          10642: #endif
1.1.1.4   root     10643:        }
                   10644: }
                   10645: 
1.1.1.9 ! root     10646: static uae_u32 read_dcache030_debug(uaecptr addr, uae_u32 size, uae_u32 fc, bool *cached)
1.1.1.7   root     10647: {
1.1.1.9 ! root     10648:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
        !          10649:        struct cache030 *c1, *c2;
        !          10650:        int lws1, lws2;
        !          10651:        uae_u32 tag1, tag2;
        !          10652:        int aligned = addr & 3;
        !          10653:        uae_u32 v1, v2;
        !          10654:        int width = 8 << size;
        !          10655:        int offset = 8 * aligned;
        !          10656:        uae_u32 out;
        !          10657: 
        !          10658:        *cached = false;
        !          10659:        if (!currprefs.cpu_data_cache) {
        !          10660:                if (size == 0)
        !          10661:                        return get_byte_debug(addr);
        !          10662:                if (size == 1)
        !          10663:                        return get_word_debug(addr);
        !          10664:                return get_long_debug(addr);
        !          10665:        }
        !          10666: 
        !          10667:        c1 = getdcache030(dcaches030, addr, &tag1, &lws1);
        !          10668:        addr &= ~3;
        !          10669:        if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) {
        !          10670:                v1 = get_long_debug(addr);
1.1.1.7   root     10671:        } else {
1.1.1.9 ! root     10672:                // Cache hit, inhibited caching do not prevent read hits.
        !          10673:                v1 = c1->data[lws1];
        !          10674:                *cached = true;
        !          10675:        }
        !          10676: 
        !          10677:        // only one long fetch needed?
        !          10678:        if (width + offset <= 32) {
        !          10679:                out = v1 >> (32 - (offset + width));
        !          10680:                out &= mask[size];
        !          10681:                return out;
        !          10682:        }
        !          10683: 
        !          10684:        // no, need another one
        !          10685:        addr += 4;
        !          10686:        c2 = getdcache030(dcaches030, addr, &tag2, &lws2);
        !          10687:        if (!c2->valid[lws2] || c2->tag != tag2 || c2->fc != fc) {
        !          10688:                v2 = get_long_debug(addr);
        !          10689:        } else {
        !          10690:                v2 = c2->data[lws2];
        !          10691:                *cached = true;
1.1.1.7   root     10692:        }
1.1.1.9 ! root     10693: 
        !          10694:        uae_u64 v64 = ((uae_u64)v1 << 32) | v2;
        !          10695:        out = (uae_u32)(v64 >> (64 - (offset + width)));
        !          10696:        out &= mask[size];
        !          10697:        return out;
1.1.1.7   root     10698: }
                   10699: 
                   10700: // [HATARI] Define next line to check for 68030 data cache mismatch after every write
                   10701: //#define WINUAE_FOR_HATARI_DEBUG_CACHE
                   10702: #ifdef WINUAE_FOR_HATARI_DEBUG_CACHE
1.1.1.9 ! root     10703: uae_u32 read_dcache030_0 (uaecptr addr, uae_u32 size, uae_u32 fc);
        !          10704: static uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
1.1.1.7   root     10705: {
                   10706:   uae_u32 v;
                   10707: 
1.1.1.9 ! root     10708:   v = read_dcache030_0 ( addr , size , fc );
        !          10709:   if (!(regs.cacr & 0x100))
1.1.1.7   root     10710:     return v;
                   10711:   if ( ( ( size==2 ) && ( v != get_long ( addr ) ) )
                   10712:     || ( ( size==1 ) && ( (v&0xffff) != (get_word ( addr ) & 0xffff) ) )
                   10713:     || ( ( size==0 ) && ( (v&0xff) != (get_byte ( addr ) & 0xff ) ) ) )
                   10714:     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) );
                   10715:   return v;
                   10716: }
1.1.1.9 ! root     10717: uae_u32 read_dcache030_0 (uaecptr addr, uae_u32 size, uae_u32 fc)
1.1.1.7   root     10718: #else
1.1.1.9 ! root     10719: static uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
1.1.1.7   root     10720: #endif
1.1.1.4   root     10721: {
1.1.1.9 ! root     10722:        uae_u32 addr_o = addr;
        !          10723:        regs.fc030 = fc;
        !          10724:        if (regs.cacr & 0x100) { // data cache enabled?
        !          10725:                static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
        !          10726:                struct cache030 *c1, *c2;
        !          10727:                int lws1, lws2;
        !          10728:                uae_u32 tag1, tag2;
        !          10729:                int aligned = addr & 3;
        !          10730:                uae_u32 v1, v2;
        !          10731:                int width = 8 << size;
        !          10732:                int offset = 8 * aligned;
        !          10733:                uae_u32 out;
        !          10734: 
        !          10735:                c1 = getdcache030 (dcaches030, addr, &tag1, &lws1);
        !          10736:                addr &= ~3;
        !          10737:                if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) {
        !          10738:                        // MMU validate address, returns zero if valid but uncacheable
        !          10739:                        // throws bus error if invalid
        !          10740:                        uae_u8 cs = dcache_check(addr_o, false, size);
        !          10741:                        if (!(cs & CACHE_ENABLE_DATA))
        !          10742:                                goto end;
        !          10743:                        v1 = dcache_lget(addr);
        !          10744:                        update_dcache030 (c1, v1, tag1, fc, lws1);
        !          10745:                        if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100)
        !          10746:                                dcache030_maybe_burst(addr, c1, lws1);
        !          10747: #if VALIDATE_68030_DATACACHE
        !          10748:                        validate_dcache030();
        !          10749: #endif
        !          10750: //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) );
        !          10751: #ifdef WINUAE_FOR_HATARI
        !          10752:                CpuInstruction.D_Cache_miss++;
        !          10753: #endif
1.1.1.7   root     10754:                } else {
1.1.1.9 ! root     10755:                        // Cache hit, inhibited caching do not prevent read hits.
        !          10756:                        v1 = c1->data[lws1];
1.1.1.7   root     10757: #ifdef WINUAE_FOR_HATARI
                   10758:                CpuInstruction.D_Cache_hit++;
                   10759: #endif
                   10760:                }
1.1.1.9 ! root     10761: 
        !          10762:                // only one long fetch needed?
        !          10763:                if (width + offset <= 32) {
        !          10764:                        out = v1 >> (32 - (offset + width));
        !          10765:                        out &= mask[size];
        !          10766: #if VALIDATE_68030_DATACACHE
        !          10767:                        validate_dcache030_read(addr_o, out, size);
        !          10768: #endif
        !          10769:                        return out;
        !          10770:                }
        !          10771: 
        !          10772:                // no, need another one
        !          10773:                addr += 4;
        !          10774:                c2 = getdcache030 (dcaches030, addr, &tag2, &lws2);
        !          10775:                if (!c2->valid[lws2] || c2->tag != tag2 || c2->fc != fc) {
        !          10776:                        uae_u8 cs = dcache_check(addr, false, 2);
        !          10777:                        if (!(cs & CACHE_ENABLE_DATA))
        !          10778:                                goto end;
        !          10779:                        v2 = dcache_lget(addr);
        !          10780:                        update_dcache030 (c2, v2, tag2, fc, lws2);
        !          10781:                        if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100)
        !          10782:                                dcache030_maybe_burst(addr, c2, lws2);
        !          10783: #if VALIDATE_68030_DATACACHE
        !          10784:                        validate_dcache030();
        !          10785: #endif
1.1.1.7   root     10786: //fprintf ( stderr , "read cache %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x\n", addr, v1, size, tag1, lws1, tag2, lws2 );
                   10787: #ifdef WINUAE_FOR_HATARI
                   10788:                CpuInstruction.D_Cache_miss++;
                   10789: #endif
1.1.1.9 ! root     10790:                } else {
        !          10791:                        v2 = c2->data[lws2];
        !          10792: #ifdef WINUAE_FOR_HATARI
1.1.1.7   root     10793:                CpuInstruction.D_Cache_hit++;
                   10794: #endif
1.1.1.9 ! root     10795:                }
        !          10796: 
        !          10797:                uae_u64 v64 = ((uae_u64)v1 << 32) | v2;
        !          10798:                out = (uae_u32)(v64 >> (64 - (offset + width)));
        !          10799:                out &= mask[size];
        !          10800: 
        !          10801: #if VALIDATE_68030_DATACACHE
        !          10802:                validate_dcache030_read(addr_o, out, size);
        !          10803: #endif
        !          10804:                return out;
        !          10805: 
        !          10806:        }
        !          10807: end:
        !          10808:        // read from memory, data cache is disabled or inhibited.
        !          10809:        if (size == 2)
        !          10810:                return dcache_lget (addr_o);
        !          10811:        else if (size == 1)
        !          10812:                return dcache_wget (addr_o);
        !          10813:        else
        !          10814:                return dcache_bget (addr_o);
        !          10815: }
        !          10816: uae_u32 read_dcache030_bget(uaecptr addr, uae_u32 fc)
        !          10817: {
        !          10818:        return read_dcache030(addr, 0, fc);
        !          10819: }
        !          10820: uae_u32 read_dcache030_wget(uaecptr addr, uae_u32 fc)
        !          10821: {
        !          10822:        return read_dcache030(addr, 1, fc);
        !          10823: }
        !          10824: uae_u32 read_dcache030_lget(uaecptr addr, uae_u32 fc)
        !          10825: {
        !          10826:        return read_dcache030(addr, 2, fc);
        !          10827: }
1.1.1.7   root     10828: 
1.1.1.9 ! root     10829: uae_u32 read_dcache030_mmu_bget(uaecptr addr)
        !          10830: {
        !          10831:        return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
        !          10832: }
        !          10833: uae_u32 read_dcache030_mmu_wget(uaecptr addr)
        !          10834: {
        !          10835:        return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
        !          10836: }
        !          10837: uae_u32 read_dcache030_mmu_lget(uaecptr addr)
        !          10838: {
        !          10839:        return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
        !          10840: }
        !          10841: void write_dcache030_mmu_bput(uaecptr addr, uae_u32 val)
        !          10842: {
        !          10843:        write_dcache030_bput(addr, val, (regs.s ? 4 : 0) | 1);
        !          10844: }
        !          10845: void write_dcache030_mmu_wput(uaecptr addr, uae_u32 val)
        !          10846: {
        !          10847:        write_dcache030_wput(addr, val, (regs.s ? 4 : 0) | 1);
        !          10848: }
        !          10849: void write_dcache030_mmu_lput(uaecptr addr, uae_u32 val)
        !          10850: {
        !          10851:        write_dcache030_lput(addr, val, (regs.s ? 4 : 0) | 1);
        !          10852: }
1.1.1.4   root     10853: 
1.1.1.9 ! root     10854: uae_u32 read_dcache030_lrmw_mmu(uaecptr addr, uae_u32 size)
        !          10855: {
        !          10856:        if (currprefs.cpu_data_cache) {
        !          10857:                mmu030_cache_state = CACHE_DISABLE_MMU;
        !          10858:                if (size == 0)
        !          10859:                        return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
        !          10860:                if (size == 1)
        !          10861:                        return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
        !          10862:                return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
        !          10863:        } else {
        !          10864:                if (size == 0)
        !          10865:                        return read_data_030_bget(addr);
        !          10866:                if (size == 1)
        !          10867:                        return read_data_030_wget(addr);
        !          10868:                return read_data_030_lget(addr);
        !          10869:        }
        !          10870: }
        !          10871: void write_dcache030_lrmw_mmu(uaecptr addr, uae_u32 val, uae_u32 size)
        !          10872: {
        !          10873:        if (currprefs.cpu_data_cache) {
        !          10874:                mmu030_cache_state = CACHE_DISABLE_MMU;
        !          10875:                if (size == 0)
        !          10876:                        write_dcache030_bput(addr, val, (regs.s ? 4 : 0) | 1);
        !          10877:                else if (size == 1)
        !          10878:                        write_dcache030_wput(addr, val, (regs.s ? 4 : 0) | 1);
        !          10879:                else
        !          10880:                        write_dcache030_lput(addr, val, (regs.s ? 4 : 0) | 1);
        !          10881:        } else {
        !          10882:                if (size == 0)
        !          10883:                        write_data_030_bput(addr, val);
        !          10884:                else if (size == 1)
        !          10885:                        write_data_030_wput(addr, val);
        !          10886:                else
        !          10887:                        write_data_030_lput(addr, val);
        !          10888:        }
1.1.1.4   root     10889: }
                   10890: 
1.1.1.9 ! root     10891: static void do_access_or_bus_error(uaecptr pc, uaecptr pcnow)
        !          10892: {
        !          10893:        // TODO: handle external bus errors
        !          10894:        if (!currprefs.mmu_model)
        !          10895:                return;
        !          10896:        if (pc != 0xffffffff)
        !          10897:                regs.instruction_pc = pc;
        !          10898:        mmu030_opcode = -1;
        !          10899:        mmu030_page_fault(pcnow, true, -1, 0);
        !          10900: }
        !          10901: 
        !          10902: static uae_u32 get_word_ce030_prefetch_2 (int o)
1.1.1.4   root     10903: {
                   10904:        uae_u32 pc = m68k_getpc () + o;
1.1.1.7   root     10905:        uae_u32 v;
1.1.1.4   root     10906: 
1.1.1.9 ! root     10907: //fprintf ( stderr , "get_word_ce030_prefetch_2 %d pc=%x\n" , currcycle , pc);
        !          10908:        v = regs.prefetch020[0];
        !          10909:        regs.prefetch020[0] = regs.prefetch020[1];
        !          10910:        regs.prefetch020[1] = regs.prefetch020[2];
1.1.1.7   root     10911: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9 ! root     10912:        pipeline_020(pc);
1.1.1.7   root     10913: #endif
1.1.1.9 ! root     10914:        if (pc & 2) {
1.1.1.7   root     10915:                // branch instruction detected in pipeline: stop fetches until branch executed.
                   10916:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
                   10917:                        fill_icache030 (pc + 2 + 4);
1.1.1.9 ! root     10918:                } else {
        !          10919:                        if (regs.cacheholdingdata_valid > 0)
        !          10920:                                regs.cacheholdingdata_valid++;
1.1.1.7   root     10921:                }
1.1.1.9 ! root     10922:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     10923:        } else {
1.1.1.9 ! root     10924:                pc += 4;
        !          10925:                // cacheholdingdata020 may be invalid if RTE from bus error
        !          10926:                if ((!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) && regs.cacheholdingaddr020 != pc) {
        !          10927:                        fill_icache030 (pc);
        !          10928:                }
        !          10929:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.7   root     10930:        }
1.1.1.9 ! root     10931:        regs.db = regs.prefetch020[0];
1.1.1.7   root     10932:        do_cycles_ce020_internal (2);
                   10933:        return v;
                   10934: }
                   10935: 
1.1.1.9 ! root     10936: uae_u32 get_word_ce030_prefetch (int o)
        !          10937: {
        !          10938:        return get_word_ce030_prefetch_2(o);
        !          10939: }
        !          10940: uae_u32 get_word_ce030_prefetch_opcode (int o)
        !          10941: {
        !          10942:        return get_word_ce030_prefetch_2(o);
        !          10943: }
        !          10944: 
        !          10945: uae_u32 get_word_030_prefetch (int o)
1.1.1.7   root     10946: {
1.1.1.9 ! root     10947:        uae_u32 pc = m68k_getpc () + o;
1.1.1.7   root     10948:        uae_u32 v;
                   10949: 
1.1.1.9 ! root     10950:        v = regs.prefetch020[0];
        !          10951:        regs.prefetch020[0] = regs.prefetch020[1];
        !          10952:        regs.prefetch020[1] = regs.prefetch020[2];
        !          10953:        regs.prefetch020_valid[0] = regs.prefetch020_valid[1];
        !          10954:        regs.prefetch020_valid[1] = regs.prefetch020_valid[2];
        !          10955:        regs.prefetch020_valid[2] = false;
        !          10956:        if (!regs.prefetch020_valid[1]) {
        !          10957:                do_access_or_bus_error(0xffffffff, pc + 4);
        !          10958:        }
1.1.1.7   root     10959: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9 ! root     10960:        pipeline_020(pc);
1.1.1.7   root     10961: #endif
1.1.1.9 ! root     10962:        if (pc & 2) {
1.1.1.7   root     10963:                // branch instruction detected in pipeline: stop fetches until branch executed.
                   10964:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
1.1.1.9 ! root     10965:                        fill_icache030 (pc + 2 + 4);
        !          10966:                } else {
        !          10967:                        if (regs.cacheholdingdata_valid > 0)
        !          10968:                                regs.cacheholdingdata_valid++;
1.1.1.7   root     10969:                }
1.1.1.9 ! root     10970:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     10971:        } else {
1.1.1.9 ! root     10972:                pc += 4;
        !          10973:                // cacheholdingdata020 may be invalid if RTE from bus error
        !          10974:                if ((!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) && regs.cacheholdingaddr020 != pc) {
        !          10975:                        fill_icache030 (pc);
        !          10976:                }
        !          10977:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.7   root     10978:        }
1.1.1.9 ! root     10979:        regs.prefetch020_valid[2] = regs.cacheholdingdata_valid;
        !          10980:        regs.db = regs.prefetch020[0];
        !          10981: //if ( ( v & 0xffff ) != ( get_word(pc) & 0xffff ) )
        !          10982: //  fprintf ( stderr , "prefetch mismatch pc=%x prefetch=%x != mem=%x, i-cache error ?\n" , pc , v&0xffff , get_word(pc)&0xffff );
1.1.1.7   root     10983:        return v;
                   10984: }
                   10985: 
                   10986: uae_u32 get_word_icache030(uaecptr addr)
                   10987: {
                   10988:        fill_icache030(addr);
                   10989:        return regs.cacheholdingdata020 >> ((addr & 2) ? 0 : 16);
                   10990: }
                   10991: uae_u32 get_long_icache030(uaecptr addr)
                   10992: {
                   10993:        uae_u32 v;
                   10994:        fill_icache030(addr);
                   10995:        if ((addr & 2) == 0)
                   10996:                return regs.cacheholdingdata020;
                   10997:        v = regs.cacheholdingdata020 << 16;
                   10998:        fill_icache030(addr + 4);
                   10999:        v |= regs.cacheholdingdata020 >> 16;
                   11000:        return v;
                   11001: }
                   11002: 
1.1.1.9 ! root     11003: uae_u32 fill_icache040(uae_u32 addr)
        !          11004: {
        !          11005:        int index, lws;
        !          11006:        uae_u32 tag, addr2;
        !          11007:        struct cache040 *c;
        !          11008:        int line;
        !          11009:        int i;
        !          11010: 
        !          11011:        addr2 = addr & ~15;
        !          11012:        lws = (addr >> 2) & 3;
        !          11013: 
        !          11014:        if (regs.prefetch020addr == addr2) {
        !          11015:                return regs.prefetch040[lws];
        !          11016:        }
        !          11017: 
        !          11018:        if (regs.cacr & 0x8000) {
        !          11019:                uae_u8 cs = mmu_cache_state;
        !          11020: 
        !          11021:                if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_INS))
        !          11022:                        cs = CACHE_DISABLE_MMU;
        !          11023: 
        !          11024:                index = (addr >> 4) & cacheisets04060mask;
        !          11025:                tag = addr & cacheitag04060mask;
        !          11026:                c = &icaches040[index];
        !          11027:                for (i = 0; i < CACHELINES040; i++) {
        !          11028:                        if (c->valid[cache_lastline] && c->tag[cache_lastline] == tag) {
        !          11029:                                // cache hit
        !          11030:                                if (!(cs & CACHE_ENABLE_INS) || (cs & CACHE_DISABLE_MMU)) {
        !          11031:                                        c->valid[cache_lastline] = false;
        !          11032:                                        goto end;
        !          11033:                                }
        !          11034:                                if ((lws & 1) != icachehalfline) {
        !          11035:                                        icachehalfline ^= 1;
        !          11036:                                        icachelinecnt++;
        !          11037: #ifdef WINUAE_FOR_HATARI
        !          11038:                                CpuInstruction.I_Cache_hit++;
        !          11039: #endif
        !          11040:                                }
        !          11041:                                return c->data[cache_lastline][lws];
        !          11042:                        }
        !          11043:                        cache_lastline++;
        !          11044:                        cache_lastline &= (CACHELINES040 - 1);
        !          11045:                }
        !          11046:                // cache miss
        !          11047:                regs.prefetch020addr = 0xffffffff;
        !          11048:                regs.prefetch040[0] = icache_fetch(addr2 +  0);
        !          11049:                regs.prefetch040[1] = icache_fetch(addr2 +  4);
        !          11050:                regs.prefetch040[2] = icache_fetch(addr2 +  8);
        !          11051:                regs.prefetch040[3] = icache_fetch(addr2 + 12);
        !          11052:                regs.prefetch020addr = addr2;
        !          11053:                if (!(cs & CACHE_ENABLE_INS) || (cs & CACHE_DISABLE_MMU))
        !          11054:                        goto end;
        !          11055:                if (regs.cacr & 0x00004000) // 68060 NAI
        !          11056:                        goto end;
        !          11057:                if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
        !          11058:                        line = icachelinecnt & (CACHELINES040 - 1);
        !          11059:                        icachehalfline = (lws & 1) ? 0 : 1;
        !          11060:                } else {
        !          11061:                        for (line = 0; line < CACHELINES040; line++) {
        !          11062:                                if (c->valid[line] == false)
        !          11063:                                        break;
        !          11064:                        }
        !          11065:                }
        !          11066:                c->tag[line] = tag;
        !          11067:                c->valid[line] = true;
        !          11068:                c->data[line][0] = regs.prefetch040[0];
        !          11069:                c->data[line][1] = regs.prefetch040[1];
        !          11070:                c->data[line][2] = regs.prefetch040[2];
        !          11071:                c->data[line][3] = regs.prefetch040[3];
        !          11072:                if ((lws & 1) != icachehalfline) {
        !          11073:                        icachehalfline ^= 1;
        !          11074:                        icachelinecnt++;
        !          11075:                }
        !          11076: #ifdef WINUAE_FOR_HATARI
        !          11077:                CpuInstruction.I_Cache_miss++;
        !          11078: #endif
        !          11079:                return c->data[line][lws];
        !          11080: 
        !          11081:        }
        !          11082: 
        !          11083: end:
        !          11084:        if (regs.prefetch020addr == addr2)
        !          11085:                return regs.prefetch040[lws];
        !          11086:        regs.prefetch020addr = addr2;
        !          11087:        regs.prefetch040[0] = icache_fetch(addr2 +  0);
        !          11088:        regs.prefetch040[1] = icache_fetch(addr2 +  4);
        !          11089:        regs.prefetch040[2] = icache_fetch(addr2 +  8);
        !          11090:        regs.prefetch040[3] = icache_fetch(addr2 + 12);
        !          11091:        return regs.prefetch040[lws];
        !          11092: }
        !          11093: 
        !          11094: STATIC_INLINE void do_cycles_c040_mem (int clocks, uae_u32 val)
        !          11095: {
        !          11096:        x_do_cycles_post (clocks * cpucycleunit, val);
        !          11097: }
        !          11098: 
        !          11099: uae_u32 mem_access_delay_longi_read_c040 (uaecptr addr)
        !          11100: {
        !          11101:        uae_u32 v;
        !          11102:        switch (ce_banktype[addr >> 16])
        !          11103:        {
        !          11104:        case CE_MEMBANK_CHIP16:
        !          11105:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          11106:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          11107:                break;
        !          11108:        case CE_MEMBANK_CHIP32:
        !          11109:                if ((addr & 3) != 0) {
        !          11110:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          11111:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          11112:                } else {
        !          11113:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
        !          11114:                }
        !          11115:                break;
        !          11116:        case CE_MEMBANK_FAST16:
        !          11117:                v = get_longi (addr);
        !          11118:                do_cycles_c040_mem(1, v);
        !          11119:                break;
        !          11120:        case CE_MEMBANK_FAST32:
        !          11121:                v = get_longi (addr);
        !          11122:                break;
        !          11123:        default:
        !          11124:                v = get_longi (addr);
        !          11125:                break;
        !          11126:        }
        !          11127:        return v;
        !          11128: }
        !          11129: uae_u32 mem_access_delay_long_read_c040 (uaecptr addr)
        !          11130: {
        !          11131:        uae_u32 v;
        !          11132:        switch (ce_banktype[addr >> 16])
        !          11133:        {
        !          11134:        case CE_MEMBANK_CHIP16:
        !          11135:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          11136:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          11137:                break;
        !          11138:        case CE_MEMBANK_CHIP32:
        !          11139:                if ((addr & 3) != 0) {
        !          11140:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
        !          11141:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
        !          11142:                } else {
        !          11143:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
        !          11144:                }
        !          11145:                break;
        !          11146:        case CE_MEMBANK_FAST16:
        !          11147:                v = get_long (addr);
        !          11148:                do_cycles_c040_mem(1, v);
        !          11149:                break;
        !          11150:        case CE_MEMBANK_FAST32:
        !          11151:                v = get_long (addr);
        !          11152:                break;
        !          11153:        default:
        !          11154:                v = get_long (addr);
        !          11155:                break;
        !          11156:        }
        !          11157:        return v;
        !          11158: }
        !          11159: 
        !          11160: uae_u32 mem_access_delay_word_read_c040 (uaecptr addr)
        !          11161: {
        !          11162:        uae_u32 v;
        !          11163:        switch (ce_banktype[addr >> 16])
        !          11164:        {
        !          11165:        case CE_MEMBANK_CHIP16:
        !          11166:        case CE_MEMBANK_CHIP32:
        !          11167:                if ((addr & 3) == 3) {
        !          11168:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
        !          11169:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
        !          11170:                } else {
        !          11171:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
        !          11172:                }
        !          11173:                break;
        !          11174:        case CE_MEMBANK_FAST16:
        !          11175:                v = get_word (addr);
        !          11176:                do_cycles_c040_mem (2, v);
        !          11177:                break;
        !          11178:        case CE_MEMBANK_FAST32:
        !          11179:                v = get_word (addr);
        !          11180:                 break;
        !          11181:        default:
        !          11182:                 v = get_word (addr);
        !          11183:                break;
        !          11184:        }
        !          11185:        return v;
        !          11186: }
        !          11187: 
        !          11188: uae_u32 mem_access_delay_byte_read_c040 (uaecptr addr)
        !          11189: {
        !          11190:        uae_u32 v;
        !          11191:        switch (ce_banktype[addr >> 16])
        !          11192:        {
        !          11193:        case CE_MEMBANK_CHIP16:
        !          11194:        case CE_MEMBANK_CHIP32:
        !          11195:                v = wait_cpu_cycle_read_ce020 (addr, 0);
        !          11196:                break;
        !          11197:        case CE_MEMBANK_FAST16:
        !          11198:                v = get_byte (addr);
        !          11199:                do_cycles_c040_mem (1, v);
        !          11200:                break;
        !          11201:        case CE_MEMBANK_FAST32:
        !          11202:                v = get_byte (addr);
        !          11203:                break;
        !          11204:        default:
        !          11205:                v = get_byte (addr);
        !          11206:                break;
        !          11207:        }
        !          11208:        return v;
        !          11209: }
        !          11210: 
        !          11211: void mem_access_delay_byte_write_c040 (uaecptr addr, uae_u32 v)
        !          11212: {
        !          11213:        switch (ce_banktype[addr >> 16])
        !          11214:        {
        !          11215:        case CE_MEMBANK_CHIP16:
        !          11216:        case CE_MEMBANK_CHIP32:
        !          11217:                wait_cpu_cycle_write_ce020 (addr, 0, v);
        !          11218:                break;
        !          11219:        case CE_MEMBANK_FAST16:
        !          11220:                put_byte (addr, v);
        !          11221:                do_cycles_c040_mem (1, v);
        !          11222:                break;
        !          11223:        case CE_MEMBANK_FAST32:
        !          11224:                put_byte (addr, v);
        !          11225:                break;
        !          11226:        default:
        !          11227:                put_byte (addr, v);
        !          11228:        break;
        !          11229:        }
        !          11230: }
        !          11231: 
        !          11232: void mem_access_delay_word_write_c040 (uaecptr addr, uae_u32 v)
        !          11233: {
        !          11234:        switch (ce_banktype[addr >> 16])
        !          11235:        {
        !          11236:        case CE_MEMBANK_CHIP16:
        !          11237:        case CE_MEMBANK_CHIP32:
        !          11238:                if ((addr & 3) == 3) {
        !          11239:                        wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
        !          11240:                        wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
        !          11241:                } else {
        !          11242:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
        !          11243:                }
        !          11244:                break;
        !          11245:        case CE_MEMBANK_FAST16:
        !          11246:                put_word (addr, v);
        !          11247:                if ((addr & 3) == 3)
        !          11248:                        do_cycles_c040_mem(2, v);
        !          11249:                else
        !          11250:                        do_cycles_c040_mem(1, v);
        !          11251:                break;
        !          11252:        case CE_MEMBANK_FAST32:
        !          11253:                put_word (addr, v);
        !          11254:                break;
        !          11255:        default:
        !          11256:                put_word (addr, v);
        !          11257:        break;
        !          11258:        }
        !          11259: }
        !          11260: 
        !          11261: void mem_access_delay_long_write_c040 (uaecptr addr, uae_u32 v)
        !          11262: {
        !          11263:        switch (ce_banktype[addr >> 16])
        !          11264:        {
        !          11265:        case CE_MEMBANK_CHIP16:
        !          11266:                wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
        !          11267:                wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
        !          11268:                break;
        !          11269:        case CE_MEMBANK_CHIP32:
        !          11270:                if ((addr & 3) == 3) {
        !          11271:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
        !          11272:                        wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
        !          11273:                } else {
        !          11274:                        wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
        !          11275:                }
        !          11276:                break;
        !          11277:        case CE_MEMBANK_FAST16:
        !          11278:                put_long (addr, v);
        !          11279:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
        !          11280:                break;
        !          11281:        case CE_MEMBANK_FAST32:
        !          11282:                put_long (addr, v);
        !          11283:                break;
        !          11284:        default:
        !          11285:                put_long (addr, v);
        !          11286:                break;
        !          11287:        }
        !          11288: }
        !          11289: 
        !          11290: static uae_u32 dcache040_get_data(uaecptr addr, struct cache040 *c, int line, int size)
1.1.1.7   root     11291: {
1.1.1.9 ! root     11292:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
        !          11293:        int offset = (addr & 15) * 8;
        !          11294:        int offset32 = offset & 31;
        !          11295:        int slot = offset / 32;
        !          11296:        int width = 8 << size;
        !          11297:        uae_u32 vv;
        !          11298: 
        !          11299:        if (offset32 + width <= 32) {
        !          11300:                uae_u32 v = c->data[line][slot];
        !          11301:                v >>= 32 - (offset32 + width);
        !          11302:                v &= mask[size];
        !          11303:                vv = v;
        !          11304:        } else {
        !          11305: #if VALIDATE_68040_DATACACHE
        !          11306:                if (slot >= 3) {
        !          11307:                        write_log(_T("invalid dcache040_get_data!\n"));
        !          11308:                        return 0;
1.1.1.7   root     11309:                }
1.1.1.9 ! root     11310: #endif
        !          11311:                uae_u64 v = c->data[line][slot];
        !          11312:                v <<= 32;
        !          11313:                v |= c->data[line][slot + 1];
        !          11314:                v >>= 64 - (offset32 + width);
        !          11315:                vv = v & mask[size];
1.1.1.7   root     11316:        }
1.1.1.9 ! root     11317:        return vv;
        !          11318: }
1.1.1.7   root     11319: 
1.1.1.9 ! root     11320: static void dcache040_update(uaecptr addr, struct cache040 *c, int line, uae_u32 val, int size)
        !          11321: {
        !          11322:        static const uae_u64 mask64[3] = { 0xff, 0xffff, 0xffffffff };
        !          11323:        static const uae_u32 mask32[3] = { 0xff, 0xffff, 0xffffffff };
        !          11324:        int offset = (addr & 15) * 8;
        !          11325:        int offset32 = offset & 31;
        !          11326:        int slot = offset / 32;
        !          11327:        int width = 8 << size;
        !          11328: 
        !          11329: #if VALIDATE_68040_DATACACHE > 1
        !          11330:        validate_dcache040();
1.1.1.7   root     11331: #endif
1.1.1.9 ! root     11332: 
        !          11333:        if (offset32 + width <= 32) {
        !          11334:                int shift = 32 - (offset32 + width);
        !          11335:                uae_u32 v = c->data[line][slot];
        !          11336:                v &= ~(mask32[size] << shift);
        !          11337:                v |= val << shift;
        !          11338:                c->data[line][slot] = v;
        !          11339:                c->dirty[line][slot] = true;
        !          11340:        } else {
        !          11341: #if VALIDATE_68040_DATACACHE
        !          11342:                if (slot >= 3) {
        !          11343:                        write_log(_T("invalid dcache040_update!\n"));
        !          11344:                        return;
1.1.1.7   root     11345:                }
1.1.1.9 ! root     11346: #endif
        !          11347:                int shift = 64 - (offset32 + width);
        !          11348:                uae_u64 v = c->data[line][slot];
        !          11349:                v <<= 32;
        !          11350:                v |= c->data[line][slot + 1];
        !          11351:                v &= ~(mask64[size] << shift);
        !          11352:                v |= ((uae_u64)val) << shift;
        !          11353:                c->data[line][slot] = v >> 32;
        !          11354:                c->dirty[line][slot] = true;
        !          11355:                c->data[line][slot + 1] = (uae_u32)v;
        !          11356:                c->dirty[line][slot + 1] = true;
1.1.1.7   root     11357:        }
1.1.1.9 ! root     11358:        c->gdirty[line] = true;
        !          11359: }
        !          11360: 
        !          11361: static int dcache040_fill_line(int index, uae_u32 tag, uaecptr addr)
        !          11362: {
1.1.1.7   root     11363:        // cache miss
1.1.1.9 ! root     11364:        struct cache040 *c = &dcaches040[index];
        !          11365:        int line;
1.1.1.7   root     11366:        if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
1.1.1.9 ! root     11367:                // all lines allocated, choose one, push and invalidate.
        !          11368:                line = dcachelinecnt & (CACHELINES040 - 1);
        !          11369:                dcachelinecnt++;
        !          11370:                dcache040_push_line(index, line, false, true);
        !          11371:        } else {
        !          11372:                // at least one invalid
1.1.1.7   root     11373:                for (line = 0; line < CACHELINES040; line++) {
                   11374:                        if (c->valid[line] == false)
                   11375:                                break;
                   11376:                }
                   11377:        }
                   11378:        c->tag[line] = tag;
1.1.1.9 ! root     11379:        c->dirty[line][0] = false;
        !          11380:        c->dirty[line][1] = false;
        !          11381:        c->dirty[line][2] = false;
        !          11382:        c->dirty[line][3] = false;
        !          11383:        c->gdirty[line] = false;
        !          11384:        c->data[line][0] = dcache_lget(addr + 0);
        !          11385:        c->data[line][1] = dcache_lget(addr + 4);
        !          11386:        c->data[line][2] = dcache_lget(addr + 8);
        !          11387:        c->data[line][3] = dcache_lget(addr + 12);
1.1.1.7   root     11388:        c->valid[line] = true;
1.1.1.9 ! root     11389:        return line;
1.1.1.7   root     11390: }
                   11391: 
1.1.1.9 ! root     11392: static uae_u32 read_dcache040_debug(uae_u32 addr, int size, bool *cached)
1.1.1.7   root     11393: {
1.1.1.9 ! root     11394:        int index;
1.1.1.7   root     11395:        uae_u32 tag;
                   11396:        struct cache040 *c;
1.1.1.9 ! root     11397:        int line;
        !          11398:        uae_u32 addr_o = addr;
        !          11399:        uae_u8 cs = mmu_cache_state;
        !          11400: 
        !          11401:        *cached = false;
        !          11402:        if (!currprefs.cpu_data_cache)
        !          11403:                goto nocache;
        !          11404:        if (!(regs.cacr & 0x80000000))
        !          11405:                goto nocache;
1.1.1.7   root     11406: 
                   11407:        addr &= ~15;
1.1.1.9 ! root     11408:        index = (addr >> 4) & cachedsets04060mask;
        !          11409:        tag = addr & cachedtag04060mask;
1.1.1.7   root     11410:        c = &dcaches040[index];
1.1.1.9 ! root     11411:        for (line = 0; line < CACHELINES040; line++) {
        !          11412:                if (c->valid[line] && c->tag[line] == tag) {
        !          11413:                        // cache hit
        !          11414:                        return dcache040_get_data(addr_o, c, line, size);
1.1.1.7   root     11415:                }
                   11416:        }
1.1.1.9 ! root     11417: nocache:
        !          11418:        if (size == 0)
        !          11419:                return get_byte_debug(addr);
        !          11420:        if (size == 1)
        !          11421:                return get_word_debug(addr);
        !          11422:        return get_long_debug(addr);
1.1.1.7   root     11423: }
                   11424: 
1.1.1.9 ! root     11425: static uae_u32 read_dcache040(uae_u32 addr, int size, uae_u32 (*fetch)(uaecptr))
1.1.1.7   root     11426: {
1.1.1.9 ! root     11427:        int index;
1.1.1.7   root     11428:        uae_u32 tag;
                   11429:        struct cache040 *c;
                   11430:        int line;
1.1.1.9 ! root     11431:        uae_u32 addr_o = addr;
        !          11432:        uae_u8 cs = mmu_cache_state;
        !          11433: 
        !          11434:        if (!(regs.cacr & 0x80000000))
        !          11435:                goto nocache;
        !          11436: 
        !          11437: #if VALIDATE_68040_DATACACHE > 1
        !          11438:        validate_dcache040();
        !          11439: #endif
        !          11440: 
        !          11441:        // Simple because 68040+ caches physical addresses (68030 caches logical addresses)
        !          11442:        if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_DATA))
        !          11443:                cs = CACHE_DISABLE_MMU;
1.1.1.7   root     11444: 
                   11445:        addr &= ~15;
1.1.1.9 ! root     11446:        index = (addr >> 4) & cachedsets04060mask;
        !          11447:        tag = addr & cachedtag04060mask;
1.1.1.7   root     11448:        c = &dcaches040[index];
1.1.1.9 ! root     11449:        for (line = 0; line < CACHELINES040; line++) {
        !          11450:                if (c->valid[line] && c->tag[line] == tag) {
1.1.1.7   root     11451:                        // cache hit
                   11452:                        dcachelinecnt++;
1.1.1.9 ! root     11453:                        // Cache hit but MMU disabled: do not cache, push and invalidate possible existing line
        !          11454:                        if (cs & CACHE_DISABLE_MMU) {
        !          11455:                                dcache040_push_line(index, line, false, true);
        !          11456:                                goto nocache;
1.1.1.7   root     11457:                        }
1.1.1.9 ! root     11458:                        return dcache040_get_data(addr_o, c, line, size);
1.1.1.7   root     11459:                }
                   11460:        }
1.1.1.9 ! root     11461:        // Cache miss
        !          11462:        // 040+ always caches whole line
        !          11463:        if ((cs & CACHE_DISABLE_MMU) || !(cs & CACHE_ENABLE_DATA) || (cs & CACHE_DISABLE_ALLOCATE) || (regs.cacr & 0x400000000)) {
        !          11464: nocache:
        !          11465:                return fetch(addr_o);
1.1.1.7   root     11466:        }
1.1.1.9 ! root     11467:        // Allocate new cache line, return requested data.
        !          11468:        line = dcache040_fill_line(index, tag, addr);
        !          11469:        return dcache040_get_data(addr_o, c, line, size);
1.1.1.7   root     11470: }
                   11471: 
1.1.1.9 ! root     11472: static void write_dcache040(uae_u32 addr, uae_u32 val, int size, void (*store)(uaecptr, uae_u32))
1.1.1.7   root     11473: {
1.1.1.9 ! root     11474:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
        !          11475:        int index;
1.1.1.7   root     11476:        uae_u32 tag;
                   11477:        struct cache040 *c;
                   11478:        int line;
1.1.1.9 ! root     11479:        uae_u32 addr_o = addr;
        !          11480:        uae_u8 cs = mmu_cache_state;
        !          11481: 
        !          11482:        val &= mask[size];
        !          11483: 
        !          11484:        if (!(regs.cacr & 0x80000000))
        !          11485:                goto nocache;
        !          11486: 
        !          11487:        if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_DATA))
        !          11488:                cs = CACHE_DISABLE_MMU;
1.1.1.7   root     11489: 
                   11490:        addr &= ~15;
1.1.1.9 ! root     11491:        index = (addr >> 4) & cachedsets04060mask;
        !          11492:        tag = addr & cachedtag04060mask;
1.1.1.7   root     11493:        c = &dcaches040[index];
1.1.1.9 ! root     11494:        for (line = 0; line < CACHELINES040; line++) {
        !          11495:                if (c->valid[line] && c->tag[line] == tag) {
1.1.1.7   root     11496:                        // cache hit
                   11497:                        dcachelinecnt++;
1.1.1.9 ! root     11498:                        // Cache hit but MMU disabled: do not cache, push and invalidate possible existing line
        !          11499:                        if (cs & CACHE_DISABLE_MMU) {
        !          11500:                                dcache040_push_line(index, line, false, true);
        !          11501:                                goto nocache;
        !          11502:                        }
        !          11503:                        dcache040_update(addr_o, c, line, val, size);
        !          11504:                        // If not copyback mode: push modifications immediately (write-through)
        !          11505:                        if (!(cs & CACHE_ENABLE_COPYBACK) || DISABLE_68040_COPYBACK) {
        !          11506:                                dcache040_push_line(index, line, true, false);
1.1.1.4   root     11507:                        }
1.1.1.9 ! root     11508:                        return;
1.1.1.4   root     11509:                }
                   11510:        }
1.1.1.9 ! root     11511:        // Cache miss
        !          11512:        // 040+ always caches whole line
        !          11513:        // Writes misses in write-through mode don't allocate new cache lines
        !          11514:        if (!(cs & CACHE_ENABLE_DATA) || (cs & CACHE_DISABLE_MMU) || (cs & CACHE_DISABLE_ALLOCATE) || !(cs & CACHE_ENABLE_COPYBACK) || (regs.cacr & 0x400000000)) {
        !          11515: nocache:
        !          11516:                store(addr_o, val);
        !          11517:                return;
        !          11518:        }
        !          11519:        // Allocate new cache line and update it with new data.
        !          11520:        line = dcache040_fill_line(index, tag, addr);
        !          11521:        dcache040_update(addr_o, c, line, val, size);
        !          11522:        if (DISABLE_68040_COPYBACK) {
        !          11523:                dcache040_push_line(index, line, true, false);
1.1.1.7   root     11524:        }
                   11525: }
                   11526: 
                   11527: // really unoptimized
                   11528: uae_u32 get_word_icache040(uaecptr addr)
                   11529: {
                   11530:        uae_u32 v = fill_icache040(addr);
                   11531:        return v >> ((addr & 2) ? 0 : 16);
                   11532: }
                   11533: uae_u32 get_long_icache040(uaecptr addr)
                   11534: {
                   11535:        uae_u32 v1, v2;
                   11536:        v1 = fill_icache040(addr);
                   11537:        if ((addr & 2) == 0)
                   11538:                return v1;
                   11539:        v2 = fill_icache040(addr + 4);
                   11540:        return (v2 >> 16) | (v1 << 16);
                   11541: }
                   11542: uae_u32 get_ilong_cache_040(int o)
                   11543: {
                   11544:        return get_long_icache040(m68k_getpci() + o);
                   11545: }
                   11546: uae_u32 get_iword_cache_040(int o)
                   11547: {
                   11548:        return get_word_icache040(m68k_getpci() + o);
                   11549: }
                   11550: 
                   11551: void put_long_cache_040(uaecptr addr, uae_u32 v)
                   11552: {
1.1.1.9 ! root     11553:        int offset = addr & 15;
        !          11554:        // access must not cross cachelines
        !          11555:        if (offset < 13) {
        !          11556:                write_dcache040(addr, v, 2, dcache_lput);
        !          11557:        } else if (offset == 13 || offset == 15) {
        !          11558:                write_dcache040(addr + 0, v >> 24, 0, dcache_bput);
        !          11559:                write_dcache040(addr + 1, v >>  8, 1, dcache_wput);
        !          11560:                write_dcache040(addr + 3, v >>  0, 0, dcache_bput);
        !          11561:        } else if (offset == 14) {
        !          11562:                write_dcache040(addr + 0, v >> 16, 1, dcache_wput);
        !          11563:                write_dcache040(addr + 2, v >>  0, 1, dcache_wput);
1.1.1.7   root     11564:        }
                   11565: }
                   11566: void put_word_cache_040(uaecptr addr, uae_u32 v)
                   11567: {
1.1.1.9 ! root     11568:        int offset = addr & 15;
        !          11569:        if (offset < 15) {
        !          11570:                write_dcache040(addr, v, 1, dcache_wput);
1.1.1.7   root     11571:        } else {
1.1.1.9 ! root     11572:                write_dcache040(addr + 0, v >> 8, 0, dcache_bput);
        !          11573:                write_dcache040(addr + 1, v >> 0, 0, dcache_bput);
1.1.1.7   root     11574:        }
                   11575: }
                   11576: void put_byte_cache_040(uaecptr addr, uae_u32 v)
                   11577: {
1.1.1.9 ! root     11578:        return write_dcache040(addr, v, 0, dcache_bput);
1.1.1.4   root     11579: }
                   11580: 
1.1.1.7   root     11581: uae_u32 get_long_cache_040(uaecptr addr)
                   11582: {
1.1.1.9 ! root     11583:        uae_u32 v;
        !          11584:        int offset = addr & 15;
        !          11585:        if (offset < 13) {
        !          11586:                v = read_dcache040(addr, 2, dcache_lget);
        !          11587:        } else if (offset == 13 || offset == 15) {
        !          11588:                v =  read_dcache040(addr + 0, 0, dcache_bget) << 24;
        !          11589:                v |= read_dcache040(addr + 1, 1, dcache_wget) <<  8;
        !          11590:                v |= read_dcache040(addr + 3, 0, dcache_bget) <<  0;
        !          11591:        } else if (offset == 14) {
        !          11592:                v =  read_dcache040(addr + 0, 1, dcache_wget) << 16;
        !          11593:                v |= read_dcache040(addr + 2, 1, dcache_wget) <<  0;
        !          11594:        }
        !          11595:        return v;
1.1.1.7   root     11596: }
                   11597: uae_u32 get_word_cache_040(uaecptr addr)
                   11598: {
1.1.1.9 ! root     11599:        uae_u32 v;
        !          11600:        int offset = addr & 15;
        !          11601:        if (offset < 15) {
        !          11602:                v = read_dcache040(addr, 1, dcache_wget);
        !          11603:        } else {
        !          11604:                v =  read_dcache040(addr + 0, 0, dcache_bget) << 8;
        !          11605:                v |= read_dcache040(addr + 1, 0, dcache_bget) << 0;
        !          11606:        }
        !          11607:        return v;
1.1.1.7   root     11608: }
                   11609: uae_u32 get_byte_cache_040(uaecptr addr)
                   11610: {
1.1.1.9 ! root     11611:        return read_dcache040(addr, 0, dcache_bget);
1.1.1.7   root     11612: }
                   11613: uae_u32 next_iword_cache040(void)
                   11614: {
                   11615:        uae_u32 r = get_word_icache040(m68k_getpci());
                   11616:        m68k_incpci(2);
                   11617:        return r;
                   11618: }
                   11619: uae_u32 next_ilong_cache040(void)
                   11620: {
                   11621:        uae_u32 r = get_long_icache040(m68k_getpci());
                   11622:        m68k_incpci(4);
                   11623:        return r;
                   11624: }
1.1.1.4   root     11625: 
1.1.1.9 ! root     11626: uae_u32 get_byte_cache_debug(uaecptr addr, bool *cached)
1.1.1.4   root     11627: {
1.1.1.9 ! root     11628:        *cached = false;
        !          11629:        if (currprefs.cpu_model == 68030) {
        !          11630:                return read_dcache030_debug(addr, 0, regs.s ? 5 : 1, cached);
        !          11631:        } else if (currprefs.cpu_model >= 68040) {
        !          11632:                return read_dcache040_debug(addr, 0, cached);
        !          11633:        }
        !          11634:        return get_byte_debug(addr);
        !          11635: }
        !          11636: uae_u32 get_word_cache_debug(uaecptr addr, bool *cached)
        !          11637: {
        !          11638:        *cached = false;
        !          11639:        if (currprefs.cpu_model == 68030) {
        !          11640:                return read_dcache030_debug(addr, 1, regs.s ? 5 : 1, cached);
        !          11641:        } else if (currprefs.cpu_model >= 68040) {
        !          11642:                return read_dcache040_debug(addr, 1, cached);
1.1.1.4   root     11643:        }
1.1.1.9 ! root     11644:        return get_word_debug(addr);
1.1.1.4   root     11645: }
                   11646: 
1.1.1.9 ! root     11647: uae_u32 get_long_cache_debug(uaecptr addr, bool *cached)
1.1.1.4   root     11648: {
1.1.1.9 ! root     11649:        *cached = false;
        !          11650:        if (currprefs.cpu_model == 68030) {
        !          11651:                return read_dcache030_debug(addr, 2, regs.s ? 5 : 1, cached);
        !          11652:        } else if (currprefs.cpu_model >= 68040) {
        !          11653:                return read_dcache040_debug(addr, 2, cached);
1.1.1.7   root     11654:        }
1.1.1.9 ! root     11655:        return get_long_debug(addr);
        !          11656: }
        !          11657: 
        !          11658: void check_t0_trace(void)
        !          11659: {
        !          11660:        if (regs.t0 && currprefs.cpu_model >= 68020) {
        !          11661:                unset_special (SPCFLAG_TRACE);
        !          11662:                set_special (SPCFLAG_DOTRACE);
1.1.1.7   root     11663:        }
1.1.1.9 ! root     11664: }
        !          11665: 
        !          11666: static void reset_pipeline_state(void)
        !          11667: {
        !          11668: #if MORE_ACCURATE_68020_PIPELINE
        !          11669:        regs.pipeline_pos = 0;
        !          11670:        regs.pipeline_stop = 0;
        !          11671:        regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
        !          11672: #endif
        !          11673: }
        !          11674: 
        !          11675: static int add_prefetch_030(int idx, uae_u16 w, uaecptr pc)
        !          11676: {
        !          11677:        regs.prefetch020[0] = regs.prefetch020[1];
        !          11678:        regs.prefetch020_valid[0] = regs.prefetch020_valid[1];
        !          11679:        regs.prefetch020[1] = regs.prefetch020[2];
        !          11680:        regs.prefetch020_valid[1] = regs.prefetch020_valid[2];
        !          11681:        regs.prefetch020[2] = w;
        !          11682:        regs.prefetch020_valid[2] = regs.cacheholdingdata_valid;
        !          11683: 
        !          11684: #if MORE_ACCURATE_68020_PIPELINE
        !          11685:        if (idx >= 1) {
        !          11686:                pipeline_020(pc);
        !          11687:        }
        !          11688: #endif
        !          11689: 
        !          11690:        if  (!regs.prefetch020_valid[2]) {
        !          11691:                if (idx == 0 || !regs.pipeline_stop) {
        !          11692:                        // Pipeline refill and first opcode word is invalid?
        !          11693:                        // Generate previously detected bus error/MMU fault
        !          11694:                        do_access_or_bus_error(pc, pc + idx * 2);
1.1.1.7   root     11695:                }
                   11696:        }
1.1.1.9 ! root     11697:        return idx + 1;
1.1.1.4   root     11698: }
                   11699: 
1.1.1.9 ! root     11700: void fill_prefetch_030_ntx(void)
1.1.1.4   root     11701: {
1.1.1.9 ! root     11702: //fprintf ( stderr , "fill_prefetch_030_ntx %d\n" , currcycle);
1.1.1.7   root     11703:        uaecptr pc = m68k_getpc ();
                   11704:        uaecptr pc2 = pc;
1.1.1.9 ! root     11705:        int idx = 0;
        !          11706: 
1.1.1.7   root     11707:        pc &= ~3;
1.1.1.9 ! root     11708:        mmu030_idx = 0;
        !          11709:        reset_pipeline_state();
        !          11710:        regs.cacheholdingdata_valid = 1;
        !          11711:        regs.cacheholdingaddr020 = 0xffffffff;
        !          11712:        regs.prefetch020_valid[0] = regs.prefetch020_valid[1] = regs.prefetch020_valid[2] = 0;
1.1.1.4   root     11713: 
1.1.1.9 ! root     11714:        fill_icache030(pc);
1.1.1.7   root     11715:        if (currprefs.cpu_cycle_exact)
                   11716:                do_cycles_ce020_internal(2);
1.1.1.9 ! root     11717:        if (pc2 & 2) {
        !          11718:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
        !          11719:        } else {
        !          11720:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
        !          11721:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
        !          11722:        }
1.1.1.7   root     11723: 
1.1.1.9 ! root     11724:        fill_icache030(pc + 4);
1.1.1.7   root     11725:        if (currprefs.cpu_cycle_exact)
                   11726:                do_cycles_ce020_internal(2);
                   11727:        if (pc2 & 2) {
1.1.1.9 ! root     11728:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
        !          11729:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
1.1.1.7   root     11730:        } else {
1.1.1.9 ! root     11731:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
1.1.1.4   root     11732:        }
1.1.1.9 ! root     11733: 
        !          11734:        if (currprefs.cpu_cycle_exact)
        !          11735:                regs.irc = get_word_ce030_prefetch_opcode (0);
        !          11736:        else
        !          11737:                regs.irc = get_word_030_prefetch (0);
        !          11738: }
        !          11739: 
        !          11740: void fill_prefetch_030_ntx_continue (void)
        !          11741: {
        !          11742:        uaecptr pc = m68k_getpc ();
        !          11743:        uaecptr pc_orig = pc;
        !          11744:        int idx = 0;
        !          11745:        int i;
        !          11746: 
        !          11747:        mmu030_idx = 0;
        !          11748:        reset_pipeline_state();
        !          11749:        regs.cacheholdingdata_valid = 1;
        !          11750:        regs.cacheholdingaddr020 = 0xffffffff;
        !          11751: 
        !          11752:        for (i = 2; i >= 0; i--) {
        !          11753:                if (!regs.prefetch020_valid[i])
        !          11754:                        break;
        !          11755: #if MORE_ACCURATE_68020_PIPELINE
        !          11756:                if (idx >= 1) {
        !          11757:                        pipeline_020(pc);
        !          11758:                }
1.1.1.7   root     11759: #endif
1.1.1.9 ! root     11760:                pc += 2;
        !          11761:                idx++;
        !          11762:        }
        !          11763: 
        !          11764:        if (idx < 3 && !regs.pipeline_stop) {
        !          11765:                uaecptr pc2 = pc;
        !          11766:                pc &= ~3;
        !          11767: 
        !          11768:                fill_icache030(pc);
        !          11769:                if (currprefs.cpu_cycle_exact)
        !          11770:                        do_cycles_ce020_internal(2);
        !          11771:                if (pc2 & 2) {
        !          11772:                        idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
        !          11773:                } else {
        !          11774:                        idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
        !          11775:                        if (idx < 3)
        !          11776:                                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
        !          11777:                }
        !          11778: 
        !          11779:                if (idx < 3) {
        !          11780:                        fill_icache030(pc + 4);
        !          11781:                        if (currprefs.cpu_cycle_exact)
        !          11782:                                do_cycles_ce020_internal(2);
        !          11783:                        if (pc2 & 2) {
        !          11784:                                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
        !          11785:                                if (idx < 3)
        !          11786:                                        idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
        !          11787:                        } else {
        !          11788:                                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
        !          11789:                        }
        !          11790:                }
        !          11791:        }
1.1.1.4   root     11792: 
1.1.1.7   root     11793:        if (currprefs.cpu_cycle_exact)
1.1.1.9 ! root     11794:                regs.irc = get_word_ce030_prefetch_opcode (0);
1.1.1.7   root     11795:        else
1.1.1.9 ! root     11796:                regs.irc = get_word_030_prefetch (0);
        !          11797: //fprintf ( stderr , "fill_prefetch_030_ntx4 %d\n" , currcycle);
1.1.1.4   root     11798: }
                   11799: 
1.1.1.9 ! root     11800: void fill_prefetch_020_ntx(void)
1.1.1.4   root     11801: {
1.1.1.7   root     11802:        uaecptr pc = m68k_getpc ();
                   11803:        uaecptr pc2 = pc;
1.1.1.9 ! root     11804:        int idx = 0;
        !          11805: 
1.1.1.7   root     11806:        pc &= ~3;
1.1.1.9 ! root     11807:        reset_pipeline_state();
1.1.1.7   root     11808: 
1.1.1.9 ! root     11809:        fill_icache020 (pc, true);
1.1.1.7   root     11810:        if (currprefs.cpu_cycle_exact)
                   11811:                do_cycles_ce020_internal(2);
1.1.1.9 ! root     11812:        if (pc2 & 2) {
        !          11813:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
        !          11814:        } else {
        !          11815:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
        !          11816:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
        !          11817:        }
1.1.1.7   root     11818: 
1.1.1.9 ! root     11819:        fill_icache020 (pc + 4, true);
1.1.1.7   root     11820:        if (currprefs.cpu_cycle_exact)
                   11821:                do_cycles_ce020_internal(2);
                   11822:        if (pc2 & 2) {
1.1.1.9 ! root     11823:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
        !          11824:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
1.1.1.7   root     11825:        } else {
1.1.1.9 ! root     11826:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
1.1.1.7   root     11827:        }
                   11828: 
                   11829:        if (currprefs.cpu_cycle_exact)
1.1.1.9 ! root     11830:                regs.irc = get_word_ce020_prefetch_opcode (0);
1.1.1.7   root     11831:        else
                   11832:                regs.irc = get_word_020_prefetch (0);
1.1.1.4   root     11833: }
                   11834: 
1.1.1.9 ! root     11835: // Not exactly right, requires logic analyzer checks.
        !          11836: void continue_ce020_prefetch(void)
        !          11837: {
        !          11838:        fill_prefetch_020_ntx();
        !          11839: }
        !          11840: void continue_020_prefetch(void)
        !          11841: {
        !          11842:        fill_prefetch_020_ntx();
        !          11843: }
        !          11844: 
        !          11845: void continue_ce030_prefetch(void)
        !          11846: {
        !          11847:        fill_prefetch_030_ntx();
        !          11848: }
        !          11849: void continue_030_prefetch(void)
        !          11850: {
        !          11851:        fill_prefetch_030_ntx();
        !          11852: }
        !          11853: 
        !          11854: void fill_prefetch_020(void)
        !          11855: {
        !          11856:        fill_prefetch_020_ntx();
        !          11857:        check_t0_trace();
        !          11858: }
        !          11859: 
        !          11860: void fill_prefetch_030(void)
        !          11861: {
        !          11862:        fill_prefetch_030_ntx();
        !          11863:        check_t0_trace();
        !          11864: }
        !          11865: 
        !          11866: 
1.1.1.7   root     11867: void fill_prefetch (void)
1.1.1.4   root     11868: {
1.1.1.9 ! root     11869:        reset_pipeline_state();
1.1.1.7   root     11870:        if (currprefs.cachesize)
                   11871:                return;
                   11872:        if (!currprefs.cpu_compatible)
                   11873:                return;
                   11874:        if (currprefs.cpu_model >= 68040) {
1.1.1.8   root     11875:                if (currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) {
1.1.1.7   root     11876:                        fill_icache040(m68k_getpc() + 16);
                   11877:                        fill_icache040(m68k_getpc());
                   11878:                }
                   11879:        } else if (currprefs.cpu_model == 68020) {
                   11880:                fill_prefetch_020 ();
                   11881:        } else if (currprefs.cpu_model == 68030) {
                   11882:                fill_prefetch_030 ();
                   11883:        } else if (currprefs.cpu_model <= 68010) {
                   11884:                uaecptr pc = m68k_getpc ();
                   11885:                regs.ir = x_get_word (pc);
                   11886:                regs.irc = x_get_word (pc + 2);
                   11887:        }
1.1.1.4   root     11888: }

unix.superglobalmegacorp.com

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