Annotation of previous/src/cpu/newcpu.c, revision 1.1.1.6

1.1.1.2   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
                     11: 
1.1.1.3   root       12: #include "main.h"
1.1.1.5   root       13: #include "m68000.h"
1.1.1.2   root       14: #include "compat.h"
                     15: #include "sysconfig.h"
                     16: #include "sysdeps.h"
                     17: #include "hatari-glue.h"
                     18: #include "options_cpu.h"
                     19: #include "maccess.h"
                     20: #include "memory.h"
                     21: #include "newcpu.h"
                     22: #include "cpummu.h"
1.1.1.3   root       23: #include "cpummu030.h"
1.1.1.5   root       24: #ifdef WITH_SOFTFLOAT
                     25: #include "fpp-softfloat.h"
                     26: #else
                     27: #include "md-fpp.h"
                     28: #endif
1.1.1.2   root       29: #include "main.h"
1.1.1.4   root       30: #include "dsp.h"
1.1.1.6 ! root       31: #include "dimension.hpp"
1.1.1.2   root       32: #include "reset.h"
                     33: #include "cycInt.h"
                     34: #include "dialog.h"
                     35: #include "screen.h"
                     36: #include "video.h"
                     37: #include "log.h"
                     38: #include "debugui.h"
                     39: #include "debugcpu.h"
1.1.1.6 ! root       40: #include "sysReg.h"
1.1.1.2   root       41: 
                     42: 
                     43: /* Opcode of faulting instruction */
                     44: static uae_u16 last_op_for_exception_3;
                     45: /* PC at fault time */
                     46: static uaecptr last_addr_for_exception_3;
                     47: /* Address that generated the exception */
                     48: static uaecptr last_fault_for_exception_3;
                     49: /* read (0) or write (1) access */
                     50: static int last_writeaccess_for_exception_3;
                     51: /* instruction (1) or data (0) access */
                     52: static int last_instructionaccess_for_exception_3;
                     53: int mmu_enabled, mmu_triggered;
                     54: int cpu_cycles;
                     55: 
                     56: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
                     57: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
                     58: 
                     59: int movem_index1[256];
                     60: int movem_index2[256];
                     61: int movem_next[256];
                     62: 
                     63: cpuop_func *cpufunctbl[65536];
                     64: 
                     65: int OpcodeFamily;
                     66: struct mmufixup mmufixup[2];
                     67: 
1.1.1.5   root       68: uae_u32 fpp_get_fpsr (void);
1.1.1.2   root       69: 
                     70: static struct cache030 icaches030[CACHELINES030];
                     71: static struct cache030 dcaches030[CACHELINES030];
                     72: 
1.1.1.5   root       73: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode);
1.1.1.2   root       74: 
                     75: uae_u32 (*x_prefetch)(int);
                     76: uae_u32 (*x_next_iword)(void);
                     77: uae_u32 (*x_next_ilong)(void);
1.1.1.4   root       78: uae_u32 (*x_get_ilong)(int);
                     79: uae_u32 (*x_get_iword)(int);
                     80: uae_u32 (*x_get_ibyte)(int);
1.1.1.2   root       81: uae_u32 (*x_get_long)(uaecptr);
                     82: uae_u32 (*x_get_word)(uaecptr);
                     83: uae_u32 (*x_get_byte)(uaecptr);
                     84: void (*x_put_long)(uaecptr,uae_u32);
                     85: void (*x_put_word)(uaecptr,uae_u32);
                     86: void (*x_put_byte)(uaecptr,uae_u32);
                     87: 
1.1.1.4   root       88: uae_u32 (*x_cp_next_iword)(void);
                     89: uae_u32 (*x_cp_next_ilong)(void);
                     90: uae_u32 (*x_cp_get_long)(uaecptr);
                     91: uae_u32 (*x_cp_get_word)(uaecptr);
                     92: uae_u32 (*x_cp_get_byte)(uaecptr);
                     93: void (*x_cp_put_long)(uaecptr,uae_u32);
                     94: void (*x_cp_put_word)(uaecptr,uae_u32);
                     95: void (*x_cp_put_byte)(uaecptr,uae_u32);
                     96: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
                     97: 
1.1.1.2   root       98: // shared memory access functions
                     99: static void set_x_funcs (void)
                    100: {
1.1.1.5   root      101:     if (currprefs.cpu_model == 68040) {
                    102:         x_prefetch   = get_iword_mmu040;
                    103:         x_get_ilong  = get_ilong_mmu040;
                    104:         x_get_iword  = get_iword_mmu040;
                    105:         x_get_ibyte  = get_ibyte_mmu040;
                    106:         x_next_iword = next_iword_mmu040;
                    107:         x_next_ilong = next_ilong_mmu040;
                    108:         x_put_long   = put_long_mmu040;
                    109:         x_put_word   = put_word_mmu040;
                    110:         x_put_byte   = put_byte_mmu040;
                    111:         x_get_long   = get_long_mmu040;
                    112:         x_get_word   = get_word_mmu040;
                    113:         x_get_byte   = get_byte_mmu040;
                    114:     } else {
                    115:         x_prefetch   = get_iword_mmu030;
                    116:         x_get_ilong  = get_ilong_mmu030;
                    117:         x_get_iword  = get_iword_mmu030;
                    118:         x_get_ibyte  = get_ibyte_mmu030;
                    119:         x_next_iword = next_iword_mmu030;
                    120:         x_next_ilong = next_ilong_mmu030;
                    121:         x_put_long   = put_long_mmu030;
                    122:         x_put_word   = put_word_mmu030;
                    123:         x_put_byte   = put_byte_mmu030;
                    124:         x_get_long   = get_long_mmu030;
                    125:         x_get_word   = get_word_mmu030;
                    126:         x_get_byte   = get_byte_mmu030;
                    127:     }
                    128:     
                    129:     if (currprefs.mmu_model == 68030) {
                    130:         x_cp_put_long = put_long_mmu030_state;
                    131:         x_cp_put_word = put_word_mmu030_state;
                    132:         x_cp_put_byte = put_byte_mmu030_state;
                    133:         x_cp_get_long = get_long_mmu030_state;
                    134:         x_cp_get_word = get_word_mmu030_state;
                    135:         x_cp_get_byte = get_byte_mmu030_state;
                    136:         x_cp_next_iword = next_iword_mmu030_state;
                    137:         x_cp_next_ilong = next_ilong_mmu030_state;
                    138:         x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
                    139:     } else {
                    140:         x_cp_put_long = x_put_long;
                    141:         x_cp_put_word = x_put_word;
                    142:         x_cp_put_byte = x_put_byte;
                    143:         x_cp_get_long = x_get_long;
                    144:         x_cp_get_word = x_get_word;
                    145:         x_cp_get_byte = x_get_byte;
                    146:         x_cp_next_iword = x_next_iword;
                    147:         x_cp_next_ilong = x_next_ilong;
                    148:         x_cp_get_disp_ea_020 = x_get_disp_ea_020;
                    149:     }
                    150: }
1.1.1.2   root      151: 
1.1.1.5   root      152: void flush_cpu_caches_040(uae_u16 opcode)
                    153: {
                    154:     int cache = (opcode >> 6) & 3;
                    155:     if (!(cache & 2))
                    156:         return;
                    157:     set_cpu_caches(true);
1.1.1.2   root      158: }
                    159: 
1.1.1.4   root      160: void set_cpu_caches (bool flush)
1.1.1.2   root      161: {
                    162:        int i;
                    163: 
1.1.1.5   root      164:        if (currprefs.cpu_model == 68030) {
1.1.1.2   root      165:                if (regs.cacr & 0x08) { // clear instr cache
                    166:                        for (i = 0; i < CACHELINES030; i++) {
                    167:                                icaches030[i].valid[0] = 0;
                    168:                                icaches030[i].valid[1] = 0;
                    169:                                icaches030[i].valid[2] = 0;
                    170:                                icaches030[i].valid[3] = 0;
                    171:                        }
1.1.1.5   root      172:             regs.cacr &= ~0x08;
1.1.1.2   root      173:                }
                    174:                if (regs.cacr & 0x04) { // clear entry in instr cache
                    175:                        icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
                    176:                        regs.cacr &= ~0x04;
                    177:                }
                    178:                if (regs.cacr & 0x800) { // clear data cache
                    179:                        for (i = 0; i < CACHELINES030; i++) {
                    180:                                dcaches030[i].valid[0] = 0;
                    181:                                dcaches030[i].valid[1] = 0;
                    182:                                dcaches030[i].valid[2] = 0;
                    183:                                dcaches030[i].valid[3] = 0;
                    184:                        }
                    185:                        regs.cacr &= ~0x800;
                    186:                }
                    187:                if (regs.cacr & 0x400) { // clear entry in data cache
                    188:                        dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
                    189:                        regs.cacr &= ~0x400;
                    190:                }
                    191:        }
                    192: }
                    193: 
1.1.1.5   root      194: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
1.1.1.2   root      195: {
1.1.1.5   root      196:     op_illg (opcode);
                    197:     return 4;
1.1.1.2   root      198: }
1.1.1.5   root      199: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
1.1.1.2   root      200: {
1.1.1.5   root      201:     if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
                    202:         op_illg (opcode);
                    203:     else
                    204:         op_unimpl (opcode);
                    205:     return 4;
1.1.1.2   root      206: }
                    207: 
                    208: void build_cpufunctbl (void)
                    209: {
                    210:        int i, opcnt;
                    211:        unsigned long opcode;
                    212:        const struct cputbl *tbl = 0;
                    213:        int lvl;
                    214: 
                    215:        switch (currprefs.cpu_model)
                    216:        {
                    217:        case 68040:
                    218:                lvl = 4;
1.1.1.5   root      219:                tbl = op_smalltbl_31_ff;
1.1.1.2   root      220:                break;
                    221:        case 68030:
                    222:                lvl = 3;
1.1.1.5   root      223:         tbl = op_smalltbl_32_ff;
1.1.1.2   root      224:                break;
                    225:        default:
1.1.1.5   root      226:                changed_prefs.cpu_model = currprefs.cpu_model = 68030;
                    227:         lvl = 3;
                    228:         tbl = op_smalltbl_32_ff;
1.1.1.2   root      229:        }
                    230: 
                    231:        if (tbl == 0) {
                    232:                write_log ("no CPU emulation cores available CPU=%d!", currprefs.cpu_model);
1.1.1.5   root      233:         DebugUI();
1.1.1.2   root      234:        }
                    235: 
                    236:        for (opcode = 0; opcode < 65536; opcode++)
                    237:                cpufunctbl[opcode] = op_illg_1;
                    238:        for (i = 0; tbl[i].handler != NULL; i++) {
                    239:                opcode = tbl[i].opcode;
                    240:                cpufunctbl[opcode] = tbl[i].handler;
                    241:        }
                    242: 
                    243:        opcnt = 0;
                    244:        for (opcode = 0; opcode < 65536; opcode++) {
                    245:                cpuop_func *f;
                    246: 
                    247:                if (table68k[opcode].mnemo == i_ILLG)
                    248:                        continue;
                    249:                if (table68k[opcode].clev > lvl) {
                    250:                        continue;
                    251:                }
                    252: 
                    253:                if (table68k[opcode].handler != -1) {
                    254:                        int idx = table68k[opcode].handler;
                    255:                        f = cpufunctbl[idx];
                    256:                        if (f == op_illg_1)
1.1.1.5   root      257:                 DebugUI();
1.1.1.2   root      258:                        cpufunctbl[opcode] = f;
                    259:                        opcnt++;
                    260:                }
                    261:        }
1.1.1.5   root      262:        write_log ("Building CPU, %d opcodes (%d %d)\n",
                    263:                opcnt, lvl, currprefs.cpu_compatible ? 1 : 0);
1.1.1.6 ! root      264:        write_log ("CPU=%d, MMU=%d, FPU=%d ($%02x)\n",
1.1.1.4   root      265:                currprefs.cpu_model, currprefs.mmu_model,
1.1.1.6 ! root      266:                currprefs.fpu_model, currprefs.fpu_revision);
1.1.1.4   root      267:        set_cpu_caches (0);
1.1.1.2   root      268:        if (currprefs.mmu_model) {
1.1.1.3   root      269:         if (currprefs.cpu_model >= 68040) {
                    270:             mmu_reset ();
                    271:             mmu_set_tc (regs.tcr);
                    272:             mmu_set_super (regs.s != 0);
                    273:         } else {
                    274:             mmu030_reset(1);
                    275:         }
                    276:     }
1.1.1.2   root      277: }
                    278: 
