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

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

unix.superglobalmegacorp.com

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