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

1.1.1.4   root        1: /*
                      2: * UAE - The Un*x Amiga Emulator
                      3: *
                      4: * MC68000 emulation
                      5: *
                      6: * (c) 1995 Bernd Schmidt
                      7: */
                      8: 
                      9: #define MMUOP_DEBUG 2
                     10: #define DEBUG_CD32CDTVIO 0
1.1.1.7   root       11: #define EXCEPTION3_DEBUGGER 0
                     12: #define CPUTRACE_DEBUG 0
                     13: 
1.1.1.9   root       14: #define VALIDATE_68030_DATACACHE 0
                     15: #define VALIDATE_68040_DATACACHE 0
                     16: #define DISABLE_68040_COPYBACK 0
                     17: 
1.1.1.7   root       18: #define MORE_ACCURATE_68020_PIPELINE 1
1.1.1.4   root       19: 
1.1.1.8   root       20: #include <inttypes.h>          /* Needed for PRIX64 */
                     21: 
1.1.1.5   root       22: #include "main.h"
1.1.1.4   root       23: #include "compat.h"
1.1.1.7   root       24: 
1.1.1.4   root       25: #include "sysconfig.h"
                     26: #include "sysdeps.h"
1.1.1.7   root       27: 
1.1.1.4   root       28: #include "hatari-glue.h"
1.1.1.7   root       29: 
1.1.1.4   root       30: #include "options_cpu.h"
                     31: #include "events.h"
                     32: #include "memory.h"
1.1.1.7   root       33: #include "custom.h"
1.1.1.4   root       34: #include "newcpu.h"
                     35: #include "cpummu.h"
1.1.1.5   root       36: #include "cpummu030.h"
1.1.1.4   root       37: #include "cpu_prefetch.h"
1.1.1.10! root       38: #include "debugmem.h"
1.1.1.7   root       39: #include "savestate.h"
1.1.1.9   root       40: #include "fpp.h"
1.1.1.10! root       41: 
1.1.1.7   root       42: #ifdef WINUAE_FOR_HATARI
                     43: #include "debug.h"
                     44: #include "m68000.h"
1.1.1.4   root       45: #include "reset.h"
                     46: #include "cycInt.h"
                     47: #include "mfp.h"
                     48: #include "tos.h"
                     49: #include "vdi.h"
                     50: #include "cart.h"
                     51: #include "dialog.h"
                     52: #include "bios.h"
                     53: #include "xbios.h"
                     54: #include "screen.h"
                     55: #include "video.h"
                     56: #include "options.h"
                     57: #include "dsp.h"
                     58: #include "log.h"
                     59: #include "debugui.h"
                     60: #include "debugcpu.h"
1.1.1.5   root       61: #include "stMemory.h"
1.1.1.9   root       62: #include "blitter.h"
1.1.1.10! root       63: #endif
1.1.1.4   root       64: 
                     65: 
                     66: #ifdef JIT
                     67: #include "jit/compemu.h"
                     68: #include <signal.h>
                     69: #else
                     70: /* Need to have these somewhere */
1.1.1.8   root       71: //#ifndef WINUAE_FOR_HATARI
                     72: bool check_prefs_changed_comp (bool checkonly) { return false; }
                     73: //#endif
1.1.1.7   root       74: #endif
1.1.1.4   root       75: 
                     76: /* Opcode of faulting instruction */
                     77: static uae_u16 last_op_for_exception_3;
                     78: /* PC at fault time */
                     79: static uaecptr last_addr_for_exception_3;
                     80: /* Address that generated the exception */
                     81: static uaecptr last_fault_for_exception_3;
                     82: /* read (0) or write (1) access */
1.1.1.7   root       83: static bool last_writeaccess_for_exception_3;
1.1.1.4   root       84: /* instruction (1) or data (0) access */
1.1.1.7   root       85: static bool last_instructionaccess_for_exception_3;
                     86: /* not instruction */
                     87: static bool last_notinstruction_for_exception_3;
                     88: /* set when writing exception stack frame */
                     89: static int exception_in_exception;
                     90: 
1.1.1.4   root       91: int mmu_enabled, mmu_triggered;
                     92: int cpu_cycles;
1.1.1.7   root       93: int bus_error_offset;
                     94: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root       95: static int baseclock;
1.1.1.7   root       96: #endif
                     97: int m68k_pc_indirect;
                     98: bool m68k_interrupt_delay;
                     99: static bool m68k_reset_delay;
1.1.1.9   root      100: 
1.1.1.10! root      101: #ifndef WINUAE_FOR_HATARI
        !           102: static volatile uae_atomic uae_interrupt;
        !           103: static volatile uae_atomic uae_interrupts2[IRQ_SOURCE_MAX];
        !           104: static volatile uae_atomic uae_interrupts6[IRQ_SOURCE_MAX];
        !           105: #endif
        !           106: 
1.1.1.9   root      107: static int cacheisets04060, cacheisets04060mask, cacheitag04060mask;
                    108: static int cachedsets04060, cachedsets04060mask, cachedtag04060mask;
                    109: 
1.1.1.7   root      110: static int cpu_prefs_changed_flag;
                    111: 
1.1.1.4   root      112: int cpucycleunit;
1.1.1.7   root      113: int cpu_tracer;
1.1.1.4   root      114: 
                    115: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
                    116: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
                    117: 
                    118: int movem_index1[256];
                    119: int movem_index2[256];
                    120: int movem_next[256];
                    121: 
                    122: cpuop_func *cpufunctbl[65536];
                    123: 
1.1.1.7   root      124: struct cputbl_data
                    125: {
                    126:        uae_s16 length;
                    127:        uae_s8 disp020[2];
                    128:        uae_u8 branch;
                    129: };
                    130: static struct cputbl_data cpudatatbl[65536];
1.1.1.5   root      131: 
1.1.1.4   root      132: struct mmufixup mmufixup[2];
                    133: 
                    134: #define COUNT_INSTRS 0
                    135: #define MC68060_PCR   0x04300000
                    136: #define MC68EC060_PCR 0x04310000
                    137: 
1.1.1.7   root      138: static uae_u64 fake_srp_030, fake_crp_030;
                    139: static uae_u32 fake_tt0_030, fake_tt1_030, fake_tc_030;
                    140: static uae_u16 fake_mmusr_030;
1.1.1.4   root      141: 
                    142: static struct cache020 caches020[CACHELINES020];
                    143: static struct cache030 icaches030[CACHELINES030];
                    144: static struct cache030 dcaches030[CACHELINES030];
1.1.1.9   root      145: static int icachelinecnt, icachehalfline;
                    146: static int dcachelinecnt;
                    147: static struct cache040 icaches040[CACHESETS060];
                    148: static struct cache040 dcaches040[CACHESETS060];
                    149: static int cache_lastline; 
1.1.1.7   root      150: 
1.1.1.8   root      151: static int fallback_cpu_model, fallback_mmu_model, fallback_fpu_model;
1.1.1.9   root      152: static bool fallback_cpu_compatible, fallback_cpu_address_space_24;
1.1.1.8   root      153: static struct regstruct fallback_regs;
                    154: static int fallback_new_cpu_model;
1.1.1.7   root      155: 
                    156: #ifdef WINUAE_FOR_HATARI
                    157: int OpcodeFamily;
                    158: int BusCyclePenalty = 0;
1.1.1.4   root      159: 
1.1.1.7   root      160: FILE *console_out_FILE = NULL;
1.1.1.9   root      161: 
1.1.1.10! root      162: int quit_program = 0;                  /* from main.cpp */
1.1.1.7   root      163: #endif
1.1.1.4   root      164: 
                    165: 
                    166: #if COUNT_INSTRS
                    167: static unsigned long int instrcount[65536];
                    168: static uae_u16 opcodenums[65536];
                    169: 
                    170: static int compfn (const void *el1, const void *el2)
                    171: {
                    172:        return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
                    173: }
                    174: 
                    175: static TCHAR *icountfilename (void)
                    176: {
                    177:        TCHAR *name = getenv ("INSNCOUNT");
                    178:        if (name)
                    179:                return name;
                    180:        return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
                    181: }
                    182: 
                    183: void dump_counts (void)
                    184: {
                    185:        FILE *f = fopen (icountfilename (), "w");
                    186:        unsigned long int total;
                    187:        int i;
                    188: 
1.1.1.7   root      189:        write_log (_T("Writing instruction count file...\n"));
1.1.1.4   root      190:        for (i = 0; i < 65536; i++) {
                    191:                opcodenums[i] = i;
                    192:                total += instrcount[i];
                    193:        }
                    194:        qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
                    195: 
                    196:        fprintf (f, "Total: %lu\n", total);
                    197:        for (i=0; i < 65536; i++) {
                    198:                unsigned long int cnt = instrcount[opcodenums[i]];
                    199:                struct instr *dp;
                    200:                struct mnemolookup *lookup;
                    201:                if (!cnt)
                    202:                        break;
                    203:                dp = table68k + opcodenums[i];
                    204:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                    205:                        ;
                    206:                fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
                    207:        }
                    208:        fclose (f);
                    209: }
                    210: #else
                    211: void dump_counts (void)
                    212: {
                    213: }
                    214: #endif
                    215: 
1.1.1.7   root      216: /*
                    217: 
                    218:  ok, all this to "record" current instruction state
                    219:  for later 100% cycle-exact restoring
                    220: 
                    221:  */
                    222: 
                    223: static uae_u32 (*x2_prefetch)(int);
                    224: static uae_u32 (*x2_prefetch_long)(int);
                    225: static uae_u32 (*x2_next_iword)(void);
                    226: static uae_u32 (*x2_next_ilong)(void);
                    227: static uae_u32 (*x2_get_ilong)(int);
                    228: static uae_u32 (*x2_get_iword)(int);
                    229: static uae_u32 (*x2_get_ibyte)(int);
                    230: static uae_u32 (*x2_get_long)(uaecptr);
                    231: static uae_u32 (*x2_get_word)(uaecptr);
                    232: static uae_u32 (*x2_get_byte)(uaecptr);
                    233: static void (*x2_put_long)(uaecptr,uae_u32);
                    234: static void (*x2_put_word)(uaecptr,uae_u32);
                    235: static void (*x2_put_byte)(uaecptr,uae_u32);
                    236: static void (*x2_do_cycles)(unsigned long);
                    237: static void (*x2_do_cycles_pre)(unsigned long);
                    238: static void (*x2_do_cycles_post)(unsigned long, uae_u32);
1.1.1.4   root      239: 
                    240: uae_u32 (*x_prefetch)(int);
                    241: uae_u32 (*x_next_iword)(void);
                    242: uae_u32 (*x_next_ilong)(void);
1.1.1.7   root      243: uae_u32 (*x_get_ilong)(int);
                    244: uae_u32 (*x_get_iword)(int);
                    245: uae_u32 (*x_get_ibyte)(int);
1.1.1.4   root      246: uae_u32 (*x_get_long)(uaecptr);
                    247: uae_u32 (*x_get_word)(uaecptr);
                    248: uae_u32 (*x_get_byte)(uaecptr);
                    249: void (*x_put_long)(uaecptr,uae_u32);
                    250: void (*x_put_word)(uaecptr,uae_u32);
                    251: void (*x_put_byte)(uaecptr,uae_u32);
                    252: 
1.1.1.7   root      253: uae_u32 (*x_cp_next_iword)(void);
                    254: uae_u32 (*x_cp_next_ilong)(void);
                    255: uae_u32 (*x_cp_get_long)(uaecptr);
                    256: uae_u32 (*x_cp_get_word)(uaecptr);
                    257: uae_u32 (*x_cp_get_byte)(uaecptr);
                    258: void (*x_cp_put_long)(uaecptr,uae_u32);
                    259: void (*x_cp_put_word)(uaecptr,uae_u32);
                    260: void (*x_cp_put_byte)(uaecptr,uae_u32);
                    261: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
                    262: 
                    263: void (*x_do_cycles)(unsigned long);
                    264: void (*x_do_cycles_pre)(unsigned long);
                    265: void (*x_do_cycles_post)(unsigned long, uae_u32);
                    266: 
                    267: uae_u32(*x_phys_get_iword)(uaecptr);
                    268: uae_u32(*x_phys_get_ilong)(uaecptr);
                    269: uae_u32(*x_phys_get_byte)(uaecptr);
                    270: uae_u32(*x_phys_get_word)(uaecptr);
                    271: uae_u32(*x_phys_get_long)(uaecptr);
                    272: void(*x_phys_put_byte)(uaecptr, uae_u32);
                    273: void(*x_phys_put_word)(uaecptr, uae_u32);
                    274: void(*x_phys_put_long)(uaecptr, uae_u32);
                    275: 
                    276: static void set_x_cp_funcs(void)
                    277: {
                    278:        x_cp_put_long = x_put_long;
                    279:        x_cp_put_word = x_put_word;
                    280:        x_cp_put_byte = x_put_byte;
                    281:        x_cp_get_long = x_get_long;
                    282:        x_cp_get_word = x_get_word;
                    283:        x_cp_get_byte = x_get_byte;
                    284:        x_cp_next_iword = x_next_iword;
                    285:        x_cp_next_ilong = x_next_ilong;
                    286:        x_cp_get_disp_ea_020 = x_get_disp_ea_020;
                    287: 
                    288:        if (currprefs.mmu_model == 68030) {
1.1.1.9   root      289:                if (currprefs.cpu_compatible) {
                    290:                        x_cp_put_long = put_long_mmu030c_state;
                    291:                        x_cp_put_word = put_word_mmu030c_state;
                    292:                        x_cp_put_byte = put_byte_mmu030c_state;
                    293:                        x_cp_get_long = get_long_mmu030c_state;
                    294:                        x_cp_get_word = get_word_mmu030c_state;
                    295:                        x_cp_get_byte = get_byte_mmu030c_state;
                    296:                        x_cp_next_iword = next_iword_mmu030c_state;
                    297:                        x_cp_next_ilong = next_ilong_mmu030c_state;
                    298:                        x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030c;
                    299:                } else {
                    300:                        x_cp_put_long = put_long_mmu030_state;
                    301:                        x_cp_put_word = put_word_mmu030_state;
                    302:                        x_cp_put_byte = put_byte_mmu030_state;
                    303:                        x_cp_get_long = get_long_mmu030_state;
                    304:                        x_cp_get_word = get_word_mmu030_state;
                    305:                        x_cp_get_byte = get_byte_mmu030_state;
                    306:                        x_cp_next_iword = next_iword_mmu030_state;
                    307:                        x_cp_next_ilong = next_ilong_mmu030_state;
                    308:                        x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
                    309:                }
1.1.1.7   root      310:        }
                    311: }
                    312: 
                    313: static struct cputracestruct cputrace;
                    314: 
                    315: #if CPUTRACE_DEBUG
                    316: static void validate_trace (void)
                    317: {
                    318:        for (int i = 0; i < cputrace.memoryoffset; i++) {
                    319:                struct cputracememory *ctm = &cputrace.ctm[i];
                    320:                if (ctm->data == 0xdeadf00d) {
                    321:                        write_log (_T("unfinished write operation %d %08x\n"), i, ctm->addr);
                    322:                }
                    323:        }
                    324: }
                    325: #endif
                    326: 
                    327: static void debug_trace (void)
                    328: {
                    329:        if (cputrace.writecounter > 10000 || cputrace.readcounter > 10000)
                    330:                write_log (_T("cputrace.readcounter=%d cputrace.writecounter=%d\n"), cputrace.readcounter, cputrace.writecounter);
                    331: }
                    332: 
                    333: STATIC_INLINE void clear_trace (void)
                    334: {
                    335: #if CPUTRACE_DEBUG
                    336:        validate_trace ();
                    337: #endif
1.1.1.9   root      338:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE)
                    339:                return;
1.1.1.7   root      340:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
1.1.1.9   root      341:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE) {
                    342:                write_log(_T("CPUTRACE overflow, stopping tracing.\n"));
                    343:                return;
                    344:        }
1.1.1.7   root      345:        ctm->mode = 0;
                    346:        cputrace.cyclecounter = 0;
                    347:        cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                    348: }
                    349: static void set_trace (uaecptr addr, int accessmode, int size)
                    350: {
                    351: #if CPUTRACE_DEBUG
                    352:        validate_trace ();
                    353: #endif
1.1.1.9   root      354:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE)
                    355:                return;
1.1.1.7   root      356:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
1.1.1.9   root      357:        if (cputrace.memoryoffset == MAX_CPUTRACESIZE) {
                    358:                write_log(_T("CPUTRACE overflow, stopping tracing.\n"));
                    359:                return;
                    360:        }
1.1.1.7   root      361:        ctm->addr = addr;
                    362:        ctm->data = 0xdeadf00d;
                    363:        ctm->mode = accessmode | (size << 4);
                    364:        cputrace.cyclecounter_pre = -1;
                    365:        if (accessmode == 1)
                    366:                cputrace.writecounter++;
                    367:        else
                    368:                cputrace.readcounter++;
                    369:        debug_trace ();
                    370: }
                    371: static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size)
                    372: {
                    373:        if (cputrace.memoryoffset < 1) {
                    374: #if CPUTRACE_DEBUG
                    375:                write_log (_T("add_trace memoryoffset=%d!\n"), cputrace.memoryoffset);
                    376: #endif
                    377:                return;
                    378:        }
                    379:        int mode = accessmode | (size << 4);
                    380:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
                    381:        ctm->addr = addr;
                    382:        ctm->data = val;
                    383:        if (!ctm->mode) {
                    384:                ctm->mode = mode;
                    385:                if (accessmode == 1)
                    386:                        cputrace.writecounter++;
                    387:                else
                    388:                        cputrace.readcounter++;
                    389:        }
                    390:        debug_trace ();
                    391:        cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                    392: }
                    393: 
                    394: 
                    395: static void check_trace2 (void)
                    396: {
                    397:        if (cputrace.readcounter || cputrace.writecounter ||
                    398:                cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
                    399:                write_log (_T("CPU tracer invalid state during playback!\n"));
                    400: }
                    401: 
                    402: static bool check_trace (void)
                    403: {
                    404:        if (!cpu_tracer)
                    405:                return true;
                    406:        if (!cputrace.readcounter && !cputrace.writecounter && !cputrace.cyclecounter) {
                    407:                if (cpu_tracer != -2) {
                    408:                        write_log (_T("CPU trace: dma_cycle() enabled. %08x %08x NOW=%08lx\n"),
                    409:                                cputrace.cyclecounter_pre, cputrace.cyclecounter_post, get_cycles ());
                    410:                        cpu_tracer = -2; // dma_cycle() allowed to work now
                    411:                }
                    412:        }
                    413:        if (cputrace.readcounter || cputrace.writecounter ||
                    414:                cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
                    415:                return false;
                    416:        x_prefetch = x2_prefetch;
                    417:        x_get_ilong = x2_get_ilong;
                    418:        x_get_iword = x2_get_iword;
                    419:        x_get_ibyte = x2_get_ibyte;
                    420:        x_next_iword = x2_next_iword;
                    421:        x_next_ilong = x2_next_ilong;
                    422:        x_put_long = x2_put_long;
                    423:        x_put_word = x2_put_word;
                    424:        x_put_byte = x2_put_byte;
                    425:        x_get_long = x2_get_long;
                    426:        x_get_word = x2_get_word;
                    427:        x_get_byte = x2_get_byte;
                    428:        x_do_cycles = x2_do_cycles;
                    429:        x_do_cycles_pre = x2_do_cycles_pre;
                    430:        x_do_cycles_post = x2_do_cycles_post;
                    431:        set_x_cp_funcs();
                    432:        write_log (_T("CPU tracer playback complete. STARTCYCLES=%08x NOWCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
                    433:        cputrace.needendcycles = 1;
                    434:        cpu_tracer = 0;
                    435:        return true;
                    436: }
                    437: 
                    438: static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data)
                    439: {
                    440:        int mode = accessmode | (size << 4);
1.1.1.10! root      441:        for (int i = 0; i < cputrace.memoryoffset; i++) {
1.1.1.7   root      442:                struct cputracememory *ctm = &cputrace.ctm[i];
                    443:                if (ctm->addr == addr && ctm->mode == mode) {
                    444:                        ctm->mode = 0;
                    445:                        write_log (_T("CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d (%08lx)\n"),
                    446:                                i, cputrace.pc, addr, ctm->data, accessmode, size,
                    447:                                cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
                    448:                                cputrace.readcounter, cputrace.writecounter, get_cycles ());
                    449:                        if (accessmode == 1)
                    450:                                cputrace.writecounter--;
                    451:                        else
                    452:                                cputrace.readcounter--;
                    453:                        if (cputrace.writecounter == 0 && cputrace.readcounter == 0) {
                    454:                                if (cputrace.cyclecounter_post) {
                    455:                                        int c = cputrace.cyclecounter_post;
                    456:                                        cputrace.cyclecounter_post = 0;
                    457:                                        x_do_cycles (c);
                    458:                                } else if (cputrace.cyclecounter_pre) {
                    459:                                        check_trace ();
                    460:                                        *data = ctm->data;
                    461:                                        return true; // argh, need to rerun the memory access..
                    462:                                }
                    463:                        }
                    464:                        check_trace ();
                    465:                        *data = ctm->data;
                    466:                        return false;
                    467:                }
                    468:        }
                    469:        if (cputrace.cyclecounter_post) {
                    470:                int c = cputrace.cyclecounter_post;
                    471:                cputrace.cyclecounter_post = 0;
                    472:                check_trace ();
                    473:                check_trace2 ();
                    474:                x_do_cycles (c);
                    475:                return false;
                    476:        }
                    477:        gui_message (_T("CPU trace: GET %08x %d %d NOT FOUND!\n"), addr, accessmode, size);
                    478:        check_trace ();
                    479:        *data = 0;
                    480:        return false;
                    481: }
                    482: 
                    483: static uae_u32 cputracefunc_x_prefetch (int o)
                    484: {
                    485:        uae_u32 pc = m68k_getpc ();
                    486:        set_trace (pc + o, 2, 2);
                    487:        uae_u32 v = x2_prefetch (o);
                    488:        add_trace (pc + o, v, 2, 2);
                    489:        return v;
                    490: }
                    491: static uae_u32 cputracefunc2_x_prefetch (int o)
                    492: {
                    493:        uae_u32 v;
                    494:        if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
                    495:                v = x2_prefetch (o);
                    496:                check_trace2 ();
                    497:        }
                    498:        return v;
                    499: }
                    500: 
                    501: static uae_u32 cputracefunc_x_next_iword (void)
                    502: {
                    503:        uae_u32 pc = m68k_getpc ();
                    504:        set_trace (pc, 2, 2);
                    505:        uae_u32 v = x2_next_iword ();
                    506:        add_trace (pc, v, 2, 2);
                    507:        return v;
                    508: }
                    509: static uae_u32 cputracefunc_x_next_ilong (void)
                    510: {
                    511:        uae_u32 pc = m68k_getpc ();
                    512:        set_trace (pc, 2, 4);
                    513:        uae_u32 v = x2_next_ilong ();
                    514:        add_trace (pc, v, 2, 4);
                    515:        return v;
                    516: }
                    517: static uae_u32 cputracefunc2_x_next_iword (void)
                    518: {
                    519:        uae_u32 v;
                    520:        if (get_trace (m68k_getpc (), 2, 2, &v)) {
                    521:                v = x2_next_iword ();
                    522:                check_trace2 ();
                    523:        }
                    524:        return v;
                    525: }
                    526: static uae_u32 cputracefunc2_x_next_ilong (void)
                    527: {
                    528:        uae_u32 v;
                    529:        if (get_trace (m68k_getpc (), 2, 4, &v)) {
                    530:                v = x2_next_ilong ();
                    531:                check_trace2 ();
                    532:        }
                    533:        return v;
                    534: }
                    535: 
                    536: static uae_u32 cputracefunc_x_get_ilong (int o)
                    537: {
                    538:        uae_u32 pc = m68k_getpc ();
                    539:        set_trace (pc + o, 2, 4);
                    540:        uae_u32 v = x2_get_ilong (o);
                    541:        add_trace (pc + o, v, 2, 4);
                    542:        return v;
                    543: }
                    544: static uae_u32 cputracefunc_x_get_iword (int o)
                    545: {
                    546:        uae_u32 pc = m68k_getpc ();
                    547:        set_trace (pc + o, 2, 2);
                    548:        uae_u32 v = x2_get_iword (o);
                    549:        add_trace (pc + o, v, 2, 2);
                    550:        return v;
                    551: }
                    552: static uae_u32 cputracefunc_x_get_ibyte (int o)
                    553: {
                    554:        uae_u32 pc = m68k_getpc ();
                    555:        set_trace (pc + o, 2, 1);
                    556:        uae_u32 v = x2_get_ibyte (o);
                    557:        add_trace (pc + o, v, 2, 1);
                    558:        return v;
                    559: }
                    560: static uae_u32 cputracefunc2_x_get_ilong (int o)
                    561: {
                    562:        uae_u32 v;
                    563:        if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
                    564:                v = x2_get_ilong (o);
                    565:                check_trace2 ();
                    566:        }
                    567:        return v;
                    568: }
                    569: static uae_u32 cputracefunc2_x_get_iword (int o)
                    570: {
                    571:        uae_u32 v;
                    572:        if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
                    573:                v = x2_get_iword (o);
                    574:                check_trace2 ();
                    575:        }
                    576:        return v;
                    577: }
                    578: static uae_u32 cputracefunc2_x_get_ibyte (int o)
                    579: {
                    580:        uae_u32 v;
                    581:        if (get_trace (m68k_getpc () + o, 2, 1, &v)) {
                    582:                v = x2_get_ibyte (o);
                    583:                check_trace2 ();
                    584:        }
                    585:        return v;
                    586: }
                    587: 
                    588: static uae_u32 cputracefunc_x_get_long (uaecptr o)
                    589: {
                    590:        set_trace (o, 0, 4);
                    591:        uae_u32 v = x2_get_long (o);
                    592:        add_trace (o, v, 0, 4);
                    593:        return v;
                    594: }
                    595: static uae_u32 cputracefunc_x_get_word (uaecptr o)
                    596: {
                    597:        set_trace (o, 0, 2);
                    598:        uae_u32 v = x2_get_word (o);
                    599:        add_trace (o, v, 0, 2);
                    600:        return v;
                    601: }
                    602: static uae_u32 cputracefunc_x_get_byte (uaecptr o)
                    603: {
                    604:        set_trace (o, 0, 1);
                    605:        uae_u32 v = x2_get_byte (o);
                    606:        add_trace (o, v, 0, 1);
                    607:        return v;
                    608: }
                    609: static uae_u32 cputracefunc2_x_get_long (uaecptr o)
                    610: {
                    611:        uae_u32 v;
                    612:        if (get_trace (o, 0, 4, &v)) {
                    613:                v = x2_get_long (o);
                    614:                check_trace2 ();
                    615:        }
                    616:        return v;
                    617: }
                    618: static uae_u32 cputracefunc2_x_get_word (uaecptr o)
                    619: {
                    620:        uae_u32 v;
                    621:        if (get_trace (o, 0, 2, &v)) {
                    622:                v = x2_get_word (o);
                    623:                check_trace2 ();
                    624:        }
                    625:        return v;
                    626: }
                    627: static uae_u32 cputracefunc2_x_get_byte (uaecptr o)
                    628: {
                    629:        uae_u32 v;
                    630:        if (get_trace (o, 0, 1, &v)) {
                    631:                v = x2_get_byte (o);
                    632:                check_trace2 ();
                    633:        }
                    634:        return v;
                    635: }
                    636: 
                    637: static void cputracefunc_x_put_long (uaecptr o, uae_u32 val)
                    638: {
                    639:        clear_trace ();
                    640:        add_trace (o, val, 1, 4);
                    641:        x2_put_long (o, val);
                    642: }
                    643: static void cputracefunc_x_put_word (uaecptr o, uae_u32 val)
                    644: {
                    645:        clear_trace ();
                    646:        add_trace (o, val, 1, 2);
                    647:        x2_put_word (o, val);
                    648: }
                    649: static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val)
                    650: {
                    651:        clear_trace ();
                    652:        add_trace (o, val, 1, 1);
                    653:        x2_put_byte (o, val);
                    654: }
                    655: static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val)
                    656: {
                    657:        uae_u32 v;
                    658:        if (get_trace (o, 1, 4, &v)) {
                    659:                x2_put_long (o, val);
                    660:                check_trace2 ();
                    661:        }
                    662:        if (v != val)
                    663:                write_log (_T("cputracefunc2_x_put_long %d <> %d\n"), v, val);
                    664: }
                    665: static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val)
                    666: {
                    667:        uae_u32 v;
                    668:        if (get_trace (o, 1, 2, &v)) {
                    669:                x2_put_word (o, val);
                    670:                check_trace2 ();
                    671:        }
                    672:        if (v != val)
                    673:                write_log (_T("cputracefunc2_x_put_word %d <> %d\n"), v, val);
                    674: }
                    675: static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val)
                    676: {
                    677:        uae_u32 v;
                    678:        if (get_trace (o, 1, 1, &v)) {
                    679:                x2_put_byte (o, val);
                    680:                check_trace2 ();
                    681:        }
                    682:        if (v != val)
                    683:                write_log (_T("cputracefunc2_x_put_byte %d <> %d\n"), v, val);
                    684: }
                    685: 
                    686: static void cputracefunc_x_do_cycles (unsigned long cycles)
                    687: {
                    688:        while (cycles >= CYCLE_UNIT) {
                    689:                cputrace.cyclecounter += CYCLE_UNIT;
                    690:                cycles -= CYCLE_UNIT;
                    691:                x2_do_cycles (CYCLE_UNIT);
                    692:        }
                    693:        if (cycles > 0) {
                    694:                cputrace.cyclecounter += cycles;
                    695:                x2_do_cycles (cycles);
                    696:        }
                    697: }
                    698: 
                    699: static void cputracefunc2_x_do_cycles (unsigned long cycles)
                    700: {
                    701:        if (cputrace.cyclecounter > (long)cycles) {
                    702:                cputrace.cyclecounter -= cycles;
                    703:                return;
                    704:        }
                    705:        cycles -= cputrace.cyclecounter;
                    706:        cputrace.cyclecounter = 0;
                    707:        check_trace ();
                    708:        x_do_cycles = x2_do_cycles;
                    709:        if (cycles > 0)
                    710:                x_do_cycles (cycles);
                    711: }
                    712: 
                    713: static void cputracefunc_x_do_cycles_pre (unsigned long cycles)
                    714: {
                    715:        cputrace.cyclecounter_post = 0;
                    716:        cputrace.cyclecounter_pre = 0;
                    717:        while (cycles >= CYCLE_UNIT) {
                    718:                cycles -= CYCLE_UNIT;
                    719:                cputrace.cyclecounter_pre += CYCLE_UNIT;
                    720:                x2_do_cycles (CYCLE_UNIT);
                    721:        }
                    722:        if (cycles > 0) {
                    723:                x2_do_cycles (cycles);
                    724:                cputrace.cyclecounter_pre += cycles;
                    725:        }
                    726:        cputrace.cyclecounter_pre = 0;
                    727: }
                    728: // cyclecounter_pre = how many cycles we need to SWALLOW
                    729: // -1 = rerun whole access
                    730: static void cputracefunc2_x_do_cycles_pre (unsigned long cycles)
                    731: {
                    732:        if (cputrace.cyclecounter_pre == -1) {
                    733:                cputrace.cyclecounter_pre = 0;
                    734:                check_trace ();
                    735:                check_trace2 ();
                    736:                x_do_cycles (cycles);
                    737:                return;
                    738:        }
                    739:        if (cputrace.cyclecounter_pre > (long)cycles) {
                    740:                cputrace.cyclecounter_pre -= cycles;
                    741:                return;
                    742:        }
                    743:        cycles -= cputrace.cyclecounter_pre;
                    744:        cputrace.cyclecounter_pre = 0;
                    745:        check_trace ();
                    746:        if (cycles > 0)
                    747:                x_do_cycles (cycles);
                    748: }
                    749: 
                    750: static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v)
                    751: {
                    752:        if (cputrace.memoryoffset < 1) {
                    753: #if CPUTRACE_DEBUG
                    754:                write_log (_T("cputracefunc_x_do_cycles_post memoryoffset=%d!\n"), cputrace.memoryoffset);
                    755: #endif
                    756:                return;
                    757:        }
                    758:        struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
                    759:        ctm->data = v;
                    760:        cputrace.cyclecounter_post = cycles;
                    761:        cputrace.cyclecounter_pre = 0;
                    762:        while (cycles >= CYCLE_UNIT) {
                    763:                cycles -= CYCLE_UNIT;
                    764:                cputrace.cyclecounter_post -= CYCLE_UNIT;
                    765:                x2_do_cycles (CYCLE_UNIT);
                    766:        }
                    767:        if (cycles > 0) {
                    768:                cputrace.cyclecounter_post -= cycles;
                    769:                x2_do_cycles (cycles);
                    770:        }
                    771:        cputrace.cyclecounter_post = 0;
                    772: }
                    773: // cyclecounter_post = how many cycles we need to WAIT
                    774: static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v)
                    775: {
                    776:        uae_u32 c;
                    777:        if (cputrace.cyclecounter_post) {
                    778:                c = cputrace.cyclecounter_post;
                    779:                cputrace.cyclecounter_post = 0;
                    780:        } else {
                    781:                c = cycles;
                    782:        }
                    783:        check_trace ();
                    784:        if (c > 0)
                    785:                x_do_cycles (c);
                    786: }
                    787: 
                    788: static void do_cycles_post (unsigned long cycles, uae_u32 v)
                    789: {
                    790:        do_cycles (cycles);
                    791: }
                    792: static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
                    793: {
                    794:        do_cycles_ce (cycles);
                    795: }
                    796: static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
                    797: {
                    798: #ifndef WINUAE_FOR_HATARI
                    799:        do_cycles_ce020 (cycles);
                    800: #else
                    801:        do_cycles_ce020_long (cycles);
                    802: #endif
                    803: }
                    804: 
1.1.1.9   root      805: static uae_u8 dcache_check_nommu(uaecptr addr, bool write, uae_u32 size)
                    806: {
                    807:        return ce_cachable[addr >> 16];
                    808: }
                    809: 
                    810: static void mem_access_delay_long_write_ce030_cicheck(uaecptr addr, uae_u32 v)
                    811: {
                    812:        mem_access_delay_long_write_ce020(addr, v);
                    813:        mmu030_cache_state = ce_cachable[addr >> 16];
                    814: }
                    815: static void mem_access_delay_word_write_ce030_cicheck(uaecptr addr, uae_u32 v)
                    816: {
                    817:        mem_access_delay_word_write_ce020(addr, v);
                    818:        mmu030_cache_state = ce_cachable[addr >> 16];
                    819: }
                    820: static void mem_access_delay_byte_write_ce030_cicheck(uaecptr addr, uae_u32 v)
                    821: {
                    822:        mem_access_delay_byte_write_ce020(addr, v);
                    823:        mmu030_cache_state = ce_cachable[addr >> 16];
                    824: }
                    825: 
                    826: static void put_long030_cicheck(uaecptr addr, uae_u32 v)
                    827: {
                    828:        put_long(addr, v);
                    829:        mmu030_cache_state = ce_cachable[addr >> 16];
                    830: }
                    831: static void put_word030_cicheck(uaecptr addr, uae_u32 v)
                    832: {
                    833:        put_word(addr, v);
                    834:        mmu030_cache_state = ce_cachable[addr >> 16];
                    835: }
                    836: static void put_byte030_cicheck(uaecptr addr, uae_u32 v)
                    837: {
                    838:        put_byte(addr, v);
                    839:        mmu030_cache_state = ce_cachable[addr >> 16];
                    840: }
                    841: 
                    842: static uae_u32 (*icache_fetch)(uaecptr);
                    843: static uae_u32 (*dcache_lget)(uaecptr);
                    844: static uae_u32 (*dcache_wget)(uaecptr);
                    845: static uae_u32 (*dcache_bget)(uaecptr);
                    846: static uae_u8 (*dcache_check)(uaecptr, bool, uae_u32);
                    847: static void (*dcache_lput)(uaecptr, uae_u32);
                    848: static void (*dcache_wput)(uaecptr, uae_u32);
                    849: static void (*dcache_bput)(uaecptr, uae_u32);
                    850: 
                    851: uae_u32(*read_data_030_bget)(uaecptr);
                    852: uae_u32(*read_data_030_wget)(uaecptr);
                    853: uae_u32(*read_data_030_lget)(uaecptr);
                    854: void(*write_data_030_bput)(uaecptr,uae_u32);
                    855: void(*write_data_030_wput)(uaecptr,uae_u32);
                    856: void(*write_data_030_lput)(uaecptr,uae_u32);
                    857: 
                    858: uae_u32(*read_data_030_fc_bget)(uaecptr, uae_u32);
                    859: uae_u32(*read_data_030_fc_wget)(uaecptr, uae_u32);
                    860: uae_u32(*read_data_030_fc_lget)(uaecptr, uae_u32);
                    861: void(*write_data_030_fc_bput)(uaecptr, uae_u32, uae_u32);
                    862: void(*write_data_030_fc_wput)(uaecptr, uae_u32, uae_u32);
                    863: void(*write_data_030_fc_lput)(uaecptr, uae_u32, uae_u32);
                    864: 
                    865:  
                    866:  static void set_x_ifetches(void)
1.1.1.7   root      867: {
                    868:        if (m68k_pc_indirect) {
                    869:                if (currprefs.cachesize) {
                    870:                        // indirect via addrbank
                    871:                        x_get_ilong = get_iilong_jit;
                    872:                        x_get_iword = get_iiword_jit;
                    873:                        x_get_ibyte = get_iibyte_jit;
                    874:                        x_next_iword = next_iiword_jit;
                    875:                        x_next_ilong = next_iilong_jit;
                    876:                } else {
                    877:                        // indirect via addrbank
                    878:                        x_get_ilong = get_iilong;
                    879:                        x_get_iword = get_iiword;
                    880:                        x_get_ibyte = get_iibyte;
                    881:                        x_next_iword = next_iiword;
                    882:                        x_next_ilong = next_iilong;
                    883:                }
                    884:        } else {
                    885:                // direct to memory
                    886:                x_get_ilong = get_dilong;
                    887:                x_get_iword = get_diword;
                    888:                x_get_ibyte = get_dibyte;
                    889:                x_next_iword = next_diword;
                    890:                x_next_ilong = next_dilong;
                    891:        }
                    892: }
                    893: 
1.1.1.9   root      894: 
                    895: #ifdef WINUAE_FOR_HATARI
                    896: 
                    897: void (*x_do_cycles_hatari_blitter_save)(unsigned long);
                    898: void (*x_do_cycles_pre_hatari_blitter_save)(unsigned long);
                    899: void (*x_do_cycles_post_hatari_blitter_save)(unsigned long, uae_u32);
                    900: 
                    901: static void do_cycles_ce_post_hatari_blitter (unsigned long cycles, uae_u32 v)
                    902: {
                    903:        do_cycles_ce_hatari_blitter (cycles);
                    904: }
                    905: 
                    906: void set_x_funcs_hatari_blitter (int flag)
                    907: {
                    908:        if ( flag == 0 )
                    909:        {
                    910: //fprintf ( stderr , "restore blitter x_funcs\n" );
                    911:                /* disable blitter, restore functions if needed */
                    912:                if ( x_do_cycles_hatari_blitter_save )
                    913:                {
                    914:                        x_do_cycles                     = x_do_cycles_hatari_blitter_save;
                    915:                        x_do_cycles_pre                 = x_do_cycles_pre_hatari_blitter_save;
                    916:                        x_do_cycles_post                = x_do_cycles_post_hatari_blitter_save;
                    917:                }
                    918:        }
                    919:        else
                    920:        {
                    921: //fprintf ( stderr , "save/set blitter x_funcs\n" );
                    922:                /* save current functions */
                    923:                x_do_cycles_hatari_blitter_save         = x_do_cycles;
                    924:                x_do_cycles_pre_hatari_blitter_save     = x_do_cycles_pre;
                    925:                x_do_cycles_post_hatari_blitter_save    = x_do_cycles_post;
                    926: 
                    927:                /* set blitter specific functions */
                    928:                x_do_cycles                             = do_cycles_ce_hatari_blitter;
                    929:                x_do_cycles_pre                         = do_cycles_ce_hatari_blitter;
                    930:                x_do_cycles_post                        = do_cycles_ce_post_hatari_blitter;
                    931:        }
                    932: }
                    933: 
                    934: #endif
                    935: 
1.1.1.7   root      936: // indirect memory access functions
1.1.1.4   root      937: static void set_x_funcs (void)
                    938: {
1.1.1.7   root      939:        if (currprefs.mmu_model) {
                    940:                if (currprefs.cpu_model == 68060) {
1.1.1.9   root      941: 
1.1.1.7   root      942:                        x_prefetch = get_iword_mmu060;
                    943:                        x_get_ilong = get_ilong_mmu060;
                    944:                        x_get_iword = get_iword_mmu060;
                    945:                        x_get_ibyte = get_ibyte_mmu060;
                    946:                        x_next_iword = next_iword_mmu060;
                    947:                        x_next_ilong = next_ilong_mmu060;
                    948:                        x_put_long = put_long_mmu060;
                    949:                        x_put_word = put_word_mmu060;
                    950:                        x_put_byte = put_byte_mmu060;
                    951:                        x_get_long = get_long_mmu060;
                    952:                        x_get_word = get_word_mmu060;
                    953:                        x_get_byte = get_byte_mmu060;
1.1.1.9   root      954: 
1.1.1.7   root      955:                } else if (currprefs.cpu_model == 68040) {
1.1.1.9   root      956: 
1.1.1.7   root      957:                        x_prefetch = get_iword_mmu040;
                    958:                        x_get_ilong = get_ilong_mmu040;
                    959:                        x_get_iword = get_iword_mmu040;
                    960:                        x_get_ibyte = get_ibyte_mmu040;
                    961:                        x_next_iword = next_iword_mmu040;
                    962:                        x_next_ilong = next_ilong_mmu040;
                    963:                        x_put_long = put_long_mmu040;
                    964:                        x_put_word = put_word_mmu040;
                    965:                        x_put_byte = put_byte_mmu040;
                    966:                        x_get_long = get_long_mmu040;
                    967:                        x_get_word = get_word_mmu040;
                    968:                        x_get_byte = get_byte_mmu040;
1.1.1.9   root      969: 
1.1.1.7   root      970:                } else {
1.1.1.9   root      971: 
                    972:                        if (currprefs.cpu_memory_cycle_exact) {
                    973:                                x_prefetch = get_iword_mmu030c_state;
                    974:                                x_get_ilong = get_ilong_mmu030c_state;
                    975:                                x_get_iword = get_iword_mmu030c_state;
                    976:                                x_get_ibyte = NULL;
                    977:                                x_next_iword = next_iword_mmu030c_state;
                    978:                                x_next_ilong = next_ilong_mmu030c_state;
                    979:                                x_do_cycles = do_cycles;
                    980:                                x_do_cycles_pre = do_cycles;
                    981:                                x_do_cycles_post = do_cycles_post;
                    982:                        } else if (currprefs.cpu_compatible) {
                    983:                                x_prefetch = get_iword_mmu030c_state;
                    984:                                x_get_ilong = get_ilong_mmu030c_state;
                    985:                                x_get_iword = get_iword_mmu030c_state;
                    986:                                x_get_ibyte = NULL;
                    987:                                x_next_iword = next_iword_mmu030c_state;
                    988:                                x_next_ilong = next_ilong_mmu030c_state;
                    989:                                x_do_cycles = do_cycles;
                    990:                                x_do_cycles_pre = do_cycles;
                    991:                                x_do_cycles_post = do_cycles_post;
                    992:                        } else {
                    993:                                x_prefetch = get_iword_mmu030;
                    994:                                x_get_ilong = get_ilong_mmu030;
                    995:                                x_get_iword = get_iword_mmu030;
                    996:                                x_get_ibyte = get_ibyte_mmu030;
                    997:                                x_next_iword = next_iword_mmu030;
                    998:                                x_next_ilong = next_ilong_mmu030;
                    999:                        }
1.1.1.7   root     1000:                        x_put_long = put_long_mmu030;
                   1001:                        x_put_word = put_word_mmu030;
                   1002:                        x_put_byte = put_byte_mmu030;
                   1003:                        x_get_long = get_long_mmu030;
                   1004:                        x_get_word = get_word_mmu030;
                   1005:                        x_get_byte = get_byte_mmu030;
1.1.1.9   root     1006:                        if (currprefs.cpu_data_cache) {
                   1007:                                x_put_long = put_long_dc030;
                   1008:                                x_put_word = put_word_dc030;
                   1009:                                x_put_byte = put_byte_dc030;
                   1010:                                x_get_long = get_long_dc030;
                   1011:                                x_get_word = get_word_dc030;
                   1012:                                x_get_byte = get_byte_dc030;
                   1013:                        }
                   1014: 
1.1.1.7   root     1015:                }
                   1016:                x_do_cycles = do_cycles;
                   1017:                x_do_cycles_pre = do_cycles;
                   1018:                x_do_cycles_post = do_cycles_post;
1.1.1.4   root     1019:        } else if (currprefs.cpu_model < 68020) {
1.1.1.7   root     1020:                // 68000/010
                   1021:                if (currprefs.cpu_cycle_exact) {
                   1022:                        x_prefetch = get_word_ce000_prefetch;
                   1023:                        x_get_ilong = NULL;
                   1024:                        x_get_iword = get_wordi_ce000;
                   1025:                        x_get_ibyte = NULL;
                   1026:                        x_next_iword = NULL;
                   1027:                        x_next_ilong = NULL;
                   1028:                        x_put_long = put_long_ce000;
                   1029:                        x_put_word = put_word_ce000;
                   1030:                        x_put_byte = put_byte_ce000;
                   1031:                        x_get_long = get_long_ce000;
                   1032:                        x_get_word = get_word_ce000;
                   1033:                        x_get_byte = get_byte_ce000;
                   1034:                        x_do_cycles = do_cycles_ce;
                   1035:                        x_do_cycles_pre = do_cycles_ce;
                   1036:                        x_do_cycles_post = do_cycles_ce_post;
1.1.1.8   root     1037:                } else if (currprefs.cpu_memory_cycle_exact) {
                   1038:                        // cpu_memory_cycle_exact + cpu_compatible
                   1039:                        x_prefetch = get_word_000_prefetch;
                   1040:                        x_get_ilong = NULL;
                   1041:                        x_get_iword = get_iiword;
                   1042:                        x_get_ibyte = get_iibyte;
                   1043:                        x_next_iword = NULL;
                   1044:                        x_next_ilong = NULL;
                   1045:                        x_put_long = put_long_ce000;
                   1046:                        x_put_word = put_word_ce000;
                   1047:                        x_put_byte = put_byte_ce000;
                   1048:                        x_get_long = get_long_ce000;
                   1049:                        x_get_word = get_word_ce000;
                   1050:                        x_get_byte = get_byte_ce000;
                   1051:                        x_do_cycles = do_cycles;
                   1052:                        x_do_cycles_pre = do_cycles;
                   1053:                        x_do_cycles_post = do_cycles_post;
1.1.1.7   root     1054:                } else if (currprefs.cpu_compatible) {
1.1.1.8   root     1055:                        // cpu_compatible only
                   1056:                        x_prefetch = get_word_000_prefetch;
1.1.1.7   root     1057:                        x_get_ilong = NULL;
                   1058:                        x_get_iword = get_iiword;
                   1059:                        x_get_ibyte = get_iibyte;
                   1060:                        x_next_iword = NULL;
                   1061:                        x_next_ilong = NULL;
                   1062:                        x_put_long = put_long;
                   1063:                        x_put_word = put_word;
                   1064:                        x_put_byte = put_byte;
                   1065:                        x_get_long = get_long;
                   1066:                        x_get_word = get_word;
                   1067:                        x_get_byte = get_byte;
                   1068:                        x_do_cycles = do_cycles;
                   1069:                        x_do_cycles_pre = do_cycles;
                   1070:                        x_do_cycles_post = do_cycles_post;
                   1071:                } else {
                   1072:                        x_prefetch = NULL;
                   1073:                        x_get_ilong = get_dilong;
                   1074:                        x_get_iword = get_diword;
                   1075:                        x_get_ibyte = get_dibyte;
                   1076:                        x_next_iword = next_diword;
                   1077:                        x_next_ilong = next_dilong;
                   1078:                        x_put_long = put_long;
                   1079:                        x_put_word = put_word;
                   1080:                        x_put_byte = put_byte;
                   1081:                        x_get_long = get_long;
                   1082:                        x_get_word = get_word;
                   1083:                        x_get_byte = get_byte;
                   1084:                        x_do_cycles = do_cycles;
                   1085:                        x_do_cycles_pre = do_cycles;
                   1086:                        x_do_cycles_post = do_cycles_post;
                   1087:                }
                   1088:        } else if (!currprefs.cpu_cycle_exact) {
                   1089:                // 68020+ no ce
1.1.1.8   root     1090:                if (currprefs.cpu_memory_cycle_exact) {
                   1091:                        // cpu_memory_cycle_exact + cpu_compatible
                   1092:                        if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
                   1093:                                x_prefetch = get_word_020_prefetch;
                   1094:                                x_get_ilong = get_long_020_prefetch;
                   1095:                                x_get_iword = get_word_020_prefetch;
                   1096:                                x_get_ibyte = NULL;
                   1097:                                x_next_iword = next_iword_020_prefetch;
                   1098:                                x_next_ilong = next_ilong_020_prefetch;
                   1099:                                x_put_long = put_long_ce020;
                   1100:                                x_put_word = put_word_ce020;
                   1101:                                x_put_byte = put_byte_ce020;
                   1102:                                x_get_long = get_long_ce020;
                   1103:                                x_get_word = get_word_ce020;
                   1104:                                x_get_byte = get_byte_ce020;
                   1105:                                x_do_cycles = do_cycles;
                   1106:                                x_do_cycles_pre = do_cycles;
                   1107:                                x_do_cycles_post = do_cycles_post;
                   1108:                        } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
                   1109:                                x_prefetch = get_word_030_prefetch;
                   1110:                                x_get_ilong = get_long_030_prefetch;
                   1111:                                x_get_iword = get_word_030_prefetch;
                   1112:                                x_get_ibyte = NULL;
                   1113:                                x_next_iword = next_iword_030_prefetch;
                   1114:                                x_next_ilong = next_ilong_030_prefetch;
                   1115:                                x_put_long = put_long_ce030;
                   1116:                                x_put_word = put_word_ce030;
                   1117:                                x_put_byte = put_byte_ce030;
                   1118:                                x_get_long = get_long_ce030;
                   1119:                                x_get_word = get_word_ce030;
                   1120:                                x_get_byte = get_byte_ce030;
                   1121:                                x_do_cycles = do_cycles;
                   1122:                                x_do_cycles_pre = do_cycles;
                   1123:                                x_do_cycles_post = do_cycles_post;
                   1124:                        } else if (currprefs.cpu_model < 68040) {
                   1125:                                // JIT or 68030+ does not have real prefetch only emulation
                   1126:                                x_prefetch = NULL;
                   1127:                                set_x_ifetches();
                   1128:                                x_put_long = put_long;
                   1129:                                x_put_word = put_word;
                   1130:                                x_put_byte = put_byte;
                   1131:                                x_get_long = get_long;
                   1132:                                x_get_word = get_word;
                   1133:                                x_get_byte = get_byte;
                   1134:                                x_do_cycles = do_cycles;
                   1135:                                x_do_cycles_pre = do_cycles;
                   1136:                                x_do_cycles_post = do_cycles_post;
                   1137:                        } else {
                   1138:                                // 68040+ (same as below)
                   1139:                                x_prefetch = NULL;
                   1140:                                x_get_ilong = get_ilong_cache_040;
                   1141:                                x_get_iword = get_iword_cache_040;
                   1142:                                x_get_ibyte = NULL;
                   1143:                                x_next_iword = next_iword_cache040;
                   1144:                                x_next_ilong = next_ilong_cache040;
1.1.1.9   root     1145:                                if (currprefs.cpu_data_cache) {
                   1146:                                        x_put_long = put_long_cache_040;
                   1147:                                        x_put_word = put_word_cache_040;
                   1148:                                        x_put_byte = put_byte_cache_040;
                   1149:                                        x_get_long = get_long_cache_040;
                   1150:                                        x_get_word = get_word_cache_040;
                   1151:                                        x_get_byte = get_byte_cache_040;
                   1152:                                } else {
                   1153:                                        x_get_byte = mem_access_delay_byte_read_c040;
                   1154:                                        x_get_word = mem_access_delay_word_read_c040;
                   1155:                                        x_get_long = mem_access_delay_long_read_c040;
                   1156:                                        x_put_byte = mem_access_delay_byte_write_c040;
                   1157:                                        x_put_word = mem_access_delay_word_write_c040;
                   1158:                                        x_put_long = mem_access_delay_long_write_c040;
                   1159:                                }
1.1.1.8   root     1160:                                x_do_cycles = do_cycles;
                   1161:                                x_do_cycles_pre = do_cycles;
                   1162:                                x_do_cycles_post = do_cycles_post;
                   1163:                        }
                   1164:                } else if (currprefs.cpu_compatible) {
                   1165:                        // cpu_compatible only
1.1.1.7   root     1166:                        if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
1.1.1.8   root     1167:                                x_prefetch = get_word_020_prefetch;
1.1.1.7   root     1168:                                x_get_ilong = get_long_020_prefetch;
                   1169:                                x_get_iword = get_word_020_prefetch;
                   1170:                                x_get_ibyte = NULL;
                   1171:                                x_next_iword = next_iword_020_prefetch;
                   1172:                                x_next_ilong = next_ilong_020_prefetch;
                   1173:                                x_put_long = put_long;
                   1174:                                x_put_word = put_word;
                   1175:                                x_put_byte = put_byte;
                   1176:                                x_get_long = get_long;
                   1177:                                x_get_word = get_word;
                   1178:                                x_get_byte = get_byte;
                   1179:                                x_do_cycles = do_cycles;
                   1180:                                x_do_cycles_pre = do_cycles;
                   1181:                                x_do_cycles_post = do_cycles_post;
                   1182:                        } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
1.1.1.9   root     1183:                                x_prefetch = get_word_030_prefetch;
1.1.1.7   root     1184:                                x_get_ilong = get_long_030_prefetch;
                   1185:                                x_get_iword = get_word_030_prefetch;
                   1186:                                x_get_ibyte = NULL;
                   1187:                                x_next_iword = next_iword_030_prefetch;
                   1188:                                x_next_ilong = next_ilong_030_prefetch;
1.1.1.9   root     1189:                                x_put_long = put_long_030;
                   1190:                                x_put_word = put_word_030;
                   1191:                                x_put_byte = put_byte_030;
                   1192:                                x_get_long = get_long_030;
                   1193:                                x_get_word = get_word_030;
                   1194:                                x_get_byte = get_byte_030;
1.1.1.7   root     1195:                                x_do_cycles = do_cycles;
                   1196:                                x_do_cycles_pre = do_cycles;
                   1197:                                x_do_cycles_post = do_cycles_post;
                   1198:                        } else if (currprefs.cpu_model < 68040) {
                   1199:                                // JIT or 68030+ does not have real prefetch only emulation
                   1200:                                x_prefetch = NULL;
                   1201:                                set_x_ifetches();
                   1202:                                x_put_long = put_long;
                   1203:                                x_put_word = put_word;
                   1204:                                x_put_byte = put_byte;
                   1205:                                x_get_long = get_long;
                   1206:                                x_get_word = get_word;
                   1207:                                x_get_byte = get_byte;
                   1208:                                x_do_cycles = do_cycles;
                   1209:                                x_do_cycles_pre = do_cycles;
                   1210:                                x_do_cycles_post = do_cycles_post;
                   1211:                        } else {
                   1212:                                x_prefetch = NULL;
                   1213:                                x_get_ilong = get_ilong_cache_040;
                   1214:                                x_get_iword = get_iword_cache_040;
                   1215:                                x_get_ibyte = NULL;
                   1216:                                x_next_iword = next_iword_cache040;
                   1217:                                x_next_ilong = next_ilong_cache040;
1.1.1.9   root     1218:                                if (currprefs.cpu_data_cache) {
                   1219:                                        x_put_long = put_long_cache_040;
                   1220:                                        x_put_word = put_word_cache_040;
                   1221:                                        x_put_byte = put_byte_cache_040;
                   1222:                                        x_get_long = get_long_cache_040;
                   1223:                                        x_get_word = get_word_cache_040;
                   1224:                                        x_get_byte = get_byte_cache_040;
                   1225:                                } else {
                   1226:                                        x_put_long = put_long;
                   1227:                                        x_put_word = put_word;
                   1228:                                        x_put_byte = put_byte;
                   1229:                                        x_get_long = get_long;
                   1230:                                        x_get_word = get_word;
                   1231:                                        x_get_byte = get_byte;
                   1232:                                }
1.1.1.7   root     1233:                                x_do_cycles = do_cycles;
                   1234:                                x_do_cycles_pre = do_cycles;
                   1235:                                x_do_cycles_post = do_cycles_post;
                   1236:                        }
                   1237:                } else {
                   1238:                        x_prefetch = NULL;
                   1239:                        set_x_ifetches();
1.1.1.8   root     1240:                        if (currprefs.cachesize) {
                   1241:                                x_put_long = put_long_jit;
                   1242:                                x_put_word = put_word_jit;
                   1243:                                x_put_byte = put_byte_jit;
                   1244:                                x_get_long = get_long_jit;
                   1245:                                x_get_word = get_word_jit;
                   1246:                                x_get_byte = get_byte_jit;
                   1247:                        } else {
                   1248:                                x_put_long = put_long;
                   1249:                                x_put_word = put_word;
                   1250:                                x_put_byte = put_byte;
                   1251:                                x_get_long = get_long;
                   1252:                                x_get_word = get_word;
                   1253:                                x_get_byte = get_byte;
                   1254:                        }
1.1.1.7   root     1255:                        x_do_cycles = do_cycles;
                   1256:                        x_do_cycles_pre = do_cycles;
                   1257:                        x_do_cycles_post = do_cycles_post;
                   1258:                }
                   1259:                // 68020+ cycle exact
1.1.1.4   root     1260:        } else if (currprefs.cpu_model == 68020) {
                   1261:                x_prefetch = get_word_ce020_prefetch;
1.1.1.7   root     1262:                x_get_ilong = get_long_ce020_prefetch;
                   1263:                x_get_iword = get_word_ce020_prefetch;
                   1264:                x_get_ibyte = NULL;
1.1.1.4   root     1265:                x_next_iword = next_iword_020ce;
                   1266:                x_next_ilong = next_ilong_020ce;
                   1267:                x_put_long = put_long_ce020;
                   1268:                x_put_word = put_word_ce020;
                   1269:                x_put_byte = put_byte_ce020;
                   1270:                x_get_long = get_long_ce020;
                   1271:                x_get_word = get_word_ce020;
                   1272:                x_get_byte = get_byte_ce020;
1.1.1.7   root     1273: #ifndef WINUAE_FOR_HATARI
                   1274:                x_do_cycles = do_cycles_ce020;
                   1275:                x_do_cycles_pre = do_cycles_ce020;
                   1276:                x_do_cycles_post = do_cycles_ce020_post;
                   1277: #else
                   1278:                x_do_cycles = do_cycles_ce020_long;
                   1279:                x_do_cycles_pre = do_cycles_ce020_long;
                   1280:                x_do_cycles_post = do_cycles_ce020_post;
                   1281: #endif
                   1282:        } else if (currprefs.cpu_model == 68030) {
1.1.1.4   root     1283:                x_prefetch = get_word_ce030_prefetch;
1.1.1.7   root     1284:                x_get_ilong = get_long_ce030_prefetch;
                   1285:                x_get_iword = get_word_ce030_prefetch;
                   1286:                x_get_ibyte = NULL;
1.1.1.4   root     1287:                x_next_iword = next_iword_030ce;
                   1288:                x_next_ilong = next_ilong_030ce;
1.1.1.9   root     1289:                if (currprefs.cpu_data_cache) {
                   1290:                        x_put_long = put_long_dc030;
                   1291:                        x_put_word = put_word_dc030;
                   1292:                        x_put_byte = put_byte_dc030;
                   1293:                        x_get_long = get_long_dc030;
                   1294:                        x_get_word = get_word_dc030;
                   1295:                        x_get_byte = get_byte_dc030;
                   1296:                } else {
                   1297:                        x_put_long = put_long_ce030;
                   1298:                        x_put_word = put_word_ce030;
                   1299:                        x_put_byte = put_byte_ce030;
                   1300:                        x_get_long = get_long_ce030;
                   1301:                        x_get_word = get_word_ce030;
                   1302:                        x_get_byte = get_byte_ce030;
                   1303:                }
1.1.1.7   root     1304: #ifndef WINUAE_FOR_HATARI
                   1305:                x_do_cycles = do_cycles_ce020;
                   1306:                x_do_cycles_pre = do_cycles_ce020;
                   1307:                x_do_cycles_post = do_cycles_ce020_post;
                   1308: #else
                   1309:                x_do_cycles = do_cycles_ce020_long;
                   1310:                x_do_cycles_pre = do_cycles_ce020_long;
                   1311:                x_do_cycles_post = do_cycles_ce020_post;
                   1312: #endif
                   1313:        } else if (currprefs.cpu_model >= 68040) {
                   1314:                x_prefetch = NULL;
                   1315:                x_get_ilong = get_ilong_cache_040;
                   1316:                x_get_iword = get_iword_cache_040;
                   1317:                x_get_ibyte = NULL;
                   1318:                x_next_iword = next_iword_cache040;
                   1319:                x_next_ilong = next_ilong_cache040;
1.1.1.9   root     1320:                if (currprefs.cpu_data_cache) {
                   1321:                        x_put_long = put_long_cache_040;
                   1322:                        x_put_word = put_word_cache_040;
                   1323:                        x_put_byte = put_byte_cache_040;
                   1324:                        x_get_long = get_long_cache_040;
                   1325:                        x_get_word = get_word_cache_040;
                   1326:                        x_get_byte = get_byte_cache_040;
                   1327:                } else {
                   1328:                        x_get_byte = mem_access_delay_byte_read_c040;
                   1329:                        x_get_word = mem_access_delay_word_read_c040;
                   1330:                        x_get_long = mem_access_delay_long_read_c040;
                   1331:                        x_put_byte = mem_access_delay_byte_write_c040;
                   1332:                        x_put_word = mem_access_delay_word_write_c040;
                   1333:                        x_put_long = mem_access_delay_long_write_c040;
                   1334:                }
1.1.1.7   root     1335: #ifndef WINUAE_FOR_HATARI
                   1336:                x_do_cycles = do_cycles_ce020;
                   1337:                x_do_cycles_pre = do_cycles_ce020;
                   1338:                x_do_cycles_post = do_cycles_ce020_post;
                   1339: #else
                   1340:                x_do_cycles = do_cycles_ce020_long;
                   1341:                x_do_cycles_pre = do_cycles_ce020_long;
                   1342:                x_do_cycles_post = do_cycles_ce020_post;
                   1343: #endif
                   1344:        }
                   1345:        x2_prefetch = x_prefetch;
                   1346:        x2_get_ilong = x_get_ilong;
                   1347:        x2_get_iword = x_get_iword;
                   1348:        x2_get_ibyte = x_get_ibyte;
                   1349:        x2_next_iword = x_next_iword;
                   1350:        x2_next_ilong = x_next_ilong;
                   1351:        x2_put_long = x_put_long;
                   1352:        x2_put_word = x_put_word;
                   1353:        x2_put_byte = x_put_byte;
                   1354:        x2_get_long = x_get_long;
                   1355:        x2_get_word = x_get_word;
                   1356:        x2_get_byte = x_get_byte;
                   1357:        x2_do_cycles = x_do_cycles;
                   1358:        x2_do_cycles_pre = x_do_cycles_pre;
                   1359:        x2_do_cycles_post = x_do_cycles_post;
                   1360: 
                   1361:        if (cpu_tracer > 0) {
                   1362:                x_prefetch = cputracefunc_x_prefetch;
                   1363:                x_get_ilong = cputracefunc_x_get_ilong;
                   1364:                x_get_iword = cputracefunc_x_get_iword;
                   1365:                x_get_ibyte = cputracefunc_x_get_ibyte;
                   1366:                x_next_iword = cputracefunc_x_next_iword;
                   1367:                x_next_ilong = cputracefunc_x_next_ilong;
                   1368:                x_put_long = cputracefunc_x_put_long;
                   1369:                x_put_word = cputracefunc_x_put_word;
                   1370:                x_put_byte = cputracefunc_x_put_byte;
                   1371:                x_get_long = cputracefunc_x_get_long;
                   1372:                x_get_word = cputracefunc_x_get_word;
                   1373:                x_get_byte = cputracefunc_x_get_byte;
                   1374:                x_do_cycles = cputracefunc_x_do_cycles;
                   1375:                x_do_cycles_pre = cputracefunc_x_do_cycles_pre;
                   1376:                x_do_cycles_post = cputracefunc_x_do_cycles_post;
                   1377:        } else if (cpu_tracer < 0) {
                   1378:                if (!check_trace ()) {
                   1379:                        x_prefetch = cputracefunc2_x_prefetch;
                   1380:                        x_get_ilong = cputracefunc2_x_get_ilong;
                   1381:                        x_get_iword = cputracefunc2_x_get_iword;
                   1382:                        x_get_ibyte = cputracefunc2_x_get_ibyte;
                   1383:                        x_next_iword = cputracefunc2_x_next_iword;
                   1384:                        x_next_ilong = cputracefunc2_x_next_ilong;
                   1385:                        x_put_long = cputracefunc2_x_put_long;
                   1386:                        x_put_word = cputracefunc2_x_put_word;
                   1387:                        x_put_byte = cputracefunc2_x_put_byte;
                   1388:                        x_get_long = cputracefunc2_x_get_long;
                   1389:                        x_get_word = cputracefunc2_x_get_word;
                   1390:                        x_get_byte = cputracefunc2_x_get_byte;
                   1391:                        x_do_cycles = cputracefunc2_x_do_cycles;
                   1392:                        x_do_cycles_pre = cputracefunc2_x_do_cycles_pre;
                   1393:                        x_do_cycles_post = cputracefunc2_x_do_cycles_post;
                   1394:                }
                   1395:        }
                   1396: 
                   1397:        set_x_cp_funcs();
                   1398:        mmu_set_funcs();
                   1399:        mmu030_set_funcs();
                   1400: 
1.1.1.9   root     1401:        dcache_lput = put_long;
                   1402:        dcache_wput = put_word;
                   1403:        dcache_bput = put_byte;
                   1404:        dcache_lget = get_long;
                   1405:        dcache_wget = get_word;
                   1406:        dcache_bget = get_byte;
                   1407:        dcache_check = dcache_check_nommu;
                   1408: 
                   1409:        icache_fetch = get_longi;
                   1410:        if (currprefs.cpu_cycle_exact) {
                   1411:                icache_fetch = mem_access_delay_longi_read_ce020;
                   1412:        }
                   1413:        if (currprefs.cpu_model >= 68040 && currprefs.cpu_memory_cycle_exact) {
                   1414:                icache_fetch = mem_access_delay_longi_read_c040;
                   1415:                dcache_bget = mem_access_delay_byte_read_c040;
                   1416:                dcache_wget = mem_access_delay_word_read_c040;
                   1417:                dcache_lget = mem_access_delay_long_read_c040;
                   1418:                dcache_bput = mem_access_delay_byte_write_c040;
                   1419:                dcache_wput = mem_access_delay_word_write_c040;
                   1420:                dcache_lput = mem_access_delay_long_write_c040;
                   1421:        }
                   1422: 
                   1423:        if (currprefs.cpu_model == 68030) {
                   1424: 
                   1425:                if (currprefs.cpu_data_cache) {
                   1426:                        read_data_030_bget = read_dcache030_mmu_bget;
                   1427:                        read_data_030_wget = read_dcache030_mmu_wget;
                   1428:                        read_data_030_lget = read_dcache030_mmu_lget;
                   1429:                        write_data_030_bput = write_dcache030_mmu_bput;
                   1430:                        write_data_030_wput = write_dcache030_mmu_wput;
                   1431:                        write_data_030_lput = write_dcache030_mmu_lput;
                   1432: 
                   1433:                        read_data_030_fc_bget = read_dcache030_bget;
                   1434:                        read_data_030_fc_wget = read_dcache030_wget;
                   1435:                        read_data_030_fc_lget = read_dcache030_lget;
                   1436:                        write_data_030_fc_bput = write_dcache030_bput;
                   1437:                        write_data_030_fc_wput = write_dcache030_wput;
                   1438:                        write_data_030_fc_lput = write_dcache030_lput;
                   1439:                } else {
                   1440:                        read_data_030_bget = dcache_bget;
                   1441:                        read_data_030_wget = dcache_wget;
                   1442:                        read_data_030_lget = dcache_lget;
                   1443:                        write_data_030_bput = dcache_bput;
                   1444:                        write_data_030_wput = dcache_wput;
                   1445:                        write_data_030_lput = dcache_lput;
                   1446: 
                   1447:                        read_data_030_fc_bget = mmu030_get_fc_byte;
                   1448:                        read_data_030_fc_wget = mmu030_get_fc_word;
                   1449:                        read_data_030_fc_lget = mmu030_get_fc_long;
                   1450:                        write_data_030_fc_bput = mmu030_put_fc_byte;
                   1451:                        write_data_030_fc_wput = mmu030_put_fc_word;
                   1452:                        write_data_030_fc_lput = mmu030_put_fc_long;
                   1453:                }
                   1454: 
                   1455:                if (currprefs.mmu_model) {
                   1456:                        if (currprefs.cpu_compatible) {
                   1457:                                icache_fetch = uae_mmu030_get_ilong_fc;
                   1458:                        } else {
                   1459:                                icache_fetch = uae_mmu030_get_ilong;
                   1460:                        }
1.1.1.10! root     1461:                        dcache_lput = uae_mmu030_put_long_fc;
        !          1462:                        dcache_wput = uae_mmu030_put_word_fc;
        !          1463:                        dcache_bput = uae_mmu030_put_byte_fc;
        !          1464:                        dcache_lget = uae_mmu030_get_long_fc;
        !          1465:                        dcache_wget = uae_mmu030_get_word_fc;
        !          1466:                        dcache_bget = uae_mmu030_get_byte_fc;
1.1.1.9   root     1467:                        if (currprefs.cpu_data_cache) {
                   1468:                                read_data_030_bget = read_dcache030_mmu_bget;
                   1469:                                read_data_030_wget = read_dcache030_mmu_wget;
                   1470:                                read_data_030_lget = read_dcache030_mmu_lget;
                   1471:                                write_data_030_bput = write_dcache030_mmu_bput;
                   1472:                                write_data_030_wput = write_dcache030_mmu_wput;
                   1473:                                write_data_030_lput = write_dcache030_mmu_lput;
                   1474:                                dcache_check = uae_mmu030_check_fc;
                   1475:                        } else {
                   1476:                                read_data_030_bget = uae_mmu030_get_byte;
                   1477:                                read_data_030_wget = uae_mmu030_get_word;
                   1478:                                read_data_030_lget = uae_mmu030_get_long;
                   1479:                                write_data_030_bput = uae_mmu030_put_byte;
                   1480:                                write_data_030_wput = uae_mmu030_put_word;
                   1481:                                write_data_030_lput = uae_mmu030_put_long;
                   1482:                        }
                   1483:                } else if (currprefs.cpu_memory_cycle_exact) {
                   1484:                        icache_fetch = mem_access_delay_longi_read_ce020;
                   1485:                        dcache_lget = mem_access_delay_long_read_ce020;
                   1486:                        dcache_wget = mem_access_delay_word_read_ce020;
                   1487:                        dcache_bget = mem_access_delay_byte_read_ce020;
                   1488:                        if (currprefs.cpu_data_cache) {
                   1489:                                dcache_lput = mem_access_delay_long_write_ce030_cicheck;
                   1490:                                dcache_wput = mem_access_delay_word_write_ce030_cicheck;
                   1491:                                dcache_bput = mem_access_delay_byte_write_ce030_cicheck;
                   1492:                        } else {
                   1493:                                dcache_lput = mem_access_delay_long_write_ce020;
                   1494:                                dcache_wput = mem_access_delay_word_write_ce020;
                   1495:                                dcache_bput = mem_access_delay_byte_write_ce020;
                   1496:                        }
                   1497:                } else if (currprefs.cpu_data_cache) {
                   1498:                        dcache_lput = put_long030_cicheck;
                   1499:                        dcache_wput = put_word030_cicheck;
                   1500:                        dcache_bput = put_byte030_cicheck;
                   1501:                        if (currprefs.cpu_data_cache) {
                   1502:                                dcache_lput = mem_access_delay_long_write_ce030_cicheck;
                   1503:                                dcache_wput = mem_access_delay_word_write_ce030_cicheck;
                   1504:                                dcache_bput = mem_access_delay_byte_write_ce030_cicheck;
                   1505:                        } else {
                   1506:                                dcache_lput = mem_access_delay_long_write_ce020;
                   1507:                                dcache_wput = mem_access_delay_word_write_ce020;
                   1508:                                dcache_bput = mem_access_delay_byte_write_ce020;
                   1509:                        }
                   1510:                } else if (currprefs.cpu_data_cache) {
                   1511:                        dcache_lput = put_long030_cicheck;
                   1512:                        dcache_wput = put_word030_cicheck;
                   1513:                        dcache_bput = put_byte030_cicheck;
                   1514:                }
                   1515:        }
1.1.1.7   root     1516: }
                   1517: 
                   1518: bool can_cpu_tracer (void)
                   1519: {
1.1.1.8   root     1520:        return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_memory_cycle_exact;
1.1.1.7   root     1521: }
                   1522: 
                   1523: bool is_cpu_tracer (void)
                   1524: {
                   1525:        return cpu_tracer > 0;
                   1526: }
                   1527: bool set_cpu_tracer (bool state)
                   1528: {
                   1529:        if (cpu_tracer < 0)
                   1530:                return false;
                   1531:        int old = cpu_tracer;
                   1532: #ifndef WINUAE_FOR_HATARI
                   1533:        if (input_record)
                   1534:                state = true;
                   1535: #endif
                   1536:        cpu_tracer = 0;
                   1537:        if (state && can_cpu_tracer ()) {
                   1538:                cpu_tracer = 1;
                   1539:                set_x_funcs ();
                   1540:                if (old != cpu_tracer)
                   1541:                        write_log (_T("CPU tracer enabled\n"));
1.1.1.4   root     1542:        }
1.1.1.7   root     1543:        if (old > 0 && state == false) {
                   1544:                set_x_funcs ();
                   1545:                write_log (_T("CPU tracer disabled\n"));
                   1546:        }
                   1547:        return is_cpu_tracer ();
1.1.1.4   root     1548: }
                   1549: 
1.1.1.9   root     1550: void invalidate_cpu_data_caches(void)
                   1551: {
                   1552:        if (currprefs.cpu_model == 68030) {
1.1.1.10! root     1553:                for (int i = 0; i < CACHELINES030; i++) {
1.1.1.9   root     1554:                        dcaches030[i].valid[0] = 0;
                   1555:                        dcaches030[i].valid[1] = 0;
                   1556:                        dcaches030[i].valid[2] = 0;
                   1557:                        dcaches030[i].valid[3] = 0;
                   1558:                }
                   1559:        } else if (currprefs.cpu_model >= 68040) {
                   1560:                dcachelinecnt = 0;
1.1.1.10! root     1561:                for (int i = 0; i < CACHESETS060; i++) {
        !          1562:                        for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     1563:                                dcaches040[i].valid[j] = false;
                   1564:                        }
                   1565:                }
                   1566:        }
                   1567: }
                   1568: 
1.1.1.7   root     1569: void flush_cpu_caches(bool force)
1.1.1.4   root     1570: {
1.1.1.8   root     1571:        bool doflush = currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact;
1.1.1.4   root     1572: 
                   1573:        if (currprefs.cpu_model == 68020) {
1.1.1.9   root     1574:                if ((regs.cacr & 0x08) || force) { // clear instr cache
1.1.1.10! root     1575:                        for (int i = 0; i < CACHELINES020; i++)
1.1.1.4   root     1576:                                caches020[i].valid = 0;
1.1.1.7   root     1577:                        regs.cacr &= ~0x08;
1.1.1.4   root     1578:                }
                   1579:                if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7   root     1580:                        caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
1.1.1.4   root     1581:                        regs.cacr &= ~0x04;
                   1582:                }
                   1583:        } else if (currprefs.cpu_model == 68030) {
1.1.1.9   root     1584:                if ((regs.cacr & 0x08) || force) { // clear instr cache
1.1.1.7   root     1585:                        if (doflush) {
1.1.1.10! root     1586:                                for (int i = 0; i < CACHELINES030; i++) {
1.1.1.7   root     1587:                                        icaches030[i].valid[0] = 0;
                   1588:                                        icaches030[i].valid[1] = 0;
                   1589:                                        icaches030[i].valid[2] = 0;
                   1590:                                        icaches030[i].valid[3] = 0;
                   1591:                                }
1.1.1.4   root     1592:                        }
1.1.1.7   root     1593:                        regs.cacr &= ~0x08;
1.1.1.4   root     1594:                }
                   1595:                if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7   root     1596:                        icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4   root     1597:                        regs.cacr &= ~0x04;
                   1598:                }
1.1.1.9   root     1599:                if ((regs.cacr & 0x800) || force) { // clear data cache
1.1.1.7   root     1600:                        if (doflush) {
1.1.1.10! root     1601:                                for (int i = 0; i < CACHELINES030; i++) {
1.1.1.7   root     1602:                                        dcaches030[i].valid[0] = 0;
                   1603:                                        dcaches030[i].valid[1] = 0;
                   1604:                                        dcaches030[i].valid[2] = 0;
                   1605:                                        dcaches030[i].valid[3] = 0;
                   1606:                                }
1.1.1.4   root     1607:                        }
                   1608:                        regs.cacr &= ~0x800;
                   1609:                }
                   1610:                if (regs.cacr & 0x400) { // clear entry in data cache
1.1.1.7   root     1611:                        dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4   root     1612:                        regs.cacr &= ~0x400;
                   1613:                }
1.1.1.7   root     1614:        } else if (currprefs.cpu_model >= 68040) {
1.1.1.9   root     1615:                if (doflush && force) {
                   1616:                        mmu_flush_cache();
                   1617:                        icachelinecnt = 0;
                   1618:                        icachehalfline = 0;
1.1.1.10! root     1619:                        for (int i = 0; i < CACHESETS060; i++) {
        !          1620:                                for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     1621:                                        icaches040[i].valid[j] = false;
                   1622:                                }
                   1623:                        }
                   1624:                }
                   1625:        }
                   1626: }
                   1627: 
                   1628: #if VALIDATE_68040_DATACACHE > 1
                   1629: static void validate_dcache040(void)
                   1630: {
1.1.1.10! root     1631:        for (int i = 0; i < cachedsets04060; i++) {
1.1.1.9   root     1632:                struct cache040 *c = &dcaches040[i];
1.1.1.10! root     1633:                for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     1634:                        if (c->valid[j]) {
                   1635:                                uae_u32 addr = (c->tag[j] & cachedtag04060mask) | (i << 4);
                   1636:                                if (addr < 0x200000 || (addr >= 0xd80000 && addr < 0xe00000) || (addr >= 0xe80000 && addr < 0xf00000) || (addr >= 0xa00000 && addr < 0xc00000)) {
                   1637:                                        write_log(_T("Chip RAM or IO address cached! %08x\n"), addr);
                   1638:                                }
1.1.1.10! root     1639:                                for (int k = 0; k < 4; k++) {
1.1.1.9   root     1640:                                        if (!c->dirty[j][k]) {
                   1641:                                                uae_u32 v = get_long(addr + k * 4);
                   1642:                                                if (v != c->data[j][k]) {
                   1643:                                                        write_log(_T("Address %08x data cache mismatch %08x != %08x\n"), addr, v, c->data[j][k]);
                   1644:                                                }
                   1645:                                        }
                   1646:                                }
                   1647:                        }
                   1648:                }
                   1649:        }
                   1650: }
                   1651: #endif
                   1652: 
                   1653: static void dcache040_push_line(int index, int line, bool writethrough, bool invalidate)
                   1654: {
                   1655:        struct cache040 *c = &dcaches040[index];
                   1656: #if VALIDATE_68040_DATACACHE
                   1657:        if (!c->valid[line]) {
                   1658:                write_log("dcache040_push_line pushing invalid line!\n");
                   1659:        }
                   1660: #endif
                   1661:        if (c->gdirty[line]) {
                   1662:                uae_u32 addr = (c->tag[line] & cachedtag04060mask) | (index << 4);
1.1.1.10! root     1663:                for (int i = 0; i < 4; i++) {
1.1.1.9   root     1664:                        if (c->dirty[line][i] || (!writethrough && currprefs.cpu_model == 68060)) {
                   1665:                                dcache_lput(addr + i * 4, c->data[line][i]);
                   1666:                                c->dirty[line][i] = false;
1.1.1.4   root     1667:                        }
                   1668:                }
1.1.1.9   root     1669:                c->gdirty[line] = false;
1.1.1.4   root     1670:        }
1.1.1.9   root     1671:        if (invalidate)
                   1672:                c->valid[line] = false;
                   1673: 
                   1674: #if VALIDATE_68040_DATACACHE > 1
                   1675:        validate_dcache040();
                   1676: #endif
1.1.1.4   root     1677: }
                   1678: 
1.1.1.10! root     1679: static void flush_cpu_caches_040_2(int cache, int scope, uaecptr addr, bool push, bool pushinv)
1.1.1.4   root     1680: {
1.1.1.9   root     1681: 
                   1682: #if VALIDATE_68040_DATACACHE
                   1683:        write_log(_T("push %d %d %d %08x %d %d\n"), cache, scope, areg, addr, push, pushinv);
                   1684: #endif
                   1685: 
                   1686:        if (cache & 2)
                   1687:                regs.prefetch020addr = 0xffffffff;
1.1.1.10! root     1688:        for (int k = 0; k < 2; k++) {
1.1.1.9   root     1689:                if (cache & (1 << k)) {
                   1690:                        if (scope == 3) {
                   1691:                                // all
                   1692:                                if (!k) {
                   1693:                                        // data
1.1.1.10! root     1694:                                        for (int i = 0; i < cachedsets04060; i++) {
1.1.1.9   root     1695:                                                struct cache040 *c = &dcaches040[i];
1.1.1.10! root     1696:                                                for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     1697:                                                        if (c->valid[j]) {
                   1698:                                                                if (push) {
                   1699:                                                                        dcache040_push_line(i, j, false, pushinv);
                   1700:                                                                } else {
                   1701:                                                                        c->valid[j] = false;
                   1702:                                                                }
                   1703:                                                        }
                   1704:                                                }
                   1705:                                        }
                   1706:                                        dcachelinecnt = 0;
                   1707:                                } else {
                   1708:                                        // instruction
                   1709:                                        flush_cpu_caches(true);
                   1710:                                }
                   1711:                        } else {
                   1712:                                uae_u32 pagesize;
                   1713:                                if (scope == 2) {
                   1714:                                        // page
                   1715:                                        pagesize = mmu_pagesize_8k ? 8192 : 4096;
                   1716:                                } else {
                   1717:                                        // line
                   1718:                                        pagesize = 16;
                   1719:                                }
                   1720:                                addr &= ~(pagesize - 1);
1.1.1.10! root     1721:                                uae_u32 j;
1.1.1.9   root     1722:                                for (j = 0; j < pagesize; j += 16, addr += 16) {
                   1723:                                        int index;
                   1724:                                        uae_u32 tag;
                   1725:                                        uae_u32 tagmask;
                   1726:                                        struct cache040 *c;
                   1727:                                        if (k) {
                   1728:                                                tagmask = cacheitag04060mask;
                   1729:                                                index = (addr >> 4) & cacheisets04060mask;
                   1730:                                                c = &icaches040[index];
                   1731:                                        } else {
                   1732:                                                tagmask = cachedtag04060mask;
                   1733:                                                index = (addr >> 4) & cachedsets04060mask;
                   1734:                                                c = &dcaches040[index];
                   1735:                                        }
                   1736:                                        tag = addr & tagmask;
1.1.1.10! root     1737:                                        for (int i = 0; i < CACHELINES040; i++) {
1.1.1.9   root     1738:                                                if (c->valid[i] && c->tag[i] == tag) {
                   1739:                                                        if (push) {
                   1740:                                                                dcache040_push_line(index, i, false, pushinv);
                   1741:                                                        } else {
                   1742:                                                                c->valid[i] = false;
                   1743:                                                        }
                   1744:                                                }
                   1745:                                        }
                   1746:                                }
                   1747:                        }
                   1748:                }
                   1749:        }
1.1.1.10! root     1750: }
        !          1751: 
        !          1752: void flush_cpu_caches_040(uae_u16 opcode)
        !          1753: {
        !          1754:        // 0 (1) = data, 1 (2) = instruction
        !          1755:        int cache = (opcode >> 6) & 3;
        !          1756:        int scope = (opcode >> 3) & 3;
        !          1757:        int areg = opcode & 7;
        !          1758:        uaecptr addr = m68k_areg(regs, areg);
        !          1759:        bool push = (opcode & 0x20) != 0;
        !          1760:        bool pushinv = (regs.cacr & 0x01000000) == 0; // 68060 DPI
        !          1761: 
        !          1762:        flush_cpu_caches_040_2(cache, scope, addr, push, pushinv);
1.1.1.9   root     1763:        mmu_flush_cache();
1.1.1.4   root     1764: }
                   1765: 
1.1.1.10! root     1766: void cpu_invalidate_cache(uaecptr addr, int size)
        !          1767: {
        !          1768:        if (!currprefs.cpu_data_cache)
        !          1769:                return;
        !          1770:        if (currprefs.cpu_model == 68030) {
        !          1771:                uaecptr end = addr + size;
        !          1772:                addr &= ~3;
        !          1773:                while (addr < end) {
        !          1774:                        dcaches030[(addr >> 4) & (CACHELINES030 - 1)].valid[(addr >> 2) & 3] = 0;
        !          1775:                        addr += 4;
        !          1776:                }
        !          1777:        } else if (currprefs.cpu_model >= 68040) {
        !          1778:                uaecptr end = addr + size;
        !          1779:                while (addr < end) {
        !          1780:                        flush_cpu_caches_040_2(0, 1, addr, true, true);
        !          1781:                        addr += 16;
        !          1782:                }
        !          1783:        }
        !          1784: }
        !          1785: 
        !          1786: 
1.1.1.7   root     1787: void set_cpu_caches (bool flush)
1.1.1.4   root     1788: {
1.1.1.7   root     1789:        regs.prefetch020addr = 0xffffffff;
                   1790:        regs.cacheholdingaddr020 = 0xffffffff;
1.1.1.9   root     1791:        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
                   1792: 
                   1793:        // 68060 FIC 1/2 instruction cache
                   1794:        cacheisets04060 = currprefs.cpu_model == 68060 && !(regs.cacr & 0x00002000) ? CACHESETS060 : CACHESETS040;
                   1795:        cacheisets04060mask = cacheisets04060 - 1;
                   1796:        cacheitag04060mask = ~((cacheisets04060 << 4) - 1);
                   1797:        // 68060 FOC 1/2 data cache
                   1798:        cachedsets04060 = currprefs.cpu_model == 68060 && !(regs.cacr & 0x08000000) ? CACHESETS060 : CACHESETS040;
                   1799:        cachedsets04060mask = cachedsets04060 - 1;
                   1800:        cachedtag04060mask = ~((cachedsets04060 << 4) - 1);
                   1801:        cache_lastline = 0;
1.1.1.4   root     1802: 
1.1.1.7   root     1803: #ifdef JIT
                   1804:        if (currprefs.cachesize) {
                   1805:                if (currprefs.cpu_model < 68040) {
                   1806:                        set_cache_state (regs.cacr & 1);
                   1807:                        if (regs.cacr & 0x08) {
1.1.1.9   root     1808:                                flush_icache (3);
1.1.1.7   root     1809:                        }
                   1810:                } else {
                   1811:                        set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
                   1812:                }
                   1813:        }
                   1814: #endif
                   1815:        flush_cpu_caches(flush);
                   1816: }
                   1817: 
                   1818: STATIC_INLINE void count_instr (unsigned int opcode)
                   1819: {
                   1820: }
                   1821: 
                   1822: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
                   1823: {
                   1824:        op_illg (opcode);
                   1825:        return 4;
                   1826: }
                   1827: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
                   1828: {
                   1829:        if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
                   1830:                op_illg (opcode);
                   1831:        else
                   1832:                op_unimpl (opcode);
                   1833:        return 4;
                   1834: }
                   1835: 
1.1.1.9   root     1836: // generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mmu+more compatible, mmu+mc+ce
                   1837: static const struct cputbl *cputbls[6][8] =
1.1.1.7   root     1838: {
                   1839:        // 68000
1.1.1.9   root     1840:        { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL, NULL, NULL },
1.1.1.7   root     1841:        // 68010
1.1.1.9   root     1842:        { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL, NULL, NULL },
1.1.1.7   root     1843:        // 68020
1.1.1.9   root     1844:        { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL, NULL, NULL },
1.1.1.7   root     1845:        // 68030
1.1.1.9   root     1846:        { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff, op_smalltbl_34_ff, op_smalltbl_35_ff },
1.1.1.7   root     1847:        // 68040
1.1.1.9   root     1848:        { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff, op_smalltbl_31_ff, op_smalltbl_31_ff },
1.1.1.7   root     1849:        // 68060
1.1.1.9   root     1850:        { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff, op_smalltbl_33_ff, op_smalltbl_33_ff }
1.1.1.7   root     1851: };
                   1852: 
                   1853: static void build_cpufunctbl (void)
1.1.1.4   root     1854: {
                   1855:        int i, opcnt;
                   1856:        unsigned long opcode;
                   1857:        const struct cputbl *tbl = 0;
1.1.1.7   root     1858:        int lvl, mode;
1.1.1.4   root     1859: 
1.1.1.7   root     1860:        if (!currprefs.cachesize) {
1.1.1.9   root     1861:                if (currprefs.mmu_model) {
                   1862:                        if (currprefs.cpu_cycle_exact)
                   1863:                                mode = 7;
                   1864:                        else if (currprefs.cpu_compatible)
                   1865:                                mode = 6;
                   1866:                        else
                   1867:                                mode = 5;
                   1868:                } else if (currprefs.cpu_cycle_exact) {
1.1.1.8   root     1869:                        mode = 4;
1.1.1.9   root     1870:                } else if (currprefs.cpu_compatible) {
1.1.1.8   root     1871:                        mode = 3;
1.1.1.9   root     1872:                } else {
1.1.1.7   root     1873:                        mode = 0;
1.1.1.9   root     1874:                }
1.1.1.7   root     1875:                m68k_pc_indirect = mode != 0 ? 1 : 0;
                   1876:        } else {
1.1.1.8   root     1877:                mode = 1;
1.1.1.7   root     1878:                m68k_pc_indirect = 0;
                   1879:                if (currprefs.comptrustbyte) {
1.1.1.8   root     1880:                        mode = 2;
1.1.1.7   root     1881:                        m68k_pc_indirect = -1;
                   1882:                }
1.1.1.4   root     1883:        }
1.1.1.7   root     1884:        lvl = (currprefs.cpu_model - 68000) / 10;
                   1885:        if (lvl == 6)
                   1886:                lvl = 5;
                   1887:        tbl = cputbls[lvl][mode];
1.1.1.4   root     1888: 
1.1.1.7   root     1889:        if (tbl == NULL) {
                   1890:                write_log (_T("no CPU emulation cores available CPU=%d!"), currprefs.cpu_model);
1.1.1.4   root     1891:                abort ();
                   1892:        }
                   1893: 
                   1894:        for (opcode = 0; opcode < 65536; opcode++)
                   1895:                cpufunctbl[opcode] = op_illg_1;
                   1896:        for (i = 0; tbl[i].handler != NULL; i++) {
                   1897:                opcode = tbl[i].opcode;
                   1898:                cpufunctbl[opcode] = tbl[i].handler;
1.1.1.7   root     1899:                cpudatatbl[opcode].length = tbl[i].length;
                   1900:                cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
                   1901:                cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
                   1902:                cpudatatbl[opcode].branch = tbl[i].branch;
1.1.1.4   root     1903:        }
                   1904: 
                   1905:        /* hack fpu to 68000/68010 mode */
                   1906:        if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                   1907:                tbl = op_smalltbl_3_ff;
                   1908:                for (i = 0; tbl[i].handler != NULL; i++) {
1.1.1.7   root     1909:                        if ((tbl[i].opcode & 0xfe00) == 0xf200) {
1.1.1.4   root     1910:                                cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1.1.1.7   root     1911:                                cpudatatbl[tbl[i].opcode].length = tbl[i].length;
                   1912:                                cpudatatbl[tbl[i].opcode].disp020[0] = tbl[i].disp020[0];
                   1913:                                cpudatatbl[tbl[i].opcode].disp020[1] = tbl[i].disp020[1];
                   1914:                                cpudatatbl[tbl[i].opcode].branch = tbl[i].branch;
                   1915:                        }
1.1.1.4   root     1916:                }
                   1917:        }
1.1.1.7   root     1918: 
1.1.1.4   root     1919:        opcnt = 0;
                   1920:        for (opcode = 0; opcode < 65536; opcode++) {
                   1921:                cpuop_func *f;
1.1.1.7   root     1922:                struct instr *table = &table68k[opcode];
                   1923: 
                   1924:                if (table->mnemo == i_ILLG)
                   1925:                        continue;               
                   1926: 
                   1927:                /* unimplemented opcode? */
                   1928:                if (table->unimpclev > 0 && lvl >= table->unimpclev) {
1.1.1.8   root     1929:                        if (currprefs.cpu_model == 68060) {
                   1930:                                // remove unimplemented integer instructions
                   1931:                                // unimpclev == 5: not implemented in 68060,
                   1932:                                // generates unimplemented instruction exception.
                   1933:                                if (currprefs.int_no_unimplemented && table->unimpclev == 5) {
                   1934:                                        cpufunctbl[opcode] = op_unimpl_1;
                   1935:                                        continue;
                   1936:                                }
                   1937:                                // remove unimplemented instruction that were removed in previous models,
                   1938:                                // generates normal illegal instruction exception.
                   1939:                                // unimplclev < 5: instruction was removed in 68040 or previous model.
                   1940:                                // clev=4: implemented in 68040 or later. unimpclev=5: not in 68060
                   1941:                                if (table->unimpclev < 5 || (table->clev == 4 && table->unimpclev == 5)) {
1.1.1.7   root     1942:                                        cpufunctbl[opcode] = op_illg_1;
                   1943:                                        continue;
                   1944:                                }
1.1.1.8   root     1945:                        } else {
                   1946:                                cpufunctbl[opcode] = op_illg_1;
                   1947:                                continue;
1.1.1.7   root     1948:                        }
                   1949:                }
1.1.1.4   root     1950: 
                   1951:                if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                   1952:                        /* more hack fpu to 68000/68010 mode */
1.1.1.7   root     1953:                        if (table->clev > lvl && (opcode & 0xfe00) != 0xf200)
1.1.1.4   root     1954:                                continue;
1.1.1.7   root     1955:                } else if (table->clev > lvl) {
1.1.1.4   root     1956:                        continue;
                   1957:                }
                   1958: 
1.1.1.7   root     1959:                if (table->handler != -1) {
                   1960:                        int idx = table->handler;
1.1.1.4   root     1961:                        f = cpufunctbl[idx];
                   1962:                        if (f == op_illg_1)
                   1963:                                abort ();
                   1964:                        cpufunctbl[opcode] = f;
1.1.1.7   root     1965:                        memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
1.1.1.4   root     1966:                        opcnt++;
                   1967:                }
                   1968:        }
1.1.1.7   root     1969:        write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
1.1.1.4   root     1970:                opcnt, lvl,
1.1.1.8   root     1971:                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     1972: #ifdef JIT
1.1.1.8   root     1973:        write_log(_T("JIT: &countdown =  %p\n"), &countdown);
                   1974:        write_log(_T("JIT: &build_comp = %p\n"), &build_comp);
1.1.1.4   root     1975:        build_comp ();
                   1976: #endif
1.1.1.7   root     1977: 
1.1.1.9   root     1978:        write_log(_T("CPU=%d, FPU=%d%s, MMU=%d, JIT%s=%d."),
                   1979:                currprefs.cpu_model,
1.1.1.10! root     1980:                currprefs.fpu_model, currprefs.fpu_model ? (currprefs.fpu_mode > 0 ? _T(" (softfloat)") : (currprefs.fpu_mode < 0 ? _T(" (host 80b)") : _T(" (host 64b)"))) : _T(""),
1.1.1.9   root     1981:                currprefs.mmu_model,
                   1982:                currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
                   1983:                currprefs.cachesize);
1.1.1.7   root     1984: 
                   1985:        regs.address_space_mask = 0xffffffff;
                   1986: #ifndef WINUAE_FOR_HATARI
                   1987:        if (currprefs.cpu_compatible) {
                   1988:                if (currprefs.address_space_24 && currprefs.cpu_model >= 68040)
                   1989:                        currprefs.address_space_24 = false;
                   1990:        }
                   1991: #else
                   1992:        /* Hatari : don't force address_space_24=0 for 68030, as the Falcon has a 68030 LC with only 24 bits */
                   1993:        /* TODO ? Force address_space_24=0 for 68040 ? */
                   1994: #endif
                   1995:        m68k_interrupt_delay = false;
                   1996:        if (currprefs.cpu_cycle_exact) {
                   1997:                if (tbl == op_smalltbl_14_ff || tbl == op_smalltbl_13_ff || tbl == op_smalltbl_21_ff || tbl == op_smalltbl_23_ff)
                   1998:                        m68k_interrupt_delay = true;
                   1999:        }
                   2000: 
                   2001:        if (currprefs.cpu_cycle_exact) {
                   2002:                if (currprefs.cpu_model == 68000)
                   2003:                        write_log(_T(" prefetch and cycle-exact"));
                   2004:                else
                   2005:                        write_log(_T(" ~cycle-exact"));
1.1.1.8   root     2006:        } else if (currprefs.cpu_memory_cycle_exact) {
                   2007:                        write_log(_T(" ~memory-cycle-exact"));
1.1.1.7   root     2008:        } else if (currprefs.cpu_compatible) {
                   2009:                if (currprefs.cpu_model <= 68020) {
                   2010:                        write_log(_T(" prefetch"));
                   2011:                } else {
                   2012:                        write_log(_T(" fake prefetch"));
1.1.1.5   root     2013:                }
1.1.1.4   root     2014:        }
1.1.1.7   root     2015:        if (currprefs.m68k_speed < 0)
                   2016:                write_log(_T(" fast"));
                   2017:        if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
                   2018:                write_log(_T(" no unimplemented integer instructions"));
                   2019:        }
                   2020:        if (currprefs.fpu_no_unimplemented && currprefs.fpu_model) {
                   2021:                write_log(_T(" no unimplemented floating point instructions"));
                   2022:        }
                   2023:        if (currprefs.address_space_24) {
                   2024:                regs.address_space_mask = 0x00ffffff;
                   2025:                write_log(_T(" 24-bit"));
                   2026:        }
                   2027:        write_log(_T("\n"));
1.1.1.4   root     2028: 
1.1.1.7   root     2029:        set_cpu_caches (true);
1.1.1.10! root     2030: #ifndef WINUAE_FOR_HATARI
        !          2031:        target_cpu_speed();
        !          2032: #endif
1.1.1.4   root     2033: }
                   2034: 
1.1.1.7   root     2035: #define CYCLES_DIV 8192
                   2036: static unsigned long cycles_mult;
1.1.1.4   root     2037: 
                   2038: static void update_68k_cycles (void)
                   2039: {
1.1.1.7   root     2040:        cycles_mult = 0;
1.1.1.9   root     2041: #ifdef WINUAE_FOR_HATARI
                   2042:        Log_Printf(LOG_DEBUG, "update cyc speed %d throttle %f clock_mult %d\n", currprefs.m68k_speed, currprefs.m68k_speed_throttle, changed_prefs.cpu_clock_multiplier);
                   2043: #else  /* Don't adjust cycles_mult in Hatari and ignore m68k_speed (forced to 0) */
1.1.1.7   root     2044:        if (currprefs.m68k_speed >= 0 && !currprefs.cpu_cycle_exact) {
                   2045:                if (currprefs.m68k_speed_throttle < 0) {
                   2046:                        cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
                   2047:                } else if (currprefs.m68k_speed_throttle > 0) {
                   2048:                        cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
                   2049:                }
                   2050:        }
                   2051:        if (currprefs.m68k_speed == 0) {
                   2052:                if (currprefs.cpu_model >= 68040) {
                   2053:                        if (!cycles_mult)
                   2054:                                cycles_mult = CYCLES_DIV / 8;
                   2055:                        else
                   2056:                                cycles_mult /= 8;
                   2057:                } else if (currprefs.cpu_model >= 68020) {
                   2058:                        if (!cycles_mult)
                   2059:                                cycles_mult = CYCLES_DIV / 4;
                   2060:                        else
                   2061:                                cycles_mult /= 4;
                   2062:                }
1.1.1.4   root     2063:        }
1.1.1.7   root     2064: #endif
                   2065: 
1.1.1.4   root     2066:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
                   2067:        currprefs.cpu_frequency = changed_prefs.cpu_frequency;
                   2068: 
1.1.1.7   root     2069: #ifndef WINUAE_FOR_HATARI
                   2070:        baseclock = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) * 8;
                   2071: #endif
1.1.1.4   root     2072:        cpucycleunit = CYCLE_UNIT / 2;
                   2073:        if (currprefs.cpu_clock_multiplier) {
                   2074:                if (currprefs.cpu_clock_multiplier >= 256) {
                   2075:                        cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
                   2076:                } else {
                   2077:                        cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
                   2078:                }
1.1.1.7   root     2079:                if (currprefs.cpu_model >= 68040)
                   2080:                        cpucycleunit /= 2;
                   2081: #ifndef WINUAE_FOR_HATARI              /* [NP] TODO : handle any cpu frequency, not just mulltiplier ? */
1.1.1.4   root     2082:        } else if (currprefs.cpu_frequency) {
                   2083:                cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
1.1.1.7   root     2084: #endif
                   2085:        } else if (currprefs.cpu_cycle_exact && currprefs.cpu_clock_multiplier == 0) {
                   2086:                if (currprefs.cpu_model >= 68040) {
                   2087:                        cpucycleunit = CYCLE_UNIT / 16;
                   2088:                } if (currprefs.cpu_model == 68030) {
                   2089:                        cpucycleunit = CYCLE_UNIT / 8;
                   2090:                } else if (currprefs.cpu_model == 68020) {
                   2091:                        cpucycleunit = CYCLE_UNIT / 4;
                   2092:                } else {
                   2093:                        cpucycleunit = CYCLE_UNIT / 2;
                   2094:                }
1.1.1.4   root     2095:        }
                   2096:        if (cpucycleunit < 1)
                   2097:                cpucycleunit = 1;
                   2098:        if (currprefs.cpu_cycle_exact)
1.1.1.7   root     2099:                write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
                   2100: write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
                   2101: #ifndef WINUAE_FOR_HATARI
                   2102:        set_config_changed ();
                   2103: #endif
1.1.1.4   root     2104: }
                   2105: 
                   2106: static void prefs_changed_cpu (void)
                   2107: {
                   2108:        fixup_cpu (&changed_prefs);
1.1.1.8   root     2109:        check_prefs_changed_comp(false);
1.1.1.4   root     2110:        currprefs.cpu_model = changed_prefs.cpu_model;
                   2111:        currprefs.fpu_model = changed_prefs.fpu_model;
1.1.1.9   root     2112:        if (currprefs.mmu_model != changed_prefs.mmu_model) {
                   2113:                int oldmmu = currprefs.mmu_model;
                   2114:                currprefs.mmu_model = changed_prefs.mmu_model;
                   2115:                if (currprefs.mmu_model >= 68040) {
                   2116:                        uae_u32 tcr = regs.tcr;
                   2117:                        mmu_reset();
                   2118:                        mmu_set_tc(tcr);
                   2119:                        mmu_set_super(regs.s != 0);
                   2120:                        mmu_tt_modified();
                   2121:                } else if (currprefs.mmu_model == 68030) {
                   2122:                        mmu030_reset(-1);
                   2123:                        mmu030_flush_atc_all();
                   2124:                        tc_030 = fake_tc_030;
                   2125:                        tt0_030 = fake_tt0_030;
                   2126:                        tt1_030 = fake_tt1_030;
                   2127:                        srp_030 = fake_srp_030;
                   2128:                        crp_030 = fake_crp_030;
                   2129:                        mmu030_decode_tc(tc_030, false);
                   2130:                } else if (oldmmu == 68030) {
                   2131:                        fake_tc_030 = tc_030;
                   2132:                        fake_tt0_030 = tt0_030;
                   2133:                        fake_tt1_030 = tt1_030;
                   2134:                        fake_srp_030 = srp_030;
                   2135:                        fake_crp_030 = crp_030;
                   2136:                }
                   2137:        }
                   2138:        currprefs.mmu_ec = changed_prefs.mmu_ec;
                   2139:        if (currprefs.cpu_compatible != changed_prefs.cpu_compatible) {
                   2140:                currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                   2141:                flush_cpu_caches(true);
                   2142:                invalidate_cpu_data_caches();
                   2143:        }
                   2144:        if (currprefs.cpu_data_cache != changed_prefs.cpu_data_cache) {
                   2145:                currprefs.cpu_data_cache = changed_prefs.cpu_data_cache;
                   2146:                invalidate_cpu_data_caches();
                   2147:        }
1.1.1.8   root     2148:        currprefs.address_space_24 = changed_prefs.address_space_24;
1.1.1.4   root     2149:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1.1.1.8   root     2150:        currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact;
1.1.1.7   root     2151:        currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented;
                   2152:        currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented;
                   2153:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
1.1.1.4   root     2154: }
                   2155: 
1.1.1.7   root     2156: static int check_prefs_changed_cpu2(void)
1.1.1.4   root     2157: {
1.1.1.7   root     2158:        int changed = 0;
1.1.1.4   root     2159: 
                   2160: #ifdef JIT
1.1.1.8   root     2161:        changed = check_prefs_changed_comp(true) ? 1 : 0;
1.1.1.4   root     2162: #endif
                   2163:        if (changed
                   2164:                || currprefs.cpu_model != changed_prefs.cpu_model
                   2165:                || currprefs.fpu_model != changed_prefs.fpu_model
                   2166:                || currprefs.mmu_model != changed_prefs.mmu_model
1.1.1.9   root     2167:                || currprefs.mmu_ec != changed_prefs.mmu_ec
                   2168:                || currprefs.cpu_data_cache != changed_prefs.cpu_data_cache
1.1.1.8   root     2169:                || currprefs.address_space_24 != changed_prefs.address_space_24  /* WINUAE_FOR_HATARI */
1.1.1.7   root     2170:                || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
                   2171:                || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
1.1.1.4   root     2172:                || currprefs.cpu_compatible != changed_prefs.cpu_compatible
1.1.1.8   root     2173:                || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact
1.1.1.9   root     2174:                || currprefs.cpu_memory_cycle_exact != changed_prefs.cpu_memory_cycle_exact
1.1.1.10! root     2175:                || currprefs.fpu_mode != changed_prefs.fpu_mode) {
1.1.1.7   root     2176:                        cpu_prefs_changed_flag |= 1;
1.1.1.4   root     2177:        }
                   2178:        if (changed
                   2179:                || currprefs.m68k_speed != changed_prefs.m68k_speed
1.1.1.7   root     2180:                || currprefs.m68k_speed_throttle != changed_prefs.m68k_speed_throttle
1.1.1.4   root     2181:                || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
1.1.1.7   root     2182:                || currprefs.reset_delay != changed_prefs.reset_delay
1.1.1.4   root     2183:                || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
1.1.1.7   root     2184:                        cpu_prefs_changed_flag |= 2;
1.1.1.4   root     2185:        }
1.1.1.7   root     2186:        return cpu_prefs_changed_flag;
                   2187: }
1.1.1.4   root     2188: 
1.1.1.7   root     2189: void check_prefs_changed_cpu(void)
                   2190: {
1.1.1.8   root     2191: #ifndef WINUAE_FOR_HATARI      /* [NP] TODO : handle cpu change on the fly ? */
1.1.1.7   root     2192:        if (!config_changed)
                   2193:                return;
1.1.1.8   root     2194: #endif
1.1.1.4   root     2195: 
1.1.1.7   root     2196:        currprefs.cpu_idle = changed_prefs.cpu_idle;
                   2197:        currprefs.ppc_cpu_idle = changed_prefs.ppc_cpu_idle;
                   2198:        currprefs.reset_delay = changed_prefs.reset_delay;
                   2199: 
                   2200:        if (check_prefs_changed_cpu2()) {
                   2201:                set_special(SPCFLAG_MODE_CHANGE);
                   2202:                reset_frame_rate_hack();
                   2203:        }
1.1.1.4   root     2204: }
                   2205: 
                   2206: void init_m68k (void)
                   2207: {
                   2208:        prefs_changed_cpu ();
                   2209:        update_68k_cycles ();
                   2210: 
1.1.1.10! root     2211:        for (int i = 0 ; i < 256 ; i++) {
1.1.1.4   root     2212:                int j;
                   2213:                for (j = 0 ; j < 8 ; j++) {
                   2214:                        if (i & (1 << j)) break;
                   2215:                }
                   2216:                movem_index1[i] = j;
1.1.1.7   root     2217:                movem_index2[i] = 7 - j;
1.1.1.4   root     2218:                movem_next[i] = i & (~(1 << j));
                   2219:        }
                   2220: 
                   2221: #if COUNT_INSTRS
                   2222:        {
                   2223:                FILE *f = fopen (icountfilename (), "r");
                   2224:                memset (instrcount, 0, sizeof instrcount);
                   2225:                if (f) {
                   2226:                        uae_u32 opcode, count, total;
                   2227:                        TCHAR name[20];
1.1.1.7   root     2228:                        write_log (_T("Reading instruction count file...\n"));
1.1.1.4   root     2229:                        fscanf (f, "Total: %lu\n", &total);
1.1.1.7   root     2230:                        while (fscanf (f, "%x: %lu %s\n", &opcode, &count, name) == 3) {
1.1.1.4   root     2231:                                instrcount[opcode] = count;
                   2232:                        }
                   2233:                        fclose (f);
                   2234:                }
                   2235:        }
                   2236: #endif
                   2237: 
                   2238:        read_table68k ();
                   2239:        do_merges ();
                   2240: 
1.1.1.7   root     2241:        write_log (_T("%d CPU functions\n"), nr_cpuop_funcs);
1.1.1.4   root     2242: }
                   2243: 
                   2244: struct regstruct regs, mmu_backup_regs;
                   2245: struct flag_struct regflags;
1.1.1.7   root     2246: static int m68kpc_offset;
1.1.1.4   root     2247: 
1.1.1.9   root     2248: static const TCHAR *fpsizes[] = {
                   2249:        _T("L"),
                   2250:        _T("S"),
                   2251:        _T("X"),
                   2252:        _T("P"),
                   2253:        _T("W"),
                   2254:        _T("D"),
                   2255:        _T("B"),
                   2256:        _T("P")
                   2257: };
                   2258: static const int fpsizeconv[] = {
                   2259:        sz_long,
                   2260:        sz_single,
                   2261:        sz_extended,
                   2262:        sz_packed,
                   2263:        sz_word,
                   2264:        sz_double,
                   2265:        sz_byte,
                   2266:        sz_packed
                   2267: };
                   2268: static const int datasizes[] = {
                   2269:        1,
                   2270:        2,
                   2271:        4,
                   2272:        4,
                   2273:        8,
                   2274:        12,
                   2275:        12
                   2276: };
                   2277: 
                   2278: static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size)
                   2279: {
                   2280:        struct mnemolookup *lookup;
                   2281:        struct instr *table = &table68k[opcode];
                   2282: 
1.1.1.10! root     2283: 
        !          2284: #ifndef WINUAE_FOR_HATARI
        !          2285:        if (addr >= 0xe90000 && addr < 0xf00000)
        !          2286:                goto skip;
        !          2287:        if (addr >= 0xdff000 && addr < 0xe00000)
        !          2288:                goto skip;
        !          2289: #endif
        !          2290: 
1.1.1.9   root     2291:        for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++)
                   2292:                ;
                   2293:        if (!(lookup->flags & 1))
1.1.1.10! root     2294:                goto skip;
1.1.1.9   root     2295:        buffer += _tcslen(buffer);
                   2296:        if (debug_safe_addr(addr, datasizes[size])) {
                   2297:                bool cached = false;
                   2298:                switch (size)
                   2299:                {
                   2300:                        case sz_byte:
                   2301:                        {
                   2302:                                uae_u8 v = get_byte_cache_debug(addr, &cached);
                   2303:                                uae_u8 v2 = v;
                   2304:                                if (cached)
                   2305:                                        v2 = get_byte_debug(addr);
                   2306:                                if (v != v2) {
                   2307:                                        _stprintf(buffer, _T(" [%02x:%02x]"), v, v2);
                   2308:                                } else {
                   2309:                                        _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v);
                   2310:                                }
                   2311:                        }
                   2312:                        break;
                   2313:                        case sz_word:
                   2314:                        {
                   2315:                                uae_u16 v = get_word_cache_debug(addr, &cached);
                   2316:                                uae_u16 v2 = v;
                   2317:                                if (cached)
                   2318:                                        v2 = get_word_debug(addr);
                   2319:                                if (v != v2) {
                   2320:                                        _stprintf(buffer, _T(" [%04x:%04x]"), v, v2);
                   2321:                                } else {
                   2322:                                        _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v);
                   2323:                                }
                   2324:                        }
                   2325:                        break;
                   2326:                        case sz_long:
                   2327:                        {
                   2328:                                uae_u32 v = get_long_cache_debug(addr, &cached);
                   2329:                                uae_u32 v2 = v;
                   2330:                                if (cached)
                   2331:                                        v2 = get_long_debug(addr);
                   2332:                                if (v != v2) {
                   2333:                                        _stprintf(buffer, _T(" [%08x:%08x]"), v, v2);
                   2334:                                } else {
                   2335:                                        _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v);
                   2336:                                }
                   2337:                        }
                   2338:                        break;
                   2339:                        case sz_single:
                   2340:                        {
                   2341:                                fpdata fp;
                   2342:                                fpp_to_single(&fp, get_long_debug(addr));
                   2343:                                _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
                   2344:                        }
                   2345:                        break;
                   2346:                        case sz_double:
                   2347:                        {
                   2348:                                fpdata fp;
                   2349:                                fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4));
                   2350:                                _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
                   2351:                        }
                   2352:                        break;
                   2353:                        case sz_extended:
                   2354:                        {
                   2355:                                fpdata fp;
                   2356:                                fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
                   2357:                                _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
                   2358:                                break;
                   2359:                        }
                   2360:                        case sz_packed:
                   2361:                                _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
                   2362:                                break;
                   2363:                }
                   2364:        }
1.1.1.10! root     2365: skip:
        !          2366: #ifndef WINUAE_FOR_HATARI
        !          2367:        for (int i = 0; i < size; i++) {
        !          2368:                TCHAR name[256];
        !          2369:                if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) {
        !          2370:                        _stprintf(buffer + _tcslen(buffer), _T(" %s"), name);
        !          2371:                }
        !          2372:        }
        !          2373: #else
        !          2374:        return;
        !          2375: #endif
1.1.1.9   root     2376: }
1.1.1.4   root     2377: 
1.1.1.10! root     2378: static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name)
1.1.1.4   root     2379: {
1.1.1.10! root     2380:        uaecptr addr;
1.1.1.4   root     2381:        uae_u16 dp;
                   2382:        int r;
                   2383:        uae_u32 dispreg;
1.1.1.10! root     2384:        uaecptr pc = *pcp;
        !          2385:        TCHAR mult[20];
        !          2386: 
        !          2387:        dp = get_iword_debug(pc);
        !          2388:        pc += 2;
        !          2389: 
        !          2390:        r = (dp & 0x7000) >> 12; // REGISTER
        !          2391: 
        !          2392:        dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r);
        !          2393:        if (!(dp & 0x800)) { // W/L
        !          2394:                dispreg = (uae_s32)(uae_s16)(dispreg);
        !          2395:        }
        !          2396: 
        !          2397:        if (currprefs.cpu_model >= 68020) {
        !          2398:                dispreg <<= (dp >> 9) & 3; // SCALE
        !          2399:        }
        !          2400: 
        !          2401:        int m = 1 << ((dp >> 9) & 3);
        !          2402:        mult[0] = 0;
        !          2403:        if (m > 1) {
        !          2404:                _stprintf(mult, _T("*%d"), m);
        !          2405:        }
        !          2406: 
        !          2407:        buffer[0] = 0;
        !          2408:        if ((dp & 0x100) && currprefs.cpu_model >= 68020) {
        !          2409:                TCHAR dr[20];
        !          2410:                // Full format extension (68020+)
        !          2411:                uae_s32 outer = 0, disp = 0;
        !          2412:                if (dp & 0x80) { // BS (base register suppress)
        !          2413:                        base = 0;
        !          2414:                        name = NULL;
        !          2415:                }
        !          2416:                _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
        !          2417:                if (dp & 0x40) {
        !          2418:                        dispreg = 0;
        !          2419:                        dr[0] = 0;
        !          2420:                }
        !          2421: 
        !          2422:                _tcscpy(buffer, _T("("));
        !          2423:                TCHAR *p = buffer + _tcslen(buffer);
        !          2424: 
        !          2425:                if (dp & 3) {
        !          2426:                        _stprintf(p, _T("["));
        !          2427:                        p += _tcslen(p);
        !          2428:                }
        !          2429: 
        !          2430:                if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD)
        !          2431:                        disp = (uae_s32)(uae_s16)get_iword_debug(pc);
        !          2432:                        _stprintf(p, _T("$%04x,"), (uae_s16)disp);
        !          2433:                        p += _tcslen(p);
        !          2434:                        pc += 2;
        !          2435:                        base += disp;
        !          2436:                } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG)
        !          2437:                        disp = get_ilong_debug(pc);
        !          2438:                        _stprintf(p, _T("$%08x,"), disp);
        !          2439:                        p += _tcslen(p);
        !          2440:                        pc += 4;
        !          2441:                        base += disp;
        !          2442:                }
        !          2443: 
        !          2444:                if ((dp & 0x04) == 0x00 && name) {
        !          2445:                        _stprintf(p, _T("%s,"), name);
        !          2446:                        p += _tcslen(p);
        !          2447:                }
        !          2448: 
        !          2449:                if (dr[0] && (dp & 0x04) == 0) {
        !          2450:                        _stprintf(p, _T("%s%s,"), dr, mult);
        !          2451:                        p += _tcslen(p);
        !          2452:                }
        !          2453: 
        !          2454:                if (dp & 3) {
        !          2455:                        if (p[-1] == ',')
        !          2456:                                p--;
        !          2457:                        _stprintf(p, _T("],"));
        !          2458:                        p += _tcslen(p);
        !          2459:                }
        !          2460: 
        !          2461:                if (dr[0] && (dp & 0x04) != 0) {
        !          2462:                        _stprintf(p, _T("%s%s,"), dr, mult);
        !          2463:                        p += _tcslen(p);
        !          2464:                }
        !          2465: 
        !          2466:                if ((dp & 0x03) == 0x02) {
        !          2467:                        outer = (uae_s32)(uae_s16)get_iword_debug(pc);
        !          2468:                        _stprintf(p, _T("$%04x,"), (uae_s16)outer);
        !          2469:                        p += _tcslen(p);
        !          2470:                        pc += 2;
        !          2471:                } else  if ((dp & 0x03) == 0x03) {
        !          2472:                        outer = get_ilong_debug(pc);
        !          2473:                        _stprintf(p, _T("$%08x,"), outer);
        !          2474:                        p += _tcslen(p);
        !          2475:                        pc += 4;
        !          2476:                }
        !          2477: 
        !          2478:                if (p[-1] == ',')
        !          2479:                        p--;
        !          2480:                _stprintf(p, _T(")"));
        !          2481:                p += _tcslen(p);
        !          2482: 
        !          2483:                if ((dp & 0x4) == 0)
        !          2484:                        base += dispreg;
        !          2485:                if (dp & 0x3)
        !          2486:                        base = get_long_debug(base);
        !          2487:                if (dp & 0x4)
        !          2488:                        base += dispreg;
        !          2489: 
        !          2490:                addr = base + outer;
        !          2491: 
        !          2492:                _stprintf(p, _T(" == $%08x"), addr);
        !          2493:                p += _tcslen(p);
        !          2494: 
        !          2495:        } else {
        !          2496:                // Brief format extension
        !          2497:                TCHAR regstr[20];
        !          2498:                uae_s8 disp8 = dp & 0xFF;
        !          2499: 
        !          2500:                regstr[0] = 0;
        !          2501:                _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
        !          2502:                addr = base + (uae_s32)((uae_s8)disp8) + dispreg;
        !          2503:                _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, disp8, addr);
        !          2504:                if (dp & 0x100) {
        !          2505:                        _tcscat(buffer, _T(" (68020+)"));
        !          2506:                }
        !          2507:        }
        !          2508: 
        !          2509:        *pcp = pc;
        !          2510:        return addr;
        !          2511: }
        !          2512: 
        !          2513: static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
        !          2514: {
1.1.1.7   root     2515:        uaecptr addr = pc;
1.1.1.10! root     2516:        uae_s16 disp16;
1.1.1.4   root     2517:        uae_s32 offset = 0;
                   2518:        TCHAR buffer[80];
                   2519: 
                   2520:        switch (mode){
                   2521:        case Dreg:
1.1.1.7   root     2522:                _stprintf (buffer, _T("D%d"), reg);
1.1.1.4   root     2523:                break;
                   2524:        case Areg:
1.1.1.7   root     2525:                _stprintf (buffer, _T("A%d"), reg);
1.1.1.4   root     2526:                break;
                   2527:        case Aind:
1.1.1.7   root     2528:                _stprintf (buffer, _T("(A%d)"), reg);
1.1.1.4   root     2529:                addr = regs.regs[reg + 8];
1.1.1.9   root     2530:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2531:                break;
                   2532:        case Aipi:
1.1.1.7   root     2533:                _stprintf (buffer, _T("(A%d)+"), reg);
1.1.1.4   root     2534:                addr = regs.regs[reg + 8];
1.1.1.9   root     2535:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2536:                break;
                   2537:        case Apdi:
1.1.1.7   root     2538:                _stprintf (buffer, _T("-(A%d)"), reg);
1.1.1.4   root     2539:                addr = regs.regs[reg + 8];
1.1.1.9   root     2540:                showea_val(buffer, opcode, addr - datasizes[size], size);
1.1.1.4   root     2541:                break;
                   2542:        case Ad16:
                   2543:                {
1.1.1.10! root     2544:                        TCHAR offtxt[8];
1.1.1.7   root     2545:                        disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4   root     2546:                        if (disp16 < 0)
1.1.1.7   root     2547:                                _stprintf (offtxt, _T("-$%04x"), -disp16);
1.1.1.4   root     2548:                        else
1.1.1.7   root     2549:                                _stprintf (offtxt, _T("$%04x"), disp16);
1.1.1.4   root     2550:                        addr = m68k_areg (regs, reg) + disp16;
1.1.1.10! root     2551:                        _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr);
1.1.1.9   root     2552:                        showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2553:                }
                   2554:                break;
                   2555:        case Ad8r:
1.1.1.10! root     2556:                {
1.1.1.4   root     2557:                        TCHAR name[10];
1.1.1.10! root     2558:                        _stprintf(name, _T("A%d"), reg);
        !          2559:                        addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name);
        !          2560:                        showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2561:                }
                   2562:                break;
                   2563:        case PC16:
1.1.1.7   root     2564:                disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4   root     2565:                addr += (uae_s16)disp16;
1.1.1.7   root     2566:                _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
1.1.1.9   root     2567:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2568:                break;
                   2569:        case PC8r:
1.1.1.10! root     2570:                {
        !          2571:                        addr = ShowEA_disp(&pc, addr, buffer, _T("PC"));
        !          2572:                        showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2573:                }
                   2574:                break;
                   2575:        case absw:
1.1.1.7   root     2576:                addr = (uae_s32)(uae_s16)get_iword_debug (pc);
1.1.1.9   root     2577:                _stprintf (buffer, _T("$%04x"), (uae_u16)addr);
1.1.1.7   root     2578:                pc += 2;
1.1.1.9   root     2579:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2580:                break;
                   2581:        case absl:
1.1.1.7   root     2582:                addr = get_ilong_debug (pc);
                   2583:                _stprintf (buffer, _T("$%08x"), addr);
                   2584:                pc += 4;
1.1.1.9   root     2585:                showea_val(buffer, opcode, addr, size);
1.1.1.4   root     2586:                break;
                   2587:        case imm:
                   2588:                switch (size){
                   2589:                case sz_byte:
1.1.1.7   root     2590:                        _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
                   2591:                        pc += 2;
1.1.1.4   root     2592:                        break;
                   2593:                case sz_word:
1.1.1.7   root     2594:                        _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
                   2595:                        pc += 2;
1.1.1.4   root     2596:                        break;
                   2597:                case sz_long:
1.1.1.7   root     2598:                        _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
                   2599:                        pc += 4;
                   2600:                        break;
                   2601:                case sz_single:
                   2602:                        {
                   2603:                                fpdata fp;
1.1.1.9   root     2604:                                fpp_to_single(&fp, get_ilong_debug(pc));
                   2605:                                _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
1.1.1.7   root     2606:                                pc += 4;
                   2607:                        }
                   2608:                        break;
                   2609:                case sz_double:
                   2610:                        {
                   2611:                                fpdata fp;
1.1.1.9   root     2612:                                fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
                   2613:                                _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
1.1.1.7   root     2614:                                pc += 8;
                   2615:                        }
                   2616:                        break;
                   2617:                case sz_extended:
                   2618:                {
                   2619:                        fpdata fp;
1.1.1.9   root     2620:                        fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
                   2621:                        _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
1.1.1.7   root     2622:                        pc += 12;
                   2623:                        break;
                   2624:                }
                   2625:                case sz_packed:
                   2626:                        _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
                   2627:                        pc += 12;
1.1.1.4   root     2628:                        break;
                   2629:                default:
                   2630:                        break;
                   2631:                }
                   2632:                break;
                   2633:        case imm0:
1.1.1.7   root     2634:                offset = (uae_s32)(uae_s8)get_iword_debug (pc);
                   2635:                _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
                   2636:                addr = pc + 2 + offset;
1.1.1.10! root     2637:                if ((opcode & 0xf000) == 0x6000) {
        !          2638:                        showea_val(buffer, opcode, addr, 1);
        !          2639:                }
1.1.1.7   root     2640:                pc += 2;
1.1.1.4   root     2641:                break;
                   2642:        case imm1:
1.1.1.7   root     2643:                offset = (uae_s32)(uae_s16)get_iword_debug (pc);
1.1.1.4   root     2644:                buffer[0] = 0;
1.1.1.7   root     2645:                _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
                   2646:                addr = pc + offset;
1.1.1.10! root     2647:                if ((opcode & 0xf000) == 0x6000) {
        !          2648:                        showea_val(buffer, opcode, addr, 2);
        !          2649:                }
1.1.1.7   root     2650:                pc += 2;
1.1.1.4   root     2651:                break;
                   2652:        case imm2:
1.1.1.7   root     2653:                offset = (uae_s32)get_ilong_debug (pc);
                   2654:                _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
                   2655:                addr = pc + offset;
1.1.1.10! root     2656:                if ((opcode & 0xf000) == 0x6000) {
        !          2657:                        showea_val(buffer, opcode, addr, 4);
        !          2658:                }
1.1.1.7   root     2659:                pc += 4;
1.1.1.4   root     2660:                break;
                   2661:        case immi:
                   2662:                offset = (uae_s32)(uae_s8)(reg & 0xff);
1.1.1.9   root     2663:                _stprintf (buffer, _T("#$%02x"), (uae_u8)offset);
1.1.1.7   root     2664:                addr = pc + offset;
1.1.1.4   root     2665:                break;
                   2666:        default:
                   2667:                break;
                   2668:        }
1.1.1.10! root     2669:        if (buf == NULL)
1.1.1.7   root     2670:                f_out (f, _T("%s"), buffer);
1.1.1.4   root     2671:        else
                   2672:                _tcscat (buf, buffer);
                   2673:        if (eaddr)
                   2674:                *eaddr = addr;
1.1.1.7   root     2675:        return pc;
1.1.1.4   root     2676: }
                   2677: 
                   2678: #if 0
                   2679: /* The plan is that this will take over the job of exception 3 handling -
                   2680: * the CPU emulation functions will just do a longjmp to m68k_go whenever
                   2681: * they hit an odd address. */
                   2682: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
                   2683: {
                   2684:        uae_u16 dp;
                   2685:        uae_s8 disp8;
                   2686:        uae_s16 disp16;
                   2687:        int r;
                   2688:        uae_u32 dispreg;
                   2689:        uaecptr addr;
                   2690:        uae_s32 offset = 0;
                   2691: 
                   2692:        switch (mode){
                   2693:        case Dreg:
                   2694:                *val = m68k_dreg (regs, reg);
                   2695:                return 1;
                   2696:        case Areg:
                   2697:                *val = m68k_areg (regs, reg);
                   2698:                return 1;
                   2699: 
                   2700:        case Aind:
                   2701:        case Aipi:
                   2702:                addr = m68k_areg (regs, reg);
                   2703:                break;
                   2704:        case Apdi:
                   2705:                addr = m68k_areg (regs, reg);
                   2706:                break;
                   2707:        case Ad16:
                   2708:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   2709:                addr = m68k_areg (regs, reg) + (uae_s16)disp16;
                   2710:                break;
                   2711:        case Ad8r:
                   2712:                addr = m68k_areg (regs, reg);
                   2713: d8r_common:
                   2714:                dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   2715:                disp8 = dp & 0xFF;
                   2716:                r = (dp & 0x7000) >> 12;
                   2717:                dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                   2718:                if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                   2719:                dispreg <<= (dp >> 9) & 3;
                   2720: 
                   2721:                if (dp & 0x100) {
                   2722:                        uae_s32 outer = 0, disp = 0;
                   2723:                        uae_s32 base = addr;
                   2724:                        if (dp & 0x80) base = 0;
                   2725:                        if (dp & 0x40) dispreg = 0;
                   2726:                        if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                   2727:                        if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
                   2728:                        base += disp;
                   2729: 
                   2730:                        if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                   2731:                        if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
                   2732: 
                   2733:                        if (!(dp & 4)) base += dispreg;
                   2734:                        if (dp & 3) base = get_long (base);
                   2735:                        if (dp & 4) base += dispreg;
                   2736: 
                   2737:                        addr = base + outer;
                   2738:                } else {
                   2739:                        addr += (uae_s32)((uae_s8)disp8) + dispreg;
                   2740:                }
                   2741:                break;
                   2742:        case PC16:
                   2743:                addr = m68k_getpc () + m68kpc_offset;
                   2744:                disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
                   2745:                addr += (uae_s16)disp16;
                   2746:                break;
                   2747:        case PC8r:
                   2748:                addr = m68k_getpc () + m68kpc_offset;
                   2749:                goto d8r_common;
                   2750:        case absw:
                   2751:                addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                   2752:                m68kpc_offset += 2;
                   2753:                break;
                   2754:        case absl:
                   2755:                addr = get_ilong_1 (m68kpc_offset);
                   2756:                m68kpc_offset += 4;
                   2757:                break;
                   2758:        case imm:
                   2759:                switch (size){
                   2760:                case sz_byte:
                   2761:                        *val = get_iword_1 (m68kpc_offset) & 0xff;
                   2762:                        m68kpc_offset += 2;
                   2763:                        break;
                   2764:                case sz_word:
                   2765:                        *val = get_iword_1 (m68kpc_offset) & 0xffff;
                   2766:                        m68kpc_offset += 2;
                   2767:                        break;
                   2768:                case sz_long:
                   2769:                        *val = get_ilong_1 (m68kpc_offset);
                   2770:                        m68kpc_offset += 4;
                   2771:                        break;
                   2772:                default:
                   2773:                        break;
                   2774:                }
                   2775:                return 1;
                   2776:        case imm0:
                   2777:                *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
                   2778:                m68kpc_offset += 2;
                   2779:                return 1;
                   2780:        case imm1:
                   2781:                *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                   2782:                m68kpc_offset += 2;
                   2783:                return 1;
                   2784:        case imm2:
                   2785:                *val = get_ilong_1 (m68kpc_offset);
                   2786:                m68kpc_offset += 4;
                   2787:                return 1;
                   2788:        case immi:
                   2789:                *val = (uae_s32)(uae_s8)(reg & 0xff);
                   2790:                return 1;
                   2791:        default:
                   2792:                addr = 0;
                   2793:                break;
                   2794:        }
                   2795:        if ((addr & 1) == 0)
                   2796:                return 1;
                   2797: 
                   2798:        last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
                   2799:        last_fault_for_exception_3 = addr;
                   2800:        last_writeaccess_for_exception_3 = 0;
                   2801:        last_instructionaccess_for_exception_3 = 0;
                   2802:        return 0;
                   2803: }
                   2804: #endif
                   2805: 
                   2806: int get_cpu_model (void)
                   2807: {
                   2808:        return currprefs.cpu_model;
                   2809: }
                   2810: 
1.1.1.7   root     2811: #ifndef WINUAE_FOR_HATARI
                   2812: STATIC_INLINE int in_rom (uaecptr pc)
1.1.1.4   root     2813: {
1.1.1.7   root     2814:        return (munge24 (pc) & 0xFFF80000) == 0xF80000;
1.1.1.4   root     2815: }
                   2816: 
1.1.1.7   root     2817: STATIC_INLINE int in_rtarea (uaecptr pc)
1.1.1.4   root     2818: {
1.1.1.9   root     2819:        return (munge24 (pc) & 0xFFFF0000) == rtarea_base && (uae_boot_rom_type || currprefs.uaeboard > 0);
1.1.1.4   root     2820: }
1.1.1.7   root     2821: #endif
1.1.1.4   root     2822: 
1.1.1.7   root     2823: STATIC_INLINE void wait_memory_cycles (void)
1.1.1.4   root     2824: {
1.1.1.7   root     2825:        if (regs.memory_waitstate_cycles) {
                   2826:                x_do_cycles(regs.memory_waitstate_cycles);
                   2827:                regs.memory_waitstate_cycles = 0;
1.1.1.4   root     2828:        }
1.1.1.7   root     2829:        if (regs.ce020extracycles >= 16) {
                   2830:                regs.ce020extracycles = 0;
                   2831:                x_do_cycles(4 * CYCLE_UNIT);
1.1.1.4   root     2832:        }
                   2833: }
                   2834: 
1.1.1.7   root     2835: STATIC_INLINE int adjust_cycles (int cycles)
1.1.1.4   root     2836: {
1.1.1.7   root     2837:        int mc = regs.memory_waitstate_cycles;
                   2838:        regs.memory_waitstate_cycles = 0;
                   2839:        if (currprefs.m68k_speed < 0 || cycles_mult == 0)
                   2840:                return cycles + mc;
                   2841:        cycles *= cycles_mult;
                   2842:        cycles /= CYCLES_DIV;
                   2843:        return cycles + mc;
1.1.1.4   root     2844: }
                   2845: 
1.1.1.9   root     2846: void m68k_cancel_idle(void)
                   2847: {
                   2848: #ifndef WINUAE_FOR_HATARI
                   2849:        cpu_last_stop_vpos = -1;
                   2850: #endif
                   2851: }
                   2852: 
1.1.1.8   root     2853: static void m68k_set_stop(void)
                   2854: {
                   2855:        if (regs.stopped)
                   2856:                return;
                   2857:        regs.stopped = 1;
                   2858:        set_special(SPCFLAG_STOP);
                   2859: #ifndef WINUAE_FOR_HATARI
1.1.1.9   root     2860:        if (cpu_last_stop_vpos >= 0) {
                   2861:                cpu_last_stop_vpos = vpos;
                   2862:        }
1.1.1.8   root     2863: #endif
                   2864: }
                   2865: 
                   2866: static void m68k_unset_stop(void)
                   2867: {
                   2868:        regs.stopped = 0;
                   2869:        unset_special(SPCFLAG_STOP);
                   2870: #ifndef WINUAE_FOR_HATARI
1.1.1.9   root     2871:        if (cpu_last_stop_vpos >= 0) {
                   2872:                cpu_stopped_lines += vpos - cpu_last_stop_vpos;
                   2873:                cpu_last_stop_vpos = vpos;
                   2874:        }
1.1.1.8   root     2875: #endif
                   2876: }
                   2877: 
1.1.1.9   root     2878: static void activate_trace(void)
                   2879: {
                   2880:        unset_special (SPCFLAG_TRACE);
                   2881:        set_special (SPCFLAG_DOTRACE);
                   2882: }
                   2883: 
1.1.1.10! root     2884: // make sure interrupt is checked immediately after current instruction
        !          2885: static void doint_imm(void)
        !          2886: {
        !          2887:        doint();
        !          2888:        if (!currprefs.cachesize && !(regs.spcflags & SPCFLAG_INT) && (regs.spcflags & SPCFLAG_DOINT))
        !          2889:                set_special(SPCFLAG_INT);
        !          2890: }
        !          2891: 
1.1.1.9   root     2892: void REGPARAM2 MakeSR (void)
1.1.1.4   root     2893: {
                   2894:        regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
                   2895:                | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
                   2896:                | (GET_XFLG () << 4) | (GET_NFLG () << 3)
                   2897:                | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
                   2898:                |  GET_CFLG ());
                   2899: }
                   2900: 
1.1.1.8   root     2901: static void SetSR (uae_u16 sr)
1.1.1.4   root     2902: {
1.1.1.7   root     2903:        regs.sr &= 0xff00;
                   2904:        regs.sr |= sr;
1.1.1.4   root     2905: 
                   2906:        SET_XFLG ((regs.sr >> 4) & 1);
                   2907:        SET_NFLG ((regs.sr >> 3) & 1);
                   2908:        SET_ZFLG ((regs.sr >> 2) & 1);
                   2909:        SET_VFLG ((regs.sr >> 1) & 1);
                   2910:        SET_CFLG (regs.sr & 1);
1.1.1.7   root     2911: }
                   2912: 
1.1.1.9   root     2913: static void MakeFromSR_x(int t0trace)
1.1.1.7   root     2914: {
                   2915:        int oldm = regs.m;
                   2916:        int olds = regs.s;
1.1.1.9   root     2917:        int oldt0 = regs.t0;
                   2918:        int oldt1 = regs.t1;
1.1.1.7   root     2919: 
                   2920:        SET_XFLG ((regs.sr >> 4) & 1);
                   2921:        SET_NFLG ((regs.sr >> 3) & 1);
                   2922:        SET_ZFLG ((regs.sr >> 2) & 1);
                   2923:        SET_VFLG ((regs.sr >> 1) & 1);
                   2924:        SET_CFLG (regs.sr & 1);
                   2925:        if (regs.t1 == ((regs.sr >> 15) & 1) &&
                   2926:                regs.t0 == ((regs.sr >> 14) & 1) &&
                   2927:                regs.s  == ((regs.sr >> 13) & 1) &&
1.1.1.4   root     2928:                regs.m  == ((regs.sr >> 12) & 1) &&
                   2929:                regs.intmask == ((regs.sr >> 8) & 7))
                   2930:                return;
                   2931:        regs.t1 = (regs.sr >> 15) & 1;
                   2932:        regs.t0 = (regs.sr >> 14) & 1;
                   2933:        regs.s  = (regs.sr >> 13) & 1;
                   2934:        regs.m  = (regs.sr >> 12) & 1;
                   2935:        regs.intmask = (regs.sr >> 8) & 7;
                   2936:        if (currprefs.cpu_model >= 68020) {
                   2937:                /* 68060 does not have MSP but does have M-bit.. */
                   2938:                if (currprefs.cpu_model >= 68060)
                   2939:                        regs.msp = regs.isp;
                   2940:                if (olds != regs.s) {
                   2941:                        if (olds) {
                   2942:                                if (oldm)
                   2943:                                        regs.msp = m68k_areg (regs, 7);
                   2944:                                else
                   2945:                                        regs.isp = m68k_areg (regs, 7);
                   2946:                                m68k_areg (regs, 7) = regs.usp;
                   2947:                        } else {
                   2948:                                regs.usp = m68k_areg (regs, 7);
                   2949:                                m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
                   2950:                        }
                   2951:                } else if (olds && oldm != regs.m) {
                   2952:                        if (oldm) {
                   2953:                                regs.msp = m68k_areg (regs, 7);
                   2954:                                m68k_areg (regs, 7) = regs.isp;
                   2955:                        } else {
                   2956:                                regs.isp = m68k_areg (regs, 7);
                   2957:                                m68k_areg (regs, 7) = regs.msp;
                   2958:                        }
                   2959:                }
                   2960:                if (currprefs.cpu_model >= 68060)
                   2961:                        regs.t0 = 0;
                   2962:        } else {
                   2963:                regs.t0 = regs.m = 0;
                   2964:                if (olds != regs.s) {
                   2965:                        if (olds) {
                   2966:                                regs.isp = m68k_areg (regs, 7);
                   2967:                                m68k_areg (regs, 7) = regs.usp;
                   2968:                        } else {
                   2969:                                regs.usp = m68k_areg (regs, 7);
                   2970:                                m68k_areg (regs, 7) = regs.isp;
                   2971:                        }
                   2972:                }
                   2973:        }
                   2974:        if (currprefs.mmu_model)
                   2975:                mmu_set_super (regs.s != 0);
                   2976: 
1.1.1.10! root     2977:        doint_imm();
1.1.1.9   root     2978:        if (regs.t1 || regs.t0) {
1.1.1.4   root     2979:                set_special (SPCFLAG_TRACE);
1.1.1.9   root     2980:        } else {
1.1.1.4   root     2981:                /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
                   2982:                SR-modifying instructions (including STOP).  */
                   2983:                unset_special (SPCFLAG_TRACE);
1.1.1.9   root     2984:        }
                   2985:        // Stop SR-modification does not generate T0
                   2986:        // If this SR modification set Tx bit, no trace until next instruction.
                   2987:        if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) {
                   2988:                // Always trace if Tx bits were already set, even if this SR modification cleared them.
                   2989:                activate_trace();
                   2990:        }
                   2991: }
                   2992: 
                   2993: void REGPARAM2 MakeFromSR_T0(void)
                   2994: {
                   2995:        MakeFromSR_x(1);
                   2996: }
                   2997: void REGPARAM2 MakeFromSR(void)
                   2998: {
                   2999:        MakeFromSR_x(0);
1.1.1.4   root     3000: }
                   3001: 
1.1.1.8   root     3002: static void exception_check_trace (int nr)
1.1.1.4   root     3003: {
                   3004:        unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                   3005:        if (regs.t1 && !regs.t0) {
                   3006:                /* trace stays pending if exception is div by zero, chk,
                   3007:                * trapv or trap #x
                   3008:                */
                   3009:                if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
                   3010:                        set_special (SPCFLAG_DOTRACE);
                   3011:        }
1.1.1.8   root     3012:        regs.t1 = regs.t0 = 0;
1.1.1.4   root     3013: }
                   3014: 
                   3015: static void exception_debug (int nr)
                   3016: {
1.1.1.7   root     3017: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     3018:        if (unlikely(ExceptionDebugMask & EXCEPT_NOHANDLER) && STMemory_ReadLong(regs.vbr + 4*nr) == 0) {
1.1.1.10! root     3019:                fprintf(stderr,"Uninitialized exception handler #%i!\n", nr);
1.1.1.8   root     3020:                DebugUI(REASON_CPU_EXCEPTION);
                   3021:        } else {
                   3022:                DebugUI_Exceptions(nr, M68K_GETPC);
                   3023:        }
1.1.1.9   root     3024: #else
                   3025: #ifdef DEBUGGER
                   3026:        if (!exception_debugging)
                   3027:                return;
                   3028:        console_out_f (_T("Exception %d, PC=%08X\n"), nr, M68K_GETPC);
                   3029: #endif
1.1.1.7   root     3030: #endif
1.1.1.4   root     3031: }
                   3032: 
1.1.1.7   root     3033: #ifdef CPUEMU_13
1.1.1.4   root     3034: 
                   3035: /* cycle-exact exception handler, 68000 only */
                   3036: 
                   3037: /*
                   3038: 
                   3039: Address/Bus Error:
                   3040: 
1.1.1.7   root     3041: - 8 idle cycles
1.1.1.4   root     3042: - write PC low word
                   3043: - write SR
                   3044: - write PC high word
                   3045: - write instruction word
                   3046: - write fault address low word
                   3047: - write status code
                   3048: - write fault address high word
                   3049: - 2 idle cycles
                   3050: - read exception address high word
                   3051: - read exception address low word
                   3052: - prefetch
                   3053: - 2 idle cycles
                   3054: - prefetch
                   3055: 
                   3056: Division by Zero:
                   3057: 
1.1.1.7   root     3058: - 8 idle cycles
1.1.1.4   root     3059: - write PC low word
                   3060: - write SR
                   3061: - write PC high word
                   3062: - read exception address high word
                   3063: - read exception address low word
                   3064: - prefetch
                   3065: - 2 idle cycles
                   3066: - prefetch
                   3067: 
                   3068: Traps:
                   3069: 
1.1.1.7   root     3070: - 4 idle cycles
1.1.1.4   root     3071: - write PC low word
                   3072: - write SR
                   3073: - write PC high word
                   3074: - read exception address high word
                   3075: - read exception address low word
                   3076: - prefetch
                   3077: - 2 idle cycles
                   3078: - prefetch
                   3079: 
                   3080: TrapV:
                   3081: 
1.1.1.7   root     3082: (- normal prefetch done by TRAPV)
1.1.1.4   root     3083: - write PC low word
                   3084: - write SR
                   3085: - write PC high word
                   3086: - read exception address high word
                   3087: - read exception address low word
                   3088: - prefetch
                   3089: - 2 idle cycles
                   3090: - prefetch
                   3091: 
                   3092: CHK:
                   3093: 
1.1.1.7   root     3094: - 8 idle cycles
1.1.1.4   root     3095: - write PC low word
                   3096: - write SR
                   3097: - write PC high word
                   3098: - read exception address high word
                   3099: - read exception address low word
                   3100: - prefetch
                   3101: - 2 idle cycles
                   3102: - prefetch
                   3103: 
                   3104: Illegal Instruction:
1.1.1.7   root     3105: Privilege violation:
1.1.1.8   root     3106: Trace:
1.1.1.7   root     3107: Line A:
                   3108: Line F:
1.1.1.4   root     3109: 
1.1.1.7   root     3110: - 4 idle cycles
1.1.1.4   root     3111: - write PC low word
                   3112: - write SR
                   3113: - write PC high word
                   3114: - read exception address high word
                   3115: - read exception address low word
                   3116: - prefetch
                   3117: - 2 idle cycles
                   3118: - prefetch
                   3119: 
1.1.1.7   root     3120: Interrupt:
1.1.1.4   root     3121: 
                   3122: - 6 idle cycles
                   3123: - write PC low word
                   3124: - read exception number byte from (0xfffff1 | (interrupt number << 1))
                   3125: - 4 idle cycles
                   3126: - write SR
                   3127: - write PC high word
                   3128: - read exception address high word
                   3129: - read exception address low word
                   3130: - prefetch
                   3131: - 2 idle cycles
                   3132: - prefetch
                   3133: 
                   3134: */
                   3135: 
1.1.1.7   root     3136: static int iack_cycle(int nr)
                   3137: {
                   3138:        int vector;
                   3139: 
                   3140: #ifndef WINUAE_FOR_HATARI
                   3141:        if (1) {
                   3142:                // non-autovectored
                   3143:                vector = x_get_byte(0x00fffff1 | ((nr - 24) << 1));
                   3144:                if (currprefs.cpu_cycle_exact)
                   3145:                        x_do_cycles(4 * cpucycleunit);
                   3146:        } else {
                   3147:                // autovectored
                   3148: 
                   3149:        }
                   3150: #else
                   3151:        int iack_start = CPU_IACK_CYCLES_START;
                   3152:        int e_cycles;
1.1.1.8   root     3153:        int cycle_exact = currprefs.cpu_cycle_exact && !currprefs.mmu_model;
1.1.1.7   root     3154: 
                   3155:        /* In cycle exact mode, the cycles before reaching IACK are already counted */
1.1.1.8   root     3156:        if (cycle_exact)
1.1.1.7   root     3157:                iack_start = 0;
                   3158: 
                   3159:        /* Pending bits / vector number can change before the end of the IACK sequence. */
                   3160:        /* We need to handle MFP/DSP and HBL/VBL cases for this. */
                   3161:        /* - Level 6 (MFP/DSP) use vectored interrupts */
                   3162:        /* - Level 2 (HBL) and 4 (VBL) use auto-vectored interrupts and require sync with E-clock */
                   3163:        vector = nr;
                   3164:        if ( nr == 30 )                                                         /* MFP or DSP */
                   3165:         {
                   3166:                vector = -1;
                   3167:                if (bDspEnabled)                                                /* Check DSP first */
                   3168:                {
                   3169:                        /* TODO : For DSP, we just get the vector, we don't add IACK cycles */
                   3170:                        vector = DSP_ProcessIACK ();
                   3171:                }
                   3172: 
                   3173:                if ( vector < 0 )                                               /* No DSP, check MFP */
                   3174:                {
1.1.1.8   root     3175:                        if (cycle_exact)
                   3176:                        {
                   3177:                                x_do_cycles ( ( iack_start + CPU_IACK_CYCLES_MFP ) * cpucycleunit );
                   3178:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   3179:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3180:                                currcycle=0;
                   3181:                        }
                   3182:                        else
                   3183:                                M68000_AddCycles ( iack_start + CPU_IACK_CYCLES_MFP );
                   3184: 
1.1.1.7   root     3185:                        CPU_IACK = true;
                   3186:                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3187:                                CALL_VAR(PendingInterruptFunction);
                   3188:                        vector = MFP_ProcessIACK ( nr );
                   3189:                        CPU_IACK = false;
                   3190:                }
1.1.1.8   root     3191: 
                   3192:                if ( vector >= 0 )                                              /* We have a valid vector for level 6 */
                   3193:                {
                   3194:                        /* If a DSP IRQ is pending, we don't clear level 6 pending bit, else the DSP IRQ */
                   3195:                        /* will never be processed. If there's no DSP IRQ, we clear level 6 pending bit now */
                   3196:                        /* and if there's a lower MFP pending int, level 6 will be set again at the next instruction */
                   3197:                        if ( DSP_GetHREQ() == 0 )
                   3198:                                pendingInterrupts &= ~( 1 << 6 );
                   3199:                }
1.1.1.7   root     3200:        }
                   3201:        else if ( ( nr == 26 ) || ( nr == 28 ) )                                /* HBL / VBL */
                   3202:        {
1.1.1.8   root     3203:                if (cycle_exact)
                   3204:                {
                   3205:                        /* In CE mode, iack_start = 0, no need to call x_do_cycles() */
                   3206:                        //x_do_cycles ( ( iack_start + CPU_IACK_CYCLES_VIDEO_CE + e_cycles ) * cpucycleunit );
                   3207:                        /* Flush all CE cycles so far before calling M68000_WaitEClock() */
                   3208:                        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3209:                        currcycle = 0;
                   3210:                }
                   3211:                else
                   3212:                        M68000_AddCycles ( iack_start );
                   3213: 
1.1.1.7   root     3214:                e_cycles = M68000_WaitEClock ();
1.1.1.8   root     3215: //             fprintf ( stderr , "wait e clock %d\n" , e_cycles);
                   3216: 
                   3217:                if (cycle_exact)
                   3218:                {
                   3219:                        x_do_cycles ( ( e_cycles + CPU_IACK_CYCLES_VIDEO_CE ) * cpucycleunit );
                   3220:                        /* Flush all CE cycles so far to update PendingInterruptCount */
                   3221:                        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3222:                        currcycle = 0;
                   3223:                }
                   3224:                else
                   3225:                        M68000_AddCycles ( e_cycles + CPU_IACK_CYCLES_VIDEO_CE );
1.1.1.7   root     3226: 
                   3227:                CPU_IACK = true;
                   3228:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3229:                        CALL_VAR(PendingInterruptFunction);
                   3230:                if ( MFP_UpdateNeeded == true )
                   3231:                        MFP_UpdateIRQ ( 0 );                                    /* update MFP's state if some internal timers related to MFP expired */
1.1.1.8   root     3232:                pendingInterrupts &= ~( 1 << ( nr - 24 ) );                     /* clear HBL or VBL pending bit (even if an MFP timer occurred during IACK) */
1.1.1.7   root     3233:                CPU_IACK = false;
                   3234:        }
                   3235: 
                   3236:        /* TODO If there was no DSP and no MFP IRQ, then we have a spurious interrupt */
                   3237:        /* In that case, we use vector 24 and we jump to $60 */
                   3238:        if ( vector < 0 )
                   3239:        {
                   3240:        }
1.1.1.8   root     3241: 
                   3242:        /* Add 4 idle cycles for CE mode. For non-CE mode, this will be counted in add_approximate_exception_cycles() */
                   3243:        if (cycle_exact)
                   3244:                x_do_cycles( 4 * cpucycleunit );
1.1.1.7   root     3245: #endif
                   3246:        return vector;
                   3247: }
                   3248: 
                   3249: static void Exception_ce000 (int nr)
1.1.1.4   root     3250: {
                   3251:        uae_u32 currpc = m68k_getpc (), newpc;
                   3252:        int sv = regs.s;
1.1.1.7   root     3253:        int start, interrupt;
                   3254:        int vector_nr = nr;
1.1.1.4   root     3255: 
1.1.1.8   root     3256: //fprintf ( stderr , "ex in %d %ld %ld\n" , nr , currcycle , CyclesGlobalClockCounter );
1.1.1.7   root     3257:        start = 6;
1.1.1.4   root     3258:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.7   root     3259:        if (!interrupt) {
                   3260:                start = 8;
                   3261:                if (nr == 7) // TRAPV
                   3262:                        start = 0;
                   3263:                else if (nr >= 32 && nr < 32 + 16) // TRAP #x
                   3264:                        start = 4;
1.1.1.8   root     3265:                else if (nr == 4 || nr == 8 || nr == 9 || nr == 10 || nr == 11) // ILLG, PRIV, TRACE, LINEA, LINEF
1.1.1.7   root     3266:                        start = 4;
                   3267:        }
1.1.1.4   root     3268: 
                   3269:        if (start)
1.1.1.7   root     3270:                x_do_cycles (start * cpucycleunit);
1.1.1.4   root     3271: 
1.1.1.7   root     3272: #ifdef WINUAE_FOR_HATARI
                   3273:        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",
                   3274:                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);
                   3275: #endif
1.1.1.4   root     3276:        exception_debug (nr);
                   3277:        MakeSR ();
                   3278: 
                   3279:        if (!regs.s) {
                   3280:                regs.usp = m68k_areg (regs, 7);
                   3281:                m68k_areg (regs, 7) = regs.isp;
                   3282:                regs.s = 1;
                   3283:        }
                   3284:        if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
1.1.1.7   root     3285:                if ((m68k_areg(regs, 7) & 1) || exception_in_exception < 0) {
1.1.1.8   root     3286:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3287:                        return;
                   3288:                }
1.1.1.4   root     3289:                uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   3290:                mode |= last_writeaccess_for_exception_3 ? 0 : 16;
1.1.1.7   root     3291:                mode |= last_notinstruction_for_exception_3 ? 8 : 0;
                   3292:                // undocumented bits seem to contain opcode
                   3293:                mode |= last_op_for_exception_3 & ~31;
1.1.1.4   root     3294:                m68k_areg (regs, 7) -= 14;
1.1.1.7   root     3295:                exception_in_exception = -1;
                   3296:                x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
                   3297:                x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
                   3298:                x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
                   3299:                x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
                   3300:                x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
                   3301:                x_put_word (m68k_areg (regs, 7) + 0, mode);
                   3302:                x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
                   3303:                x_do_cycles (2 * cpucycleunit);
1.1.1.8   root     3304: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     3305:                write_log (_T("Exception %d (%04x %x) at %x -> %x!\n"),
                   3306:                        nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug (4 * nr));
1.1.1.8   root     3307: #else
1.1.1.10! root     3308:                if (nr != 2 || M68000_IsVerboseBusError(currpc, last_fault_for_exception_3))
        !          3309:                        Log_Printf(LOG_WARN, "%s Error %s at address $%x, PC=$%x addr_e3=%x op_e3=%x\n",
        !          3310:                                   nr == 2 ? "Bus" : "Address",
        !          3311:                                   last_writeaccess_for_exception_3 ? "writing" : "reading",
        !          3312:                                   last_fault_for_exception_3, currpc,
        !          3313:                                   last_addr_for_exception_3 , last_op_for_exception_3);
1.1.1.7   root     3314: #endif
1.1.1.4   root     3315:                goto kludge_me_do;
                   3316:        }
1.1.1.7   root     3317:        if (currprefs.cpu_model == 68010) {
                   3318:                // 68010 creates only format 0 and 8 stack frames
                   3319:                m68k_areg (regs, 7) -= 8;
                   3320:                if (m68k_areg(regs, 7) & 1) {
                   3321:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
                   3322:                        return;
                   3323:                }
                   3324:                exception_in_exception = 1;
                   3325:                x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
                   3326:                if (interrupt)
                   3327:                        vector_nr = iack_cycle(nr);
                   3328:                x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
                   3329:                x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
                   3330:                x_put_word (m68k_areg (regs, 7) + 6, vector_nr * 4);
                   3331:        } else {
                   3332:                m68k_areg (regs, 7) -= 6;
                   3333:                if (m68k_areg(regs, 7) & 1) {
                   3334:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
                   3335:                        return;
                   3336:                }
                   3337:                exception_in_exception = 1;
                   3338:                x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
1.1.1.8   root     3339: //fprintf ( stderr , "ex iack1 %d %ld\n" , nr , currcycle );
1.1.1.7   root     3340:                if (interrupt)
                   3341:                        vector_nr = iack_cycle(nr);
1.1.1.8   root     3342: //fprintf ( stderr , "ex iack2 %d %ld\n" , nr , currcycle );
1.1.1.7   root     3343:                x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
                   3344:                x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
1.1.1.4   root     3345:        }
                   3346: kludge_me_do:
1.1.1.7   root     3347:        newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
                   3348:        newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
                   3349:        exception_in_exception = 0;
1.1.1.4   root     3350:        if (newpc & 1) {
                   3351:                if (nr == 2 || nr == 3)
1.1.1.8   root     3352:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3353:                else
1.1.1.7   root     3354:                        exception3_notinstruction(regs.ir, newpc);
1.1.1.4   root     3355:                return;
                   3356:        }
                   3357:        m68k_setpc (newpc);
1.1.1.10! root     3358:        if (interrupt)
        !          3359:                regs.intmask = nr - 24;
        !          3360:        branch_stack_push(currpc, currpc);
1.1.1.7   root     3361:        regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
                   3362:        x_do_cycles (2 * cpucycleunit);
1.1.1.8   root     3363: #ifdef WINUAE_FOR_HATARI
                   3364:        /* [NP] IPL should be updated just before the last x_get_word for irc */
                   3365:        /* (4 cycles before end of exception), so we need to add 2 cycles now */
                   3366:        /* to be aligned on 4 cycles (else the 2 cycles will be added in x_get_word */
                   3367:        /* and IPL will be updated 2 cycles too soon) */
                   3368:        x_do_cycles (2 * cpucycleunit);
                   3369:        /* Add all cycles needed for the exception so far */
                   3370:        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3371:        currcycle = 0;
                   3372:        /* Update IPL / interrupts state, in case a new interrupt happened during this exception */
                   3373:        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   3374:                CALL_VAR(PendingInterruptFunction);
                   3375: #endif
                   3376:        regs.ipl_pin = intlev();
                   3377:        ipl_fetch();
1.1.1.7   root     3378:        regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2
1.1.1.4   root     3379: #ifdef JIT
                   3380:        set_special (SPCFLAG_END_COMPILE);
                   3381: #endif
1.1.1.8   root     3382:        exception_check_trace (nr);
1.1.1.7   root     3383: 
                   3384: //fprintf ( stderr , "ex out %d %ld\n" , nr , currcycle );
                   3385: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     3386:        /* Add all cycles needed for the exception */
                   3387:        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   3388:        currcycle = 0;
1.1.1.7   root     3389: #endif
                   3390: }
                   3391: #endif
                   3392: 
                   3393: static uae_u32 exception_pc (int nr)
                   3394: {
                   3395:        // bus error, address error, illegal instruction, privilege violation, a-line, f-line
                   3396:        if (nr == 2 || nr == 3 || nr == 4 || nr == 8 || nr == 10 || nr == 11)
                   3397:                return regs.instruction_pc;
                   3398:        return m68k_getpc ();
                   3399: }
                   3400: 
                   3401: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
                   3402: {
                   3403:     int i;
                   3404:    
                   3405: #if 0
                   3406:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
                   3407:         write_log(_T("Building exception stack frame (format %X)\n"), format);
                   3408:     }
                   3409: #endif
                   3410: 
1.1.1.9   root     3411:        switch (format) {
1.1.1.7   root     3412:         case 0x0: // four word stack frame
                   3413:         case 0x1: // throwaway four word stack frame
                   3414:             break;
                   3415:         case 0x2: // six word stack frame
                   3416:             m68k_areg (regs, 7) -= 4;
                   3417:             x_put_long (m68k_areg (regs, 7), oldpc);
                   3418:             break;
1.1.1.9   root     3419:                case 0x3: // floating point post-instruction stack frame (68040)
                   3420:                        m68k_areg (regs, 7) -= 4;
                   3421:                        x_put_long (m68k_areg (regs, 7), regs.fp_ea);
                   3422:                        break;
                   3423:                case 0x7: // access error stack frame (68040)
1.1.1.7   root     3424: 
                   3425:                        for (i = 3; i >= 0; i--) {
                   3426:                                // WB1D/PD0,PD1,PD2,PD3
                   3427:                 m68k_areg (regs, 7) -= 4;
                   3428:                 x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
                   3429:                        }
                   3430: 
                   3431:             m68k_areg (regs, 7) -= 4;
                   3432:             x_put_long (m68k_areg (regs, 7), 0); // WB1A
                   3433:                        m68k_areg (regs, 7) -= 4;
                   3434:             x_put_long (m68k_areg (regs, 7), 0); // WB2D
                   3435:             m68k_areg (regs, 7) -= 4;
                   3436:             x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
                   3437:                        m68k_areg (regs, 7) -= 4;
                   3438:             x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
                   3439:             m68k_areg (regs, 7) -= 4;
                   3440:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
                   3441: 
                   3442:                        m68k_areg (regs, 7) -= 4;
                   3443:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
                   3444:             
                   3445:                        m68k_areg (regs, 7) -= 2;
                   3446:             x_put_word (m68k_areg (regs, 7), 0);
                   3447:             m68k_areg (regs, 7) -= 2;
                   3448:             x_put_word (m68k_areg (regs, 7), regs.wb2_status);
                   3449:             regs.wb2_status = 0;
                   3450:             m68k_areg (regs, 7) -= 2;
                   3451:             x_put_word (m68k_areg (regs, 7), regs.wb3_status);
                   3452:             regs.wb3_status = 0;
                   3453: 
                   3454:                        m68k_areg (regs, 7) -= 2;
                   3455:                        x_put_word (m68k_areg (regs, 7), ssw);
                   3456:             m68k_areg (regs, 7) -= 4;
                   3457:             x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
                   3458:             break;
                   3459:         case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
                   3460:             m68k_areg (regs, 7) -= 4;
1.1.1.9   root     3461:             x_put_long (m68k_areg (regs, 7), regs.fp_ea);
1.1.1.7   root     3462:             m68k_areg (regs, 7) -= 4;
1.1.1.9   root     3463:                        x_put_long (m68k_areg (regs, 7), regs.fp_opword);
                   3464:                        m68k_areg (regs, 7) -= 4;
1.1.1.7   root     3465:             x_put_long (m68k_areg (regs, 7), oldpc);
                   3466:             break;
                   3467:         case 0x8: // bus and address error stack frame (68010)
                   3468:             write_log(_T("Exception stack frame format %X not implemented\n"), format);
                   3469:             return;
                   3470:         case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
1.1.1.9   root     3471:                        // or 68060 bus access fault stack frame
1.1.1.7   root     3472:                        m68k_areg (regs, 7) -= 4;
1.1.1.9   root     3473:                        x_put_long (m68k_areg (regs, 7), ssw);
1.1.1.7   root     3474:                        m68k_areg (regs, 7) -= 4;
1.1.1.9   root     3475:                        x_put_long (m68k_areg (regs, 7), oldpc);
1.1.1.7   root     3476:                        break;
                   3477:                case 0xB: // long bus cycle fault stack frame (68020, 68030)
                   3478:                        // We always use B frame because it is easier to emulate,
                   3479:                        // our PC always points at start of instruction but A frame assumes
                   3480:                        // it is + 2 and handling this properly is not easy.
                   3481:                        // Store state information to internal register space
1.1.1.10! root     3482: #if MMU030_DEBUG
        !          3483:                        if (mmu030_idx >= MAX_MMU030_ACCESS) {
        !          3484:                                write_log(_T("mmu030_idx out of bounds! %d >= %d\n"), mmu030_idx, MAX_MMU030_ACCESS);
        !          3485:                        }
        !          3486: #endif
        !          3487:                        if (!(ssw & MMU030_SSW_RW)) {
        !          3488:                                mmu030_ad[mmu030_idx].val = regs.wb3_data;
        !          3489:                        }
1.1.1.7   root     3490:                        for (i = 0; i < mmu030_idx + 1; i++) {
                   3491:                                m68k_areg (regs, 7) -= 4;
                   3492:                                x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
                   3493:                        }
1.1.1.10! root     3494:                        while (i < MAX_MMU030_ACCESS) {
1.1.1.7   root     3495:                                uae_u32 v = 0;
                   3496:                                m68k_areg (regs, 7) -= 4;
                   3497:                                // mmu030_idx is always small enough if instruction is FMOVEM.
                   3498:                                if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
1.1.1.10! root     3499: #if MMU030_DEBUG
        !          3500:                                        if (mmu030_idx >= MAX_MMU030_ACCESS - 2) {
        !          3501:                                                write_log(_T("mmu030_idx (FMOVEM) out of bounds! %d >= %d\n"), mmu030_idx, MAX_MMU030_ACCESS - 2);
        !          3502:                                        }
        !          3503: #endif
        !          3504:                                        if (i == MAX_MMU030_ACCESS - 2)
1.1.1.7   root     3505:                                                v = mmu030_fmovem_store[0];
1.1.1.10! root     3506:                                        else if (i == MAX_MMU030_ACCESS - 1)
1.1.1.7   root     3507:                                                v = mmu030_fmovem_store[1];
                   3508:                                }
                   3509:                                x_put_long (m68k_areg (regs, 7), v);
                   3510:                                i++;
                   3511:                        }
                   3512:                         // version & internal information (We store index here)
                   3513:                        m68k_areg (regs, 7) -= 2;
                   3514:                        x_put_word (m68k_areg (regs, 7), mmu030_idx);
                   3515:                        // 3* internal registers
                   3516:                        m68k_areg (regs, 7) -= 2;
                   3517:                        x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
                   3518:                        m68k_areg (regs, 7) -= 2;
1.1.1.10! root     3519:                        x_put_word (m68k_areg(regs, 7), regs.wb2_address); // = mmu030_state[1]
1.1.1.7   root     3520:                        m68k_areg (regs, 7) -= 2;
                   3521:                        x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
                   3522:                        // data input buffer = fault address
                   3523:                        m68k_areg (regs, 7) -= 4;
                   3524:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3525:                        // 2xinternal
1.1.1.9   root     3526:                        {
                   3527:                                uae_u32 ps = (regs.prefetch020_valid[0] ? 1 : 0) | (regs.prefetch020_valid[1] ? 2 : 0) | (regs.prefetch020_valid[2] ? 4 : 0);
                   3528:                                ps |= ((regs.pipeline_r8[0] & 7) << 8);
                   3529:                                ps |= ((regs.pipeline_r8[1] & 7) << 11);
                   3530:                                ps |= ((regs.pipeline_pos & 15) << 16);
                   3531:                                ps |= ((regs.pipeline_stop & 15) << 20);
                   3532:                                if (mmu030_opcode == -1)
                   3533:                                        ps |= 1 << 31;
                   3534:                                m68k_areg (regs, 7) -= 4;
                   3535:                                x_put_long (m68k_areg (regs, 7), ps);
                   3536:                        }
1.1.1.7   root     3537:                        // stage b address
                   3538:                        m68k_areg (regs, 7) -= 4;
                   3539:                        x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
                   3540:                        // 2xinternal
                   3541:                        m68k_areg (regs, 7) -= 4;
                   3542:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
                   3543:                /* fall through */
                   3544:                case 0xA: // short bus cycle fault stack frame (68020, 68030)
                   3545:                        m68k_areg (regs, 7) -= 4;
                   3546:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
                   3547:                        m68k_areg (regs, 7) -= 4;
1.1.1.10! root     3548:                        // Data output buffer = value that was going to be written
        !          3549:                        x_put_long (m68k_areg (regs, 7), regs.wb3_data);
1.1.1.7   root     3550:                        m68k_areg (regs, 7) -= 4;
1.1.1.9   root     3551:                        x_put_long (m68k_areg (regs, 7), (mmu030_opcode & 0xffff) | (regs.prefetch020[0] << 16));  // Internal register (opcode storage)
1.1.1.7   root     3552:                        m68k_areg (regs, 7) -= 4;
                   3553:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
                   3554:                        m68k_areg (regs, 7) -= 2;
1.1.1.9   root     3555:                        x_put_word (m68k_areg (regs, 7), regs.prefetch020[2]);  // Instr. pipe stage B
1.1.1.7   root     3556:                        m68k_areg (regs, 7) -= 2;
1.1.1.9   root     3557:                        x_put_word (m68k_areg (regs, 7), regs.prefetch020[1]);  // Instr. pipe stage C
1.1.1.7   root     3558:                        m68k_areg (regs, 7) -= 2;
                   3559:                        x_put_word (m68k_areg (regs, 7), ssw);
                   3560:                        m68k_areg (regs, 7) -= 2;
                   3561:                        x_put_word (m68k_areg (regs, 7), 0);  // Internal register
                   3562:                        break;
                   3563:                default:
                   3564:             write_log(_T("Unknown exception stack frame format: %X\n"), format);
                   3565:             return;
                   3566:     }
                   3567:     m68k_areg (regs, 7) -= 2;
                   3568:     x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
                   3569:     m68k_areg (regs, 7) -= 4;
                   3570:     x_put_long (m68k_areg (regs, 7), currpc);
                   3571:     m68k_areg (regs, 7) -= 2;
                   3572:     x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.4   root     3573: }
1.1.1.7   root     3574: 
1.1.1.9   root     3575: static void Exception_build_stack_frame_common (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr)
                   3576: {
                   3577:        if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
                   3578:                Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
                   3579:        } else if (nr == 60 || nr == 61) {
                   3580:                Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
                   3581:        } else if (nr >= 48 && nr <= 55) {
                   3582:                if (regs.fpu_exp_pre) {
                   3583:                        if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
                   3584:                                Exception_build_stack_frame(regs.fp_ea, regs.instruction_pc, 0, nr, 0x2);
                   3585:                        } else {
                   3586:                                Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0);
                   3587:                        }
                   3588:                } else { /* post-instruction */
                   3589:                        if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
                   3590:                                Exception_build_stack_frame(regs.fp_ea, currpc, 0, nr, 0x2);
                   3591:                        } else {
                   3592:                                Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x3);
                   3593:                        }
                   3594:                }
                   3595:        } else if (nr == 11 && regs.fp_unimp_ins) {
                   3596:                regs.fp_unimp_ins = false;
                   3597:                if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2))) ||
                   3598:                        (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
                   3599:                        Exception_build_stack_frame(regs.fp_ea, currpc, regs.instruction_pc, nr, 0x4);
                   3600:                } else {
                   3601:                        Exception_build_stack_frame(regs.fp_ea, currpc, regs.mmu_ssw, nr, 0x2);
                   3602:                }
                   3603:        } else {
                   3604:                Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                   3605:        }
                   3606: }
1.1.1.7   root     3607: 
                   3608: // 68030 MMU
                   3609: static void Exception_mmu030 (int nr, uaecptr oldpc)
                   3610: {
                   3611:     uae_u32 currpc = m68k_getpc (), newpc;
                   3612:        int interrupt;
                   3613: 
                   3614:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.4   root     3615: 
1.1.1.7   root     3616: #ifdef WINUAE_FOR_HATARI
                   3617:        if (interrupt)
                   3618:                nr = iack_cycle(nr);
                   3619: #endif
                   3620: 
                   3621: #ifdef WINUAE_FOR_HATARI
                   3622:        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",
                   3623:                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);
                   3624: #endif
                   3625:     exception_debug (nr);
                   3626:     MakeSR ();
                   3627:     
                   3628:     if (!regs.s) {
                   3629:         regs.usp = m68k_areg (regs, 7);
                   3630:         m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
                   3631:         regs.s = 1;
                   3632:         mmu_set_super (1);
                   3633:     }
                   3634:  
                   3635: #if 0
                   3636:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
                   3637:         write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
                   3638:                    nr, currpc, oldpc, regs.mmu_fault_addr);
                   3639:     }
                   3640: #endif
                   3641: 
1.1.1.9   root     3642:     newpc = x_get_long (regs.vbr + 4 * nr);
                   3643: 
1.1.1.7   root     3644: #if 0
1.1.1.9   root     3645:        write_log (_T("Exception %d -> %08x\n"), nr, newpc);
1.1.1.7   root     3646: #endif
                   3647: 
                   3648:        if (regs.m && interrupt) { /* M + Interrupt */
                   3649:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                   3650:                MakeSR ();
                   3651:                regs.m = 0;
                   3652:                regs.msp = m68k_areg (regs, 7);
                   3653:                m68k_areg (regs, 7) = regs.isp;
                   3654:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
                   3655:     } else if (nr == 2) {
                   3656:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr,  0xB);
                   3657:     } else if (nr == 3) {
                   3658:                regs.mmu_fault_addr = last_fault_for_exception_3;
                   3659:                mmu030_state[0] = mmu030_state[1] = 0;
1.1.1.10! root     3660:                mmu030_data_buffer_out = 0;
1.1.1.7   root     3661:         Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr,  0xA);
1.1.1.9   root     3662:        } else {
                   3663:                Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
                   3664:        }
                   3665: 
1.1.1.7   root     3666:        if (newpc & 1) {
                   3667:                if (nr == 2 || nr == 3)
1.1.1.8   root     3668:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3669:                else
                   3670:                        exception3_read(regs.ir, newpc);
                   3671:                return;
                   3672:        }
1.1.1.10! root     3673:        if (interrupt)
        !          3674:                regs.intmask = nr - 24;
1.1.1.7   root     3675:        m68k_setpci (newpc);
                   3676:        fill_prefetch ();
1.1.1.8   root     3677:        exception_check_trace (nr);
1.1.1.7   root     3678: }
                   3679: 
                   3680: // 68040/060 MMU
1.1.1.4   root     3681: static void Exception_mmu (int nr, uaecptr oldpc)
                   3682: {
                   3683:        uae_u32 currpc = m68k_getpc (), newpc;
1.1.1.7   root     3684:        int interrupt;
1.1.1.4   root     3685: 
1.1.1.7   root     3686:        interrupt = nr >= 24 && nr < 24 + 8;
                   3687: 
1.1.1.9   root     3688:        // exception vector fetch and exception stack frame
                   3689:        // operations don't allocate new cachelines
                   3690:        cache_default_data |= CACHE_DISABLE_ALLOCATE;
                   3691: 
1.1.1.7   root     3692: #ifdef WINUAE_FOR_HATARI
                   3693:        if (interrupt)
                   3694:                nr = iack_cycle(nr);
                   3695: #endif
                   3696: 
                   3697: #ifdef WINUAE_FOR_HATARI
                   3698:        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",
                   3699:                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);
                   3700: #endif
1.1.1.4   root     3701:        exception_debug (nr);
                   3702:        MakeSR ();
                   3703: 
                   3704:        if (!regs.s) {
                   3705:                regs.usp = m68k_areg (regs, 7);
1.1.1.8   root     3706:                if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) {
1.1.1.4   root     3707:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7   root     3708:                } else {
1.1.1.4   root     3709:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.7   root     3710:                }
1.1.1.4   root     3711:                regs.s = 1;
                   3712:                mmu_set_super (1);
                   3713:        }
1.1.1.8   root     3714: 
1.1.1.7   root     3715:        newpc = x_get_long (regs.vbr + 4 * nr);
                   3716: #if 0
                   3717:        write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
                   3718: #endif
1.1.1.5   root     3719: 
1.1.1.7   root     3720:        if (nr == 2) { // bus error
                   3721:         //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
                   3722:         if (currprefs.mmu_model == 68040)
                   3723:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
                   3724:                else
1.1.1.9   root     3725:                        Exception_build_stack_frame(regs.mmu_fault_addr, currpc, regs.mmu_fslw, nr, 0x4);
1.1.1.7   root     3726:        } else if (nr == 3) { // address error
                   3727:         Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
                   3728:                write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * nr));
                   3729:        } else if (regs.m && interrupt) { /* M + Interrupt */
1.1.1.8   root     3730:                Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                   3731:                MakeSR();
                   3732:                regs.m = 0;
                   3733:                if (currprefs.cpu_model < 68060) {
                   3734:                        regs.msp = m68k_areg(regs, 7);
                   3735:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
                   3736:                }
1.1.1.4   root     3737:        } else {
1.1.1.9   root     3738:                Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
1.1.1.4   root     3739:        }
1.1.1.7   root     3740:     
1.1.1.4   root     3741:        if (newpc & 1) {
                   3742:                if (nr == 2 || nr == 3)
1.1.1.8   root     3743:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3744:                else
1.1.1.7   root     3745:                        exception3_read(regs.ir, newpc);
1.1.1.4   root     3746:                return;
                   3747:        }
1.1.1.9   root     3748: 
                   3749:        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
                   3750: 
1.1.1.7   root     3751:        m68k_setpci (newpc);
1.1.1.10! root     3752:        if (interrupt)
        !          3753:                regs.intmask = nr - 24;
1.1.1.7   root     3754:        fill_prefetch ();
1.1.1.8   root     3755:        exception_check_trace (nr);
1.1.1.4   root     3756: }
                   3757: 
1.1.1.7   root     3758: static void add_approximate_exception_cycles(int nr)
1.1.1.4   root     3759: {
1.1.1.7   root     3760:        int cycles;
                   3761: 
                   3762:        if (currprefs.cpu_model > 68000)
                   3763:                return;
                   3764: #ifndef WINUAE_FOR_HATARI
                   3765:        if (nr >= 24 && nr <= 31) {
                   3766:                /* Interrupts */
                   3767:                cycles = 44 + 4; 
                   3768: #else
                   3769:        if ( nr >= 24 && nr <= 31 ) {
1.1.1.8   root     3770:                /* Atari's specific interrupts take 56 cycles instead of 44 due to iack sequence */
                   3771:                /* We must subtract CPU_IACK_CYCLES_START cycles already counted into iack_cycle() */
1.1.1.7   root     3772:                if ( nr == 30 )                                 /* MFP/DSP */
1.1.1.8   root     3773:                        cycles = 44-CPU_IACK_CYCLES_START;
1.1.1.7   root     3774:                else if ( nr == 28 )                            /* VBL */
1.1.1.8   root     3775:                        cycles = 44-CPU_IACK_CYCLES_START;
1.1.1.7   root     3776:                else if ( nr == 26 )                            /* HBL */
1.1.1.8   root     3777:                        cycles = 44-CPU_IACK_CYCLES_START;
1.1.1.7   root     3778:                else
1.1.1.8   root     3779:                        cycles = 44+4;                          /* Other interrupts (not used in Atari machines) */
1.1.1.7   root     3780: #endif
                   3781:        } else if (nr >= 32 && nr <= 47) {
                   3782:                /* Trap (total is 34, but cpuemux.c already adds 4) */ 
                   3783:                cycles = 34 -4;
                   3784:        } else {
                   3785:                switch (nr)
                   3786:                {
                   3787:                        case 2: cycles = 50; break;             /* Bus error */
                   3788:                        case 3: cycles = 50; break;             /* Address error */
                   3789:                        case 4: cycles = 34; break;             /* Illegal instruction */
                   3790:                        case 5: cycles = 38; break;             /* Division by zero */
                   3791:                        case 6: cycles = 40; break;             /* CHK */
                   3792:                        case 7: cycles = 34; break;             /* TRAPV */
                   3793:                        case 8: cycles = 34; break;             /* Privilege violation */
                   3794:                        case 9: cycles = 34; break;             /* Trace */
                   3795:                        case 10: cycles = 34; break;    /* Line-A */
                   3796:                        case 11: cycles = 34; break;    /* Line-F */
                   3797:                        default:
                   3798:                        cycles = 4;
                   3799:                        break;
                   3800:                }
                   3801:        }
                   3802: #ifdef WINUAE_FOR_HATARI
                   3803:        M68000_AddCycles ( cycles );
                   3804: #endif
                   3805:        cycles = adjust_cycles(cycles * CYCLE_UNIT / 2);
                   3806:        x_do_cycles(cycles);
                   3807: }
                   3808: 
                   3809: static void Exception_normal (int nr)
                   3810: {
1.1.1.9   root     3811:        uae_u32 newpc;
                   3812:        uae_u32 currpc = m68k_getpc();
                   3813:        uae_u32 nextpc;
1.1.1.4   root     3814:        int sv = regs.s;
1.1.1.7   root     3815:        int interrupt;
                   3816:        int vector_nr = nr;
                   3817: 
1.1.1.9   root     3818:        cache_default_data |= CACHE_DISABLE_ALLOCATE;
                   3819: 
1.1.1.7   root     3820:        interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.4   root     3821: 
1.1.1.7   root     3822: #ifndef WINUAE_FOR_HATARI
                   3823:        if (interrupt && currprefs.cpu_model <= 68010)
                   3824: #else
                   3825:        if (interrupt)
1.1.1.4   root     3826: #endif
1.1.1.7   root     3827:                vector_nr = iack_cycle(nr);
1.1.1.4   root     3828: 
                   3829:        exception_debug (nr);
                   3830:        MakeSR ();
                   3831: 
                   3832:        if (!regs.s) {
                   3833:                regs.usp = m68k_areg (regs, 7);
1.1.1.8   root     3834:                if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) {
1.1.1.4   root     3835:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7   root     3836:                } else {
1.1.1.4   root     3837:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.7   root     3838:                }
1.1.1.4   root     3839:                regs.s = 1;
                   3840:                if (currprefs.mmu_model)
                   3841:                        mmu_set_super (regs.s != 0);
                   3842:        }
1.1.1.7   root     3843: 
1.1.1.8   root     3844:        if ((m68k_areg(regs, 7) & 1) && currprefs.cpu_model < 68020) {
1.1.1.7   root     3845:                if (nr == 2 || nr == 3)
1.1.1.8   root     3846:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3847:                else
                   3848:                        exception3_notinstruction(regs.ir, m68k_areg(regs, 7));
                   3849:                return;
                   3850:        }
                   3851:        if ((nr == 2 || nr == 3) && exception_in_exception < 0) {
1.1.1.8   root     3852:                cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.7   root     3853:                return;
                   3854:        }
                   3855: 
1.1.1.8   root     3856: #ifndef WINUAE_FOR_HATARI
                   3857:        if (!currprefs.cpu_compatible) {
                   3858:                addrbank *ab = &get_mem_bank(m68k_areg(regs, 7) - 4);
                   3859:                // Not plain RAM check because some CPU type tests that
                   3860:                // don't need to return set stack to ROM..
                   3861:                if (!ab || ab == &dummy_bank || (ab->flags & ABFLAG_IO)) {
                   3862:                        cpu_halt(CPU_HALT_SSP_IN_NON_EXISTING_ADDRESS);
                   3863:                        return;
                   3864:                }
                   3865:        }
                   3866: #endif
                   3867:        
1.1.1.9   root     3868:        bool used_exception_build_stack_frame = false;
                   3869: 
1.1.1.7   root     3870:        if (currprefs.cpu_model > 68000) {
1.1.1.9   root     3871:                uae_u32 oldpc = regs.instruction_pc;
                   3872:                nextpc = exception_pc (nr);
1.1.1.7   root     3873: #ifdef WINUAE_FOR_HATARI
                   3874:                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",
                   3875:                        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);
                   3876: #endif
                   3877:                if (nr == 2 || nr == 3) {
                   3878:                        int i;
1.1.1.4   root     3879:                        if (currprefs.cpu_model >= 68040) {
                   3880:                                if (nr == 2) {
                   3881:                                        if (currprefs.mmu_model) {
1.1.1.7   root     3882:                                                // 68040 mmu bus error
1.1.1.4   root     3883:                                                for (i = 0 ; i < 7 ; i++) {
                   3884:                                                        m68k_areg (regs, 7) -= 4;
                   3885:                                                        x_put_long (m68k_areg (regs, 7), 0);
                   3886:                                                }
                   3887:                                                m68k_areg (regs, 7) -= 4;
                   3888:                                                x_put_long (m68k_areg (regs, 7), regs.wb3_data);
                   3889:                                                m68k_areg (regs, 7) -= 4;
                   3890:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3891:                                                m68k_areg (regs, 7) -= 4;
                   3892:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3893:                                                m68k_areg (regs, 7) -= 2;
                   3894:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3895:                                                m68k_areg (regs, 7) -= 2;
                   3896:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3897:                                                m68k_areg (regs, 7) -= 2;
                   3898:                                                x_put_word (m68k_areg (regs, 7), regs.wb3_status);
                   3899:                                                regs.wb3_status = 0;
                   3900:                                                m68k_areg (regs, 7) -= 2;
                   3901:                                                x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
                   3902:                                                m68k_areg (regs, 7) -= 4;
                   3903:                                                x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                   3904: 
                   3905:                                                m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3906:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4   root     3907:                                                m68k_areg (regs, 7) -= 4;
1.1.1.7   root     3908:                                                x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     3909:                                                m68k_areg (regs, 7) -= 2;
                   3910:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.7   root     3911:                                                newpc = x_get_long (regs.vbr + 4 * vector_nr);
1.1.1.4   root     3912:                                                if (newpc & 1) {
                   3913:                                                        if (nr == 2 || nr == 3)
1.1.1.8   root     3914:                                                                cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     3915:                                                        else
1.1.1.7   root     3916:                                                                exception3_read(regs.ir, newpc);
1.1.1.4   root     3917:                                                        return;
                   3918:                                                }
                   3919:                                                m68k_setpc (newpc);
                   3920: #ifdef JIT
                   3921:                                                set_special (SPCFLAG_END_COMPILE);
                   3922: #endif
1.1.1.8   root     3923:                                                exception_check_trace (nr);
1.1.1.4   root     3924:                                                return;
                   3925: 
                   3926:                                        } else {
                   3927: 
1.1.1.7   root     3928:                                                // 68040 bus error (not really, some garbage?)
1.1.1.4   root     3929:                                                for (i = 0 ; i < 18 ; i++) {
                   3930:                                                        m68k_areg (regs, 7) -= 2;
                   3931:                                                        x_put_word (m68k_areg (regs, 7), 0);
                   3932:                                                }
                   3933:                                                m68k_areg (regs, 7) -= 4;
                   3934:                                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   3935:                                                m68k_areg (regs, 7) -= 2;
                   3936:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3937:                                                m68k_areg (regs, 7) -= 2;
                   3938:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3939:                                                m68k_areg (regs, 7) -= 2;
                   3940:                                                x_put_word (m68k_areg (regs, 7), 0);
                   3941:                                                m68k_areg (regs, 7) -= 2;
                   3942:                                                x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
                   3943:                                                m68k_areg (regs, 7) -= 4;
                   3944:                                                x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
                   3945:                                                m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3946:                                                x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4   root     3947:                                                m68k_areg (regs, 7) -= 4;
1.1.1.7   root     3948:                                                x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4   root     3949:                                                m68k_areg (regs, 7) -= 2;
                   3950:                                                x_put_word (m68k_areg (regs, 7), regs.sr);
                   3951:                                                goto kludge_me_do;
                   3952: 
                   3953:                                        }
                   3954: 
                   3955:                                } else {
                   3956:                                        m68k_areg (regs, 7) -= 4;
                   3957:                                        x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   3958:                                        m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3959:                                        x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
1.1.1.4   root     3960:                                }
                   3961:                        } else {
1.1.1.7   root     3962:                                // 68020 address error
1.1.1.4   root     3963:                                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   3964:                                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
                   3965:                                ssw |= 0x20;
                   3966:                                for (i = 0 ; i < 36; i++) {
                   3967:                                        m68k_areg (regs, 7) -= 2;
                   3968:                                        x_put_word (m68k_areg (regs, 7), 0);
                   3969:                                }
                   3970:                                m68k_areg (regs, 7) -= 4;
                   3971:                                x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                   3972:                                m68k_areg (regs, 7) -= 2;
                   3973:                                x_put_word (m68k_areg (regs, 7), 0);
                   3974:                                m68k_areg (regs, 7) -= 2;
                   3975:                                x_put_word (m68k_areg (regs, 7), 0);
                   3976:                                m68k_areg (regs, 7) -= 2;
                   3977:                                x_put_word (m68k_areg (regs, 7), 0);
                   3978:                                m68k_areg (regs, 7) -= 2;
                   3979:                                x_put_word (m68k_areg (regs, 7), ssw);
                   3980:                                m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3981:                                x_put_word (m68k_areg (regs, 7), 0xb000 + vector_nr * 4);
1.1.1.4   root     3982:                        }
1.1.1.10! root     3983: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     3984:                        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.10! root     3985: #else
        !          3986:                        if (nr != 2 || M68000_IsVerboseBusError(currpc, last_fault_for_exception_3))
        !          3987:                                Log_Printf(LOG_WARN, "%s Error %s at address $%x, PC=$%x addr_e3=%x op_e3=%x\n",
        !          3988:                                           nr == 2 ? "Bus" : "Address",
        !          3989:                                           last_writeaccess_for_exception_3 ? "writing" : "reading",
        !          3990:                                           last_fault_for_exception_3, currpc,
        !          3991:                                           last_addr_for_exception_3, last_op_for_exception_3);
        !          3992: #endif
1.1.1.7   root     3993:                } else if (regs.m && interrupt) { /* M + Interrupt */
1.1.1.4   root     3994:                        m68k_areg (regs, 7) -= 2;
1.1.1.7   root     3995:                        x_put_word (m68k_areg (regs, 7), vector_nr * 4);
1.1.1.8   root     3996:                        if (currprefs.cpu_model < 68060) {
                   3997:                                m68k_areg (regs, 7) -= 4;
                   3998:                                x_put_long (m68k_areg (regs, 7), currpc);
                   3999:                                m68k_areg (regs, 7) -= 2;
                   4000:                                x_put_word (m68k_areg (regs, 7), regs.sr);
                   4001:                                regs.sr |= (1 << 13);
                   4002:                                regs.msp = m68k_areg(regs, 7);
                   4003:                                regs.m = 0;
                   4004:                                m68k_areg(regs, 7) = regs.isp;
                   4005:                                m68k_areg (regs, 7) -= 2;
                   4006:                                x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
                   4007:                        }
1.1.1.4   root     4008:                } else {
1.1.1.9   root     4009:                        Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
                   4010:                        used_exception_build_stack_frame = true;
1.1.1.7   root     4011:                }
1.1.1.9   root     4012:        } else {
1.1.1.7   root     4013:                add_approximate_exception_cycles(nr);
1.1.1.9   root     4014:                nextpc = m68k_getpc ();
1.1.1.7   root     4015: #ifdef WINUAE_FOR_HATARI
                   4016:                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",
                   4017:                        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);
                   4018: #endif
                   4019:                if (nr == 2 || nr == 3) {
                   4020:                        // 68000 address error
                   4021:                        uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                   4022:                        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
                   4023:                        mode |= last_notinstruction_for_exception_3 ? 8 : 0;
                   4024:                        // undocumented bits seem to contain opcode
                   4025:                        mode |= last_op_for_exception_3 & ~31;
                   4026:                        m68k_areg (regs, 7) -= 14;
                   4027:                        exception_in_exception = -1;
                   4028:                        x_put_word (m68k_areg (regs, 7) + 0, mode);
                   4029:                        x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
                   4030:                        x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
                   4031:                        x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
                   4032:                        x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
1.1.1.8   root     4033: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     4034:                        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     4035: #else
1.1.1.10! root     4036:                        if (nr != 2 || M68000_IsVerboseBusError(currpc, last_fault_for_exception_3))
        !          4037:                                Log_Printf(LOG_WARN, "%s Error %s at address $%x, PC=$%x addr_e3=%x op_e3=%x\n",
        !          4038:                                           nr == 2 ? "Bus" : "Address",
        !          4039:                                           last_writeaccess_for_exception_3 ? "writing" : "reading",
        !          4040:                                           last_fault_for_exception_3, currpc,
        !          4041:                                           last_addr_for_exception_3, last_op_for_exception_3);
1.1.1.7   root     4042: #endif
                   4043:                        goto kludge_me_do;
1.1.1.4   root     4044:                }
                   4045:        }
1.1.1.9   root     4046:        if (!used_exception_build_stack_frame) {
                   4047:                m68k_areg (regs, 7) -= 4;
                   4048:                x_put_long (m68k_areg (regs, 7), nextpc);
                   4049:                m68k_areg (regs, 7) -= 2;
                   4050:                x_put_word (m68k_areg (regs, 7), regs.sr);
                   4051:        }
1.1.1.8   root     4052:        if (currprefs.cpu_model == 68060 && interrupt) {
                   4053:                regs.m = 0;
                   4054:        }
1.1.1.4   root     4055: kludge_me_do:
1.1.1.7   root     4056:        newpc = x_get_long (regs.vbr + 4 * vector_nr);
                   4057:        exception_in_exception = 0;
1.1.1.4   root     4058:        if (newpc & 1) {
                   4059:                if (nr == 2 || nr == 3)
1.1.1.8   root     4060:                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
1.1.1.4   root     4061:                else
1.1.1.7   root     4062:                        exception3_notinstruction(regs.ir, newpc);
1.1.1.4   root     4063:                return;
                   4064:        }
1.1.1.10! root     4065:        if (interrupt)
        !          4066:                regs.intmask = nr - 24;
1.1.1.4   root     4067:        m68k_setpc (newpc);
1.1.1.9   root     4068:        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
1.1.1.8   root     4069: #ifdef WINUAE_FOR_HATARI
                   4070:        /* Update IPL / interrupts state, in case a new interrupt happened during this exception */
                   4071:        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
                   4072:                CALL_VAR(PendingInterruptFunction);
                   4073: #endif
1.1.1.4   root     4074: #ifdef JIT
                   4075:        set_special (SPCFLAG_END_COMPILE);
                   4076: #endif
1.1.1.10! root     4077:        branch_stack_push(currpc, nextpc);
1.1.1.7   root     4078:        fill_prefetch ();
1.1.1.8   root     4079:        exception_check_trace (nr);
1.1.1.4   root     4080: }
                   4081: 
1.1.1.7   root     4082: // address = format $2 stack frame address field
                   4083: static void ExceptionX (int nr, uaecptr address)
1.1.1.4   root     4084: {
1.1.1.10! root     4085:        uaecptr pc = m68k_getpc();
1.1.1.7   root     4086:        regs.exception = nr;
                   4087:        if (cpu_tracer) {
                   4088:                cputrace.state = nr;
1.1.1.6   root     4089:        }
1.1.1.10! root     4090:        if (!regs.s) {
        !          4091:                regs.instruction_pc_user_exception = pc;
        !          4092:        }
1.1.1.6   root     4093: 
1.1.1.8   root     4094: #ifdef WINUAE_FOR_HATARI
                   4095:        /* Handle Hatari GEM and BIOS traps */
                   4096:        if (nr == 0x22) {
                   4097:                /* Intercept VDI & AES exceptions (Trap #2) */
                   4098:                if (bVdiAesIntercept && VDI_AES_Entry()) {
                   4099:                        /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
                   4100:                         * This will call OpCode_VDI() after completion of Trap call!
                   4101:                         * Used to modify specific VDI return vectors contents. */
                   4102:                        VDI_OldPC = m68k_getpc();
                   4103:                        m68k_setpc(CART_VDI_OPCODE_ADDR);
                   4104:                }
                   4105:        }
                   4106:        else if (nr == 0x2d) {
                   4107:                /* Intercept BIOS (Trap #13) calls */
                   4108:                if (Bios()) {
                   4109:                        fill_prefetch ();
                   4110:                        regs.exception = 0;
                   4111:                        return;
                   4112:                }
                   4113:        }
                   4114:        else if (nr == 0x2e) {
                   4115:                /* Intercept XBIOS (Trap #14) calls */
                   4116:                if (XBios()) {
                   4117:                        fill_prefetch ();
                   4118:                        regs.exception = 0;
                   4119:                        return;
                   4120:                }
                   4121:        }
                   4122: #endif
                   4123: 
1.1.1.7   root     4124: #ifdef JIT
                   4125:        if (currprefs.cachesize)
1.1.1.10! root     4126:                regs.instruction_pc = address == -1 ? pc : address;
        !          4127: #endif
        !          4128: 
        !          4129: #ifndef WINUAE_FOR_HATARI
        !          4130:        if (debug_illegal && !in_rom(pc)) {
        !          4131:                if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
        !          4132:                        write_log(_T("Exception %d breakpoint\n"), nr);
        !          4133:                        activate_debugger();
        !          4134:                }
        !          4135:        }
1.1.1.7   root     4136: #endif
1.1.1.10! root     4137: 
1.1.1.7   root     4138: #ifdef CPUEMU_13
                   4139:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010)
                   4140:                Exception_ce000 (nr);
1.1.1.4   root     4141:        else
                   4142: #endif
1.1.1.7   root     4143:                if (currprefs.mmu_model) {
                   4144:                        if (currprefs.cpu_model == 68030)
                   4145:                                Exception_mmu030 (nr, m68k_getpc ());
                   4146:                        else
                   4147:                                Exception_mmu (nr, m68k_getpc ());
                   4148:                } else {
                   4149:                        Exception_normal (nr);
                   4150:                }
1.1.1.4   root     4151: 
1.1.1.7   root     4152:        regs.exception = 0;
                   4153:        if (cpu_tracer) {
                   4154:                cputrace.state = 0;
                   4155:        }
                   4156: }
                   4157: 
1.1.1.9   root     4158: void REGPARAM2 Exception_cpu(int nr)
                   4159: {
                   4160:        bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
                   4161:        ExceptionX (nr, -1);
                   4162:        // check T0 trace
                   4163:        if (t0) {
                   4164:                activate_trace();
                   4165:        }
                   4166: }
1.1.1.7   root     4167: void REGPARAM2 Exception (int nr)
                   4168: {
                   4169:        ExceptionX (nr, -1);
                   4170: }
                   4171: void REGPARAM2 ExceptionL (int nr, uaecptr address)
                   4172: {
                   4173:        ExceptionX (nr, address);
1.1.1.4   root     4174: }
                   4175: 
1.1.1.9   root     4176: static void bus_error(void)
                   4177: {
                   4178:        TRY (prb2) {
                   4179:                Exception (2);
                   4180:        } CATCH (prb2) {
                   4181:                cpu_halt (CPU_HALT_BUS_ERROR_DOUBLE_FAULT);
                   4182:        } ENDTRY
                   4183: }
                   4184: 
1.1.1.7   root     4185: static void do_interrupt (int nr)
1.1.1.4   root     4186: {
1.1.1.7   root     4187: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4188:        if (debug_dma)
                   4189:                record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
1.1.1.7   root     4190: 
                   4191:        if (inputrecord_debug & 2) {
                   4192:                if (input_record > 0)
                   4193:                        inprec_recorddebug_cpu (2);
                   4194:                else if (input_play > 0)
                   4195:                        inprec_playdebug_cpu (2);
                   4196:        }
1.1.1.4   root     4197: #endif
                   4198: 
1.1.1.8   root     4199:        m68k_unset_stop();
1.1.1.4   root     4200:        assert (nr < 8 && nr >= 0);
                   4201: 
1.1.1.8   root     4202:        for (;;) {
                   4203:                Exception (nr + 24);
                   4204:                if (!currprefs.cpu_compatible || currprefs.cpu_model == 68060)
                   4205:                        break;
                   4206:                if (m68k_interrupt_delay)
                   4207:                        nr = regs.ipl;
                   4208:                else
                   4209:                        nr = intlev();
                   4210:                if (nr <= 0 || regs.intmask >= nr)
                   4211:                        break;
                   4212:        }
1.1.1.4   root     4213: 
                   4214:        doint ();
                   4215: }
                   4216: 
                   4217: void NMI (void)
                   4218: {
1.1.1.7   root     4219:        do_interrupt (7);
1.1.1.4   root     4220: }
                   4221: 
1.1.1.7   root     4222: static void m68k_reset_sr(void)
1.1.1.4   root     4223: {
1.1.1.7   root     4224:        SET_XFLG ((regs.sr >> 4) & 1);
                   4225:        SET_NFLG ((regs.sr >> 3) & 1);
                   4226:        SET_ZFLG ((regs.sr >> 2) & 1);
                   4227:        SET_VFLG ((regs.sr >> 1) & 1);
                   4228:        SET_CFLG (regs.sr & 1);
                   4229:        regs.t1 = (regs.sr >> 15) & 1;
                   4230:        regs.t0 = (regs.sr >> 14) & 1;
                   4231:        regs.s  = (regs.sr >> 13) & 1;
                   4232:        regs.m  = (regs.sr >> 12) & 1;
                   4233:        regs.intmask = (regs.sr >> 8) & 7;
                   4234:        /* set stack pointer */
                   4235:        if (regs.s)
                   4236:                m68k_areg (regs, 7) = regs.isp;
                   4237:        else
                   4238:                m68k_areg (regs, 7) = regs.usp;
1.1.1.4   root     4239: }
                   4240: 
1.1.1.7   root     4241: static void m68k_reset2(bool hardreset)
1.1.1.4   root     4242: {
1.1.1.7   root     4243:        uae_u32 v;
1.1.1.4   root     4244: 
1.1.1.10! root     4245: //fprintf ( stderr,"m68k_reset2 hard=%d in pc=%x\n" , hardreset , regs.pc );
1.1.1.7   root     4246:        regs.halted = 0;
                   4247: #ifndef WINUAE_FOR_HATARI
                   4248:        gui_data.cpu_halted = 0;
                   4249:        gui_led (LED_CPU, 0, -1);
1.1.1.4   root     4250: #endif
                   4251: 
1.1.1.7   root     4252:        regs.spcflags = 0;
                   4253:        m68k_reset_delay = 0;
                   4254:        regs.ipl = regs.ipl_pin = 0;
1.1.1.10! root     4255: #ifndef WINUAE_FOR_HATARI
        !          4256:        for (int i = 0; i < IRQ_SOURCE_MAX; i++) {
        !          4257:                uae_interrupts2[i] = 0;
        !          4258:                uae_interrupts6[i] = 0;
        !          4259:                uae_interrupt = 0;
        !          4260:        }
        !          4261: #endif
1.1.1.4   root     4262: 
1.1.1.7   root     4263: #ifdef SAVESTATE
                   4264:        if (isrestore ()) {
                   4265:                m68k_reset_sr();
                   4266:                m68k_setpc_normal (regs.pc);
1.1.1.4   root     4267:                return;
                   4268:        } else {
1.1.1.7   root     4269:                m68k_reset_delay = currprefs.reset_delay;
                   4270:                set_special(SPCFLAG_CHECK);
1.1.1.4   root     4271:        }
                   4272: #endif
1.1.1.7   root     4273:        regs.s = 1;
                   4274: #ifndef WINUAE_FOR_HATARI
                   4275:        if (currprefs.cpuboard_type) {
1.1.1.8   root     4276:                uaecptr stack;
1.1.1.7   root     4277:                v = cpuboard_get_reset_pc(&stack);
                   4278:                m68k_areg (regs, 7) = stack;
1.1.1.4   root     4279:        } else {
1.1.1.7   root     4280:                v = get_long (4);
                   4281:                m68k_areg (regs, 7) = get_long (0);
1.1.1.8   root     4282:        }
1.1.1.4   root     4283: #else
1.1.1.7   root     4284:        v = get_long (4);
                   4285:        m68k_areg (regs, 7) = get_long (0);
1.1.1.4   root     4286: #endif
1.1.1.8   root     4287: 
1.1.1.7   root     4288:        m68k_setpc_normal(v);
1.1.1.4   root     4289:        regs.m = 0;
                   4290:        regs.stopped = 0;
                   4291:        regs.t1 = 0;
                   4292:        regs.t0 = 0;
                   4293:        SET_ZFLG (0);
                   4294:        SET_XFLG (0);
                   4295:        SET_CFLG (0);
                   4296:        SET_VFLG (0);
                   4297:        SET_NFLG (0);
                   4298:        regs.intmask = 7;
                   4299:        regs.vbr = regs.sfc = regs.dfc = 0;
                   4300:        regs.irc = 0xffff;
                   4301: #ifdef FPUEMU
                   4302:        fpu_reset ();
                   4303: #endif
                   4304:        regs.caar = regs.cacr = 0;
                   4305:        regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
                   4306:        regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
1.1.1.7   root     4307:        mmu_tt_modified (); 
1.1.1.4   root     4308:        if (currprefs.cpu_model == 68020) {
                   4309:                regs.cacr |= 8;
1.1.1.7   root     4310:                set_cpu_caches (false);
1.1.1.4   root     4311:        }
                   4312: 
                   4313:        mmufixup[0].reg = -1;
                   4314:        mmufixup[1].reg = -1;
1.1.1.9   root     4315:        mmu030_cache_state = CACHE_ENABLE_ALL;
                   4316:        mmu_cache_state = CACHE_ENABLE_ALL;
                   4317:        if (currprefs.cpu_model >= 68040) {
                   4318:                set_cpu_caches(false);
                   4319:        }
1.1.1.7   root     4320:        if (currprefs.mmu_model >= 68040) {
                   4321:                mmu_reset ();
                   4322:                mmu_set_tc (regs.tcr);
                   4323:                mmu_set_super (regs.s != 0);
                   4324:        } else if (currprefs.mmu_model == 68030) {
                   4325:                mmu030_reset (hardreset || regs.halted);
                   4326:        } else {
                   4327: #ifndef WINUAE_FOR_HATARI
                   4328:                a3000_fakekick (0);
                   4329: #endif
                   4330:                /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
                   4331:                fake_tc_030 &= ~0x80000000;
                   4332:                fake_tt0_030 &= ~0x80000000;
                   4333:                fake_tt1_030 &= ~0x80000000;
                   4334:                if (hardreset || regs.halted) {
                   4335:                        fake_srp_030 = fake_crp_030 = 0;
                   4336:                        fake_tt0_030 = fake_tt1_030 = fake_tc_030 = 0;
1.1.1.5   root     4337:                }
1.1.1.7   root     4338:                fake_mmusr_030 = 0;
1.1.1.4   root     4339:        }
                   4340: 
                   4341:        /* 68060 FPU is not compatible with 68040,
                   4342:        * 68060 accelerators' boot ROM disables the FPU
                   4343:        */
                   4344:        regs.pcr = 0;
                   4345:        if (currprefs.cpu_model == 68060) {
                   4346:                regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
                   4347:                regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
1.1.1.7   root     4348: #ifndef WINUAE_FOR_HATARI
1.1.1.10! root     4349:                if (currprefs.fpu_model == 0 || (currprefs.cpuboard_type == 0 && rtarea_base != 0xf00000)) {
        !          4350:                        /* disable FPU if no accelerator board and no $f0 ROM */
        !          4351:                        regs.pcr |= 2;
        !          4352:                }
1.1.1.7   root     4353: #endif
                   4354:        }
1.1.1.9   root     4355: //     regs.ce020memcycles = 0;
                   4356:        regs.ce020startcycle = regs.ce020endcycle = 0;
1.1.1.7   root     4357:        fill_prefetch ();
1.1.1.10! root     4358: //fprintf ( stderr,"m68k_reset2 out pc=%x\n" , regs.pc );
1.1.1.7   root     4359: }
1.1.1.8   root     4360: 
1.1.1.7   root     4361: void m68k_reset(void)
                   4362: {
                   4363:        m68k_reset2(false);
                   4364: }
                   4365: 
1.1.1.8   root     4366: #ifndef WINUAE_FOR_HATARI
                   4367: void cpu_change(int newmodel)
                   4368: {
                   4369:        if (newmodel == currprefs.cpu_model)
                   4370:                return;
                   4371:        fallback_new_cpu_model = newmodel;
                   4372:        cpu_halt(CPU_HALT_ACCELERATOR_CPU_FALLBACK);
                   4373: }
1.1.1.7   root     4374: 
1.1.1.8   root     4375: void cpu_fallback(int mode)
1.1.1.7   root     4376: {
1.1.1.8   root     4377:        int fallbackmodel;
                   4378:        if (currprefs.chipset_mask & CSMASK_AGA) {
                   4379:                fallbackmodel = 68020;
                   4380:        } else {
                   4381:                fallbackmodel = 68000;
                   4382:        }
                   4383:        if (mode < 0) {
                   4384:                if (currprefs.cpu_model > fallbackmodel) {
                   4385:                        cpu_change(fallbackmodel);
                   4386:                } else if (fallback_new_cpu_model) {
                   4387:                        cpu_change(fallback_new_cpu_model);
                   4388:                }
                   4389:        } else if (mode == 0) {
                   4390:                cpu_change(fallbackmodel);
                   4391:        } else if (mode) {
                   4392:                if (fallback_cpu_model) {
                   4393:                        cpu_change(fallback_cpu_model);
                   4394:                }
1.1.1.4   root     4395:        }
1.1.1.8   root     4396: }
                   4397: 
                   4398: static void cpu_do_fallback(void)
                   4399: {
                   4400:        bool fallbackmode = false;
                   4401:        if ((fallback_new_cpu_model < 68020 && !(currprefs.chipset_mask & CSMASK_AGA)) || (fallback_new_cpu_model == 68020 && (currprefs.chipset_mask & CSMASK_AGA))) {
                   4402:                // -> 68000/68010 or 68EC020
                   4403:                fallback_cpu_model = currprefs.cpu_model;
                   4404:                fallback_fpu_model = currprefs.fpu_model;
                   4405:                fallback_mmu_model = currprefs.mmu_model;
                   4406:                fallback_cpu_compatible = currprefs.cpu_compatible;
                   4407:                fallback_cpu_address_space_24 = currprefs.address_space_24;
                   4408:                changed_prefs.cpu_model = currprefs.cpu_model_fallback && fallback_new_cpu_model <= 68020 ? currprefs.cpu_model_fallback : fallback_new_cpu_model;
                   4409:                changed_prefs.fpu_model = 0;
                   4410:                changed_prefs.mmu_model = 0;
                   4411:                changed_prefs.cpu_compatible = true;
                   4412:                changed_prefs.address_space_24 = true;
                   4413:                memcpy(&fallback_regs, &regs, sizeof(struct regstruct));
                   4414:                fallback_regs.pc = M68K_GETPC;
                   4415:                fallbackmode = true;
                   4416:        } else {
                   4417:                // -> 68020+
                   4418:                changed_prefs.cpu_model = fallback_cpu_model;
                   4419:                changed_prefs.fpu_model = fallback_fpu_model;
                   4420:                changed_prefs.mmu_model = fallback_mmu_model;
                   4421:                changed_prefs.cpu_compatible = fallback_cpu_compatible;
                   4422:                changed_prefs.address_space_24 = fallback_cpu_address_space_24;
                   4423:                fallback_cpu_model = 0;
                   4424:        }
                   4425:        init_m68k();
                   4426:        m68k_reset2(false);
                   4427:        if (!fallbackmode) {
                   4428:                // restore original 68020+
                   4429:                memcpy(&regs, &fallback_regs, sizeof(regs));
                   4430:                restore_banks();
                   4431:                memory_restore();
                   4432:                memory_map_dump();
                   4433:                m68k_setpc(fallback_regs.pc);
                   4434:        } else {
1.1.1.9   root     4435:                // 68000/010/EC020
1.1.1.8   root     4436:                memory_restore();
                   4437:                expansion_cpu_fallback();
                   4438:                memory_map_dump();
                   4439:        }
                   4440: }
1.1.1.10! root     4441: #endif
1.1.1.8   root     4442: 
                   4443: static void m68k_reset_restore(void)
                   4444: {
1.1.1.10! root     4445: #ifndef WINUAE_FOR_HATARI
1.1.1.8   root     4446:        // hardreset and 68000/68020 fallback mode? Restore original mode.
                   4447:        if (fallback_cpu_model) {
                   4448:                fallback_new_cpu_model = fallback_cpu_model;
                   4449:                fallback_regs.pc = 0;
                   4450:                cpu_do_fallback();
                   4451:        }
                   4452: #endif
1.1.1.10! root     4453: }
        !          4454: 
1.1.1.8   root     4455: void REGPARAM2 op_unimpl (uae_u16 opcode)
                   4456: {
                   4457:        static int warned;
                   4458:        if (warned < 20) {
                   4459:                write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
                   4460:                warned++;
                   4461:        }
                   4462:        ExceptionL (61, regs.instruction_pc);
1.1.1.4   root     4463: }
                   4464: 
1.1.1.7   root     4465: uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
1.1.1.4   root     4466: {
                   4467:        uaecptr pc = m68k_getpc ();
                   4468:        static int warned;
                   4469: 
1.1.1.7   root     4470: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4471:        int inrom = in_rom (pc);
                   4472:        int inrt = in_rtarea (pc);
                   4473: 
1.1.1.9   root     4474:        if ((opcode == 0x4afc || opcode == 0xfc4a) && !valid_address(pc, 4) && valid_address(pc - 4, 4)) {
                   4475:                // PC fell off the end of RAM
                   4476:                bus_error();
                   4477:                return 4;
                   4478:        }
                   4479: 
1.1.1.10! root     4480:        if (debugmem_illg(opcode)) {
        !          4481:                m68k_incpc_normal(2);
        !          4482:                return 4;
        !          4483:        }
        !          4484: 
1.1.1.4   root     4485:        if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
                   4486:                m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
1.1.1.7   root     4487:                m68k_incpc_normal (2);
                   4488:                fill_prefetch ();
1.1.1.4   root     4489:                return 4;
                   4490:        }
                   4491: 
1.1.1.7   root     4492:        if (opcode == 0x4E7B && inrom) {
                   4493:                if (get_long (0x10) == 0) {
                   4494:                        notify_user (NUMSG_KS68020);
                   4495:                        uae_restart (-1, NULL);
1.1.1.8   root     4496:                        m68k_setstopped();
                   4497:                        return 4;
1.1.1.7   root     4498:                }
1.1.1.4   root     4499:        }
                   4500: 
                   4501: #ifdef AUTOCONFIG
1.1.1.7   root     4502:        if (opcode == 0xFF0D && inrt) {
                   4503:                /* User-mode STOP replacement */
                   4504:                m68k_setstopped ();
                   4505:                return 4;
1.1.1.4   root     4506:        }
                   4507: 
                   4508:        if ((opcode & 0xF000) == 0xA000 && inrt) {
                   4509:                /* Calltrap. */
1.1.1.7   root     4510:                m68k_incpc_normal (2);
                   4511:                m68k_handle_trap(opcode & 0xFFF);
                   4512:                fill_prefetch ();
1.1.1.4   root     4513:                return 4;
                   4514:        }
                   4515: #endif
1.1.1.7   root     4516: #endif
1.1.1.4   root     4517: 
                   4518:        if ((opcode & 0xF000) == 0xF000) {
1.1.1.7   root     4519: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4520:                if (warned < 20) {
1.1.1.7   root     4521:                        write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
1.1.1.4   root     4522:                        warned++;
                   4523:                }
1.1.1.7   root     4524: #endif
                   4525:                Exception (0xB);
1.1.1.10! root     4526:                //activate_debugger_new();
1.1.1.4   root     4527:                return 4;
                   4528:        }
                   4529:        if ((opcode & 0xF000) == 0xA000) {
1.1.1.7   root     4530: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     4531:                if (warned < 20) {
1.1.1.7   root     4532:                        write_log(_T("A-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x28));
1.1.1.4   root     4533:                        warned++;
                   4534:                }
1.1.1.7   root     4535: #endif
                   4536:                Exception (0xA);
1.1.1.10! root     4537:                //activate_debugger_new();
1.1.1.4   root     4538:                return 4;
                   4539:        }
                   4540:        if (warned < 20) {
1.1.1.7   root     4541:                write_log (_T("Illegal instruction: %04x at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x10));
1.1.1.4   root     4542:                warned++;
1.1.1.10! root     4543:                //activate_debugger_new();
1.1.1.4   root     4544:        }
                   4545: 
1.1.1.7   root     4546:        Exception (4);
1.1.1.4   root     4547:        return 4;
                   4548: }
                   4549: 
                   4550: #ifdef CPUEMU_0
                   4551: 
1.1.1.9   root     4552: static bool mmu_op30_invea(uae_u32 opcode)
1.1.1.4   root     4553: {
1.1.1.9   root     4554:        int eamode = (opcode >> 3) & 7;
1.1.1.7   root     4555:        int rreg = opcode & 7;
1.1.1.9   root     4556: 
                   4557:        // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
1.1.1.10! root     4558:        if (eamode == 0 || eamode == 1 || eamode == 3 || eamode == 4 || (eamode == 7 && rreg > 1))
1.1.1.9   root     4559:                return true;
                   4560:        return false;
                   4561: }
                   4562: 
                   4563: static bool mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
                   4564: {
1.1.1.7   root     4565:        int preg = (next >> 10) & 31;
                   4566:        int rw = (next >> 9) & 1;
                   4567:        int fd = (next >> 8) & 1;
1.1.1.9   root     4568:        int unused = (next & 0xff);
1.1.1.7   root     4569:        const TCHAR *reg = NULL;
1.1.1.8   root     4570: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     4571:        uae_u32 otc = fake_tc_030;
1.1.1.8   root     4572: #endif
1.1.1.7   root     4573:        int siz;
                   4574: 
1.1.1.9   root     4575:        if (mmu_op30_invea(opcode))
                   4576:                return true;
                   4577:        // unused low 8 bits must be zeroed
                   4578:        if (unused)
                   4579:                return true;
                   4580:        // read and fd set?
                   4581:        if (rw && fd)
1.1.1.7   root     4582:                return true;
1.1.1.5   root     4583: 
1.1.1.7   root     4584:        switch (preg)
                   4585:        {
                   4586:        case 0x10: // TC
                   4587:                reg = _T("TC");
                   4588:                siz = 4;
                   4589:                if (rw)
                   4590:                        x_put_long (extra, fake_tc_030);
                   4591:                else
                   4592:                        fake_tc_030 = x_get_long (extra);
                   4593:                break;
                   4594:        case 0x12: // SRP
                   4595:                reg = _T("SRP");
                   4596:                siz = 8;
                   4597:                if (rw) {
                   4598:                        x_put_long (extra, fake_srp_030 >> 32);
                   4599:                        x_put_long (extra + 4, (uae_u32)fake_srp_030);
                   4600:                } else {
                   4601:                        fake_srp_030 = (uae_u64)x_get_long (extra) << 32;
                   4602:                        fake_srp_030 |= x_get_long (extra + 4);
                   4603:                }
                   4604:                break;
                   4605:        case 0x13: // CRP
                   4606:                reg = _T("CRP");
                   4607:                siz = 8;
                   4608:                if (rw) {
                   4609:                        x_put_long (extra, fake_crp_030 >> 32);
                   4610:                        x_put_long (extra + 4, (uae_u32)fake_crp_030);
                   4611:                } else {
                   4612:                        fake_crp_030 = (uae_u64)x_get_long (extra) << 32;
                   4613:                        fake_crp_030 |= x_get_long (extra + 4);
                   4614:                }
                   4615:                break;
                   4616:        case 0x18: // MMUSR
1.1.1.9   root     4617:                if (fd) {
                   4618:                        // FD must be always zero when MMUSR read or write
                   4619:                        return true;
                   4620:                }
1.1.1.7   root     4621:                reg = _T("MMUSR");
                   4622:                siz = 2;
                   4623:                if (rw)
                   4624:                        x_put_word (extra, fake_mmusr_030);
                   4625:                else
                   4626:                        fake_mmusr_030 = x_get_word (extra);
                   4627:                break;
                   4628:        case 0x02: // TT0
                   4629:                reg = _T("TT0");
                   4630:                siz = 4;
                   4631:                if (rw)
                   4632:                        x_put_long (extra, fake_tt0_030);
                   4633:                else
                   4634:                        fake_tt0_030 = x_get_long (extra);
                   4635:                break;
                   4636:        case 0x03: // TT1
                   4637:                reg = _T("TT1");
                   4638:                siz = 4;
                   4639:                if (rw)
                   4640:                        x_put_long (extra, fake_tt1_030);
                   4641:                else
                   4642:                        fake_tt1_030 = x_get_long (extra);
                   4643:                break;
                   4644:        }
1.1.1.4   root     4645: 
1.1.1.9   root     4646:        if (!reg)
1.1.1.7   root     4647:                return true;
1.1.1.9   root     4648: 
1.1.1.4   root     4649: #if MMUOP_DEBUG > 0
1.1.1.7   root     4650:        {
                   4651:                uae_u32 val;
                   4652:                if (siz == 8) {
                   4653:                        uae_u32 val2 = x_get_long (extra);
                   4654:                        val = x_get_long (extra + 4);
                   4655:                        if (rw)
                   4656:                                write_log (_T("PMOVE %s,%08X%08X"), reg, val2, val);
                   4657:                        else
                   4658:                                write_log (_T("PMOVE %08X%08X,%s"), val2, val, reg);
                   4659:                } else {
                   4660:                        if (siz == 4)
                   4661:                                val = x_get_long (extra);
                   4662:                        else
                   4663:                                val = x_get_word (extra);
                   4664:                        if (rw)
                   4665:                                write_log (_T("PMOVE %s,%08X"), reg, val);
                   4666:                        else
                   4667:                                write_log (_T("PMOVE %08X,%s"), val, reg);
1.1.1.4   root     4668:                }
1.1.1.7   root     4669:                write_log (_T(" PC=%08X\n"), pc);
                   4670:        }
1.1.1.4   root     4671: #endif
1.1.1.7   root     4672: #ifndef WINUAE_FOR_HATARI
                   4673:        if ((currprefs.cs_mbdmac & 1) && currprefs.mbresmem_low_size > 0) {
                   4674:                if (otc != fake_tc_030) {
                   4675:                        a3000_fakekick (fake_tc_030 & 0x80000000);
1.1.1.4   root     4676:                }
                   4677:        }
                   4678: #endif
1.1.1.7   root     4679:        return false;
1.1.1.4   root     4680: }
                   4681: 
1.1.1.7   root     4682: static bool mmu_op30fake_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
                   4683: {
1.1.1.9   root     4684:        int eamode = (opcode >> 3) & 7;
                   4685:        int rreg = opcode & 7;
                   4686:     int level = (next&0x1C00)>>10;
                   4687:     int a = (next >> 8) & 1;
                   4688: 
                   4689:        if (mmu_op30_invea(opcode))
                   4690:                return true;
                   4691:     if (!level && a)
                   4692:                return true;
                   4693: 
1.1.1.7   root     4694: #if MMUOP_DEBUG > 0
                   4695:        TCHAR tmp[10];
                   4696: 
                   4697:        tmp[0] = 0;
                   4698:        if ((next >> 8) & 1)
                   4699:                _stprintf (tmp, _T(",A%d"), (next >> 4) & 15);
                   4700:        write_log (_T("PTEST%c %02X,%08X,#%X%s PC=%08X\n"),
                   4701:                ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
1.1.1.4   root     4702: #endif
1.1.1.7   root     4703:        fake_mmusr_030 = 0;
                   4704:        return false;
                   4705: }
1.1.1.4   root     4706: 
1.1.1.9   root     4707: static bool mmu_op30fake_pload (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
                   4708: {
                   4709:        int unused = (next & (0x100 | 0x80 | 0x40 | 0x20));
                   4710: 
                   4711:        if (mmu_op30_invea(opcode))
                   4712:                return true;
                   4713:        if (unused)
                   4714:                return true;
                   4715:        write_log(_T("PLOAD\n"));
                   4716:        return false;
                   4717: }
                   4718: 
1.1.1.7   root     4719: static bool mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
                   4720: {
1.1.1.9   root     4721:        int flushmode = (next >> 8) & 31;
1.1.1.7   root     4722:        int fc = next & 31;
                   4723:        int mask = (next >> 5) & 3;
1.1.1.9   root     4724:        int fc_bits = next & 0x7f;
1.1.1.7   root     4725:        TCHAR fname[100];
                   4726: 
                   4727:        switch (flushmode)
                   4728:        {
1.1.1.9   root     4729:        case 0x00:
1.1.1.10! root     4730:        case 0x02:
1.1.1.9   root     4731:                return mmu_op30fake_pload(pc, opcode, next, extra);
                   4732:        case 0x18:
                   4733:                if (mmu_op30_invea(opcode))
1.1.1.7   root     4734:                        return true;
                   4735:                _stprintf (fname, _T("FC=%x MASK=%x EA=%08x"), fc, mask, 0);
                   4736:                break;
1.1.1.9   root     4737:        case 0x10:
1.1.1.7   root     4738:                _stprintf (fname, _T("FC=%x MASK=%x"), fc, mask);
                   4739:                break;
1.1.1.9   root     4740:        case 0x04:
                   4741:                if (fc_bits)
                   4742:                        return true;
1.1.1.7   root     4743:                _tcscpy (fname, _T("ALL"));
                   4744:                break;
                   4745:        default:
                   4746:                return true;
                   4747:        }
                   4748: #if MMUOP_DEBUG > 0
                   4749:        write_log (_T("PFLUSH %s PC=%08X\n"), fname, pc);
                   4750: #endif
                   4751:        return false;
                   4752: }
                   4753: 
                   4754: // 68030 (68851) MMU instructions only
                   4755: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
                   4756: {
                   4757:        int type = extra >> 13;
1.1.1.9   root     4758:        bool fline = false;
1.1.1.7   root     4759: 
                   4760:        switch (type)
                   4761:        {
                   4762:        case 0:
                   4763:        case 2:
                   4764:        case 3:
1.1.1.9   root     4765:                if (currprefs.mmu_model)
                   4766:                        fline = mmu_op30_pmove (pc, opcode, extra, extraa); 
                   4767:                else
                   4768:                        fline = mmu_op30fake_pmove (pc, opcode, extra, extraa);
1.1.1.7   root     4769:        break;
                   4770:        case 1:
1.1.1.9   root     4771:                if (currprefs.mmu_model)
                   4772:                        fline = mmu_op30_pflush (pc, opcode, extra, extraa); 
                   4773:                else
                   4774:                        fline = mmu_op30fake_pflush (pc, opcode, extra, extraa);
1.1.1.7   root     4775:        break;
                   4776:        case 4:
1.1.1.9   root     4777:                if (currprefs.mmu_model)
                   4778:                        fline = mmu_op30_ptest (pc, opcode, extra, extraa);
                   4779:                else
                   4780:                        fline = mmu_op30fake_ptest (pc, opcode, extra, extraa);
1.1.1.7   root     4781:        break;
                   4782:        }
1.1.1.9   root     4783:        if (fline) {
                   4784:                m68k_setpc(pc);
                   4785:                op_illg(opcode);
                   4786:        }
                   4787:        return fline;   
                   4788: }
                   4789: 
                   4790: /* check if an address matches a ttr */
                   4791: static int fake_mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super)
                   4792: {
                   4793:        if (ttr & MMU_TTR_BIT_ENABLED)  {       /* TTR enabled */
                   4794:                uae_u8 msb, mask;
                   4795: 
                   4796:                msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24;
                   4797:                mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16;
                   4798: 
                   4799:                if (!(msb & ~mask)) {
                   4800: 
                   4801:                        if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) {
                   4802:                                if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) {
                   4803:                                        return TTR_NO_MATCH;
                   4804:                                }
                   4805:                        }
                   4806: 
                   4807:                        return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH;
                   4808:                }
                   4809:        }
                   4810:        return TTR_NO_MATCH;
                   4811: }
                   4812: 
                   4813: static int fake_mmu_match_ttr(uaecptr addr, bool super, bool data)
                   4814: {
                   4815:        int res;
                   4816: 
                   4817:        if (data) {
                   4818:                res = fake_mmu_do_match_ttr(regs.dtt0, addr, super);
                   4819:                if (res == TTR_NO_MATCH)
                   4820:                        res = fake_mmu_do_match_ttr(regs.dtt1, addr, super);
                   4821:        } else {
                   4822:                res = fake_mmu_do_match_ttr(regs.itt0, addr, super);
                   4823:                if (res == TTR_NO_MATCH)
                   4824:                        res = fake_mmu_do_match_ttr(regs.itt1, addr, super);
                   4825:        }
                   4826:        return res;
1.1.1.7   root     4827: }
                   4828: 
                   4829: // 68040+ MMU instructions only
                   4830: void mmu_op (uae_u32 opcode, uae_u32 extra)
                   4831: {
                   4832:        if (currprefs.mmu_model) {
                   4833:                mmu_op_real (opcode, extra);
                   4834:                return;
                   4835:        }
                   4836: #if MMUOP_DEBUG > 1
                   4837:        write_log (_T("mmu_op %04X PC=%08X\n"), opcode, m68k_getpc ());
                   4838: #endif
                   4839:        if ((opcode & 0xFE0) == 0x0500) {
                   4840:                /* PFLUSH */
                   4841:                regs.mmusr = 0;
                   4842: #if MMUOP_DEBUG > 0
                   4843:                write_log (_T("PFLUSH\n"));
                   4844: #endif
                   4845:                return;
1.1.1.9   root     4846:        } else if ((opcode & 0x0FD8) == 0x0548) {
1.1.1.7   root     4847:                if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
                   4848:                        /* PTEST */
1.1.1.9   root     4849:                        int regno = opcode & 7;
                   4850:                        uae_u32 addr = m68k_areg(regs, regno);
                   4851:                        bool write = (opcode & 32) == 0;
                   4852:                        bool super = (regs.dfc & 4) != 0;
                   4853:                        bool data = (regs.dfc & 3) != 2;
                   4854: 
                   4855:                        regs.mmusr = 0;
                   4856:                        if (fake_mmu_match_ttr(addr, super, data) != TTR_NO_MATCH) {
                   4857:                                regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
                   4858:                        }
                   4859:                        regs.mmusr |= addr & 0xfffff000;
1.1.1.7   root     4860: #if MMUOP_DEBUG > 0
1.1.1.9   root     4861:                        write_log (_T("PTEST%c %08x\n"), write ? 'W' : 'R', addr);
1.1.1.7   root     4862: #endif
                   4863:                        return;
                   4864:                }
1.1.1.9   root     4865:        } else if ((opcode & 0x0FB8) == 0x0588) {
1.1.1.7   root     4866:                /* PLPA */
                   4867:                if (currprefs.cpu_model == 68060) {
1.1.1.9   root     4868:                        int regno = opcode & 7;
                   4869:                        uae_u32 addr = m68k_areg (regs, regno);
                   4870:                        int write = (opcode & 0x40) == 0;
                   4871:                        bool data = (regs.dfc & 3) != 2;
                   4872:                        bool super = (regs.dfc & 4) != 0;
                   4873: 
                   4874:                        if (fake_mmu_match_ttr(addr, super, data) == TTR_NO_MATCH) {
                   4875:                                m68k_areg (regs, regno) = addr;
                   4876:                        }
1.1.1.7   root     4877: #if MMUOP_DEBUG > 0
                   4878:                        write_log (_T("PLPA\n"));
                   4879: #endif
                   4880:                        return;
                   4881:                }
                   4882:        }
                   4883: #if MMUOP_DEBUG > 0
                   4884:        write_log (_T("Unknown MMU OP %04X\n"), opcode);
                   4885: #endif
                   4886:        m68k_setpc_normal (m68k_getpc () - 2);
                   4887:        op_illg (opcode);
                   4888: }
                   4889: 
                   4890: #endif
                   4891: 
1.1.1.4   root     4892: static void do_trace (void)
                   4893: {
                   4894:        if (regs.t0 && currprefs.cpu_model >= 68020) {
1.1.1.9   root     4895:                // this is obsolete
                   4896:                return;
                   4897:        }
                   4898:        if (regs.t1) {
                   4899:                activate_trace();
1.1.1.4   root     4900:        }
                   4901: }
                   4902: 
1.1.1.8   root     4903: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     4904: static void check_uae_int_request(void)
                   4905: {
1.1.1.10! root     4906:        bool irq2 = false;
        !          4907:        bool irq6 = false;
        !          4908:        if (atomic_and(&uae_interrupt, 0)) {
        !          4909:                for (int i = 0; i < IRQ_SOURCE_MAX; i++) {
        !          4910:                        if (!irq2 && uae_interrupts2[i]) {
        !          4911:                                uae_atomic v = atomic_and(&uae_interrupts2[i], 0);
        !          4912:                                if (v) {
        !          4913:                                        INTREQ_f(0x8000 | 0x0008);
        !          4914:                                        irq2 = true;
        !          4915:                                }
        !          4916:                        }
        !          4917:                        if (!irq6 && uae_interrupts6[i]) {
        !          4918:                                uae_atomic v = atomic_and(&uae_interrupts6[i], 0);
        !          4919:                                if (v) {
        !          4920:                                        INTREQ_f(0x8000 | 0x2000);
        !          4921:                                        irq6 = true;
        !          4922:                                }
        !          4923:                        }
        !          4924:                }
        !          4925:        }
1.1.1.8   root     4926:        if (uae_int_requested) {
1.1.1.10! root     4927:                if (!irq2 && (uae_int_requested & 0x00ff)) {
1.1.1.7   root     4928:                        INTREQ_f(0x8000 | 0x0008);
1.1.1.10! root     4929:                        irq2 = true;
1.1.1.8   root     4930:                }
1.1.1.10! root     4931:                if (!irq6 && (uae_int_requested & 0xff00)) {
1.1.1.7   root     4932:                        INTREQ_f(0x8000 | 0x2000);
1.1.1.10! root     4933:                        irq6 = true;
1.1.1.8   root     4934:                }
                   4935:                if (uae_int_requested & 0xff0000) {
1.1.1.10! root     4936:                        if (!cpuboard_is_ppcboard_irq()) {
1.1.1.8   root     4937:                                atomic_and(&uae_int_requested, ~0x010000);
1.1.1.10! root     4938:                        }
1.1.1.8   root     4939:                }
1.1.1.10! root     4940:        }
        !          4941:        if (irq2 || irq6) {
        !          4942:                doint();
1.1.1.7   root     4943:        }
1.1.1.8   root     4944: }
                   4945: 
1.1.1.10! root     4946: void safe_interrupt_set(int num, int id, bool i6)
1.1.1.8   root     4947: {
1.1.1.10! root     4948:        if (!is_mainthread()) {
        !          4949:                set_special_exter(SPCFLAG_UAEINT);
        !          4950:                volatile uae_atomic *p;
        !          4951:                if (i6)
        !          4952:                        p = &uae_interrupts6[num];
        !          4953:                else
        !          4954:                        p = &uae_interrupts2[num];
        !          4955:                atomic_or(p, 1 << id);
        !          4956:                atomic_or(&uae_interrupt, 1);
        !          4957:        } else {
        !          4958:                uae_u16 v = i6 ? 0x2000 : 0x0008;
        !          4959:                if (currprefs.cpu_cycle_exact || (!(intreq & v) && !currprefs.cpu_cycle_exact)) {
        !          4960:                        INTREQ_0(0x8000 | v);
        !          4961:                }
        !          4962:        }
1.1.1.7   root     4963: }
1.1.1.8   root     4964: #endif
                   4965: 
                   4966: int cpu_sleep_millis(int ms)
                   4967: {
                   4968:        int ret = 0;
1.1.1.7   root     4969: #ifdef WITH_PPC
                   4970:        int state = ppc_state;
                   4971:        if (state)
                   4972:                uae_ppc_spinlock_release();
                   4973: #endif
1.1.1.8   root     4974: #ifdef WITH_X86
1.1.1.10! root     4975: //     if (x86_turbo_on) {
        !          4976: //             execute_other_cpu(read_processor_time() + vsynctimebase / 20);
        !          4977: //     } else {
1.1.1.8   root     4978:                ret = sleep_millis_main(ms);
1.1.1.10! root     4979: //     }
1.1.1.8   root     4980: #endif
1.1.1.7   root     4981: #ifdef WITH_PPC
                   4982:        if (state)
                   4983:                uae_ppc_spinlock_get();
                   4984: #endif
1.1.1.8   root     4985:        return ret;
1.1.1.7   root     4986: }
                   4987: 
                   4988: #define PPC_HALTLOOP_SCANLINES 25
                   4989: // ppc_cpu_idle
                   4990: // 0 = busy
                   4991: // 1-9 = wait, levels
                   4992: // 10 = max wait
                   4993: 
1.1.1.8   root     4994: #ifndef WINUAE_FOR_HATARI
                   4995: static bool haltloop_do(int vsynctimeline, int rpt_end, int lines)
                   4996: {
                   4997:        int ovpos = vpos;
                   4998:        while (lines-- >= 0) {
                   4999:                ovpos = vpos;
                   5000:                while (ovpos == vpos) {
                   5001:                        x_do_cycles(8 * CYCLE_UNIT);
                   5002:                        unset_special(SPCFLAG_UAEINT);
                   5003:                        check_uae_int_request();
                   5004: #ifdef WITH_PPC
                   5005:                        ppc_interrupt(intlev());
                   5006:                        uae_ppc_execute_check();
                   5007: #endif
                   5008:                        if (regs.spcflags & SPCFLAG_COPPER)
                   5009:                                do_copper();
                   5010:                        if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
                   5011:                                if (regs.spcflags & SPCFLAG_BRK) {
                   5012:                                        unset_special(SPCFLAG_BRK);
                   5013:        #ifdef DEBUGGER
                   5014:                                        if (debugging)
                   5015:                                                debug();
                   5016:        #endif
                   5017:                                }
                   5018:                                return true;
                   5019:                        }
                   5020:                }
                   5021: 
                   5022:                // sync chipset with real time
                   5023:                for (;;) {
                   5024:                        check_uae_int_request();
                   5025: #ifdef WITH_PPC
                   5026:                        ppc_interrupt(intlev());
                   5027:                        uae_ppc_execute_check();
                   5028: #endif
                   5029:                        if (event_wait)
                   5030:                                break;
                   5031:                        int d = read_processor_time() - rpt_end;
                   5032:                        if (d < -2 * vsynctimeline || d >= 0)
                   5033:                                break;
                   5034:                }
                   5035:        }
                   5036:        return false;
                   5037: }
                   5038: #endif
                   5039: 
1.1.1.7   root     5040: static bool haltloop(void)
                   5041: {
                   5042: #ifndef WINUAE_FOR_HATARI
                   5043: #ifdef WITH_PPC
                   5044:        if (regs.halted < 0) {
                   5045:                int rpt_end = 0;
                   5046:                int ovpos = vpos;
                   5047: 
                   5048:                while (regs.halted) {
                   5049:                        int vsynctimeline = vsynctimebase / (maxvpos_display + 1);
                   5050:                        int lines;
                   5051:                        int rpt_scanline = read_processor_time();
                   5052:                        int rpt_end = rpt_scanline + vsynctimeline;
                   5053: 
                   5054:                        // See expansion handling.
                   5055:                        // Dialog must be opened from main thread.
                   5056:                        if (regs.halted == -2) {
                   5057:                                regs.halted = -1;
                   5058:                                notify_user (NUMSG_UAEBOOTROM_PPC);
                   5059:                        }
                   5060: 
                   5061:                        if (currprefs.ppc_cpu_idle) {
                   5062: 
                   5063:                                int maxlines = 100 - (currprefs.ppc_cpu_idle - 1) * 10;
                   5064:                                int i;
                   5065: 
                   5066:                                event_wait = false;
                   5067:                                for (i = 0; i < ev_max; i++) {
                   5068:                                        if (i == ev_hsync)
                   5069:                                                continue;
                   5070:                                        if (i == ev_audio)
                   5071:                                                continue;
                   5072:                                        if (!eventtab[i].active)
                   5073:                                                continue;
                   5074:                                        if (eventtab[i].evtime - currcycle < maxlines * maxhpos * CYCLE_UNIT)
                   5075:                                                break;
                   5076:                                }
                   5077:                                if (currprefs.ppc_cpu_idle >= 10 || (i == ev_max && vpos > 0 && vpos < maxvpos - maxlines)) {
                   5078:                                        cpu_sleep_millis(1);
                   5079:                                }
                   5080:                                check_uae_int_request();
                   5081:                                uae_ppc_execute_check();
                   5082: 
                   5083:                                lines = (read_processor_time() - rpt_scanline) / vsynctimeline + 1;
                   5084: 
                   5085:                        } else {
                   5086: 
                   5087:                                event_wait = true;
                   5088:                                lines = 0;
                   5089: 
                   5090:                        }
                   5091: 
                   5092:                        if (lines > maxvpos / 2)
                   5093:                                lines = maxvpos / 2;
                   5094: 
1.1.1.8   root     5095:                        if (haltloop_do(vsynctimeline, rpt_end, lines))
                   5096:                                return true;
1.1.1.7   root     5097: 
1.1.1.4   root     5098:                }
1.1.1.7   root     5099: 
                   5100:        } else  {
1.1.1.4   root     5101: #endif
1.1.1.7   root     5102:                while (regs.halted) {
                   5103:                        static int prevvpos;
                   5104:                        if (vpos == 0 && prevvpos) {
                   5105:                                prevvpos = 0;
                   5106:                                cpu_sleep_millis(8);
                   5107:                        }
                   5108:                        if (vpos)
                   5109:                                prevvpos = 1;
                   5110:                        x_do_cycles(8 * CYCLE_UNIT);
                   5111: 
                   5112:                        if (regs.spcflags & SPCFLAG_COPPER)
                   5113:                                do_copper();
                   5114: 
                   5115:                        if (regs.spcflags) {
                   5116:                                if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
                   5117:                                        return true;
                   5118:                        }
                   5119:                }
                   5120: #ifdef WITH_PPC
1.1.1.4   root     5121:        }
1.1.1.7   root     5122: #endif
                   5123: 
                   5124:        return false;
                   5125: #else
                   5126:        /* In Hatari, we don't use the halt state, we do a reset */
                   5127:        return false;
                   5128: #endif
1.1.1.4   root     5129: }
                   5130: 
1.1.1.7   root     5131: #ifdef WITH_PPC
                   5132: static bool uae_ppc_poll_check_halt(void)
1.1.1.4   root     5133: {
1.1.1.7   root     5134:        if (regs.halted) {
                   5135:                if (haltloop())
                   5136:                        return true;
1.1.1.4   root     5137:        }
1.1.1.7   root     5138:        return false;
1.1.1.4   root     5139: }
1.1.1.7   root     5140: #endif
1.1.1.4   root     5141: 
                   5142: 
1.1.1.7   root     5143: // handle interrupt delay (few cycles)
                   5144: STATIC_INLINE bool time_for_interrupt (void)
1.1.1.4   root     5145: {
1.1.1.7   root     5146:        return regs.ipl > regs.intmask || regs.ipl == 7;
                   5147: }
1.1.1.4   root     5148: 
1.1.1.7   root     5149: void doint (void)
                   5150: {
                   5151: #ifdef WITH_PPC
                   5152:        if (ppc_state) {
                   5153:                if (!ppc_interrupt(intlev()))
                   5154:                        return;
1.1.1.4   root     5155:        }
1.1.1.7   root     5156: #endif
1.1.1.8   root     5157: //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     5158:        if (m68k_interrupt_delay) {
                   5159:                regs.ipl_pin = intlev ();
                   5160:                unset_special (SPCFLAG_INT);
1.1.1.8   root     5161: //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     5162:                return;
1.1.1.4   root     5163:        }
1.1.1.7   root     5164:        if (currprefs.cpu_compatible && currprefs.cpu_model < 68020)
                   5165:                set_special (SPCFLAG_INT);
                   5166:        else
                   5167:                set_special (SPCFLAG_DOINT);
1.1.1.4   root     5168: }
                   5169: 
                   5170: 
1.1.1.7   root     5171: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     5172: /*
                   5173:  * Handle special flags
                   5174:  */
                   5175: 
                   5176: static bool do_specialties_interrupt (int Pending)
                   5177: {
1.1.1.5   root     5178: #if ENABLE_DSP_EMU
                   5179:     /* Check for DSP int first (if enabled) (level 6) */
                   5180:     if (regs.spcflags & SPCFLAG_DSP) {
                   5181:        if (DSP_ProcessIRQ() == true)
                   5182:          return true;
                   5183:     }
                   5184: #endif
                   5185: 
                   5186:     /* Check for MFP ints (level 6) */
1.1.1.4   root     5187:     if (regs.spcflags & SPCFLAG_MFP) {
1.1.1.5   root     5188:        if (MFP_ProcessIRQ() == true)
1.1.1.4   root     5189:          return true;                                  /* MFP exception was generated, no higher interrupt can happen */
                   5190:     }
                   5191: 
                   5192:     /* No MFP int, check for VBL/HBL ints (levels 4/2) */
                   5193:     if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
                   5194:        int intr = intlev ();
                   5195:        /* SPCFLAG_DOINT will be enabled again in MakeFromSR to handle pending interrupts! */
                   5196: //     unset_special (SPCFLAG_DOINT);
                   5197:        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   5198:        if (intr != -1 && intr > regs.intmask) {
1.1.1.7   root     5199:            do_interrupt (intr);                        /* process the interrupt */
1.1.1.4   root     5200:            return true;
                   5201:        }
                   5202:     }
                   5203: 
                   5204:     return false;                                      /* no interrupt was found */
                   5205: }
1.1.1.7   root     5206: #endif
1.1.1.4   root     5207: 
1.1.1.7   root     5208: static int do_specialties (int cycles)
1.1.1.4   root     5209: {
1.1.1.10! root     5210:        bool stopped_debug = false;
        !          5211: 
1.1.1.7   root     5212:        if (regs.spcflags & SPCFLAG_MODE_CHANGE)
                   5213:                return 1;
                   5214:        
                   5215: #ifndef WINUAE_FOR_HATARI
                   5216:        if (regs.spcflags & SPCFLAG_CHECK) {
                   5217:                if (regs.halted) {
1.1.1.8   root     5218:                        if (regs.halted == CPU_HALT_ACCELERATOR_CPU_FALLBACK) {
                   5219:                                return 1;
                   5220:                        }
                   5221:                        unset_special(SPCFLAG_CHECK);
1.1.1.7   root     5222:                        if (haltloop())
                   5223:                                return 1;
                   5224:                }
                   5225:                if (m68k_reset_delay) {
                   5226:                        int vsynccnt = 60;
                   5227:                        int vsyncstate = -1;
                   5228:                        while (vsynccnt > 0 && !quit_program) {
                   5229:                                x_do_cycles(8 * CYCLE_UNIT);
                   5230:                                if (regs.spcflags & SPCFLAG_COPPER)
                   5231:                                        do_copper();
                   5232:                                if (timeframes != vsyncstate) {
                   5233:                                        vsyncstate = timeframes;
                   5234:                                        vsynccnt--;
                   5235:                                }
                   5236:                        }
                   5237:                }
                   5238:                m68k_reset_delay = 0;
                   5239:                unset_special(SPCFLAG_CHECK);
                   5240:        }
                   5241: #endif
                   5242: 
                   5243: #ifdef ACTION_REPLAY
                   5244: #ifdef ACTION_REPLAY_HRTMON
                   5245:        if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
                   5246:                int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size);
                   5247:                /* exit from HRTMon? */
                   5248:                if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
                   5249:                        hrtmon_hide ();
                   5250:                /* HRTMon breakpoint? (not via IRQ7) */
                   5251:                if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt)
                   5252:                        hrtmon_breakenter ();
                   5253:                if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
                   5254:                        hrtmon_enter ();
                   5255:        }
                   5256: #endif
                   5257:        if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) {
                   5258:                /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/
                   5259:                /*      write_log (_T("PC:%p\n"), m68k_getpc ());*/
                   5260: 
                   5261:                if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
                   5262:                        action_replay_enter ();
                   5263:                if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom ()) {
                   5264:                        action_replay_hide ();
                   5265:                        unset_special (SPCFLAG_ACTION_REPLAY);
                   5266:                }
                   5267:                if (action_replay_flag == ACTION_REPLAY_WAIT_PC) {
                   5268:                        /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/
                   5269:                        if (m68k_getpc () == wait_for_pc) {
                   5270:                                action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
                   5271:                        }
                   5272:                }
                   5273:        }
                   5274: #endif
                   5275: 
                   5276: #ifndef WINUAE_FOR_HATARI
                   5277:        if (regs.spcflags & SPCFLAG_COPPER)
                   5278:                do_copper ();
                   5279: #endif
                   5280: 
1.1.1.4   root     5281: #ifdef JIT
                   5282:        unset_special (SPCFLAG_END_COMPILE);   /* has done its job */
                   5283: #endif
                   5284: 
1.1.1.7   root     5285: #ifndef WINUAE_FOR_HATARI
1.1.1.9   root     5286:        while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && ((currprefs.waiting_blits && currprefs.cpu_model >= 68020) || !currprefs.blitter_cycle_exact)) {
1.1.1.4   root     5287:                int c = blitnasty ();
1.1.1.7   root     5288:                if (c < 0) {
                   5289:                        break;
                   5290:                } else if (c > 0) {
1.1.1.4   root     5291:                        cycles -= c * CYCLE_UNIT * 2;
                   5292:                        if (cycles < CYCLE_UNIT)
                   5293:                                cycles = 0;
1.1.1.7   root     5294:                } else {
1.1.1.4   root     5295:                        c = 4;
1.1.1.7   root     5296:                }
                   5297:                x_do_cycles (c * CYCLE_UNIT);
1.1.1.4   root     5298:                if (regs.spcflags & SPCFLAG_COPPER)
                   5299:                        do_copper ();
1.1.1.7   root     5300: #ifdef WITH_PPC
                   5301:                if (ppc_state)  {
                   5302:                        if (uae_ppc_poll_check_halt())
                   5303:                                return true;
                   5304:                        uae_ppc_execute_check();
                   5305:                }
                   5306: #endif
1.1.1.4   root     5307:        }
                   5308: #endif
                   5309: 
1.1.1.7   root     5310: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     5311:        if (regs.spcflags & SPCFLAG_BUSERROR) {
                   5312:                /* We can not execute bus errors directly in the memory handler
                   5313:                * functions since the PC should point to the address of the next
                   5314:                * instruction, so we're executing the bus errors here: */
                   5315:                unset_special(SPCFLAG_BUSERROR);
1.1.1.7   root     5316:                Exception(2);
1.1.1.4   root     5317:        }
1.1.1.7   root     5318: #endif
1.1.1.4   root     5319: 
                   5320:        if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.7   root     5321:                Exception (9);
1.1.1.4   root     5322: 
1.1.1.7   root     5323: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5324:        if (regs.spcflags & SPCFLAG_TRAP) {
                   5325:                unset_special (SPCFLAG_TRAP);
1.1.1.7   root     5326:                Exception (3);
1.1.1.4   root     5327:        }
1.1.1.7   root     5328: #endif
1.1.1.9   root     5329:        if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) {
                   5330:                // 68000/68010 undocumented special case:
                   5331:                // if STOP clears S-bit and T was not set:
                   5332:                // cause privilege violation exception, PC pointing to following instruction.
                   5333:                // If T was set before STOP: STOP works as documented.
                   5334:                m68k_unset_stop();
                   5335:                Exception(8);
                   5336:        }
                   5337: 
1.1.1.7   root     5338:        bool first = true;
                   5339:        while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
1.1.1.8   root     5340: //fprintf ( stderr , "stop wait %d %ld %ld\n" , currcycle , CyclesGlobalClockCounter );
                   5341:        isstopped:
1.1.1.9   root     5342: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     5343:                check_uae_int_request();
                   5344:                {
                   5345:                        if (bsd_int_requested)
                   5346:                                bsdsock_fake_int_handler ();
                   5347:                }
                   5348: #endif
                   5349: 
                   5350:                if (cpu_tracer > 0) {
                   5351:                        cputrace.stopped = regs.stopped;
                   5352:                        cputrace.intmask = regs.intmask;
                   5353:                        cputrace.sr = regs.sr;
                   5354:                        cputrace.state = 1;
                   5355:                        cputrace.pc = m68k_getpc ();
                   5356:                        cputrace.memoryoffset = 0;
                   5357:                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   5358:                        cputrace.readcounter = cputrace.writecounter = 0;
                   5359:                }
                   5360:                if (!first)
                   5361:                        x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
1.1.1.4   root     5362: 
1.1.1.7   root     5363: #ifdef WINUAE_FOR_HATARI
                   5364:                if (!first)
                   5365:                {
1.1.1.8   root     5366:                        if (currprefs.cpu_cycle_exact && !currprefs.mmu_model)
                   5367:                        {
                   5368:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   5369:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   5370:                                currcycle = 0;
                   5371:                        }
                   5372:                        else
1.1.1.7   root     5373:                                M68000_AddCycles(4);
                   5374:                }
1.1.1.4   root     5375: 
                   5376:                /* It is possible one or more ints happen at the same time */
1.1.1.5   root     5377:                /* We must process them during the same cpu cycle then choose the highest priority one */
                   5378:                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
1.1.1.7   root     5379:                        CALL_VAR(PendingInterruptFunction);
1.1.1.5   root     5380:                if ( MFP_UpdateNeeded == true )
1.1.1.7   root     5381:                        MFP_UpdateIRQ ( 0 );
1.1.1.4   root     5382: 
1.1.1.5   root     5383:                /* Check is there's an interrupt to process (could be a delayed MFP interrupt) */
1.1.1.7   root     5384:                if (regs.spcflags & SPCFLAG_MFP) {
                   5385:                        MFP_DelayIRQ ();                        /* Handle IRQ propagation */
                   5386:                        M68000_Update_intlev ();                /* Refresh the list of pending interrupts */
1.1.1.5   root     5387:                }
1.1.1.7   root     5388: #endif
                   5389:                first = false;
                   5390: #ifndef WINUAE_FOR_HATARI
1.1.1.5   root     5391:                if (regs.spcflags & SPCFLAG_COPPER)
                   5392:                        do_copper ();
1.1.1.4   root     5393: #endif
                   5394: 
1.1.1.7   root     5395:                if (m68k_interrupt_delay) {
1.1.1.5   root     5396:                        ipl_fetch ();
                   5397:                        if (time_for_interrupt ()) {
1.1.1.7   root     5398:                                do_interrupt (regs.ipl);
1.1.1.5   root     5399:                        }
                   5400:                } else {
1.1.1.7   root     5401:                        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
                   5402:                                int intr = intlev ();
                   5403:                                unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   5404: #ifdef WITH_PPC
                   5405:                                bool m68kint = true;
                   5406:                                if (ppc_state) {
                   5407:                                        m68kint = ppc_interrupt(intr);
                   5408:                                }
                   5409:                                if (m68kint) {
1.1.1.4   root     5410: #endif
1.1.1.7   root     5411:                                        if (intr > 0 && intr > regs.intmask)
                   5412:                                                do_interrupt (intr);
                   5413: #ifdef WITH_PPC
                   5414:                                }
                   5415: #endif
                   5416:                        }
1.1.1.5   root     5417:                }
1.1.1.7   root     5418: 
                   5419:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
                   5420:                        m68k_resumestopped();
1.1.1.5   root     5421:                        return 1;
                   5422:                }
1.1.1.4   root     5423: 
1.1.1.7   root     5424: #ifdef WITH_PPC
                   5425:                if (ppc_state) {
                   5426:                        uae_ppc_execute_check();
                   5427:                        uae_ppc_poll_check_halt();
1.1.1.4   root     5428:                }
1.1.1.7   root     5429: #endif
                   5430: 
1.1.1.4   root     5431:        }
                   5432: 
                   5433:        if (regs.spcflags & SPCFLAG_TRACE)
                   5434:                do_trace ();
                   5435: 
1.1.1.8   root     5436: #ifndef WINUAE_FOR_HATARI
                   5437:        if (regs.spcflags & SPCFLAG_UAEINT) {
                   5438:                check_uae_int_request();
                   5439:                unset_special(SPCFLAG_UAEINT);
                   5440:        }
                   5441: #endif
                   5442: 
1.1.1.7   root     5443: #ifdef WINUAE_FOR_HATARI
                   5444:        if (regs.spcflags & SPCFLAG_MFP) {
                   5445:                MFP_DelayIRQ ();                        /* Handle IRQ propagation */
                   5446:                M68000_Update_intlev ();                /* Refresh the list of pending interrupts */
                   5447:        }
                   5448: #endif
                   5449: 
1.1.1.8   root     5450: //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     5451:        if (m68k_interrupt_delay) {
1.1.1.4   root     5452:                if (time_for_interrupt ()) {
1.1.1.7   root     5453:                        do_interrupt (regs.ipl);
1.1.1.4   root     5454:                }
                   5455:        } else {
                   5456:                if (regs.spcflags & SPCFLAG_INT) {
                   5457:                        int intr = intlev ();
                   5458:                        unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
                   5459:                        if (intr > 0 && (intr > regs.intmask || intr == 7))
1.1.1.7   root     5460:                                do_interrupt (intr);
1.1.1.4   root     5461:                }
                   5462:        }
                   5463: 
1.1.1.8   root     5464: //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     5465:        if (regs.spcflags & SPCFLAG_DOINT) {
                   5466:                unset_special (SPCFLAG_DOINT);
                   5467:                set_special (SPCFLAG_INT);
                   5468:        }
1.1.1.8   root     5469: //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     5470: 
1.1.1.7   root     5471: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     5472:        if (regs.spcflags & SPCFLAG_DEBUGGER)
1.1.1.4   root     5473:                DebugCpu_Check();
1.1.1.7   root     5474: #endif
1.1.1.4   root     5475: 
1.1.1.10! root     5476:        if ((regs.spcflags & SPCFLAG_BRK) || stopped_debug) {
1.1.1.7   root     5477:                unset_special(SPCFLAG_BRK);
                   5478: #ifdef DEBUGGER
1.1.1.10! root     5479:                if (stopped_debug && !regs.stopped) {
        !          5480:                        if (debugging) {
        !          5481:                                debugger_active = 1;
        !          5482:                                stopped_debug = false;
        !          5483:                        }
        !          5484:                }
1.1.1.7   root     5485:                if (debugging) {
1.1.1.10! root     5486:                        if (!stopped_debug)
        !          5487:                                debug();
        !          5488:                        if (regs.stopped) {
        !          5489:                                stopped_debug = true;
        !          5490:                                if (debugging) {
        !          5491:                                        debugger_active = 0;
        !          5492:                                }
1.1.1.7   root     5493:                                goto isstopped;
1.1.1.10! root     5494:                        }
1.1.1.7   root     5495:                }
                   5496: #endif
                   5497: #ifdef WINUAE_FOR_HATARI
                   5498:                return 1;                       /* Exit the upper run_xxx() function */
                   5499: #endif
1.1.1.4   root     5500:        }
1.1.1.7   root     5501: 
1.1.1.4   root     5502:        return 0;
                   5503: }
                   5504: 
                   5505: //static uae_u32 pcs[1000];
                   5506: 
1.1.1.7   root     5507: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5508: #if DEBUG_CD32CDTVIO
                   5509: 
                   5510: static uae_u32 cd32nextpc, cd32request;
                   5511: 
                   5512: static void out_cd32io2 (void)
                   5513: {
                   5514:        uae_u32 request = cd32request;
1.1.1.7   root     5515:        write_log (_T("%08x returned\n"), request);
                   5516:        //write_log (_T("ACTUAL=%d ERROR=%d\n"), get_long (request + 32), get_byte (request + 31));
1.1.1.4   root     5517:        cd32nextpc = 0;
                   5518:        cd32request = 0;
                   5519: }
                   5520: 
                   5521: static void out_cd32io (uae_u32 pc)
                   5522: {
                   5523:        TCHAR out[100];
                   5524:        int ioreq = 0;
                   5525:        uae_u32 request = m68k_areg (regs, 1);
                   5526: 
                   5527:        if (pc == cd32nextpc) {
                   5528:                out_cd32io2 ();
                   5529:                return;
                   5530:        }
                   5531:        out[0] = 0;
                   5532:        switch (pc)
                   5533:        {
                   5534:        case 0xe57cc0:
                   5535:        case 0xf04c34:
1.1.1.7   root     5536:                _stprintf (out, _T("opendevice"));
1.1.1.4   root     5537:                break;
                   5538:        case 0xe57ce6:
                   5539:        case 0xf04c56:
1.1.1.7   root     5540:                _stprintf (out, _T("closedevice"));
1.1.1.4   root     5541:                break;
                   5542:        case 0xe57e44:
                   5543:        case 0xf04f2c:
1.1.1.7   root     5544:                _stprintf (out, _T("beginio"));
1.1.1.4   root     5545:                ioreq = 1;
                   5546:                break;
                   5547:        case 0xe57ef2:
                   5548:        case 0xf0500e:
1.1.1.7   root     5549:                _stprintf (out, _T("abortio"));
1.1.1.4   root     5550:                ioreq = -1;
                   5551:                break;
                   5552:        }
                   5553:        if (out[0] == 0)
                   5554:                return;
                   5555:        if (cd32request)
1.1.1.7   root     5556:                write_log (_T("old request still not returned!\n"));
1.1.1.4   root     5557:        cd32request = request;
                   5558:        cd32nextpc = get_long (m68k_areg (regs, 7));
1.1.1.7   root     5559:        write_log (_T("%s A1=%08X\n"), out, request);
1.1.1.4   root     5560:        if (ioreq) {
                   5561:                static int cnt = 0;
                   5562:                int cmd = get_word (request + 28);
                   5563: #if 0
1.1.1.7   root     5564:                if (cmd == 33) {
                   5565:                        uaecptr data = get_long (request + 40);
                   5566:                        write_log (_T("CD_CONFIG:\n"));
                   5567:                        for (int i = 0; i < 16; i++) {
                   5568:                                write_log (_T("%08X=%08X\n"), get_long (data), get_long (data + 4));
                   5569:                                data += 8;
                   5570:                        }
                   5571:                }
                   5572: #endif
                   5573: #if 0
1.1.1.4   root     5574:                if (cmd == 37) {
                   5575:                        cnt--;
                   5576:                        if (cnt <= 0)
                   5577:                                activate_debugger ();
                   5578:                }
                   5579: #endif
1.1.1.7   root     5580:                write_log (_T("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n"),
                   5581:                        cmd, get_long (request + 40),
                   5582:                        get_long (request + 36), get_long (request + 44), M68K_GETPC);
1.1.1.4   root     5583:        }
                   5584:        if (ioreq < 0)
                   5585:                ;//activate_debugger ();
                   5586: }
                   5587: 
1.1.1.7   root     5588: #endif
                   5589: #endif
                   5590: 
1.1.1.4   root     5591: #ifndef CPUEMU_11
                   5592: 
                   5593: static void m68k_run_1 (void)
                   5594: {
                   5595: }
                   5596: 
                   5597: #else
                   5598: 
                   5599: /* It's really sad to have two almost identical functions for this, but we
                   5600: do it all for performance... :(
                   5601: This version emulates 68000's prefetch "cache" */
                   5602: static void m68k_run_1 (void)
                   5603: {
                   5604:        struct regstruct *r = &regs;
1.1.1.7   root     5605:        bool exit = false;
1.1.1.8   root     5606: 
                   5607:        Log_Printf(LOG_DEBUG, "m68k_run_1\n");
1.1.1.4   root     5608: 
1.1.1.7   root     5609:        while (!exit) {
                   5610:                TRY (prb) {
                   5611:                        while (!exit) {
                   5612:                                r->opcode = r->ir;
                   5613: 
                   5614:                                count_instr (r->opcode);
                   5615: 
                   5616: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     5617:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     5618:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   5619:                                {
                   5620:                                        int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4   root     5621: 
1.1.1.7   root     5622:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4   root     5623: 
1.1.1.7   root     5624:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     5625:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     5626:                                }
                   5627: #endif
1.1.1.4   root     5628: 
1.1.1.7   root     5629: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     5630: #if DEBUG_CD32CDTVIO
1.1.1.7   root     5631:                                out_cd32io (m68k_getpc ());
                   5632: #endif
1.1.1.4   root     5633: #endif
                   5634: 
                   5635: #if 0
1.1.1.7   root     5636:                                int pc = m68k_getpc ();
                   5637:                                if (pc == 0xdff002)
                   5638:                                        write_log (_T("hip\n"));
                   5639:                                if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
                   5640:                                        memmove (pcs + 1, pcs, 998 * 4);
                   5641:                                        pcs[0] = pc;
                   5642:                                        //write_log (_T("%08X-%04X "), pc, r->opcode);
                   5643:                                }
1.1.1.4   root     5644: #endif
1.1.1.7   root     5645:                                do_cycles (cpu_cycles);
                   5646:                                r->instruction_pc = m68k_getpc ();
                   5647:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   5648:                                cpu_cycles = adjust_cycles (cpu_cycles);
                   5649: 
                   5650: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     5651:                                /* Also add some extra cycles to simulate some wait state */
                   5652:                                /* TODO  [NP] do this in all m68k_run_xx() */
                   5653:                                M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT + WaitStateCycles);
                   5654:                                WaitStateCycles = 0;
1.1.1.5   root     5655: 
1.1.1.7   root     5656:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   5657:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   5658:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   5659:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   5660:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   5661:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   5662:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   5663:                                if ( MFP_UpdateNeeded == true )
                   5664:                                        MFP_UpdateIRQ ( 0 );
                   5665: #endif
1.1.1.4   root     5666: 
1.1.1.7   root     5667:                                if (r->spcflags) {
                   5668:                                        if (do_specialties (cpu_cycles))
                   5669:                                                exit = true;
                   5670:                                }
                   5671:                                regs.ipl = regs.ipl_pin;
1.1.1.10! root     5672: 
        !          5673: #ifdef WINUAE_FOR_HATARI
        !          5674:                                if ( savestate_state == STATE_SAVE )
        !          5675:                                        save_state ( NULL , NULL );
        !          5676: #endif
        !          5677: 
1.1.1.7   root     5678:                                if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010))
                   5679:                                        exit = true;
                   5680:                        }
                   5681:                } CATCH (prb) {
                   5682:                        bus_error();
                   5683:                        if (r->spcflags) {
                   5684:                                if (do_specialties(cpu_cycles))
                   5685:                                        exit = true;
                   5686:                        }
                   5687:                        regs.ipl = regs.ipl_pin;
                   5688:                } ENDTRY
                   5689:        }
                   5690: }
1.1.1.4   root     5691: 
                   5692: #endif /* CPUEMU_11 */
                   5693: 
1.1.1.7   root     5694: #ifndef CPUEMU_13
1.1.1.4   root     5695: 
                   5696: static void m68k_run_1_ce (void)
                   5697: {
                   5698: }
                   5699: 
                   5700: #else
                   5701: 
                   5702: /* cycle-exact m68k_run () */
                   5703: 
                   5704: static void m68k_run_1_ce (void)
                   5705: {
                   5706:        struct regstruct *r = &regs;
1.1.1.7   root     5707:        bool first = true;
                   5708:        bool exit = false;
1.1.1.8   root     5709: 
                   5710:        Log_Printf(LOG_DEBUG, "m68k_run_1_ce\n");
1.1.1.7   root     5711: 
                   5712:        while (!exit) {
                   5713:                TRY (prb) {
                   5714:                        if (first) {
                   5715:                                if (cpu_tracer < 0) {
                   5716:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                   5717:                                        r->ir = cputrace.ir;
                   5718:                                        r->irc = cputrace.irc;
                   5719:                                        r->sr = cputrace.sr;
                   5720:                                        r->usp = cputrace.usp;
                   5721:                                        r->isp = cputrace.isp;
                   5722:                                        r->intmask = cputrace.intmask;
                   5723:                                        r->stopped = cputrace.stopped;
                   5724:                                        m68k_setpc (cputrace.pc);
                   5725:                                        if (!r->stopped) {
                   5726:                                                if (cputrace.state > 1) {
                   5727:                                                        write_log (_T("CPU TRACE: EXCEPTION %d\n"), cputrace.state);
                   5728:                                                        Exception (cputrace.state);
                   5729:                                                } else if (cputrace.state == 1) {
                   5730:                                                        write_log (_T("CPU TRACE: %04X\n"), cputrace.opcode);
                   5731:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                   5732:                                                }
                   5733:                                        } else {
                   5734:                                                write_log (_T("CPU TRACE: STOPPED\n"));
                   5735:                                        }
                   5736:                                        if (r->stopped)
                   5737:                                                set_special (SPCFLAG_STOP);
                   5738:                                        set_cpu_tracer (false);
                   5739:                                        goto cont;
                   5740:                                }
                   5741:                                set_cpu_tracer (false);
                   5742:                                first = false;
                   5743:                        }
1.1.1.4   root     5744: 
1.1.1.7   root     5745:                        while (!exit) {
                   5746:                                r->opcode = r->ir;
1.1.1.4   root     5747: 
1.1.1.7   root     5748: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     5749:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     5750:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   5751:                                {
                   5752:                                        int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4   root     5753: 
1.1.1.7   root     5754:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4   root     5755: 
1.1.1.8   root     5756: //fprintf ( stderr , "clock %ld\n" , CyclesGlobalClockCounter );
1.1.1.7   root     5757:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     5758:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     5759:                                }
                   5760: #endif
                   5761: 
                   5762: #ifndef WINUAE_FOR_HATARI
                   5763: #if DEBUG_CD32CDTVIO
                   5764:                                out_cd32io (m68k_getpc ());
                   5765: #endif
                   5766: #endif
                   5767:                                if (cpu_tracer) {
                   5768:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
                   5769:                                        cputrace.opcode = r->opcode;
                   5770:                                        cputrace.ir = r->ir;
                   5771:                                        cputrace.irc = r->irc;
                   5772:                                        cputrace.sr = r->sr;
                   5773:                                        cputrace.usp = r->usp;
                   5774:                                        cputrace.isp = r->isp;
                   5775:                                        cputrace.intmask = r->intmask;
                   5776:                                        cputrace.stopped = r->stopped;
                   5777:                                        cputrace.state = 1;
                   5778:                                        cputrace.pc = m68k_getpc ();
                   5779:                                        cputrace.startcycles = get_cycles ();
                   5780:                                        cputrace.memoryoffset = 0;
                   5781:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   5782:                                        cputrace.readcounter = cputrace.writecounter = 0;
                   5783:                                }
                   5784: 
                   5785: #ifndef WINUAE_FOR_HATARI
                   5786:                                if (inputrecord_debug & 4) {
                   5787:                                        if (input_record > 0)
                   5788:                                                inprec_recorddebug_cpu (1);
                   5789:                                        else if (input_play > 0)
                   5790:                                                inprec_playdebug_cpu (1);
                   5791:                                }
                   5792: #endif
                   5793: 
                   5794: #ifdef WINUAE_FOR_HATARI
                   5795:                                currcycle = 0;
                   5796: #endif
                   5797: 
                   5798:                                r->instruction_pc = m68k_getpc ();
                   5799:                                (*cpufunctbl[r->opcode])(r->opcode);
                   5800:                                wait_memory_cycles();                   // TODO NP : ici, ou plus bas ?
                   5801: #ifdef WINUAE_FOR_HATARI
                   5802: //fprintf ( stderr, "cyc_1ce %d\n" , currcycle );
1.1.1.8   root     5803:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   5804:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   5805:                                currcycle = 0;
1.1.1.7   root     5806: 
                   5807:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   5808:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   5809:                                if ( MFP_UpdateNeeded == true )
                   5810:                                        MFP_UpdateIRQ ( 0 );
                   5811: #endif
                   5812: 
                   5813:                                if (cpu_tracer) {
                   5814:                                        cputrace.state = 0;
                   5815:                                }
                   5816: cont:
                   5817:                                if (cputrace.needendcycles) {
                   5818:                                        cputrace.needendcycles = 0;
                   5819:                                        write_log (_T("STARTCYCLES=%08x ENDCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
                   5820: #ifndef WINUAE_FOR_HATARI
                   5821:                                        log_dma_record ();
                   5822: #endif
                   5823:                                }
                   5824: 
                   5825:                                if (r->spcflags || time_for_interrupt ()) {
                   5826:                                        if (do_specialties (0))
                   5827:                                                exit = true;
                   5828:                                }
                   5829: 
1.1.1.10! root     5830: #ifdef WINUAE_FOR_HATARI
        !          5831:                                if ( savestate_state == STATE_SAVE )
        !          5832:                                        save_state ( NULL , NULL );
        !          5833: #endif
        !          5834: 
1.1.1.7   root     5835:                                if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68010)
                   5836:                                        exit = true;
                   5837:                        }
                   5838:                } CATCH (prb) {
                   5839:                        bus_error();
                   5840:                        if (r->spcflags || time_for_interrupt()) {
                   5841:                                if (do_specialties(0))
                   5842:                                        exit = true;
                   5843:                        }
                   5844:                } ENDTRY
                   5845:        }
                   5846: }
                   5847: 
                   5848: #endif
                   5849: 
1.1.1.8   root     5850: #if defined(CPUEMU_20) && defined(JIT)
1.1.1.7   root     5851: // emulate simple prefetch
                   5852: static uae_u16 get_word_020_prefetchf (uae_u32 pc)
                   5853: {
                   5854:        if (pc == regs.prefetch020addr) {
                   5855:                uae_u16 v = regs.prefetch020[0];
                   5856:                regs.prefetch020[0] = regs.prefetch020[1];
                   5857:                regs.prefetch020[1] = regs.prefetch020[2];
                   5858:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5859:                regs.prefetch020addr += 2;
                   5860:                return v;
                   5861:        } else if (pc == regs.prefetch020addr + 2) {
                   5862:                uae_u16 v = regs.prefetch020[1];
                   5863:                regs.prefetch020[0] = regs.prefetch020[2];
                   5864:                regs.prefetch020[1] = x_get_word (pc + 4);
                   5865:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5866:                regs.prefetch020addr = pc + 2;
                   5867:                return v;
                   5868:        } else if (pc == regs.prefetch020addr + 4) {
                   5869:                uae_u16 v = regs.prefetch020[2];
                   5870:                regs.prefetch020[0] = x_get_word (pc + 2);
                   5871:                regs.prefetch020[1] = x_get_word (pc + 4);
                   5872:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5873:                regs.prefetch020addr = pc + 2;
                   5874:                return v;
                   5875:        } else {
                   5876:                regs.prefetch020addr = pc + 2;
                   5877:                regs.prefetch020[0] = x_get_word (pc + 2);
                   5878:                regs.prefetch020[1] = x_get_word (pc + 4);
                   5879:                regs.prefetch020[2] = x_get_word (pc + 6);
                   5880:                return x_get_word (pc);
1.1.1.4   root     5881:        }
                   5882: }
                   5883: #endif
                   5884: 
1.1.1.8   root     5885: #ifdef WITH_THREADED_CPU
                   5886: static volatile int cpu_thread_active;
1.1.1.10! root     5887: static uae_sem_t cpu_in_sema, cpu_out_sema, cpu_wakeup_sema;
        !          5888: 
        !          5889: static volatile int cpu_thread_ilvl;
        !          5890: static volatile uae_u32 cpu_thread_indirect_mode;
        !          5891: static volatile uae_u32 cpu_thread_indirect_addr;
        !          5892: static volatile uae_u32 cpu_thread_indirect_val;
        !          5893: static volatile uae_u32 cpu_thread_indirect_size;
        !          5894: static volatile uae_u32 cpu_thread_reset;
        !          5895: static uae_thread_id cpu_thread_tid;
1.1.1.8   root     5896: 
                   5897: static bool m68k_cs_initialized;
                   5898: 
                   5899: static int do_specialties_thread(void)
                   5900: {
                   5901:        if (regs.spcflags & SPCFLAG_MODE_CHANGE)
                   5902:                return 1;
                   5903: 
                   5904: #ifdef JIT
                   5905:        unset_special(SPCFLAG_END_COMPILE);   /* has done its job */
                   5906: #endif
                   5907: 
                   5908:        if (regs.spcflags & SPCFLAG_DOTRACE)
                   5909:                Exception(9);
                   5910: 
                   5911:        if (regs.spcflags & SPCFLAG_TRAP) {
                   5912:                unset_special(SPCFLAG_TRAP);
                   5913:                Exception(3);
                   5914:        }
                   5915: 
                   5916:        if (regs.spcflags & SPCFLAG_TRACE)
                   5917:                do_trace();
                   5918: 
1.1.1.10! root     5919:        for (;;) {
1.1.1.8   root     5920: 
1.1.1.10! root     5921:                if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
        !          5922:                        return 1;
        !          5923:                }
1.1.1.8   root     5924: 
1.1.1.10! root     5925:                int ilvl = cpu_thread_ilvl;
        !          5926:                if (ilvl > 0 && (ilvl > regs.intmask || ilvl == 7)) {
        !          5927:                        do_interrupt(ilvl);
        !          5928:                }
        !          5929: 
        !          5930:                if (!(regs.spcflags & SPCFLAG_STOP))
        !          5931:                        break;
        !          5932: 
        !          5933:                uae_sem_wait(&cpu_wakeup_sema);
1.1.1.8   root     5934:        }
                   5935: 
                   5936:        return 0;
                   5937: }
                   5938: 
1.1.1.10! root     5939: static void init_cpu_thread(void)
1.1.1.8   root     5940: {
                   5941:        if (!currprefs.cpu_thread)
                   5942:                return;
1.1.1.10! root     5943:        if (m68k_cs_initialized)
1.1.1.8   root     5944:                return;
1.1.1.10! root     5945:        uae_sem_init(&cpu_in_sema, 0, 0);
        !          5946:        uae_sem_init(&cpu_out_sema, 0, 0);
        !          5947:        uae_sem_init(&cpu_wakeup_sema, 0, 0);
        !          5948:        m68k_cs_initialized = true;
1.1.1.8   root     5949: }
1.1.1.10! root     5950: 
        !          5951: extern addrbank *thread_mem_banks[MEMORY_BANKS];
        !          5952: 
        !          5953: uae_u32 process_cpu_indirect_memory_read(uae_u32 addr, int size)
1.1.1.8   root     5954: {
1.1.1.10! root     5955:        // Do direct access if call is from filesystem etc thread 
        !          5956:        if (cpu_thread_tid != uae_thread_get_id()) {
        !          5957:                uae_u32 data = 0;
        !          5958:                addrbank *ab = thread_mem_banks[bankindex(addr)];
        !          5959:                switch (size)
        !          5960:                {
        !          5961:                case 0:
        !          5962:                        data = ab->bget(addr) & 0xff;
        !          5963:                        break;
        !          5964:                case 1:
        !          5965:                        data = ab->wget(addr) & 0xffff;
        !          5966:                        break;
        !          5967:                case 2:
        !          5968:                        data = ab->lget(addr);
        !          5969:                        break;
        !          5970:                }
        !          5971:                return data;
1.1.1.8   root     5972:        }
1.1.1.10! root     5973: 
        !          5974:        cpu_thread_indirect_mode = 2;
        !          5975:        cpu_thread_indirect_addr = addr;
        !          5976:        cpu_thread_indirect_size = size;
        !          5977:        uae_sem_post(&cpu_out_sema);
        !          5978:        uae_sem_wait(&cpu_in_sema);
        !          5979:        cpu_thread_indirect_mode = 0xfe;
        !          5980:        return cpu_thread_indirect_val;
1.1.1.8   root     5981: }
                   5982: 
1.1.1.10! root     5983: void process_cpu_indirect_memory_write(uae_u32 addr, uae_u32 data, int size)
1.1.1.8   root     5984: {
1.1.1.10! root     5985:        if (cpu_thread_tid != uae_thread_get_id()) {
        !          5986:                addrbank *ab = thread_mem_banks[bankindex(addr)];
        !          5987:                switch (size)
        !          5988:                {
        !          5989:                case 0:
        !          5990:                        ab->bput(addr, data & 0xff);
        !          5991:                        break;
        !          5992:                case 1:
        !          5993:                        ab->wput(addr, data & 0xffff);
        !          5994:                        break;
        !          5995:                case 2:
        !          5996:                        ab->lput(addr, data);
        !          5997:                        break;
        !          5998:                }
1.1.1.8   root     5999:                return;
                   6000:        }
1.1.1.10! root     6001:        cpu_thread_indirect_mode = 1;
        !          6002:        cpu_thread_indirect_addr = addr;
        !          6003:        cpu_thread_indirect_size = size;
        !          6004:        cpu_thread_indirect_val = data;
        !          6005:        uae_sem_post(&cpu_out_sema);
        !          6006:        uae_sem_wait(&cpu_in_sema);
        !          6007:        cpu_thread_indirect_mode = 0xff;
1.1.1.8   root     6008: }
                   6009: 
                   6010: static void run_cpu_thread(void *(*f)(void *))
                   6011: {
1.1.1.10! root     6012:        int framecnt = -1;
        !          6013:        int vp = 0;
        !          6014:        int intlev_prev = 0;
        !          6015: 
1.1.1.8   root     6016:        cpu_thread_active = 0;
1.1.1.10! root     6017:        uae_sem_init(&cpu_in_sema, 0, 0);
        !          6018:        uae_sem_init(&cpu_out_sema, 0, 0);
        !          6019:        uae_sem_init(&cpu_wakeup_sema, 0, 0);
        !          6020: 
        !          6021:        if (!uae_start_thread(_T("cpu"), f, NULL, NULL))
        !          6022:                return;
        !          6023:        while (!cpu_thread_active) {
        !          6024:                sleep_millis(1);
        !          6025:        }
        !          6026: 
        !          6027:        while (!(regs.spcflags & SPCFLAG_MODE_CHANGE)) {
        !          6028:                int maxperloop = 10;
        !          6029: 
        !          6030:                while (!uae_sem_trywait(&cpu_out_sema)) {
        !          6031:                        uae_u32 cmd, addr, data, size, mode;
        !          6032: 
        !          6033:                        addr = cpu_thread_indirect_addr;
        !          6034:                        data = cpu_thread_indirect_val;
        !          6035:                        size = cpu_thread_indirect_size;
        !          6036:                        mode = cpu_thread_indirect_mode;
        !          6037: 
        !          6038:                        switch(mode)
        !          6039:                        {
        !          6040:                                case 1:
        !          6041:                                {
        !          6042:                                        addrbank *ab = thread_mem_banks[bankindex(addr)];
        !          6043:                                        switch (size)
        !          6044:                                        {
        !          6045:                                        case 0:
        !          6046:                                                ab->bput(addr, data & 0xff);
        !          6047:                                                break;
        !          6048:                                        case 1:
        !          6049:                                                ab->wput(addr, data & 0xffff);
        !          6050:                                                break;
        !          6051:                                        case 2:
        !          6052:                                                ab->lput(addr, data);
        !          6053:                                                break;
1.1.1.8   root     6054:                                        }
1.1.1.10! root     6055:                                        uae_sem_post(&cpu_in_sema);
        !          6056:                                        break;
1.1.1.8   root     6057:                                }
1.1.1.10! root     6058:                                case 2:
        !          6059:                                {
        !          6060:                                        addrbank *ab = thread_mem_banks[bankindex(addr)];
        !          6061:                                        switch (size)
        !          6062:                                        {
        !          6063:                                        case 0:
        !          6064:                                                data = ab->bget(addr) & 0xff;
        !          6065:                                                break;
        !          6066:                                        case 1:
        !          6067:                                                data = ab->wget(addr) & 0xffff;
        !          6068:                                                break;
        !          6069:                                        case 2:
        !          6070:                                                data = ab->lget(addr);
        !          6071:                                                break;
1.1.1.8   root     6072:                                        }
1.1.1.10! root     6073:                                        cpu_thread_indirect_val = data;
        !          6074:                                        uae_sem_post(&cpu_in_sema);
        !          6075:                                        break;
1.1.1.8   root     6076:                                }
1.1.1.10! root     6077:                                default:
        !          6078:                                        write_log(_T("cpu_thread_indirect_mode=%08x!\n"), mode);
        !          6079:                                        break;
1.1.1.8   root     6080:                        }
                   6081: 
1.1.1.10! root     6082:                        if (maxperloop-- < 0)
        !          6083:                                break;
        !          6084:                }
        !          6085: 
        !          6086:                if (framecnt != timeframes) {
        !          6087:                        framecnt = timeframes;
        !          6088:                }
        !          6089: 
        !          6090:                if (cpu_thread_reset) {
        !          6091:                        bool hardreset = cpu_thread_reset & 2;
        !          6092:                        bool keyboardreset = cpu_thread_reset & 4;
        !          6093:                        custom_reset(hardreset, keyboardreset);
        !          6094:                        cpu_thread_reset = 0;
        !          6095:                        uae_sem_post(&cpu_in_sema);
        !          6096:                }
        !          6097: 
        !          6098:                if (regs.spcflags & SPCFLAG_BRK) {
1.1.1.8   root     6099:                        unset_special(SPCFLAG_BRK);
                   6100: #ifdef DEBUGGER
                   6101:                        if (debugging) {
                   6102:                                debug();
                   6103:                        }
                   6104: #endif
                   6105:                }
1.1.1.10! root     6106: 
        !          6107:                if (vp == vpos) {
        !          6108: 
        !          6109:                        do_cycles((maxhpos / 2) * CYCLE_UNIT);
        !          6110: 
        !          6111:                        if (regs.spcflags & SPCFLAG_COPPER) {
        !          6112:                                do_copper();
        !          6113:                        }
        !          6114: 
        !          6115:                        check_uae_int_request();
        !          6116:                        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
        !          6117:                                int intr = intlev();
        !          6118:                                unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
        !          6119:                                if (intr > 0) {
        !          6120:                                        cpu_thread_ilvl = intr;
        !          6121:                                        cycles_do_special();
        !          6122:                                        uae_sem_post(&cpu_wakeup_sema);
        !          6123:                                } else {
        !          6124:                                        cpu_thread_ilvl = 0;
        !          6125:                                }
        !          6126:                        }
        !          6127:                        continue;
        !          6128:                }
        !          6129: 
        !          6130:                frame_time_t next = vsyncmintimepre + (vsynctimebase * vpos / (maxvpos + 1));
        !          6131:                frame_time_t c = read_processor_time();
        !          6132:                if ((int)next - (int)c > 0 && (int)next - (int)c < vsyncmaxtime * 2)
        !          6133:                        continue;
        !          6134: 
        !          6135:                vp = vpos;
        !          6136: 
        !          6137:        }
        !          6138: 
        !          6139:        while (cpu_thread_active) {
        !          6140:                uae_sem_post(&cpu_in_sema);
        !          6141:                uae_sem_post(&cpu_wakeup_sema);
        !          6142:                sleep_millis(1);
1.1.1.8   root     6143:        }
1.1.1.10! root     6144: 
        !          6145: }
        !          6146: 
        !          6147: #endif
        !          6148: 
        !          6149: #ifndef WINUAE_FOR_HATARI
        !          6150: void custom_reset_cpu(bool hardreset, bool keyboardreset)
        !          6151: {
        !          6152: #ifdef WITH_THREADED_CPU
        !          6153:        if (cpu_thread_tid != uae_thread_get_id()) {
        !          6154:                custom_reset(hardreset, keyboardreset);
        !          6155:                return;
        !          6156:        }
        !          6157:        cpu_thread_reset = 1 | (hardreset ? 2 : 0) | (keyboardreset ? 4 : 0);
        !          6158:        uae_sem_post(&cpu_wakeup_sema);
        !          6159:        uae_sem_wait(&cpu_in_sema);
        !          6160: #else
        !          6161:        custom_reset(hardreset, keyboardreset);
        !          6162: #endif
1.1.1.8   root     6163: }
                   6164: #endif
                   6165: 
1.1.1.4   root     6166: #ifdef JIT  /* Completely different run_2 replacement */
                   6167: 
                   6168: void do_nothing (void)
                   6169: {
1.1.1.8   root     6170:        if (!currprefs.cpu_thread) {
                   6171:                /* What did you expect this to do? */
                   6172:                do_cycles (0);
                   6173:                /* I bet you didn't expect *that* ;-) */
                   6174:        }
1.1.1.4   root     6175: }
                   6176: 
                   6177: void exec_nostats (void)
                   6178: {
                   6179:        struct regstruct *r = &regs;
                   6180: 
                   6181:        for (;;)
                   6182:        {
1.1.1.7   root     6183:                if (currprefs.cpu_compatible) {
                   6184:                        r->opcode = get_word_020_prefetchf(m68k_getpc());
                   6185:                } else {
                   6186:                        r->opcode = x_get_iword(0);
                   6187:                }
                   6188:                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   6189:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.8   root     6190: 
                   6191:                if (!currprefs.cpu_thread) {
                   6192:                        do_cycles (cpu_cycles);
1.1.1.4   root     6193: 
1.1.1.7   root     6194: #ifdef WITH_PPC
1.1.1.8   root     6195:                        if (ppc_state)
                   6196:                                ppc_interrupt(intlev());
1.1.1.7   root     6197: #endif
1.1.1.8   root     6198:                }
1.1.1.7   root     6199: #ifdef WINUAE_FOR_HATARI
                   6200:                if (end_block(r->opcode) || r->spcflags)
                   6201: #else
                   6202: 
1.1.1.8   root     6203:                if (end_block(r->opcode) || r->spcflags || uae_int_requested)
1.1.1.7   root     6204: #endif
1.1.1.4   root     6205:                        return; /* We will deal with the spcflags in the caller */
                   6206:        }
                   6207: }
                   6208: 
                   6209: void execute_normal (void)
                   6210: {
                   6211:        struct regstruct *r = &regs;
                   6212:        int blocklen;
                   6213:        cpu_history pc_hist[MAXRUN];
                   6214:        int total_cycles;
                   6215: 
                   6216:        if (check_for_cache_miss ())
                   6217:                return;
                   6218: 
                   6219:        total_cycles = 0;
                   6220:        blocklen = 0;
                   6221:        start_pc_p = r->pc_oldp;
                   6222:        start_pc = r->pc;
                   6223:        for (;;) {
                   6224:                /* Take note: This is the do-it-normal loop */
1.1.1.7   root     6225:                regs.instruction_pc = m68k_getpc ();
                   6226:                if (currprefs.cpu_compatible) {
                   6227:                        r->opcode = get_word_020_prefetchf (regs.instruction_pc);
                   6228:                } else {
                   6229:                        r->opcode = x_get_iword(0);
                   6230:                }
1.1.1.4   root     6231: 
                   6232:                special_mem = DISTRUST_CONSISTENT_MEM;
                   6233:                pc_hist[blocklen].location = (uae_u16*)r->pc_p;
                   6234: 
1.1.1.7   root     6235:                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
1.1.1.8   root     6236:                cpu_cycles = adjust_cycles(cpu_cycles);
                   6237:                if (!currprefs.cpu_thread) {
                   6238:                        do_cycles (cpu_cycles);
                   6239:                }
1.1.1.4   root     6240:                total_cycles += cpu_cycles;
                   6241:                pc_hist[blocklen].specmem = special_mem;
                   6242:                blocklen++;
1.1.1.7   root     6243: #ifdef WINUAE_FOR_HATARI
                   6244:                if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags) {
                   6245: #else
1.1.1.8   root     6246:                if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested) {
1.1.1.7   root     6247: #endif
1.1.1.4   root     6248:                        compile_block (pc_hist, blocklen, total_cycles);
                   6249:                        return; /* We will deal with the spcflags in the caller */
                   6250:                }
                   6251:                /* No need to check regs.spcflags, because if they were set,
                   6252:                we'd have ended up inside that "if" */
1.1.1.7   root     6253: 
                   6254: #ifdef WITH_PPC
                   6255:                if (ppc_state)
                   6256:                        ppc_interrupt(intlev());
                   6257: #endif
1.1.1.4   root     6258:        }
                   6259: }
                   6260: 
                   6261: typedef void compiled_handler (void);
                   6262: 
1.1.1.8   root     6263: #ifdef WITH_THREADED_CPU
                   6264: static void *cpu_thread_run_jit(void *v)
1.1.1.4   root     6265: {
1.1.1.10! root     6266:        cpu_thread_tid = uae_thread_get_id();
1.1.1.8   root     6267:        cpu_thread_active = 1;
1.1.1.10! root     6268: #ifdef USE_STRUCTURED_EXCEPTION_HANDLING
        !          6269:        __try
        !          6270: #endif
        !          6271:        {
        !          6272:                for (;;) {
        !          6273:                        ((compiled_handler*)(pushall_call_handler))();
        !          6274:                        /* Whenever we return from that, we should check spcflags */
        !          6275:                        if (regs.spcflags || cpu_thread_ilvl > 0) {
        !          6276:                                if (do_specialties_thread()) {
        !          6277:                                        break;
        !          6278:                                }
1.1.1.8   root     6279:                        }
                   6280:                }
                   6281:        }
1.1.1.10! root     6282: #ifdef USE_STRUCTURED_EXCEPTION_HANDLING
        !          6283: #ifdef JIT
        !          6284:        __except (EvalException(GetExceptionInformation()))
        !          6285: #else
        !          6286:        __except (DummyException(GetExceptionInformation(), GetExceptionCode()))
        !          6287: #endif
        !          6288:        {
        !          6289:                // EvalException does the good stuff...
        !          6290:        }
        !          6291: #endif
1.1.1.8   root     6292:        cpu_thread_active = 0;
                   6293:        return 0;
                   6294: }
                   6295: #endif
                   6296: 
                   6297: static void m68k_run_jit(void)
                   6298: {
                   6299:        Log_Printf(LOG_DEBUG, "m68k_run_jit\n");
                   6300: #ifdef WITH_THREADED_CPU
                   6301:        if (currprefs.cpu_thread) {
                   6302:                run_cpu_thread(cpu_thread_run_jit);
                   6303:                return;
                   6304:        }
                   6305: #endif
                   6306: 
1.1.1.4   root     6307:        for (;;) {
1.1.1.10! root     6308: #ifdef USE_STRUCTURED_EXCEPTION_HANDLING
        !          6309:                __try {
        !          6310: #endif
        !          6311:                        for (;;) {
1.1.1.7   root     6312: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     6313:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
        !          6314:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          6315:                                {
        !          6316:                                        int FrameCycles, HblCounterVideo, LineCycles;
        !          6317:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          6318:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          6319:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
        !          6320:                                }
1.1.1.7   root     6321: #endif
1.1.1.4   root     6322: 
1.1.1.10! root     6323:                                ((compiled_handler*)(pushall_call_handler))();
        !          6324:                                /* Whenever we return from that, we should check spcflags */
        !          6325:                                check_uae_int_request();
        !          6326:                                if (regs.spcflags) {
        !          6327:                                        if (do_specialties(0)) {
        !          6328:                                                return;
        !          6329:                                        }
        !          6330:                                }
1.1.1.4   root     6331:                        }
1.1.1.10! root     6332: 
        !          6333: #ifdef USE_STRUCTURED_EXCEPTION_HANDLING
        !          6334:                } __except (EvalException(GetExceptionInformation())) {
        !          6335:                        // Something very bad happened, generate fake bus error exception
        !          6336:                        // Either emulation continues normally or crashes.
        !          6337:                        // Without this it would have crashed in any case..
        !          6338:                        uaecptr pc = M68K_GETPC;
        !          6339:                        write_log(_T("Unhandled JIT exception! PC=%08x\n"), pc);
        !          6340:                        if (pc & 1)
        !          6341:                                Exception(3);
        !          6342:                        else
        !          6343:                                Exception(2);
1.1.1.4   root     6344:                }
1.1.1.10! root     6345: #endif
1.1.1.4   root     6346:        }
1.1.1.10! root     6347: 
1.1.1.4   root     6348: }
                   6349: #endif /* JIT */
                   6350: 
                   6351: #ifndef CPUEMU_0
                   6352: 
                   6353: static void m68k_run_2 (void)
                   6354: {
                   6355: }
                   6356: 
                   6357: #else
                   6358: 
1.1.1.7   root     6359: static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full)
1.1.1.4   root     6360: {
                   6361:        struct mnemolookup *lookup;
                   6362:        struct instr *dp;
                   6363:        uae_u32 addr;
                   6364:        int fault;
                   6365: 
                   6366:        if (cpufunctbl[opcode] == op_illg_1)
                   6367:                opcode = 0x4AFC;
                   6368:        dp = table68k + opcode;
                   6369:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   6370:                ;
                   6371:        fault = 0;
                   6372:        TRY(prb) {
1.1.1.9   root     6373:                addr = mmu_translate (pc, 0, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0, sz_word);
1.1.1.4   root     6374:        } CATCH (prb) {
                   6375:                fault = 1;
                   6376:        } ENDTRY
                   6377:        if (!fault) {
1.1.1.7   root     6378:                TCHAR buf[100];
                   6379:                if (full)
                   6380:                        write_log (_T("mmufixup=%d %04x %04x\n"), mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
1.1.1.10! root     6381:                m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0xffffffff, 0);
1.1.1.7   root     6382:                write_log (_T("%s\n"), buf);
                   6383:                if (full)
1.1.1.10! root     6384:                        m68k_dumpstate(NULL, 0xffffffff);
1.1.1.7   root     6385:        }
                   6386: }
                   6387: 
1.1.1.9   root     6388: static void check_halt(void)
                   6389: {
                   6390:        if (regs.halted)
                   6391:                do_specialties (0);
                   6392: }
                   6393: 
1.1.1.7   root     6394: void cpu_halt (int id)
                   6395: {
                   6396: #ifndef WINUAE_FOR_HATARI
                   6397:        // id < 0: m68k halted, PPC active.
                   6398:        // id > 0: emulation halted.
                   6399:        if (!regs.halted) {
                   6400:                write_log (_T("CPU halted: reason = %d PC=%08x\n"), id, M68K_GETPC);
                   6401:                regs.halted = id;
                   6402:                gui_data.cpu_halted = id;
                   6403:                gui_led(LED_CPU, 0, -1);
                   6404:                if (id >= 0) {
                   6405:                        regs.intmask = 7;
                   6406:                        MakeSR ();
                   6407:                        audio_deactivate ();
                   6408:                }
                   6409:        }
1.1.1.9   root     6410:        set_special(SPCFLAG_CHECK);
1.1.1.7   root     6411: #else
                   6412:        Dialog_HaltDlg();
                   6413: #endif
                   6414: }
                   6415: 
                   6416: #ifdef CPUEMU_33
                   6417: /* [NP] TODO : use 68060 in Hatari ? with DSP ? */
                   6418: /* MMU 68060  */
                   6419: static void m68k_run_mmu060 (void)
                   6420: {
                   6421:        struct flag_struct f;
                   6422:        int halt = 0;
1.1.1.8   root     6423: 
1.1.1.9   root     6424:        check_halt();
1.1.1.8   root     6425: #ifdef WINUAE_FOR_HATARI
                   6426:        Log_Printf(LOG_DEBUG,  "m68k_run_mmu060\n");
                   6427: #endif
1.1.1.7   root     6428: 
                   6429:        while (!halt) {
                   6430:                TRY (prb) {
                   6431:                        for (;;) {
1.1.1.8   root     6432: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     6433:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.8   root     6434:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6435:                                {
                   6436:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6437:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6438:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     6439:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.8   root     6440:                                }
                   6441: #endif
1.1.1.7   root     6442:                                f.cznv = regflags.cznv;
                   6443:                                f.x = regflags.x;
                   6444:                                regs.instruction_pc = m68k_getpc ();
                   6445: 
                   6446:                                do_cycles (cpu_cycles);
                   6447: 
                   6448:                                mmu_opcode = -1;
                   6449:                                mmu060_state = 0;
                   6450:                                mmu_opcode = regs.opcode = x_prefetch (0);
                   6451:                                mmu060_state = 1;
                   6452: 
                   6453:                                count_instr (regs.opcode);
                   6454:                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   6455: 
                   6456:                                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.8   root     6457: #ifdef WINUAE_FOR_HATARI
                   6458:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.7   root     6459: 
1.1.1.8   root     6460:                                if ( WaitStateCycles ) {
                   6461:                                        /* Add some extra cycles to simulate a wait state */
                   6462:                                        M68000_AddCycles(WaitStateCycles);
                   6463:                                        WaitStateCycles = 0;
                   6464:                                }
                   6465: 
                   6466:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6467:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6468:                                if ( MFP_UpdateNeeded == true )
                   6469:                                        MFP_UpdateIRQ ( 0 );
                   6470: #endif
1.1.1.7   root     6471:                                if (regs.spcflags) {
                   6472:                                        if (do_specialties (cpu_cycles))
                   6473:                                                return;
                   6474:                                }
1.1.1.8   root     6475: #ifdef WINUAE_FOR_HATARI
                   6476:                                /* Run DSP 56k code if necessary */
                   6477:                                if (bDspEnabled) {
                   6478:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
                   6479: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
                   6480:                                }
1.1.1.10! root     6481: 
        !          6482:                                if ( savestate_state == STATE_SAVE )
        !          6483:                                        save_state ( NULL , NULL );
1.1.1.8   root     6484: #endif
1.1.1.7   root     6485:                        }
                   6486:                } CATCH (prb) {
                   6487: 
                   6488:                        m68k_setpci (regs.instruction_pc);
                   6489:                        regflags.cznv = f.cznv;
                   6490:                        regflags.x = f.x;
                   6491: 
                   6492:                        if (mmufixup[0].reg >= 0) {
                   6493:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                   6494:                                mmufixup[0].reg = -1;
                   6495:                        }
                   6496:                        if (mmufixup[1].reg >= 0) {
                   6497:                                m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
                   6498:                                mmufixup[1].reg = -1;
                   6499:                        }
                   6500: 
                   6501:                        TRY (prb2) {
                   6502:                                Exception (prb);
                   6503:                        } CATCH (prb2) {
                   6504:                                halt = 1;
                   6505:                        } ENDTRY
                   6506:                } ENDTRY
1.1.1.4   root     6507:        }
1.1.1.7   root     6508:        cpu_halt(halt);
1.1.1.4   root     6509: }
1.1.1.7   root     6510: 
1.1.1.4   root     6511: #endif
                   6512: 
1.1.1.7   root     6513: #ifdef CPUEMU_31
1.1.1.4   root     6514: 
                   6515: /* Aranym MMU 68040  */
                   6516: static void m68k_run_mmu040 (void)
                   6517: {
1.1.1.7   root     6518:        struct flag_struct f;
                   6519:        int halt = 0;
1.1.1.8   root     6520: 
1.1.1.9   root     6521:        check_halt();
1.1.1.8   root     6522: #ifdef WINUAE_FOR_HATARI
                   6523:        Log_Printf(LOG_DEBUG,  "m68k_run_mmu040\n");
                   6524: #endif
1.1.1.7   root     6525: 
                   6526:        while (!halt) {
                   6527:                TRY (prb) {
                   6528:                        for (;;) {
                   6529: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     6530:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     6531:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6532:                                {
                   6533:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6534:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6535:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     6536:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     6537:                                }
                   6538: #endif
                   6539:                                f.cznv = regflags.cznv;
                   6540:                                f.x = regflags.x;
                   6541:                                mmu_restart = true;
                   6542:                                regs.instruction_pc = m68k_getpc ();
                   6543: 
                   6544:                                do_cycles (cpu_cycles);
                   6545: 
                   6546:                                mmu_opcode = -1;
                   6547:                                mmu_opcode = regs.opcode = x_prefetch (0);
                   6548:                                count_instr (regs.opcode);
                   6549:                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   6550:                                cpu_cycles = adjust_cycles (cpu_cycles);
                   6551: 
                   6552: #ifdef WINUAE_FOR_HATARI
                   6553:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
                   6554: 
1.1.1.8   root     6555:                                if ( WaitStateCycles ) {
1.1.1.7   root     6556:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     6557:                                        M68000_AddCycles(WaitStateCycles);
                   6558:                                        WaitStateCycles = 0;
1.1.1.7   root     6559:                                }
1.1.1.4   root     6560: 
1.1.1.7   root     6561:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6562:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6563:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6564:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6565:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6566:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6567:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6568:                                if ( MFP_UpdateNeeded == true )
                   6569:                                        MFP_UpdateIRQ ( 0 );
                   6570: #endif
1.1.1.4   root     6571: 
1.1.1.7   root     6572:                                if (regs.spcflags) {
                   6573:                                        if (do_specialties (cpu_cycles))
                   6574:                                                return;
1.1.1.4   root     6575:                                }
1.1.1.7   root     6576: 
                   6577: #ifdef WINUAE_FOR_HATARI
                   6578:                                /* Run DSP 56k code if necessary */
                   6579:                                if (bDspEnabled) {
                   6580:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     6581: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     6582:                                }
1.1.1.10! root     6583: 
        !          6584:                                if ( savestate_state == STATE_SAVE )
        !          6585:                                        save_state ( NULL , NULL );
1.1.1.7   root     6586: #endif
1.1.1.4   root     6587:                        }
1.1.1.7   root     6588:                } CATCH (prb) {
                   6589: 
                   6590:                        if (mmu_restart) {
                   6591:                                /* restore state if instruction restart */
                   6592:                                regflags.cznv = f.cznv;
                   6593:                                regflags.x = f.x;
                   6594:                                m68k_setpci (regs.instruction_pc);
1.1.1.4   root     6595:                        }
1.1.1.7   root     6596: 
                   6597:                        if (mmufixup[0].reg >= 0) {
                   6598:                                m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                   6599:                                mmufixup[0].reg = -1;
1.1.1.4   root     6600:                        }
1.1.1.7   root     6601: 
                   6602:                        TRY (prb2) {
                   6603:                                Exception (prb);
                   6604:                        } CATCH (prb2) {
                   6605:                                halt = 1;
                   6606:                        } ENDTRY
                   6607:                } ENDTRY
                   6608:        }
                   6609:        cpu_halt(halt);
                   6610: }
                   6611: 
                   6612: #endif
                   6613: 
                   6614: #ifdef CPUEMU_32
                   6615: 
                   6616: // Previous MMU 68030
                   6617: static void m68k_run_mmu030 (void)
                   6618: {
                   6619:        struct flag_struct f;
                   6620:        int halt = 0;
1.1.1.8   root     6621: 
                   6622: #ifdef WINUAE_FOR_HATARI
                   6623:        Log_Printf(LOG_DEBUG,  "m68k_run_mmu030\n");
                   6624: #endif
1.1.1.7   root     6625: 
                   6626:        mmu030_opcode_stageb = -1;
                   6627:        mmu030_fake_prefetch = -1;
1.1.1.9   root     6628:        check_halt();
1.1.1.7   root     6629:        while(!halt) {
                   6630:                TRY (prb) {
                   6631:                        for (;;) {
                   6632:                                int cnt;
                   6633: insretry:
                   6634:                                regs.instruction_pc = m68k_getpc ();
                   6635:                                f.cznv = regflags.cznv;
                   6636:                                f.x = regflags.x;
                   6637: 
                   6638:                                mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
                   6639:                                mmu030_opcode = -1;
                   6640:                                if (mmu030_fake_prefetch >= 0) {
                   6641:                                        // use fake prefetch opcode only if mapping changed
                   6642:                                        uaecptr new_addr = mmu030_translate(regs.instruction_pc, regs.s != 0, false, false);
                   6643:                                        if (mmu030_fake_prefetch_addr != new_addr) {
                   6644:                                                regs.opcode = mmu030_fake_prefetch;
1.1.1.8   root     6645:                                                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     6646:                                        } else {
                   6647:                                                if (mmu030_opcode_stageb < 0) {
                   6648:                                                        regs.opcode = x_prefetch (0);
                   6649:                                                } else {
                   6650:                                                        regs.opcode = mmu030_opcode_stageb;
                   6651:                                                        mmu030_opcode_stageb = -1;
                   6652:                                                }
                   6653:                                        }
                   6654:                                        mmu030_fake_prefetch = -1;
                   6655:                                } else if (mmu030_opcode_stageb < 0) {
1.1.1.9   root     6656:                                        if (currprefs.cpu_compatible)
                   6657:                                                regs.opcode = regs.irc;
                   6658:                                        else
                   6659:                                                regs.opcode = x_prefetch (0);
1.1.1.7   root     6660:                                } else {
                   6661:                                        regs.opcode = mmu030_opcode_stageb;
                   6662:                                        mmu030_opcode_stageb = -1;
                   6663:                                }
                   6664: 
                   6665:                                mmu030_opcode = regs.opcode;
                   6666:                                mmu030_ad[0].done = false;
                   6667: 
                   6668:                                cnt = 50;
                   6669:                                for (;;) {
1.1.1.10! root     6670: #ifdef WINUAE_FOR_HATARI
        !          6671:                                        //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
        !          6672:                                        if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
        !          6673:                                        {
        !          6674:                                                int FrameCycles, HblCounterVideo, LineCycles;
        !          6675:                                                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
        !          6676:                                                LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
        !          6677:                                                m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
        !          6678:                                        }
        !          6679: #endif
1.1.1.9   root     6680:                                        regs.opcode = regs.irc = mmu030_opcode;
1.1.1.7   root     6681:                                        mmu030_idx = 0;
1.1.1.9   root     6682: 
1.1.1.7   root     6683:                                        mmu030_retry = false;
                   6684: 
1.1.1.9   root     6685:                                        if (!currprefs.cpu_cycle_exact) {
                   6686: 
                   6687:                                                count_instr (regs.opcode);
                   6688:                                                do_cycles (cpu_cycles);
                   6689: 
                   6690:                                                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   6691: 
                   6692:                                        } else {
                   6693: #ifdef WINUAE_FOR_HATARI
                   6694:                                                currcycle = 0;
                   6695: #endif
                   6696:                                                (*cpufunctbl[regs.opcode])(regs.opcode);
                   6697: 
                   6698:                                                wait_memory_cycles();
                   6699:                                        }
                   6700: 
1.1.1.7   root     6701:                                        cnt--; // so that we don't get in infinite loop if things go horribly wrong
                   6702:                                        if (!mmu030_retry)
                   6703:                                                break;
                   6704:                                        if (cnt < 0) {
1.1.1.8   root     6705:                                                cpu_halt (CPU_HALT_CPU_STUCK);
1.1.1.7   root     6706:                                                break;
                   6707:                                        }
                   6708:                                        if (mmu030_retry && mmu030_opcode == -1)
                   6709:                                                goto insretry; // urgh
                   6710:                                }
1.1.1.4   root     6711: 
1.1.1.7   root     6712:                                mmu030_opcode = -1;
1.1.1.4   root     6713: 
1.1.1.9   root     6714:                                if (!currprefs.cpu_cycle_exact) {
1.1.1.4   root     6715: 
1.1.1.9   root     6716:                                        cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.7   root     6717: #ifdef WINUAE_FOR_HATARI
1.1.1.9   root     6718:                                        M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4   root     6719: 
1.1.1.9   root     6720:                                        if ( WaitStateCycles ) {
                   6721:                                                /* Add some extra cycles to simulate a wait state */
                   6722:                                                M68000_AddCycles(WaitStateCycles);
                   6723:                                                WaitStateCycles = 0;
                   6724:                                        }
1.1.1.7   root     6725: 
1.1.1.9   root     6726:                                        /* We can have several interrupts at the same time before the next CPU instruction */
                   6727:                                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6728:                                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6729:                                        /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6730:                                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6731:                                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6732:                                                CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6733:                                        if ( MFP_UpdateNeeded == true )
                   6734:                                                MFP_UpdateIRQ ( 0 );
1.1.1.7   root     6735: #endif
1.1.1.9   root     6736:                                        if (regs.spcflags) {
                   6737:                                                if (do_specialties (cpu_cycles))
                   6738:                                                        return;
                   6739:                                        }
1.1.1.7   root     6740: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     6741:                                        /* Run DSP 56k code if necessary */
        !          6742:                                        if (bDspEnabled) {
        !          6743:                                                DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
        !          6744: //                                             DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
        !          6745:                                        }
1.1.1.7   root     6746: #endif
                   6747: 
1.1.1.9   root     6748:                                } else {
                   6749: 
                   6750: #ifdef WINUAE_FOR_HATARI
                   6751: //fprintf ( stderr, "cyc_2ce %d\n" , currcycle );
                   6752:                                        /* Flush all CE cycles so far to update PendingInterruptCount */
                   6753:                                        M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   6754: //                                     currcycle = 0;  // FIXME : uncomment this when using DSP_CyclesGlobalClockCounter in DSP_Run
                   6755: 
                   6756:                                        /* We can have several interrupts at the same time before the next CPU instruction */
                   6757:                                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6758:                                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6759:                                        /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6760:                                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6761:                                        while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6762:                                                CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6763:                                        if ( MFP_UpdateNeeded == true )
                   6764:                                                MFP_UpdateIRQ ( 0 );
                   6765: #endif
                   6766: 
                   6767:                                        if (regs.spcflags || time_for_interrupt ()) {
                   6768:                                                if (do_specialties (0))
                   6769:                                                        return;
                   6770:                                        }
                   6771: 
                   6772: #ifdef WINUAE_FOR_HATARI
                   6773:                                        /* Run DSP 56k code if necessary */
                   6774:                                        if (bDspEnabled) {
                   6775: //fprintf ( stderr, "dsp cyc_2ce %d\n" , currcycle );
                   6776:                                                DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
                   6777: //fprintf ( stderr, "dsp cyc_2ce %d - %d\n" , currcycle * 2 / CYCLE_UNIT , (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) );
                   6778: //                                             DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
                   6779:                                        }
                   6780: #endif
                   6781: 
                   6782:                                        regs.ipl = regs.ipl_pin;
                   6783: 
                   6784:                                }
                   6785: 
1.1.1.10! root     6786: #ifdef WINUAE_FOR_HATARI
        !          6787:                                if ( savestate_state == STATE_SAVE )
        !          6788:                                        save_state ( NULL , NULL );
        !          6789: #endif
1.1.1.9   root     6790:                        }
                   6791: 
                   6792:                } CATCH (prb) {
                   6793: 
                   6794:                        if (mmu030_opcode == -1 && currprefs.cpu_compatible) {
                   6795:                                // full prefetch fill access fault
                   6796:                                // TODO: this should create shorter A-frame
                   6797:                                mmufixup[0].reg = -1;
                   6798:                                mmufixup[1].reg = -1;
1.1.1.10! root     6799:                        } else if (!(mmu030_state[1] & MMU030_STATEFLAG1_LASTWRITE)) {
1.1.1.9   root     6800:                                regflags.cznv = f.cznv;
                   6801:                                regflags.x = f.x;
                   6802: 
                   6803:                                if (mmufixup[0].reg >= 0) {
1.1.1.10! root     6804:                                        m68k_areg(regs, mmufixup[0].reg) = mmufixup[0].value;
1.1.1.9   root     6805:                                        mmufixup[0].reg = -1;
                   6806:                                }
                   6807:                                if (mmufixup[1].reg >= 0) {
1.1.1.10! root     6808:                                        m68k_areg(regs, mmufixup[1].reg) = mmufixup[1].value;
1.1.1.9   root     6809:                                        mmufixup[1].reg = -1;
                   6810:                                }
                   6811:                        }
                   6812: 
                   6813:                        m68k_setpci (regs.instruction_pc);
                   6814: 
                   6815:                        TRY (prb2) {
                   6816:                                Exception (prb);
                   6817:                        } CATCH (prb2) {
                   6818:                                halt = 1;
                   6819:                        } ENDTRY
                   6820:                } ENDTRY
                   6821:        }
                   6822:        cpu_halt (halt);
                   6823: }
1.1.1.7   root     6824: 
                   6825: #endif
                   6826: 
                   6827: 
                   6828: /* "cycle exact" 68040/060 */
                   6829: 
                   6830: static void m68k_run_3ce (void)
                   6831: {
                   6832:        struct regstruct *r = &regs;
                   6833:        bool exit = false;
1.1.1.10! root     6834:        int extracycles = 0;
1.1.1.8   root     6835: 
                   6836:        Log_Printf(LOG_DEBUG, "m68k_run_3ce\n");
1.1.1.7   root     6837: 
                   6838:        while (!exit) {
                   6839:                TRY(prb) {
                   6840:                        while (!exit) {
                   6841: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     6842:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     6843:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6844:                                {
                   6845:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6846:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6847:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     6848:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     6849:                                }
1.1.1.8   root     6850:                                currcycle = CYCLE_UNIT / 2;     /* Assume at least 1 cycle per instruction */
1.1.1.7   root     6851: #endif
                   6852:                                r->instruction_pc = m68k_getpc();
                   6853:                                r->opcode = get_iword_cache_040(0);
                   6854:                                // "prefetch"
                   6855:                                if (regs.cacr & 0x8000)
                   6856:                                        fill_icache040(r->instruction_pc + 16);
                   6857: 
                   6858:                                (*cpufunctbl[r->opcode])(r->opcode);
                   6859: 
                   6860: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     6861: //fprintf ( stderr, "cyc_3ce %ld\n" , currcycle );
                   6862:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   6863:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   6864: //                             currcycle = 0;  // FIXME : uncomment this when using DSP_CyclesGlobalClockCounter in DSP_Run
1.1.1.7   root     6865: 
                   6866:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6867:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6868:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6869:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6870:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6871:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6872:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6873:                                if ( MFP_UpdateNeeded == true )
                   6874:                                        MFP_UpdateIRQ ( 0 );
                   6875: #endif
                   6876:                                if (r->spcflags) {
                   6877:                                        if (do_specialties (0))
                   6878:                                                exit = true;
                   6879:                                }
                   6880: 
1.1.1.10! root     6881:                                // workaround for situation when all accesses are cached
        !          6882:                                extracycles++;
        !          6883:                                if (extracycles >= 8) {
        !          6884:                                        extracycles = 0;
        !          6885: #ifdef WINUAE_FOR_HATARI
        !          6886:                                        x_do_cycles(CYCLE_UNIT);
        !          6887: #else
        !          6888:                                        M68000_AddCycles_CE ( 2 );
        !          6889: #endif
        !          6890:                                }
        !          6891: 
1.1.1.7   root     6892: #ifdef WINUAE_FOR_HATARI
                   6893:                                /* Run DSP 56k code if necessary */
                   6894:                                if (bDspEnabled) {
                   6895:                                        DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
1.1.1.8   root     6896: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.4   root     6897:                                }
1.1.1.10! root     6898: 
        !          6899:                                if ( savestate_state == STATE_SAVE )
        !          6900:                                        save_state ( NULL , NULL );
1.1.1.7   root     6901: #endif
1.1.1.4   root     6902:                        }
1.1.1.7   root     6903:                } CATCH(prb) {
                   6904:                        bus_error();
                   6905:                        if (r->spcflags) {
                   6906:                                if (do_specialties(0))
                   6907:                                        exit = true;
                   6908:                        }
                   6909:                } ENDTRY
                   6910:        }
                   6911: }
1.1.1.4   root     6912: 
1.1.1.7   root     6913: /* "prefetch" 68040/060 */
1.1.1.4   root     6914: 
1.1.1.7   root     6915: static void m68k_run_3p(void)
                   6916: {
                   6917:        struct regstruct *r = &regs;
                   6918:        bool exit = false;
                   6919:        int cycles;
1.1.1.8   root     6920: 
                   6921:        Log_Printf(LOG_DEBUG, "m68k_run_3p\n");
1.1.1.7   root     6922: 
                   6923:        while (!exit)  {
                   6924:                TRY(prb) {
                   6925:                        while (!exit) {
                   6926: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     6927:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     6928:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   6929:                                {
                   6930:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   6931:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   6932:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     6933:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     6934:                                }
                   6935: #endif
                   6936:                                r->instruction_pc = m68k_getpc();
                   6937:                                r->opcode = get_iword_cache_040(0);
                   6938:                                // "prefetch"
                   6939:                                if (regs.cacr & 0x8000)
                   6940:                                        fill_icache040(r->instruction_pc + 16);
                   6941: 
                   6942:                                (*cpufunctbl[r->opcode])(r->opcode);
                   6943: 
1.1.1.8   root     6944: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     6945:                                cpu_cycles = 1 * CYCLE_UNIT;
                   6946:                                cycles = adjust_cycles(cpu_cycles);
                   6947:                                do_cycles(cycles);
1.1.1.8   root     6948: #else
                   6949:                                cycles = cpu_cycles = CYCLE_UNIT / 2;
                   6950:                                M68000_AddCycles_CE(cycles * 2 / CYCLE_UNIT);
1.1.1.7   root     6951: 
1.1.1.8   root     6952:                                if ( WaitStateCycles ) {
1.1.1.7   root     6953:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     6954:                                        M68000_AddCycles(WaitStateCycles);
                   6955:                                        WaitStateCycles = 0;
1.1.1.7   root     6956:                                }
1.1.1.4   root     6957: 
1.1.1.7   root     6958:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   6959:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   6960:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   6961:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   6962:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   6963:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   6964:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   6965:                                if ( MFP_UpdateNeeded == true )
                   6966:                                        MFP_UpdateIRQ ( 0 );
                   6967: #endif
                   6968: 
                   6969:                                if (r->spcflags) {
                   6970:                                        if (do_specialties(0))
                   6971:                                                exit = true;
                   6972:                                }
                   6973: 
                   6974: #ifdef WINUAE_FOR_HATARI
                   6975:                                /* Run DSP 56k code if necessary */
                   6976:                                if (bDspEnabled) {
                   6977:                                        DSP_Run(2 * cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     6978: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     6979:                                }
1.1.1.10! root     6980: 
        !          6981:                                if ( savestate_state == STATE_SAVE )
        !          6982:                                        save_state ( NULL , NULL );
1.1.1.7   root     6983: #endif
                   6984:                        }
                   6985:                } CATCH(prb) {
                   6986:                        bus_error();
                   6987:                        if (r->spcflags) {
                   6988:                                if (do_specialties(0))
                   6989:                                        exit = true;
                   6990:                        }
                   6991:                } ENDTRY
                   6992:        }
1.1.1.4   root     6993: }
                   6994: 
                   6995: /* "cycle exact" 68020/030  */
1.1.1.7   root     6996: 
                   6997: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp);
1.1.1.4   root     6998: static void m68k_run_2ce (void)
                   6999: {
                   7000:        struct regstruct *r = &regs;
1.1.1.7   root     7001:        bool exit = false;
                   7002:        bool first = true;
1.1.1.8   root     7003: 
                   7004:        Log_Printf(LOG_DEBUG, "m68k_run_2ce\n");
1.1.1.7   root     7005: 
                   7006:        while (!exit) {
                   7007:                TRY(prb) {
                   7008:                        if (first) {
                   7009:                                if (cpu_tracer < 0) {
                   7010:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                   7011:                                        r->ir = cputrace.ir;
                   7012:                                        r->irc = cputrace.irc;
                   7013:                                        r->sr = cputrace.sr;
                   7014:                                        r->usp = cputrace.usp;
                   7015:                                        r->isp = cputrace.isp;
                   7016:                                        r->intmask = cputrace.intmask;
                   7017:                                        r->stopped = cputrace.stopped;
                   7018: 
                   7019:                                        r->msp = cputrace.msp;
                   7020:                                        r->vbr = cputrace.vbr;
                   7021:                                        r->caar = cputrace.caar;
                   7022:                                        r->cacr = cputrace.cacr;
                   7023:                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
                   7024:                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
                   7025:                                        r->prefetch020addr = cputrace.prefetch020addr;
1.1.1.9   root     7026:                                        memcpy(&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof(uae_u16));
                   7027:                                        memcpy(&r->prefetch020_valid, &cputrace.prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
                   7028:                                        memcpy(&caches020, &cputrace.caches020, sizeof caches020);
1.1.1.7   root     7029: 
                   7030:                                        m68k_setpc (cputrace.pc);
                   7031:                                        if (!r->stopped) {
                   7032:                                                if (cputrace.state > 1)
                   7033:                                                        Exception (cputrace.state);
                   7034:                                                else if (cputrace.state == 1)
                   7035:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                   7036:                                        }
                   7037:                                        if (regs.stopped)
                   7038:                                                set_special (SPCFLAG_STOP);
                   7039:                                        set_cpu_tracer (false);
                   7040:                                        goto cont;
                   7041:                                }
                   7042:                                set_cpu_tracer (false);
                   7043:                                first = false;
                   7044:                        }
1.1.1.4   root     7045: 
1.1.1.7   root     7046:                        while (!exit) {
1.1.1.8   root     7047: #if 0
1.1.1.7   root     7048:                                static int prevopcode;
1.1.1.8   root     7049: #endif
1.1.1.7   root     7050: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     7051:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     7052:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   7053:                                {
                   7054:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   7055:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   7056:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     7057:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     7058: #if 0
                   7059: // logs to debug data cache issues
                   7060: struct cache030 *c1 ,*c2;
                   7061:         int lws1, lws2;
                   7062:         uae_u32 tag1, tag2;
                   7063: c1 = getcache030 (dcaches030, (uaecptr)0x27ece, &tag1, &lws1);
                   7064: c2 = getcache030 (dcaches030, (uaecptr)0x7f8192+4, &tag2, &lws2);
                   7065: 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) );
                   7066: //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) );
                   7067: #endif
                   7068:                                }
1.1.1.4   root     7069: 
1.1.1.7   root     7070:                                currcycle = 0;
                   7071: #endif
                   7072:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     7073: 
1.1.1.8   root     7074: #if 0
1.1.1.7   root     7075:                                if (regs.irc == 0xfffb) {
                   7076:                                        gui_message (_T("OPCODE %04X HAS FAULTY PREFETCH! PC=%08X"), prevopcode, r->instruction_pc);
                   7077:                                }
1.1.1.8   root     7078: #endif
1.1.1.4   root     7079: 
1.1.1.7   root     7080:                                //write_log (_T("%x %04x\n"), r->instruction_pc, regs.irc);
1.1.1.4   root     7081: 
1.1.1.7   root     7082:                                r->opcode = regs.irc;
1.1.1.8   root     7083: #if 0
1.1.1.7   root     7084:                                prevopcode = r->opcode;
                   7085:                                regs.irc = 0xfffb;
1.1.1.8   root     7086: #endif
1.1.1.7   root     7087:                                //write_log (_T("%08x %04x\n"), r->instruction_pc, opcode);
1.1.1.5   root     7088: 
1.1.1.7   root     7089: #ifndef WINUAE_FOR_HATARI
                   7090: #if DEBUG_CD32CDTVIO
                   7091:                                out_cd32io (r->instruction_pc);
                   7092: #endif
                   7093: #endif
1.1.1.4   root     7094: 
1.1.1.7   root     7095:                                if (cpu_tracer) {
1.1.1.4   root     7096: 
1.1.1.7   root     7097: #if CPUTRACE_DEBUG
                   7098:                                        validate_trace ();
                   7099: #endif
                   7100:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
                   7101:                                        cputrace.opcode = r->opcode;
                   7102:                                        cputrace.ir = r->ir;
                   7103:                                        cputrace.irc = r->irc;
                   7104:                                        cputrace.sr = r->sr;
                   7105:                                        cputrace.usp = r->usp;
                   7106:                                        cputrace.isp = r->isp;
                   7107:                                        cputrace.intmask = r->intmask;
                   7108:                                        cputrace.stopped = r->stopped;
                   7109:                                        cputrace.state = 1;
                   7110:                                        cputrace.pc = m68k_getpc ();
                   7111: 
                   7112:                                        cputrace.msp = r->msp;
                   7113:                                        cputrace.vbr = r->vbr;
                   7114:                                        cputrace.caar = r->caar;
                   7115:                                        cputrace.cacr = r->cacr;
                   7116:                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
                   7117:                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
                   7118:                                        cputrace.prefetch020addr = r->prefetch020addr;
1.1.1.9   root     7119:                                        memcpy(&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
                   7120:                                        memcpy(&cputrace.prefetch020_valid, &r->prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
                   7121:                                        memcpy(&cputrace.caches020, &caches020, sizeof caches020);
1.1.1.7   root     7122: 
                   7123:                                        cputrace.memoryoffset = 0;
                   7124:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   7125:                                        cputrace.readcounter = cputrace.writecounter = 0;
                   7126:                                }
1.1.1.4   root     7127: 
1.1.1.7   root     7128: #ifndef WINUAE_FOR_HATARI
                   7129:                                if (inputrecord_debug & 4) {
                   7130:                                        if (input_record > 0)
                   7131:                                                inprec_recorddebug_cpu (1);
                   7132:                                        else if (input_play > 0)
                   7133:                                                inprec_playdebug_cpu (1);
                   7134:                                }
                   7135: #endif
1.1.1.4   root     7136: 
1.1.1.7   root     7137:                                (*cpufunctbl[r->opcode])(r->opcode);
                   7138:                
                   7139:                                wait_memory_cycles();
                   7140: 
1.1.1.8   root     7141: #ifdef WINUAE_FOR_HATARI
                   7142: //fprintf ( stderr, "cyc_2ce %d\n" , currcycle );
                   7143:                                /* Flush all CE cycles so far to update PendingInterruptCount */
                   7144:                                M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
                   7145: //                             currcycle = 0;  // FIXME : uncomment this when using DSP_CyclesGlobalClockCounter in DSP_Run
1.1.1.4   root     7146: 
1.1.1.7   root     7147:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   7148:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   7149:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   7150:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   7151:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   7152:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   7153:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   7154:                                if ( MFP_UpdateNeeded == true )
                   7155:                                        MFP_UpdateIRQ ( 0 );
                   7156: #endif
1.1.1.4   root     7157: 
1.1.1.9   root     7158:                cont:
1.1.1.7   root     7159:                                if (r->spcflags || time_for_interrupt ()) {
                   7160:                                        if (do_specialties (0))
                   7161:                                                exit = true;
                   7162:                                }
1.1.1.4   root     7163: 
1.1.1.10! root     7164:                                regs.ipl = regs.ipl_pin;
1.1.1.7   root     7165: #ifdef WINUAE_FOR_HATARI
                   7166:                                /* Run DSP 56k code if necessary */
                   7167:                                if (bDspEnabled) {
                   7168: //fprintf ( stderr, "dsp cyc_2ce %d\n" , currcycle );
                   7169:                                        DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
1.1.1.8   root     7170: //fprintf ( stderr, "dsp cyc_2ce %d - %d\n" , currcycle * 2 / CYCLE_UNIT , (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) );
                   7171: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     7172:                                }
1.1.1.4   root     7173: 
1.1.1.10! root     7174:                                if ( savestate_state == STATE_SAVE )
        !          7175:                                        save_state ( NULL , NULL );
        !          7176: #endif
1.1.1.4   root     7177: 
1.1.1.7   root     7178:                        }
                   7179:                } CATCH(prb) {
                   7180:                        bus_error();
                   7181:                        if (r->spcflags || time_for_interrupt()) {
1.1.1.9   root     7182:                                if (do_specialties(0))
1.1.1.7   root     7183:                                        exit = true;
                   7184:                        }
1.1.1.9   root     7185:                        regs.ipl = regs.ipl_pin;
1.1.1.7   root     7186:                } ENDTRY
1.1.1.4   root     7187:        }
                   7188: }
                   7189: 
1.1.1.7   root     7190: #ifdef CPUEMU_20
                   7191: 
                   7192: // full prefetch 020 (more compatible)
1.1.1.4   root     7193: static void m68k_run_2p (void)
                   7194: {
                   7195:        struct regstruct *r = &regs;
1.1.1.7   root     7196:        bool exit = false;
1.1.1.8   root     7197:        bool first = true;
                   7198: 
                   7199:        Log_Printf(LOG_DEBUG, "m68k_run_2p\n");
1.1.1.4   root     7200: 
1.1.1.7   root     7201:        while (!exit) {
                   7202:                TRY(prb) {
1.1.1.8   root     7203: 
                   7204:                        if (first) {
                   7205:                                if (cpu_tracer < 0) {
                   7206:                                        memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
                   7207:                                        r->ir = cputrace.ir;
                   7208:                                        r->irc = cputrace.irc;
                   7209:                                        r->sr = cputrace.sr;
                   7210:                                        r->usp = cputrace.usp;
                   7211:                                        r->isp = cputrace.isp;
                   7212:                                        r->intmask = cputrace.intmask;
                   7213:                                        r->stopped = cputrace.stopped;
                   7214: 
                   7215:                                        r->msp = cputrace.msp;
                   7216:                                        r->vbr = cputrace.vbr;
                   7217:                                        r->caar = cputrace.caar;
                   7218:                                        r->cacr = cputrace.cacr;
                   7219:                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
                   7220:                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
                   7221:                                        r->prefetch020addr = cputrace.prefetch020addr;
1.1.1.9   root     7222:                                        memcpy(&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof(uae_u16));
                   7223:                                        memcpy(&r->prefetch020_valid, &cputrace.prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
                   7224:                                        memcpy(&caches020, &cputrace.caches020, sizeof caches020);
1.1.1.8   root     7225: 
                   7226:                                        m68k_setpc (cputrace.pc);
                   7227:                                        if (!r->stopped) {
                   7228:                                                if (cputrace.state > 1)
                   7229:                                                        Exception (cputrace.state);
                   7230:                                                else if (cputrace.state == 1)
                   7231:                                                        (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
                   7232:                                        }
                   7233:                                        if (regs.stopped)
                   7234:                                                set_special (SPCFLAG_STOP);
                   7235:                                        set_cpu_tracer (false);
                   7236:                                        goto cont;
                   7237:                                }
                   7238:                                set_cpu_tracer (false);
                   7239:                                first = false;
                   7240:                        }
                   7241: 
1.1.1.7   root     7242:                        while (!exit) {
                   7243: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     7244:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     7245:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   7246:                                {
                   7247:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   7248:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   7249:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     7250:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     7251:                                }
                   7252: #endif
                   7253:                                r->instruction_pc = m68k_getpc ();
1.1.1.8   root     7254:                                r->opcode = regs.irc;
1.1.1.4   root     7255: 
1.1.1.7   root     7256: #ifndef WINUAE_FOR_HATARI
1.1.1.4   root     7257: #if DEBUG_CD32CDTVIO
1.1.1.7   root     7258:                                out_cd32io (m68k_getpc ());
                   7259: #endif
1.1.1.4   root     7260: #endif
                   7261: 
1.1.1.8   root     7262:                                if (cpu_tracer) {
1.1.1.4   root     7263: 
1.1.1.8   root     7264: #if CPUTRACE_DEBUG
                   7265:                                        validate_trace ();
                   7266: #endif
                   7267:                                        memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
                   7268:                                        cputrace.opcode = r->opcode;
                   7269:                                        cputrace.ir = r->ir;
                   7270:                                        cputrace.irc = r->irc;
                   7271:                                        cputrace.sr = r->sr;
                   7272:                                        cputrace.usp = r->usp;
                   7273:                                        cputrace.isp = r->isp;
                   7274:                                        cputrace.intmask = r->intmask;
                   7275:                                        cputrace.stopped = r->stopped;
                   7276:                                        cputrace.state = 1;
                   7277:                                        cputrace.pc = m68k_getpc ();
                   7278: 
                   7279:                                        cputrace.msp = r->msp;
                   7280:                                        cputrace.vbr = r->vbr;
                   7281:                                        cputrace.caar = r->caar;
                   7282:                                        cputrace.cacr = r->cacr;
                   7283:                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
                   7284:                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
                   7285:                                        cputrace.prefetch020addr = r->prefetch020addr;
1.1.1.9   root     7286:                                        memcpy(&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof(uae_u16));
                   7287:                                        memcpy(&cputrace.prefetch020_valid, &r->prefetch020_valid, CPU_PIPELINE_MAX * sizeof(uae_u8));
                   7288:                                        memcpy(&cputrace.caches020, &caches020, sizeof caches020);
1.1.1.8   root     7289: 
                   7290:                                        cputrace.memoryoffset = 0;
                   7291:                                        cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
                   7292:                                        cputrace.readcounter = cputrace.writecounter = 0;
                   7293:                                }
                   7294: 
                   7295: #ifndef WINUAE_FOR_HATARI
                   7296:                                if (inputrecord_debug & 4) {
                   7297:                                        if (input_record > 0)
                   7298:                                                inprec_recorddebug_cpu (1);
                   7299:                                        else if (input_play > 0)
                   7300:                                                inprec_playdebug_cpu (1);
                   7301:                                }
                   7302: #endif
1.1.1.10! root     7303:                                if (cpu_cycles > 0)
        !          7304:                                        x_do_cycles(cpu_cycles);
        !          7305: 
1.1.1.9   root     7306:                                if (currprefs.cpu_memory_cycle_exact) {
1.1.1.8   root     7307: 
1.1.1.9   root     7308:                                        (*cpufunctbl[r->opcode])(r->opcode);
1.1.1.10! root     7309:                                        // 0% = no extra cycles
        !          7310:                                        cpu_cycles = 4 * CYCLE_UNIT * cycles_mult;
        !          7311:                                        cpu_cycles /= CYCLES_DIV;
        !          7312:                                        cpu_cycles -= CYCLE_UNIT;
        !          7313:                                        if (cpu_cycles <= 0)
        !          7314:                                                cpu_cycles = cpucycleunit;
1.1.1.4   root     7315: 
1.1.1.9   root     7316:                                } else {
                   7317: 
                   7318:                                        cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   7319:                                        cpu_cycles = adjust_cycles (cpu_cycles);
                   7320: 
                   7321:                                }
1.1.1.8   root     7322: cont:
1.1.1.7   root     7323: #ifdef WINUAE_FOR_HATARI
1.1.1.8   root     7324: //fprintf ( stderr , "waits %d %d %ld\n" , cpu_cycles*2/CYCLE_UNIT , WaitStateCycles , CyclesGlobalClockCounter );
1.1.1.7   root     7325:                                M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4   root     7326: 
1.1.1.8   root     7327: //fprintf ( stderr , "waits %d %d %ld\n" , cpu_cycles*2/CYCLE_UNIT , WaitStateCycles , CyclesGlobalClockCounter );
1.1.1.10! root     7328:                                if ( WaitStateCycles ) {
1.1.1.7   root     7329:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     7330:                                        M68000_AddCycles(WaitStateCycles);
                   7331:                                        WaitStateCycles = 0;
1.1.1.7   root     7332:                                }
1.1.1.8   root     7333: //fprintf ( stderr , "waits %d %d %ld\n" , cpu_cycles*2/CYCLE_UNIT , WaitStateCycles , CyclesGlobalClockCounter );
1.1.1.4   root     7334: 
1.1.1.7   root     7335:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   7336:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   7337:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   7338:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   7339:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   7340:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   7341:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   7342:                                if ( MFP_UpdateNeeded == true )
                   7343:                                        MFP_UpdateIRQ ( 0 );
                   7344: #endif
1.1.1.4   root     7345: 
1.1.1.7   root     7346:                                if (r->spcflags) {
                   7347:                                        if (do_specialties (cpu_cycles))
                   7348:                                                exit = true;
                   7349:                                }
1.1.1.10! root     7350:                                ipl_fetch ();
1.1.1.7   root     7351: 
                   7352: #ifdef WINUAE_FOR_HATARI
                   7353:                                /* Run DSP 56k code if necessary */
                   7354:                                if (bDspEnabled) {
1.1.1.8   root     7355: //if ( DSP_CPU_FREQ_RATIO * ( (CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter) << nCpuFreqShift )  - 2 * cpu_cycles * 2 / CYCLE_UNIT >= 8 )
                   7356: //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     7357:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     7358: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     7359:                                }
                   7360: 
1.1.1.10! root     7361:                                if ( savestate_state == STATE_SAVE )
        !          7362:                                        save_state ( NULL , NULL );
        !          7363: #endif
1.1.1.7   root     7364:                        }
                   7365:                } CATCH(prb) {
                   7366:                        bus_error();
                   7367:                        if (r->spcflags) {
                   7368:                                if (do_specialties(cpu_cycles))
1.1.1.8   root     7369:                                        exit = true;
1.1.1.7   root     7370:                        }
                   7371:                        ipl_fetch();
                   7372:                } ENDTRY
1.1.1.4   root     7373:        }
                   7374: }
                   7375: 
1.1.1.7   root     7376: #endif
1.1.1.4   root     7377: 
1.1.1.8   root     7378: #ifdef WITH_THREADED_CPU
                   7379: static void *cpu_thread_run_2(void *v)
                   7380: {
                   7381:        bool exit = false;
                   7382:        struct regstruct *r = &regs;
                   7383: 
1.1.1.10! root     7384:        cpu_thread_tid = uae_thread_get_id();
        !          7385: 
1.1.1.8   root     7386:        cpu_thread_active = 1;
                   7387:        while (!exit) {
                   7388:                TRY(prb)
                   7389:                {
                   7390:                        while (!exit) {
                   7391:                                r->instruction_pc = m68k_getpc();
                   7392: 
                   7393:                                r->opcode = x_get_iword(0);
                   7394: 
                   7395:                                (*cpufunctbl[r->opcode])(r->opcode);
                   7396: 
1.1.1.10! root     7397:                                if (regs.spcflags || cpu_thread_ilvl > 0) {
1.1.1.8   root     7398:                                        if (do_specialties_thread())
                   7399:                                                exit = true;
                   7400:                                }
1.1.1.10! root     7401: 
1.1.1.8   root     7402:                        }
                   7403:                } CATCH(prb)
                   7404:                {
                   7405:                        bus_error();
                   7406:                        if (r->spcflags) {
                   7407:                                if (do_specialties_thread())
                   7408:                                        exit = true;
                   7409:                        }
                   7410:                } ENDTRY
                   7411:        }
                   7412:        cpu_thread_active = 0;
                   7413:        return 0;
                   7414: }
                   7415: #endif
1.1.1.4   root     7416: 
                   7417: /* Same thing, but don't use prefetch to get opcode.  */
                   7418: static void m68k_run_2 (void)
                   7419: {
1.1.1.8   root     7420: #ifdef WITH_THREADED_CPU
                   7421:        if (currprefs.cpu_thread) {
                   7422:                run_cpu_thread(cpu_thread_run_2);
                   7423:                return;
                   7424:        }
                   7425: #endif
                   7426: 
1.1.1.4   root     7427:        struct regstruct *r = &regs;
1.1.1.7   root     7428:        bool exit = false;
1.1.1.8   root     7429: 
                   7430:        Log_Printf(LOG_DEBUG, "m68k_run_2\n");
1.1.1.4   root     7431: 
1.1.1.7   root     7432:        while (!exit) {
                   7433:                TRY(prb) {
                   7434:                        while (!exit) {
                   7435: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     7436:                                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.7   root     7437:                                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   7438:                                {
                   7439:                                        int FrameCycles, HblCounterVideo, LineCycles;
                   7440:                                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   7441:                                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     7442:                                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.7   root     7443:                                }
                   7444: #endif
                   7445:                                r->instruction_pc = m68k_getpc ();
1.1.1.4   root     7446: 
1.1.1.7   root     7447:                                r->opcode = x_get_iword(0);
                   7448:                                count_instr (r->opcode);
1.1.1.4   root     7449: 
1.1.1.7   root     7450:                                do_cycles (cpu_cycles);
1.1.1.5   root     7451: 
1.1.1.7   root     7452:                                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                   7453:                                cpu_cycles = adjust_cycles (cpu_cycles);
                   7454: #ifdef WINUAE_FOR_HATARI
                   7455: //fprintf ( stderr , "cyc_2 %d\n" , cpu_cycles );
                   7456:                                M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT);
                   7457: 
1.1.1.8   root     7458:                                if ( WaitStateCycles ) {
1.1.1.7   root     7459:                                        /* Add some extra cycles to simulate a wait state */
1.1.1.8   root     7460:                                        M68000_AddCycles(WaitStateCycles);
                   7461:                                        WaitStateCycles = 0;
1.1.1.7   root     7462:                                }
1.1.1.4   root     7463: 
1.1.1.7   root     7464:                                /* We can have several interrupts at the same time before the next CPU instruction */
                   7465:                                /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   7466:                                /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   7467:                                /* and prevent exiting the STOP state when calling do_specialties() after. */
                   7468:                                /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   7469:                                while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
                   7470:                                        CALL_VAR(PendingInterruptFunction);             /* call the interrupt handler */
                   7471:                                if ( MFP_UpdateNeeded == true )
                   7472:                                        MFP_UpdateIRQ ( 0 );
                   7473: #endif
1.1.1.4   root     7474: 
1.1.1.7   root     7475:                                if (r->spcflags) {
                   7476:                                        if (do_specialties (cpu_cycles))
                   7477:                                                exit = true;
                   7478:                                }
                   7479: 
                   7480: #ifdef WINUAE_FOR_HATARI
                   7481:                                /* Run DSP 56k code if necessary */
                   7482:                                if (bDspEnabled) {
                   7483:                                        DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.8   root     7484: //                                     DSP_Run ( DSP_CPU_FREQ_RATIO * ( CyclesGlobalClockCounter - DSP_CyclesGlobalClockCounter ) );
1.1.1.7   root     7485:                                }
1.1.1.10! root     7486: 
        !          7487:                                if ( savestate_state == STATE_SAVE )
        !          7488:                                        save_state ( NULL , NULL );
1.1.1.7   root     7489: #endif
                   7490:                        }
                   7491:                } CATCH(prb) {
                   7492:                        bus_error();
                   7493:                        if (r->spcflags) {
                   7494:                                if (do_specialties(cpu_cycles))
                   7495:                                        exit = true;
                   7496:                        }
                   7497:                } ENDTRY
1.1.1.4   root     7498:        }
                   7499: }
                   7500: 
                   7501: /* fake MMU 68k  */
1.1.1.8   root     7502: #if 0
1.1.1.4   root     7503: static void m68k_run_mmu (void)
                   7504: {
                   7505:        for (;;) {
1.1.1.7   root     7506: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     7507:                //m68k_dumpstate_file(stderr, NULL, 0xffffffff);
1.1.1.4   root     7508:                if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
                   7509:                {
                   7510:                        int FrameCycles, HblCounterVideo, LineCycles;
                   7511:                        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                   7512:                        LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.10! root     7513:                        m68k_disasm_file(stderr, m68k_getpc (), NULL, m68k_getpc (), 1);
1.1.1.4   root     7514:                }
1.1.1.7   root     7515: #endif
                   7516:                regs.opcode = get_iiword (0);
1.1.1.4   root     7517:                do_cycles (cpu_cycles);
                   7518:                mmu_backup_regs = regs;
1.1.1.7   root     7519:                cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
                   7520:                cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4   root     7521:                if (mmu_triggered)
                   7522:                        mmu_do_hit ();
                   7523:                if (regs.spcflags) {
                   7524:                        if (do_specialties (cpu_cycles))
                   7525:                                return;
                   7526:                }
                   7527:        }
                   7528: }
1.1.1.8   root     7529: #endif
1.1.1.4   root     7530: 
                   7531: #endif /* CPUEMU_0 */
                   7532: 
                   7533: int in_m68k_go = 0;
                   7534: 
1.1.1.8   root     7535: #if 0
1.1.1.4   root     7536: static void exception2_handle (uaecptr addr, uaecptr fault)
                   7537: {
                   7538:        last_addr_for_exception_3 = addr;
                   7539:        last_fault_for_exception_3 = fault;
                   7540:        last_writeaccess_for_exception_3 = 0;
                   7541:        last_instructionaccess_for_exception_3 = 0;
1.1.1.7   root     7542:        Exception (2);
                   7543: }
1.1.1.8   root     7544: #endif
1.1.1.7   root     7545: 
                   7546: static bool cpu_hardreset, cpu_keyboardreset;
                   7547: 
                   7548: bool is_hardreset(void)
                   7549: {
                   7550:        return cpu_hardreset;
                   7551: }
                   7552: bool is_keyboardreset(void)
                   7553: {
                   7554:        return  cpu_keyboardreset;
1.1.1.4   root     7555: }
                   7556: 
                   7557: void m68k_go (int may_quit)
                   7558: {
1.1.1.7   root     7559:        int hardboot = 1;
                   7560:        int startup = 1;
                   7561: 
1.1.1.8   root     7562: #ifdef WITH_THREADED_CPU
                   7563:        init_cpu_thread();
                   7564: #endif
1.1.1.4   root     7565:        if (in_m68k_go || !may_quit) {
1.1.1.7   root     7566:                write_log (_T("Bug! m68k_go is not reentrant.\n"));
1.1.1.4   root     7567:                abort ();
                   7568:        }
                   7569: 
                   7570:        reset_frame_rate_hack ();
                   7571:        update_68k_cycles ();
1.1.1.7   root     7572: #ifndef WINUAE_FOR_HATARI
                   7573:        start_cycles = 0;
                   7574: #endif
                   7575: 
                   7576:        set_cpu_tracer (false);
1.1.1.4   root     7577: 
1.1.1.7   root     7578:        cpu_prefs_changed_flag = 0;
1.1.1.4   root     7579:        in_m68k_go++;
                   7580:        for (;;) {
                   7581:                void (*run_func)(void);
                   7582: 
1.1.1.7   root     7583: #ifdef WINUAE_FOR_HATARI
1.1.1.4   root     7584:                /* Exit hatari ? */
                   7585:                if (bQuitProgram == true)
                   7586:                        break;
1.1.1.7   root     7587: #endif
                   7588: 
                   7589:                cputrace.state = -1;
                   7590: 
                   7591: #ifndef WINUAE_FOR_HATARI
1.1.1.8   root     7592:                if (regs.halted == CPU_HALT_ACCELERATOR_CPU_FALLBACK) {
                   7593:                        regs.halted = 0;
                   7594:                        cpu_do_fallback();
                   7595:                }
                   7596: 
1.1.1.7   root     7597:                if (currprefs.inprecfile[0] && input_play) {
                   7598:                        inprec_open (currprefs.inprecfile, NULL);
                   7599:                        changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0;
                   7600:                        quit_program = UAE_RESET;
                   7601:                }
                   7602:                if (input_play || input_record)
                   7603:                        inprec_startup ();
1.1.1.10! root     7604: #endif
1.1.1.7   root     7605: 
                   7606:                if (quit_program > 0) {
                   7607:                        int restored = 0;
                   7608:                        cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD;
                   7609:                        cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0;
                   7610: 
                   7611:                        if (quit_program == UAE_QUIT)
                   7612:                                break;
                   7613: 
                   7614:                        hsync_counter = 0;
                   7615:                        vsync_counter = 0;
                   7616:                        quit_program = 0;
                   7617:                        hardboot = 0;
                   7618: 
                   7619: #ifdef SAVESTATE
                   7620:                        if (savestate_state == STATE_DORESTORE)
                   7621:                                savestate_state = STATE_RESTORE;
                   7622:                        if (savestate_state == STATE_RESTORE)
                   7623:                                restore_state (savestate_fname);
1.1.1.10! root     7624: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     7625:                        else if (savestate_state == STATE_REWIND)
                   7626:                                savestate_rewind ();
                   7627: #endif
1.1.1.10! root     7628: #endif
1.1.1.8   root     7629:                        if (cpu_hardreset)
                   7630:                                m68k_reset_restore();
                   7631:                        prefs_changed_cpu();
1.1.1.9   root     7632:                        build_cpufunctbl();
                   7633:                        set_x_funcs();
1.1.1.10! root     7634: #ifndef WINUAE_FOR_HATARI
1.1.1.9   root     7635:                        set_cycles (start_cycles);
1.1.1.10! root     7636: #endif
1.1.1.7   root     7637:                        custom_reset (cpu_hardreset != 0, cpu_keyboardreset);
                   7638:                        m68k_reset2 (cpu_hardreset != 0);
                   7639:                        if (cpu_hardreset) {
                   7640:                                memory_clear ();
                   7641:                                write_log (_T("hardreset, memory cleared\n"));
                   7642:                        }
                   7643:                        cpu_hardreset = false;
                   7644: #ifdef SAVESTATE
                   7645:                        /* We may have been restoring state, but we're done now.  */
                   7646:                        if (isrestore ()) {
1.1.1.10! root     7647: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     7648:                                if (debug_dma) {
                   7649:                                        record_dma_reset ();
                   7650:                                        record_dma_reset ();
                   7651:                                }
1.1.1.10! root     7652: #endif
1.1.1.7   root     7653:                                savestate_restore_finish ();
1.1.1.10! root     7654: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     7655:                                memory_map_dump ();
1.1.1.10! root     7656: #endif
1.1.1.7   root     7657:                                if (currprefs.mmu_model == 68030) {
1.1.1.9   root     7658:                                        mmu030_decode_tc (tc_030, true);
1.1.1.7   root     7659:                                } else if (currprefs.mmu_model >= 68040) {
                   7660:                                        mmu_set_tc (regs.tcr);
                   7661:                                }
                   7662:                                startup = 1;
                   7663:                                restored = 1;
                   7664:                        }
                   7665: #endif
1.1.1.10! root     7666: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     7667:                        if (currprefs.produce_sound == 0)
                   7668:                                eventtab[ev_audio].active = 0;
                   7669:                        m68k_setpc_normal (regs.pc);
                   7670:                        check_prefs_changed_audio ();
                   7671: 
                   7672:                        if (!restored || hsync_counter == 0)
                   7673:                                savestate_check ();
                   7674:                        if (input_record == INPREC_RECORD_START)
                   7675:                                input_record = INPREC_RECORD_NORMAL;
                   7676:                        statusline_clear();
1.1.1.10! root     7677: #else
        !          7678:                        m68k_setpc_normal (regs.pc);
        !          7679: #endif
1.1.1.7   root     7680:                } else {
1.1.1.10! root     7681: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     7682:                        if (input_record == INPREC_RECORD_START) {
                   7683:                                input_record = INPREC_RECORD_NORMAL;
                   7684:                                savestate_init ();
                   7685:                                hsync_counter = 0;
                   7686:                                vsync_counter = 0;
                   7687:                                savestate_check ();
                   7688:                        }
1.1.1.10! root     7689: #endif
1.1.1.7   root     7690:                }
                   7691: 
1.1.1.10! root     7692: #ifndef WINUAE_FOR_HATARI
1.1.1.7   root     7693:                if (changed_prefs.inprecfile[0] && input_record)
                   7694:                        inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
                   7695: #endif
                   7696: 
                   7697:                set_cpu_tracer (false);
1.1.1.4   root     7698: 
                   7699: #ifdef DEBUGGER
                   7700:                if (debugging)
                   7701:                        debug ();
                   7702: #endif
1.1.1.7   root     7703:                if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
                   7704:                        if (cpu_prefs_changed_flag & 1) {
                   7705:                                uaecptr pc = m68k_getpc();
                   7706:                                prefs_changed_cpu();
1.1.1.9   root     7707:                                fpu_modechange();
1.1.1.10! root     7708: #ifndef WINUAE_FOR_HATARI
        !          7709:                                custom_cpuchange();
        !          7710: #endif
1.1.1.7   root     7711:                                build_cpufunctbl();
                   7712:                                m68k_setpc_normal(pc);
                   7713:                                fill_prefetch();
                   7714:                        }
                   7715:                        if (cpu_prefs_changed_flag & 2) {
                   7716:                                fixup_cpu(&changed_prefs);
                   7717:                                currprefs.m68k_speed = changed_prefs.m68k_speed;
                   7718:                                currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
                   7719:                                update_68k_cycles();
1.1.1.10! root     7720: #ifndef WINUAE_FOR_HATARI
        !          7721:                                target_cpu_speed();
        !          7722: #endif
1.1.1.7   root     7723:                        }
                   7724:                        cpu_prefs_changed_flag = 0;
                   7725:                }
1.1.1.4   root     7726: 
1.1.1.7   root     7727:                set_x_funcs();
                   7728: #ifndef WINUAE_FOR_HATARI
                   7729:                if (startup) {
                   7730:                        custom_prepare ();
                   7731:                        protect_roms (true);
1.1.1.4   root     7732:                }
1.1.1.7   root     7733:                startup = 0;
                   7734:                event_wait = true;
1.1.1.4   root     7735: #endif
1.1.1.7   root     7736:                unset_special(SPCFLAG_MODE_CHANGE);
1.1.1.4   root     7737: 
1.1.1.9   root     7738:                if (!regs.halted) {
                   7739:                        // check that PC points to something that looks like memory.
                   7740:                        uaecptr pc = m68k_getpc();
                   7741: #ifndef WINUAE_FOR_HATARI
                   7742:                        addrbank *ab = get_mem_bank_real(pc);
                   7743: #else
                   7744:                        addrbank *ab = &get_mem_bank(pc);
                   7745: #endif
                   7746:                        if (ab == NULL || ab == &dummy_bank || (!currprefs.cpu_compatible && !valid_address(pc, 2)) || (pc & 1)) {
                   7747:                                cpu_halt(CPU_HALT_INVALID_START_ADDRESS);
                   7748:                        }
                   7749:                }
1.1.1.7   root     7750:                if (regs.halted) {
                   7751:                        cpu_halt (regs.halted);
                   7752:                        if (regs.halted < 0) {
                   7753:                                haltloop();
                   7754:                                continue;
                   7755:                        }
                   7756:                }
                   7757: 
1.1.1.10! root     7758: #ifdef WINUAE_FOR_HATARI
        !          7759:                /* Apply patches for gemdos HD if needed (we need to do it after */
        !          7760:                /* cpu tables for all opcodes were rebuilt in build_cpufunctbl() ) */
        !          7761:                Cart_PatchCpuTables();
        !          7762: 
        !          7763:                /* Restore debugger state (breakpoints) after a reset */
        !          7764:                M68000_RestoreDebugger();
        !          7765: #endif
        !          7766: 
1.1.1.7   root     7767: #if 0
1.1.1.4   root     7768:                if (mmu_enabled && !currprefs.cachesize) {
                   7769:                        run_func = m68k_run_mmu;
                   7770:                } else {
1.1.1.7   root     7771: #endif
                   7772:                        run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010 ? m68k_run_1_ce :
                   7773:                                currprefs.cpu_compatible && currprefs.cpu_model <= 68010 ? m68k_run_1 :
1.1.1.4   root     7774: #ifdef JIT
                   7775:                                currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
                   7776: #endif
1.1.1.7   root     7777:                                currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
                   7778:                                currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
                   7779:                                currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
                   7780: 
                   7781:                                currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
1.1.1.4   root     7782:                                currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
1.1.1.7   root     7783: 
                   7784:                                currprefs.cpu_model <= 68020 && currprefs.cpu_compatible ? m68k_run_2p :
                   7785:                                currprefs.cpu_model == 68030 && currprefs.cpu_compatible ? m68k_run_2p :
                   7786:                                currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
                   7787: 
                   7788:                                m68k_run_2;
                   7789: #if 0
1.1.1.4   root     7790:                }
1.1.1.7   root     7791: #endif
                   7792:                run_func();
1.1.1.8   root     7793:                Log_Printf(LOG_DEBUG, "exit m68k_run\n");
1.1.1.4   root     7794:        }
1.1.1.7   root     7795: #ifndef WINUAE_FOR_HATARI
                   7796:        protect_roms (false);
                   7797: #endif
1.1.1.4   root     7798:        in_m68k_go--;
                   7799: }
                   7800: 
                   7801: #if 0
                   7802: static void m68k_verify (uaecptr addr, uaecptr *nextpc)
                   7803: {
1.1.1.7   root     7804:        uae_u16 opcode, val;
1.1.1.4   root     7805:        struct instr *dp;
                   7806: 
                   7807:        opcode = get_iword_1 (0);
                   7808:        last_op_for_exception_3 = opcode;
                   7809:        m68kpc_offset = 2;
                   7810: 
                   7811:        if (cpufunctbl[opcode] == op_illg_1) {
                   7812:                opcode = 0x4AFC;
                   7813:        }
                   7814:        dp = table68k + opcode;
                   7815: 
                   7816:        if (dp->suse) {
                   7817:                if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
                   7818:                        Exception (3, 0);
                   7819:                        return;
                   7820:                }
                   7821:        }
                   7822:        if (dp->duse) {
                   7823:                if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
                   7824:                        Exception (3, 0);
                   7825:                        return;
                   7826:                }
                   7827:        }
                   7828: }
                   7829: #endif
                   7830: 
                   7831: static const TCHAR *ccnames[] =
1.1.1.7   root     7832: {
                   7833:        _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
                   7834:        _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
                   7835: };
                   7836: static const TCHAR *fpccnames[] =
                   7837: {
                   7838:        _T("F"),
                   7839:        _T("EQ"),
                   7840:        _T("OGT"),
                   7841:        _T("OGE"),
                   7842:        _T("OLT"),
                   7843:        _T("OLE"),
                   7844:        _T("OGL"),
                   7845:        _T("OR"),
                   7846:        _T("UN"),
                   7847:        _T("UEQ"),
                   7848:        _T("UGT"),
                   7849:        _T("UGE"),
                   7850:        _T("ULT"),
                   7851:        _T("ULE"),
                   7852:        _T("NE"),
                   7853:        _T("T"),
                   7854:        _T("SF"),
                   7855:        _T("SEQ"),
                   7856:        _T("GT"),
                   7857:        _T("GE"),
                   7858:        _T("LT"),
                   7859:        _T("LE"),
                   7860:        _T("GL"),
                   7861:        _T("GLE"),
                   7862:        _T("NGLE"),
                   7863:        _T("NGL"),
                   7864:        _T("NLE"),
                   7865:        _T("NLT"),
                   7866:        _T("NGE"),
                   7867:        _T("NGT"),
                   7868:        _T("SNE"),
                   7869:        _T("ST")
                   7870: };
                   7871: static const TCHAR *fpuopcodes[] =
                   7872: {
                   7873:        _T("FMOVE"),
                   7874:        _T("FINT"),
                   7875:        _T("FSINH"),
                   7876:        _T("FINTRZ"),
                   7877:        _T("FSQRT"),
                   7878:        NULL,
                   7879:        _T("FLOGNP1"),
                   7880:        NULL,
                   7881:        _T("FETOXM1"),
                   7882:        _T("FTANH"),
                   7883:        _T("FATAN"),
                   7884:        NULL,
                   7885:        _T("FASIN"),
                   7886:        _T("FATANH"),
                   7887:        _T("FSIN"),
                   7888:        _T("FTAN"),
                   7889:        _T("FETOX"),    // 0x10
                   7890:        _T("FTWOTOX"),
                   7891:        _T("FTENTOX"),
                   7892:        NULL,
                   7893:        _T("FLOGN"),
                   7894:        _T("FLOG10"),
                   7895:        _T("FLOG2"),
                   7896:        NULL,
                   7897:        _T("FABS"),
                   7898:        _T("FCOSH"),
                   7899:        _T("FNEG"),
                   7900:        NULL,
                   7901:        _T("FACOS"),
                   7902:        _T("FCOS"),
                   7903:        _T("FGETEXP"),
                   7904:        _T("FGETMAN"),
                   7905:        _T("FDIV"),             // 0x20
                   7906:        _T("FMOD"),
                   7907:        _T("FADD"),
                   7908:        _T("FMUL"),
                   7909:        _T("FSGLDIV"),
                   7910:        _T("FREM"),
                   7911:        _T("FSCALE"),
                   7912:        _T("FSGLMUL"),
                   7913:        _T("FSUB"),
                   7914:        NULL,
                   7915:        NULL,
                   7916:        NULL,
                   7917:        NULL,
                   7918:        NULL,
                   7919:        NULL,
                   7920:        NULL,
                   7921:        _T("FSINCOS"),  // 0x30
                   7922:        _T("FSINCOS"),
                   7923:        _T("FSINCOS"),
                   7924:        _T("FSINCOS"),
                   7925:        _T("FSINCOS"),
                   7926:        _T("FSINCOS"),
                   7927:        _T("FSINCOS"),
                   7928:        _T("FSINCOS"),
                   7929:        _T("FCMP"),
                   7930:        NULL,
                   7931:        _T("FTST"),
                   7932:        NULL,
                   7933:        NULL,
                   7934:        NULL,
                   7935:        NULL,
                   7936:        NULL
                   7937: };
                   7938: 
                   7939: static const TCHAR *movemregs[] =
                   7940: {
                   7941:        _T("D0"),
                   7942:        _T("D1"),
                   7943:        _T("D2"),
                   7944:        _T("D3"),
                   7945:        _T("D4"),
                   7946:        _T("D5"),
                   7947:        _T("D6"),
                   7948:        _T("D7"),
                   7949:        _T("A0"),
                   7950:        _T("A1"),
                   7951:        _T("A2"),
                   7952:        _T("A3"),
                   7953:        _T("A4"),
                   7954:        _T("A5"),
                   7955:        _T("A6"),
                   7956:        _T("A7"),
                   7957:        _T("FP0"),
                   7958:        _T("FP1"),
                   7959:        _T("FP2"),
                   7960:        _T("FP3"),
                   7961:        _T("FP4"),
                   7962:        _T("FP5"),
                   7963:        _T("FP6"),
                   7964:        _T("FP7"),
1.1.1.8   root     7965:        _T("FPIAR"),
1.1.1.7   root     7966:        _T("FPSR"),
1.1.1.8   root     7967:        _T("FPCR")
1.1.1.7   root     7968: };
1.1.1.4   root     7969: 
1.1.1.7   root     7970: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
1.1.1.4   root     7971: {
                   7972:        TCHAR *p = out + _tcslen (out);
                   7973:        if (*prevreg < 0) {
                   7974:                *prevreg = reg;
                   7975:                *lastreg = reg;
                   7976:                return;
                   7977:        }
1.1.1.7   root     7978:        if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
                   7979:                _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
1.1.1.4   root     7980:                p = p + _tcslen (p);
1.1.1.8   root     7981:                if (*lastreg != *prevreg) {
                   7982:                        if ((*lastreg) + 2 == reg) {
                   7983:                                _stprintf(p, _T("/%s"), movemregs[*prevreg]);
                   7984:                        } else if ((*lastreg) != (*prevreg)) {
                   7985:                                _stprintf(p, _T("-%s"), movemregs[*prevreg]);
                   7986:                        }
1.1.1.4   root     7987:                }
                   7988:                *lastreg = reg;
                   7989:                *first = 0;
                   7990:        }
                   7991:        *prevreg = reg;
                   7992: }
                   7993: 
1.1.1.10! root     7994: static bool movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode, bool dst)
1.1.1.4   root     7995: {
                   7996:        unsigned int dmask, amask;
                   7997:        int prevreg = -1, lastreg = -1, first = 1;
                   7998: 
1.1.1.7   root     7999:        if (mode == Apdi && !fpmode) {
                   8000:                uae_u8 dmask2;
                   8001:                uae_u8 amask2;
                   8002:                
                   8003:                amask2 = mask & 0xff;
                   8004:                dmask2 = (mask >> 8) & 0xff;
1.1.1.4   root     8005:                dmask = 0;
                   8006:                amask = 0;
1.1.1.10! root     8007:                for (int i = 0; i < 8; i++) {
1.1.1.4   root     8008:                        if (dmask2 & (1 << i))
                   8009:                                dmask |= 1 << (7 - i);
                   8010:                        if (amask2 & (1 << i))
                   8011:                                amask |= 1 << (7 - i);
                   8012:                }
                   8013:        } else {
                   8014:                dmask = mask & 0xff;
                   8015:                amask = (mask >> 8) & 0xff;
1.1.1.7   root     8016:                if (fpmode == 1 && mode != Apdi) {
                   8017:                        uae_u8 dmask2 = dmask;
                   8018:                        dmask = 0;
1.1.1.10! root     8019:                        for (int i = 0; i < 8; i++) {
1.1.1.7   root     8020:                                if (dmask2 & (1 << i))
                   8021:                                        dmask |= 1 << (7 - i);
                   8022:                        }
                   8023:                }
                   8024:        }
1.1.1.10! root     8025:        bool dataout = dmask != 0 || amask != 0;
        !          8026:        if (dst && dataout)
        !          8027:                _tcscat(out, _T(","));
1.1.1.7   root     8028:        if (fpmode) {
                   8029:                while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
                   8030:        } else {
                   8031:                while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
                   8032:                while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
1.1.1.4   root     8033:        }
1.1.1.7   root     8034:        addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
1.1.1.10! root     8035:        return dataout;
1.1.1.4   root     8036: }
                   8037: 
                   8038: static void disasm_size (TCHAR *instrname, struct instr *dp)
                   8039: {
1.1.1.7   root     8040:        if (dp->unsized) {
                   8041:                _tcscat(instrname, _T(" "));
                   8042:                return;
1.1.1.4   root     8043:        }
                   8044:        switch (dp->size)
                   8045:        {
                   8046:        case sz_byte:
1.1.1.7   root     8047:                _tcscat (instrname, _T(".B "));
1.1.1.4   root     8048:                break;
                   8049:        case sz_word:
1.1.1.7   root     8050:                _tcscat (instrname, _T(".W "));
1.1.1.4   root     8051:                break;
                   8052:        case sz_long:
1.1.1.7   root     8053:                _tcscat (instrname, _T(".L "));
1.1.1.4   root     8054:                break;
                   8055:        default:
1.1.1.7   root     8056:                _tcscat (instrname, _T(" "));
1.1.1.4   root     8057:                break;
                   8058:        }
                   8059: }
                   8060: 
1.1.1.9   root     8061: static void asm_add_extensions(uae_u16 *data, int *dcntp, int mode, uae_u32 v, uae_u16 *ext, uaecptr pc, int size)
                   8062: {
                   8063:        int dcnt = *dcntp;
                   8064:        if (mode < 0)
                   8065:                return;
                   8066:        if (mode == Ad16) {
                   8067:                data[dcnt++] = v;
                   8068:        }
                   8069:        if (mode == PC16) {
                   8070:                data[dcnt++] = v - (pc + 2);
                   8071:        }
                   8072:        if (mode == Ad8r || mode == PC8r) {
                   8073:                data[dcnt++] = ext[0];
                   8074:        }
                   8075:        if (mode == absw) {
                   8076:                data[dcnt++] = (uae_u16)v;
                   8077:        }
                   8078:        if (mode == absl) {
                   8079:                data[dcnt++] = (uae_u16)(v >> 16);
                   8080:                data[dcnt++] = (uae_u16)v;
                   8081:        }
                   8082:        if ((mode == imm && size == 0) || mode == imm0) {
                   8083:                data[dcnt++] = (uae_u8)v;
                   8084:        }
                   8085:        if ((mode == imm && size == 1) || mode == imm1) {
                   8086:                data[dcnt++] = (uae_u16)v;
                   8087:        }
                   8088:        if ((mode == imm && size == 2) || mode == imm2) {
                   8089:                data[dcnt++] = (uae_u16)(v >> 16);
                   8090:                data[dcnt++] = (uae_u16)v;
                   8091:        }
                   8092:        *dcntp = dcnt;
                   8093: }
                   8094: 
                   8095: static int asm_isdreg(const TCHAR *s)
                   8096: {
                   8097:        if (s[0] == 'D' && s[1] >= '0' && s[1] <= '7')
                   8098:                return s[1] - '0';
                   8099:        return -1;
                   8100: }
                   8101: static int asm_isareg(const TCHAR *s)
                   8102: {
                   8103:        if (s[0] == 'A' && s[1] >= '0' && s[1] <= '7')
                   8104:                return s[1] - '0';
1.1.1.10! root     8105:        if (s[0] == 'S' && s[1] == 'P')
        !          8106:                return 7;
1.1.1.9   root     8107:        return -1;
                   8108: }
                   8109: static int asm_ispc(const TCHAR *s)
                   8110: {
                   8111:        if (s[0] == 'P' && s[1] == 'C')
                   8112:                return 1;
                   8113:        return 0;
                   8114: }
                   8115: 
1.1.1.10! root     8116: static uae_u32 asmgetval(const TCHAR *s)
        !          8117: {
        !          8118:        TCHAR *endptr;
        !          8119:        if (s[0] == '-')
        !          8120:                return _tcstol(s, &endptr, 16);
        !          8121:        return _tcstoul(s, &endptr, 16);
        !          8122: }
        !          8123: 
1.1.1.9   root     8124: static int asm_parse_mode(TCHAR *s, uae_u8 *reg, uae_u32 *v, uae_u16 *ext)
                   8125: {
                   8126:        TCHAR *ss = s;
                   8127:        *reg = -1;
                   8128:        *v = 0;
                   8129:        *ext = 0;
                   8130:        if (s[0] == 0)
                   8131:                return -1;
                   8132:        // Dn
                   8133:        if (asm_isdreg(s) >= 0 && s[2] == 0) {
                   8134:                *reg = asm_isdreg(s);
                   8135:                return Dreg;
                   8136:        }
                   8137:        // An
                   8138:        if (asm_isareg(s) >= 0 && s[2] == 0) {
                   8139:                *reg = asm_isareg(s);
                   8140:                return Areg;
                   8141:        }
                   8142:        // (An) and (An)+
                   8143:        if (s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')') {
                   8144:                *reg = asm_isareg(s + 1);
                   8145:                if (s[4] == '+' && s[5] == 0)
                   8146:                        return Aipi;
                   8147:                if (s[4] == 0)
                   8148:                        return Aind;
                   8149:                return -1;
                   8150:        }
                   8151:        // -(An)
                   8152:        if (s[0] == '-' && s[1] == '(' && asm_isareg(s + 2) >= 0 && s[4] == ')' && s[5] == 0) {
                   8153:                *reg = asm_isareg(s + 2);
                   8154:                return Apdi;
                   8155:        }
                   8156:        // Immediate
                   8157:        if (s[0] == '#') {
                   8158:                if (s[1] == '!') {
                   8159:                        *v = _tstol(s + 2);
                   8160:                } else {
1.1.1.10! root     8161:                        *v = asmgetval(s + 1);
1.1.1.9   root     8162:                }
                   8163:                return imm;
                   8164:        }
                   8165:        // Value
                   8166:        if (s[0] == '!') {
                   8167:                *v = _tstol(s + 1);
                   8168:        } else {
1.1.1.10! root     8169:                *v = asmgetval(s);
1.1.1.9   root     8170:        }
                   8171:        int dots = 0;
                   8172:        unsigned int i;
                   8173:        for (i = 0; i < _tcslen(s); i++) {
                   8174:                if (s[i] == ',')
                   8175:                        dots++;
                   8176:        }
                   8177:        while (*s != 0) {
                   8178:                // d16(An)
                   8179:                if (dots == 0 && s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')' && s[4] == 0) {
                   8180:                        *reg = asm_isareg(s + 1);
                   8181:                        return Ad16;
                   8182:                }
                   8183:                // d16(PC)
                   8184:                if (dots == 0 && s[0] == '(' && asm_ispc(s + 1) && s[3] == ')' && s[4] == 0) {
                   8185:                        *reg = 2;
                   8186:                        return PC16;
                   8187:                }
                   8188:                // (d16,An) / (d16,PC)
                   8189:                if (dots == 1 && s[0] == '(' && !asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
                   8190:                        TCHAR *startptr, *endptr;
                   8191:                        if (s[1] == '!') {
                   8192:                                startptr = s + 2;
                   8193:                                *v = _tcstol(startptr, &endptr, 10);
                   8194:                        } else {
                   8195:                                startptr = s + 1;
                   8196:                                *v = _tcstol(startptr, &endptr, 16);
                   8197:                        }
                   8198:                        if (endptr == startptr || endptr[0] != ',')
                   8199:                                return -1;
                   8200:                        if (asm_ispc(endptr + 1) && endptr[3] == ')') {
                   8201:                                *reg = 2;
                   8202:                                return PC16;
                   8203:                        }
                   8204:                        if (asm_isareg(endptr + 1) >= 0 && endptr[3] == ')') {
                   8205:                                *reg = asm_isareg(endptr + 1);
                   8206:                                return Ad16;
                   8207:                        }
                   8208:                        return -1;
                   8209:                }
                   8210:                // Ad8r PC8r
                   8211:                if (s[0] == '(') {
                   8212:                        TCHAR *s2 = s;
                   8213:                        if (!asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
                   8214:                                if (dots != 2)
                   8215:                                        return -1;
                   8216:                                TCHAR *startptr, *endptr;
                   8217:                                if (s[1] == '!') {
                   8218:                                        startptr = s + 2;
                   8219:                                        *v = _tcstol(startptr, &endptr, 10);
                   8220:                                } else {
                   8221:                                        startptr = s + 1;
                   8222:                                        *v = _tcstol(startptr, &endptr, 16);
                   8223:                                }
                   8224:                                if (endptr == startptr || endptr[0] != ',')
                   8225:                                        return -1;
                   8226:                                s2 = endptr + 1;
                   8227:                        } else if (((asm_isareg(s + 1) >= 0 || asm_ispc(s + 1)) && s[3] == ',') || (asm_isdreg(s + 4) >= 0 || asm_isareg(s + 4) >= 0)) {
                   8228:                                if (dots != 1)
                   8229:                                        return -1;
                   8230:                                s2 = s + 1;
                   8231:                        } else {
                   8232:                                return -1;
                   8233:                        }
                   8234:                        uae_u8 reg2;
                   8235:                        bool ispc = asm_ispc(s2);
                   8236:                        if (ispc) {
                   8237:                                *reg = 3;
                   8238:                        } else {
                   8239:                                *reg = asm_isareg(s2);
                   8240:                        }
                   8241:                        s2 += 2;
                   8242:                        if (*s2 != ',')
                   8243:                                return -1;
                   8244:                        s2++;
                   8245:                        if (asm_isdreg(s2) >= 0) {
                   8246:                                reg2 = asm_isdreg(s2);
                   8247:                        } else {
                   8248:                                reg2 = asm_isareg(s2);
                   8249:                                *ext |= 1 << 15;
                   8250:                        }
                   8251:                        s2 += 2;
                   8252:                        *ext |= reg2 << 12;
                   8253:                        *ext |= (*v) & 0xff;
                   8254:                        if (s2[0] == '.' && s2[1] == 'W') {
                   8255:                                s2 += 2;
                   8256:                        } else if (s2[0] == '.' && s2[1] == 'L') {
                   8257:                                *ext |= 1 << 11;
                   8258:                                s2 += 2;
                   8259:                        }
                   8260:                        if (s2[0] == '*') {
                   8261:                                TCHAR scale = s2[1];
                   8262:                                if (scale == '2')
                   8263:                                        *ext |= 1 << 9;
                   8264:                                else if (scale == '4')
                   8265:                                        *ext |= 2 << 9;
                   8266:                                else if (scale == '8')
                   8267:                                        *ext |= 3 << 9;
                   8268:                                else
                   8269:                                        return -1;
                   8270:                                s2 += 2;
                   8271:                        }
                   8272:                        if (s2[0] == ')' && s2[1] == 0) {
                   8273:                                return ispc ? PC8r : Ad8r;
                   8274:                        }
                   8275:                        return -1;
                   8276:                }
                   8277:                s++;
                   8278:        }
                   8279:        // abs.w
                   8280:        if (s - ss > 2 && s[-2] == '.' && s[-1] == 'W') {
                   8281:                *reg = 0;
                   8282:                return absw;
                   8283:        }
                   8284:        // abs.l
                   8285:        *reg = 1;
                   8286:        return absl;
                   8287: }
                   8288: 
                   8289: static TCHAR *asm_parse_parm(TCHAR *parm, TCHAR *out)
                   8290: {
                   8291:        TCHAR *p = parm;
                   8292:        bool quote = false;
                   8293: 
                   8294:        for (;;) {
                   8295:                if (*p == '(') {
                   8296:                        quote = true;
                   8297:                }
                   8298:                if (*p == ')') {
                   8299:                        if (!quote)
                   8300:                                return NULL;
                   8301:                        quote = false;
                   8302:                }
                   8303:                if ((*p == ',' || *p == 0) && !quote) {
                   8304:                        TCHAR c = *p;
                   8305:                        p[0] = 0;
                   8306:                        _tcscpy(out, parm);
                   8307:                        my_trim(out);
                   8308:                        if (c)
                   8309:                                p++;
                   8310:                        return p;
                   8311:                }
                   8312:                p++;
                   8313:        }
                   8314: }
                   8315: 
                   8316: static bool m68k_asm_parse_movec(TCHAR *s, TCHAR *d)
                   8317: {
1.1.1.10! root     8318:        for (int i = 0; m2cregs[i].regname; i++) {
1.1.1.9   root     8319:                if (!_tcscmp(s, m2cregs[i].regname)) {
                   8320:                        uae_u16 v = m2cregs[i].regno;
                   8321:                        if (asm_isareg(d) >= 0)
                   8322:                                v |= 0x8000 | (asm_isareg(d) << 12);
                   8323:                        else if (asm_isdreg(d) >= 0)
                   8324:                                v |= (asm_isdreg(d) << 12);
                   8325:                        else
                   8326:                                return false;
                   8327:                        _stprintf(s, _T("#%X"), v);
                   8328:                        return true;
                   8329:                }
                   8330:        }
                   8331:        return false;
                   8332: }
                   8333: 
                   8334: static bool m68k_asm_parse_movem(TCHAR *s, int dir)
                   8335: {
                   8336:        TCHAR *d = s;
                   8337:        uae_u16 regmask = 0;
                   8338:        uae_u16 mask = dir ? 0x8000 : 0x0001;
                   8339:        bool ret = false;
                   8340:        while(*s) {
                   8341:                int dreg = asm_isdreg(s);
                   8342:                int areg = asm_isareg(s);
                   8343:                if (dreg < 0 && areg < 0)
                   8344:                        break;
                   8345:                int reg = dreg >= 0 ? dreg : areg + 8;
                   8346:                regmask |= dir ? (mask >> reg) : (mask << reg);
                   8347:                s += 2;
                   8348:                if (*s == 0) {
                   8349:                        ret = true;
                   8350:                        break;
                   8351:                } else if (*s == '/') {
                   8352:                        s++;
                   8353:                        continue;
                   8354:                } else if (*s == '-') {
                   8355:                        s++;
                   8356:                        int dreg2 = asm_isdreg(s);
                   8357:                        int areg2 = asm_isareg(s);
                   8358:                        if (dreg2 < 0 && areg2 < 0)
                   8359:                                break;
                   8360:                        int reg2 = dreg2 >= 0 ? dreg2 : areg2 + 8;
                   8361:                        if (reg2 < reg)
                   8362:                                break;
                   8363:                        while (reg2 >= reg) {
                   8364:                                regmask |= dir ? (mask >> reg) : (mask << reg);
                   8365:                                reg++;
                   8366:                        }
                   8367:                        s += 2;
                   8368:                        if (*s == 0) {
                   8369:                                ret = true;
                   8370:                                break;
                   8371:                        }
                   8372:                } else {
                   8373:                        break;
                   8374:                }
                   8375:        }
                   8376:        if (ret)
                   8377:                _stprintf(d, _T("#%X"), regmask);
                   8378:        return ret;
                   8379: }
                   8380: 
                   8381: int m68k_asm(TCHAR *sline, uae_u16 *out, uaecptr pc)
                   8382: {
                   8383:        TCHAR *p;
                   8384:        const TCHAR *cp1;
                   8385:        TCHAR ins[256], parms[256];
                   8386:        TCHAR line[256];
                   8387:        TCHAR srcea[256], dstea[256];
                   8388:        uae_u16 data[16], sexts[8], dexts[8];
                   8389:        int dcnt = 0;
                   8390:        int cc = -1;
                   8391:        int quick = 0;
                   8392:        bool immrelpc = false;
                   8393: 
                   8394:        if (_tcslen(sline) > 100)
                   8395:                return -1;
                   8396: 
                   8397:        srcea[0] = dstea[0] = 0;
                   8398:        parms[0] = 0;
                   8399: 
                   8400:        // strip all white space except first space
                   8401:        p = line;
                   8402:        bool firstsp = true;
1.1.1.10! root     8403:        for (int i = 0; sline[i]; i++) {
1.1.1.9   root     8404:                TCHAR c = sline[i];
                   8405:                if (c == 32 && firstsp) {
                   8406:                        firstsp = false;
                   8407:                        *p++ = 32;
                   8408:                }
                   8409:                if (c <= 32)
                   8410:                        continue;
                   8411:                *p++ = c;
                   8412:        }
                   8413:        *p = 0;
                   8414: 
                   8415:        to_upper(line, _tcslen(line));
                   8416: 
                   8417:        p = line;
                   8418:        while (*p && *p != ' ')
                   8419:                p++;
                   8420:        if (*p == ' ') {
                   8421:                *p = 0;
                   8422:                _tcscpy(parms, p + 1);
                   8423:                my_trim(parms);
                   8424:        }
                   8425:        _tcscpy(ins, line);
                   8426:        
                   8427:        if (_tcslen(ins) == 0)
                   8428:                return 0;
                   8429: 
                   8430:        int size = 1;
                   8431:        int inssize = -1;
                   8432:        cp1 = _tcschr(line, '.');
                   8433:        if (cp1) {
                   8434:                size = cp1[1];
                   8435:                if (size == 'W')
                   8436:                        size = 1;
                   8437:                else if (size == 'L')
                   8438:                        size = 2;
                   8439:                else if (size == 'B')
                   8440:                        size = 0;
                   8441:                else
                   8442:                        return 0;
                   8443:                inssize = size;
                   8444:                line[cp1 - line] = 0;
                   8445:                _tcscpy(ins, line);
                   8446:        }
                   8447: 
                   8448:        TCHAR *parmp = parms;
                   8449:        parmp = asm_parse_parm(parmp, srcea);
                   8450:        if (!parmp)
                   8451:                return 0;
                   8452:        if (srcea[0]) {
                   8453:                parmp = asm_parse_parm(parmp, dstea);
                   8454:                if (!parmp)
                   8455:                        return 0;
                   8456:        }
                   8457: 
                   8458:        int smode = -1;
                   8459:        int dmode = -1;
                   8460:        uae_u8 sreg = -1;
                   8461:        uae_u8 dreg = -1;
                   8462:        uae_u32 sval = 0;
                   8463:        uae_u32 dval = 0;
                   8464:        int ssize = -1;
                   8465:        int dsize = -1;
                   8466: 
                   8467:        dmode = asm_parse_mode(dstea, &dreg, &dval, dexts);
                   8468: 
                   8469: 
                   8470:        // Common alias
                   8471:        if (!_tcscmp(ins, _T("BRA"))) {
                   8472:                _tcscpy(ins, _T("BT"));
                   8473:        } else if (!_tcscmp(ins, _T("BSR"))) {
                   8474:                immrelpc = true;
                   8475:        } else if (!_tcscmp(ins, _T("MOVEM"))) {
                   8476:                if (dmode >= Aind && _tcschr(dstea, '-') == NULL && _tcschr(dstea, '/') == NULL) {
                   8477:                        _tcscpy(ins, _T("MVMLE"));
                   8478:                        if (!m68k_asm_parse_movem(srcea, dmode == Apdi))
                   8479:                                return -1;
                   8480:                } else {
                   8481:                        TCHAR tmp[256];
                   8482:                        _tcscpy(ins, _T("MVMEL"));
                   8483:                        _tcscpy(tmp, srcea);
                   8484:                        _tcscpy(srcea, dstea);
                   8485:                        _tcscpy(dstea, tmp);
                   8486:                        if (!m68k_asm_parse_movem(srcea, 0))
                   8487:                                return -1;
                   8488:                        dmode = asm_parse_mode(dstea, &dreg, &dval, dexts);
                   8489:                }
                   8490:        } else if (!_tcscmp(ins, _T("MOVEC"))) {
                   8491:                if (dmode == Dreg || dmode == Areg) {
                   8492:                        _tcscpy(ins, _T("MOVEC2"));
                   8493:                        if (!m68k_asm_parse_movec(srcea, dstea))
                   8494:                                return -1;
                   8495:                } else {
                   8496:                        TCHAR tmp[256];
                   8497:                        _tcscpy(ins, _T("MOVE2C"));
                   8498:                        _tcscpy(tmp, srcea);
                   8499:                        _tcscpy(srcea, dstea);
                   8500:                        dstea[0] = 0;
                   8501:                        if (!m68k_asm_parse_movec(srcea, tmp))
                   8502:                                return -1;
                   8503:                }
                   8504:                dmode = -1;
                   8505:        }
                   8506:        
                   8507:        if (dmode == Areg) {
                   8508:                int l = _tcslen(ins);
                   8509:                if (l <= 2)
                   8510:                        return -1;
                   8511:                TCHAR last = ins[l- 1];
                   8512:                if (last == 'Q') {
                   8513:                        last = ins[l - 2];
                   8514:                        if (last != 'A') {
                   8515:                                ins[l - 1] = 'A';
                   8516:                                ins[l] = 'Q';
                   8517:                                ins[l + 1] = 0;
                   8518:                        }
                   8519:                } else if (last != 'A') {
                   8520:                        _tcscat(ins, _T("A"));
                   8521:                }
                   8522:        }
                   8523: 
1.1.1.10! root     8524:        bool fp = ins[0] == 'F';
        !          8525: 
        !          8526:        if (ins[_tcslen(ins) - 1] == 'Q' && _tcslen(ins) > 3 && !fp) {
1.1.1.9   root     8527:                quick = 1;
                   8528:                ins[_tcslen(ins) - 1] = 0;
                   8529:        }
                   8530: 
                   8531:        struct mnemolookup *lookup;
                   8532:        for (lookup = lookuptab; lookup->name; lookup++) {
                   8533:                if (!_tcscmp(ins, lookup->name))
                   8534:                        break;
                   8535:        }
                   8536:        if (!lookup->name) {
                   8537:                // Check cc variants
                   8538:                for (lookup = lookuptab; lookup->name; lookup++) {
                   8539:                        const TCHAR *ccp = _tcsstr(lookup->name, _T("cc"));
                   8540:                        if (ccp) {
                   8541:                                TCHAR tmp[256];
1.1.1.10! root     8542:                                for (int i = 0; i < (fp ? 32 : 16); i++) {
1.1.1.9   root     8543:                                        const TCHAR *ccname = fp ? fpccnames[i] : ccnames[i];
                   8544:                                        _tcscpy(tmp, lookup->name);
                   8545:                                        _tcscpy(tmp + (ccp - lookup->name), ccname);
                   8546:                                        if (tmp[_tcslen(tmp) - 1] == ' ')
                   8547:                                                tmp[_tcslen(tmp) - 1] = 0;
                   8548:                                        if (!_tcscmp(tmp, ins)) {
                   8549:                                                _tcscpy(ins, lookup->name);
                   8550:                                                cc = i;
1.1.1.10! root     8551:                                                if (lookup->mnemo == i_DBcc || lookup->mnemo == i_Bcc) {
        !          8552:                                                        // Bcc.B uses same encoding mode as MOVEQ
        !          8553:                                                        immrelpc = true;
        !          8554:                                                }
1.1.1.9   root     8555:                                                if (size == 0) {
                   8556:                                                        quick = 2;
                   8557:                                                }
                   8558:                                                break;
                   8559:                                        }
                   8560:                                }
                   8561:                        }
                   8562:                        if (cc >= 0)
                   8563:                                break;
                   8564:                }
                   8565:        }
                   8566: 
                   8567:        if (!lookup->name)
                   8568:                return 0;
                   8569: 
                   8570:        int mnemo = lookup->mnemo;
                   8571: 
                   8572:        int found = 0;
                   8573:        int sizemask = 0;
                   8574:        int tsize = size;
                   8575:        int unsized = 0;
                   8576: 
1.1.1.10! root     8577:        for (int round = 0; round < 9; round++) {
1.1.1.9   root     8578: 
                   8579:                if (!found && round == 8)
                   8580:                        return 0;
                   8581: 
                   8582:                if (round == 3) {
                   8583:                        // Q is always LONG sized
                   8584:                        if (quick == 1) {
                   8585:                                tsize = 2;
                   8586:                        }
                   8587:                        bool isimm = srcea[0] == '#';
                   8588:                        if (immrelpc && !isimm) {
                   8589:                                TCHAR tmp[256];
                   8590:                                _tcscpy(tmp, srcea);
                   8591:                                srcea[0] = '#';
                   8592:                                _tcscpy(srcea + 1, tmp);
                   8593:                        }
                   8594:                        smode = asm_parse_mode(srcea, &sreg, &sval, sexts);
                   8595:                        if (immrelpc && !isimm) {
                   8596:                                sval = sval - (pc + 2);
                   8597:                        }
                   8598:                        if (quick) {
                   8599:                                smode = immi;
                   8600:                                sreg = sval & 0xff;
                   8601:                        }
                   8602:                }
                   8603: 
                   8604:                if (round == 1) {
                   8605:                        if (!quick && (sizemask == 1 || sizemask == 2 || sizemask == 4)) {
                   8606:                                tsize = 0;
                   8607:                                if (sizemask == 2)
                   8608:                                        tsize = 1;
                   8609:                                else if (sizemask == 4)
                   8610:                                        tsize = 2;
                   8611:                        } else {
                   8612:                                continue;
                   8613:                        }
                   8614:                }
                   8615:                if (round == 2 && !found) {
                   8616:                        unsized = 1;
                   8617:                }
                   8618: 
                   8619:                if (round == 4 && smode == imm) {
                   8620:                        smode = imm0;
                   8621:                } else if (round == 5 && smode == imm0) {
                   8622:                        smode = imm1;
                   8623:                } else if (round == 6 && smode == imm1) {
                   8624:                        smode = imm2;
                   8625:                } else if (round == 7 && smode == imm2) {
                   8626:                        smode = immi;
                   8627:                        sreg = sval & 0xff;
                   8628:                } else if (round == 4) {
                   8629:                        round += 5 - 1;
                   8630:                }
                   8631: 
1.1.1.10! root     8632:                for (int opcode = 0; opcode < 65536; opcode++) {
1.1.1.9   root     8633:                        struct instr *table = &table68k[opcode];
                   8634:                        if (table->mnemo != mnemo)
                   8635:                                continue;
                   8636:                        if (cc >= 0 && table->cc != cc)
                   8637:                                continue;
                   8638: 
                   8639: #if 0
                   8640:                        if (round == 0) {
                   8641:                                console_out_f(_T("%s OP=%04x S=%d SR=%d SM=%d SU=%d SP=%d DR=%d DM=%d DU=%d DP=%d SDU=%d\n"), lookup->name, opcode, table->size,
                   8642:                                        table->sreg, table->smode, table->suse, table->spos,
                   8643:                                        table->dreg, table->dmode, table->duse, table->dpos,
                   8644:                                        table->sduse);
                   8645:                        }
                   8646: #endif
                   8647: 
                   8648:                        if (table->duse && !(table->dmode == dmode || (dmode >= imm && dmode <= imm2 && table->dmode >= imm && table->dmode <= imm2)))
                   8649:                                continue;
                   8650:                        if (round == 0) {
                   8651:                                sizemask |= 1 << table->size;
                   8652:                        }
                   8653:                        if (unsized > 0 && !table->unsized) {
                   8654:                                continue;
                   8655:                        }
                   8656: 
                   8657:                        found++;
                   8658: 
                   8659:                        if (round >= 3) {
                   8660: 
                   8661:                                if (
                   8662:                                        ((table->size == tsize || table->unsized)) &&
                   8663:                                        ((!table->suse && smode < 0) || (table->suse && table->smode == smode)) &&
                   8664:                                        ((!table->duse && dmode < 0) || (table->duse && (table->dmode == dmode || (dmode == imm && (table->dmode >= imm && table->dmode <= imm2))))) &&
                   8665:                                        ((table->sreg == sreg || (table->smode >= absw && table->smode != immi))) &&
                   8666:                                        ((table->dreg == dreg || table->dmode >= absw))
                   8667:                                        )
                   8668:                                {
                   8669:                                        if (inssize >= 0 && tsize != inssize)
                   8670:                                                continue;
                   8671: 
                   8672: 
                   8673:                                        data[dcnt++] = opcode;
                   8674:                                        asm_add_extensions(data, &dcnt, smode, sval, sexts, pc, tsize);
                   8675:                                        if (smode >= 0)
                   8676:                                                asm_add_extensions(data, &dcnt, dmode, dval, dexts, pc, tsize);
1.1.1.10! root     8677:                                        for (int i = 0; i < dcnt; i++) {
1.1.1.9   root     8678:                                                out[i] = data[i];
                   8679:                                        }
                   8680:                                        return dcnt;
                   8681:                                }
                   8682: 
                   8683:                        }
                   8684:                }
                   8685:        }
                   8686: 
                   8687:        return 0;
                   8688: }
                   8689: 
1.1.1.10! root     8690: static void resolve_if_jmp(TCHAR *s, uae_u32 addr)
        !          8691: {
        !          8692:        uae_u16 opcode = get_word_debug(addr);
        !          8693:        if (opcode == 0x4ef9) { // JMP x.l
        !          8694:                TCHAR *p = s + _tcslen(s);
        !          8695:                uae_u32 addr2 = get_long_debug(addr + 2);
        !          8696:                _stprintf(p, _T(" == $%08x "), addr2);
        !          8697:                showea_val(p + _tcslen(p), opcode, addr2, 4);
        !          8698:                TCHAR txt[256];
        !          8699:                bool ext;
        !          8700:                if (debugmem_get_segment(addr2, NULL, &ext, NULL, txt)) {
        !          8701:                        if (ext) {
        !          8702:                                _tcscat(p, _T(" "));
        !          8703:                                _tcscat(p, txt);
        !          8704:                        }
        !          8705:                }
        !          8706:        }
        !          8707: }
        !          8708: 
        !          8709: 
        !          8710: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode)
1.1.1.4   root     8711: {
1.1.1.7   root     8712:        uae_u32 seaddr2;
                   8713:        uae_u32 deaddr2;
1.1.1.4   root     8714: 
                   8715:        if (!table68k)
                   8716:                return;
                   8717:        while (cnt-- > 0) {
1.1.1.10! root     8718:                TCHAR instrname[256], *ccpt;
        !          8719:                TCHAR segout[256], segname[256];
1.1.1.4   root     8720:                int i;
                   8721:                uae_u32 opcode;
1.1.1.7   root     8722:                uae_u16 extra;
1.1.1.4   root     8723:                struct mnemolookup *lookup;
                   8724:                struct instr *dp;
1.1.1.7   root     8725:                uaecptr oldpc;
                   8726:                uaecptr m68kpc_illg = 0;
                   8727:                bool illegal = false;
1.1.1.10! root     8728:                int segid, lastsegid;
        !          8729:                TCHAR *symbolpos;
1.1.1.7   root     8730: 
                   8731:                seaddr2 = deaddr2 = 0;
                   8732:                oldpc = pc;
                   8733:                opcode = get_word_debug (pc);
                   8734:                extra = get_word_debug (pc + 2);
                   8735:                if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
                   8736:                        m68kpc_illg = pc + 2;
                   8737:                        illegal = TRUE;
                   8738:                }
1.1.1.4   root     8739: 
1.1.1.7   root     8740:                dp = table68k + opcode;
                   8741:                if (dp->mnemo == i_ILLG) {
                   8742:                        illegal = FALSE;
1.1.1.4   root     8743:                        opcode = 0x4AFC;
1.1.1.7   root     8744:                        dp = table68k + opcode;
1.1.1.4   root     8745:                }
                   8746:                for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   8747:                        ;
                   8748: 
1.1.1.10! root     8749:                lastsegid = -1;
        !          8750:                bool exact = false;
        !          8751:                if (lastpc != 0xffffffff) {
        !          8752:                        lastsegid = debugmem_get_segment(lastpc, NULL, NULL, NULL, NULL);
        !          8753:                }
        !          8754:                segid = debugmem_get_segment(pc, &exact, NULL, segout, segname);
        !          8755:                if (segid && (lastsegid != -1 || exact) && (segid != lastsegid || pc == lastpc || exact)) {
        !          8756:                        buf = buf_out(buf, &bufsize, _T("%s\n"), segname);
        !          8757:                }
        !          8758:                symbolpos = buf;
        !          8759: 
1.1.1.7   root     8760:                buf = buf_out (buf, &bufsize, _T("%08X "), pc);
1.1.1.4   root     8761: 
1.1.1.10! root     8762:                if (segid) {
        !          8763:                        buf = buf_out(buf, &bufsize, _T("%s "), segout);
        !          8764:                }
        !          8765: 
1.1.1.7   root     8766:                pc += 2;
                   8767:                
                   8768:                if (lookup->friendlyname)
1.1.1.4   root     8769:                        _tcscpy (instrname, lookup->friendlyname);
                   8770:                else
                   8771:                        _tcscpy (instrname, lookup->name);
1.1.1.7   root     8772:                ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4   root     8773:                if (ccpt != 0) {
1.1.1.7   root     8774:                        if ((opcode & 0xf000) == 0xf000)
                   8775:                                _tcscpy (ccpt, fpccnames[extra & 0x1f]);
                   8776:                        else
                   8777:                                _tcsncpy (ccpt, ccnames[dp->cc], 2);
1.1.1.4   root     8778:                }
                   8779:                disasm_size (instrname, dp);
                   8780: 
                   8781:                if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
1.1.1.7   root     8782:                        uae_u16 imm = extra;
1.1.1.4   root     8783:                        uae_u16 creg = imm & 0x0fff;
                   8784:                        uae_u16 r = imm >> 12;
                   8785:                        TCHAR regs[16];
1.1.1.7   root     8786:                        const TCHAR *cname = _T("?");
1.1.1.10! root     8787:                        int j;
        !          8788:                        for (j = 0; m2cregs[j].regname; j++) {
        !          8789:                                if (m2cregs[j].regno == creg)
1.1.1.4   root     8790:                                        break;
                   8791:                        }
1.1.1.7   root     8792:                        _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
1.1.1.10! root     8793:                        if (m2cregs[j].regname)
        !          8794:                                cname = m2cregs[j].regname;
1.1.1.4   root     8795:                        if (lookup->mnemo == i_MOVE2C) {
                   8796:                                _tcscat (instrname, regs);
1.1.1.7   root     8797:                                _tcscat (instrname, _T(","));
1.1.1.4   root     8798:                                _tcscat (instrname, cname);
                   8799:                        } else {
                   8800:                                _tcscat (instrname, cname);
1.1.1.7   root     8801:                                _tcscat (instrname, _T(","));
1.1.1.4   root     8802:                                _tcscat (instrname, regs);
                   8803:                        }
1.1.1.7   root     8804:                        pc += 2;
1.1.1.4   root     8805:                } else if (lookup->mnemo == i_MVMEL) {
1.1.1.7   root     8806:                        uae_u16 mask = extra;
                   8807:                        pc += 2;
                   8808:                        pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
1.1.1.10! root     8809:                        movemout (instrname, mask, dp->dmode, 0, true);
1.1.1.4   root     8810:                } else if (lookup->mnemo == i_MVMLE) {
1.1.1.7   root     8811:                        uae_u16 mask = extra;
                   8812:                        pc += 2;
1.1.1.10! root     8813:                        if (movemout(instrname, mask, dp->dmode, 0, false))
        !          8814:                                _tcscat(instrname, _T(","));
1.1.1.7   root     8815:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8816:                } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
                   8817:                        TCHAR *p;
                   8818:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8819:                        extra = get_word_debug(pc);
                   8820:                        pc += 2;
                   8821:                        p = instrname + _tcslen(instrname);
                   8822:                        if (extra & 0x0400)
                   8823:                                _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
                   8824:                        else
                   8825:                                _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
                   8826:                } else if (lookup->mnemo == i_MOVES) {
                   8827:                        TCHAR *p;
                   8828:                        pc += 2;
1.1.1.9   root     8829:                        if (!(extra & 0x0800)) {
1.1.1.7   root     8830:                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8831:                                p = instrname + _tcslen(instrname);
                   8832:                                _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                   8833:                        } else {
                   8834:                                p = instrname + _tcslen(instrname);
                   8835:                                _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                   8836:                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8837:                        }
                   8838:                } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
                   8839:                                   lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
                   8840:                                   lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
                   8841:                                   lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
                   8842:                        TCHAR *p;
                   8843:                        int reg = -1;
                   8844: 
                   8845:                        pc += 2;
                   8846:                        p = instrname + _tcslen(instrname);
                   8847:                        if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
                   8848:                                reg = (extra >> 12) & 7;
                   8849:                        if (lookup->mnemo == i_BFINS)
                   8850:                                _stprintf(p, _T("D%d,"), reg);
                   8851:                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   8852:                        _tcscat(instrname, _T(" {"));
                   8853:                        p = instrname + _tcslen(instrname);
                   8854:                        if (extra & 0x0800)
                   8855:                                _stprintf(p, _T("D%d"), (extra >> 6) & 7);
                   8856:                        else
                   8857:                                _stprintf(p, _T("%d"), (extra >> 6) & 31);
                   8858:                        _tcscat(instrname, _T(":"));
                   8859:                        p = instrname + _tcslen(instrname);
                   8860:                        if (extra & 0x0020)
                   8861:                                _stprintf(p, _T("D%d"), extra & 7);
                   8862:                        else
                   8863:                                _stprintf(p, _T("%d"), extra  & 31);
                   8864:                        _tcscat(instrname, _T("}"));
                   8865:                        p = instrname + _tcslen(instrname);
                   8866:                        if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
                   8867:                                _stprintf(p, _T(",D%d"), reg);
                   8868:                } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
                   8869:                        lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
                   8870:                        if ((opcode & 0xc0) == 0xc0)
                   8871:                                _tcscat(instrname, _T("BC"));
                   8872:                        else if (opcode & 0x80)
                   8873:                                _tcscat(instrname, _T("IC"));
                   8874:                        else if (opcode & 0x40)
                   8875:                                _tcscat(instrname, _T("DC"));
                   8876:                        else
                   8877:                                _tcscat(instrname, _T("?"));
                   8878:                        if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
                   8879:                                TCHAR *p = instrname + _tcslen(instrname);
                   8880:                                _stprintf(p, _T(",(A%d)"), opcode & 7);
                   8881:                        }
1.1.1.10! root     8882:                } else if (lookup->mnemo == i_MOVE16) {
        !          8883:                        TCHAR *p = instrname + _tcslen(instrname);
        !          8884:                        if (opcode & 0x20) {
        !          8885:                                _stprintf(p, _T("(A%d)+,(A%d)+"), opcode & 7, (extra >> 12) & 7);
        !          8886:                                pc += 2;
        !          8887:                        } else {
        !          8888:                                uae_u32 addr = get_long_debug(pc + 2);
        !          8889:                                int ay = opcode & 7;
        !          8890:                                pc += 4;
        !          8891:                                switch ((opcode >> 3) & 3)
        !          8892:                                {
        !          8893:                                case 0:
        !          8894:                                        _stprintf(p, _T("(A%d)+,$%08x"), ay, addr);
        !          8895:                                        break;
        !          8896:                                case 1:
        !          8897:                                        _stprintf(p, _T("$%08x,(A%d)+"), addr, ay);
        !          8898:                                        break;
        !          8899:                                case 2:
        !          8900:                                        _stprintf(p, _T("(A%d),$%08x"), ay, addr);
        !          8901:                                        break;
        !          8902:                                case 3:
        !          8903:                                        _stprintf(p, _T("$%08x,(A%d)"), addr, ay);
        !          8904:                                        break;
        !          8905:                                }
        !          8906:                        }
1.1.1.7   root     8907:                } else if (lookup->mnemo == i_FPP) {
                   8908:                        TCHAR *p;
                   8909:                        int ins = extra & 0x3f;
                   8910:                        int size = (extra >> 10) & 7;
                   8911: 
                   8912:                        pc += 2;
                   8913:                        if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
                   8914:                                fpdata fp;
1.1.1.9   root     8915:                                fpu_get_constant(&fp, extra);
                   8916:                                _stprintf(instrname, _T("FMOVECR.X #0x%02x [%s],FP%d"), extra & 0x7f, fpp_print(&fp, 0), (extra >> 7) & 7);
1.1.1.7   root     8917:                        } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
                   8918:                                int dr = (extra >> 13) & 1;
                   8919:                                int mode;
                   8920:                                int dreg = (extra >> 4) & 7;
                   8921:                                int regmask, fpmode;
                   8922:                                
                   8923:                                if (extra & 0x4000) {
                   8924:                                        mode = (extra >> 11) & 3;
                   8925:                                        regmask = extra & 0xff;  // FMOVEM FPx
                   8926:                                        fpmode = 1;
                   8927:                                        _tcscpy(instrname, _T("FMOVEM.X "));
                   8928:                                } else {
                   8929:                                        mode = 0;
                   8930:                                        regmask = (extra >> 10) & 7;  // FMOVEM control
                   8931:                                        fpmode = 2;
                   8932:                                        _tcscpy(instrname, _T("FMOVEM.L "));
                   8933:                                        if (regmask == 1 || regmask == 2 || regmask == 4)
                   8934:                                                _tcscpy(instrname, _T("FMOVE.L "));
                   8935:                                }
                   8936:                                p = instrname + _tcslen(instrname);
                   8937:                                if (dr) {
                   8938:                                        if (mode & 1)
                   8939:                                                _stprintf(instrname, _T("D%d"), dreg);
                   8940:                                        else
1.1.1.10! root     8941:                                                movemout(instrname, regmask, dp->dmode, fpmode, false);
1.1.1.7   root     8942:                                        _tcscat(instrname, _T(","));
                   8943:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8944:                                } else {
                   8945:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   8946:                                        p = instrname + _tcslen(instrname);
                   8947:                                        if (mode & 1)
1.1.1.10! root     8948:                                                _stprintf(p, _T(",D%d"), dreg);
1.1.1.7   root     8949:                                        else
1.1.1.10! root     8950:                                                movemout(p, regmask, dp->dmode, fpmode, true);
1.1.1.7   root     8951:                                }
                   8952:                        } else {
                   8953:                                if (fpuopcodes[ins])
                   8954:                                        _tcscpy(instrname, fpuopcodes[ins]);
                   8955:                                else
                   8956:                                        _tcscpy(instrname, _T("F?"));
                   8957: 
                   8958:                                if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
                   8959:                                        int kfactor = extra & 0x7f;
                   8960:                                        _tcscpy(instrname, _T("FMOVE."));
                   8961:                                        _tcscat(instrname, fpsizes[size]);
                   8962:                                        _tcscat(instrname, _T(" "));
                   8963:                                        p = instrname + _tcslen(instrname);
                   8964:                                        _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
                   8965:                                        pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
                   8966:                                        p = instrname + _tcslen(instrname);
                   8967:                                        if (size == 7) {
                   8968:                                                _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
                   8969:                                        } else if (kfactor) {
                   8970:                                                if (kfactor & 0x40)
                   8971:                                                        kfactor |= ~0x3f;
                   8972:                                                _stprintf(p, _T(" {%d}"), kfactor);
                   8973:                                        }
                   8974:                                } else {
                   8975:                                        if (extra & 0x4000) { // source is EA
                   8976:                                                _tcscat(instrname, _T("."));
                   8977:                                                _tcscat(instrname, fpsizes[size]);
                   8978:                                                _tcscat(instrname, _T(" "));
                   8979:                                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
                   8980:                                        } else { // source is FPx
                   8981:                                                p = instrname + _tcslen(instrname);
                   8982:                                                _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
                   8983:                                        }
                   8984:                                        p = instrname + _tcslen(instrname);
                   8985:                                        if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
                   8986:                                                _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
                   8987:                                        if (ins >= 0x30 && ins < 0x38) { // FSINCOS
                   8988:                                                p = instrname + _tcslen(instrname);
                   8989:                                                _stprintf(p, _T(",FP%d"), extra & 7);
                   8990:                                        }
                   8991:                                }
                   8992:                        }
                   8993:                } else if ((opcode & 0xf000) == 0xa000) {
                   8994:                        _tcscpy(instrname, _T("A-LINE"));
1.1.1.4   root     8995:                } else {
                   8996:                        if (dp->suse) {
1.1.1.7   root     8997:                                pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
1.1.1.10! root     8998: 
        !          8999:                                // JSR x(a6) / JMP x(a6)
        !          9000:                                if (opcode == 0x4ea8 + 6 || opcode == 0x4ee8 + 6) {
        !          9001:                                        TCHAR sname[256];
        !          9002:                                        if (debugger_get_library_symbol(m68k_areg(regs, 6), 0xffff0000 | extra, sname)) {
        !          9003:                                                TCHAR *p = instrname + _tcslen(instrname);
        !          9004:                                                _stprintf(p, _T(" %s"), sname);
        !          9005:                                                resolve_if_jmp(instrname, m68k_areg(regs, 6) + (uae_s16)extra);
        !          9006:                                        }
        !          9007:                                }
        !          9008:                                // show target address if JSR x(pc) + JMP xxxx combination
        !          9009:                                if (opcode == 0x4eba && seaddr2 && instrname[0]) { // JSR x(pc)
        !          9010:                                        resolve_if_jmp(instrname, seaddr2);
        !          9011:                                }
1.1.1.4   root     9012:                        }
                   9013:                        if (dp->suse && dp->duse)
1.1.1.7   root     9014:                                _tcscat (instrname, _T(","));
1.1.1.4   root     9015:                        if (dp->duse) {
1.1.1.7   root     9016:                                pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
1.1.1.4   root     9017:                        }
                   9018:                }
                   9019: 
1.1.1.7   root     9020:                for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) {
                   9021:                        buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
1.1.1.4   root     9022:                }
                   9023:                while (i++ < 5)
1.1.1.7   root     9024:                        buf = buf_out (buf, &bufsize, _T("     "));
1.1.1.4   root     9025: 
1.1.1.7   root     9026:                if (illegal)
                   9027:                        buf = buf_out (buf, &bufsize, _T("[ "));
                   9028:                buf = buf_out (buf, &bufsize, instrname);
                   9029:                if (illegal)
                   9030:                        buf = buf_out (buf, &bufsize, _T(" ]"));
1.1.1.4   root     9031: 
                   9032:                if (ccpt != 0) {
1.1.1.7   root     9033:                        uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
1.1.1.4   root     9034:                        if (deaddr)
1.1.1.7   root     9035:                                *deaddr = pc;
                   9036:                        if ((opcode & 0xf000) == 0xf000) {
                   9037:                                if (fpp_cond(dp->cc)) {
                   9038:                                        buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
                   9039:                                } else {
                   9040:                                        buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
                   9041:                                }
                   9042:                        } else {
1.1.1.10! root     9043:                                if (dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
        !          9044:                                        if (cctrue(dp->cc)) {
        !          9045:                                                buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
        !          9046:                                        } else {
        !          9047:                                                buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
        !          9048:                                        }
1.1.1.7   root     9049:                                } else {
1.1.1.10! root     9050:                                        if (cctrue(dp->cc)) {
        !          9051:                                                buf = buf_out(buf, &bufsize, _T(" (T)"));
        !          9052:                                        } else {
        !          9053:                                                buf = buf_out(buf, &bufsize, _T(" (F)"));
        !          9054:                                        }
1.1.1.7   root     9055:                                }
                   9056:                        }
1.1.1.4   root     9057:                } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
                   9058:                        if (deaddr)
1.1.1.7   root     9059:                                *deaddr = pc;
                   9060:                        buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
1.1.1.4   root     9061:                }
1.1.1.7   root     9062:                buf = buf_out (buf, &bufsize, _T("\n"));
                   9063: 
1.1.1.10! root     9064:                for (uaecptr segpc = oldpc; segpc < pc; segpc++) {
        !          9065:                        TCHAR segout[256];
        !          9066:                        if (debugmem_get_symbol(segpc, segout, sizeof(segout) / sizeof(TCHAR))) {
        !          9067:                                _tcscat(segout, _T(":\n"));
        !          9068:                                if (bufsize > _tcslen(segout)) {
        !          9069:                                        memmove(symbolpos + _tcslen(segout), symbolpos, (_tcslen(symbolpos) + 1) * sizeof(TCHAR));
        !          9070:                                        memcpy(symbolpos, segout, _tcslen(segout) * sizeof(TCHAR));
        !          9071:                                        bufsize -= _tcslen(segout);
        !          9072:                                        buf += _tcslen(segout);
        !          9073:                                        symbolpos += _tcslen(segout);
        !          9074:                                }
        !          9075:                        }
        !          9076:                }
        !          9077: 
        !          9078:                int srcline = -1;
        !          9079:                for (uaecptr segpc = oldpc; segpc < pc; segpc++) {
        !          9080:                        TCHAR sourceout[256];
        !          9081:                        int line = debugmem_get_sourceline(segpc, sourceout, sizeof(sourceout) / sizeof(TCHAR));
        !          9082:                        if (line < 0)
        !          9083:                                break;
        !          9084:                        if (srcline != line) {
        !          9085:                                if (srcline < 0)
        !          9086:                                        buf = buf_out(buf, &bufsize, _T("\n"));
        !          9087:                                buf = buf_out(buf, &bufsize, sourceout);
        !          9088:                                srcline = line;
        !          9089:                        }
        !          9090:                }
        !          9091:                if (srcline >= 0) {
        !          9092:                        buf = buf_out(buf, &bufsize, _T("\n"));
        !          9093:                }
        !          9094: 
1.1.1.7   root     9095:                if (illegal)
                   9096:                        pc =  m68kpc_illg;
1.1.1.4   root     9097:        }
                   9098:        if (nextpc)
1.1.1.7   root     9099:                *nextpc = pc;
                   9100:        if (seaddr)
                   9101:                *seaddr = seaddr2;
                   9102:        if (deaddr)
                   9103:                *deaddr = deaddr2;
1.1.1.4   root     9104: }
                   9105: 
1.1.1.10! root     9106: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc)
1.1.1.7   root     9107: {
                   9108:        TCHAR *buf;
                   9109: 
1.1.1.10! root     9110:        buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
1.1.1.7   root     9111:        if (!buf)
                   9112:                return;
1.1.1.10! root     9113:        m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, seaddr, deaddr, lastpc, 1);
1.1.1.7   root     9114:        xfree (buf);
                   9115: }
1.1.1.10! root     9116: void m68k_disasm (uaecptr addr, uaecptr *nextpc, uaecptr lastpc, int cnt)
1.1.1.4   root     9117: {
1.1.1.7   root     9118:        TCHAR *buf;
                   9119: 
1.1.1.10! root     9120:        buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
1.1.1.7   root     9121:        if (!buf)
                   9122:                return;
1.1.1.10! root     9123:        m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, NULL, NULL, lastpc, 0);
1.1.1.7   root     9124:        console_out_f (_T("%s"), buf);
                   9125:        xfree (buf);
1.1.1.4   root     9126: }
1.1.1.10! root     9127: void m68k_disasm_file (FILE *f, uaecptr addr, uaecptr *nextpc, uaecptr lastpc, int cnt)
1.1.1.4   root     9128: {
1.1.1.7   root     9129:        TCHAR *buf;
                   9130: 
                   9131:        buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
                   9132:        if (!buf)
                   9133:                return;
                   9134:        console_out_FILE = f;
1.1.1.10! root     9135:        m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, NULL, NULL, lastpc, 0);
1.1.1.7   root     9136:        f_out (f, _T("%s"), buf);
                   9137:        xfree (buf);
                   9138:        console_out_FILE = NULL;
1.1.1.4   root     9139: }
                   9140: 
                   9141: /*************************************************************
                   9142: Disasm the m68kcode at the given address into instrname
                   9143: and instrcode
                   9144: *************************************************************/
1.1.1.10! root     9145: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc)
1.1.1.4   root     9146: {
                   9147:        TCHAR *ccpt;
                   9148:        uae_u32 opcode;
                   9149:        struct mnemolookup *lookup;
                   9150:        struct instr *dp;
1.1.1.7   root     9151:        uaecptr pc, oldpc;
1.1.1.4   root     9152: 
1.1.1.7   root     9153:        pc = oldpc = addr;
                   9154:        opcode = get_word_debug (pc);
1.1.1.4   root     9155:        if (cpufunctbl[opcode] == op_illg_1) {
                   9156:                opcode = 0x4AFC;
                   9157:        }
                   9158:        dp = table68k + opcode;
                   9159:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
                   9160: 
1.1.1.7   root     9161:        pc += 2;
1.1.1.4   root     9162: 
                   9163:        _tcscpy (instrname, lookup->name);
1.1.1.7   root     9164:        ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4   root     9165:        if (ccpt != 0) {
                   9166:                _tcsncpy (ccpt, ccnames[dp->cc], 2);
                   9167:        }
                   9168:        switch (dp->size){
1.1.1.7   root     9169:        case sz_byte: _tcscat (instrname, _T(".B ")); break;
                   9170:        case sz_word: _tcscat (instrname, _T(".W ")); break;
                   9171:        case sz_long: _tcscat (instrname, _T(".L ")); break;
                   9172:        default: _tcscat (instrname, _T("   ")); break;
1.1.1.4   root     9173:        }
                   9174: 
                   9175:        if (dp->suse) {
1.1.1.7   root     9176:                pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
1.1.1.4   root     9177:        }
                   9178:        if (dp->suse && dp->duse)
1.1.1.7   root     9179:                _tcscat (instrname, _T(","));
1.1.1.4   root     9180:        if (dp->duse) {
1.1.1.7   root     9181:                pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
1.1.1.4   root     9182:        }
                   9183:        if (instrcode)
                   9184:        {
                   9185:                int i;
1.1.1.10! root     9186:                for (i = 0; i < (pc - oldpc) / 2; i++)
1.1.1.4   root     9187:                {
1.1.1.7   root     9188:                        _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
1.1.1.4   root     9189:                        instrcode += _tcslen (instrcode);
                   9190:                }
                   9191:        }
                   9192:        if (nextpc)
1.1.1.7   root     9193:                *nextpc = pc;
1.1.1.4   root     9194: }
                   9195: 
                   9196: struct cpum2c m2cregs[] = {
1.1.1.7   root     9197:        { 0, _T("SFC") },
                   9198:        { 1, _T("DFC") },
                   9199:        { 2, _T("CACR") },
                   9200:        { 3, _T("TC") },
                   9201:        { 4, _T("ITT0") },
                   9202:        { 5, _T("ITT1") },
                   9203:        { 6, _T("DTT0") },
                   9204:        { 7, _T("DTT1") },
                   9205:        { 8, _T("BUSC") },
                   9206:        { 0x800, _T("USP") },
                   9207:        { 0x801, _T("VBR") },
                   9208:        { 0x802, _T("CAAR") },
                   9209:        { 0x803, _T("MSP") },
                   9210:        { 0x804, _T("ISP") },
                   9211:        { 0x805, _T("MMUS") },
                   9212:        { 0x806, _T("URP") },
                   9213:        { 0x807, _T("SRP") },
                   9214:        { 0x808, _T("PCR") },
                   9215:     { -1, NULL }
1.1.1.4   root     9216: };
                   9217: 
1.1.1.10! root     9218: void m68k_dumpstate(uaecptr *nextpc, uaecptr prevpc)
1.1.1.4   root     9219: {
                   9220:        int i, j;
1.1.1.10! root     9221:        uaecptr pc = M68K_GETPC;
1.1.1.4   root     9222: 
                   9223:        for (i = 0; i < 8; i++){
1.1.1.7   root     9224:                console_out_f (_T("  D%d %08X "), i, m68k_dreg (regs, i));
                   9225:                if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4   root     9226:        }
                   9227:        for (i = 0; i < 8; i++){
1.1.1.7   root     9228:                console_out_f (_T("  A%d %08X "), i, m68k_areg (regs, i));
                   9229:                if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4   root     9230:        }
                   9231:        if (regs.s == 0)
                   9232:                regs.usp = m68k_areg (regs, 7);
                   9233:        if (regs.s && regs.m)
                   9234:                regs.msp = m68k_areg (regs, 7);
                   9235:        if (regs.s && regs.m == 0)
                   9236:                regs.isp = m68k_areg (regs, 7);
                   9237:        j = 2;
1.1.1.7   root     9238:        console_out_f (_T("USP  %08X ISP  %08X "), regs.usp, regs.isp);
1.1.1.4   root     9239:        for (i = 0; m2cregs[i].regno>= 0; i++) {
                   9240:                if (!movec_illg (m2cregs[i].regno)) {
1.1.1.7   root     9241:                        if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
1.1.1.4   root     9242:                                continue;
                   9243:                        if (j > 0 && (j % 4) == 0)
1.1.1.7   root     9244:                                console_out_f (_T("\n"));
                   9245:                        console_out_f (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
1.1.1.4   root     9246:                        j++;
                   9247:                }
                   9248:        }
                   9249:        if (j > 0)
1.1.1.7   root     9250:                console_out_f (_T("\n"));
                   9251:                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     9252:                regs.t1, regs.t0, regs.s, regs.m,
                   9253:                GET_XFLG (), GET_NFLG (), GET_ZFLG (),
                   9254:                GET_VFLG (), GET_CFLG (),
                   9255:                regs.intmask, regs.stopped);
                   9256: #ifdef FPUEMU
                   9257:        if (currprefs.fpu_model) {
                   9258:                uae_u32 fpsr;
1.1.1.9   root     9259:                for (i = 0; i < 8; i++) {
                   9260:                        if (!(i & 1))
                   9261:                                console_out_f(_T("%d: "), i);
                   9262:                        console_out_f (_T("%s "), fpp_print(&regs.fp[i], -1));
                   9263:                        console_out_f (_T("%s "), fpp_print(&regs.fp[i], 0));
                   9264:                        if (i & 1)
1.1.1.7   root     9265:                                console_out_f (_T("\n"));
1.1.1.4   root     9266:                }
1.1.1.7   root     9267:                fpsr = fpp_get_fpsr ();
1.1.1.9   root     9268:                console_out_f (_T("FPSR: %08X FPCR: %08x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
1.1.1.7   root     9269:                        fpsr, regs.fpcr, regs.fpiar,
1.1.1.4   root     9270:                        (fpsr & 0x8000000) != 0,
                   9271:                        (fpsr & 0x4000000) != 0,
                   9272:                        (fpsr & 0x2000000) != 0,
                   9273:                        (fpsr & 0x1000000) != 0);
                   9274:        }
                   9275: #endif
1.1.1.7   root     9276:        if (currprefs.mmu_model == 68030) {
                   9277: #ifndef WINUAE_FOR_HATARI
                   9278:                console_out_f (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
1.1.1.8   root     9279: #else          /* Use PRIX64 since MinGW on Windows does not know about %llx (?) */
                   9280:                console_out_f (_T("SRP: %"PRIX64" CRP: %"PRIX64"\n"), (uint64_t)srp_030, (uint64_t)crp_030);
1.1.1.7   root     9281: #endif
                   9282:                console_out_f (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
                   9283:        }
1.1.1.9   root     9284:        if (currprefs.cpu_compatible) {
                   9285:                if (currprefs.cpu_model == 68000) {
                   9286:                        struct instr *dp;
                   9287:                        struct mnemolookup *lookup1, *lookup2;
                   9288:                        dp = table68k + regs.irc;
                   9289:                        for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++)
                   9290:                                ;
                   9291:                        dp = table68k + regs.ir;
                   9292:                        for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++)
                   9293:                                ;
                   9294:                        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);
                   9295:                } else if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
                   9296:                        console_out_f (_T("Prefetch %08x %08x (%d) %04x (%d) %04x (%d) %04x (%d)\n"),
                   9297:                                regs.cacheholdingaddr020, regs.cacheholdingdata020, regs.cacheholdingdata_valid,
                   9298:                                regs.prefetch020[0], regs.prefetch020_valid[0],
                   9299:                                regs.prefetch020[1], regs.prefetch020_valid[1],
                   9300:                                regs.prefetch020[2], regs.prefetch020_valid[2]);
                   9301:                }
1.1.1.4   root     9302:        }
1.1.1.10! root     9303:        if (prevpc != 0xffffffff && pc - prevpc < 100) {
        !          9304:                while (prevpc < pc) {
        !          9305:                        m68k_disasm(prevpc, &prevpc, 0xffffffff, 1);
        !          9306:                }
1.1.1.7   root     9307:        }
1.1.1.10! root     9308:        m68k_disasm (pc, nextpc, pc, 1);
        !          9309:        if (nextpc)
        !          9310:                console_out_f (_T("Next PC: %08x\n"), *nextpc);
1.1.1.7   root     9311: }
                   9312: #ifdef WINUAE_FOR_HATARI
1.1.1.10! root     9313: void m68k_dumpstate_file (FILE *f, uaecptr *nextpc, uaecptr prevpc)
1.1.1.7   root     9314: {
                   9315:        console_out_FILE = f;
1.1.1.10! root     9316:        m68k_dumpstate(nextpc, prevpc);
1.1.1.7   root     9317:        console_out_FILE = NULL;
                   9318: }
                   9319: #endif
1.1.1.9   root     9320: void m68k_dumpcache (bool dc)
1.1.1.7   root     9321: {
                   9322:        if (!currprefs.cpu_compatible)
                   9323:                return;
                   9324:        if (currprefs.cpu_model == 68020) {
1.1.1.10! root     9325:                for (int i = 0; i < CACHELINES020; i += 4) {
        !          9326:                        for (int j = 0; j < 4; j++) {
1.1.1.7   root     9327:                                int s = i + j;
                   9328:                                uaecptr addr;
1.1.1.9   root     9329:                                int fc;
1.1.1.7   root     9330:                                struct cache020 *c = &caches020[s];
1.1.1.9   root     9331:                                fc = c->tag & 1;
1.1.1.7   root     9332:                                addr = c->tag & ~1;
                   9333:                                addr |= s << 2;
1.1.1.9   root     9334:                                console_out_f (_T("%08X%c:%08X%c"), addr, fc ? 'S' : 'U', c->data, c->valid ? '*' : ' ');
1.1.1.7   root     9335:                        }
                   9336:                        console_out_f (_T("\n"));
                   9337:                }
                   9338:        } else if (currprefs.cpu_model == 68030) {
1.1.1.10! root     9339:                for (int i = 0; i < CACHELINES030; i++) {
1.1.1.9   root     9340:                        struct cache030 *c = dc ? &dcaches030[i] : &icaches030[i];
                   9341:                        int fc;
1.1.1.7   root     9342:                        uaecptr addr;
1.1.1.9   root     9343:                        if (!dc) {
                   9344:                                fc = (c->tag & 1) ? 6 : 2;
                   9345:                        } else {
                   9346:                                fc = c->fc;
                   9347:                        }
1.1.1.7   root     9348:                        addr = c->tag & ~1;
                   9349:                        addr |= i << 4;
1.1.1.9   root     9350:                        console_out_f (_T("%08X %d: "), addr, fc);
1.1.1.10! root     9351:                        for (int j = 0; j < 4; j++) {
1.1.1.7   root     9352:                                console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
                   9353:                        }
                   9354:                        console_out_f (_T("\n"));
                   9355:                }
1.1.1.9   root     9356:        } else if (currprefs.cpu_model >= 68040) {
                   9357:                uae_u32 tagmask = dc ? cachedtag04060mask : cacheitag04060mask;
1.1.1.10! root     9358:                for (int i = 0; i < cachedsets04060; i++) {
1.1.1.9   root     9359:                        struct cache040 *c = dc ? &dcaches040[i] : &icaches040[i];
1.1.1.10! root     9360:                        for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     9361:                                if (c->valid[j]) {
                   9362:                                        uae_u32 addr = (c->tag[j] & tagmask) | (i << 4);
                   9363:                                        write_log(_T("%02d:%d %08x = %08x%c %08x%c %08x%c %08x%c\n"),
                   9364:                                                i, j, addr,
                   9365:                                                c->data[j][0], c->dirty[j][0] ? '*' : ' ',
                   9366:                                                c->data[j][1], c->dirty[j][1] ? '*' : ' ',
                   9367:                                                c->data[j][2], c->dirty[j][2] ? '*' : ' ',
                   9368:                                                c->data[j][3], c->dirty[j][3] ? '*' : ' ');
                   9369:                                }
                   9370:                        }
                   9371:                }
1.1.1.7   root     9372:        }
1.1.1.4   root     9373: }
                   9374: 
                   9375: #ifdef SAVESTATE
                   9376: 
                   9377: /* CPU save/restore code */
                   9378: 
                   9379: #define CPUTYPE_EC 1
                   9380: #define CPUMODE_HALT 1
                   9381: 
                   9382: uae_u8 *restore_cpu (uae_u8 *src)
                   9383: {
1.1.1.10! root     9384:        int flags, model;
1.1.1.4   root     9385:        uae_u32 l;
                   9386: 
1.1.1.7   root     9387:        currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 ();
1.1.1.4   root     9388:        flags = restore_u32 ();
                   9389:        changed_prefs.address_space_24 = 0;
                   9390:        if (flags & CPUTYPE_EC)
                   9391:                changed_prefs.address_space_24 = 1;
                   9392:        currprefs.address_space_24 = changed_prefs.address_space_24;
                   9393:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                   9394:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1.1.1.8   root     9395:        currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact;
1.1.1.4   root     9396:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
                   9397:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
                   9398:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
1.1.1.10! root     9399:        for (int i = 0; i < 15; i++)
1.1.1.4   root     9400:                regs.regs[i] = restore_u32 ();
                   9401:        regs.pc = restore_u32 ();
                   9402:        regs.irc = restore_u16 ();
                   9403:        regs.ir = restore_u16 ();
                   9404:        regs.usp = restore_u32 ();
                   9405:        regs.isp = restore_u32 ();
                   9406:        regs.sr = restore_u16 ();
                   9407:        l = restore_u32 ();
                   9408:        if (l & CPUMODE_HALT) {
                   9409:                regs.stopped = 1;
                   9410:        } else {
                   9411:                regs.stopped = 0;
                   9412:        }
                   9413:        if (model >= 68010) {
                   9414:                regs.dfc = restore_u32 ();
                   9415:                regs.sfc = restore_u32 ();
                   9416:                regs.vbr = restore_u32 ();
                   9417:        }
                   9418:        if (model >= 68020) {
                   9419:                regs.caar = restore_u32 ();
                   9420:                regs.cacr = restore_u32 ();
                   9421:                regs.msp = restore_u32 ();
                   9422:        }
                   9423:        if (model >= 68030) {
1.1.1.7   root     9424:                crp_030 = fake_crp_030 = restore_u64 ();
                   9425:                srp_030 = fake_srp_030 = restore_u64 ();
                   9426:                tt0_030 = fake_tt0_030 = restore_u32 ();
                   9427:                tt1_030 = fake_tt1_030 = restore_u32 ();
                   9428:                tc_030 = fake_tc_030 = restore_u32 ();
                   9429:                mmusr_030 = fake_mmusr_030 = restore_u16 ();
1.1.1.4   root     9430:        }
                   9431:        if (model >= 68040) {
                   9432:                regs.itt0 = restore_u32 ();
                   9433:                regs.itt1 = restore_u32 ();
                   9434:                regs.dtt0 = restore_u32 ();
                   9435:                regs.dtt1 = restore_u32 ();
                   9436:                regs.tcr = restore_u32 ();
                   9437:                regs.urp = restore_u32 ();
                   9438:                regs.srp = restore_u32 ();
                   9439:        }
                   9440:        if (model >= 68060) {
                   9441:                regs.buscr = restore_u32 ();
                   9442:                regs.pcr = restore_u32 ();
                   9443:        }
                   9444:        if (flags & 0x80000000) {
                   9445:                int khz = restore_u32 ();
                   9446:                restore_u32 ();
                   9447:                if (khz > 0 && khz < 800000)
                   9448:                        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
                   9449:        }
1.1.1.7   root     9450:        set_cpu_caches (true);
                   9451:        if (flags & 0x40000000) {
                   9452:                if (model == 68020) {
1.1.1.10! root     9453:                        for (int i = 0; i < CACHELINES020; i++) {
1.1.1.7   root     9454:                                caches020[i].data = restore_u32 ();
                   9455:                                caches020[i].tag = restore_u32 ();
                   9456:                                caches020[i].valid = restore_u8 () != 0;
                   9457:                        }
                   9458:                        regs.prefetch020addr = restore_u32 ();
                   9459:                        regs.cacheholdingaddr020 = restore_u32 ();
                   9460:                        regs.cacheholdingdata020 = restore_u32 ();
                   9461:                        if (flags & 0x20000000) {
1.1.1.9   root     9462:                                if (flags & 0x4000000) {
                   9463:                                        // 3.6 new (back to 16 bits)
1.1.1.10! root     9464:                                        for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.9   root     9465:                                                uae_u32 v = restore_u32();
                   9466:                                                regs.prefetch020[i] = v >> 16;
                   9467:                                                regs.prefetch020_valid[i] = (v & 1) != 0;
                   9468:                                        }
                   9469:                                } else {
                   9470:                                        // old
                   9471:                                        uae_u32 v = restore_u32();
                   9472:                                        regs.prefetch020[0] = v >> 16;
                   9473:                                        regs.prefetch020[1] = (uae_u16)v;
                   9474:                                        v = restore_u32();
                   9475:                                        regs.prefetch020[2] = v >> 16;
                   9476:                                        regs.prefetch020[3] = (uae_u16)v;
                   9477:                                        restore_u32();
                   9478:                                        restore_u32();
                   9479:                                        regs.prefetch020_valid[0] = true;
                   9480:                                        regs.prefetch020_valid[1] = true;
                   9481:                                        regs.prefetch020_valid[2] = true;
                   9482:                                        regs.prefetch020_valid[3] = true;
                   9483:                                }
1.1.1.7   root     9484:                        }
                   9485:                } else if (model == 68030) {
1.1.1.10! root     9486:                        for (int i = 0; i < CACHELINES030; i++) {
        !          9487:                                for (int j = 0; j < 4; j++) {
1.1.1.7   root     9488:                                        icaches030[i].data[j] = restore_u32 ();
                   9489:                                        icaches030[i].valid[j] = restore_u8 () != 0;
                   9490:                                }
                   9491:                                icaches030[i].tag = restore_u32 ();
                   9492:                        }
1.1.1.10! root     9493:                        for (int i = 0; i < CACHELINES030; i++) {
        !          9494:                                for (int j = 0; j < 4; j++) {
1.1.1.7   root     9495:                                        dcaches030[i].data[j] = restore_u32 ();
                   9496:                                        dcaches030[i].valid[j] = restore_u8 () != 0;
                   9497:                                }
                   9498:                                dcaches030[i].tag = restore_u32 ();
                   9499:                        }
                   9500:                        regs.prefetch020addr = restore_u32 ();
                   9501:                        regs.cacheholdingaddr020 = restore_u32 ();
                   9502:                        regs.cacheholdingdata020 = restore_u32 ();
1.1.1.9   root     9503:                        if (flags & 0x4000000) {
1.1.1.10! root     9504:                                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.9   root     9505:                                        uae_u32 v = restore_u32();
                   9506:                                        regs.prefetch020[i] = v >> 16;
                   9507:                                        regs.prefetch020_valid[i] = (v & 1) != 0;
                   9508:                                }
                   9509:                        } else {
1.1.1.10! root     9510:                                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.9   root     9511:                                        regs.prefetch020[i] = restore_u32 ();
                   9512:                                        regs.prefetch020_valid[i] = false;
                   9513:                                }
                   9514:                        }
                   9515:                } else if (model == 68040) {
1.1.1.7   root     9516:                        if (flags & 0x8000000) {
1.1.1.10! root     9517:                                for (int i = 0; i < ((model == 68060 && (flags & 0x4000000)) ? CACHESETS060 : CACHESETS040); i++) {
        !          9518:                                        for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     9519:                                                struct cache040 *c = &icaches040[i];
                   9520:                                                c->data[j][0] = restore_u32();
                   9521:                                                c->data[j][1] = restore_u32();
                   9522:                                                c->data[j][2] = restore_u32();
                   9523:                                                c->data[j][3] = restore_u32();
                   9524:                                                c->tag[j] = restore_u32();
                   9525:                                                c->valid[j] = restore_u16() & 1;
1.1.1.7   root     9526:                                        }
                   9527:                                }
                   9528:                                regs.prefetch020addr = restore_u32();
                   9529:                                regs.cacheholdingaddr020 = restore_u32();
                   9530:                                regs.cacheholdingdata020 = restore_u32();
1.1.1.10! root     9531:                                for (int i = 0; i < CPU_PIPELINE_MAX; i++)
1.1.1.9   root     9532:                                        regs.prefetch040[i] = restore_u32();
                   9533:                                if (flags & 0x4000000) {
1.1.1.10! root     9534:                                        for (int i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
        !          9535:                                                for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     9536:                                                        struct cache040 *c = &dcaches040[i];
                   9537:                                                        c->data[j][0] = restore_u32();
                   9538:                                                        c->data[j][1] = restore_u32();
                   9539:                                                        c->data[j][2] = restore_u32();
                   9540:                                                        c->data[j][3] = restore_u32();
                   9541:                                                        c->tag[j] = restore_u32();
                   9542:                                                        uae_u16 v = restore_u16();
                   9543:                                                        c->valid[j] = (v & 1) != 0;
                   9544:                                                        c->dirty[j][0] = (v & 0x10) != 0;
                   9545:                                                        c->dirty[j][1] = (v & 0x20) != 0;
                   9546:                                                        c->dirty[j][2] = (v & 0x40) != 0;
                   9547:                                                        c->dirty[j][3] = (v & 0x80) != 0;
                   9548:                                                        c->gdirty[j] = c->dirty[j][0] || c->dirty[j][1] || c->dirty[j][2] || c->dirty[j][3];
                   9549:                                                }
                   9550:                                        }
                   9551:                                }
1.1.1.7   root     9552:                        }
                   9553:                }
                   9554:                if (model >= 68020) {
1.1.1.9   root     9555:                        restore_u32 (); // regs.ce020memcycles
                   9556:                        regs.ce020startcycle = regs.ce020endcycle = 0;
1.1.1.7   root     9557:                        restore_u32 ();
                   9558:                }
                   9559:        }
                   9560:        if (flags & 0x10000000) {
                   9561:                regs.chipset_latch_rw = restore_u32 ();
                   9562:                regs.chipset_latch_read = restore_u32 ();
                   9563:                regs.chipset_latch_write = restore_u32 ();
                   9564:        }
                   9565: 
1.1.1.9   root     9566:        regs.pipeline_pos = -1;
                   9567:        regs.pipeline_stop = 0;
                   9568:        if (flags & 0x4000000 && currprefs.cpu_model == 68020) {
                   9569:                regs.pipeline_pos = restore_u16();
                   9570:                regs.pipeline_r8[0] = restore_u16();
                   9571:                regs.pipeline_r8[1] = restore_u16();
                   9572:                regs.pipeline_stop = restore_u16();
                   9573:        }
                   9574: 
1.1.1.7   root     9575:        m68k_reset_sr();
                   9576: 
                   9577:        write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
                   9578:                model / 1000, flags & 1 ? _T("EC") : _T(""), model % 1000, regs.pc);
1.1.1.4   root     9579: 
                   9580:        return src;
                   9581: }
                   9582: 
1.1.1.7   root     9583: static void fill_prefetch_quick (void)
                   9584: {
                   9585:        if (currprefs.cpu_model >= 68020) {
                   9586:                fill_prefetch ();
                   9587:                return;
                   9588:        }
                   9589:        // old statefile compatibility, this needs to done,
                   9590:        // even in 68000 cycle-exact mode
                   9591:        regs.ir = get_word (m68k_getpc ());
                   9592:        regs.irc = get_word (m68k_getpc () + 2);
                   9593: }
                   9594: 
1.1.1.4   root     9595: void restore_cpu_finish (void)
                   9596: {
1.1.1.10! root     9597:        if (!currprefs.fpu_model)
        !          9598:                fpu_reset();
1.1.1.4   root     9599:        init_m68k ();
1.1.1.7   root     9600:        m68k_setpc_normal (regs.pc);
1.1.1.4   root     9601:        doint ();
1.1.1.7   root     9602:        fill_prefetch_quick ();
                   9603: #ifndef WINUAE_FOR_HATARI
                   9604:        set_cycles (start_cycles);
                   9605:        events_schedule ();
                   9606: #endif
1.1.1.4   root     9607:        if (regs.stopped)
                   9608:                set_special (SPCFLAG_STOP);
                   9609:        //activate_debugger ();
                   9610: }
                   9611: 
1.1.1.7   root     9612: uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
1.1.1.4   root     9613: {
1.1.1.7   root     9614:        uae_u8 *dstbak, *dst;
1.1.1.4   root     9615: 
1.1.1.7   root     9616:        if (cputrace.state <= 0)
                   9617:                return NULL;
1.1.1.4   root     9618: 
1.1.1.7   root     9619:        if (dstptr)
                   9620:                dstbak = dst = dstptr;
                   9621:        else
1.1.1.8   root     9622:                dstbak = dst = xmalloc (uae_u8, 10000);
1.1.1.7   root     9623: 
1.1.1.9   root     9624:        save_u32 (2 | 4 | 16 | 32);
1.1.1.7   root     9625:        save_u16 (cputrace.opcode);
1.1.1.10! root     9626:        for (int i = 0; i < 16; i++)
1.1.1.7   root     9627:                save_u32 (cputrace.regs[i]);
                   9628:        save_u32 (cputrace.pc);
                   9629:        save_u16 (cputrace.irc);
                   9630:        save_u16 (cputrace.ir);
                   9631:        save_u32 (cputrace.usp);
                   9632:        save_u32 (cputrace.isp);
                   9633:        save_u16 (cputrace.sr);
                   9634:        save_u16 (cputrace.intmask);
                   9635:        save_u16 ((cputrace.stopped ? 1 : 0) | (regs.stopped ? 2 : 0));
                   9636:        save_u16 (cputrace.state);
                   9637:        save_u32 (cputrace.cyclecounter);
                   9638:        save_u32 (cputrace.cyclecounter_pre);
                   9639:        save_u32 (cputrace.cyclecounter_post);
                   9640:        save_u32 (cputrace.readcounter);
                   9641:        save_u32 (cputrace.writecounter);
                   9642:        save_u32 (cputrace.memoryoffset);
                   9643:        write_log (_T("CPUT SAVE: PC=%08x C=%08X %08x %08x %08x %d %d %d\n"),
                   9644:                cputrace.pc, cputrace.startcycles,
                   9645:                cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
                   9646:                cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset);
1.1.1.10! root     9647:        for (int i = 0; i < cputrace.memoryoffset; i++) {
1.1.1.7   root     9648:                save_u32 (cputrace.ctm[i].addr);
                   9649:                save_u32 (cputrace.ctm[i].data);
                   9650:                save_u32 (cputrace.ctm[i].mode);
                   9651:                write_log (_T("CPUT%d: %08x %08x %08x\n"), i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode);
                   9652:        }
                   9653:        save_u32 (cputrace.startcycles);
                   9654: 
                   9655:        if (currprefs.cpu_model == 68020) {
1.1.1.10! root     9656:                for (int i = 0; i < CACHELINES020; i++) {
1.1.1.7   root     9657:                        save_u32 (cputrace.caches020[i].data);
                   9658:                        save_u32 (cputrace.caches020[i].tag);
                   9659:                        save_u8 (cputrace.caches020[i].valid ? 1 : 0);
                   9660:                }
                   9661:                save_u32 (cputrace.prefetch020addr);
                   9662:                save_u32 (cputrace.cacheholdingaddr020);
                   9663:                save_u32 (cputrace.cacheholdingdata020);
1.1.1.10! root     9664:                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.7   root     9665:                        save_u16 (cputrace.prefetch020[i]);
1.1.1.9   root     9666:                }
1.1.1.10! root     9667:                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.7   root     9668:                        save_u32 (cputrace.prefetch020[i]);
1.1.1.9   root     9669:                }
1.1.1.10! root     9670:                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.9   root     9671:                        save_u8 (cputrace.prefetch020_valid[i]);
                   9672:                }
                   9673:                save_u16(cputrace.pipeline_pos);
                   9674:                save_u16(cputrace.pipeline_r8[0]);
                   9675:                save_u16(cputrace.pipeline_r8[1]);
                   9676:                save_u16(cputrace.pipeline_stop);
1.1.1.7   root     9677:        }
                   9678: 
                   9679:        *len = dst - dstbak;
                   9680:        cputrace.needendcycles = 1;
                   9681:        return dstbak;
                   9682: }
                   9683: 
                   9684: uae_u8 *restore_cpu_trace (uae_u8 *src)
                   9685: {
                   9686:        cpu_tracer = 0;
                   9687:        cputrace.state = 0;
                   9688:        uae_u32 v = restore_u32 ();
                   9689:        if (!(v & 2))
                   9690:                return src;
                   9691:        cputrace.opcode = restore_u16 ();
1.1.1.10! root     9692:        for (int i = 0; i < 16; i++)
1.1.1.7   root     9693:                cputrace.regs[i] = restore_u32 ();
                   9694:        cputrace.pc = restore_u32 ();
                   9695:        cputrace.irc = restore_u16 ();
                   9696:        cputrace.ir = restore_u16 ();
                   9697:        cputrace.usp = restore_u32 ();
                   9698:        cputrace.isp = restore_u32 ();
                   9699:        cputrace.sr = restore_u16 ();
                   9700:        cputrace.intmask = restore_u16 ();
                   9701:        cputrace.stopped = restore_u16 ();
                   9702:        cputrace.state = restore_u16 ();
                   9703:        cputrace.cyclecounter = restore_u32 ();
                   9704:        cputrace.cyclecounter_pre = restore_u32 ();
                   9705:        cputrace.cyclecounter_post = restore_u32 ();
                   9706:        cputrace.readcounter = restore_u32 ();
                   9707:        cputrace.writecounter = restore_u32 ();
                   9708:        cputrace.memoryoffset = restore_u32 ();
1.1.1.10! root     9709:        for (int i = 0; i < cputrace.memoryoffset; i++) {
1.1.1.7   root     9710:                cputrace.ctm[i].addr = restore_u32 ();
                   9711:                cputrace.ctm[i].data = restore_u32 ();
                   9712:                cputrace.ctm[i].mode = restore_u32 ();
                   9713:        }
                   9714:        cputrace.startcycles = restore_u32 ();
                   9715: 
                   9716:        if (v & 4) {
                   9717:                if (currprefs.cpu_model == 68020) {
1.1.1.10! root     9718:                        for (int i = 0; i < CACHELINES020; i++) {
1.1.1.7   root     9719:                                cputrace.caches020[i].data = restore_u32 ();
                   9720:                                cputrace.caches020[i].tag = restore_u32 ();
                   9721:                                cputrace.caches020[i].valid = restore_u8 () != 0;
                   9722:                        }
                   9723:                        cputrace.prefetch020addr = restore_u32 ();
                   9724:                        cputrace.cacheholdingaddr020 = restore_u32 ();
                   9725:                        cputrace.cacheholdingdata020 = restore_u32 ();
1.1.1.10! root     9726:                        for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.7   root     9727:                                cputrace.prefetch020[i] = restore_u16 ();
1.1.1.9   root     9728:                        }
1.1.1.7   root     9729:                        if (v & 8) {
1.1.1.9   root     9730:                                // backwards compatibility
1.1.1.10! root     9731:                                uae_u32 v2 = restore_u32();
        !          9732:                                cputrace.prefetch020[0] = v2 >> 16;
        !          9733:                                cputrace.prefetch020[1] = (uae_u16)v2;
        !          9734:                                v2 = restore_u32();
        !          9735:                                cputrace.prefetch020[2] = v2 >> 16;
        !          9736:                                cputrace.prefetch020[3] = (uae_u16)v2;
1.1.1.9   root     9737:                                restore_u32();
                   9738:                                restore_u32();
                   9739:                                cputrace.prefetch020_valid[0] = true;
                   9740:                                cputrace.prefetch020_valid[1] = true;
                   9741:                                cputrace.prefetch020_valid[2] = true;
                   9742:                                cputrace.prefetch020_valid[3] = true;
                   9743: 
                   9744:                                cputrace.prefetch020[0] = cputrace.prefetch020[1];
                   9745:                                cputrace.prefetch020[1] = cputrace.prefetch020[2];
                   9746:                                cputrace.prefetch020[2] = cputrace.prefetch020[3];
                   9747:                                cputrace.prefetch020_valid[3] = false;
                   9748:                        }
                   9749:                        if (v & 16) {
1.1.1.10! root     9750:                                if ((v & 32) && !(v & 8)) {
        !          9751:                                        restore_u32();
        !          9752:                                        restore_u32();
        !          9753:                                        restore_u32();
        !          9754:                                        restore_u32();
        !          9755:                                }
        !          9756:                                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.9   root     9757:                                        cputrace.prefetch020_valid[i] = restore_u8() != 0;
                   9758:                                }
                   9759:                        }
                   9760:                        if (v & 32) {
                   9761:                                cputrace.pipeline_pos = restore_u16();
                   9762:                                cputrace.pipeline_r8[0] = restore_u16();
                   9763:                                cputrace.pipeline_r8[1] = restore_u16();
                   9764:                                cputrace.pipeline_stop = restore_u16();
1.1.1.7   root     9765:                        }
                   9766:                }
                   9767:        }
                   9768: 
                   9769:        cputrace.needendcycles = 1;
                   9770:        if (v && cputrace.state) {
                   9771:                if (currprefs.cpu_model > 68000) {
                   9772:                        if (v & 4)
                   9773:                                cpu_tracer = -1;
                   9774:                        // old format?
1.1.1.10! root     9775:                        if ((v & (4 | 8)) != (4 | 8) && (v & (32 | 16 | 8 | 4)) != (32 | 16 | 4))
1.1.1.7   root     9776:                                cpu_tracer = 0;
                   9777:                } else {
                   9778:                        cpu_tracer = -1;
                   9779:                }
                   9780:        }
                   9781: 
                   9782:        return src;
                   9783: }
                   9784: 
                   9785: uae_u8 *restore_cpu_extra (uae_u8 *src)
                   9786: {
                   9787:        restore_u32 ();
                   9788:        uae_u32 flags = restore_u32 ();
                   9789: 
                   9790:        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
1.1.1.8   root     9791:        currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = currprefs.cpu_cycle_exact;
                   9792:        if ((flags & 32) && !(flags & 1))
                   9793:                currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = true;
1.1.1.7   root     9794:        currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
                   9795:        currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
                   9796:        currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
                   9797:        currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
                   9798:        //currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
                   9799: 
                   9800:        currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
                   9801:        if (flags & 4)
1.1.1.4   root     9802:                currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
1.1.1.7   root     9803:        if (flags & 16)
                   9804:                currprefs.m68k_speed = changed_prefs.m68k_speed = (flags >> 24) * CYCLE_UNIT;
1.1.1.4   root     9805: 
                   9806:        currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
                   9807:        currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
                   9808: 
                   9809:        return src;
                   9810: }
                   9811: 
                   9812: uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
                   9813: {
                   9814:        uae_u8 *dstbak, *dst;
                   9815:        uae_u32 flags;
                   9816: 
                   9817:        if (dstptr)
                   9818:                dstbak = dst = dstptr;
                   9819:        else
                   9820:                dstbak = dst = xmalloc (uae_u8, 1000);
                   9821:        save_u32 (0); // version
                   9822:        flags = 0;
                   9823:        flags |= currprefs.cpu_cycle_exact ? 1 : 0;
                   9824:        flags |= currprefs.cpu_compatible ? 2 : 0;
                   9825:        flags |= currprefs.m68k_speed < 0 ? 4 : 0;
                   9826:        flags |= currprefs.cachesize > 0 ? 8 : 0;
1.1.1.7   root     9827:        flags |= currprefs.m68k_speed > 0 ? 16 : 0;
1.1.1.8   root     9828:        flags |= currprefs.cpu_memory_cycle_exact ? 32 : 0;
1.1.1.7   root     9829:        if (currprefs.m68k_speed > 0)
                   9830:                flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24;
1.1.1.4   root     9831:        save_u32 (flags);
                   9832:        save_u32 (currprefs.cpu_frequency);
                   9833:        save_u32 (currprefs.cpu_clock_multiplier);
                   9834:        save_u8 (currprefs.cpu060_revision);
                   9835:        save_u8 (currprefs.fpu_revision);
                   9836:        *len = dst - dstbak;
                   9837:        return dstbak;
                   9838: }
                   9839: 
                   9840: uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                   9841: {
                   9842:        uae_u8 *dstbak, *dst;
1.1.1.10! root     9843:        int model, khz;
1.1.1.4   root     9844: 
                   9845:        if (dstptr)
                   9846:                dstbak = dst = dstptr;
                   9847:        else
1.1.1.10! root     9848:                dstbak = dst = xmalloc (uae_u8, 1000 + 30000);
1.1.1.4   root     9849:        model = currprefs.cpu_model;
                   9850:        save_u32 (model);                                       /* MODEL */
1.1.1.9   root     9851:        save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 | 0x4000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
1.1.1.10! root     9852:        for (int i = 0;i < 15; i++)
1.1.1.4   root     9853:                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
                   9854:        save_u32 (m68k_getpc ());                       /* PC */
                   9855:        save_u16 (regs.irc);                            /* prefetch */
                   9856:        save_u16 (regs.ir);                                     /* instruction prefetch */
                   9857:        MakeSR ();
                   9858:        save_u32 (!regs.s ? regs.regs[15] : regs.usp);  /* USP */
                   9859:        save_u32 (regs.s ? regs.regs[15] : regs.isp);   /* ISP */
                   9860:        save_u16 (regs.sr);                                                             /* SR/CCR */
                   9861:        save_u32 (regs.stopped ? CPUMODE_HALT : 0);             /* flags */
                   9862:        if (model >= 68010) {
                   9863:                save_u32 (regs.dfc);                    /* DFC */
                   9864:                save_u32 (regs.sfc);                    /* SFC */
                   9865:                save_u32 (regs.vbr);                    /* VBR */
                   9866:        }
                   9867:        if (model >= 68020) {
                   9868:                save_u32 (regs.caar);                   /* CAAR */
                   9869:                save_u32 (regs.cacr);                   /* CACR */
                   9870:                save_u32 (regs.msp);                    /* MSP */
                   9871:        }
                   9872:        if (model >= 68030) {
1.1.1.7   root     9873:                if (currprefs.mmu_model) {
                   9874:                        save_u64 (crp_030);                             /* CRP */
                   9875:                        save_u64 (srp_030);                             /* SRP */
                   9876:                        save_u32 (tt0_030);                             /* TT0/AC0 */
                   9877:                        save_u32 (tt1_030);                             /* TT1/AC1 */
                   9878:                        save_u32 (tc_030);                              /* TCR */
                   9879:                        save_u16 (mmusr_030);                   /* MMUSR/ACUSR */
                   9880:                } else {
                   9881:                        save_u64 (fake_crp_030);                /* CRP */
                   9882:                        save_u64 (fake_srp_030);                /* SRP */
                   9883:                        save_u32 (fake_tt0_030);                /* TT0/AC0 */
                   9884:                        save_u32 (fake_tt1_030);                /* TT1/AC1 */
                   9885:                        save_u32 (fake_tc_030);                 /* TCR */
                   9886:                        save_u16 (fake_mmusr_030);              /* MMUSR/ACUSR */
                   9887:                }
1.1.1.4   root     9888:        }
                   9889:        if (model >= 68040) {
                   9890:                save_u32 (regs.itt0);                   /* ITT0 */
                   9891:                save_u32 (regs.itt1);                   /* ITT1 */
                   9892:                save_u32 (regs.dtt0);                   /* DTT0 */
                   9893:                save_u32 (regs.dtt1);                   /* DTT1 */
                   9894:                save_u32 (regs.tcr);                    /* TCR */
                   9895:                save_u32 (regs.urp);                    /* URP */
                   9896:                save_u32 (regs.srp);                    /* SRP */
                   9897:        }
                   9898:        if (model >= 68060) {
                   9899:                save_u32 (regs.buscr);                  /* BUSCR */
                   9900:                save_u32 (regs.pcr);                    /* PCR */
                   9901:        }
                   9902:        khz = -1;
                   9903:        if (currprefs.m68k_speed == 0) {
                   9904:                khz = currprefs.ntscmode ? 715909 : 709379;
                   9905:                if (currprefs.cpu_model >= 68020)
                   9906:                        khz *= 2;
                   9907:        }
                   9908:        save_u32 (khz); // clock rate in KHz: -1 = fastest possible
                   9909:        save_u32 (0); // spare
1.1.1.7   root     9910:        if (model == 68020) {
1.1.1.10! root     9911:                for (int i = 0; i < CACHELINES020; i++) {
1.1.1.7   root     9912:                        save_u32 (caches020[i].data);
                   9913:                        save_u32 (caches020[i].tag);
                   9914:                        save_u8 (caches020[i].valid ? 1 : 0);
                   9915:                }
                   9916:                save_u32 (regs.prefetch020addr);
                   9917:                save_u32 (regs.cacheholdingaddr020);
                   9918:                save_u32 (regs.cacheholdingdata020);
1.1.1.10! root     9919:                for (int i = 0; i < CPU_PIPELINE_MAX; i++)
1.1.1.9   root     9920:                        save_u32 ((regs.prefetch020[i] << 16) | (regs.prefetch020_valid[i] ? 1 : 0));
1.1.1.7   root     9921:        } else if (model == 68030) {
1.1.1.10! root     9922:                for (int i = 0; i < CACHELINES030; i++) {
        !          9923:                        for (int j = 0; j < 4; j++) {
1.1.1.7   root     9924:                                save_u32 (icaches030[i].data[j]);
                   9925:                                save_u8 (icaches030[i].valid[j] ? 1 : 0);
                   9926:                        }
                   9927:                        save_u32 (icaches030[i].tag);
                   9928:                }
1.1.1.10! root     9929:                for (int i = 0; i < CACHELINES030; i++) {
        !          9930:                        for (int j = 0; j < 4; j++) {
1.1.1.7   root     9931:                                save_u32 (dcaches030[i].data[j]);
                   9932:                                save_u8 (dcaches030[i].valid[j] ? 1 : 0);
                   9933:                        }
                   9934:                        save_u32 (dcaches030[i].tag);
                   9935:                }
                   9936:                save_u32 (regs.prefetch020addr);
                   9937:                save_u32 (regs.cacheholdingaddr020);
                   9938:                save_u32 (regs.cacheholdingdata020);
1.1.1.10! root     9939:                for (int i = 0; i < CPU_PIPELINE_MAX; i++)
1.1.1.7   root     9940:                        save_u32 (regs.prefetch020[i]);
                   9941:        } else if (model >= 68040) {
1.1.1.10! root     9942:                for (int i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
        !          9943:                        for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     9944:                                struct cache040 *c = &icaches040[i];
                   9945:                                save_u32(c->data[j][0]);
                   9946:                                save_u32(c->data[j][1]);
                   9947:                                save_u32(c->data[j][2]);
                   9948:                                save_u32(c->data[j][3]);
                   9949:                                save_u32(c->tag[j]);
                   9950:                                save_u16(c->valid[j] ? 1 : 0);
1.1.1.7   root     9951:                        }
                   9952:                }
                   9953:                save_u32(regs.prefetch020addr);
                   9954:                save_u32(regs.cacheholdingaddr020);
                   9955:                save_u32(regs.cacheholdingdata020);
1.1.1.10! root     9956:                for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
1.1.1.9   root     9957:                        save_u32(regs.prefetch040[i]);
                   9958:                }
1.1.1.10! root     9959:                for (int i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
        !          9960:                        for (int j = 0; j < CACHELINES040; j++) {
1.1.1.9   root     9961:                                struct cache040 *c = &dcaches040[i];
                   9962:                                save_u32(c->data[j][0]);
                   9963:                                save_u32(c->data[j][1]);
                   9964:                                save_u32(c->data[j][2]);
                   9965:                                save_u32(c->data[j][3]);
                   9966:                                save_u32(c->tag[j]);
                   9967:                                uae_u16 v = c->valid[j] ? 1 : 0;
                   9968:                                v |= c->dirty[j][0] ? 0x10 : 0;
                   9969:                                v |= c->dirty[j][1] ? 0x20 : 0;
                   9970:                                v |= c->dirty[j][2] ? 0x40 : 0;
                   9971:                                v |= c->dirty[j][3] ? 0x80 : 0;
                   9972:                                save_u16(v);
                   9973:                        }
                   9974:                }
1.1.1.7   root     9975:        }
                   9976:        if (currprefs.cpu_model >= 68020) {
1.1.1.9   root     9977:                save_u32 (0); //save_u32 (regs.ce020memcycles);
1.1.1.7   root     9978:                save_u32 (0);
                   9979:        }
                   9980:        save_u32 (regs.chipset_latch_rw);
                   9981:        save_u32 (regs.chipset_latch_read);
                   9982:        save_u32 (regs.chipset_latch_write);
1.1.1.9   root     9983:        if (currprefs.cpu_model == 68020) {
                   9984:                save_u16(regs.pipeline_pos);
                   9985:                save_u16(regs.pipeline_r8[0]);
                   9986:                save_u16(regs.pipeline_r8[1]);
                   9987:                save_u16(regs.pipeline_stop);
                   9988:        }
1.1.1.4   root     9989:        *len = dst - dstbak;
                   9990:        return dstbak;
                   9991: }
                   9992: 
                   9993: uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
                   9994: {
                   9995:        uae_u8 *dstbak, *dst;
                   9996:        int model;
                   9997: 
                   9998:        model = currprefs.mmu_model;
1.1.1.7   root     9999: #ifndef WINUAE_FOR_HATARI
1.1.1.8   root     10000:        /* Under Hatari, we save all MMU variables, even if mmu_model==0 */
1.1.1.7   root     10001:        if (model != 68030 && model != 68040 && model != 68060)
1.1.1.4   root     10002:                return NULL;
1.1.1.7   root     10003: #endif
1.1.1.4   root     10004:        if (dstptr)
                   10005:                dstbak = dst = dstptr;
                   10006:        else
                   10007:                dstbak = dst = xmalloc (uae_u8, 1000);
                   10008:        save_u32 (model);       /* MODEL */
1.1.1.7   root     10009:        save_u32 (0);           /* FLAGS */
1.1.1.4   root     10010:        *len = dst - dstbak;
                   10011:        return dstbak;
                   10012: }
                   10013: 
                   10014: uae_u8 *restore_mmu (uae_u8 *src)
                   10015: {
                   10016:        int flags, model;
                   10017: 
                   10018:        changed_prefs.mmu_model = model = restore_u32 ();
                   10019:        flags = restore_u32 ();
1.1.1.7   root     10020:        write_log (_T("MMU: %d\n"), model);
1.1.1.4   root     10021:        return src;
                   10022: }
                   10023: 
                   10024: #endif /* SAVESTATE */
                   10025: 
1.1.1.7   root     10026: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
1.1.1.4   root     10027: {
                   10028:        if (currprefs.cpu_model >= 68040)
                   10029:                addr &= ~1;
1.1.1.7   root     10030:        if (currprefs.cpu_model >= 68020) {
                   10031:                if (pc == 0xffffffff)
                   10032:                        last_addr_for_exception_3 = regs.instruction_pc;
                   10033:                else
                   10034:                        last_addr_for_exception_3 = pc;
                   10035:        } else if (pc == 0xffffffff) {
                   10036:                last_addr_for_exception_3 = m68k_getpc ();
                   10037:                if (plus2)
                   10038:                        last_addr_for_exception_3 += 2;
                   10039:        } else {
                   10040:                last_addr_for_exception_3 = pc;
                   10041:        }
                   10042:        last_fault_for_exception_3 = addr;
1.1.1.4   root     10043:        last_op_for_exception_3 = opcode;
                   10044:        last_writeaccess_for_exception_3 = writeaccess;
                   10045:        last_instructionaccess_for_exception_3 = instructionaccess;
1.1.1.7   root     10046:        last_notinstruction_for_exception_3 = notinstruction;
                   10047:        Exception (3);
                   10048: #if EXCEPTION3_DEBUGGER
                   10049:        activate_debugger();
                   10050: #endif
1.1.1.4   root     10051: }
                   10052: 
1.1.1.7   root     10053: void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
1.1.1.4   root     10054: {
1.1.1.7   root     10055:        exception3f (opcode, addr, true, false, true, 0xffffffff, false);
1.1.1.4   root     10056: }
1.1.1.7   root     10057: void exception3_read(uae_u32 opcode, uaecptr addr)
                   10058: {
                   10059:        exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
                   10060: }
                   10061: void exception3_write(uae_u32 opcode, uaecptr addr)
                   10062: {
                   10063:        exception3f (opcode, addr, true, 0, false, 0xffffffff, false);
                   10064: }
                   10065: void exception3i (uae_u32 opcode, uaecptr addr)
                   10066: {
                   10067:        exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
                   10068: }
                   10069: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
1.1.1.4   root     10070: {
1.1.1.7   root     10071:        exception3f (opcode, addr, w, i, false, pc, true);
1.1.1.4   root     10072: }
                   10073: 
1.1.1.10! root     10074: void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
        !          10075: {
        !          10076:        last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
        !          10077:        last_fault_for_exception_3 = addr;
        !          10078:        last_writeaccess_for_exception_3 = read == 0;
        !          10079:        last_instructionaccess_for_exception_3 = (fc & 1) == 0;
        !          10080:        last_op_for_exception_3 = regs.opcode;
        !          10081:        last_notinstruction_for_exception_3 = exception_in_exception != 0;
        !          10082: }
        !          10083: 
1.1.1.7   root     10084: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
1.1.1.4   root     10085: {
1.1.1.7   root     10086:        if (currprefs.mmu_model) {
                   10087:                if (currprefs.mmu_model == 68030) {
                   10088:                        uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
                   10089:                        mmu030_page_fault (addr, read, flags, fc);
                   10090:                } else {
1.1.1.9   root     10091:                        mmu_bus_error (addr, 0, fc, read == false, size, 0, true);
1.1.1.7   root     10092:                }
                   10093:        } else {
1.1.1.10! root     10094:                exception2_setup(addr, read, size, fc);
1.1.1.7   root     10095:                THROW(2);
                   10096:        }
1.1.1.4   root     10097: }
                   10098: 
                   10099: void cpureset (void)
                   10100: {
1.1.1.7   root     10101:     /* RESET hasn't increased PC yet, 1 word offset */
1.1.1.4   root     10102:        uaecptr pc;
1.1.1.7   root     10103: #ifndef WINUAE_FOR_HATARI
                   10104:        uaecptr ksboot = 0xf80002 - 2;
1.1.1.4   root     10105:        uae_u16 ins;
1.1.1.7   root     10106: #endif
                   10107:        addrbank *ab;
1.1.1.4   root     10108: 
1.1.1.10! root     10109: #ifndef WINUAE_FOR_HATARI
        !          10110:        if (currprefs.cpu_model == 68060 && currprefs.cpuboard_type == 0 && rtarea_base != 0xf00000) {
        !          10111:                // disable FPU at reset if no accelerator board and no $f0 ROM.
        !          10112:                regs.pcr |= 2;
        !          10113:        }
        !          10114: #endif
1.1.1.7   root     10115:        m68k_reset_delay = currprefs.reset_delay;
                   10116:        set_special(SPCFLAG_CHECK);
                   10117: #ifndef WINUAE_FOR_HATARI
                   10118:        send_internalevent(INTERNALEVENT_CPURESET);
1.1.1.8   root     10119:        if ((currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) && currprefs.cpu_model <= 68020) {
1.1.1.10! root     10120:                custom_reset_cpu (false, false);
1.1.1.4   root     10121:                return;
                   10122:        }
1.1.1.7   root     10123: #endif
                   10124:        pc = m68k_getpc () + 2;
                   10125:        ab = &get_mem_bank (pc);
                   10126:        if (ab->check (pc, 2)) {
                   10127:                write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name);
                   10128: #ifndef WINUAE_FOR_HATARI
                   10129:                ins = get_word (pc);
1.1.1.10! root     10130:                custom_reset_cpu(false, false);
1.1.1.7   root     10131:                // did memory disappear under us?
                   10132:                if (ab == &get_mem_bank (pc))
                   10133:                        return;
                   10134:                // it did
                   10135:                if ((ins & ~7) == 0x4ed0) {
                   10136:                        int reg = ins & 7;
                   10137:                        uae_u32 addr = m68k_areg (regs, reg);
                   10138:                        if (addr < 0x80000)
                   10139:                                addr += 0xf80000;
                   10140:                        write_log (_T("reset/jmp (ax) combination at %08x emulated -> %x\n"), pc, addr);
                   10141:                        m68k_setpc_normal (addr - 2);
1.1.1.4   root     10142:                        return;
                   10143:                }
1.1.1.7   root     10144: #else
                   10145:                customreset ();         /* From hatari-glue.c */
                   10146:                return;
                   10147: #endif
                   10148:        }
                   10149:        // the best we can do, jump directly to ROM entrypoint
                   10150:        // (which is probably what program wanted anyway)
                   10151: #ifndef WINUAE_FOR_HATARI
                   10152:        write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2);
1.1.1.10! root     10153:        custom_reset_cpu (false, false);
1.1.1.7   root     10154:        m68k_setpc_normal (ksboot);
                   10155: #else
                   10156:        write_log (_T("CPU Reset PC=%x (%s), invalid memory\n"), pc, ab->name);
                   10157:        customreset ();                 /* From hatari-glue.c */
                   10158: #endif
1.1.1.4   root     10159: }
                   10160: 
                   10161: 
                   10162: void m68k_setstopped (void)
                   10163: {
                   10164:        /* A traced STOP instruction drops through immediately without
                   10165:        actually stopping.  */
1.1.1.8   root     10166:        if ((regs.spcflags & SPCFLAG_DOTRACE) == 0) {
                   10167:                m68k_set_stop();
                   10168:        } else {
1.1.1.4   root     10169:                m68k_resumestopped ();
1.1.1.8   root     10170:        }
1.1.1.4   root     10171: }
                   10172: 
                   10173: void m68k_resumestopped (void)
                   10174: {
                   10175:        if (!regs.stopped)
                   10176:                return;
1.1.1.8   root     10177:        if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000) {
                   10178:                x_do_cycles (6 * cpucycleunit);
1.1.1.4   root     10179:        }
1.1.1.7   root     10180:        fill_prefetch ();
1.1.1.8   root     10181:        m68k_unset_stop();
                   10182: }
                   10183: 
                   10184: 
                   10185: uae_u32 mem_access_delay_word_read (uaecptr addr)
                   10186: {
                   10187:        uae_u32 v;
                   10188: //#ifndef WINUAE_FOR_HATARI
1.1.1.9   root     10189:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     10190: #if 1
                   10191:        switch (ce_banktype[addr >> 16])
                   10192:        {
                   10193:        case CE_MEMBANK_CHIP16:
                   10194:        case CE_MEMBANK_CHIP32:
                   10195:                v = wait_cpu_cycle_read (addr, 1);
                   10196:                break;
                   10197:        case CE_MEMBANK_FAST16:
                   10198:        case CE_MEMBANK_FAST32:
                   10199:                v = get_word (addr);
                   10200:                x_do_cycles_post (4 * cpucycleunit, v);
                   10201:                break;
                   10202:        default:
                   10203:                v = get_word (addr);
                   10204:                break;
                   10205:        }
                   10206: #else
                   10207: //fprintf ( stderr , "word read mis %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   10208:        v = get_word (addr);
                   10209:        x_do_cycles_post (4 * cpucycleunit, v);
                   10210: #endif
                   10211:        regs.db = v;
1.1.1.9   root     10212:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 );         // WINUAE_FOR_HATARI
1.1.1.8   root     10213:        return v;
                   10214: }
                   10215: uae_u32 mem_access_delay_wordi_read (uaecptr addr)
                   10216: {
                   10217:        uae_u32 v;
                   10218: //#ifndef WINUAE_FOR_HATARI
1.1.1.9   root     10219:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     10220: #if 1
                   10221:        switch (ce_banktype[addr >> 16])
                   10222:        {
                   10223:        case CE_MEMBANK_CHIP16:
                   10224:        case CE_MEMBANK_CHIP32:
                   10225:                v = wait_cpu_cycle_read (addr, 2);
                   10226:                break;
                   10227:        case CE_MEMBANK_FAST16:
                   10228:        case CE_MEMBANK_FAST32:
                   10229:                v = get_wordi (addr);
                   10230:                x_do_cycles_post (4 * cpucycleunit, v);
                   10231:                break;
                   10232:        default:
                   10233:                v = get_wordi (addr);
                   10234:                break;
                   10235:        }
                   10236: #else
                   10237: //fprintf ( stderr , "wordi read mis %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   10238:        v = get_wordi (addr);
                   10239:        x_do_cycles_post (4 * cpucycleunit, v);
                   10240: #endif
                   10241:        regs.db = v;
1.1.1.9   root     10242:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 );         // WINUAE_FOR_HATARI
1.1.1.8   root     10243:        return v;
                   10244: }
                   10245: 
                   10246: uae_u32 mem_access_delay_byte_read (uaecptr addr)
                   10247: {
                   10248:        uae_u32  v;
                   10249: //#ifndef WINUAE_FOR_HATARI
1.1.1.9   root     10250:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     10251: #if 1
                   10252:        switch (ce_banktype[addr >> 16])
                   10253:        {
                   10254:        case CE_MEMBANK_CHIP16:
                   10255:        case CE_MEMBANK_CHIP32:
                   10256:                v = wait_cpu_cycle_read (addr, 0);
                   10257:                break;
                   10258:        case CE_MEMBANK_FAST16:
                   10259:        case CE_MEMBANK_FAST32:
                   10260:                v = get_byte (addr);
                   10261:                x_do_cycles_post (4 * cpucycleunit, v);
                   10262:                break;
                   10263:        default:
                   10264:                v = get_byte (addr);
                   10265:                break;
                   10266:        }
                   10267: #else
                   10268: //fprintf ( stderr , "byte read mis %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   10269:        v = get_byte (addr);
                   10270:        x_do_cycles_post (4 * cpucycleunit, v);
                   10271: #endif
                   10272:        regs.db = (v << 8) | v;
1.1.1.9   root     10273:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 );         // WINUAE_FOR_HATARI
1.1.1.8   root     10274:        return v;
                   10275: }
                   10276: void mem_access_delay_byte_write (uaecptr addr, uae_u32 v)
                   10277: {
                   10278:        regs.db = (v << 8)  | v;
                   10279: //#ifndef WINUAE_FOR_HATARI
1.1.1.9   root     10280:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     10281: #if 1
                   10282:        switch (ce_banktype[addr >> 16])
                   10283:        {
                   10284:        case CE_MEMBANK_CHIP16:
                   10285:        case CE_MEMBANK_CHIP32:
                   10286:                wait_cpu_cycle_write (addr, 0, v);
1.1.1.9   root     10287:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     10288:                return;
                   10289:        case CE_MEMBANK_FAST16:
                   10290:        case CE_MEMBANK_FAST32:
                   10291:                put_byte (addr, v);
                   10292:                x_do_cycles_post (4 * cpucycleunit, v);
1.1.1.9   root     10293:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     10294:                return;
                   10295:        }
                   10296:        put_byte (addr, v);
                   10297: #else
                   10298:        put_byte (addr, v);
                   10299:        x_do_cycles_post (4 * cpucycleunit, v);
                   10300: #endif
                   10301: }
                   10302: void mem_access_delay_word_write (uaecptr addr, uae_u32 v)
                   10303: {
                   10304: //#ifndef WINUAE_FOR_HATARI
1.1.1.9   root     10305:        if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_before ( 1 );        // WINUAE_FOR_HATARI
1.1.1.8   root     10306: #if 1
                   10307:        regs.db = v;
                   10308:        switch (ce_banktype[addr >> 16])
                   10309:        {
                   10310:        case CE_MEMBANK_CHIP16:
                   10311:        case CE_MEMBANK_CHIP32:
                   10312:                wait_cpu_cycle_write (addr, 1, v);
1.1.1.9   root     10313:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     10314:                return;
                   10315:        case CE_MEMBANK_FAST16:
                   10316:        case CE_MEMBANK_FAST32:
                   10317:                put_word (addr, v);
                   10318:                x_do_cycles_post (4 * cpucycleunit, v);
1.1.1.9   root     10319:                if ( BlitterPhase )     Blitter_HOG_CPU_mem_access_after ( 1 ); // WINUAE_FOR_HATARI
1.1.1.8   root     10320:                return;
                   10321:        }
                   10322:        put_word (addr, v);
                   10323: #else
                   10324:        put_word (addr, v);
                   10325:        x_do_cycles_post (4 * cpucycleunit, v);
                   10326: #endif
1.1.1.4   root     10327: }
                   10328: 
1.1.1.9   root     10329: static void start_020_cycle(void)
                   10330: {
                   10331:        regs.ce020startcycle = get_cycles();
                   10332: }
                   10333: 
                   10334: static void start_020_cycle_prefetch(bool opcode)
                   10335: {
                   10336:        regs.ce020startcycle = get_cycles();
                   10337:        // back to back prefetch cycles require 2 extra cycles (maybe)
                   10338:        if (opcode && regs.ce020startcycle == regs.ce020prefetchendcycle && currprefs.cpu_cycle_exact) {
                   10339:                x_do_cycles(2 * cpucycleunit);
                   10340:                regs.ce020startcycle = get_cycles();
                   10341:        }
                   10342: }
                   10343: static void end_020_cycle(void)
                   10344: {
                   10345:        regs.ce020endcycle = get_cycles();
                   10346: }
                   10347: static void end_020_cycle_prefetch(bool opcode)
                   10348: {
                   10349:        regs.ce020endcycle = get_cycles();
                   10350:        if (opcode) {
                   10351:                regs.ce020prefetchendcycle = regs.ce020endcycle;
                   10352:        } else {
                   10353:                regs.ce020prefetchendcycle = regs.ce020startcycle;
                   10354:        }
                   10355: }
1.1.1.8   root     10356: 
1.1.1.4   root     10357: // this one is really simple and easy
1.1.1.9   root     10358: static void fill_icache020 (uae_u32 addr, bool opcode)
1.1.1.4   root     10359: {
                   10360:        int index;
                   10361:        uae_u32 tag;
                   10362:        uae_u32 data;
                   10363:        struct cache020 *c;
                   10364: 
1.1.1.9   root     10365:        regs.fc030 = (regs.s ? 4 : 0) | 2;
1.1.1.4   root     10366:        addr &= ~3;
1.1.1.7   root     10367:        if (regs.cacheholdingaddr020 == addr)
                   10368:                return;
1.1.1.4   root     10369:        index = (addr >> 2) & (CACHELINES020 - 1);
                   10370:        tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
                   10371:        c = &caches020[index];
1.1.1.9   root     10372:        if ((regs.cacr & 1) && c->valid && c->tag == tag) {
1.1.1.4   root     10373:                // cache hit
1.1.1.7   root     10374:                regs.cacheholdingaddr020 = addr;
                   10375:                regs.cacheholdingdata020 = c->data;
1.1.1.9   root     10376:                regs.cacheholdingdata_valid = true;
1.1.1.7   root     10377: #ifdef WINUAE_FOR_HATARI
                   10378:                CpuInstruction.I_Cache_hit++;
                   10379: #endif
1.1.1.4   root     10380:                return;
                   10381:        }
1.1.1.9   root     10382: 
1.1.1.4   root     10383:        // cache miss
1.1.1.9   root     10384: #if 0
1.1.1.7   root     10385:        // Prefetch apparently can be queued by bus controller
                   10386:        // even if bus controller is currently processing
                   10387:        // previous data access.
                   10388:        // Other combinations are not possible.
1.1.1.9   root     10389:        if (!regs.ce020memcycle_data) {
                   10390:                if (regs.ce020memcycles > 0)
                   10391:                        x_do_cycles (regs.ce020memcycles);
1.1.1.7   root     10392:                regs.ce020memcycles = 0;
1.1.1.9   root     10393:        }
                   10394: #endif
                   10395: 
                   10396:        start_020_cycle_prefetch(opcode);
                   10397:        data = icache_fetch(addr);
                   10398:        end_020_cycle_prefetch(opcode);
                   10399: 
                   10400:        // enabled and not frozen
                   10401:        if ((regs.cacr & 1) && !(regs.cacr & 2)) {
1.1.1.4   root     10402:                c->tag = tag;
1.1.1.9   root     10403:                c->valid = true;
1.1.1.4   root     10404:                c->data = data;
                   10405:        }
1.1.1.7   root     10406:        regs.cacheholdingaddr020 = addr;
                   10407:        regs.cacheholdingdata020 = data;
1.1.1.9   root     10408:        regs.cacheholdingdata_valid = true;
1.1.1.7   root     10409: #ifdef WINUAE_FOR_HATARI
                   10410:        CpuInstruction.I_Cache_miss++;
                   10411: #endif
1.1.1.4   root     10412: }
                   10413: 
1.1.1.7   root     10414: #if MORE_ACCURATE_68020_PIPELINE
                   10415: #define PIPELINE_DEBUG 0
                   10416: #if PIPELINE_DEBUG
                   10417: static uae_u16 pipeline_opcode;
                   10418: #endif
1.1.1.9   root     10419: static void pipeline_020(uaecptr pc)
1.1.1.4   root     10420: {
1.1.1.9   root     10421:        uae_u16 w = regs.prefetch020[1];
                   10422:        if (regs.prefetch020_valid[1] == 0) {
                   10423:                regs.pipeline_stop = -1;
                   10424:                return;
                   10425:        }
1.1.1.7   root     10426:        if (regs.pipeline_pos < 0)
                   10427:                return;
                   10428:        if (regs.pipeline_pos > 0) {
                   10429:                // handle annoying 68020+ addressing modes
                   10430:                if (regs.pipeline_pos == regs.pipeline_r8[0]) {
                   10431:                        regs.pipeline_r8[0] = 0;
                   10432:                        if (w & 0x100) {
                   10433:                                int extra = 0;
                   10434:                                if ((w & 0x30) == 0x20)
                   10435:                                        extra += 2;
                   10436:                                if ((w & 0x30) == 0x30)
                   10437:                                        extra += 4;
                   10438:                                if ((w & 0x03) == 0x02)
                   10439:                                        extra += 2;
                   10440:                                if ((w & 0x03) == 0x03)
                   10441:                                        extra += 4;
                   10442:                                regs.pipeline_pos += extra;
                   10443:                        }
                   10444:                        return;
                   10445:                }
                   10446:                if (regs.pipeline_pos == regs.pipeline_r8[1]) {
                   10447:                        regs.pipeline_r8[1] = 0;
                   10448:                        if (w & 0x100) {
                   10449:                                int extra = 0;
                   10450:                                if ((w & 0x30) == 0x20)
                   10451:                                        extra += 2;
                   10452:                                if ((w & 0x30) == 0x30)
                   10453:                                        extra += 4;
                   10454:                                if ((w & 0x03) == 0x02)
                   10455:                                        extra += 2;
                   10456:                                if ((w & 0x03) == 0x03)
                   10457:                                        extra += 4;
                   10458:                                regs.pipeline_pos += extra;
1.1.1.4   root     10459:                        }
1.1.1.7   root     10460:                        return;
                   10461:                }
                   10462:        }
                   10463:        if (regs.pipeline_pos > 2) {
                   10464:                regs.pipeline_pos -= 2;
                   10465:                // If stop set, prefetches stop 1 word early.
                   10466:                if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2)
                   10467:                        regs.pipeline_stop = -1;
                   10468:                return;
                   10469:        }
                   10470:        if (regs.pipeline_stop) {
                   10471:                regs.pipeline_stop = -1;
                   10472:                return;
                   10473:        }
                   10474: #if PIPELINE_DEBUG
                   10475:        pipeline_opcode = w;
                   10476: #endif
                   10477:        regs.pipeline_r8[0] = cpudatatbl[w].disp020[0];
                   10478:        regs.pipeline_r8[1] = cpudatatbl[w].disp020[1];
                   10479:        regs.pipeline_pos = cpudatatbl[w].length;
                   10480: #if PIPELINE_DEBUG
                   10481:        if (!regs.pipeline_pos) {
                   10482:                write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
                   10483:        }
                   10484: #endif
1.1.1.8   root     10485:        // illegal instructions, TRAP, TRAPV, A-line, F-line don't stop prefetches
1.1.1.7   root     10486:        int branch = cpudatatbl[w].branch;
                   10487:        if (regs.pipeline_pos > 0 && branch) {
                   10488:                // Short branches (Bcc.s) still do one more prefetch.
                   10489: #if 0
                   10490:                // RTS and other unconditional single opcode instruction stop immediately.
                   10491:                if (branch == 2) {
                   10492:                        // Immediate stop
                   10493:                        regs.pipeline_stop = -1;
                   10494:                } else {
                   10495:                        // Stop 1 word early than normally
                   10496:                        regs.pipeline_stop = 1;
1.1.1.4   root     10497:                }
1.1.1.7   root     10498: #else
                   10499:                regs.pipeline_stop = 1;
                   10500: #endif
1.1.1.4   root     10501:        }
                   10502: }
                   10503: 
1.1.1.7   root     10504: #endif
1.1.1.4   root     10505: 
1.1.1.9   root     10506: static uae_u32 get_word_ce020_prefetch_2 (int o, bool opcode)
1.1.1.4   root     10507: {
1.1.1.7   root     10508:        uae_u32 pc = m68k_getpc () + o;
                   10509:        uae_u32 v;
1.1.1.4   root     10510: 
1.1.1.9   root     10511:        v = regs.prefetch020[0];
                   10512:        regs.prefetch020[0] = regs.prefetch020[1];
                   10513:        regs.prefetch020[1] = regs.prefetch020[2];
1.1.1.7   root     10514: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9   root     10515:        pipeline_020(pc);
1.1.1.7   root     10516: #endif
1.1.1.9   root     10517:        if (pc & 2) {
1.1.1.7   root     10518:                // branch instruction detected in pipeline: stop fetches until branch executed.
                   10519:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
1.1.1.9   root     10520:                        fill_icache020 (pc + 2 + 4, opcode);
1.1.1.4   root     10521:                }
1.1.1.9   root     10522:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     10523:        } else {
1.1.1.9   root     10524:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.4   root     10525:        }
1.1.1.7   root     10526:        do_cycles_ce020_internal (2);
1.1.1.9   root     10527:        regs.db = regs.prefetch020[0];
1.1.1.7   root     10528:        return v;
1.1.1.4   root     10529: }
                   10530: 
1.1.1.9   root     10531: uae_u32 get_word_ce020_prefetch (int o)
                   10532: {
                   10533:        return get_word_ce020_prefetch_2(o, false);
                   10534: }
                   10535: 
                   10536: uae_u32 get_word_ce020_prefetch_opcode (int o)
                   10537: {
                   10538:        return get_word_ce020_prefetch_2(o, true);
                   10539: }
                   10540: 
1.1.1.7   root     10541: uae_u32 get_word_020_prefetch (int o)
1.1.1.4   root     10542: {
1.1.1.7   root     10543:        uae_u32 pc = m68k_getpc () + o;
                   10544:        uae_u32 v;
1.1.1.4   root     10545: 
1.1.1.9   root     10546:        v = regs.prefetch020[0];
                   10547:        regs.prefetch020[0] = regs.prefetch020[1];
                   10548:        regs.prefetch020[1] = regs.prefetch020[2];
1.1.1.7   root     10549: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9   root     10550:        pipeline_020(pc);
1.1.1.7   root     10551: #endif
1.1.1.9   root     10552:        if (pc & 2) {
                   10553:                // branch instruction detected in pipeline: stop fetches until branch executed.
1.1.1.7   root     10554:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
1.1.1.9   root     10555:                        fill_icache020 (pc + 2 + 4, false);
1.1.1.7   root     10556:                }
1.1.1.9   root     10557:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     10558:        } else {
1.1.1.9   root     10559:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.7   root     10560:        }
1.1.1.9   root     10561:        regs.db = regs.prefetch020[0];
1.1.1.7   root     10562: //if ( ( v & 0xffff ) != ( get_word(pc) & 0xffff ) )
                   10563: //  fprintf ( stderr , "prefetch mismatch pc=%x prefetch=%x != mem=%x, i-cache error ?\n" , pc , v&0xffff , get_word(pc)&0xffff );
                   10564:        return v;
                   10565: }
1.1.1.4   root     10566: 
1.1.1.7   root     10567: // these are also used by 68030.
1.1.1.4   root     10568: 
1.1.1.9   root     10569: #if 0
1.1.1.7   root     10570: #define RESET_CE020_CYCLES \
                   10571:        regs.ce020memcycles = 0; \
                   10572:        regs.ce020memcycle_data = true;
                   10573: #define STORE_CE020_CYCLES \
                   10574:        unsigned long cycs = get_cycles ()
                   10575: #define ADD_CE020_CYCLES \
                   10576:        regs.ce020memcycles += get_cycles () - cycs
1.1.1.9   root     10577: #endif
1.1.1.4   root     10578: 
1.1.1.7   root     10579: uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
                   10580: {
                   10581:        uae_u32 v;
1.1.1.9   root     10582: //fprintf ( stderr , "long read ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   10583:        start_020_cycle();
1.1.1.7   root     10584:        switch (ce_banktype[addr >> 16])
                   10585:        {
                   10586:        case CE_MEMBANK_CHIP16:
                   10587:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   10588:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   10589:                break;
                   10590:        case CE_MEMBANK_CHIP32:
                   10591:                if ((addr & 3) != 0) {
                   10592:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   10593:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   10594:                } else {
                   10595:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
                   10596:                }
                   10597:                break;
                   10598:        case CE_MEMBANK_FAST32:
                   10599:                v = get_long (addr);
                   10600:                if ((addr & 3) != 0)
                   10601:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10602:                else
                   10603:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10604:                break;
                   10605:        case CE_MEMBANK_FAST16:
                   10606:                v = get_long (addr);
                   10607:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10608:                break;
                   10609:        default:
                   10610:                v = get_long (addr);
                   10611:                break;
                   10612:        }
1.1.1.9   root     10613: //fprintf ( stderr , "long read2 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
                   10614:        end_020_cycle();
                   10615: //fprintf ( stderr , "long read3 ce020 %lu %lu\n" , currcycle / cpucycleunit , currcycle );
1.1.1.7   root     10616:        return v;
                   10617: }
                   10618: 
                   10619: uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
                   10620: {
                   10621:        uae_u32 v;
                   10622:        switch (ce_banktype[addr >> 16])
                   10623:        {
                   10624:        case CE_MEMBANK_CHIP16:
1.1.1.8   root     10625:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 2) << 16;
                   10626:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 2) <<  0;
1.1.1.7   root     10627:                break;
                   10628:        case CE_MEMBANK_CHIP32:
                   10629:                if ((addr & 3) != 0) {
1.1.1.8   root     10630:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 2) << 16;
                   10631:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 2) <<  0;
1.1.1.7   root     10632:                } else {
1.1.1.8   root     10633:                        v = wait_cpu_cycle_read_ce020 (addr, -2);
1.1.1.7   root     10634:                }
                   10635:                break;
                   10636:        case CE_MEMBANK_FAST32:
                   10637:                v = get_longi (addr);
                   10638:                if ((addr & 3) != 0)
                   10639:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10640:                else
                   10641:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10642:                break;
                   10643:        case CE_MEMBANK_FAST16:
                   10644:                v = get_longi (addr);
                   10645:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10646:                break;
                   10647:        default:
                   10648:                v = get_longi (addr);
                   10649:                break;
                   10650:        }
                   10651:        return v;
                   10652: }
                   10653: 
1.1.1.9   root     10654: uae_u32 mem_access_delay_wordi_read_ce020 (uaecptr addr)
                   10655: {
                   10656:        uae_u32 v;
                   10657:        start_020_cycle();
                   10658:        switch (ce_banktype[addr >> 16])
                   10659:        {
                   10660:        case CE_MEMBANK_CHIP16:
                   10661:        case CE_MEMBANK_CHIP32:
                   10662:                if ((addr & 3) == 3) {
                   10663:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
                   10664:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
                   10665:                } else {
                   10666:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
                   10667:                }
                   10668:                break;
                   10669:        case CE_MEMBANK_FAST16:
                   10670:        case CE_MEMBANK_FAST32:
                   10671:                v = get_wordi (addr);
                   10672:                if ((addr & 3) == 3)
                   10673:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10674:                else
                   10675:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10676:                 break;
                   10677:        default:
                   10678:                 v = get_wordi (addr);
                   10679:                break;
                   10680:        }
                   10681:        end_020_cycle();
                   10682:        return v;
                   10683: }
                   10684: 
1.1.1.7   root     10685: uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
                   10686: {
                   10687:        uae_u32 v;
1.1.1.9   root     10688:        start_020_cycle();
1.1.1.7   root     10689:        switch (ce_banktype[addr >> 16])
                   10690:        {
                   10691:        case CE_MEMBANK_CHIP16:
                   10692:        case CE_MEMBANK_CHIP32:
                   10693:                if ((addr & 3) == 3) {
                   10694:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
                   10695:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
                   10696:                } else {
                   10697:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
                   10698:                }
                   10699:                break;
                   10700:        case CE_MEMBANK_FAST16:
                   10701:        case CE_MEMBANK_FAST32:
                   10702:                v = get_word (addr);
                   10703:                if ((addr & 3) == 3)
                   10704:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10705:                else
                   10706:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10707:                 break;
                   10708:        default:
                   10709:                 v = get_word (addr);
                   10710:                break;
                   10711:        }
1.1.1.9   root     10712:        end_020_cycle();
1.1.1.7   root     10713:        return v;
                   10714: }
                   10715: 
                   10716: uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
                   10717: {
                   10718:        uae_u32 v;
1.1.1.9   root     10719:        start_020_cycle();
1.1.1.7   root     10720:        switch (ce_banktype[addr >> 16])
                   10721:        {
                   10722:        case CE_MEMBANK_CHIP16:
                   10723:        case CE_MEMBANK_CHIP32:
                   10724:                v = wait_cpu_cycle_read_ce020 (addr, 0);
                   10725:                break;
                   10726:        case CE_MEMBANK_FAST16:
                   10727:        case CE_MEMBANK_FAST32:
                   10728:                v = get_byte (addr);
                   10729:                do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10730:                break;
                   10731:        default:
                   10732:                v = get_byte (addr);
                   10733:                break;
                   10734:        }
1.1.1.9   root     10735:        end_020_cycle();
1.1.1.7   root     10736:        return v;
                   10737: }
                   10738: 
                   10739: void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
                   10740: {
1.1.1.9   root     10741:        start_020_cycle();
1.1.1.7   root     10742:        switch (ce_banktype[addr >> 16])
                   10743:        {
                   10744:        case CE_MEMBANK_CHIP16:
                   10745:        case CE_MEMBANK_CHIP32:
                   10746:                wait_cpu_cycle_write_ce020 (addr, 0, v);
                   10747:                break;
                   10748:        case CE_MEMBANK_FAST16:
                   10749:        case CE_MEMBANK_FAST32:
                   10750:                put_byte (addr, v);
                   10751:                do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10752:                break;
                   10753:        default:
                   10754:                put_byte (addr, v);
                   10755:        break;
1.1.1.4   root     10756:        }
1.1.1.9   root     10757:        end_020_cycle();
1.1.1.7   root     10758: }
                   10759: 
                   10760: void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
                   10761: {
1.1.1.9   root     10762:        start_020_cycle();
1.1.1.7   root     10763:        switch (ce_banktype[addr >> 16])
                   10764:        {
                   10765:        case CE_MEMBANK_CHIP16:
                   10766:        case CE_MEMBANK_CHIP32:
                   10767:                if ((addr & 3) == 3) {
                   10768:                        wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
                   10769:                        wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
                   10770:                } else {
                   10771:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
                   10772:                }
                   10773:                break;
                   10774:        case CE_MEMBANK_FAST16:
                   10775:        case CE_MEMBANK_FAST32:
                   10776:                put_word (addr, v);
                   10777:                if ((addr & 3) == 3)
                   10778:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10779:                else
                   10780:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10781:                break;
                   10782:        default:
                   10783:                put_word (addr, v);
                   10784:        break;
                   10785:        }
1.1.1.9   root     10786:        end_020_cycle();
1.1.1.7   root     10787: }
                   10788: 
                   10789: void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
                   10790: {
1.1.1.9   root     10791:        start_020_cycle();
1.1.1.7   root     10792:        switch (ce_banktype[addr >> 16])
                   10793:        {
                   10794:        case CE_MEMBANK_CHIP16:
                   10795:                wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
                   10796:                wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
                   10797:                break;
                   10798:        case CE_MEMBANK_CHIP32:
                   10799:                if ((addr & 3) == 3) {
                   10800:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
                   10801:                        wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
                   10802:                } else {
                   10803:                        wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
                   10804:                }
                   10805:                break;
                   10806:        case CE_MEMBANK_FAST32:
                   10807:                put_long (addr, v);
                   10808:                if ((addr & 3) != 0)
                   10809:                        do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10810:                else
                   10811:                        do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
                   10812:                break;
                   10813:        case CE_MEMBANK_FAST16:
                   10814:                put_long (addr, v);
                   10815:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   10816:                break;
                   10817:        default:
                   10818:                put_long (addr, v);
                   10819:                break;
                   10820:        }
1.1.1.9   root     10821:        end_020_cycle();
1.1.1.7   root     10822: }
                   10823: 
                   10824: 
                   10825: // 68030 caches aren't so simple as 68020 cache..
1.1.1.10! root     10826: 
1.1.1.9   root     10827: STATIC_INLINE struct cache030 *geticache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
1.1.1.7   root     10828: {
                   10829:        int index, lws;
                   10830:        uae_u32 tag;
                   10831:        struct cache030 *c;
                   10832: 
                   10833:        addr &= ~3;
                   10834:        index = (addr >> 4) & (CACHELINES030 - 1);
                   10835:        tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
                   10836:        lws = (addr >> 2) & 3;
                   10837:        c = &cp[index];
                   10838:        *tagp = tag;
                   10839:        *lwsp = lws;
1.1.1.9   root     10840: //fprintf ( stderr , "getcache addr=%x index=%x tag=%x lws=%x\n" , addr , index , tag , lws );
                   10841:        return c;
                   10842: }
                   10843: 
                   10844: STATIC_INLINE void update_icache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
                   10845: {
                   10846:        if (c->tag != tag)
                   10847:                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
                   10848:        c->tag = tag;
                   10849:        c->valid[lws] = true;
                   10850:        c->data[lws] = val;
                   10851: }
                   10852: 
                   10853: STATIC_INLINE struct cache030 *getdcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
                   10854: {
                   10855:        int index, lws;
                   10856:        uae_u32 tag;
                   10857:        struct cache030 *c;
                   10858: 
                   10859:        addr &= ~3;
                   10860:        index = (addr >> 4) & (CACHELINES030 - 1);
                   10861:        tag = addr & ~((CACHELINES030 << 4) - 1);
                   10862:        lws = (addr >> 2) & 3;
                   10863:        c = &cp[index];
                   10864:        *tagp = tag;
                   10865:        *lwsp = lws;
1.1.1.7   root     10866:        return c;
                   10867: }
                   10868: 
1.1.1.9   root     10869: STATIC_INLINE void update_dcache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, uae_u8 fc, int lws)
1.1.1.7   root     10870: {
                   10871:        if (c->tag != tag)
                   10872:                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
                   10873:        c->tag = tag;
1.1.1.9   root     10874:        c->fc = fc;
1.1.1.7   root     10875:        c->valid[lws] = true;
                   10876:        c->data[lws] = val;
                   10877: }
                   10878: 
                   10879: static void fill_icache030 (uae_u32 addr)
                   10880: {
                   10881:        int lws;
                   10882:        uae_u32 tag;
                   10883:        uae_u32 data;
                   10884:        struct cache030 *c;
1.1.1.9   root     10885: //fprintf ( stderr , "fill icache030 %x %x %x\n" , addr , regs.cacr , regs.cacheholdingaddr020 );
1.1.1.7   root     10886: 
1.1.1.9   root     10887:        regs.fc030 = (regs.s ? 4 : 0) | 2;
1.1.1.7   root     10888:        addr &= ~3;
1.1.1.9   root     10889:        if (regs.cacheholdingaddr020 == addr || regs.cacheholdingdata_valid == 0)
1.1.1.7   root     10890:                return;
1.1.1.9   root     10891:        c = geticache030 (icaches030, addr, &tag, &lws);
                   10892:        if ((regs.cacr & 1) && c->valid[lws] && c->tag == tag) {
1.1.1.7   root     10893:                // cache hit
                   10894:                regs.cacheholdingaddr020 = addr;
                   10895:                regs.cacheholdingdata020 = c->data[lws];
1.1.1.9   root     10896: //fprintf ( stderr , "fill ica %x -> hit %x %x\n" , addr , regs.cacheholdingdata020 , regs.cacr );
1.1.1.7   root     10897: #ifdef WINUAE_FOR_HATARI
                   10898:                CpuInstruction.I_Cache_hit++;
1.1.1.4   root     10899: #endif
1.1.1.7   root     10900:                return;
                   10901:        }
                   10902: 
1.1.1.9   root     10903:        TRY (prb2) {
                   10904:                // cache miss
                   10905:                if (currprefs.cpu_cycle_exact) {
                   10906:                        regs.ce020memcycle_data = false;
                   10907:                        start_020_cycle_prefetch(false);
                   10908:                        data = icache_fetch(addr);
                   10909:                        end_020_cycle_prefetch(false);
                   10910:                } else {
                   10911:                        data = icache_fetch(addr);
                   10912:                }
                   10913:        } CATCH (prb2) {
                   10914:                // Bus error/MMU access fault: Delayed exception.
                   10915:                regs.cacheholdingdata_valid = 0;
                   10916:                regs.cacheholdingaddr020 = 0xffffffff;
                   10917:                regs.cacheholdingdata020 = 0xffffffff;
                   10918:                end_020_cycle_prefetch(false);
1.1.1.10! root     10919:                STOPTRY;
1.1.1.9   root     10920:                return;
                   10921:        } ENDTRY
                   10922: 
                   10923:        if (mmu030_cache_state & CACHE_ENABLE_INS) {
                   10924:                if ((regs.cacr & 0x03) == 0x01) {
                   10925:                        // instruction cache not frozen and enabled
1.1.1.7   root     10926: //fprintf ( stderr , "fill ica %x -> update %x\n" , addr , data );
1.1.1.9   root     10927:                        update_icache030 (c, data, tag, lws);
                   10928:                }
                   10929:                if ((mmu030_cache_state & CACHE_ENABLE_INS_BURST) && (regs.cacr & 0x11) == 0x11 && (c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1)) {
1.1.1.7   root     10930: //fprintf ( stderr , "fill ica %x -> burst %x\n" , addr , data );
1.1.1.9   root     10931:                        // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
                   10932:                        int i;
                   10933:                        for (i = 0; i < 4; i++) {
                   10934:                                if (c->valid[i])
                   10935:                                        break;
                   10936:                        }
                   10937:                        uaecptr baddr = addr & ~15;
                   10938:                        if (currprefs.mmu_model) {
                   10939:                                TRY (prb) {
                   10940:                                        if (currprefs.cpu_cycle_exact)
                   10941: #ifndef WINUAE_FOR_HATARI
                   10942:                                                do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1));
                   10943: #else
                   10944:                                                do_cycles_ce020_long(3 * (CPU020_MEM_CYCLE - 1));
                   10945: #endif
1.1.1.10! root     10946:                                        for (int j = 0; j < 3; j++) {
1.1.1.9   root     10947:                                                i++;
                   10948:                                                i &= 3;
                   10949:                                                c->data[i] = icache_fetch(baddr + i * 4);
                   10950:                                                c->valid[i] = true;
                   10951:                                        }
                   10952:                                } CATCH (prb) {
                   10953:                                        ; // abort burst fetch if bus error, do not report it.
                   10954:                                } ENDTRY
                   10955:                        } else {
1.1.1.10! root     10956:                                for (int j = 0; j < 3; j++) {
1.1.1.9   root     10957:                                        i++;
                   10958:                                        i &= 3;
                   10959:                                        c->data[i] = icache_fetch(baddr + i * 4);
                   10960:                                        c->valid[i] = true;
                   10961:                                }
                   10962:                                if (currprefs.cpu_cycle_exact)
                   10963:                                        do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
                   10964:                        }
                   10965:                }
1.1.1.7   root     10966:        }
                   10967:        regs.cacheholdingaddr020 = addr;
                   10968:        regs.cacheholdingdata020 = data;
                   10969: //fprintf ( stderr , "fill ica %x -> miss %x\n" , addr , regs.cacheholdingdata020 );
                   10970: #ifdef WINUAE_FOR_HATARI
                   10971:        CpuInstruction.I_Cache_miss++;
                   10972: #endif
                   10973: }
                   10974: 
1.1.1.9   root     10975: #if VALIDATE_68030_DATACACHE
                   10976: static void validate_dcache030(void)
1.1.1.7   root     10977: {
1.1.1.10! root     10978:        for (int i = 0; i < CACHELINES030; i++) {
1.1.1.9   root     10979:                struct cache030 *c = &dcaches030[i];
                   10980:                uae_u32 addr = c->tag & ~((CACHELINES030 << 4) - 1);
                   10981:                addr |= i << 4;
1.1.1.10! root     10982:                for (int j = 0; j < 4; j++) {
1.1.1.9   root     10983:                        if (c->valid[j]) {
                   10984:                                uae_u32 v = get_long(addr);
                   10985:                                if (v != c->data[j]) {
                   10986:                                        write_log(_T("Address %08x data cache mismatch %08x != %08x\n"), addr, v, c->data[j]);
                   10987:                                }
                   10988:                        }
                   10989:                        addr += 4;
                   10990:                }
                   10991:        }
1.1.1.7   root     10992: }
                   10993: 
1.1.1.9   root     10994: static void validate_dcache030_read(uae_u32 addr, uae_u32 ov, int size)
1.1.1.7   root     10995: {
1.1.1.9   root     10996:        uae_u32 ov2;
                   10997:        if (size == 2) {
                   10998:                ov2 = get_long(addr);
                   10999:        } else if (size == 1) {
                   11000:                ov2 = get_word(addr);
                   11001:                ov &= 0xffff;
                   11002:        } else {
                   11003:                ov2 = get_byte(addr);
                   11004:                ov &= 0xff;
1.1.1.4   root     11005:        }
1.1.1.9   root     11006:        if (ov2 != ov) {
                   11007:                write_log(_T("Address read %08x data cache mismatch %08x != %08x\n"), addr, ov2, ov);
                   11008:        }
                   11009: }
                   11010: #endif
1.1.1.7   root     11011: 
1.1.1.9   root     11012: // and finally the worst part, 68030 data cache..
                   11013: static void write_dcache030x(uaecptr addr, uae_u32 val, uae_u32 size, uae_u32 fc)
                   11014: {
                   11015:        if (regs.cacr & 0x100) {
                   11016:                static const uae_u32 mask[3] = { 0xff000000, 0xffff0000, 0xffffffff };
                   11017:                struct cache030 *c1, *c2;
                   11018:                int lws1, lws2;
                   11019:                uae_u32 tag1, tag2;
                   11020:                int aligned = addr & 3;
                   11021:                int wa = regs.cacr & 0x2000;
                   11022:                int width = 8 << size;
                   11023:                int offset = 8 * aligned;
                   11024:                int hit;
                   11025: 
                   11026:                c1 = getdcache030(dcaches030, addr, &tag1, &lws1);
                   11027:                hit = c1->tag == tag1 && c1->fc == fc && c1->valid[lws1];
                   11028: 
                   11029:                // Write-allocate can create new valid cache entry if
                   11030:                // long aligned long write and MMU CI is not active.
                   11031:                // All writes ignore external CIIN signal.
                   11032:                // CACHE_DISABLE_ALLOCATE = emulation only method to disable WA caching completely.
                   11033: 
                   11034:                if (width == 32 && offset == 0 && wa) {
                   11035:                        if (!(mmu030_cache_state & CACHE_DISABLE_MMU) && !(mmu030_cache_state & CACHE_DISABLE_ALLOCATE)) {
                   11036:                                update_dcache030(c1, val, tag1, fc, lws1);
                   11037: //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] );
                   11038: #if VALIDATE_68030_DATACACHE
                   11039:                                validate_dcache030();
                   11040: #endif
                   11041:                        } else if (hit) {
                   11042:                                // Does real 68030 do this if MMU cache inhibited?
1.1.1.7   root     11043:                                c1->valid[lws1] = false;
1.1.1.9   root     11044:                        }
                   11045:                        return;
                   11046:                }
                   11047: 
                   11048:                if (hit || wa) {
1.1.1.7   root     11049:                        if (hit) {
1.1.1.9   root     11050:                                uae_u32 val_left_aligned = val << (32 - width);
                   11051:                                c1->data[lws1] &= ~(mask[size] >> offset);
                   11052:                                c1->data[lws1] |= val_left_aligned >> offset;
                   11053:                        } else {
1.1.1.7   root     11054:                                c1->valid[lws1] = false;
1.1.1.9   root     11055:                        }
                   11056:                }
                   11057: 
                   11058:                // do we need to update a 2nd cache entry ?
                   11059:                if (width + offset > 32) {
                   11060:                        c2 = getdcache030(dcaches030, addr + 4, &tag2, &lws2);
                   11061:                        hit = c2->tag == tag2 && c2->fc == fc && c2->valid[lws2];
                   11062:                        if (hit || wa) {
                   11063:                                if (hit) {
                   11064:                                        c2->data[lws2] &= 0xffffffff >> (width + offset - 32);
                   11065:                                        c2->data[lws2] |= val << (32 - (width + offset - 32));
                   11066:                                } else {
                   11067:                                        c2->valid[lws2] = false;
                   11068:                                }
                   11069:                        }
1.1.1.7   root     11070:                }
1.1.1.9   root     11071: #if VALIDATE_68030_DATACACHE
                   11072:                validate_dcache030();
                   11073: #endif
1.1.1.7   root     11074:        }
1.1.1.9   root     11075: }
1.1.1.7   root     11076: 
1.1.1.9   root     11077: void write_dcache030_bput(uaecptr addr, uae_u32 v,uae_u32 fc)
                   11078: {
                   11079: //fprintf ( stderr , "write dcache %x %x %d\n" , addr , v , size );
                   11080:        regs.fc030 = fc;
                   11081:        dcache_bput(addr, v);
                   11082:        write_dcache030x(addr, v, 0, fc);
                   11083: }
                   11084: void write_dcache030_wput(uaecptr addr, uae_u32 v,uae_u32 fc)
                   11085: {
                   11086:        regs.fc030 = fc;
                   11087:        dcache_wput(addr, v);
                   11088:        write_dcache030x(addr, v, 1, fc);
                   11089: }
                   11090: void write_dcache030_lput(uaecptr addr, uae_u32 v,uae_u32 fc)
                   11091: {
                   11092:        regs.fc030 = fc;
                   11093:        dcache_lput(addr, v);
                   11094:        write_dcache030x(addr, v, 2, fc);
                   11095: }
1.1.1.7   root     11096: 
1.1.1.10! root     11097: // 68030 MMU bus fault retry case, direct write, store to cache if enabled
        !          11098: void write_dcache030_retry(uaecptr addr, uae_u32 v, uae_u32 fc, int size, int flags)
        !          11099: {
        !          11100:        regs.fc030 = fc;
        !          11101:        mmu030_put_generic(addr, v, fc, size, flags);
        !          11102:        write_dcache030x(addr, v, size, fc);
        !          11103: }
        !          11104: 
1.1.1.9   root     11105: static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
                   11106: {
                   11107:        if ((c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1) && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
                   11108:                // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
                   11109:                int i;
                   11110:                uaecptr baddr = addr & ~15;
                   11111:                for (i = 0; i < 4; i++) {
                   11112:                        if (c->valid[i])
                   11113:                                break;
1.1.1.4   root     11114:                }
1.1.1.9   root     11115:                if (currprefs.mmu_model) {
                   11116:                        TRY (prb) {
                   11117:                                if (currprefs.cpu_cycle_exact)
                   11118: #ifndef WINUAE_FOR_HATARI
                   11119:                                        do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1));
                   11120: #else
                   11121:                                        do_cycles_ce020_long(3 * (CPU020_MEM_CYCLE - 1));
                   11122: #endif
1.1.1.10! root     11123:                                for (int j = 0; j < 3; j++) {
1.1.1.9   root     11124:                                        i++;
                   11125:                                        i &= 3;
                   11126:                                        c->data[i] = dcache_lget (baddr + i * 4);
                   11127:                                        c->valid[i] = true;
                   11128:                                }
                   11129:                        } CATCH (prb) {
                   11130:                                ; // abort burst fetch if bus error
                   11131:                        } ENDTRY
                   11132:                } else {
1.1.1.10! root     11133:                        for (int j = 0; j < 3; j++) {
1.1.1.9   root     11134:                                i++;
                   11135:                                i &= 3;
                   11136:                                c->data[i] = dcache_lget (baddr + i * 4);
                   11137:                                c->valid[i] = true;
                   11138:                        }
                   11139:                        if (currprefs.cpu_cycle_exact)
                   11140:                                do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[i]);
                   11141:                }
                   11142: #if VALIDATE_68030_DATACACHE
                   11143:                validate_dcache030();
                   11144: #endif
1.1.1.4   root     11145:        }
                   11146: }
                   11147: 
1.1.1.9   root     11148: static uae_u32 read_dcache030_debug(uaecptr addr, uae_u32 size, uae_u32 fc, bool *cached)
1.1.1.7   root     11149: {
1.1.1.9   root     11150:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
                   11151:        struct cache030 *c1, *c2;
                   11152:        int lws1, lws2;
                   11153:        uae_u32 tag1, tag2;
                   11154:        int aligned = addr & 3;
                   11155:        uae_u32 v1, v2;
                   11156:        int width = 8 << size;
                   11157:        int offset = 8 * aligned;
                   11158:        uae_u32 out;
                   11159: 
                   11160:        *cached = false;
                   11161:        if (!currprefs.cpu_data_cache) {
                   11162:                if (size == 0)
                   11163:                        return get_byte_debug(addr);
                   11164:                if (size == 1)
                   11165:                        return get_word_debug(addr);
                   11166:                return get_long_debug(addr);
                   11167:        }
                   11168: 
                   11169:        c1 = getdcache030(dcaches030, addr, &tag1, &lws1);
                   11170:        addr &= ~3;
                   11171:        if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) {
                   11172:                v1 = get_long_debug(addr);
1.1.1.7   root     11173:        } else {
1.1.1.9   root     11174:                // Cache hit, inhibited caching do not prevent read hits.
                   11175:                v1 = c1->data[lws1];
                   11176:                *cached = true;
                   11177:        }
                   11178: 
                   11179:        // only one long fetch needed?
                   11180:        if (width + offset <= 32) {
                   11181:                out = v1 >> (32 - (offset + width));
                   11182:                out &= mask[size];
                   11183:                return out;
                   11184:        }
                   11185: 
                   11186:        // no, need another one
                   11187:        addr += 4;
                   11188:        c2 = getdcache030(dcaches030, addr, &tag2, &lws2);
                   11189:        if (!c2->valid[lws2] || c2->tag != tag2 || c2->fc != fc) {
                   11190:                v2 = get_long_debug(addr);
                   11191:        } else {
                   11192:                v2 = c2->data[lws2];
                   11193:                *cached = true;
1.1.1.7   root     11194:        }
1.1.1.9   root     11195: 
                   11196:        uae_u64 v64 = ((uae_u64)v1 << 32) | v2;
                   11197:        out = (uae_u32)(v64 >> (64 - (offset + width)));
                   11198:        out &= mask[size];
                   11199:        return out;
1.1.1.7   root     11200: }
                   11201: 
                   11202: // [HATARI] Define next line to check for 68030 data cache mismatch after every write
                   11203: //#define WINUAE_FOR_HATARI_DEBUG_CACHE
                   11204: #ifdef WINUAE_FOR_HATARI_DEBUG_CACHE
1.1.1.10! root     11205: bool read_dcache030_2_real (uaecptr addr, uae_u32 size, uae_u32 *valp);
        !          11206: static bool read_dcache030_2 (uaecptr addr, uae_u32 size, uae_u32 *valp)
1.1.1.7   root     11207: {
1.1.1.10! root     11208:   bool b;
1.1.1.7   root     11209: 
1.1.1.10! root     11210:   b = read_dcache030_2_real ( addr , size , valp );
        !          11211:   if ( b==false)
        !          11212:     return false;
        !          11213: 
        !          11214:   if ( ( ( size==2 ) && ( *valp != get_long ( addr ) ) )
        !          11215:     || ( ( size==1 ) && ( (*valp&0xffff) != (get_word ( addr ) & 0xffff) ) )
        !          11216:     || ( ( size==0 ) && ( (*valp&0xff) != (get_byte ( addr ) & 0xff ) ) ) )
        !          11217:     fprintf ( stderr , "d-cache mismatch pc=%x addr=%x size=%d cache=%x != mem=%x, d-cache error ?\n" , m68k_getpc(), addr, size, *valp , get_long(addr) );
        !          11218:   return true;
1.1.1.7   root     11219: }
1.1.1.10! root     11220: bool read_dcache030_2_real(uaecptr addr, uae_u32 size, uae_u32 *valp)
1.1.1.7   root     11221: #else
1.1.1.10! root     11222: static bool read_dcache030_2(uaecptr addr, uae_u32 size, uae_u32 *valp)
1.1.1.7   root     11223: #endif
1.1.1.4   root     11224: {
1.1.1.10! root     11225:        // data cache enabled?
        !          11226:        if (!(regs.cacr & 0x100))
        !          11227:                return false;
        !          11228: 
1.1.1.9   root     11229:        uae_u32 addr_o = addr;
1.1.1.10! root     11230:        uae_u32 fc = regs.fc030;
        !          11231:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
        !          11232:        struct cache030 *c1, *c2;
        !          11233:        int lws1, lws2;
        !          11234:        uae_u32 tag1, tag2;
        !          11235:        int aligned = addr & 3;
        !          11236:        uae_u32 v1, v2;
        !          11237:        int width = 8 << size;
        !          11238:        int offset = 8 * aligned;
        !          11239:        uae_u32 out;
1.1.1.9   root     11240: 
1.1.1.10! root     11241:        c1 = getdcache030(dcaches030, addr, &tag1, &lws1);
        !          11242:        addr &= ~3;
        !          11243:        if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) {
        !          11244:                // MMU validate address, returns zero if valid but uncacheable
        !          11245:                // throws bus error if invalid
        !          11246:                uae_u8 cs = dcache_check(addr_o, false, size);
        !          11247:                if (!(cs & CACHE_ENABLE_DATA))
        !          11248:                        return false;
        !          11249:                v1 = dcache_lget(addr);
        !          11250:                update_dcache030(c1, v1, tag1, fc, lws1);
        !          11251:                if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100)
        !          11252:                        dcache030_maybe_burst(addr, c1, lws1);
1.1.1.9   root     11253: #if VALIDATE_68030_DATACACHE
1.1.1.10! root     11254:                validate_dcache030();
1.1.1.9   root     11255: #endif
                   11256: //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) );
                   11257: #ifdef WINUAE_FOR_HATARI
                   11258:                CpuInstruction.D_Cache_miss++;
                   11259: #endif
1.1.1.10! root     11260:        } else {
        !          11261:                // Cache hit, inhibited caching do not prevent read hits.
        !          11262:                v1 = c1->data[lws1];
1.1.1.7   root     11263: #ifdef WINUAE_FOR_HATARI
                   11264:                CpuInstruction.D_Cache_hit++;
                   11265: #endif
1.1.1.10! root     11266:        }
1.1.1.9   root     11267: 
1.1.1.10! root     11268:        // only one long fetch needed?
        !          11269:        if (width + offset <= 32) {
        !          11270:                out = v1 >> (32 - (offset + width));
        !          11271:                out &= mask[size];
1.1.1.9   root     11272: #if VALIDATE_68030_DATACACHE
1.1.1.10! root     11273:                validate_dcache030_read(addr_o, out, size);
1.1.1.9   root     11274: #endif
1.1.1.10! root     11275:                *valp = out;
        !          11276:                return true;
        !          11277:        }
1.1.1.9   root     11278: 
1.1.1.10! root     11279:        // no, need another one
        !          11280:        addr += 4;
        !          11281:        c2 = getdcache030(dcaches030, addr, &tag2, &lws2);
        !          11282:        if (!c2->valid[lws2] || c2->tag != tag2 || c2->fc != fc) {
        !          11283:                uae_u8 cs = dcache_check(addr, false, 2);
        !          11284:                if (!(cs & CACHE_ENABLE_DATA))
        !          11285:                        return false;
        !          11286:                v2 = dcache_lget(addr);
        !          11287:                update_dcache030(c2, v2, tag2, fc, lws2);
        !          11288:                if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100)
        !          11289:                        dcache030_maybe_burst(addr, c2, lws2);
1.1.1.9   root     11290: #if VALIDATE_68030_DATACACHE
1.1.1.10! root     11291:                validate_dcache030();
1.1.1.9   root     11292: #endif
1.1.1.7   root     11293: //fprintf ( stderr , "read cache %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x\n", addr, v1, size, tag1, lws1, tag2, lws2 );
                   11294: #ifdef WINUAE_FOR_HATARI
                   11295:                CpuInstruction.D_Cache_miss++;
                   11296: #endif
1.1.1.10! root     11297:        } else {
        !          11298:                v2 = c2->data[lws2];
1.1.1.9   root     11299: #ifdef WINUAE_FOR_HATARI
1.1.1.7   root     11300:                CpuInstruction.D_Cache_hit++;
                   11301: #endif
1.1.1.10! root     11302:        }
1.1.1.9   root     11303: 
1.1.1.10! root     11304:        uae_u64 v64 = ((uae_u64)v1 << 32) | v2;
        !          11305:        out = (uae_u32)(v64 >> (64 - (offset + width)));
        !          11306:        out &= mask[size];
1.1.1.9   root     11307: 
                   11308: #if VALIDATE_68030_DATACACHE
1.1.1.10! root     11309:        validate_dcache030_read(addr_o, out, size);
1.1.1.9   root     11310: #endif
1.1.1.10! root     11311:        *valp = out;
        !          11312:        return true;
        !          11313: }
        !          11314: 
        !          11315: static uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
        !          11316: {
        !          11317:        uae_u32 val;
        !          11318:        regs.fc030 = fc;
1.1.1.9   root     11319: 
1.1.1.10! root     11320:        if (!read_dcache030_2(addr, size, &val)) {
        !          11321:                // read from memory, data cache is disabled or inhibited.
        !          11322:                if (size == 2)
        !          11323:                        return dcache_lget(addr);
        !          11324:                else if (size == 1)
        !          11325:                        return dcache_wget(addr);
        !          11326:                else
        !          11327:                        return dcache_bget(addr);
1.1.1.9   root     11328:        }
1.1.1.10! root     11329:        return val;
        !          11330: }
        !          11331: 
        !          11332: // 68030 MMU bus fault retry case, either read from cache or use direct reads
        !          11333: uae_u32 read_dcache030_retry(uaecptr addr, uae_u32 fc, int size, int flags)
        !          11334: {
        !          11335:        uae_u32 val;
        !          11336:        regs.fc030 = fc;
        !          11337: 
        !          11338:        if (!read_dcache030_2(addr, size, &val)) {
        !          11339:                return mmu030_get_generic(addr, fc, size, flags);
        !          11340:        }
        !          11341:        return val;
1.1.1.9   root     11342: }
1.1.1.10! root     11343: 
1.1.1.9   root     11344: uae_u32 read_dcache030_bget(uaecptr addr, uae_u32 fc)
                   11345: {
                   11346:        return read_dcache030(addr, 0, fc);
                   11347: }
                   11348: uae_u32 read_dcache030_wget(uaecptr addr, uae_u32 fc)
                   11349: {
                   11350:        return read_dcache030(addr, 1, fc);
                   11351: }
                   11352: uae_u32 read_dcache030_lget(uaecptr addr, uae_u32 fc)
                   11353: {
                   11354:        return read_dcache030(addr, 2, fc);
                   11355: }
1.1.1.7   root     11356: 
1.1.1.9   root     11357: uae_u32 read_dcache030_mmu_bget(uaecptr addr)
                   11358: {
                   11359:        return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
                   11360: }
                   11361: uae_u32 read_dcache030_mmu_wget(uaecptr addr)
                   11362: {
                   11363:        return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
                   11364: }
                   11365: uae_u32 read_dcache030_mmu_lget(uaecptr addr)
                   11366: {
                   11367:        return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
                   11368: }
                   11369: void write_dcache030_mmu_bput(uaecptr addr, uae_u32 val)
                   11370: {
                   11371:        write_dcache030_bput(addr, val, (regs.s ? 4 : 0) | 1);
                   11372: }
                   11373: void write_dcache030_mmu_wput(uaecptr addr, uae_u32 val)
                   11374: {
                   11375:        write_dcache030_wput(addr, val, (regs.s ? 4 : 0) | 1);
                   11376: }
                   11377: void write_dcache030_mmu_lput(uaecptr addr, uae_u32 val)
                   11378: {
                   11379:        write_dcache030_lput(addr, val, (regs.s ? 4 : 0) | 1);
                   11380: }
1.1.1.4   root     11381: 
1.1.1.10! root     11382: uae_u32 read_dcache030_lrmw_mmu_fcx(uaecptr addr, uae_u32 size, int fc)
1.1.1.9   root     11383: {
                   11384:        if (currprefs.cpu_data_cache) {
                   11385:                mmu030_cache_state = CACHE_DISABLE_MMU;
                   11386:                if (size == 0)
1.1.1.10! root     11387:                        return read_dcache030_bget(addr, fc);
1.1.1.9   root     11388:                if (size == 1)
1.1.1.10! root     11389:                        return read_dcache030_wget(addr, fc);
        !          11390:                return read_dcache030_lget(addr, fc);
1.1.1.9   root     11391:        } else {
                   11392:                if (size == 0)
                   11393:                        return read_data_030_bget(addr);
                   11394:                if (size == 1)
                   11395:                        return read_data_030_wget(addr);
                   11396:                return read_data_030_lget(addr);
                   11397:        }
                   11398: }
1.1.1.10! root     11399: uae_u32 read_dcache030_lrmw_mmu(uaecptr addr, uae_u32 size)
        !          11400: {
        !          11401:        return read_dcache030_lrmw_mmu_fcx(addr, size, (regs.s ? 4 : 0) | 1);
        !          11402: }
        !          11403: void write_dcache030_lrmw_mmu_fcx(uaecptr addr, uae_u32 val, uae_u32 size, int fc)
1.1.1.9   root     11404: {
                   11405:        if (currprefs.cpu_data_cache) {
                   11406:                mmu030_cache_state = CACHE_DISABLE_MMU;
                   11407:                if (size == 0)
1.1.1.10! root     11408:                        write_dcache030_bput(addr, val, fc);
1.1.1.9   root     11409:                else if (size == 1)
1.1.1.10! root     11410:                        write_dcache030_wput(addr, val, fc);
1.1.1.9   root     11411:                else
1.1.1.10! root     11412:                        write_dcache030_lput(addr, val, fc);
1.1.1.9   root     11413:        } else {
                   11414:                if (size == 0)
                   11415:                        write_data_030_bput(addr, val);
                   11416:                else if (size == 1)
                   11417:                        write_data_030_wput(addr, val);
                   11418:                else
                   11419:                        write_data_030_lput(addr, val);
                   11420:        }
1.1.1.4   root     11421: }
1.1.1.10! root     11422: void write_dcache030_lrmw_mmu(uaecptr addr, uae_u32 val, uae_u32 size)
        !          11423: {
        !          11424:        write_dcache030_lrmw_mmu_fcx(addr, val, size, (regs.s ? 4 : 0) | 1);
        !          11425: }
1.1.1.4   root     11426: 
1.1.1.9   root     11427: static void do_access_or_bus_error(uaecptr pc, uaecptr pcnow)
                   11428: {
                   11429:        // TODO: handle external bus errors
                   11430:        if (!currprefs.mmu_model)
                   11431:                return;
                   11432:        if (pc != 0xffffffff)
                   11433:                regs.instruction_pc = pc;
                   11434:        mmu030_opcode = -1;
                   11435:        mmu030_page_fault(pcnow, true, -1, 0);
                   11436: }
                   11437: 
                   11438: static uae_u32 get_word_ce030_prefetch_2 (int o)
1.1.1.4   root     11439: {
                   11440:        uae_u32 pc = m68k_getpc () + o;
1.1.1.7   root     11441:        uae_u32 v;
1.1.1.4   root     11442: 
1.1.1.9   root     11443: //fprintf ( stderr , "get_word_ce030_prefetch_2 %d pc=%x\n" , currcycle , pc);
                   11444:        v = regs.prefetch020[0];
                   11445:        regs.prefetch020[0] = regs.prefetch020[1];
                   11446:        regs.prefetch020[1] = regs.prefetch020[2];
1.1.1.7   root     11447: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9   root     11448:        pipeline_020(pc);
1.1.1.7   root     11449: #endif
1.1.1.9   root     11450:        if (pc & 2) {
1.1.1.7   root     11451:                // branch instruction detected in pipeline: stop fetches until branch executed.
                   11452:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
                   11453:                        fill_icache030 (pc + 2 + 4);
1.1.1.9   root     11454:                } else {
                   11455:                        if (regs.cacheholdingdata_valid > 0)
                   11456:                                regs.cacheholdingdata_valid++;
1.1.1.7   root     11457:                }
1.1.1.9   root     11458:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     11459:        } else {
1.1.1.9   root     11460:                pc += 4;
                   11461:                // cacheholdingdata020 may be invalid if RTE from bus error
                   11462:                if ((!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) && regs.cacheholdingaddr020 != pc) {
                   11463:                        fill_icache030 (pc);
                   11464:                }
                   11465:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.7   root     11466:        }
1.1.1.9   root     11467:        regs.db = regs.prefetch020[0];
1.1.1.7   root     11468:        do_cycles_ce020_internal (2);
                   11469:        return v;
                   11470: }
                   11471: 
1.1.1.9   root     11472: uae_u32 get_word_ce030_prefetch (int o)
                   11473: {
                   11474:        return get_word_ce030_prefetch_2(o);
                   11475: }
                   11476: uae_u32 get_word_ce030_prefetch_opcode (int o)
                   11477: {
                   11478:        return get_word_ce030_prefetch_2(o);
                   11479: }
                   11480: 
                   11481: uae_u32 get_word_030_prefetch (int o)
1.1.1.7   root     11482: {
1.1.1.9   root     11483:        uae_u32 pc = m68k_getpc () + o;
1.1.1.7   root     11484:        uae_u32 v;
                   11485: 
1.1.1.9   root     11486:        v = regs.prefetch020[0];
                   11487:        regs.prefetch020[0] = regs.prefetch020[1];
                   11488:        regs.prefetch020[1] = regs.prefetch020[2];
                   11489:        regs.prefetch020_valid[0] = regs.prefetch020_valid[1];
                   11490:        regs.prefetch020_valid[1] = regs.prefetch020_valid[2];
                   11491:        regs.prefetch020_valid[2] = false;
                   11492:        if (!regs.prefetch020_valid[1]) {
                   11493:                do_access_or_bus_error(0xffffffff, pc + 4);
                   11494:        }
1.1.1.7   root     11495: #if MORE_ACCURATE_68020_PIPELINE
1.1.1.9   root     11496:        pipeline_020(pc);
1.1.1.7   root     11497: #endif
1.1.1.9   root     11498:        if (pc & 2) {
1.1.1.7   root     11499:                // branch instruction detected in pipeline: stop fetches until branch executed.
                   11500:                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
1.1.1.9   root     11501:                        fill_icache030 (pc + 2 + 4);
                   11502:                } else {
                   11503:                        if (regs.cacheholdingdata_valid > 0)
                   11504:                                regs.cacheholdingdata_valid++;
1.1.1.7   root     11505:                }
1.1.1.9   root     11506:                regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
1.1.1.7   root     11507:        } else {
1.1.1.9   root     11508:                pc += 4;
                   11509:                // cacheholdingdata020 may be invalid if RTE from bus error
                   11510:                if ((!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) && regs.cacheholdingaddr020 != pc) {
                   11511:                        fill_icache030 (pc);
                   11512:                }
                   11513:                regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
1.1.1.7   root     11514:        }
1.1.1.9   root     11515:        regs.prefetch020_valid[2] = regs.cacheholdingdata_valid;
                   11516:        regs.db = regs.prefetch020[0];
                   11517: //if ( ( v & 0xffff ) != ( get_word(pc) & 0xffff ) )
                   11518: //  fprintf ( stderr , "prefetch mismatch pc=%x prefetch=%x != mem=%x, i-cache error ?\n" , pc , v&0xffff , get_word(pc)&0xffff );
1.1.1.7   root     11519:        return v;
                   11520: }
                   11521: 
                   11522: uae_u32 get_word_icache030(uaecptr addr)
                   11523: {
                   11524:        fill_icache030(addr);
                   11525:        return regs.cacheholdingdata020 >> ((addr & 2) ? 0 : 16);
                   11526: }
                   11527: uae_u32 get_long_icache030(uaecptr addr)
                   11528: {
                   11529:        uae_u32 v;
                   11530:        fill_icache030(addr);
                   11531:        if ((addr & 2) == 0)
                   11532:                return regs.cacheholdingdata020;
                   11533:        v = regs.cacheholdingdata020 << 16;
                   11534:        fill_icache030(addr + 4);
                   11535:        v |= regs.cacheholdingdata020 >> 16;
                   11536:        return v;
                   11537: }
                   11538: 
1.1.1.9   root     11539: uae_u32 fill_icache040(uae_u32 addr)
                   11540: {
                   11541:        int index, lws;
                   11542:        uae_u32 tag, addr2;
                   11543:        struct cache040 *c;
                   11544:        int line;
                   11545: 
                   11546:        addr2 = addr & ~15;
                   11547:        lws = (addr >> 2) & 3;
                   11548: 
                   11549:        if (regs.prefetch020addr == addr2) {
                   11550:                return regs.prefetch040[lws];
                   11551:        }
                   11552: 
                   11553:        if (regs.cacr & 0x8000) {
                   11554:                uae_u8 cs = mmu_cache_state;
                   11555: 
                   11556:                if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_INS))
                   11557:                        cs = CACHE_DISABLE_MMU;
                   11558: 
                   11559:                index = (addr >> 4) & cacheisets04060mask;
                   11560:                tag = addr & cacheitag04060mask;
                   11561:                c = &icaches040[index];
1.1.1.10! root     11562:                for (int i = 0; i < CACHELINES040; i++) {
1.1.1.9   root     11563:                        if (c->valid[cache_lastline] && c->tag[cache_lastline] == tag) {
                   11564:                                // cache hit
                   11565:                                if (!(cs & CACHE_ENABLE_INS) || (cs & CACHE_DISABLE_MMU)) {
                   11566:                                        c->valid[cache_lastline] = false;
                   11567:                                        goto end;
                   11568:                                }
                   11569:                                if ((lws & 1) != icachehalfline) {
                   11570:                                        icachehalfline ^= 1;
                   11571:                                        icachelinecnt++;
                   11572: #ifdef WINUAE_FOR_HATARI
                   11573:                                CpuInstruction.I_Cache_hit++;
                   11574: #endif
                   11575:                                }
                   11576:                                return c->data[cache_lastline][lws];
                   11577:                        }
                   11578:                        cache_lastline++;
                   11579:                        cache_lastline &= (CACHELINES040 - 1);
                   11580:                }
                   11581:                // cache miss
                   11582:                regs.prefetch020addr = 0xffffffff;
                   11583:                regs.prefetch040[0] = icache_fetch(addr2 +  0);
                   11584:                regs.prefetch040[1] = icache_fetch(addr2 +  4);
                   11585:                regs.prefetch040[2] = icache_fetch(addr2 +  8);
                   11586:                regs.prefetch040[3] = icache_fetch(addr2 + 12);
                   11587:                regs.prefetch020addr = addr2;
                   11588:                if (!(cs & CACHE_ENABLE_INS) || (cs & CACHE_DISABLE_MMU))
                   11589:                        goto end;
                   11590:                if (regs.cacr & 0x00004000) // 68060 NAI
                   11591:                        goto end;
                   11592:                if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
                   11593:                        line = icachelinecnt & (CACHELINES040 - 1);
                   11594:                        icachehalfline = (lws & 1) ? 0 : 1;
                   11595:                } else {
                   11596:                        for (line = 0; line < CACHELINES040; line++) {
                   11597:                                if (c->valid[line] == false)
                   11598:                                        break;
                   11599:                        }
                   11600:                }
                   11601:                c->tag[line] = tag;
                   11602:                c->valid[line] = true;
                   11603:                c->data[line][0] = regs.prefetch040[0];
                   11604:                c->data[line][1] = regs.prefetch040[1];
                   11605:                c->data[line][2] = regs.prefetch040[2];
                   11606:                c->data[line][3] = regs.prefetch040[3];
                   11607:                if ((lws & 1) != icachehalfline) {
                   11608:                        icachehalfline ^= 1;
                   11609:                        icachelinecnt++;
                   11610:                }
                   11611: #ifdef WINUAE_FOR_HATARI
                   11612:                CpuInstruction.I_Cache_miss++;
                   11613: #endif
                   11614:                return c->data[line][lws];
                   11615: 
                   11616:        }
                   11617: 
                   11618: end:
                   11619:        if (regs.prefetch020addr == addr2)
                   11620:                return regs.prefetch040[lws];
                   11621:        regs.prefetch020addr = addr2;
                   11622:        regs.prefetch040[0] = icache_fetch(addr2 +  0);
                   11623:        regs.prefetch040[1] = icache_fetch(addr2 +  4);
                   11624:        regs.prefetch040[2] = icache_fetch(addr2 +  8);
                   11625:        regs.prefetch040[3] = icache_fetch(addr2 + 12);
                   11626:        return regs.prefetch040[lws];
                   11627: }
                   11628: 
                   11629: STATIC_INLINE void do_cycles_c040_mem (int clocks, uae_u32 val)
                   11630: {
                   11631:        x_do_cycles_post (clocks * cpucycleunit, val);
                   11632: }
                   11633: 
                   11634: uae_u32 mem_access_delay_longi_read_c040 (uaecptr addr)
                   11635: {
                   11636:        uae_u32 v;
                   11637:        switch (ce_banktype[addr >> 16])
                   11638:        {
                   11639:        case CE_MEMBANK_CHIP16:
                   11640:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   11641:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   11642:                break;
                   11643:        case CE_MEMBANK_CHIP32:
                   11644:                if ((addr & 3) != 0) {
                   11645:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   11646:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   11647:                } else {
                   11648:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
                   11649:                }
                   11650:                break;
                   11651:        case CE_MEMBANK_FAST16:
                   11652:                v = get_longi (addr);
                   11653:                do_cycles_c040_mem(1, v);
                   11654:                break;
                   11655:        case CE_MEMBANK_FAST32:
                   11656:                v = get_longi (addr);
                   11657:                break;
                   11658:        default:
                   11659:                v = get_longi (addr);
                   11660:                break;
                   11661:        }
                   11662:        return v;
                   11663: }
                   11664: uae_u32 mem_access_delay_long_read_c040 (uaecptr addr)
                   11665: {
                   11666:        uae_u32 v;
                   11667:        switch (ce_banktype[addr >> 16])
                   11668:        {
                   11669:        case CE_MEMBANK_CHIP16:
                   11670:                v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   11671:                v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   11672:                break;
                   11673:        case CE_MEMBANK_CHIP32:
                   11674:                if ((addr & 3) != 0) {
                   11675:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
                   11676:                        v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
                   11677:                } else {
                   11678:                        v = wait_cpu_cycle_read_ce020 (addr, -1);
                   11679:                }
                   11680:                break;
                   11681:        case CE_MEMBANK_FAST16:
                   11682:                v = get_long (addr);
                   11683:                do_cycles_c040_mem(1, v);
                   11684:                break;
                   11685:        case CE_MEMBANK_FAST32:
                   11686:                v = get_long (addr);
                   11687:                break;
                   11688:        default:
                   11689:                v = get_long (addr);
                   11690:                break;
                   11691:        }
                   11692:        return v;
                   11693: }
                   11694: 
                   11695: uae_u32 mem_access_delay_word_read_c040 (uaecptr addr)
                   11696: {
                   11697:        uae_u32 v;
                   11698:        switch (ce_banktype[addr >> 16])
                   11699:        {
                   11700:        case CE_MEMBANK_CHIP16:
                   11701:        case CE_MEMBANK_CHIP32:
                   11702:                if ((addr & 3) == 3) {
                   11703:                        v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
                   11704:                        v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
                   11705:                } else {
                   11706:                        v = wait_cpu_cycle_read_ce020 (addr, 1);
                   11707:                }
                   11708:                break;
                   11709:        case CE_MEMBANK_FAST16:
                   11710:                v = get_word (addr);
                   11711:                do_cycles_c040_mem (2, v);
                   11712:                break;
                   11713:        case CE_MEMBANK_FAST32:
                   11714:                v = get_word (addr);
                   11715:                 break;
                   11716:        default:
                   11717:                 v = get_word (addr);
                   11718:                break;
                   11719:        }
                   11720:        return v;
                   11721: }
                   11722: 
                   11723: uae_u32 mem_access_delay_byte_read_c040 (uaecptr addr)
                   11724: {
                   11725:        uae_u32 v;
                   11726:        switch (ce_banktype[addr >> 16])
                   11727:        {
                   11728:        case CE_MEMBANK_CHIP16:
                   11729:        case CE_MEMBANK_CHIP32:
                   11730:                v = wait_cpu_cycle_read_ce020 (addr, 0);
                   11731:                break;
                   11732:        case CE_MEMBANK_FAST16:
                   11733:                v = get_byte (addr);
                   11734:                do_cycles_c040_mem (1, v);
                   11735:                break;
                   11736:        case CE_MEMBANK_FAST32:
                   11737:                v = get_byte (addr);
                   11738:                break;
                   11739:        default:
                   11740:                v = get_byte (addr);
                   11741:                break;
                   11742:        }
                   11743:        return v;
                   11744: }
                   11745: 
                   11746: void mem_access_delay_byte_write_c040 (uaecptr addr, uae_u32 v)
                   11747: {
                   11748:        switch (ce_banktype[addr >> 16])
                   11749:        {
                   11750:        case CE_MEMBANK_CHIP16:
                   11751:        case CE_MEMBANK_CHIP32:
                   11752:                wait_cpu_cycle_write_ce020 (addr, 0, v);
                   11753:                break;
                   11754:        case CE_MEMBANK_FAST16:
                   11755:                put_byte (addr, v);
                   11756:                do_cycles_c040_mem (1, v);
                   11757:                break;
                   11758:        case CE_MEMBANK_FAST32:
                   11759:                put_byte (addr, v);
                   11760:                break;
                   11761:        default:
                   11762:                put_byte (addr, v);
                   11763:        break;
                   11764:        }
                   11765: }
                   11766: 
                   11767: void mem_access_delay_word_write_c040 (uaecptr addr, uae_u32 v)
                   11768: {
                   11769:        switch (ce_banktype[addr >> 16])
                   11770:        {
                   11771:        case CE_MEMBANK_CHIP16:
                   11772:        case CE_MEMBANK_CHIP32:
                   11773:                if ((addr & 3) == 3) {
                   11774:                        wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
                   11775:                        wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
                   11776:                } else {
                   11777:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
                   11778:                }
                   11779:                break;
                   11780:        case CE_MEMBANK_FAST16:
                   11781:                put_word (addr, v);
                   11782:                if ((addr & 3) == 3)
                   11783:                        do_cycles_c040_mem(2, v);
                   11784:                else
                   11785:                        do_cycles_c040_mem(1, v);
                   11786:                break;
                   11787:        case CE_MEMBANK_FAST32:
                   11788:                put_word (addr, v);
                   11789:                break;
                   11790:        default:
                   11791:                put_word (addr, v);
                   11792:        break;
                   11793:        }
                   11794: }
                   11795: 
                   11796: void mem_access_delay_long_write_c040 (uaecptr addr, uae_u32 v)
                   11797: {
                   11798:        switch (ce_banktype[addr >> 16])
                   11799:        {
                   11800:        case CE_MEMBANK_CHIP16:
                   11801:                wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
                   11802:                wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
                   11803:                break;
                   11804:        case CE_MEMBANK_CHIP32:
                   11805:                if ((addr & 3) == 3) {
                   11806:                        wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
                   11807:                        wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
                   11808:                } else {
                   11809:                        wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
                   11810:                }
                   11811:                break;
                   11812:        case CE_MEMBANK_FAST16:
                   11813:                put_long (addr, v);
                   11814:                do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
                   11815:                break;
                   11816:        case CE_MEMBANK_FAST32:
                   11817:                put_long (addr, v);
                   11818:                break;
                   11819:        default:
                   11820:                put_long (addr, v);
                   11821:                break;
                   11822:        }
                   11823: }
                   11824: 
                   11825: static uae_u32 dcache040_get_data(uaecptr addr, struct cache040 *c, int line, int size)
1.1.1.7   root     11826: {
1.1.1.9   root     11827:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
                   11828:        int offset = (addr & 15) * 8;
                   11829:        int offset32 = offset & 31;
                   11830:        int slot = offset / 32;
                   11831:        int width = 8 << size;
                   11832:        uae_u32 vv;
                   11833: 
                   11834:        if (offset32 + width <= 32) {
                   11835:                uae_u32 v = c->data[line][slot];
                   11836:                v >>= 32 - (offset32 + width);
                   11837:                v &= mask[size];
                   11838:                vv = v;
                   11839:        } else {
                   11840: #if VALIDATE_68040_DATACACHE
                   11841:                if (slot >= 3) {
                   11842:                        write_log(_T("invalid dcache040_get_data!\n"));
                   11843:                        return 0;
1.1.1.7   root     11844:                }
1.1.1.9   root     11845: #endif
                   11846:                uae_u64 v = c->data[line][slot];
                   11847:                v <<= 32;
                   11848:                v |= c->data[line][slot + 1];
                   11849:                v >>= 64 - (offset32 + width);
                   11850:                vv = v & mask[size];
1.1.1.7   root     11851:        }
1.1.1.9   root     11852:        return vv;
                   11853: }
1.1.1.7   root     11854: 
1.1.1.9   root     11855: static void dcache040_update(uaecptr addr, struct cache040 *c, int line, uae_u32 val, int size)
                   11856: {
                   11857:        static const uae_u64 mask64[3] = { 0xff, 0xffff, 0xffffffff };
                   11858:        static const uae_u32 mask32[3] = { 0xff, 0xffff, 0xffffffff };
                   11859:        int offset = (addr & 15) * 8;
                   11860:        int offset32 = offset & 31;
                   11861:        int slot = offset / 32;
                   11862:        int width = 8 << size;
                   11863: 
                   11864: #if VALIDATE_68040_DATACACHE > 1
                   11865:        validate_dcache040();
1.1.1.7   root     11866: #endif
1.1.1.9   root     11867: 
                   11868:        if (offset32 + width <= 32) {
                   11869:                int shift = 32 - (offset32 + width);
                   11870:                uae_u32 v = c->data[line][slot];
                   11871:                v &= ~(mask32[size] << shift);
                   11872:                v |= val << shift;
                   11873:                c->data[line][slot] = v;
                   11874:                c->dirty[line][slot] = true;
                   11875:        } else {
                   11876: #if VALIDATE_68040_DATACACHE
                   11877:                if (slot >= 3) {
                   11878:                        write_log(_T("invalid dcache040_update!\n"));
                   11879:                        return;
1.1.1.7   root     11880:                }
1.1.1.9   root     11881: #endif
                   11882:                int shift = 64 - (offset32 + width);
                   11883:                uae_u64 v = c->data[line][slot];
                   11884:                v <<= 32;
                   11885:                v |= c->data[line][slot + 1];
                   11886:                v &= ~(mask64[size] << shift);
                   11887:                v |= ((uae_u64)val) << shift;
                   11888:                c->data[line][slot] = v >> 32;
                   11889:                c->dirty[line][slot] = true;
                   11890:                c->data[line][slot + 1] = (uae_u32)v;
                   11891:                c->dirty[line][slot + 1] = true;
1.1.1.7   root     11892:        }
1.1.1.9   root     11893:        c->gdirty[line] = true;
                   11894: }
                   11895: 
                   11896: static int dcache040_fill_line(int index, uae_u32 tag, uaecptr addr)
                   11897: {
1.1.1.7   root     11898:        // cache miss
1.1.1.9   root     11899:        struct cache040 *c = &dcaches040[index];
                   11900:        int line;
1.1.1.7   root     11901:        if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
1.1.1.9   root     11902:                // all lines allocated, choose one, push and invalidate.
                   11903:                line = dcachelinecnt & (CACHELINES040 - 1);
                   11904:                dcachelinecnt++;
                   11905:                dcache040_push_line(index, line, false, true);
                   11906:        } else {
                   11907:                // at least one invalid
1.1.1.7   root     11908:                for (line = 0; line < CACHELINES040; line++) {
                   11909:                        if (c->valid[line] == false)
                   11910:                                break;
                   11911:                }
                   11912:        }
                   11913:        c->tag[line] = tag;
1.1.1.9   root     11914:        c->dirty[line][0] = false;
                   11915:        c->dirty[line][1] = false;
                   11916:        c->dirty[line][2] = false;
                   11917:        c->dirty[line][3] = false;
                   11918:        c->gdirty[line] = false;
                   11919:        c->data[line][0] = dcache_lget(addr + 0);
                   11920:        c->data[line][1] = dcache_lget(addr + 4);
                   11921:        c->data[line][2] = dcache_lget(addr + 8);
                   11922:        c->data[line][3] = dcache_lget(addr + 12);
1.1.1.7   root     11923:        c->valid[line] = true;
1.1.1.9   root     11924:        return line;
1.1.1.7   root     11925: }
                   11926: 
1.1.1.9   root     11927: static uae_u32 read_dcache040_debug(uae_u32 addr, int size, bool *cached)
1.1.1.7   root     11928: {
1.1.1.9   root     11929:        int index;
1.1.1.7   root     11930:        uae_u32 tag;
                   11931:        struct cache040 *c;
1.1.1.9   root     11932:        int line;
                   11933:        uae_u32 addr_o = addr;
                   11934:        uae_u8 cs = mmu_cache_state;
                   11935: 
                   11936:        *cached = false;
                   11937:        if (!currprefs.cpu_data_cache)
                   11938:                goto nocache;
                   11939:        if (!(regs.cacr & 0x80000000))
                   11940:                goto nocache;
1.1.1.7   root     11941: 
                   11942:        addr &= ~15;
1.1.1.9   root     11943:        index = (addr >> 4) & cachedsets04060mask;
                   11944:        tag = addr & cachedtag04060mask;
1.1.1.7   root     11945:        c = &dcaches040[index];
1.1.1.9   root     11946:        for (line = 0; line < CACHELINES040; line++) {
                   11947:                if (c->valid[line] && c->tag[line] == tag) {
                   11948:                        // cache hit
                   11949:                        return dcache040_get_data(addr_o, c, line, size);
1.1.1.7   root     11950:                }
                   11951:        }
1.1.1.9   root     11952: nocache:
                   11953:        if (size == 0)
                   11954:                return get_byte_debug(addr);
                   11955:        if (size == 1)
                   11956:                return get_word_debug(addr);
                   11957:        return get_long_debug(addr);
1.1.1.7   root     11958: }
                   11959: 
1.1.1.9   root     11960: static uae_u32 read_dcache040(uae_u32 addr, int size, uae_u32 (*fetch)(uaecptr))
1.1.1.7   root     11961: {
1.1.1.9   root     11962:        int index;
1.1.1.7   root     11963:        uae_u32 tag;
                   11964:        struct cache040 *c;
                   11965:        int line;
1.1.1.9   root     11966:        uae_u32 addr_o = addr;
                   11967:        uae_u8 cs = mmu_cache_state;
                   11968: 
                   11969:        if (!(regs.cacr & 0x80000000))
                   11970:                goto nocache;
                   11971: 
                   11972: #if VALIDATE_68040_DATACACHE > 1
                   11973:        validate_dcache040();
                   11974: #endif
                   11975: 
                   11976:        // Simple because 68040+ caches physical addresses (68030 caches logical addresses)
                   11977:        if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_DATA))
                   11978:                cs = CACHE_DISABLE_MMU;
1.1.1.7   root     11979: 
                   11980:        addr &= ~15;
1.1.1.9   root     11981:        index = (addr >> 4) & cachedsets04060mask;
                   11982:        tag = addr & cachedtag04060mask;
1.1.1.7   root     11983:        c = &dcaches040[index];
1.1.1.9   root     11984:        for (line = 0; line < CACHELINES040; line++) {
                   11985:                if (c->valid[line] && c->tag[line] == tag) {
1.1.1.7   root     11986:                        // cache hit
                   11987:                        dcachelinecnt++;
1.1.1.9   root     11988:                        // Cache hit but MMU disabled: do not cache, push and invalidate possible existing line
                   11989:                        if (cs & CACHE_DISABLE_MMU) {
                   11990:                                dcache040_push_line(index, line, false, true);
                   11991:                                goto nocache;
1.1.1.7   root     11992:                        }
1.1.1.9   root     11993:                        return dcache040_get_data(addr_o, c, line, size);
1.1.1.7   root     11994:                }
                   11995:        }
1.1.1.9   root     11996:        // Cache miss
                   11997:        // 040+ always caches whole line
1.1.1.10! root     11998:        if ((cs & CACHE_DISABLE_MMU) || !(cs & CACHE_ENABLE_DATA) || (cs & CACHE_DISABLE_ALLOCATE) || (regs.cacr & 0x40000000)) {
1.1.1.9   root     11999: nocache:
                   12000:                return fetch(addr_o);
1.1.1.7   root     12001:        }
1.1.1.9   root     12002:        // Allocate new cache line, return requested data.
                   12003:        line = dcache040_fill_line(index, tag, addr);
                   12004:        return dcache040_get_data(addr_o, c, line, size);
1.1.1.7   root     12005: }
                   12006: 
1.1.1.9   root     12007: static void write_dcache040(uae_u32 addr, uae_u32 val, int size, void (*store)(uaecptr, uae_u32))
1.1.1.7   root     12008: {
1.1.1.9   root     12009:        static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
                   12010:        int index;
1.1.1.7   root     12011:        uae_u32 tag;
                   12012:        struct cache040 *c;
                   12013:        int line;
1.1.1.9   root     12014:        uae_u32 addr_o = addr;
                   12015:        uae_u8 cs = mmu_cache_state;
                   12016: 
                   12017:        val &= mask[size];
                   12018: 
                   12019:        if (!(regs.cacr & 0x80000000))
                   12020:                goto nocache;
                   12021: 
                   12022:        if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_DATA))
                   12023:                cs = CACHE_DISABLE_MMU;
1.1.1.7   root     12024: 
                   12025:        addr &= ~15;
1.1.1.9   root     12026:        index = (addr >> 4) & cachedsets04060mask;
                   12027:        tag = addr & cachedtag04060mask;
1.1.1.7   root     12028:        c = &dcaches040[index];
1.1.1.9   root     12029:        for (line = 0; line < CACHELINES040; line++) {
                   12030:                if (c->valid[line] && c->tag[line] == tag) {
1.1.1.7   root     12031:                        // cache hit
                   12032:                        dcachelinecnt++;
1.1.1.9   root     12033:                        // Cache hit but MMU disabled: do not cache, push and invalidate possible existing line
                   12034:                        if (cs & CACHE_DISABLE_MMU) {
                   12035:                                dcache040_push_line(index, line, false, true);
                   12036:                                goto nocache;
                   12037:                        }
                   12038:                        dcache040_update(addr_o, c, line, val, size);
                   12039:                        // If not copyback mode: push modifications immediately (write-through)
                   12040:                        if (!(cs & CACHE_ENABLE_COPYBACK) || DISABLE_68040_COPYBACK) {
                   12041:                                dcache040_push_line(index, line, true, false);
1.1.1.4   root     12042:                        }
1.1.1.9   root     12043:                        return;
1.1.1.4   root     12044:                }
                   12045:        }
1.1.1.9   root     12046:        // Cache miss
                   12047:        // 040+ always caches whole line
                   12048:        // Writes misses in write-through mode don't allocate new cache lines
                   12049:        if (!(cs & CACHE_ENABLE_DATA) || (cs & CACHE_DISABLE_MMU) || (cs & CACHE_DISABLE_ALLOCATE) || !(cs & CACHE_ENABLE_COPYBACK) || (regs.cacr & 0x400000000)) {
                   12050: nocache:
                   12051:                store(addr_o, val);
                   12052:                return;
                   12053:        }
                   12054:        // Allocate new cache line and update it with new data.
                   12055:        line = dcache040_fill_line(index, tag, addr);
                   12056:        dcache040_update(addr_o, c, line, val, size);
                   12057:        if (DISABLE_68040_COPYBACK) {
                   12058:                dcache040_push_line(index, line, true, false);
1.1.1.7   root     12059:        }
                   12060: }
                   12061: 
                   12062: // really unoptimized
                   12063: uae_u32 get_word_icache040(uaecptr addr)
                   12064: {
                   12065:        uae_u32 v = fill_icache040(addr);
                   12066:        return v >> ((addr & 2) ? 0 : 16);
                   12067: }
                   12068: uae_u32 get_long_icache040(uaecptr addr)
                   12069: {
                   12070:        uae_u32 v1, v2;
                   12071:        v1 = fill_icache040(addr);
                   12072:        if ((addr & 2) == 0)
                   12073:                return v1;
                   12074:        v2 = fill_icache040(addr + 4);
                   12075:        return (v2 >> 16) | (v1 << 16);
                   12076: }
                   12077: uae_u32 get_ilong_cache_040(int o)
                   12078: {
                   12079:        return get_long_icache040(m68k_getpci() + o);
                   12080: }
                   12081: uae_u32 get_iword_cache_040(int o)
                   12082: {
                   12083:        return get_word_icache040(m68k_getpci() + o);
                   12084: }
                   12085: 
                   12086: void put_long_cache_040(uaecptr addr, uae_u32 v)
                   12087: {
1.1.1.9   root     12088:        int offset = addr & 15;
                   12089:        // access must not cross cachelines
                   12090:        if (offset < 13) {
                   12091:                write_dcache040(addr, v, 2, dcache_lput);
                   12092:        } else if (offset == 13 || offset == 15) {
                   12093:                write_dcache040(addr + 0, v >> 24, 0, dcache_bput);
                   12094:                write_dcache040(addr + 1, v >>  8, 1, dcache_wput);
                   12095:                write_dcache040(addr + 3, v >>  0, 0, dcache_bput);
                   12096:        } else if (offset == 14) {
                   12097:                write_dcache040(addr + 0, v >> 16, 1, dcache_wput);
                   12098:                write_dcache040(addr + 2, v >>  0, 1, dcache_wput);
1.1.1.7   root     12099:        }
                   12100: }
                   12101: void put_word_cache_040(uaecptr addr, uae_u32 v)
                   12102: {
1.1.1.9   root     12103:        int offset = addr & 15;
                   12104:        if (offset < 15) {
                   12105:                write_dcache040(addr, v, 1, dcache_wput);
1.1.1.7   root     12106:        } else {
1.1.1.9   root     12107:                write_dcache040(addr + 0, v >> 8, 0, dcache_bput);
                   12108:                write_dcache040(addr + 1, v >> 0, 0, dcache_bput);
1.1.1.7   root     12109:        }
                   12110: }
                   12111: void put_byte_cache_040(uaecptr addr, uae_u32 v)
                   12112: {
1.1.1.9   root     12113:        return write_dcache040(addr, v, 0, dcache_bput);
1.1.1.4   root     12114: }
                   12115: 
1.1.1.7   root     12116: uae_u32 get_long_cache_040(uaecptr addr)
                   12117: {
1.1.1.9   root     12118:        uae_u32 v;
                   12119:        int offset = addr & 15;
                   12120:        if (offset < 13) {
                   12121:                v = read_dcache040(addr, 2, dcache_lget);
                   12122:        } else if (offset == 13 || offset == 15) {
                   12123:                v =  read_dcache040(addr + 0, 0, dcache_bget) << 24;
                   12124:                v |= read_dcache040(addr + 1, 1, dcache_wget) <<  8;
                   12125:                v |= read_dcache040(addr + 3, 0, dcache_bget) <<  0;
1.1.1.10! root     12126:        } else /* if (offset == 14) */ {
1.1.1.9   root     12127:                v =  read_dcache040(addr + 0, 1, dcache_wget) << 16;
                   12128:                v |= read_dcache040(addr + 2, 1, dcache_wget) <<  0;
                   12129:        }
                   12130:        return v;
1.1.1.7   root     12131: }
                   12132: uae_u32 get_word_cache_040(uaecptr addr)
                   12133: {
1.1.1.9   root     12134:        uae_u32 v;
                   12135:        int offset = addr & 15;
                   12136:        if (offset < 15) {
                   12137:                v = read_dcache040(addr, 1, dcache_wget);
                   12138:        } else {
                   12139:                v =  read_dcache040(addr + 0, 0, dcache_bget) << 8;
                   12140:                v |= read_dcache040(addr + 1, 0, dcache_bget) << 0;
                   12141:        }
                   12142:        return v;
1.1.1.7   root     12143: }
                   12144: uae_u32 get_byte_cache_040(uaecptr addr)
                   12145: {
1.1.1.9   root     12146:        return read_dcache040(addr, 0, dcache_bget);
1.1.1.7   root     12147: }
                   12148: uae_u32 next_iword_cache040(void)
                   12149: {
                   12150:        uae_u32 r = get_word_icache040(m68k_getpci());
                   12151:        m68k_incpci(2);
                   12152:        return r;
                   12153: }
                   12154: uae_u32 next_ilong_cache040(void)
                   12155: {
                   12156:        uae_u32 r = get_long_icache040(m68k_getpci());
                   12157:        m68k_incpci(4);
                   12158:        return r;
                   12159: }
1.1.1.4   root     12160: 
1.1.1.9   root     12161: uae_u32 get_byte_cache_debug(uaecptr addr, bool *cached)
1.1.1.4   root     12162: {
1.1.1.9   root     12163:        *cached = false;
                   12164:        if (currprefs.cpu_model == 68030) {
                   12165:                return read_dcache030_debug(addr, 0, regs.s ? 5 : 1, cached);
                   12166:        } else if (currprefs.cpu_model >= 68040) {
                   12167:                return read_dcache040_debug(addr, 0, cached);
                   12168:        }
                   12169:        return get_byte_debug(addr);
                   12170: }
                   12171: uae_u32 get_word_cache_debug(uaecptr addr, bool *cached)
                   12172: {
                   12173:        *cached = false;
                   12174:        if (currprefs.cpu_model == 68030) {
                   12175:                return read_dcache030_debug(addr, 1, regs.s ? 5 : 1, cached);
                   12176:        } else if (currprefs.cpu_model >= 68040) {
                   12177:                return read_dcache040_debug(addr, 1, cached);
1.1.1.4   root     12178:        }
1.1.1.9   root     12179:        return get_word_debug(addr);
1.1.1.4   root     12180: }
                   12181: 
1.1.1.9   root     12182: uae_u32 get_long_cache_debug(uaecptr addr, bool *cached)
1.1.1.4   root     12183: {
1.1.1.9   root     12184:        *cached = false;
                   12185:        if (currprefs.cpu_model == 68030) {
                   12186:                return read_dcache030_debug(addr, 2, regs.s ? 5 : 1, cached);
                   12187:        } else if (currprefs.cpu_model >= 68040) {
                   12188:                return read_dcache040_debug(addr, 2, cached);
1.1.1.7   root     12189:        }
1.1.1.9   root     12190:        return get_long_debug(addr);
                   12191: }
                   12192: 
                   12193: void check_t0_trace(void)
                   12194: {
                   12195:        if (regs.t0 && currprefs.cpu_model >= 68020) {
                   12196:                unset_special (SPCFLAG_TRACE);
                   12197:                set_special (SPCFLAG_DOTRACE);
1.1.1.7   root     12198:        }
1.1.1.9   root     12199: }
                   12200: 
                   12201: static void reset_pipeline_state(void)
                   12202: {
                   12203: #if MORE_ACCURATE_68020_PIPELINE
                   12204:        regs.pipeline_pos = 0;
                   12205:        regs.pipeline_stop = 0;
                   12206:        regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
                   12207: #endif
                   12208: }
                   12209: 
                   12210: static int add_prefetch_030(int idx, uae_u16 w, uaecptr pc)
                   12211: {
                   12212:        regs.prefetch020[0] = regs.prefetch020[1];
                   12213:        regs.prefetch020_valid[0] = regs.prefetch020_valid[1];
                   12214:        regs.prefetch020[1] = regs.prefetch020[2];
                   12215:        regs.prefetch020_valid[1] = regs.prefetch020_valid[2];
                   12216:        regs.prefetch020[2] = w;
                   12217:        regs.prefetch020_valid[2] = regs.cacheholdingdata_valid;
                   12218: 
                   12219: #if MORE_ACCURATE_68020_PIPELINE
                   12220:        if (idx >= 1) {
                   12221:                pipeline_020(pc);
                   12222:        }
                   12223: #endif
                   12224: 
                   12225:        if  (!regs.prefetch020_valid[2]) {
                   12226:                if (idx == 0 || !regs.pipeline_stop) {
                   12227:                        // Pipeline refill and first opcode word is invalid?
                   12228:                        // Generate previously detected bus error/MMU fault
                   12229:                        do_access_or_bus_error(pc, pc + idx * 2);
1.1.1.7   root     12230:                }
                   12231:        }
1.1.1.9   root     12232:        return idx + 1;
1.1.1.4   root     12233: }
                   12234: 
1.1.1.9   root     12235: void fill_prefetch_030_ntx(void)
1.1.1.4   root     12236: {
1.1.1.9   root     12237: //fprintf ( stderr , "fill_prefetch_030_ntx %d\n" , currcycle);
1.1.1.7   root     12238:        uaecptr pc = m68k_getpc ();
                   12239:        uaecptr pc2 = pc;
1.1.1.9   root     12240:        int idx = 0;
                   12241: 
1.1.1.7   root     12242:        pc &= ~3;
1.1.1.9   root     12243:        mmu030_idx = 0;
                   12244:        reset_pipeline_state();
                   12245:        regs.cacheholdingdata_valid = 1;
                   12246:        regs.cacheholdingaddr020 = 0xffffffff;
                   12247:        regs.prefetch020_valid[0] = regs.prefetch020_valid[1] = regs.prefetch020_valid[2] = 0;
1.1.1.4   root     12248: 
1.1.1.9   root     12249:        fill_icache030(pc);
1.1.1.7   root     12250:        if (currprefs.cpu_cycle_exact)
                   12251:                do_cycles_ce020_internal(2);
1.1.1.9   root     12252:        if (pc2 & 2) {
                   12253:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
                   12254:        } else {
                   12255:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
                   12256:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
                   12257:        }
1.1.1.7   root     12258: 
1.1.1.9   root     12259:        fill_icache030(pc + 4);
1.1.1.7   root     12260:        if (currprefs.cpu_cycle_exact)
                   12261:                do_cycles_ce020_internal(2);
                   12262:        if (pc2 & 2) {
1.1.1.9   root     12263:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
                   12264:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
1.1.1.7   root     12265:        } else {
1.1.1.9   root     12266:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
1.1.1.4   root     12267:        }
1.1.1.9   root     12268: 
                   12269:        if (currprefs.cpu_cycle_exact)
                   12270:                regs.irc = get_word_ce030_prefetch_opcode (0);
                   12271:        else
                   12272:                regs.irc = get_word_030_prefetch (0);
                   12273: }
                   12274: 
                   12275: void fill_prefetch_030_ntx_continue (void)
                   12276: {
                   12277:        uaecptr pc = m68k_getpc ();
                   12278:        uaecptr pc_orig = pc;
                   12279:        int idx = 0;
                   12280: 
                   12281:        mmu030_idx = 0;
                   12282:        reset_pipeline_state();
                   12283:        regs.cacheholdingdata_valid = 1;
                   12284:        regs.cacheholdingaddr020 = 0xffffffff;
                   12285: 
1.1.1.10! root     12286:        for (int i = 2; i >= 0; i--) {
1.1.1.9   root     12287:                if (!regs.prefetch020_valid[i])
                   12288:                        break;
                   12289: #if MORE_ACCURATE_68020_PIPELINE
                   12290:                if (idx >= 1) {
                   12291:                        pipeline_020(pc);
                   12292:                }
1.1.1.7   root     12293: #endif
1.1.1.9   root     12294:                pc += 2;
                   12295:                idx++;
                   12296:        }
                   12297: 
                   12298:        if (idx < 3 && !regs.pipeline_stop) {
                   12299:                uaecptr pc2 = pc;
                   12300:                pc &= ~3;
                   12301: 
                   12302:                fill_icache030(pc);
                   12303:                if (currprefs.cpu_cycle_exact)
                   12304:                        do_cycles_ce020_internal(2);
                   12305:                if (pc2 & 2) {
                   12306:                        idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
                   12307:                } else {
                   12308:                        idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
                   12309:                        if (idx < 3)
                   12310:                                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
                   12311:                }
                   12312: 
                   12313:                if (idx < 3) {
                   12314:                        fill_icache030(pc + 4);
                   12315:                        if (currprefs.cpu_cycle_exact)
                   12316:                                do_cycles_ce020_internal(2);
                   12317:                        if (pc2 & 2) {
                   12318:                                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
                   12319:                                if (idx < 3)
                   12320:                                        idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
                   12321:                        } else {
                   12322:                                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
                   12323:                        }
                   12324:                }
                   12325:        }
1.1.1.4   root     12326: 
1.1.1.7   root     12327:        if (currprefs.cpu_cycle_exact)
1.1.1.9   root     12328:                regs.irc = get_word_ce030_prefetch_opcode (0);
1.1.1.7   root     12329:        else
1.1.1.9   root     12330:                regs.irc = get_word_030_prefetch (0);
                   12331: //fprintf ( stderr , "fill_prefetch_030_ntx4 %d\n" , currcycle);
1.1.1.4   root     12332: }
                   12333: 
1.1.1.9   root     12334: void fill_prefetch_020_ntx(void)
1.1.1.4   root     12335: {
1.1.1.7   root     12336:        uaecptr pc = m68k_getpc ();
                   12337:        uaecptr pc2 = pc;
1.1.1.9   root     12338:        int idx = 0;
                   12339: 
1.1.1.7   root     12340:        pc &= ~3;
1.1.1.9   root     12341:        reset_pipeline_state();
1.1.1.7   root     12342: 
1.1.1.9   root     12343:        fill_icache020 (pc, true);
1.1.1.7   root     12344:        if (currprefs.cpu_cycle_exact)
                   12345:                do_cycles_ce020_internal(2);
1.1.1.9   root     12346:        if (pc2 & 2) {
                   12347:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
                   12348:        } else {
                   12349:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
                   12350:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
                   12351:        }
1.1.1.7   root     12352: 
1.1.1.9   root     12353:        fill_icache020 (pc + 4, true);
1.1.1.7   root     12354:        if (currprefs.cpu_cycle_exact)
                   12355:                do_cycles_ce020_internal(2);
                   12356:        if (pc2 & 2) {
1.1.1.9   root     12357:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
                   12358:                idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
1.1.1.7   root     12359:        } else {
1.1.1.9   root     12360:                idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
1.1.1.7   root     12361:        }
                   12362: 
                   12363:        if (currprefs.cpu_cycle_exact)
1.1.1.9   root     12364:                regs.irc = get_word_ce020_prefetch_opcode (0);
1.1.1.7   root     12365:        else
                   12366:                regs.irc = get_word_020_prefetch (0);
1.1.1.4   root     12367: }
                   12368: 
1.1.1.9   root     12369: // Not exactly right, requires logic analyzer checks.
                   12370: void continue_ce020_prefetch(void)
                   12371: {
                   12372:        fill_prefetch_020_ntx();
                   12373: }
                   12374: void continue_020_prefetch(void)
                   12375: {
                   12376:        fill_prefetch_020_ntx();
                   12377: }
                   12378: 
                   12379: void continue_ce030_prefetch(void)
                   12380: {
                   12381:        fill_prefetch_030_ntx();
                   12382: }
                   12383: void continue_030_prefetch(void)
                   12384: {
                   12385:        fill_prefetch_030_ntx();
                   12386: }
                   12387: 
                   12388: void fill_prefetch_020(void)
                   12389: {
                   12390:        fill_prefetch_020_ntx();
                   12391:        check_t0_trace();
                   12392: }
                   12393: 
                   12394: void fill_prefetch_030(void)
                   12395: {
                   12396:        fill_prefetch_030_ntx();
                   12397:        check_t0_trace();
                   12398: }
                   12399: 
                   12400: 
1.1.1.7   root     12401: void fill_prefetch (void)
1.1.1.4   root     12402: {
1.1.1.9   root     12403:        reset_pipeline_state();
1.1.1.7   root     12404:        if (currprefs.cachesize)
                   12405:                return;
                   12406:        if (!currprefs.cpu_compatible)
                   12407:                return;
                   12408:        if (currprefs.cpu_model >= 68040) {
1.1.1.8   root     12409:                if (currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) {
1.1.1.7   root     12410:                        fill_icache040(m68k_getpc() + 16);
                   12411:                        fill_icache040(m68k_getpc());
                   12412:                }
                   12413:        } else if (currprefs.cpu_model == 68020) {
                   12414:                fill_prefetch_020 ();
                   12415:        } else if (currprefs.cpu_model == 68030) {
                   12416:                fill_prefetch_030 ();
                   12417:        } else if (currprefs.cpu_model <= 68010) {
                   12418:                uaecptr pc = m68k_getpc ();
                   12419:                regs.ir = x_get_word (pc);
                   12420:                regs.irc = x_get_word (pc + 2);
                   12421:        }
1.1.1.4   root     12422: }
1.1.1.10! root     12423: 
        !          12424: #ifndef WINUAE_FOR_HATARI
        !          12425: extern bool cpuboard_fc_check(uaecptr addr, uae_u32 *v, int size, bool write);
        !          12426: #else
        !          12427: STATIC_INLINE bool cpuboard_fc_check(uaecptr addr, uae_u32 *v, int size, bool write)
        !          12428: {
        !          12429:        return false;
        !          12430: }
        !          12431: #endif
        !          12432: 
        !          12433: uae_u32 sfc_nommu_get_byte(uaecptr addr)
        !          12434: {
        !          12435:        uae_u32 v;
        !          12436:        if (!cpuboard_fc_check(addr, &v, 0, false))
        !          12437:                v = x_get_byte(addr);
        !          12438:        return v;
        !          12439: }
        !          12440: uae_u32 sfc_nommu_get_word(uaecptr addr)
        !          12441: {
        !          12442:        uae_u32 v;
        !          12443:        if (!cpuboard_fc_check(addr, &v, 1, false))
        !          12444:                v = x_get_word(addr);
        !          12445:        return v;
        !          12446: }
        !          12447: uae_u32 sfc_nommu_get_long(uaecptr addr)
        !          12448: {
        !          12449:        uae_u32 v;
        !          12450:        if (!cpuboard_fc_check(addr, &v, 2, false))
        !          12451:                v = x_get_long(addr);
        !          12452:        return v;
        !          12453: }
        !          12454: void dfc_nommu_put_byte(uaecptr addr, uae_u32 v)
        !          12455: {
        !          12456:        if (!cpuboard_fc_check(addr, &v, 0, true))
        !          12457:                x_put_byte(addr, v);
        !          12458: }
        !          12459: void dfc_nommu_put_word(uaecptr addr, uae_u32 v)
        !          12460: {
        !          12461:        if (!cpuboard_fc_check(addr, &v, 1, true))
        !          12462:                x_put_word(addr, v);
        !          12463: }
        !          12464: void dfc_nommu_put_long(uaecptr addr, uae_u32 v)
        !          12465: {
        !          12466:        if (!cpuboard_fc_check(addr, &v, 2, true))
        !          12467:                x_put_long(addr, v);
        !          12468: }

unix.superglobalmegacorp.com

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