1.1.1.5   root      279: static void prefs_changed_cpu (void) {
1.1.1.2   root      280:        currprefs.cpu_model = changed_prefs.cpu_model;
                    281:        currprefs.fpu_model = changed_prefs.fpu_model;
1.1.1.4   root      282:     currprefs.fpu_revision = changed_prefs.fpu_revision;
1.1.1.2   root      283:        currprefs.mmu_model = changed_prefs.mmu_model;
                    284:        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                    285: }
                    286: 
                    287: void check_prefs_changed_cpu (void)
                    288: {
                    289:        bool changed = 0;
                    290: 
1.1.1.5   root      291:     if (changed
1.1.1.2   root      292:                || currprefs.cpu_model != changed_prefs.cpu_model
                    293:                || currprefs.fpu_model != changed_prefs.fpu_model
1.1.1.4   root      294:         || currprefs.fpu_revision != changed_prefs.fpu_revision
1.1.1.2   root      295:                || currprefs.mmu_model != changed_prefs.mmu_model
1.1.1.5   root      296:                || currprefs.cpu_compatible != changed_prefs.cpu_compatible) {
1.1.1.2   root      297: 
                    298:                        prefs_changed_cpu ();
                    299:                        build_cpufunctbl ();
                    300:                        changed = 1;
                    301:        }
                    302: 
                    303:        if (currprefs.cpu_idle != changed_prefs.cpu_idle) {
                    304:                currprefs.cpu_idle = changed_prefs.cpu_idle;
                    305:        }
                    306:        if (changed)
1.1.1.4   root      307:                set_special (SPCFLAG_MODE_CHANGE);
1.1.1.2   root      308: 
                    309: }
                    310: 
                    311: void init_m68k (void)
                    312: {
                    313:        int i;
                    314: 
                    315:        prefs_changed_cpu ();
1.1.1.5   root      316:     
1.1.1.2   root      317:        for (i = 0 ; i < 256 ; i++) {
                    318:                int j;
                    319:                for (j = 0 ; j < 8 ; j++) {
                    320:                        if (i & (1 << j)) break;
                    321:                }
                    322:                movem_index1[i] = j;
                    323:                movem_index2[i] = 7-j;
                    324:                movem_next[i] = i & (~(1 << j));
                    325:        }
                    326: 
                    327:        write_log ("Building CPU table for configuration: %d", currprefs.cpu_model);
                    328:        regs.address_space_mask = 0xffffffff;
1.1.1.5   root      329: 
                    330:     if (currprefs.fpu_model > 0)
1.1.1.2   root      331:                write_log ("/%d", currprefs.fpu_model);
1.1.1.5   root      332:     if (currprefs.cpu_compatible)
1.1.1.2   root      333:                write_log (" prefetch");
                    334:        write_log ("\n");
                    335: 
                    336:        read_table68k ();
                    337:        do_merges ();
                    338: 
                    339:        write_log ("%d CPU functions\n", nr_cpuop_funcs);
                    340: 
                    341:        build_cpufunctbl ();
                    342:        set_x_funcs ();
                    343: }
                    344: 
1.1.1.5   root      345: struct regstruct regs;
1.1.1.2   root      346: struct flag_struct regflags;
                    347: 
1.1.1.5   root      348: #define get_word_debug(o) DBGMemory_ReadWord (o)
                    349: #define get_iword_debug(o) DBGMemory_ReadWord (o)
                    350: #define get_ilong_debug(o) DBGMemory_ReadLong (o)
                    351: 
                    352: static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
                    353: {
                    354:     uae_u16 dp;
                    355:     uae_s8 disp8;
                    356:     uae_s16 disp16;
                    357:     int r;
                    358:     uae_u32 dispreg;
                    359:     uaecptr addr = pc;
                    360:     uae_s32 offset = 0;
                    361:     TCHAR buffer[80];
                    362:     
                    363:     switch (mode){
                    364:         case Dreg:
                    365:             _stprintf (buffer, _T("D%d"), reg);
                    366:             break;
                    367:         case Areg:
                    368:             _stprintf (buffer, _T("A%d"), reg);
                    369:             break;
                    370:         case Aind:
                    371:             _stprintf (buffer, _T("(A%d)"), reg);
                    372:             addr = regs.regs[reg + 8];
                    373:             break;
                    374:         case Aipi:
                    375:             _stprintf (buffer, _T("(A%d)+"), reg);
                    376:             addr = regs.regs[reg + 8];
                    377:             break;
                    378:         case Apdi:
                    379:             _stprintf (buffer, _T("-(A%d)"), reg);
                    380:             addr = regs.regs[reg + 8];
                    381:             break;
                    382:         case Ad16:
                    383:         {
                    384:             TCHAR offtxt[80];
                    385:             disp16 = get_iword_debug (pc); pc += 2;
                    386:             if (disp16 < 0)
                    387:                 _stprintf (offtxt, _T("-$%04x"), -disp16);
                    388:             else
                    389:                 _stprintf (offtxt, _T("$%04x"), disp16);
                    390:             addr = m68k_areg (regs, reg) + disp16;
                    391:             _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr);
                    392:         }
                    393:             break;
                    394:         case Ad8r:
                    395:             dp = get_iword_debug (pc); pc += 2;
                    396:             disp8 = dp & 0xFF;
                    397:             r = (dp & 0x7000) >> 12;
                    398:             dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                    399:             if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                    400:             dispreg <<= (dp >> 9) & 3;
                    401:             
                    402:             if (dp & 0x100) {
                    403:                 uae_s32 outer = 0, disp = 0;
                    404:                 uae_s32 base = m68k_areg (regs, reg);
                    405:                 TCHAR name[10];
                    406:                 _stprintf (name, _T("A%d, "), reg);
                    407:                 if (dp & 0x80) { base = 0; name[0] = 0; }
                    408:                 if (dp & 0x40) dispreg = 0;
                    409:                 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                    410:                 if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
                    411:                 base += disp;
                    412:                 
                    413:                 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                    414:                 if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
                    415:                 
                    416:                 if (!(dp & 4)) base += dispreg;
                    417:                 if ((dp & 3) && !safemode) base = get_ilong_debug (base);
                    418:                 if (dp & 4) base += dispreg;
                    419:                 
                    420:                 addr = base + outer;
                    421:                 _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
                    422:                            dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    423:                            1 << ((dp >> 9) & 3),
                    424:                            disp, outer, addr);
                    425:             } else {
                    426:                 addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
                    427:                 _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg,
                    428:                            dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    429:                            1 << ((dp >> 9) & 3), disp8, addr);
                    430:             }
                    431:             break;
                    432:         case PC16:
                    433:             disp16 = get_iword_debug (pc); pc += 2;
                    434:             addr += (uae_s16)disp16;
                    435:             _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
                    436:             break;
                    437:         case PC8r:
                    438:             dp = get_iword_debug (pc); pc += 2;
                    439:             disp8 = dp & 0xFF;
                    440:             r = (dp & 0x7000) >> 12;
                    441:             dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
                    442:             if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                    443:             dispreg <<= (dp >> 9) & 3;
                    444:             
                    445:             if (dp & 0x100) {
                    446:                 uae_s32 outer = 0, disp = 0;
                    447:                 uae_s32 base = addr;
                    448:                 TCHAR name[10];
                    449:                 _stprintf (name, _T("PC, "));
                    450:                 if (dp & 0x80) { base = 0; name[0] = 0; }
                    451:                 if (dp & 0x40) dispreg = 0;
                    452:                 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                    453:                 if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
                    454:                 base += disp;
                    455:                 
                    456:                 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
                    457:                 if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
                    458:                 
                    459:                 if (!(dp & 4)) base += dispreg;
                    460:                 if ((dp & 3) && !safemode) base = get_ilong_debug (base);
                    461:                 if (dp & 4) base += dispreg;
                    462:                 
                    463:                 addr = base + outer;
                    464:                 _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
                    465:                            dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    466:                            1 << ((dp >> 9) & 3),
                    467:                            disp, outer, addr);
                    468:             } else {
                    469:                 addr += (uae_s32)((uae_s8)disp8) + dispreg;
                    470:                 _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D',
                    471:                            (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
                    472:                            disp8, addr);
                    473:             }
                    474:             break;
                    475:         case absw:
                    476:             addr = (uae_s32)(uae_s16)get_iword_debug (pc);
                    477:             _stprintf (buffer, _T("$%08x"), addr);
                    478:             pc += 2;
                    479:             break;
                    480:         case absl:
                    481:             addr = get_ilong_debug (pc);
                    482:             _stprintf (buffer, _T("$%08x"), addr);
                    483:             pc += 4;
                    484:             break;
                    485:         case imm:
                    486:             switch (size){
                    487:                 case sz_byte:
                    488:                     _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
                    489:                     pc += 2;
                    490:                     break;
                    491:                 case sz_word:
                    492:                     _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
                    493:                     pc += 2;
                    494:                     break;
                    495:                 case sz_long:
                    496:                     _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
                    497:                     pc += 4;
                    498:                     break;
                    499:                 case sz_single:
                    500:                 {
                    501:                     fptype fp;
                    502:                     to_single(&fp, get_ilong_debug(pc));
                    503:                     _stprintf(buffer, _T("#%s"), fp_print(&fp));
                    504:                     pc += 4;
                    505:                 }
                    506:                     break;
                    507:                 case sz_double:
                    508:                 {
                    509:                     fptype fp;
                    510:                     to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
                    511:                     _stprintf(buffer, _T("#%s"), fp_print(&fp));
                    512:                     pc += 8;
                    513:                 }
                    514:                     break;
                    515:                 case sz_extended:
                    516:                 {
                    517:                     fptype fp;
                    518:                     to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
                    519:                     _stprintf(buffer, _T("#%s"), fp_print(&fp));
                    520:                     pc += 12;
                    521:                     break;
                    522:                 }
                    523:                 case sz_packed:
                    524:                     _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
                    525:                     pc += 12;
                    526:                     break;
                    527:                 default:
                    528:                     break;
                    529:             }
                    530:             break;
                    531:         case imm0:
                    532:             offset = (uae_s32)(uae_s8)get_iword_debug (pc);
                    533:             _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
                    534:             addr = pc + 2 + offset;
                    535:             pc += 2;
                    536:             break;
                    537:         case imm1:
                    538:             offset = (uae_s32)(uae_s16)get_iword_debug (pc);
                    539:             buffer[0] = 0;
                    540:             _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
                    541:             addr = pc + offset;
                    542:             pc += 2;
                    543:             break;
                    544:         case imm2:
                    545:             offset = (uae_s32)get_ilong_debug (pc);
                    546:             _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
                    547:             addr = pc + offset;
                    548:             pc += 4;
                    549:             break;
                    550:         case immi:
                    551:             offset = (uae_s32)(uae_s8)(reg & 0xff);
                    552:             _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
                    553:             addr = pc + offset;
                    554:             break;
                    555:         default:
                    556:             break;
                    557:     }
                    558:     if (buf == 0)
                    559:         f_out (f, _T("%s"), buffer);
                    560:     else
                    561:         _tcscat (buf, buffer);
                    562:     if (eaddr)
                    563:         *eaddr = addr;
                    564:     return pc;
1.1.1.2   root      565: }
                    566: 
1.1.1.6 ! root      567: static void activate_trace(void)
        !           568: {
        !           569:     unset_special (SPCFLAG_TRACE);
        !           570:     set_special (SPCFLAG_DOTRACE);
        !           571: }
        !           572: 
        !           573: void check_t0_trace(void)
        !           574: {
        !           575:     if (regs.t0 && currprefs.cpu_model >= 68020) {
        !           576:         unset_special (SPCFLAG_TRACE);
        !           577:         set_special (SPCFLAG_DOTRACE);
        !           578:     }
        !           579: }
        !           580: 
1.1.1.2   root      581: void REGPARAM2 MakeSR (void)
                    582: {
                    583:        regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
                    584:                | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
                    585:                | (GET_XFLG () << 4) | (GET_NFLG () << 3)
                    586:                | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
                    587:                |  GET_CFLG ());
                    588: }
                    589: 
1.1.1.6 ! root      590: static void MakeFromSR_x(int t0trace)
1.1.1.2   root      591: {
                    592:        int oldm = regs.m;
                    593:        int olds = regs.s;
1.1.1.6 ! root      594:     int oldt0 = regs.t0;
        !           595:     int oldt1 = regs.t1;
1.1.1.2   root      596: 
                    597:        SET_XFLG ((regs.sr >> 4) & 1);
                    598:        SET_NFLG ((regs.sr >> 3) & 1);
                    599:        SET_ZFLG ((regs.sr >> 2) & 1);
                    600:        SET_VFLG ((regs.sr >> 1) & 1);
                    601:        SET_CFLG (regs.sr & 1);
                    602:        if (regs.t1 == ((regs.sr >> 15) & 1) &&
                    603:                regs.t0 == ((regs.sr >> 14) & 1) &&
                    604:                regs.s  == ((regs.sr >> 13) & 1) &&
                    605:                regs.m  == ((regs.sr >> 12) & 1) &&
                    606:                regs.intmask == ((regs.sr >> 8) & 7))
                    607:                return;
                    608:        regs.t1 = (regs.sr >> 15) & 1;
                    609:        regs.t0 = (regs.sr >> 14) & 1;
                    610:        regs.s  = (regs.sr >> 13) & 1;
                    611:        regs.m  = (regs.sr >> 12) & 1;
                    612:        regs.intmask = (regs.sr >> 8) & 7;
                    613:        if (currprefs.cpu_model >= 68020) {
                    614:                if (olds != regs.s) {
                    615:                        if (olds) {
                    616:                                if (oldm)
                    617:                                        regs.msp = m68k_areg (regs, 7);
                    618:                                else
                    619:                                        regs.isp = m68k_areg (regs, 7);
                    620:                                m68k_areg (regs, 7) = regs.usp;
                    621:                        } else {
                    622:                                regs.usp = m68k_areg (regs, 7);
                    623:                                m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
                    624:                        }
                    625:                } else if (olds && oldm != regs.m) {
                    626:                        if (oldm) {
                    627:                                regs.msp = m68k_areg (regs, 7);
                    628:                                m68k_areg (regs, 7) = regs.isp;
                    629:                        } else {
                    630:                                regs.isp = m68k_areg (regs, 7);
                    631:                                m68k_areg (regs, 7) = regs.msp;
                    632:                        }
                    633:                }
                    634:        } else {
                    635:                regs.t0 = regs.m = 0;
                    636:                if (olds != regs.s) {
                    637:                        if (olds) {
                    638:                                regs.isp = m68k_areg (regs, 7);
                    639:                                m68k_areg (regs, 7) = regs.usp;
                    640:                        } else {
                    641:                                regs.usp = m68k_areg (regs, 7);
                    642:                                m68k_areg (regs, 7) = regs.isp;
                    643:                        }
                    644:                }
                    645:        }
                    646:        if (currprefs.mmu_model)
                    647:                mmu_set_super (regs.s != 0);
                    648: 
                    649:        doint ();
1.1.1.6 ! root      650:        if (regs.t1 || regs.t0) {
1.1.1.2   root      651:                set_special (SPCFLAG_TRACE);
1.1.1.6 ! root      652:        } else {
1.1.1.2   root      653:                /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
                    654:                SR-modifying instructions (including STOP).  */
                    655:                unset_special (SPCFLAG_TRACE);
1.1.1.6 ! root      656:     }
        !           657:     // Stop SR-modification does not generate T0
        !           658:     // If this SR modification set Tx bit, no trace until next instruction.
        !           659:     if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) {
        !           660:         // Always trace if Tx bits were already set, even if this SR modification cleared them.
        !           661:         activate_trace();
        !           662:     }
        !           663: }
        !           664: 
        !           665: void REGPARAM2 MakeFromSR_T0(void)
        !           666: {
        !           667:     MakeFromSR_x(1);
        !           668: }
        !           669: void REGPARAM2 MakeFromSR(void)
        !           670: {
        !           671:     MakeFromSR_x(0);
        !           672:     
1.1.1.2   root      673: }
                    674: 
1.1.1.5   root      675: static void exception_check_trace (int nr)
1.1.1.2   root      676: {
1.1.1.5   root      677:     unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                    678:     if (regs.t1 && !regs.t0) {
                    679:         /* trace stays pending if exception is div by zero, chk,
                    680:          * trapv or trap #x
                    681:          */
                    682:         if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
                    683:             set_special (SPCFLAG_DOTRACE);
                    684:     }
                    685:     regs.t1 = regs.t0 = 0;
1.1.1.2   root      686: }
                    687: 
                    688: static void exception_debug (int nr)
                    689: {
                    690: #ifdef DEBUGGER
                    691:        if (!exception_debugging)
                    692:                return;
1.1.1.5   root      693:        printf ("Exception %d, PC=%08X\n", nr, M68K_GETPC);
                    694:     DebugUI();
1.1.1.2   root      695: #endif
                    696: }
                    697: 
1.1.1.4   root      698: void cpu_halt (int e)
                    699: {
                    700:        write_log("HALT!");
1.1.1.5   root      701:     DebugUI();
1.1.1.4   root      702: }
1.1.1.3   root      703: 
1.1.1.4   root      704: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
                    705: {
1.1.1.3   root      706:     int i;
1.1.1.4   root      707:    
                    708: #if 0
1.1.1.3   root      709:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
1.1.1.4   root      710:         write_log(_T("Building exception stack frame (format %X)\n"), format);
1.1.1.3   root      711:     }
1.1.1.4   root      712: #endif
                    713: 
1.1.1.3   root      714:     switch (format) {
                    715:         case 0x0: // four word stack frame
                    716:         case 0x1: // throwaway four word stack frame
                    717:             break;
                    718:         case 0x2: // six word stack frame
                    719:             m68k_areg (regs, 7) -= 4;
                    720:             x_put_long (m68k_areg (regs, 7), oldpc);
                    721:             break;
1.1.1.5   root      722:         case 0x3: // floating point post-instruction stack frame (68040)
                    723:             m68k_areg (regs, 7) -= 4;
                    724:             x_put_long (m68k_areg (regs, 7), regs.fp_ea);
                    725:             break;
1.1.1.3   root      726:         case 0x7: // access error stack frame (68040)
1.1.1.4   root      727: 
                    728:                        for (i = 3; i >= 0; i--) {
                    729:                                // WB1D/PD0,PD1,PD2,PD3
1.1.1.3   root      730:                 m68k_areg (regs, 7) -= 4;
1.1.1.4   root      731:                 x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
                    732:                        }
                    733: 
1.1.1.3   root      734:             m68k_areg (regs, 7) -= 4;
1.1.1.4   root      735:             x_put_long (m68k_areg (regs, 7), 0); // WB1A
                    736:                        m68k_areg (regs, 7) -= 4;
                    737:             x_put_long (m68k_areg (regs, 7), 0); // WB2D
1.1.1.3   root      738:             m68k_areg (regs, 7) -= 4;
1.1.1.4   root      739:             x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
                    740:                        m68k_areg (regs, 7) -= 4;
                    741:             x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
1.1.1.3   root      742:             m68k_areg (regs, 7) -= 4;
1.1.1.4   root      743:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
                    744: 
                    745:                        m68k_areg (regs, 7) -= 4;
                    746:             x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
                    747:             
                    748:                        m68k_areg (regs, 7) -= 2;
1.1.1.3   root      749:             x_put_word (m68k_areg (regs, 7), 0);
                    750:             m68k_areg (regs, 7) -= 2;
1.1.1.4   root      751:             x_put_word (m68k_areg (regs, 7), regs.wb2_status);
                    752:             regs.wb2_status = 0;
1.1.1.3   root      753:             m68k_areg (regs, 7) -= 2;
                    754:             x_put_word (m68k_areg (regs, 7), regs.wb3_status);
                    755:             regs.wb3_status = 0;
1.1.1.4   root      756: 
                    757:                        m68k_areg (regs, 7) -= 2;
                    758:                        x_put_word (m68k_areg (regs, 7), ssw);
1.1.1.3   root      759:             m68k_areg (regs, 7) -= 4;
1.1.1.4   root      760:             x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
1.1.1.3   root      761:             break;
                    762:         case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
                    763:             m68k_areg (regs, 7) -= 4;
1.1.1.5   root      764:             x_put_long (m68k_areg (regs, 7), regs.fp_ea);
1.1.1.3   root      765:             m68k_areg (regs, 7) -= 4;
1.1.1.5   root      766:             x_put_long (m68k_areg (regs, 7), regs.fp_opword);
1.1.1.3   root      767:             m68k_areg (regs, 7) -= 4;
                    768:             x_put_long (m68k_areg (regs, 7), oldpc);
                    769:             break;
                    770:         case 0x8: // bus and address error stack frame (68010)
1.1.1.4   root      771:             write_log(_T("Exception stack frame format %X not implemented\n"), format);
1.1.1.3   root      772:             return;
1.1.1.4   root      773:         case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
                    774:                                // or 68060 bus access fault stack frame
                    775:                        m68k_areg (regs, 7) -= 4;
1.1.1.5   root      776:                        x_put_long (m68k_areg (regs, 7), ssw);
1.1.1.4   root      777:                        m68k_areg (regs, 7) -= 4;
1.1.1.5   root      778:                        x_put_long (m68k_areg (regs, 7), oldpc);
1.1.1.4   root      779:                        break;
                    780:                case 0xB: // long bus cycle fault stack frame (68020, 68030)
                    781:                        // We always use B frame because it is easier to emulate,
                    782:                        // our PC always points at start of instruction but A frame assumes
                    783:                        // it is + 2 and handling this properly is not easy.
                    784:                        // Store state information to internal register space
                    785:                        for (i = 0; i < mmu030_idx + 1; i++) {
                    786:                                m68k_areg (regs, 7) -= 4;
                    787:                                x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
                    788:                        }
                    789:                        while (i < 9) {
                    790:                 uae_u32 v = 0;
                    791:                                m68k_areg (regs, 7) -= 4;
1.1.1.5   root      792:                 // mmu030_idx is always small enough if instruction is FMOVEM.
1.1.1.4   root      793:                 if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
                    794:                     if (i == 7)
                    795:                         v = mmu030_fmovem_store[0];
                    796:                     else if (i == 8)
                    797:                         v = mmu030_fmovem_store[1];
                    798:                 }
                    799:                 x_put_long (m68k_areg (regs, 7), v);
                    800:                 i++;
                    801:                        }
                    802:                         // version & internal information (We store index here)
                    803:                        m68k_areg (regs, 7) -= 2;
                    804:                        x_put_word (m68k_areg (regs, 7), mmu030_idx);
                    805:                        // 3* internal registers
                    806:                        m68k_areg (regs, 7) -= 2;
                    807:                        x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
                    808:                        m68k_areg (regs, 7) -= 2;
                    809:                        x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
                    810:                        m68k_areg (regs, 7) -= 2;
                    811:                        x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
                    812:                        // data input buffer = fault address
                    813:                        m68k_areg (regs, 7) -= 4;
                    814:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                    815:                        // 2xinternal
                    816:                        m68k_areg (regs, 7) -= 2;
                    817:                        x_put_word (m68k_areg (regs, 7), 0);
                    818:                        m68k_areg (regs, 7) -= 2;
                    819:                        x_put_word (m68k_areg (regs, 7), 0);
                    820:                        // stage b address
                    821:                        m68k_areg (regs, 7) -= 4;
                    822:                        x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
                    823:                        // 2xinternal
                    824:                        m68k_areg (regs, 7) -= 4;
                    825:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
                    826:                /* fall through */
                    827:                case 0xA: // short bus cycle fault stack frame (68020, 68030)
                    828:                        m68k_areg (regs, 7) -= 4;
                    829:                        x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
                    830:                        m68k_areg (regs, 7) -= 4;
                    831:                         // Data output buffer = value that was going to be written
                    832:                        x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
                    833:                        m68k_areg (regs, 7) -= 4;
                    834:                        x_put_long (m68k_areg (regs, 7), mmu030_opcode);  // Internal register (opcode storage)
                    835:                        m68k_areg (regs, 7) -= 4;
                    836:                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
                    837:                        m68k_areg (regs, 7) -= 2;
                    838:                        x_put_word (m68k_areg (regs, 7), 0);  // Instr. pipe stage B
                    839:                        m68k_areg (regs, 7) -= 2;
                    840:                        x_put_word (m68k_areg (regs, 7), 0);  // Instr. pipe stage C
                    841:                        m68k_areg (regs, 7) -= 2;
                    842:                        x_put_word (m68k_areg (regs, 7), ssw);
                    843:                        m68k_areg (regs, 7) -= 2;
                    844:                        x_put_word (m68k_areg (regs, 7), 0);  // Internal register
                    845:                        break;
                    846:                default:
                    847:             write_log(_T("Unknown exception stack frame format: %X\n"), format);
1.1.1.3   root      848:             return;
                    849:     }
                    850:     m68k_areg (regs, 7) -= 2;
1.1.1.4   root      851:     x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
1.1.1.3   root      852:     m68k_areg (regs, 7) -= 4;
                    853:     x_put_long (m68k_areg (regs, 7), currpc);
                    854:     m68k_areg (regs, 7) -= 2;
                    855:     x_put_word (m68k_areg (regs, 7), regs.sr);
                    856: }
                    857: 
1.1.1.4   root      858: // 68030 MMU
                    859: static void Exception_mmu030 (int nr, uaecptr oldpc)
                    860: {
                    861:     uae_u32 currpc = m68k_getpc (), newpc;
1.1.1.3   root      862:     
1.1.1.4   root      863:     exception_debug (nr);
                    864:     MakeSR ();
1.1.1.3   root      865:     
                    866:     if (!regs.s) {
1.1.1.4   root      867:         regs.usp = m68k_areg (regs, 7);
1.1.1.3   root      868:         m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
                    869:         regs.s = 1;
1.1.1.4   root      870:         mmu_set_super (1);
1.1.1.3   root      871:     }
1.1.1.4   root      872:  
                    873: #if 0
1.1.1.3   root      874:     if (nr < 24 || nr > 31) { // do not print debugging for interrupts
1.1.1.4   root      875:         write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
1.1.1.3   root      876:                    nr, currpc, oldpc, regs.mmu_fault_addr);
                    877:     }
1.1.1.4   root      878: #endif
                    879: 
                    880: #if 0
                    881:        write_log (_T("Exception %d -> %08x\n", nr, newpc));
                    882: #endif
                    883: 
                    884: 
                    885:     newpc = x_get_long (regs.vbr + 4 * nr);
                    886: 
                    887:        if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
                    888:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                    889:         MakeSR(); /* this sets supervisor bit in status reg */
                    890:         regs.m = 0; /* clear the M bit (but frame 0x1 uses sr with M bit set) */
                    891:         regs.msp = m68k_areg (regs, 7);
                    892:         m68k_areg (regs, 7) = regs.isp;
                    893:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
1.1.1.3   root      894:     } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) {
1.1.1.4   root      895:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x2);
                    896:     } else if (nr == 2) {
                    897:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr,  0xB);
                    898:     } else if (nr == 3) {
                    899:                regs.mmu_fault_addr = last_fault_for_exception_3;
                    900:                mmu030_state[0] = mmu030_state[1] = 0;
                    901:                mmu030_data_buffer = 0;
                    902:         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.5   root      903:     } else if (nr >= 48 && nr < 55) {
                    904:         if (regs.fpu_exp_pre) {
                    905:             Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0);
                    906:         } else { /* mid-instruction */
                    907:             Exception_build_stack_frame(regs.fpiar, currpc, 0, nr, 0x9);
                    908:         }
1.1.1.3   root      909:     } else {
1.1.1.4   root      910:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
1.1.1.3   root      911:     }
                    912:     
                    913:        if (newpc & 1) {
                    914:                if (nr == 2 || nr == 3)
1.1.1.4   root      915:                        cpu_halt (2);
1.1.1.3   root      916:                else
1.1.1.5   root      917:                        exception3_read(regs.ir, newpc);
1.1.1.3   root      918:                return;
                    919:        }
1.1.1.5   root      920:        m68k_setpci (newpc);
                    921:        exception_check_trace (nr);
1.1.1.3   root      922: }
                    923: 
                    924: 
1.1.1.5   root      925: // 68040 MMU
1.1.1.2   root      926: static void Exception_mmu (int nr, uaecptr oldpc)
                    927: {
                    928:        uae_u32 currpc = m68k_getpc (), newpc;
                    929: 
                    930:        exception_debug (nr);
                    931:        MakeSR ();
                    932: 
                    933:        if (!regs.s) {
                    934:                regs.usp = m68k_areg (regs, 7);
1.1.1.5   root      935:         if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) {
1.1.1.2   root      936:                        m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.4   root      937:                } else {
1.1.1.2   root      938:                        m68k_areg (regs, 7) = regs.isp;
1.1.1.4   root      939:                }
1.1.1.2   root      940:                regs.s = 1;
                    941:                mmu_set_super (1);
                    942:        }
1.1.1.3   root      943:     
1.1.1.4   root      944:        newpc = x_get_long (regs.vbr + 4 * nr);
                    945: #if 0
                    946:        write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
                    947: #endif
                    948: 
                    949:        if (nr == 2) { // bus error
                    950:         //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
                    951:         if (currprefs.mmu_model == 68040)
                    952:                        Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
                    953:                else
1.1.1.5   root      954:                        Exception_build_stack_frame(regs.mmu_fault_addr, currpc, regs.mmu_fslw, nr, 0x4);
1.1.1.3   root      955:        } else if (nr == 3) { // address error
1.1.1.4   root      956:         Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
                    957:                write_log (_T("Exception %d (%x) at %x!\n"), nr, last_fault_for_exception_3, currpc);
                    958:        } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
1.1.1.3   root      959:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
1.1.1.2   root      960:        } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
1.1.1.4   root      961:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                    962:         MakeSR(); /* this sets supervisor bit in status reg */
                    963:         regs.m = 0; /* clear the M bit (but frame 0x1 uses sr with M bit set) */
                    964:         regs.msp = m68k_areg (regs, 7);
                    965:         m68k_areg (regs, 7) = regs.isp;
                    966:         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
1.1.1.5   root      967:        } else if (nr == 60 || nr == 61) {
1.1.1.4   root      968:         Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
1.1.1.5   root      969:     } else if (nr >= 48 && nr <= 55) {
                    970:         if (regs.fpu_exp_pre) {
                    971:             if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
                    972:                 Exception_build_stack_frame(regs.fp_ea, regs.instruction_pc, 0, nr, 0x2);
                    973:             } else {
                    974:                 Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0);
                    975:             }
                    976:         } else { /* post-instruction */
                    977:             if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
                    978:                 Exception_build_stack_frame(regs.fp_ea, currpc, 0, nr, 0x2);
                    979:             } else {
                    980:                 Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x3);
                    981:             }
                    982:         }
                    983:     } else if (nr == 11 && regs.fp_unimp_ins) {
                    984:         regs.fp_unimp_ins = false;
                    985:         if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2))) ||
                    986:             (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
                    987:             Exception_build_stack_frame(regs.fp_ea, currpc, regs.instruction_pc, nr, 0x4);
                    988:         } else {
                    989:             Exception_build_stack_frame(regs.fp_ea, currpc, regs.mmu_ssw, nr, 0x2);
                    990:         }
1.1.1.2   root      991:        } else {
1.1.1.3   root      992:         Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
1.1.1.2   root      993:        }
1.1.1.3   root      994:     
1.1.1.2   root      995:        if (newpc & 1) {
                    996:                if (nr == 2 || nr == 3)
1.1.1.4   root      997:                        cpu_halt (2);
1.1.1.2   root      998:                else
1.1.1.5   root      999:                        exception3_read (regs.ir, newpc);
1.1.1.2   root     1000:                return;
                   1001:        }
1.1.1.5   root     1002:        m68k_setpci (newpc);
                   1003:        exception_check_trace (nr);
1.1.1.2   root     1004: }
                   1005: 
                   1006: 
1.1.1.5   root     1007: /* Handle exceptions. */
                   1008: static void ExceptionX (int nr, uaecptr address)
1.1.1.2   root     1009: {
1.1.1.5   root     1010:     if (currprefs.cpu_model == 68030)
                   1011:         Exception_mmu030 (nr, m68k_getpc ());
1.1.1.3   root     1012:     else
1.1.1.5   root     1013:         Exception_mmu (nr, m68k_getpc ());
1.1.1.2   root     1014: }
1.1.1.5   root     1015: 
1.1.1.6 ! root     1016: void REGPARAM2 Exception_cpu(int nr)
        !          1017: {
        !          1018:     bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
        !          1019:     ExceptionX (nr, -1);
        !          1020:     // check T0 trace
        !          1021:     if (t0) {
        !          1022:         activate_trace();
        !          1023:     }
        !          1024: }
1.1.1.4   root     1025: void REGPARAM2 Exception (int nr)
                   1026: {
1.1.1.5   root     1027:     ExceptionX (nr, -1);
1.1.1.4   root     1028: }
1.1.1.5   root     1029: void REGPARAM2 ExceptionL (int nr, uaecptr address)
1.1.1.2   root     1030: {
1.1.1.5   root     1031:     ExceptionX (nr, address);
                   1032: }
1.1.1.2   root     1033: 
1.1.1.5   root     1034: static void do_interrupt (int nr, int Pending)
                   1035: {
1.1.1.2   root     1036:        regs.stopped = 0;
                   1037:        unset_special (SPCFLAG_STOP);
                   1038:        assert (nr < 8 && nr >= 0);
                   1039: 
                   1040:        /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */
1.1.1.4   root     1041:        Exception (nr + 24);
1.1.1.2   root     1042: 
                   1043:        regs.intmask = nr;
                   1044:        doint ();
                   1045: 
                   1046:        set_special (SPCFLAG_INT);
                   1047: }
                   1048: 
                   1049: 
                   1050: void m68k_reset (int hardreset)
                   1051: {
1.1.1.4   root     1052:     regs.spcflags &= (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK);
1.1.1.2   root     1053:        regs.ipl = regs.ipl_pin = 0;
                   1054:        regs.s = 1;
                   1055:        regs.m = 0;
                   1056:        regs.stopped = 0;
                   1057:        regs.t1 = 0;
                   1058:        regs.t0 = 0;
                   1059:        SET_ZFLG (0);
                   1060:        SET_XFLG (0);
                   1061:        SET_CFLG (0);
                   1062:        SET_VFLG (0);
                   1063:        SET_NFLG (0);
                   1064:        regs.intmask = 7;
                   1065:        regs.vbr = regs.sfc = regs.dfc = 0;
                   1066:        regs.irc = 0xffff;
                   1067:        
                   1068:        m68k_areg (regs, 7) = get_long (0);
                   1069:        m68k_setpc (get_long (4));
                   1070: 
                   1071:        fpu_reset ();
                   1072: 
                   1073:        regs.caar = regs.cacr = 0;
                   1074:        regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
                   1075:        regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
                   1076: 
                   1077:        mmufixup[0].reg = -1;
                   1078:        mmufixup[1].reg = -1;
                   1079:        if (currprefs.mmu_model) {
1.1.1.3   root     1080:         if (currprefs.cpu_model >= 68040) {
                   1081:             mmu_reset ();
                   1082:             mmu_set_tc (regs.tcr);
                   1083:             mmu_set_super (regs.s != 0);
                   1084:         }
                   1085:         else {
                   1086:             mmu030_reset(hardreset);
                   1087:         }
                   1088:     }
1.1.1.2   root     1089: 
                   1090:        regs.pcr = 0;
                   1091: }
                   1092: 
1.1.1.4   root     1093: void REGPARAM2 op_unimpl (uae_u16 opcode)
                   1094: {
1.1.1.5   root     1095:     static int warned;
                   1096:     if (warned < 20) {
                   1097:         write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
                   1098:         warned++;
                   1099:     }
                   1100:     ExceptionL (61, regs.instruction_pc);
1.1.1.4   root     1101: }
                   1102: 
                   1103: uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
1.1.1.2   root     1104: {
                   1105:        uaecptr pc = m68k_getpc ();
                   1106:        static int warned;
                   1107: 
                   1108:        if (warned < 20) {
1.1.1.4   root     1109:                write_log ("Illegal instruction: %04x at %08X\n", opcode, pc);
1.1.1.2   root     1110:                warned++;
                   1111:        }
                   1112: 
                   1113:        if ((opcode & 0xF000)==0xA000)
1.1.1.4   root     1114:                Exception (10);
1.1.1.2   root     1115:        else 
                   1116:        if ((opcode & 0xF000)==0xF000)
1.1.1.4   root     1117:                Exception (11);
1.1.1.2   root     1118:        else
1.1.1.4   root     1119:                Exception (4);
1.1.1.2   root     1120:        return 4;
                   1121: }
                   1122: 
                   1123: #ifdef CPUEMU_0
                   1124: 
1.1.1.5   root     1125: // 68030 (68851) MMU instructions only
                   1126: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
1.1.1.2   root     1127: {
1.1.1.5   root     1128:     bool fline = false;
                   1129:     
                   1130:     if (extra & 0x8000) {
                   1131:         fline = mmu_op30_ptest (pc, opcode, extra, extraa);
                   1132:     } else if ((extra&0xE000)==0x2000 && (extra & 0x1C00)) {
                   1133:         fline = mmu_op30_pflush (pc, opcode, extra, extraa);
                   1134:     } else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00)) {
                   1135:         fline = mmu_op30_pload (pc, opcode, extra, extraa);
                   1136:     } else {
                   1137:         fline = mmu_op30_pmove (pc, opcode, extra, extraa);
                   1138:     }
                   1139:     
                   1140:     if (fline) {
                   1141:         m68k_setpc(pc);
                   1142:         op_illg(opcode);
                   1143:     }
                   1144:     return fline;
1.1.1.2   root     1145: }
                   1146: 
                   1147: void mmu_op (uae_u32 opcode, uae_u32 extra)
                   1148: {
                   1149:        if (currprefs.cpu_model) {
                   1150:                mmu_op_real (opcode, extra);
                   1151:                return;
                   1152:        }
                   1153: #if MMUOP_DEBUG > 1
                   1154:        write_log ("mmu_op %04X PC=%08X\n", opcode, m68k_getpc ());
                   1155: #endif
                   1156:        if ((opcode & 0xFE0) == 0x0500) {
                   1157:                /* PFLUSH */
                   1158:                regs.mmusr = 0;
                   1159: #if MMUOP_DEBUG > 0
                   1160:                write_log ("PFLUSH\n");
                   1161: #endif
                   1162:                return;
                   1163:        } else if ((opcode & 0x0FD8) == 0x548) {
                   1164:                if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
                   1165:                        /* PTEST */
                   1166: #if MMUOP_DEBUG > 0
                   1167:                        write_log ("PTEST\n");
                   1168: #endif
                   1169:                        return;
                   1170:                }
                   1171:        }
                   1172: #if MMUOP_DEBUG > 0
                   1173:        write_log ("Unknown MMU OP %04X\n", opcode);
                   1174: #endif
                   1175:        m68k_setpc (m68k_getpc () - 2);
                   1176:        op_illg (opcode);
                   1177: }
                   1178: 
                   1179: #endif
                   1180: 
                   1181: static void do_trace (void)
                   1182: {
                   1183:        if (regs.t0 && currprefs.cpu_model >= 68020) {
1.1.1.6 ! root     1184:         // this is obsolete
        !          1185:         return;
        !          1186:     }
        !          1187:     if (regs.t1) {
        !          1188:         activate_trace();
        !          1189:     }
1.1.1.2   root     1190: }
                   1191: 
                   1192: void doint (void)
                   1193: {
                   1194:        if (currprefs.cpu_compatible)
                   1195:                set_special (SPCFLAG_INT);
                   1196:        else
                   1197:                set_special (SPCFLAG_DOINT);
                   1198: }
                   1199: 
                   1200: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 700)
                   1201: 
                   1202: /*
                   1203:  * Handle special flags
                   1204:  */
                   1205: 
1.1.1.6 ! root     1206: static int vpos = 0;
        !          1207: 
1.1.1.5   root     1208: static int do_specialties (int cycles)
1.1.1.2   root     1209: {
                   1210:        if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.4   root     1211:                Exception (9);
1.1.1.2   root     1212: 
                   1213:     /* Handle the STOP instruction */
                   1214:     if ( regs.spcflags & SPCFLAG_STOP ) {
1.1.1.5   root     1215:         while (regs.spcflags & SPCFLAG_STOP) {
1.1.1.2   root     1216: 
1.1.1.5   root     1217:             /* Take care of quit event if needed */
                   1218:             if (regs.spcflags & SPCFLAG_BRK)
                   1219:                 return 1;
                   1220:         
                   1221:             M68000_AddCycles(cpu_cycles);
                   1222: 
                   1223:             /* It is possible one or more ints happen at the same time */
                   1224:             /* We must process them during the same cpu cycle until the special INT flag is set */
                   1225:             while (PendingInterrupt.time <=0 && PendingInterrupt.pFunction) {
                   1226:                 /* 1st, we call the interrupt handler */
                   1227:                 CALL_VAR(PendingInterrupt.pFunction);
                   1228:                 
                   1229:                 if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
                   1230:                     unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
                   1231:                     // SPCFLAG_BRK breaks STOP condition, need to prefetch
                   1232:                     m68k_resumestopped ();
                   1233:                     return 1;
                   1234:                 }
1.1.1.2   root     1235: 
1.1.1.5   root     1236:                 if (currprefs.cpu_idle && ((regs.spcflags & SPCFLAG_STOP)) == SPCFLAG_STOP) {
                   1237:                     /* sleep 1ms if STOP-instruction is executed */
                   1238:                     if (1) {
                   1239:                         static int sleepcnt, lvpos;
                   1240:                         if (vpos != lvpos) {
                   1241:                             sleepcnt--;
                   1242:                             lvpos = vpos;
                   1243:                             if (sleepcnt < 0) {
                   1244:                                     /*sleepcnt = IDLETIME / 2; */  /* Laurent : badly removed for now */
                   1245:                                 host_sleep_ms(1);
                   1246:                             }
                   1247:                         }
                   1248:                     }
                   1249:                 }
                   1250:             }
                   1251:         }
1.1.1.2   root     1252:        }
                   1253: 
                   1254:        if (regs.spcflags & SPCFLAG_TRACE)
                   1255:                do_trace ();
                   1256: 
                   1257:        if (regs.spcflags & SPCFLAG_DOINT) {
                   1258:                unset_special (SPCFLAG_DOINT);
                   1259:                set_special (SPCFLAG_INT);
                   1260:        }
                   1261: 
                   1262:     if (regs.spcflags & SPCFLAG_DEBUGGER)
                   1263:                DebugCpu_Check();
                   1264: 
                   1265:        if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
                   1266:                unset_special(SPCFLAG_MODE_CHANGE);
                   1267:                return 1;
                   1268:        }
1.1.1.5   root     1269:     
1.1.1.2   root     1270:        return 0;
                   1271: }
                   1272: 
1.1.1.5   root     1273: #ifndef CPUEMU_0
1.1.1.2   root     1274: 
1.1.1.5   root     1275: #else
1.1.1.2   root     1276: 
1.1.1.6 ! root     1277: static int ndCycles = 0;
        !          1278: // give other MPUs (DSP, i860) some time to run on m68k thread
        !          1279: static inline void run_other_MPUs() {
        !          1280:     ndCycles += cpu_cycles;
        !          1281:     // bundle some 68k cycles for MPUs
        !          1282:     
        !          1283:     if(dsp_core.running)
        !          1284:         DSP_Run(cpu_cycles);
        !          1285:     
        !          1286:     if(ndCycles > 100) {
        !          1287:         i860_Run(ndCycles);
        !          1288:         ndCycles = 0;
        !          1289:     }
        !          1290: }
        !          1291: 
        !          1292: /**
        !          1293:  * Return interrupt number (1 - 7), 0 means no interrupt.
        !          1294:  * Note that the interrupt stays pending if it can't be executed yet
        !          1295:  * due to the interrupt level field in the SR.
        !          1296:  */
        !          1297: static inline int intlev(void) {
        !          1298:  /* Poll interrupt level from interrupt status and mask registers
        !          1299:  * --> see sysReg.c
        !          1300:  */
        !          1301:     Uint32 interrupt = scrIntStat&scrIntMask;
        !          1302:     return interrupt ? scr_get_interrupt_level(interrupt) : 0;
        !          1303: }
        !          1304: 
1.1.1.5   root     1305: static int lastRegsS = 0;
1.1.1.2   root     1306: 
1.1.1.5   root     1307: // Previous MMU 68030
                   1308: static void m68k_run_mmu030 (void)
1.1.1.2   root     1309: {
1.1.1.5   root     1310:        uae_u16 opcode;
                   1311:        uaecptr pc;
                   1312:        struct flag_struct f;
                   1313:        f.cznv = 0;
                   1314:        f.x    = 0;
                   1315:     int intr             = 0;
                   1316:     int lastintr         = 0;
                   1317:        mmu030_opcode_stageb = -1;
                   1318: retry:
                   1319:        TRY (prb) {
                   1320:                for (;;) {
                   1321:                        int cnt;
                   1322: insretry:
                   1323:                        pc = regs.instruction_pc = m68k_getpc ();
                   1324:                        f.cznv = regflags.cznv;
                   1325:                        f.x    = regflags.x;
                   1326:             
                   1327:                        mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
                   1328:                        mmu030_opcode = -1;
                   1329:                        if (mmu030_opcode_stageb < 0) {
                   1330:                                opcode = get_iword_mmu030 (0);
                   1331:                        } else {
                   1332:                                opcode = mmu030_opcode_stageb;
                   1333:                                mmu030_opcode_stageb = -1;
                   1334:                        }
1.1.1.2   root     1335: 
1.1.1.5   root     1336:                        mmu030_opcode = opcode;
                   1337:                        mmu030_ad[0].done = false;
1.1.1.2   root     1338: 
1.1.1.5   root     1339:             Uint64 beforeCycles = nCyclesMainCounter;
                   1340:                        cnt = 50;
                   1341:                        for (;;) {
                   1342:                                opcode = mmu030_opcode;
                   1343:                                mmu030_idx = 0;
                   1344:                                mmu030_retry = false;
                   1345:                                cpu_cycles = (*cpufunctbl[opcode])(opcode);
                   1346:                                cnt--; // so that we don't get in infinite loop if things go horribly wrong
                   1347:                                if (!mmu030_retry)
                   1348:                                        break;
                   1349:                                if (cnt < 0) {
                   1350:                                        cpu_halt (9);
                   1351:                                        break;
                   1352:                                }
                   1353:                                if (mmu030_retry && mmu030_opcode == -1)
                   1354:                                        goto insretry; // urgh
                   1355:                        }
1.1.1.2   root     1356: 
1.1.1.5   root     1357:                        mmu030_opcode = -1;
                   1358:             
                   1359:             M68000_AddCycles(cpu_cycles);
                   1360:             cpu_cycles = nCyclesMainCounter - beforeCycles;
                   1361:             
1.1.1.6 ! root     1362:             run_other_MPUs();
1.1.1.2   root     1363: 
1.1.1.5   root     1364:                        /* We can have several interrupts at the same time before the next CPU instruction */
                   1365:                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   1366:                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   1367:                        /* and prevent exiting the STOP state when calling do_specialties() after. */
                   1368:                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
                   1369:                        while ( ( PendingInterrupt.time <= 0 ) && ( PendingInterrupt.pFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
                   1370:                                CALL_VAR(PendingInterrupt.pFunction);           /* call the interrupt handler */
                   1371:                        }
1.1.1.2   root     1372: 
1.1.1.5   root     1373:             /* Previous: for now we poll the interrupt pins with every instruction.
                   1374:              * TODO: only do this when an actual interrupt is active to not
                   1375:              * unneccessarily slow down emulation.
                   1376:              */
                   1377:             intr = intlev ();
                   1378:             if (intr>regs.intmask || (intr==7 && intr>lastintr))
                   1379:                 do_interrupt (intr, false);
                   1380:             lastintr = intr;
                   1381:             
                   1382:             if(lastRegsS != regs.s) {
                   1383:                 host_realtime(!(regs.s));
                   1384:                 lastRegsS = regs.s;
                   1385:             }
1.1.1.2   root     1386: 
1.1.1.5   root     1387:             if (regs.spcflags & ~SPCFLAG_INT) {
                   1388:                                if (do_specialties (cpu_cycles))
                   1389:                                        return;
                   1390:                        }
                   1391:                }
                   1392:        } CATCH (prb) {
1.1.1.2   root     1393: 
1.1.1.5   root     1394:                regflags.cznv = f.cznv;
                   1395:                regflags.x    = f.x;
1.1.1.2   root     1396: 
1.1.1.5   root     1397:                m68k_setpci (regs.instruction_pc);
1.1.1.2   root     1398: 
1.1.1.5   root     1399:                if (mmufixup[0].reg >= 0) {
                   1400:                        m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                   1401:                        mmufixup[0].reg = -1;
1.1.1.2   root     1402:                }
1.1.1.5   root     1403:                if (mmufixup[1].reg >= 0) {
                   1404:                        m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
                   1405:                        mmufixup[1].reg = -1;
1.1.1.2   root     1406:                }
                   1407: 
1.1.1.5   root     1408:                TRY (prb2) {
                   1409:                        Exception (prb);
                   1410:                } CATCH (prb2) {
                   1411:             write_log("[FATAL] double fault\n");
                   1412:             m68k_reset (1); // auto-reset CPU
                   1413:                        //cpu_halt (1);
                   1414:                        return;
                   1415:                } ENDTRY
                   1416:        } ENDTRY
                   1417:     goto retry;
1.1.1.2   root     1418: }
                   1419: 
1.1.1.5   root     1420: /* Aranym MMU 68040  */
                   1421: static void m68k_run_mmu040 (void)
1.1.1.2   root     1422: {
1.1.1.4   root     1423:        uae_u16 opcode;
                   1424:        struct flag_struct f;
1.1.1.5   root     1425:        f.cznv = 0;
                   1426:        f.x    = 0;
1.1.1.4   root     1427:        uaecptr pc;
                   1428:     int intr = 0;
                   1429:     int lastintr = 0;
1.1.1.6 ! root     1430:     
1.1.1.2   root     1431:        for (;;) {
                   1432:        TRY (prb) {
                   1433:                for (;;) {
1.1.1.4   root     1434:                        f.cznv = regflags.cznv;
                   1435:                        f.x = regflags.x;
                   1436:                        mmu_restart = true;
                   1437:                        pc = regs.instruction_pc = m68k_getpc ();
1.1.1.5   root     1438:         
                   1439:             Uint64 beforeCycles = nCyclesMainCounter;
1.1.1.4   root     1440:                        mmu_opcode = -1;
1.1.1.6 ! root     1441:                        mmu_opcode = opcode = get_iword_mmu040(0);
1.1.1.2   root     1442:                        cpu_cycles = (*cpufunctbl[opcode])(opcode);
1.1.1.5   root     1443:             M68000_AddCycles(cpu_cycles);
                   1444:             cpu_cycles = nCyclesMainCounter - beforeCycles;
1.1.1.2   root     1445: 
1.1.1.6 ! root     1446:             run_other_MPUs();
        !          1447:             
1.1.1.2   root     1448:                        /* We can have several interrupts at the same time before the next CPU instruction */
                   1449:                        /* We must check for pending interrupt and call do_specialties_interrupt() only */
                   1450:                        /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
                   1451:                        /* and prevent exiting the STOP state when calling do_specialties() after. */
                   1452:                        /* For performance, we first test PendingInterruptCount, then regs.spcflags */
1.1.1.5   root     1453:                        while ( ( PendingInterrupt.time <= 0 ) && ( PendingInterrupt.pFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
                   1454:                                CALL_VAR(PendingInterrupt.pFunction);           /* call the interrupt handler */
1.1.1.2   root     1455:                        }
1.1.1.4   root     1456: 
                   1457:             /* Previous: for now we poll the interrupt pins with every instruction.
                   1458:              * TODO: only do this when an actual interrupt is active to not
                   1459:              * unneccessarily slow down emulation.
                   1460:              */
                   1461:             intr = intlev ();
1.1.1.5   root     1462:             if (intr>regs.intmask || (intr==7 && intr>lastintr))
1.1.1.4   root     1463:                 do_interrupt (intr, false);
                   1464:             lastintr = intr;
                   1465:             
1.1.1.5   root     1466:             if(lastRegsS != regs.s) {
                   1467:                 host_realtime(!(regs.s));
                   1468:                 lastRegsS = regs.s;
                   1469:             }
1.1.1.4   root     1470:             
1.1.1.5   root     1471:                        if (regs.spcflags & ~SPCFLAG_INT) {
                   1472:                                if (do_specialties (cpu_cycles))
1.1.1.2   root     1473:                                        return;
                   1474:                        }
                   1475:                } // end of for(;;)
                   1476:        } CATCH (prb) {
                   1477: 
1.1.1.4   root     1478:                if (mmu_restart) {
                   1479:                        /* restore state if instruction restart */
                   1480:                        regflags.cznv = f.cznv;
                   1481:                        regflags.x = f.x;
1.1.1.5   root     1482:                        m68k_setpci (regs.instruction_pc);
1.1.1.4   root     1483:                }
1.1.1.2   root     1484: 
                   1485:                if (mmufixup[0].reg >= 0) {
                   1486:                        m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                   1487:                        mmufixup[0].reg = -1;
                   1488:                }
                   1489: 
1.1.1.5   root     1490:                TRY (prb2) {
                   1491:                        Exception (prb);
                   1492:                } CATCH (prb2) {
                   1493:             write_log("[FATAL] double fault\n");
                   1494:             m68k_reset (1); // auto-reset CPU
                   1495:             //cpu_halt (1);
                   1496:             return;
1.1.1.2   root     1497:                } ENDTRY
                   1498: 
                   1499:        } ENDTRY
                   1500:        }
                   1501: }
                   1502: 
                   1503: #endif /* CPUEMU_0 */
                   1504: 
                   1505: int in_m68k_go = 0;
                   1506: 
1.1.1.5   root     1507: #if 0
1.1.1.2   root     1508: static void exception2_handle (uaecptr addr, uaecptr fault)
                   1509: {
                   1510:        last_addr_for_exception_3 = addr;
                   1511:        last_fault_for_exception_3 = fault;
                   1512:        last_writeaccess_for_exception_3 = 0;
                   1513:        last_instructionaccess_for_exception_3 = 0;
1.1.1.4   root     1514:        Exception (2);
1.1.1.2   root     1515: }
1.1.1.5   root     1516: #endif
1.1.1.2   root     1517: 
                   1518: void m68k_go (int may_quit)
                   1519: {
                   1520:        int hardboot = 1;
                   1521: 
                   1522:        if (in_m68k_go || !may_quit) {
                   1523:                write_log ("Bug! m68k_go is not reentrant.\n");
1.1.1.5   root     1524:         DebugUI();
1.1.1.2   root     1525:        }
1.1.1.5   root     1526:     
1.1.1.2   root     1527:        in_m68k_go++;
                   1528:        for (;;) {
                   1529:                void (*run_func)(void);
                   1530:                
                   1531:                if (regs.spcflags & SPCFLAG_BRK) {
                   1532:                        unset_special(SPCFLAG_BRK);
                   1533:                                break;
                   1534:                }
                   1535: 
                   1536:                        hardboot = 0;
                   1537: 
                   1538: #ifdef DEBUGGER
                   1539:                if (debugging)
                   1540:                        debug ();
                   1541: #endif
1.1.1.5   root     1542:         
1.1.1.2   root     1543:        set_x_funcs ();
1.1.1.5   root     1544:         run_func=currprefs.cpu_model == 68040 ? m68k_run_mmu040 : m68k_run_mmu030;
1.1.1.2   root     1545:                run_func ();
                   1546:        }
                   1547:        in_m68k_go--;
                   1548: }
                   1549: 
                   1550: 
1.1.1.5   root     1551: #if 1
                   1552: TCHAR* buf_out (TCHAR *buffer, int *bufsize, const TCHAR *format, ...)
1.1.1.2   root     1553: {
1.1.1.5   root     1554:     va_list parms;
                   1555:     
                   1556:     if (buffer == NULL)
                   1557:     {
                   1558:         return NULL;
                   1559:     }
                   1560:     
                   1561:     va_start (parms, format);
                   1562:     vsnprintf (buffer, (*bufsize) - 1, format, parms);
                   1563:     va_end (parms);
                   1564:     *bufsize -= _tcslen (buffer);
                   1565:     
                   1566:     return buffer + _tcslen (buffer);
1.1.1.2   root     1567: }
1.1.1.5   root     1568: #endif
1.1.1.2   root     1569: 
1.1.1.5   root     1570: static const TCHAR *ccnames[] =
1.1.1.2   root     1571: {
1.1.1.5   root     1572:     _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
                   1573:     _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
                   1574: };
                   1575: static const TCHAR *fpccnames[] =
                   1576: {
                   1577:     _T("F"),
                   1578:     _T("EQ"),
                   1579:     _T("OGT"),
                   1580:     _T("OGE"),
                   1581:     _T("OLT"),
                   1582:     _T("OLE"),
                   1583:     _T("OGL"),
                   1584:     _T("OR"),
                   1585:     _T("UN"),
                   1586:     _T("UEQ"),
                   1587:     _T("UGT"),
                   1588:     _T("UGE"),
                   1589:     _T("ULT"),
                   1590:     _T("ULE"),
                   1591:     _T("NE"),
                   1592:     _T("T"),
                   1593:     _T("SF"),
                   1594:     _T("SEQ"),
                   1595:     _T("GT"),
                   1596:     _T("GE"),
                   1597:     _T("LT"),
                   1598:     _T("LE"),
                   1599:     _T("GL"),
                   1600:     _T("GLE"),
                   1601:     _T("NGLE"),
                   1602:     _T("NGL"),
                   1603:     _T("NLE"),
                   1604:     _T("NLT"),
                   1605:     _T("NGE"),
                   1606:     _T("NGT"),
                   1607:     _T("SNE"),
                   1608:     _T("ST")
                   1609: };
                   1610: static const TCHAR *fpuopcodes[] =
                   1611: {
                   1612:     _T("FMOVE"),
                   1613:     _T("FINT"),
                   1614:     _T("FSINH"),
                   1615:     _T("FINTRZ"),
                   1616:     _T("FSQRT"),
                   1617:     NULL,
                   1618:     _T("FLOGNP1"),
                   1619:     NULL,
                   1620:     _T("FETOXM1"),
                   1621:     _T("FTANH"),
                   1622:     _T("FATAN"),
                   1623:     NULL,
                   1624:     _T("FASIN"),
                   1625:     _T("FATANH"),
                   1626:     _T("FSIN"),
                   1627:     _T("FTAN"),
                   1628:     _T("FETOX"),       // 0x10
                   1629:     _T("FTWOTOX"),
                   1630:     _T("FTENTOX"),
                   1631:     NULL,
                   1632:     _T("FLOGN"),
                   1633:     _T("FLOG10"),
                   1634:     _T("FLOG2"),
                   1635:     NULL,
                   1636:     _T("FABS"),
                   1637:     _T("FCOSH"),
                   1638:     _T("FNEG"),
                   1639:     NULL,
                   1640:     _T("FACOS"),
                   1641:     _T("FCOS"),
                   1642:     _T("FGETEXP"),
                   1643:     _T("FGETMAN"),
                   1644:     _T("FDIV"),                // 0x20
                   1645:     _T("FMOD"),
                   1646:     _T("FADD"),
                   1647:     _T("FMUL"),
                   1648:     _T("FSGLDIV"),
                   1649:     _T("FREM"),
                   1650:     _T("FSCALE"),
                   1651:     _T("FSGLMUL"),
                   1652:     _T("FSUB"),
                   1653:     NULL,
                   1654:     NULL,
                   1655:     NULL,
                   1656:     NULL,
                   1657:     NULL,
                   1658:     NULL,
                   1659:     NULL,
                   1660:     _T("FSINCOS"),     // 0x30
                   1661:     _T("FSINCOS"),
                   1662:     _T("FSINCOS"),
                   1663:     _T("FSINCOS"),
                   1664:     _T("FSINCOS"),
                   1665:     _T("FSINCOS"),
                   1666:     _T("FSINCOS"),
                   1667:     _T("FSINCOS"),
                   1668:     _T("FCMP"),
                   1669:     NULL,
                   1670:     _T("FTST"),
                   1671:     NULL,
                   1672:     NULL,
                   1673:     NULL,
                   1674:     NULL,
                   1675:     NULL
                   1676: };
1.1.1.2   root     1677: 
1.1.1.5   root     1678: static const TCHAR *movemregs[] =
1.1.1.2   root     1679: {
1.1.1.5   root     1680:     _T("D0"),
                   1681:     _T("D1"),
                   1682:     _T("D2"),
                   1683:     _T("D3"),
                   1684:     _T("D4"),
                   1685:     _T("D5"),
                   1686:     _T("D6"),
                   1687:     _T("D7"),
                   1688:     _T("A0"),
                   1689:     _T("A1"),
                   1690:     _T("A2"),
                   1691:     _T("A3"),
                   1692:     _T("A4"),
                   1693:     _T("A5"),
                   1694:     _T("A6"),
                   1695:     _T("A7"),
                   1696:     _T("FP0"),
                   1697:     _T("FP1"),
                   1698:     _T("FP2"),
                   1699:     _T("FP3"),
                   1700:     _T("FP4"),
                   1701:     _T("FP5"),
                   1702:     _T("FP6"),
                   1703:     _T("FP7"),
                   1704:     _T("FPIAR"),
                   1705:     _T("FPSR"),
                   1706:     _T("FPCR")
                   1707: };
1.1.1.2   root     1708: 
1.1.1.5   root     1709: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
                   1710: {
                   1711:     TCHAR *p = out + _tcslen (out);
                   1712:     if (*prevreg < 0) {
                   1713:         *prevreg = reg;
                   1714:         *lastreg = reg;
                   1715:         return;
                   1716:     }
                   1717:     if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
                   1718:         _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
                   1719:         p = p + _tcslen (p);
                   1720:         if (*lastreg != *prevreg) {
                   1721:             if ((*lastreg) + 2 == reg) {
                   1722:                 _stprintf(p, _T("/%s"), movemregs[*prevreg]);
                   1723:             } else if ((*lastreg) != (*prevreg)) {
                   1724:                 _stprintf(p, _T("-%s"), movemregs[*prevreg]);
                   1725:             }
                   1726:         }
                   1727:         *lastreg = reg;
                   1728:         *first = 0;
                   1729:     }
                   1730:     *prevreg = reg;
1.1.1.2   root     1731: }
                   1732: 
1.1.1.5   root     1733: static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode)
1.1.1.2   root     1734: {
1.1.1.5   root     1735:     unsigned int dmask, amask;
                   1736:     int prevreg = -1, lastreg = -1, first = 1;
                   1737:     int i;
                   1738:     
                   1739:     if (mode == Apdi && !fpmode) {
                   1740:         uae_u8 dmask2;
                   1741:         uae_u8 amask2;
                   1742:         
                   1743:         amask2 = mask & 0xff;
                   1744:         dmask2 = (mask >> 8) & 0xff;
                   1745:         dmask = 0;
                   1746:         amask = 0;
                   1747:         for (i = 0; i < 8; i++) {
                   1748:             if (dmask2 & (1 << i))
                   1749:                 dmask |= 1 << (7 - i);
                   1750:             if (amask2 & (1 << i))
                   1751:                 amask |= 1 << (7 - i);
                   1752:         }
                   1753:     } else {
                   1754:         dmask = mask & 0xff;
                   1755:         amask = (mask >> 8) & 0xff;
                   1756:         if (fpmode == 1 && mode != Apdi) {
                   1757:             uae_u8 dmask2 = dmask;
                   1758:             dmask = 0;
                   1759:             for (i = 0; i < 8; i++) {
                   1760:                 if (dmask2 & (1 << i))
                   1761:                     dmask |= 1 << (7 - i);
                   1762:             }
                   1763:         }
                   1764:     }
                   1765:     if (fpmode) {
                   1766:         while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
                   1767:     } else {
                   1768:         while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
                   1769:         while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
                   1770:     }
                   1771:     addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
                   1772: }
1.1.1.2   root     1773: 
1.1.1.5   root     1774: static const TCHAR *fpsizes[] = {
                   1775:     _T("L"),
                   1776:     _T("S"),
                   1777:     _T("X"),
                   1778:     _T("P"),
                   1779:     _T("W"),
                   1780:     _T("D"),
                   1781:     _T("B"),
                   1782:     _T("P")
                   1783: };
                   1784: static const int fpsizeconv[] = {
                   1785:     sz_long,
                   1786:     sz_single,
                   1787:     sz_extended,
                   1788:     sz_packed,
                   1789:     sz_word,
                   1790:     sz_double,
                   1791:     sz_byte,
                   1792:     sz_packed
                   1793: };
1.1.1.2   root     1794: 
1.1.1.5   root     1795: static void disasm_size (TCHAR *instrname, struct instr *dp)
                   1796: {
                   1797:     if (dp->unsized) {
                   1798:         _tcscat(instrname, _T(" "));
                   1799:         return;
                   1800:     }
                   1801:     switch (dp->size)
                   1802:     {
                   1803:         case sz_byte:
                   1804:             _tcscat (instrname, _T(".B "));
                   1805:             break;
                   1806:         case sz_word:
                   1807:             _tcscat (instrname, _T(".W "));
                   1808:             break;
                   1809:         case sz_long:
                   1810:             _tcscat (instrname, _T(".L "));
                   1811:             break;
                   1812:         default:
                   1813:             _tcscat (instrname, _T(" "));
                   1814:             break;
                   1815:     }
                   1816: }
1.1.1.2   root     1817: 
1.1.1.5   root     1818: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
                   1819: {
                   1820:     uae_u32 seaddr2;
                   1821:     uae_u32 deaddr2;
                   1822:     
                   1823:     if (buf)
                   1824:         memset (buf, 0, bufsize * sizeof (TCHAR));
                   1825:     if (!table68k)
                   1826:         return;
                   1827:     while (cnt-- > 0) {
                   1828:         TCHAR instrname[100], *ccpt;
                   1829:         int i;
                   1830:         uae_u32 opcode;
                   1831:         uae_u16 extra;
                   1832:         struct mnemolookup *lookup;
                   1833:         struct instr *dp;
                   1834:         uaecptr oldpc;
                   1835:         uaecptr m68kpc_illg = 0;
                   1836:         bool illegal = false;
                   1837:         
                   1838:         seaddr2 = deaddr2 = 0;
                   1839:         oldpc = pc;
                   1840:         opcode = get_word_debug (pc);
                   1841:         extra = get_word_debug (pc + 2);
                   1842:         if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
                   1843:             m68kpc_illg = pc + 2;
                   1844:             illegal = true;
                   1845:         }
                   1846:         
                   1847:         dp = table68k + opcode;
                   1848:         if (dp->mnemo == i_ILLG) {
                   1849:             illegal = false;
                   1850:             opcode = 0x4AFC;
                   1851:             dp = table68k + opcode;
                   1852:         }
                   1853:         for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   1854:             ;
                   1855:         
                   1856:         buf = buf_out (buf, &bufsize, _T("%08X "), pc);
                   1857:         
                   1858:         pc += 2;
                   1859:         
                   1860:         if (lookup->friendlyname)
                   1861:             _tcscpy (instrname, lookup->friendlyname);
                   1862:         else
                   1863:             _tcscpy (instrname, lookup->name);
                   1864:         ccpt = _tcsstr (instrname, _T("cc"));
                   1865:         if (ccpt != 0) {
                   1866:             if ((opcode & 0xf000) == 0xf000)
                   1867:                 _tcscpy (ccpt, fpccnames[extra & 0x1f]);
                   1868:             else
                   1869:                 _tcsncpy (ccpt, ccnames[dp->cc], 2);
                   1870:         }
                   1871:         disasm_size (instrname, dp);
                   1872:         
                   1873:         if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
                   1874:             uae_u16 imm = extra;
                   1875:             uae_u16 creg = imm & 0x0fff;
                   1876:             uae_u16 r = imm >> 12;
                   1877:             TCHAR regs[16];
                   1878:             const TCHAR *cname = _T("?");
                   1879:             int i;
                   1880:             for (i = 0; m2cregs[i].regname; i++) {
                   1881:                 if (m2cregs[i].regno == creg)
                   1882:                     break;
                   1883:             }
                   1884:             _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
                   1885:             if (m2cregs[i].regname)
                   1886:                 cname = m2cregs[i].regname;
                   1887:             if (lookup->mnemo == i_MOVE2C) {
                   1888:                 _tcscat (instrname, regs);
                   1889:                 _tcscat (instrname, _T(","));
                   1890:                 _tcscat (instrname, cname);
                   1891:             } else {
                   1892:                 _tcscat (instrname, cname);
                   1893:                 _tcscat (instrname, _T(","));
                   1894:                 _tcscat (instrname, regs);
                   1895:             }
                   1896:             pc += 2;
                   1897:         } else if (lookup->mnemo == i_MVMEL) {
                   1898:             uae_u16 mask = extra;
                   1899:             pc += 2;
                   1900:             pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   1901:             _tcscat (instrname, _T(","));
                   1902:             movemout (instrname, mask, dp->dmode, 0);
                   1903:         } else if (lookup->mnemo == i_MVMLE) {
                   1904:             uae_u16 mask = extra;
                   1905:             pc += 2;
                   1906:             movemout(instrname, mask, dp->dmode, 0);
                   1907:             _tcscat(instrname, _T(","));
                   1908:             pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   1909:         } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
                   1910:             TCHAR *p;
                   1911:             pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   1912:             extra = get_word_debug(pc);
                   1913:             pc += 2;
                   1914:             p = instrname + _tcslen(instrname);
                   1915:             if (extra & 0x0400)
                   1916:                 _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
                   1917:             else
                   1918:                 _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
                   1919:         } else if (lookup->mnemo == i_MOVES) {
                   1920:             TCHAR *p;
                   1921:             pc += 2;
                   1922:             if (!(extra & 0x1000)) {
                   1923:                 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   1924:                 p = instrname + _tcslen(instrname);
                   1925:                 _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                   1926:             } else {
                   1927:                 p = instrname + _tcslen(instrname);
                   1928:                 _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                   1929:                 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   1930:             }
                   1931:         } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
                   1932:                    lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
                   1933:                    lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
                   1934:                    lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
                   1935:             TCHAR *p;
                   1936:             int reg = -1;
                   1937:             
                   1938:             pc += 2;
                   1939:             p = instrname + _tcslen(instrname);
                   1940:             if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
                   1941:                 reg = (extra >> 12) & 7;
                   1942:             if (lookup->mnemo == i_BFINS)
                   1943:                 _stprintf(p, _T("D%d,"), reg);
                   1944:             pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                   1945:             _tcscat(instrname, _T(" {"));
                   1946:             p = instrname + _tcslen(instrname);
                   1947:             if (extra & 0x0800)
                   1948:                 _stprintf(p, _T("D%d"), (extra >> 6) & 7);
                   1949:             else
                   1950:                 _stprintf(p, _T("%d"), (extra >> 6) & 31);
                   1951:             _tcscat(instrname, _T(":"));
                   1952:             p = instrname + _tcslen(instrname);
                   1953:             if (extra & 0x0020)
                   1954:                 _stprintf(p, _T("D%d"), extra & 7);
                   1955:             else
                   1956:                 _stprintf(p, _T("%d"), extra  & 31);
                   1957:             _tcscat(instrname, _T("}"));
                   1958:             p = instrname + _tcslen(instrname);
                   1959:             if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
                   1960:                 _stprintf(p, _T(",D%d"), reg);
                   1961:         } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
                   1962:                    lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
                   1963:             if ((opcode & 0xc0) == 0xc0)
                   1964:                 _tcscat(instrname, _T("BC"));
                   1965:             else if (opcode & 0x80)
                   1966:                 _tcscat(instrname, _T("IC"));
                   1967:             else if (opcode & 0x40)
                   1968:                 _tcscat(instrname, _T("DC"));
                   1969:             else
                   1970:                 _tcscat(instrname, _T("?"));
                   1971:             if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
                   1972:                 TCHAR *p = instrname + _tcslen(instrname);
                   1973:                 _stprintf(p, _T(",(A%d)"), opcode & 7);
                   1974:             }
                   1975:         } else if (lookup->mnemo == i_FPP) {
                   1976:             TCHAR *p;
                   1977:             int ins = extra & 0x3f;
                   1978:             int size = (extra >> 10) & 7;
                   1979:             
                   1980:             pc += 2;
                   1981:             if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
                   1982:                 fptype fp;
                   1983:                 if (fpu_get_constant(&fp, extra & 0x3f))
                   1984:                     _stprintf(instrname, _T("FMOVECR.X #%s,FP%d"), fp_print(&fp), (extra >> 7) & 7);
                   1985:                 else
                   1986:                     _stprintf(instrname, _T("FMOVECR.X #?,FP%d"), (extra >> 7) & 7);
                   1987:             } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
                   1988:                 int dr = (extra >> 13) & 1;
                   1989:                 int mode;
                   1990:                 int dreg = (extra >> 4) & 7;
                   1991:                 int regmask, fpmode;
                   1992:                 
                   1993:                 if (extra & 0x4000) {
                   1994:                     mode = (extra >> 11) & 3;
                   1995:                     regmask = extra & 0xff;  // FMOVEM FPx
                   1996:                     fpmode = 1;
                   1997:                     _tcscpy(instrname, _T("FMOVEM.X "));
                   1998:                 } else {
                   1999:                     mode = 0;
                   2000:                     regmask = (extra >> 10) & 7;  // FMOVEM control
                   2001:                     fpmode = 2;
                   2002:                     _tcscpy(instrname, _T("FMOVEM.L "));
                   2003:                     if (regmask == 1 || regmask == 2 || regmask == 4)
                   2004:                         _tcscpy(instrname, _T("FMOVE.L "));
                   2005:                 }
                   2006:                 p = instrname + _tcslen(instrname);
                   2007:                 if (dr) {
                   2008:                     if (mode & 1)
                   2009:                         _stprintf(instrname, _T("D%d"), dreg);
                   2010:                     else
                   2011:                         movemout(instrname, regmask, dp->dmode, fpmode);
                   2012:                     _tcscat(instrname, _T(","));
                   2013:                     pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   2014:                 } else {
                   2015:                     pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                   2016:                     _tcscat(instrname, _T(","));
                   2017:                     p = instrname + _tcslen(instrname);
                   2018:                     if (mode & 1)
                   2019:                         _stprintf(p, _T("D%d"), dreg);
                   2020:                     else
                   2021:                         movemout(p, regmask, dp->dmode, fpmode);
                   2022:                 }
                   2023:             } else {
                   2024:                 if (fpuopcodes[ins])
                   2025:                     _tcscpy(instrname, fpuopcodes[ins]);
                   2026:                 else
                   2027:                     _tcscpy(instrname, _T("F?"));
                   2028:                 
                   2029:                 if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
                   2030:                     int kfactor = extra & 0x7f;
                   2031:                     _tcscpy(instrname, _T("FMOVE."));
                   2032:                     _tcscat(instrname, fpsizes[size]);
                   2033:                     _tcscat(instrname, _T(" "));
                   2034:                     p = instrname + _tcslen(instrname);
                   2035:                     _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
                   2036:                     pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
                   2037:                     p = instrname + _tcslen(instrname);
                   2038:                     if (size == 7) {
                   2039:                         _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
                   2040:                     } else if (kfactor) {
                   2041:                         if (kfactor & 0x40)
                   2042:                             kfactor |= ~0x3f;
                   2043:                         _stprintf(p, _T(" {%d}"), kfactor);
                   2044:                     }
                   2045:                 } else {
                   2046:                     if (extra & 0x4000) { // source is EA
                   2047:                         _tcscat(instrname, _T("."));
                   2048:                         _tcscat(instrname, fpsizes[size]);
                   2049:                         _tcscat(instrname, _T(" "));
                   2050:                         pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
                   2051:                     } else { // source is FPx
                   2052:                         p = instrname + _tcslen(instrname);
                   2053:                         _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
                   2054:                     }
                   2055:                     p = instrname + _tcslen(instrname);
                   2056:                     if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
                   2057:                         _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
                   2058:                     if (ins >= 0x30 && ins < 0x38) { // FSINCOS
                   2059:                         p = instrname + _tcslen(instrname);
                   2060:                         _stprintf(p, _T(",FP%d"), extra & 7);
                   2061:                     }
                   2062:                 }
                   2063:             }
                   2064:         } else if ((opcode & 0xf000) == 0xa000) {
                   2065:             _tcscpy(instrname, _T("A-LINE"));
                   2066:         } else {
                   2067:             if (dp->suse) {
                   2068:                 pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
                   2069:             }
                   2070:             if (dp->suse && dp->duse)
                   2071:                 _tcscat (instrname, _T(","));
                   2072:             if (dp->duse) {
                   2073:                 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
                   2074:             }
                   2075:         }
                   2076:         
                   2077:         for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) {
                   2078:             buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
                   2079:         }
                   2080:         while (i++ < 5)
                   2081:             buf = buf_out (buf, &bufsize, _T("     "));
                   2082:         
                   2083:         if (illegal)
                   2084:             buf = buf_out (buf, &bufsize, _T("[ "));
                   2085:         buf = buf_out (buf, &bufsize, instrname);
                   2086:         if (illegal)
                   2087:             buf = buf_out (buf, &bufsize, _T(" ]"));
                   2088:         
                   2089:         if (ccpt != 0) {
                   2090:             uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
                   2091:             if (deaddr)
                   2092:                 *deaddr = pc;
                   2093:             if ((opcode & 0xf000) == 0xf000) {
                   2094:                 if (fpp_cond(dp->cc)) {
                   2095:                     buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
                   2096:                 } else {
                   2097:                     buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
                   2098:                 }
                   2099:             } else {
                   2100:                 if (cctrue (dp->cc)) {
                   2101:                     buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
                   2102:                 } else {
                   2103:                     buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
                   2104:                 }
                   2105:             }
                   2106:         } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
                   2107:             if (deaddr)
                   2108:                 *deaddr = pc;
                   2109:             buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
                   2110:         }
                   2111:         buf = buf_out (buf, &bufsize, _T("\n"));
                   2112:         
                   2113:         if (illegal)
                   2114:             pc =  m68kpc_illg;
                   2115:     }
                   2116:     if (nextpc)
                   2117:         *nextpc = pc;
                   2118:     if (seaddr)
                   2119:         *seaddr = seaddr2;
                   2120:     if (deaddr)
                   2121:         *deaddr = deaddr2;
1.1.1.2   root     2122: }
                   2123: 
1.1.1.5   root     2124: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
1.1.1.2   root     2125: {
1.1.1.5   root     2126:     TCHAR *buf;
                   2127:     
                   2128:     buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
                   2129:     if (!buf)
                   2130:         return;
                   2131:     m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
                   2132:     xfree (buf);
1.1.1.2   root     2133: }
1.1.1.5   root     2134: void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.2   root     2135: {
1.1.1.5   root     2136:     TCHAR *buf;
                   2137:     
                   2138:     buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
                   2139:     if (!buf)
                   2140:         return;
                   2141:     m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
                   2142:     printf (_T("%s"), buf);
                   2143:     xfree (buf);
1.1.1.2   root     2144: }
                   2145: 
                   2146: /*************************************************************
                   2147: Disasm the m68kcode at the given address into instrname
                   2148: and instrcode
                   2149: *************************************************************/
                   2150: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
                   2151: {
1.1.1.5   root     2152:     TCHAR *ccpt;
                   2153:     uae_u32 opcode;
                   2154:     struct mnemolookup *lookup;
                   2155:     struct instr *dp;
                   2156:     uaecptr pc, oldpc;
                   2157:     
                   2158:     pc = oldpc = addr;
                   2159:     opcode = get_word_debug (pc);
                   2160:     if (cpufunctbl[opcode] == op_illg_1) {
                   2161:         opcode = 0x4AFC;
                   2162:     }
                   2163:     dp = table68k + opcode;
                   2164:     for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
                   2165:     
                   2166:     pc += 2;
                   2167:     
                   2168:     _tcscpy (instrname, lookup->name);
                   2169:     ccpt = _tcsstr (instrname, _T("cc"));
                   2170:     if (ccpt != 0) {
                   2171:         _tcsncpy (ccpt, ccnames[dp->cc], 2);
                   2172:     }
                   2173:     switch (dp->size){
                   2174:         case sz_byte: _tcscat (instrname, _T(".B ")); break;
                   2175:         case sz_word: _tcscat (instrname, _T(".W ")); break;
                   2176:         case sz_long: _tcscat (instrname, _T(".L ")); break;
                   2177:         default: _tcscat (instrname, _T("   ")); break;
                   2178:     }
                   2179:     
                   2180:     if (dp->suse) {
                   2181:         pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
                   2182:     }
                   2183:     if (dp->suse && dp->duse)
                   2184:         _tcscat (instrname, _T(","));
                   2185:     if (dp->duse) {
                   2186:         pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
                   2187:     }
                   2188:     if (instrcode)
                   2189:     {
                   2190:         int i;
                   2191:         for (i = 0; i < (int)(pc - oldpc) / 2; i++)
                   2192:         {
                   2193:             _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
                   2194:             instrcode += _tcslen (instrcode);
                   2195:         }
                   2196:     }
                   2197:     if (nextpc)
                   2198:         *nextpc = pc;
1.1.1.2   root     2199: }
                   2200: 
                   2201: struct cpum2c m2cregs[] = {
                   2202:        { 0, "SFC" },
                   2203:        { 1, "DFC" },
                   2204:        { 2, "CACR" },
                   2205:        { 3, "TC" },
                   2206:        { 4, "ITT0" },
                   2207:        { 5, "ITT1" },
                   2208:        { 6, "DTT0" },
                   2209:        { 7, "DTT1" },
                   2210:        { 8, "BUSC" },
                   2211:        { 0x800, "USP" },
                   2212:        { 0x801, "VBR" },
                   2213:        { 0x802, "CAAR" },
                   2214:        { 0x803, "MSP" },
                   2215:        { 0x804, "ISP" },
                   2216:        { 0x805, "MMUS" },
                   2217:        { 0x806, "URP" },
                   2218:        { 0x807, "SRP" },
                   2219:        { 0x808, "PCR" },
                   2220:        { -1, NULL }
                   2221: };
                   2222: 
1.1.1.5   root     2223: void m68k_dumpstate_2 (uaecptr pc, uaecptr *nextpc)
1.1.1.2   root     2224: {
1.1.1.5   root     2225:     int i, j;
                   2226:     
                   2227:     for (i = 0; i < 8; i++){
                   2228:         printf (_T("  D%d %08X "), i, m68k_dreg (regs, i));
                   2229:         if ((i & 3) == 3) printf (_T("\n"));
                   2230:     }
                   2231:     for (i = 0; i < 8; i++){
                   2232:         printf (_T("  A%d %08X "), i, m68k_areg (regs, i));
                   2233:         if ((i & 3) == 3) printf (_T("\n"));
                   2234:     }
                   2235:     if (regs.s == 0)
                   2236:         regs.usp = m68k_areg (regs, 7);
                   2237:     if (regs.s && regs.m)
                   2238:         regs.msp = m68k_areg (regs, 7);
                   2239:     if (regs.s && regs.m == 0)
                   2240:         regs.isp = m68k_areg (regs, 7);
                   2241:     j = 2;
                   2242:     printf (_T("USP  %08X ISP  %08X "), regs.usp, regs.isp);
                   2243:     for (i = 0; m2cregs[i].regno>= 0; i++) {
                   2244:         if (!movec_illg (m2cregs[i].regno)) {
                   2245:             if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
                   2246:                 continue;
                   2247:             if (j > 0 && (j % 4) == 0)
                   2248:                 printf (_T("\n"));
                   2249:             printf (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
                   2250:             j++;
                   2251:         }
                   2252:     }
                   2253:     if (j > 0)
                   2254:         printf (_T("\n"));
                   2255:     printf (_T("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n"),
                   2256:                    regs.t1, regs.t0, regs.s, regs.m,
                   2257:                    GET_XFLG (), GET_NFLG (), GET_ZFLG (),
                   2258:                    GET_VFLG (), GET_CFLG (),
                   2259:                    regs.intmask, regs.stopped);
1.1.1.2   root     2260: #ifdef FPUEMU
1.1.1.5   root     2261:     if (currprefs.fpu_model) {
                   2262:         uae_u32 fpsr;
                   2263:         for (i = 0; i < 8; i++){
                   2264:             printf (_T("FP%d: %s "), i, fp_print(&regs.fp[i]));
                   2265:             if ((i & 3) == 3)
                   2266:                 printf (_T("\n"));
                   2267:         }
                   2268:         fpsr = fpp_get_fpsr ();
                   2269:         printf (_T("FPSR: %08X FPCR: %04x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
                   2270:                        fpsr, regs.fpcr, regs.fpiar,
                   2271:                        (fpsr & 0x8000000) != 0,
                   2272:                        (fpsr & 0x4000000) != 0,
                   2273:                        (fpsr & 0x2000000) != 0,
                   2274:                        (fpsr & 0x1000000) != 0);
                   2275:     }
1.1.1.2   root     2276: #endif
1.1.1.4   root     2277:     if (currprefs.mmu_model == 68030) {
1.1.1.5   root     2278:         printf (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
                   2279:         printf (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
                   2280:     }
                   2281:     if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
                   2282:         struct instr *dp;
                   2283:         struct mnemolookup *lookup1, *lookup2;
                   2284:         dp = table68k + regs.irc;
                   2285:         for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
                   2286:         dp = table68k + regs.ir;
                   2287:         for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
                   2288:         printf (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
                   2289:     }
                   2290:     
                   2291:     if (pc != 0xffffffff) {
                   2292:         m68k_disasm (pc, nextpc, 1);
                   2293:         if (nextpc)
                   2294:             printf (_T("Next PC: %08x\n"), *nextpc);
1.1.1.4   root     2295:     }
1.1.1.2   root     2296: }
1.1.1.5   root     2297: void m68k_dumpstate (uaecptr *nextpc)
1.1.1.2   root     2298: {
1.1.1.5   root     2299:     m68k_dumpstate_2 (m68k_getpc (), nextpc);
1.1.1.2   root     2300: }
                   2301: 
1.1.1.5   root     2302: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
1.1.1.2   root     2303: {
1.1.1.5   root     2304:     if (currprefs.cpu_model >= 68040)
                   2305:         addr &= ~1;
                   2306:     if (currprefs.cpu_model >= 68020) {
                   2307:         if (pc == 0xffffffff)
                   2308:             last_addr_for_exception_3 = regs.instruction_pc;
                   2309:         else
                   2310:             last_addr_for_exception_3 = pc;
                   2311:     } else if (pc == 0xffffffff) {
                   2312:         last_addr_for_exception_3 = m68k_getpc ();
                   2313:         if (plus2)
                   2314:             last_addr_for_exception_3 += 2;
                   2315:     } else {
                   2316:         last_addr_for_exception_3 = pc;
                   2317:     }
                   2318:     last_fault_for_exception_3 = addr;
                   2319:     last_op_for_exception_3 = opcode;
                   2320:     last_writeaccess_for_exception_3 = writeaccess;
                   2321:     last_instructionaccess_for_exception_3 = instructionaccess;
                   2322:     Exception (3);
1.1.1.2   root     2323: }
                   2324: 
1.1.1.5   root     2325: void exception3_read(uae_u32 opcode, uaecptr addr)
1.1.1.4   root     2326: {
1.1.1.5   root     2327:     exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
1.1.1.4   root     2328: }
                   2329: void exception3i (uae_u32 opcode, uaecptr addr)
1.1.1.2   root     2330: {
1.1.1.5   root     2331:     exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
1.1.1.4   root     2332: }
                   2333: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
                   2334: {
1.1.1.5   root     2335:     exception3f (opcode, addr, w, i, false, pc, true);
1.1.1.2   root     2336: }
                   2337: 
1.1.1.4   root     2338: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
1.1.1.2   root     2339: {
1.1.1.5   root     2340:     if (currprefs.mmu_model == 68030) {
                   2341:         uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
                   2342:         mmu030_page_fault (addr, read, flags, fc);
                   2343:     } else {
                   2344:         mmu_bus_error (addr, 0, fc, read == false, size, true);
                   2345:     }
1.1.1.2   root     2346: }
                   2347: 
1.1.1.5   root     2348: void cpureset (void) {
1.1.1.2   root     2349:        uaecptr pc;
                   2350:        uaecptr ksboot = 0xf80002 - 2; /* -2 = RESET hasn't increased PC yet */
                   2351:        uae_u16 ins;
                   2352: 
1.1.1.5   root     2353:        if (currprefs.cpu_compatible) {
1.1.1.2   root     2354:                return;
                   2355:        }
1.1.1.5   root     2356:     
1.1.1.2   root     2357:        pc = m68k_getpc ();
                   2358:        /* panic, RAM is going to disappear under PC */
                   2359:        ins = get_word (pc + 2);
                   2360:        if ((ins & ~7) == 0x4ed0) {
                   2361:                int reg = ins & 7;
                   2362:                uae_u32 addr = m68k_areg (regs, reg);
                   2363:                write_log ("reset/jmp (ax) combination emulated -> %x\n", addr);
                   2364:                if (addr < 0x80000)
                   2365:                        addr += 0xf80000;
                   2366:                m68k_setpc (addr - 2);
                   2367:                return;
                   2368:        }
                   2369:        write_log ("M68K RESET PC=%x, rebooting..\n", pc);
                   2370:        m68k_setpc (ksboot);
                   2371: }
                   2372: 
                   2373: 
                   2374: void m68k_setstopped (void)
                   2375: {
                   2376:        regs.stopped = 1;
                   2377:        /* A traced STOP instruction drops through immediately without
                   2378:        actually stopping.  */
                   2379:        if ((regs.spcflags & SPCFLAG_DOTRACE) == 0)
                   2380:                set_special (SPCFLAG_STOP);
                   2381:        else
                   2382:                m68k_resumestopped ();
                   2383: }
                   2384: 
                   2385: void m68k_resumestopped (void)
                   2386: {
                   2387:        if (!regs.stopped)
                   2388:                return;
                   2389:        regs.stopped = 0;
                   2390:        unset_special (SPCFLAG_STOP);
                   2391: }

unix.superglobalmegacorp.com

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