Annotation of uae/src/newcpu.c, revision 1.1.1.24

1.1.1.3   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.3   root        3:   *
1.1       root        4:   * MC68000 emulation
                      5:   *
                      6:   * (c) 1995 Bernd Schmidt
                      7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include "options.h"
                     13: #include "events.h"
1.1.1.3   root       14: #include "uae.h"
1.1       root       15: #include "memory.h"
                     16: #include "custom.h"
                     17: #include "newcpu.h"
1.1.1.23  root       18: #include "traps.h"
1.1.1.24! root       19: #include "autoconf.h"
1.1       root       20: #include "ersatz.h"
                     21: #include "debug.h"
1.1.1.3   root       22: #include "gui.h"
1.1.1.14  root       23: #include "savestate.h"
1.1.1.18  root       24: #include "blitter.h"
1.1.1.3   root       25: 
                     26: /* Opcode of faulting instruction */
1.1.1.20  root       27: static uae_u16 last_op_for_exception_3;
1.1.1.3   root       28: /* PC at fault time */
1.1.1.20  root       29: static uaecptr last_addr_for_exception_3;
1.1.1.3   root       30: /* Address that generated the exception */
1.1.1.20  root       31: static uaecptr last_fault_for_exception_3;
                     32: /* read (0) or write (1) access */
                     33: static int last_writeaccess_for_exception_3;
                     34: /* instruction (1) or data (0) access */
                     35: static int last_instructionaccess_for_exception_3;
1.1       root       36: 
1.1.1.23  root       37: const int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
                     38: const int imm8_table[] = { 8,1,2,3,4,5,6,7 };
1.1       root       39: 
                     40: int movem_index1[256];
                     41: int movem_index2[256];
                     42: int movem_next[256];
                     43: 
                     44: int fpp_movem_index1[256];
                     45: int fpp_movem_index2[256];
                     46: int fpp_movem_next[256];
                     47: 
                     48: cpuop_func *cpufunctbl[65536];
                     49: 
1.1.1.3   root       50: #define COUNT_INSTRS 0
1.1       root       51: 
                     52: #if COUNT_INSTRS
                     53: static unsigned long int instrcount[65536];
1.1.1.3   root       54: static uae_u16 opcodenums[65536];
1.1       root       55: 
1.1.1.4   root       56: static int compfn (const void *el1, const void *el2)
1.1       root       57: {
1.1.1.3   root       58:     return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
                     59: }
                     60: 
                     61: static char *icountfilename (void)
                     62: {
                     63:     char *name = getenv ("INSNCOUNT");
                     64:     if (name)
                     65:        return name;
                     66:     return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
1.1       root       67: }
                     68: 
1.1.1.4   root       69: void dump_counts (void)
1.1       root       70: {
1.1.1.4   root       71:     FILE *f = fopen (icountfilename (), "w");
1.1.1.3   root       72:     unsigned long int total;
1.1       root       73:     int i;
1.1.1.3   root       74: 
                     75:     write_log ("Writing instruction count file...\n");
1.1.1.4   root       76:     for (i = 0; i < 65536; i++) {
1.1       root       77:        opcodenums[i] = i;
1.1.1.3   root       78:        total += instrcount[i];
1.1       root       79:     }
1.1.1.4   root       80:     qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
1.1.1.3   root       81: 
                     82:     fprintf (f, "Total: %lu\n", total);
                     83:     for (i=0; i < 65536; i++) {
1.1       root       84:        unsigned long int cnt = instrcount[opcodenums[i]];
                     85:        struct instr *dp;
                     86:        struct mnemolookup *lookup;
                     87:        if (!cnt)
                     88:            break;
                     89:        dp = table68k + opcodenums[i];
1.1.1.4   root       90:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                     91:            ;
1.1.1.3   root       92:        fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
1.1       root       93:     }
1.1.1.4   root       94:     fclose (f);
1.1       root       95: }
                     96: #else
1.1.1.4   root       97: void dump_counts (void)
1.1       root       98: {
                     99: }
                    100: #endif
                    101: 
                    102: int broken_in;
                    103: 
1.1.1.4   root      104: static unsigned long op_illg_1 (uae_u32 opcode) REGPARAM;
                    105: 
                    106: static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode)
                    107: {
1.1.1.8   root      108:     op_illg (opcode);
1.1.1.4   root      109:     return 4;
                    110: }
                    111: 
1.1.1.3   root      112: static void build_cpufunctbl (void)
                    113: {
1.1.1.24! root      114:     int i, opcnt;
1.1.1.3   root      115:     unsigned long opcode;
1.1.1.24! root      116:     const struct cputbl *tbl = 0;
        !           117:     int lvl;
1.1.1.3   root      118: 
1.1.1.24! root      119:     switch (currprefs.cpu_model) {
        !           120:     case 68060:
        !           121:        lvl = 5;
        !           122:        tbl = op_smalltbl_0_ff;
        !           123:        break;
        !           124:     case 68040:
        !           125:        lvl = 4;
        !           126:        tbl = op_smalltbl_1_ff;
        !           127:        break;
        !           128:     case 68030:
        !           129:        lvl = 3;
        !           130:        tbl = op_smalltbl_2_ff;
        !           131:        break;
        !           132:     case 68020:
        !           133:        tbl = op_smalltbl_3_ff;
        !           134:        lvl = 2;
        !           135:        break;
        !           136:     case 68010:
        !           137:        tbl = op_smalltbl_4_ff;
        !           138:        lvl = 1;
        !           139:        break;
        !           140:     case 68000:
        !           141:        lvl = 0;
        !           142:        tbl = op_smalltbl_6_ff;
        !           143:        break;
        !           144:     }
        !           145: 
        !           146:     if (tbl == 0) {
        !           147:        write_log ("no CPU emulation cores available!");
        !           148:        abort ();
        !           149:     }
1.1.1.3   root      150: 
                    151:     for (opcode = 0; opcode < 65536; opcode++)
1.1.1.8   root      152:        cpufunctbl[opcode] = op_illg_1;
1.1.1.3   root      153:     for (i = 0; tbl[i].handler != NULL; i++) {
                    154:        if (! tbl[i].specific)
1.1.1.8   root      155:            cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1.1.1.3   root      156:     }
1.1.1.24! root      157: 
        !           158:     opcnt = 0;
1.1.1.3   root      159:     for (opcode = 0; opcode < 65536; opcode++) {
                    160:        cpuop_func *f;
                    161: 
1.1.1.24! root      162:        if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > lvl)
1.1.1.3   root      163:            continue;
                    164: 
                    165:        if (table68k[opcode].handler != -1) {
1.1.1.8   root      166:            f = cpufunctbl[table68k[opcode].handler];
1.1.1.4   root      167:            if (f == op_illg_1)
1.1.1.3   root      168:                abort();
1.1.1.8   root      169:            cpufunctbl[opcode] = f;
1.1.1.24! root      170:            opcnt++;
1.1.1.3   root      171:        }
                    172:     }
                    173:     for (i = 0; tbl[i].handler != NULL; i++) {
                    174:        if (tbl[i].specific)
1.1.1.8   root      175:            cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1.1.1.4   root      176:     }
1.1.1.24! root      177:     write_log ("Building CPU, %d opcodes (%d). CPU=%d, FPU=%d\n",
        !           178:               opcnt,
        !           179:               currprefs.address_space_24, currprefs.cpu_model, currprefs.fpu_model);
1.1.1.4   root      180: }
                    181: 
1.1.1.20  root      182: void fill_prefetch_slow (void)
                    183: {
                    184: #ifdef CPUEMU_6
                    185:     if (currprefs.cpu_cycle_exact) {
                    186:        regs.ir = get_word_ce (m68k_getpc ());
                    187:        regs.irc = get_word_ce (m68k_getpc () + 2);
                    188:     } else {
                    189: #endif
                    190:        regs.ir = get_word (m68k_getpc ());
                    191:        regs.irc = get_word (m68k_getpc () + 2);
                    192: #ifdef CPUEMU_6
                    193:     }
                    194: #endif
                    195: }
                    196: 
1.1.1.4   root      197: unsigned long cycles_mask, cycles_val;
                    198: 
                    199: static void update_68k_cycles (void)
                    200: {
                    201:     cycles_mask = 0;
                    202:     cycles_val = currprefs.m68k_speed;
                    203:     if (currprefs.m68k_speed < 1) {
                    204:        cycles_mask = 0xFFFFFFFF;
                    205:        cycles_val = 0;
1.1.1.3   root      206:     }
                    207: }
                    208: 
                    209: void check_prefs_changed_cpu (void)
                    210: {
1.1.1.4   root      211:     if (currprefs.m68k_speed != changed_prefs.m68k_speed) {
                    212:        currprefs.m68k_speed = changed_prefs.m68k_speed;
                    213:        reset_frame_rate_hack ();
                    214:        update_68k_cycles ();
                    215:     }
1.1.1.3   root      216: }
                    217: 
1.1       root      218: void init_m68k (void)
                    219: {
1.1.1.3   root      220:     int i;
                    221: 
1.1.1.4   root      222:     update_68k_cycles ();
                    223: 
1.1       root      224:     for (i = 0 ; i < 256 ; i++) {
1.1.1.3   root      225:        int j;
1.1       root      226:        for (j = 0 ; j < 8 ; j++) {
                    227:                if (i & (1 << j)) break;
                    228:        }
                    229:        movem_index1[i] = j;
                    230:        movem_index2[i] = 7-j;
                    231:        movem_next[i] = i & (~(1 << j));
                    232:     }
                    233:     for (i = 0 ; i < 256 ; i++) {
1.1.1.3   root      234:        int j;
1.1       root      235:        for (j = 7 ; j >= 0 ; j--) {
                    236:                if (i & (1 << j)) break;
                    237:        }
1.1.1.8   root      238:        fpp_movem_index1[i] = 7-j;
                    239:        fpp_movem_index2[i] = j;
1.1       root      240:        fpp_movem_next[i] = i & (~(1 << j));
                    241:     }
                    242: #if COUNT_INSTRS
                    243:     {
1.1.1.4   root      244:        FILE *f = fopen (icountfilename (), "r");
                    245:        memset (instrcount, 0, sizeof instrcount);
1.1       root      246:        if (f) {
1.1.1.3   root      247:            uae_u32 opcode, count, total;
1.1       root      248:            char name[20];
1.1.1.3   root      249:            write_log ("Reading instruction count file...\n");
1.1.1.4   root      250:            fscanf (f, "Total: %lu\n", &total);
                    251:            while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
1.1       root      252:                instrcount[opcode] = count;
                    253:            }
                    254:            fclose(f);
                    255:        }
                    256:     }
                    257: #endif
1.1.1.5   root      258:     write_log ("Building CPU table for configuration: 68");
1.1.1.20  root      259:     regs.address_space_mask = 0xffffffff;
1.1.1.24! root      260:     if (currprefs.address_space_24 && currprefs.cpu_model > 68010)
1.1.1.21  root      261:        write_log ("EC");
1.1.1.24! root      262:     write_log ("%03d", currprefs.cpu_model % 1000);
        !           263:     if (currprefs.fpu_model == 68881 || currprefs.fpu_model == 68882)
        !           264:        write_log ("/%d", currprefs.fpu_model % 1000);
1.1.1.20  root      265:     if (currprefs.address_space_24) {
                    266:        regs.address_space_mask = 0x00ffffff;
                    267:        write_log (" 24-bit addressing");
                    268:     }
1.1.1.5   root      269:     write_log ("\n");
1.1.1.22  root      270: 
1.1       root      271:     read_table68k ();
                    272:     do_merges ();
1.1.1.2   root      273: 
1.1.1.4   root      274:     write_log ("%d CPU functions\n", nr_cpuop_funcs);
1.1       root      275: 
1.1.1.3   root      276:     build_cpufunctbl ();
                    277: }
1.1.1.4   root      278: 
1.1       root      279: struct regstruct regs, lastint_regs;
                    280: static struct regstruct regs_backup[16];
                    281: static int backup_pointer = 0;
1.1.1.3   root      282: static long int m68kpc_offset;
1.1       root      283: int lastint_no;
                    284: 
1.1.1.24! root      285: #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
        !           286: #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
        !           287: #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1.1.1.3   root      288: 
1.1.1.11  root      289: uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf)
1.1.1.3   root      290: {
                    291:     uae_u16 dp;
                    292:     uae_s8 disp8;
                    293:     uae_s16 disp16;
1.1       root      294:     int r;
1.1.1.3   root      295:     uae_u32 dispreg;
                    296:     uaecptr addr;
                    297:     uae_s32 offset = 0;
1.1.1.2   root      298:     char buffer[80];
1.1.1.3   root      299: 
                    300:     switch (mode){
1.1       root      301:      case Dreg:
1.1.1.24! root      302:        sprintf (buffer, "D%d", reg);
1.1       root      303:        break;
                    304:      case Areg:
1.1.1.24! root      305:        sprintf (buffer, "A%d", reg);
1.1       root      306:        break;
                    307:      case Aind:
1.1.1.24! root      308:        sprintf (buffer, "(A%d)", reg);
1.1       root      309:        break;
                    310:      case Aipi:
1.1.1.24! root      311:        sprintf (buffer, "(A%d)+", reg);
1.1       root      312:        break;
                    313:      case Apdi:
1.1.1.24! root      314:        sprintf (buffer, "-(A%d)", reg);
1.1       root      315:        break;
                    316:      case Ad16:
1.1.1.4   root      317:        disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1.1.23  root      318:        addr = m68k_areg (regs,reg) + (uae_s16)disp16;
1.1.1.24! root      319:        sprintf (buffer, "(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff,
1.1.1.8   root      320:                                        (unsigned long)addr);
1.1       root      321:        break;
                    322:      case Ad8r:
1.1.1.4   root      323:        dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1       root      324:        disp8 = dp & 0xFF;
                    325:        r = (dp & 0x7000) >> 12;
1.1.1.24! root      326:        dispreg = dp & 0x8000 ? m68k_areg (regs,r) : m68k_dreg (regs,r);
1.1.1.3   root      327:        if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1.1       root      328:        dispreg <<= (dp >> 9) & 3;
1.1.1.3   root      329: 
1.1       root      330:        if (dp & 0x100) {
1.1.1.3   root      331:            uae_s32 outer = 0, disp = 0;
1.1.1.23  root      332:            uae_s32 base = m68k_areg (regs,reg);
1.1.1.3   root      333:            char name[10];
                    334:            sprintf (name,"A%d, ",reg);
                    335:            if (dp & 0x80) { base = 0; name[0] = 0; }
                    336:            if (dp & 0x40) dispreg = 0;
1.1.1.4   root      337:            if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                    338:            if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1.1.1.3   root      339:            base += disp;
                    340: 
1.1.1.4   root      341:            if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                    342:            if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1.1.1.3   root      343: 
                    344:            if (!(dp & 4)) base += dispreg;
                    345:            if (dp & 3) base = get_long (base);
                    346:            if (dp & 4) base += dispreg;
                    347: 
                    348:            addr = base + outer;
1.1.1.24! root      349:            sprintf (buffer, "(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
1.1.1.3   root      350:                    dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    351:                    1 << ((dp >> 9) & 3),
                    352:                    disp,outer,
1.1.1.8   root      353:                    (unsigned long)addr);
1.1.1.3   root      354:        } else {
1.1.1.23  root      355:          addr = m68k_areg (regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.24! root      356:          sprintf (buffer, "(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg,
1.1       root      357:               dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    358:               1 << ((dp >> 9) & 3), disp8,
1.1.1.8   root      359:               (unsigned long)addr);
1.1       root      360:        }
                    361:        break;
                    362:      case PC16:
1.1.1.4   root      363:        addr = m68k_getpc () + m68kpc_offset;
                    364:        disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1.1.3   root      365:        addr += (uae_s16)disp16;
1.1.1.24! root      366:        sprintf (buffer, "(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr);
1.1       root      367:        break;
                    368:      case PC8r:
1.1.1.4   root      369:        addr = m68k_getpc () + m68kpc_offset;
                    370:        dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1       root      371:        disp8 = dp & 0xFF;
                    372:        r = (dp & 0x7000) >> 12;
1.1.1.24! root      373:        dispreg = dp & 0x8000 ? m68k_areg (regs,r) : m68k_dreg (regs,r);
1.1.1.3   root      374:        if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1.1       root      375:        dispreg <<= (dp >> 9) & 3;
1.1.1.3   root      376: 
1.1       root      377:        if (dp & 0x100) {
1.1.1.3   root      378:            uae_s32 outer = 0,disp = 0;
                    379:            uae_s32 base = addr;
                    380:            char name[10];
                    381:            sprintf (name,"PC, ");
                    382:            if (dp & 0x80) { base = 0; name[0] = 0; }
                    383:            if (dp & 0x40) dispreg = 0;
1.1.1.4   root      384:            if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                    385:            if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1.1.1.3   root      386:            base += disp;
                    387: 
1.1.1.4   root      388:            if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                    389:            if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1.1.1.3   root      390: 
                    391:            if (!(dp & 4)) base += dispreg;
                    392:            if (dp & 3) base = get_long (base);
                    393:            if (dp & 4) base += dispreg;
                    394: 
                    395:            addr = base + outer;
1.1.1.24! root      396:            sprintf (buffer, "(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
1.1.1.3   root      397:                    dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    398:                    1 << ((dp >> 9) & 3),
                    399:                    disp,outer,
1.1.1.8   root      400:                    (unsigned long)addr);
1.1.1.2   root      401:        } else {
1.1.1.3   root      402:          addr += (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.24! root      403:          sprintf (buffer, "(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D',
1.1       root      404:                (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
1.1.1.8   root      405:                disp8, (unsigned long)addr);
1.1       root      406:        }
                    407:        break;
                    408:      case absw:
1.1.1.24! root      409:        sprintf (buffer, "$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset));
1.1.1.3   root      410:        m68kpc_offset += 2;
1.1       root      411:        break;
                    412:      case absl:
1.1.1.24! root      413:        sprintf (buffer, "$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset));
1.1.1.3   root      414:        m68kpc_offset += 4;
1.1       root      415:        break;
                    416:      case imm:
1.1.1.3   root      417:        switch (size){
1.1       root      418:         case sz_byte:
1.1.1.24! root      419:            sprintf (buffer, "#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff));
1.1.1.3   root      420:            m68kpc_offset += 2;
                    421:            break;
1.1       root      422:         case sz_word:
1.1.1.24! root      423:            sprintf (buffer, "#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff));
1.1.1.3   root      424:            m68kpc_offset += 2;
                    425:            break;
1.1       root      426:         case sz_long:
1.1.1.24! root      427:            sprintf (buffer, "#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
1.1.1.3   root      428:            m68kpc_offset += 4;
                    429:            break;
1.1       root      430:         default:
                    431:            break;
                    432:        }
                    433:        break;
                    434:      case imm0:
1.1.1.4   root      435:        offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
1.1.1.3   root      436:        m68kpc_offset += 2;
1.1.1.24! root      437:        sprintf (buffer, "#$%02x", (unsigned int)(offset & 0xff));
1.1       root      438:        break;
                    439:      case imm1:
1.1.1.4   root      440:        offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1.1.1.3   root      441:        m68kpc_offset += 2;
1.1.1.24! root      442:        sprintf (buffer, "#$%04x", (unsigned int)(offset & 0xffff));
1.1       root      443:        break;
                    444:      case imm2:
1.1.1.4   root      445:        offset = (uae_s32)get_ilong_1 (m68kpc_offset);
1.1.1.3   root      446:        m68kpc_offset += 4;
1.1.1.24! root      447:        sprintf (buffer, "#$%08lx", (unsigned long)offset);
1.1       root      448:        break;
                    449:      case immi:
1.1.1.3   root      450:        offset = (uae_s32)(uae_s8)(reg & 0xff);
1.1.1.24! root      451:        sprintf (buffer, "#$%08lx", (unsigned long)offset);
1.1       root      452:        break;
                    453:      default:
                    454:        break;
                    455:     }
1.1.1.2   root      456:     if (buf == 0)
1.1.1.11  root      457:        fprintf (f, "%s", buffer);
1.1.1.2   root      458:     else
1.1.1.4   root      459:        strcat (buf, buffer);
1.1.1.2   root      460:     return offset;
1.1       root      461: }
                    462: 
1.1.1.3   root      463: /* The plan is that this will take over the job of exception 3 handling -
                    464:  * the CPU emulation functions will just do a longjmp to m68k_go whenever
                    465:  * they hit an odd address. */
1.1.1.4   root      466: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
1.1.1.3   root      467: {
                    468:     uae_u16 dp;
                    469:     uae_s8 disp8;
                    470:     uae_s16 disp16;
                    471:     int r;
                    472:     uae_u32 dispreg;
                    473:     uaecptr addr;
                    474:     uae_s32 offset = 0;
                    475: 
                    476:     switch (mode){
                    477:      case Dreg:
                    478:        *val = m68k_dreg (regs, reg);
                    479:        return 1;
                    480:      case Areg:
                    481:        *val = m68k_areg (regs, reg);
                    482:        return 1;
                    483: 
                    484:      case Aind:
                    485:      case Aipi:
                    486:        addr = m68k_areg (regs, reg);
                    487:        break;
                    488:      case Apdi:
                    489:        addr = m68k_areg (regs, reg);
                    490:        break;
                    491:      case Ad16:
1.1.1.4   root      492:        disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1.1.23  root      493:        addr = m68k_areg (regs,reg) + (uae_s16)disp16;
1.1.1.3   root      494:        break;
                    495:      case Ad8r:
                    496:        addr = m68k_areg (regs, reg);
                    497:      d8r_common:
1.1.1.4   root      498:        dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1.1.3   root      499:        disp8 = dp & 0xFF;
                    500:        r = (dp & 0x7000) >> 12;
1.1.1.24! root      501:        dispreg = dp & 0x8000 ? m68k_areg (regs,r) : m68k_dreg (regs,r);
1.1.1.3   root      502:        if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
                    503:        dispreg <<= (dp >> 9) & 3;
                    504: 
                    505:        if (dp & 0x100) {
                    506:            uae_s32 outer = 0, disp = 0;
                    507:            uae_s32 base = addr;
                    508:            if (dp & 0x80) base = 0;
                    509:            if (dp & 0x40) dispreg = 0;
1.1.1.4   root      510:            if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                    511:            if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1.1.1.3   root      512:            base += disp;
                    513: 
1.1.1.4   root      514:            if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
                    515:            if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1.1.1.3   root      516: 
                    517:            if (!(dp & 4)) base += dispreg;
                    518:            if (dp & 3) base = get_long (base);
                    519:            if (dp & 4) base += dispreg;
                    520: 
                    521:            addr = base + outer;
                    522:        } else {
                    523:          addr += (uae_s32)((uae_s8)disp8) + dispreg;
                    524:        }
                    525:        break;
                    526:      case PC16:
1.1.1.4   root      527:        addr = m68k_getpc () + m68kpc_offset;
                    528:        disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1.1.1.3   root      529:        addr += (uae_s16)disp16;
                    530:        break;
                    531:      case PC8r:
1.1.1.4   root      532:        addr = m68k_getpc () + m68kpc_offset;
1.1.1.3   root      533:        goto d8r_common;
                    534:      case absw:
1.1.1.4   root      535:        addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1.1.1.3   root      536:        m68kpc_offset += 2;
                    537:        break;
                    538:      case absl:
1.1.1.4   root      539:        addr = get_ilong_1 (m68kpc_offset);
1.1.1.3   root      540:        m68kpc_offset += 4;
                    541:        break;
                    542:      case imm:
                    543:        switch (size){
                    544:         case sz_byte:
1.1.1.4   root      545:            *val = get_iword_1 (m68kpc_offset) & 0xff;
1.1.1.3   root      546:            m68kpc_offset += 2;
                    547:            break;
                    548:         case sz_word:
1.1.1.4   root      549:            *val = get_iword_1 (m68kpc_offset) & 0xffff;
1.1.1.3   root      550:            m68kpc_offset += 2;
                    551:            break;
                    552:         case sz_long:
1.1.1.4   root      553:            *val = get_ilong_1 (m68kpc_offset);
1.1.1.3   root      554:            m68kpc_offset += 4;
                    555:            break;
                    556:         default:
                    557:            break;
                    558:        }
                    559:        return 1;
                    560:      case imm0:
                    561:        *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
                    562:        m68kpc_offset += 2;
                    563:        return 1;
                    564:      case imm1:
                    565:        *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
                    566:        m68kpc_offset += 2;
                    567:        return 1;
                    568:      case imm2:
                    569:        *val = get_ilong_1 (m68kpc_offset);
                    570:        m68kpc_offset += 4;
                    571:        return 1;
                    572:      case immi:
                    573:        *val = (uae_s32)(uae_s8)(reg & 0xff);
                    574:        return 1;
                    575:      default:
                    576:        addr = 0;
                    577:        break;
                    578:     }
                    579:     if ((addr & 1) == 0)
                    580:        return 1;
                    581: 
1.1.1.4   root      582:     last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
1.1.1.3   root      583:     last_fault_for_exception_3 = addr;
1.1.1.20  root      584:     last_writeaccess_for_exception_3 = 0;
                    585:     last_instructionaccess_for_exception_3 = 0;
1.1.1.3   root      586:     return 0;
                    587: }
                    588: 
1.1.1.5   root      589: uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
                    590: {
                    591:     int reg = (dp >> 12) & 15;
                    592:     uae_s32 regd = regs.regs[reg];
                    593:     if ((dp & 0x800) == 0)
                    594:        regd = (uae_s32)(uae_s16)regd;
                    595:     regd <<= (dp >> 9) & 3;
                    596:     if (dp & 0x100) {
                    597:        uae_s32 outer = 0;
                    598:        if (dp & 0x80) base = 0;
                    599:        if (dp & 0x40) regd = 0;
                    600: 
                    601:        if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword();
                    602:        if ((dp & 0x30) == 0x30) base += next_ilong();
                    603: 
                    604:        if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword();
                    605:        if ((dp & 0x3) == 0x3) outer = next_ilong();
                    606: 
                    607:        if ((dp & 0x4) == 0) base += regd;
                    608:        if (dp & 0x3) base = get_long (base);
                    609:        if (dp & 0x4) base += regd;
                    610: 
                    611:        return base + outer;
                    612:     } else {
                    613:        return base + (uae_s32)((uae_s8)dp) + regd;
                    614:     }
                    615: }
                    616: 
                    617: uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
                    618: {
                    619:     int reg = (dp >> 12) & 15;
                    620:     uae_s32 regd = regs.regs[reg];
                    621: #if 1
                    622:     if ((dp & 0x800) == 0)
                    623:        regd = (uae_s32)(uae_s16)regd;
                    624:     return base + (uae_s8)dp + regd;
                    625: #else
                    626:     /* Branch-free code... benchmark this again now that
                    627:      * things are no longer inline.  */
                    628:     uae_s32 regd16;
                    629:     uae_u32 mask;
                    630:     mask = ((dp & 0x800) >> 11) - 1;
                    631:     regd16 = (uae_s32)(uae_s16)regd;
                    632:     regd16 &= mask;
                    633:     mask = ~mask;
                    634:     base += (uae_s8)dp;
                    635:     regd &= mask;
                    636:     regd |= regd16;
                    637:     return base + regd;
                    638: #endif
                    639: }
                    640: 
1.1.1.4   root      641: void MakeSR (void)
1.1       root      642: {
                    643: #if 0
                    644:     assert((regs.t1 & 1) == regs.t1);
                    645:     assert((regs.t0 & 1) == regs.t0);
                    646:     assert((regs.s & 1) == regs.s);
                    647:     assert((regs.m & 1) == regs.m);
                    648:     assert((XFLG & 1) == XFLG);
                    649:     assert((NFLG & 1) == NFLG);
                    650:     assert((ZFLG & 1) == ZFLG);
                    651:     assert((VFLG & 1) == VFLG);
                    652:     assert((CFLG & 1) == CFLG);
                    653: #endif
                    654:     regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
                    655:               | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
1.1.1.6   root      656:               | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1)
                    657:               | GET_CFLG);
1.1       root      658: }
                    659: 
1.1.1.4   root      660: void MakeFromSR (void)
1.1       root      661: {
                    662:     int oldm = regs.m;
                    663:     int olds = regs.s;
                    664: 
                    665:     regs.t1 = (regs.sr >> 15) & 1;
                    666:     regs.t0 = (regs.sr >> 14) & 1;
                    667:     regs.s = (regs.sr >> 13) & 1;
                    668:     regs.m = (regs.sr >> 12) & 1;
                    669:     regs.intmask = (regs.sr >> 8) & 7;
1.1.1.6   root      670:     SET_XFLG ((regs.sr >> 4) & 1);
                    671:     SET_NFLG ((regs.sr >> 3) & 1);
                    672:     SET_ZFLG ((regs.sr >> 2) & 1);
                    673:     SET_VFLG ((regs.sr >> 1) & 1);
                    674:     SET_CFLG (regs.sr & 1);
1.1.1.24! root      675:     if (currprefs.cpu_model >= 68020) {
1.1       root      676:        if (olds != regs.s) {
1.1.1.3   root      677:            if (olds) {
                    678:                if (oldm)
1.1.1.23  root      679:                    regs.msp = m68k_areg (regs, 7);
1.1.1.3   root      680:                else
1.1.1.23  root      681:                    regs.isp = m68k_areg (regs, 7);
                    682:                m68k_areg (regs, 7) = regs.usp;
1.1.1.3   root      683:            } else {
1.1.1.23  root      684:                regs.usp = m68k_areg (regs, 7);
                    685:                m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.3   root      686:            }
1.1       root      687:        } else if (olds && oldm != regs.m) {
                    688:            if (oldm) {
1.1.1.23  root      689:                regs.msp = m68k_areg (regs, 7);
                    690:                m68k_areg (regs, 7) = regs.isp;
1.1.1.2   root      691:            } else {
1.1.1.23  root      692:                regs.isp = m68k_areg (regs, 7);
                    693:                m68k_areg (regs, 7) = regs.msp;
1.1       root      694:            }
                    695:        }
                    696:     } else {
                    697:        if (olds != regs.s) {
1.1.1.3   root      698:            if (olds) {
1.1.1.23  root      699:                regs.isp = m68k_areg (regs, 7);
                    700:                m68k_areg (regs, 7) = regs.usp;
1.1.1.3   root      701:            } else {
1.1.1.23  root      702:                regs.usp = m68k_areg (regs, 7);
                    703:                m68k_areg (regs, 7) = regs.isp;
1.1.1.3   root      704:            }
                    705:        }
1.1       root      706:     }
1.1.1.3   root      707: 
1.1.1.12  root      708:     set_special (SPCFLAG_INT);
1.1       root      709:     if (regs.t1 || regs.t0)
1.1.1.12  root      710:        set_special (SPCFLAG_TRACE);
1.1       root      711:     else
1.1.1.22  root      712:        /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
1.1.1.16  root      713:           SR-modifying instructions (including STOP).  */
                    714:        unset_special (SPCFLAG_TRACE);
1.1       root      715: }
                    716: 
1.1.1.20  root      717: static void exception_trace (int nr)
1.1       root      718: {
1.1.1.20  root      719:     unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                    720:     if (regs.t1 && !regs.t0) {
                    721:        /* trace stays pending if exception is div by zero, chk,
                    722:         * trapv or trap #x
                    723:         */
                    724:        if (nr == 5 || nr == 6 || nr ==  7 || (nr >= 32 && nr <= 47))
                    725:            set_special (SPCFLAG_DOTRACE);
                    726:     }
                    727:     regs.t1 = regs.t0 = regs.m = 0;
                    728: }
1.1.1.12  root      729: 
1.1.1.20  root      730: static void exception_debug (int nr)
                    731: {
                    732: #ifdef DEBUGGER
                    733:     if (!exception_debugging)
                    734:        return;
1.1.1.24! root      735:     console_out ("Exception %d, PC=%08.8X\n", nr, m68k_getpc ());
1.1.1.20  root      736: #endif
                    737: }
                    738: 
                    739: void Exception_normal (int nr, uaecptr oldpc)
                    740: {
                    741:     uae_u32 currpc = m68k_getpc (), newpc;
                    742:     int sv = regs.s;
                    743: 
                    744:     exception_debug (nr);
1.1.1.24! root      745:     MakeSR ();
1.1.1.12  root      746: 
1.1       root      747:     if (!regs.s) {
1.1.1.23  root      748:        regs.usp = m68k_areg (regs, 7);
1.1.1.24! root      749:        if (currprefs.cpu_model >= 68020)
1.1.1.23  root      750:            m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.3   root      751:        else
1.1.1.23  root      752:            m68k_areg (regs, 7) = regs.isp;
1.1       root      753:        regs.s = 1;
                    754:     }
1.1.1.24! root      755:     if (currprefs.cpu_model > 68000) {
1.1       root      756:        if (nr == 2 || nr == 3) {
                    757:            int i;
1.1.1.24! root      758:            if (currprefs.cpu_model >= 68040) {
1.1.1.20  root      759:                if (nr == 2) {
                    760:                    for (i = 0 ; i < 18 ; i++) {
1.1.1.23  root      761:                        m68k_areg (regs, 7) -= 2;
                    762:                        put_word (m68k_areg (regs, 7), 0);
1.1.1.20  root      763:                    }
1.1.1.23  root      764:                    m68k_areg (regs, 7) -= 4;
                    765:                    put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                    766:                    m68k_areg (regs, 7) -= 2;
                    767:                    put_word (m68k_areg (regs, 7), 0);
                    768:                    m68k_areg (regs, 7) -= 2;
                    769:                    put_word (m68k_areg (regs, 7), 0);
                    770:                    m68k_areg (regs, 7) -= 2;
                    771:                    put_word (m68k_areg (regs, 7), 0);
                    772:                    m68k_areg (regs, 7) -= 2;
                    773:                    put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
                    774:                    m68k_areg (regs, 7) -= 4;
                    775:                    put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
                    776:                    m68k_areg (regs, 7) -= 2;
                    777:                    put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
1.1.1.20  root      778:                } else {
1.1.1.23  root      779:                    m68k_areg (regs, 7) -= 4;
                    780:                    put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                    781:                    m68k_areg (regs, 7) -= 2;
                    782:                    put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
1.1.1.20  root      783:                }
                    784:            } else {
                    785:                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
                    786:                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
                    787:                ssw |= 0x20;
                    788:                for (i = 0 ; i < 36; i++) {
1.1.1.23  root      789:                    m68k_areg (regs, 7) -= 2;
                    790:                    put_word (m68k_areg (regs, 7), 0);
1.1.1.20  root      791:                }
1.1.1.23  root      792:                m68k_areg (regs, 7) -= 4;
                    793:                put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
                    794:                m68k_areg (regs, 7) -= 2;
                    795:                put_word (m68k_areg (regs, 7), 0);
                    796:                m68k_areg (regs, 7) -= 2;
                    797:                put_word (m68k_areg (regs, 7), 0);
                    798:                m68k_areg (regs, 7) -= 2;
                    799:                put_word (m68k_areg (regs, 7), 0);
                    800:                m68k_areg (regs, 7) -= 2;
                    801:                put_word (m68k_areg (regs, 7), ssw);
                    802:                m68k_areg (regs, 7) -= 2;
                    803:                put_word (m68k_areg (regs, 7), 0xb000 + nr * 4);
1.1       root      804:            }
1.1.1.22  root      805: #if 0
1.1.1.20  root      806:            write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (regs.vbr + 4*nr));
1.1.1.22  root      807: #endif
                    808:            
1.1       root      809:        } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
1.1.1.23  root      810:            m68k_areg (regs, 7) -= 4;
                    811:            put_long (m68k_areg (regs, 7), oldpc);
                    812:            m68k_areg (regs, 7) -= 2;
                    813:            put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
1.1.1.20  root      814:        } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
1.1.1.23  root      815:            m68k_areg (regs, 7) -= 2;
                    816:            put_word (m68k_areg (regs, 7), nr * 4);
                    817:            m68k_areg (regs, 7) -= 4;
                    818:            put_long (m68k_areg (regs, 7), currpc);
                    819:            m68k_areg (regs, 7) -= 2;
                    820:            put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.3   root      821:            regs.sr |= (1 << 13);
1.1.1.23  root      822:            regs.msp = m68k_areg (regs, 7);
                    823:            m68k_areg (regs, 7) = regs.isp;
                    824:            m68k_areg (regs, 7) -= 2;
                    825:            put_word (m68k_areg (regs, 7), 0x1000 + nr * 4);
1.1.1.3   root      826:        } else {
1.1.1.23  root      827:            m68k_areg (regs, 7) -= 2;
                    828:            put_word (m68k_areg (regs, 7), nr * 4);
1.1.1.3   root      829:        }
1.1.1.20  root      830:     } else if (nr == 2 || nr == 3) {
                    831:        uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
1.1.1.21  root      832:        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
1.1.1.23  root      833:        m68k_areg (regs, 7) -= 14;
1.1.1.20  root      834:        /* fixme: bit3=I/N */
1.1.1.23  root      835:        put_word (m68k_areg (regs, 7) + 0, mode);
                    836:        put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
                    837:        put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
                    838:        put_word (m68k_areg (regs, 7) + 8, regs.sr);
                    839:        put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
1.1.1.21  root      840:        write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (regs.vbr + 4*nr));
1.1.1.20  root      841:        goto kludge_me_do;
1.1       root      842:     }
1.1.1.23  root      843:     m68k_areg (regs, 7) -= 4;
                    844:     put_long (m68k_areg (regs, 7), currpc);
                    845:     m68k_areg (regs, 7) -= 2;
                    846:     put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.20  root      847: kludge_me_do:
                    848:     newpc = get_long (regs.vbr + 4 * nr);
                    849:     if (newpc & 1) {
1.1.1.24! root      850:        if (nr == 2 || nr == 3) {
1.1.1.22  root      851:            uae_reset (1); /* there is nothing else we can do.. */
1.1.1.24! root      852:            set_special (SPCFLAG_RESTORE_SANITY);
        !           853:        } else
        !           854:            exception3 (regs.ir, m68k_getpc (), newpc);
1.1.1.20  root      855:        return;
                    856:     }
                    857:     m68k_setpc (newpc);
                    858:     fill_prefetch_slow ();
                    859:     exception_trace (nr);
                    860: }
                    861: 
                    862: void Exception (int nr, uaecptr oldpc)
                    863: {
                    864:     Exception_normal (nr, oldpc);
1.1       root      865: }
                    866: 
1.1.1.17  root      867: static void Interrupt (int nr)
1.1       root      868: {
1.1.1.20  root      869:     regs.stopped = 0;
                    870:     unset_special (SPCFLAG_STOP);
1.1       root      871:     assert(nr < 8 && nr >= 0);
                    872:     lastint_regs = regs;
                    873:     lastint_no = nr;
1.1.1.20  root      874:     Exception (nr + 24, 0);
1.1.1.3   root      875: 
1.1       root      876:     regs.intmask = nr;
1.1.1.12  root      877:     set_special (SPCFLAG_INT);
1.1       root      878: }
                    879: 
1.1.1.24! root      880: static int movec_illg (int regno)
        !           881: {
        !           882:     int regno2 = regno & 0x7ff;
        !           883: 
        !           884:     if (currprefs.cpu_model == 68060) {
        !           885:        if (regno <= 8)
        !           886:            return 0;
        !           887:        if (regno == 0x800 || regno == 0x801 ||
        !           888:            regno == 0x806 || regno == 0x807 || regno == 0x808)
        !           889:            return 0;
        !           890:        return 1;
        !           891:     } else if (currprefs.cpu_model == 68010) {
        !           892:        if (regno2 < 2)
        !           893:            return 0;
        !           894:        return 1;
        !           895:     } else if (currprefs.cpu_model == 68020) {
        !           896:        if (regno == 3)
        !           897:            /* 68040/060 only */
        !           898:            return 1;
        !           899:         /* 4 is >=68040, but 0x804 is in 68020 */
        !           900:         if (regno2 < 4 || regno == 0x804)
        !           901:            return 0;
        !           902:        return 1;
        !           903:     } else if (currprefs.cpu_model == 68030) {
        !           904:        if (regno2 <= 2)
        !           905:            return 0;
        !           906:        if (regno == 0x803 || regno == 0x804)
        !           907:            return 0;
        !           908:        return 1;
        !           909:     } else if (currprefs.cpu_model == 68040) {
        !           910:        if (regno == 0x802)
        !           911:            /* 68020 only */
        !           912:            return 1;
        !           913:        if (regno2 < 8) return 0;
        !           914:        return 1;
        !           915:     }
        !           916:     return 1;
        !           917: }
1.1       root      918: 
1.1.1.9   root      919: int m68k_move2c (int regno, uae_u32 *regp)
1.1       root      920: {
1.1.1.24! root      921:     if (movec_illg (regno)) {
1.1       root      922:        op_illg (0x4E7B);
1.1.1.9   root      923:        return 0;
1.1.1.12  root      924:     } else {
1.1       root      925:        switch (regno) {
1.1.1.12  root      926:        case 0: regs.sfc = *regp & 7; break;
                    927:        case 1: regs.dfc = *regp & 7; break;
1.1.1.24! root      928:        case 2:
        !           929:        {
        !           930:            uae_u32 cacr_mask = 0;
        !           931:            if (currprefs.cpu_model == 68020)
        !           932:                cacr_mask = 0x0000000f;
        !           933:            else if (currprefs.cpu_model == 68030)
        !           934:                cacr_mask = 0x00003f1f;
        !           935:            else if (currprefs.cpu_model == 68040)
        !           936:                cacr_mask = 0x80008000;
        !           937:            else if (currprefs.cpu_model == 68060)
        !           938:                cacr_mask = 0xf8e0e000;
        !           939:            regs.cacr = *regp & cacr_mask;
        !           940:        }
        !           941:        break;
        !           942:         /* 68040/060 only */
        !           943:        case 3:
        !           944:            regs.tcr = *regp & (currprefs.cpu_model == 68060 ? 0xfffe : 0xc000);
        !           945:            break;
        !           946: 
        !           947:        /* no differences between 68040 and 68060 */
        !           948:        case 4: regs.itt0 = *regp & 0xffffe364; break;
        !           949:        case 5: regs.itt1 = *regp & 0xffffe364; break;
        !           950:        case 6: regs.dtt0 = *regp & 0xffffe364; break;
        !           951:        case 7: regs.dtt1 = *regp & 0xffffe364; break;
        !           952:        /* 68060 only */
        !           953:        case 8: regs.buscr = *regp & 0xf0000000; break;
1.1.1.22  root      954: 
1.1.1.12  root      955:        case 0x800: regs.usp = *regp; break;
                    956:        case 0x801: regs.vbr = *regp; break;
1.1.1.24! root      957:        case 0x802: regs.caar = *regp & 0xfc; break;
1.1.1.23  root      958:        case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (regs, 7) = regs.msp; break;
                    959:        case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (regs, 7) = regs.isp; break;
1.1.1.24! root      960:        /* 68040 only */
        !           961:        case 0x805: regs.mmusr = *regp; break;
        !           962:        /* 68040/060 */
        !           963:        case 0x806: regs.urp = *regp; break;
        !           964:        case 0x807: regs.srp = *regp; break;
        !           965:        /* 68060 only */
        !           966:        case 0x808:
        !           967:        {
        !           968:            uae_u32 opcr = regs.pcr;
        !           969:            regs.pcr &= ~(0x40 | 2 | 1);
        !           970:            regs.pcr |= (*regp) & (0x40 | 2 | 1);
        !           971:            if (((opcr ^ regs.pcr) & 2) == 2) {
        !           972:                write_log("68060 FPU state: %s\n", regs.pcr & 2 ? "disabled" : "enabled");
        !           973:                /* flush possible already translated FPU instructions */
        !           974:                flush_icache (2);
        !           975:            }
        !           976:        }
        !           977:        break;
1.1.1.12  root      978:        default:
1.1       root      979:            op_illg (0x4E7B);
1.1.1.9   root      980:            return 0;
1.1       root      981:        }
1.1.1.12  root      982:     }
1.1.1.9   root      983:     return 1;
1.1       root      984: }
                    985: 
1.1.1.9   root      986: int m68k_movec2 (int regno, uae_u32 *regp)
1.1       root      987: {
1.1.1.24! root      988:     if (movec_illg (regno)) {
        !           989:        op_illg (0x4E7B);
1.1.1.9   root      990:        return 0;
1.1.1.12  root      991:     } else {
1.1       root      992:        switch (regno) {
1.1.1.12  root      993:        case 0: *regp = regs.sfc; break;
                    994:        case 1: *regp = regs.dfc; break;
1.1.1.24! root      995:        case 2: 
        !           996:        {
        !           997:            uae_u32 v = regs.cacr;
        !           998:            uae_u32 cacr_mask = 0;
        !           999:            if (currprefs.cpu_model == 68020)
        !          1000:                cacr_mask = 0x00000003;
        !          1001:            else if (currprefs.cpu_model == 68030)
        !          1002:                cacr_mask = 0x00003313;
        !          1003:            else if (currprefs.cpu_model == 68040)
        !          1004:                cacr_mask = 0x80008000;
        !          1005:            else if (currprefs.cpu_model == 68060)
        !          1006:                cacr_mask = 0xf880e000;
        !          1007:            *regp = v & cacr_mask;
        !          1008:        }
        !          1009:        break;
        !          1010:        case 3: *regp = regs.tcr; break;
        !          1011:        case 4: *regp = regs.itt0; break;
        !          1012:        case 5: *regp = regs.itt1; break;
        !          1013:        case 6: *regp = regs.dtt0; break;
        !          1014:        case 7: *regp = regs.dtt1; break;
        !          1015:        case 8: *regp = regs.buscr; break;
        !          1016: 
1.1.1.12  root     1017:        case 0x800: *regp = regs.usp; break;
                   1018:        case 0x801: *regp = regs.vbr; break;
1.1.1.24! root     1019:        case 0x802: *regp = regs.caar; break;
        !          1020:        case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
        !          1021:        case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
        !          1022:        case 0x805: *regp = regs.mmusr; break;
        !          1023:        case 0x806: *regp = regs.urp; break;
        !          1024:        case 0x807: *regp = regs.srp; break;
        !          1025:        case 0x808: *regp = regs.pcr; break;
1.1.1.12  root     1026:        default:
1.1       root     1027:            op_illg (0x4E7A);
1.1.1.9   root     1028:            return 0;
1.1       root     1029:        }
1.1.1.12  root     1030:     }
1.1.1.9   root     1031:     return 1;
1.1       root     1032: }
                   1033: 
1.1.1.8   root     1034: STATIC_INLINE int
1.1.1.3   root     1035: div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
1.1       root     1036: {
1.1.1.3   root     1037:        uae_u32 q = 0, cbit = 0;
1.1       root     1038:        int i;
                   1039: 
                   1040:        if (div <= src_hi) {
1.1.1.4   root     1041:            return 1;
1.1       root     1042:        }
                   1043:        for (i = 0 ; i < 32 ; i++) {
1.1.1.2   root     1044:                cbit = src_hi & 0x80000000ul;
1.1       root     1045:                src_hi <<= 1;
1.1.1.2   root     1046:                if (src_lo & 0x80000000ul) src_hi++;
1.1       root     1047:                src_lo <<= 1;
                   1048:                q = q << 1;
                   1049:                if (cbit || div <= src_hi) {
                   1050:                        q |= 1;
                   1051:                        src_hi -= div;
                   1052:                }
                   1053:        }
                   1054:        *quot = q;
                   1055:        *rem = src_hi;
1.1.1.4   root     1056:        return 0;
1.1       root     1057: }
                   1058: 
1.1.1.3   root     1059: void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
1.1       root     1060: {
1.1.1.3   root     1061: #if defined(uae_s64)
1.1       root     1062:     if (src == 0) {
1.1.1.4   root     1063:        Exception (5, oldpc);
1.1       root     1064:        return;
                   1065:     }
                   1066:     if (extra & 0x800) {
                   1067:        /* signed variant */
1.1.1.24! root     1068:        uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
1.1.1.3   root     1069:        uae_s64 quot, rem;
                   1070: 
1.1       root     1071:        if (extra & 0x400) {
1.1.1.3   root     1072:            a &= 0xffffffffu;
1.1.1.24! root     1073:            a |= (uae_s64)m68k_dreg (regs, extra & 7) << 32;
1.1       root     1074:        }
1.1.1.3   root     1075:        rem = a % (uae_s64)(uae_s32)src;
                   1076:        quot = a / (uae_s64)(uae_s32)src;
                   1077:        if ((quot & UVAL64(0xffffffff80000000)) != 0
                   1078:            && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
                   1079:        {
1.1.1.6   root     1080:            SET_VFLG (1);
                   1081:            SET_NFLG (1);
                   1082:            SET_CFLG (0);
1.1.1.4   root     1083:        } else {
1.1.1.3   root     1084:            if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
1.1.1.6   root     1085:            SET_VFLG (0);
                   1086:            SET_CFLG (0);
                   1087:            SET_ZFLG (((uae_s32)quot) == 0);
                   1088:            SET_NFLG (((uae_s32)quot) < 0);
1.1.1.24! root     1089:            m68k_dreg (regs, extra & 7) = rem;
        !          1090:            m68k_dreg (regs, (extra >> 12) & 7) = quot;
1.1       root     1091:        }
                   1092:     } else {
                   1093:        /* unsigned */
1.1.1.24! root     1094:        uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
1.1.1.3   root     1095:        uae_u64 quot, rem;
                   1096: 
1.1       root     1097:        if (extra & 0x400) {
1.1.1.3   root     1098:            a &= 0xffffffffu;
1.1.1.24! root     1099:            a |= (uae_u64)m68k_dreg (regs, extra & 7) << 32;
1.1       root     1100:        }
1.1.1.3   root     1101:        rem = a % (uae_u64)src;
                   1102:        quot = a / (uae_u64)src;
                   1103:        if (quot > 0xffffffffu) {
1.1.1.6   root     1104:            SET_VFLG (1);
                   1105:            SET_NFLG (1);
                   1106:            SET_CFLG (0);
1.1.1.4   root     1107:        } else {
1.1.1.6   root     1108:            SET_VFLG (0);
                   1109:            SET_CFLG (0);
                   1110:            SET_ZFLG (((uae_s32)quot) == 0);
                   1111:            SET_NFLG (((uae_s32)quot) < 0);
1.1.1.24! root     1112:            m68k_dreg (regs, extra & 7) = rem;
        !          1113:            m68k_dreg (regs, (extra >> 12) & 7) = quot;
1.1       root     1114:        }
                   1115:     }
                   1116: #else
                   1117:     if (src == 0) {
1.1.1.4   root     1118:        Exception (5, oldpc);
1.1       root     1119:        return;
                   1120:     }
                   1121:     if (extra & 0x800) {
                   1122:        /* signed variant */
1.1.1.24! root     1123:        uae_s32 lo = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
1.1.1.3   root     1124:        uae_s32 hi = lo < 0 ? -1 : 0;
                   1125:        uae_s32 save_high;
                   1126:        uae_u32 quot, rem;
                   1127:        uae_u32 sign;
                   1128: 
1.1       root     1129:        if (extra & 0x400) {
1.1.1.24! root     1130:            hi = (uae_s32)m68k_dreg (regs, extra & 7);
1.1       root     1131:        }
                   1132:        save_high = hi;
                   1133:        sign = (hi ^ src);
                   1134:        if (hi < 0) {
1.1.1.4   root     1135:            hi = ~hi;
                   1136:            lo = -lo;
                   1137:            if (lo == 0) hi++;
1.1       root     1138:        }
1.1.1.3   root     1139:        if ((uae_s32)src < 0) src = -src;
1.1       root     1140:        if (div_unsigned(hi, lo, src, &quot, &rem) ||
                   1141:            (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
1.1.1.6   root     1142:            SET_VFLG (1);
                   1143:            SET_NFLG (1);
                   1144:            SET_CFLG (0);
1.1.1.4   root     1145:        } else {
1.1       root     1146:            if (sign & 0x80000000) quot = -quot;
1.1.1.3   root     1147:            if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
1.1.1.6   root     1148:            SET_VFLG (0);
                   1149:            SET_CFLG (0);
                   1150:            SET_ZFLG (((uae_s32)quot) == 0);
                   1151:            SET_NFLG (((uae_s32)quot) < 0);
1.1.1.24! root     1152:            m68k_dreg (regs, extra & 7) = rem;
        !          1153:            m68k_dreg (regs, (extra >> 12) & 7) = quot;
1.1       root     1154:        }
                   1155:     } else {
                   1156:        /* unsigned */
1.1.1.24! root     1157:        uae_u32 lo = (uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
1.1.1.3   root     1158:        uae_u32 hi = 0;
                   1159:        uae_u32 quot, rem;
                   1160: 
1.1       root     1161:        if (extra & 0x400) {
1.1.1.24! root     1162:            hi = (uae_u32)m68k_dreg (regs, extra & 7);
1.1       root     1163:        }
                   1164:        if (div_unsigned(hi, lo, src, &quot, &rem)) {
1.1.1.6   root     1165:            SET_VFLG (1);
                   1166:            SET_NFLG (1);
                   1167:            SET_CFLG (0);
1.1.1.4   root     1168:        } else {
1.1.1.6   root     1169:            SET_VFLG (0);
                   1170:            SET_CFLG (0);
                   1171:            SET_ZFLG (((uae_s32)quot) == 0);
                   1172:            SET_NFLG (((uae_s32)quot) < 0);
1.1.1.24! root     1173:            m68k_dreg (regs, extra & 7) = rem;
        !          1174:            m68k_dreg (regs, (extra >> 12) & 7) = quot;
1.1       root     1175:        }
                   1176:     }
                   1177: #endif
                   1178: }
                   1179: 
1.1.1.8   root     1180: STATIC_INLINE void
1.1.1.3   root     1181: mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
1.1       root     1182: {
1.1.1.3   root     1183:        uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
                   1184:        uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
                   1185:        uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
                   1186:        uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
                   1187:        uae_u32 lo;
                   1188: 
                   1189:        lo = r0 + ((r1 << 16) & 0xffff0000ul);
                   1190:        if (lo < r0) r3++;
                   1191:        r0 = lo;
                   1192:        lo = r0 + ((r2 << 16) & 0xffff0000ul);
                   1193:        if (lo < r0) r3++;
                   1194:        r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
1.1       root     1195:        *dst_lo = lo;
                   1196:        *dst_hi = r3;
                   1197: }
                   1198: 
1.1.1.3   root     1199: void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
1.1       root     1200: {
1.1.1.3   root     1201: #if defined(uae_s64)
1.1       root     1202:     if (extra & 0x800) {
                   1203:        /* signed variant */
1.1.1.24! root     1204:        uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
1.1       root     1205: 
1.1.1.3   root     1206:        a *= (uae_s64)(uae_s32)src;
1.1.1.6   root     1207:        SET_VFLG (0);
                   1208:        SET_CFLG (0);
                   1209:        SET_ZFLG (a == 0);
                   1210:        SET_NFLG (a < 0);
1.1       root     1211:        if (extra & 0x400)
1.1.1.24! root     1212:            m68k_dreg (regs, extra & 7) = a >> 32;
1.1.1.3   root     1213:        else if ((a & UVAL64(0xffffffff80000000)) != 0
                   1214:                 && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
                   1215:        {
1.1.1.6   root     1216:            SET_VFLG (1);
1.1       root     1217:        }
1.1.1.24! root     1218:        m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
1.1       root     1219:     } else {
                   1220:        /* unsigned */
1.1.1.24! root     1221:        uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
1.1.1.3   root     1222: 
                   1223:        a *= (uae_u64)src;
1.1.1.6   root     1224:        SET_VFLG (0);
                   1225:        SET_CFLG (0);
                   1226:        SET_ZFLG (a == 0);
                   1227:        SET_NFLG (((uae_s64)a) < 0);
1.1       root     1228:        if (extra & 0x400)
1.1.1.24! root     1229:            m68k_dreg (regs, extra & 7) = a >> 32;
1.1.1.3   root     1230:        else if ((a & UVAL64(0xffffffff00000000)) != 0) {
1.1.1.6   root     1231:            SET_VFLG (1);
1.1       root     1232:        }
1.1.1.24! root     1233:        m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
1.1       root     1234:     }
                   1235: #else
                   1236:     if (extra & 0x800) {
                   1237:        /* signed variant */
1.1.1.3   root     1238:        uae_s32 src1,src2;
                   1239:        uae_u32 dst_lo,dst_hi;
                   1240:        uae_u32 sign;
1.1       root     1241: 
1.1.1.3   root     1242:        src1 = (uae_s32)src;
1.1.1.24! root     1243:        src2 = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
1.1       root     1244:        sign = (src1 ^ src2);
                   1245:        if (src1 < 0) src1 = -src1;
                   1246:        if (src2 < 0) src2 = -src2;
1.1.1.3   root     1247:        mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
1.1       root     1248:        if (sign & 0x80000000) {
                   1249:                dst_hi = ~dst_hi;
                   1250:                dst_lo = -dst_lo;
                   1251:                if (dst_lo == 0) dst_hi++;
                   1252:        }
1.1.1.6   root     1253:        SET_VFLG (0);
                   1254:        SET_CFLG (0);
                   1255:        SET_ZFLG (dst_hi == 0 && dst_lo == 0);
                   1256:        SET_NFLG (((uae_s32)dst_hi) < 0);
1.1       root     1257:        if (extra & 0x400)
1.1.1.24! root     1258:            m68k_dreg (regs, extra & 7) = dst_hi;
1.1.1.3   root     1259:        else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
                   1260:                 && ((dst_hi & 0xffffffff) != 0xffffffff
                   1261:                     || (dst_lo & 0x80000000) != 0x80000000))
                   1262:        {
1.1.1.6   root     1263:            SET_VFLG (1);
1.1       root     1264:        }
1.1.1.24! root     1265:        m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
1.1       root     1266:     } else {
                   1267:        /* unsigned */
1.1.1.3   root     1268:        uae_u32 dst_lo,dst_hi;
                   1269: 
1.1.1.24! root     1270:        mul_unsigned(src,(uae_u32)m68k_dreg (regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
1.1       root     1271: 
1.1.1.6   root     1272:        SET_VFLG (0);
                   1273:        SET_CFLG (0);
                   1274:        SET_ZFLG (dst_hi == 0 && dst_lo == 0);
                   1275:        SET_NFLG (((uae_s32)dst_hi) < 0);
1.1       root     1276:        if (extra & 0x400)
1.1.1.24! root     1277:            m68k_dreg (regs, extra & 7) = dst_hi;
1.1       root     1278:        else if (dst_hi != 0) {
1.1.1.6   root     1279:            SET_VFLG (1);
1.1       root     1280:        }
1.1.1.24! root     1281:        m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
1.1       root     1282:     }
                   1283: #endif
                   1284: }
1.1.1.23  root     1285: static const char *ccnames[] =
1.1       root     1286: { "T ","F ","HI","LS","CC","CS","NE","EQ",
                   1287:   "VC","VS","PL","MI","GE","LT","GT","LE" };
                   1288: 
1.1.1.24! root     1289: #define MC68060_PCR   0x04300000
        !          1290: #define MC68EC060_PCR 0x04310000
        !          1291: 
1.1.1.4   root     1292: void m68k_reset (void)
1.1       root     1293: {
1.1.1.24! root     1294:     if (currprefs.cpu_model != changed_prefs.cpu_model
        !          1295:        || currprefs.fpu_model != changed_prefs.fpu_model
1.1.1.22  root     1296:        || currprefs.address_space_24 != changed_prefs.address_space_24)
                   1297:     {
                   1298:        currprefs.address_space_24 = changed_prefs.address_space_24;
1.1.1.24! root     1299:        currprefs.cpu_model = changed_prefs.cpu_model;
        !          1300:        currprefs.fpu_model = changed_prefs.fpu_model;
1.1.1.22  root     1301:        build_cpufunctbl ();
                   1302:     }
                   1303: 
1.1.1.14  root     1304:     regs.kick_mask = 0x00F80000;
                   1305:     regs.spcflags = 0;
                   1306:     if (savestate_state == STATE_RESTORE) {
1.1.1.21  root     1307:        m68k_setpc (regs.pc);
1.1.1.14  root     1308:        /* MakeFromSR() must not swap stack pointer */
1.1.1.24! root     1309:        regs.m = (regs.sr >> 12) & 1;
1.1.1.14  root     1310:        regs.s = (regs.sr >> 13) & 1;
                   1311:        MakeFromSR();
                   1312:        /* set stack pointer */
                   1313:        if (regs.s)
1.1.1.24! root     1314:            m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.14  root     1315:        else
1.1.1.23  root     1316:            m68k_areg (regs, 7) = regs.usp;
1.1.1.14  root     1317:        return;
                   1318:     }
                   1319: 
1.1.1.3   root     1320:     m68k_areg (regs, 7) = get_long (0x00f80000);
                   1321:     m68k_setpc (get_long (0x00f80004));
1.1       root     1322:     regs.s = 1;
                   1323:     regs.m = 0;
                   1324:     regs.stopped = 0;
                   1325:     regs.t1 = 0;
                   1326:     regs.t0 = 0;
1.1.1.6   root     1327:     SET_ZFLG (0);
                   1328:     SET_XFLG (0);
                   1329:     SET_CFLG (0);
                   1330:     SET_VFLG (0);
                   1331:     SET_NFLG (0);
1.1       root     1332:     regs.intmask = 7;
                   1333:     regs.vbr = regs.sfc = regs.dfc = 0;
                   1334:     regs.fpcr = regs.fpsr = regs.fpiar = 0;
1.1.1.20  root     1335:     regs.irc = 0xffff;
1.1.1.24! root     1336: 
        !          1337:     /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
        !          1338:     regs.tc_030 &= ~0x80000000;
        !          1339:     if (1 /* hardreset */) {
        !          1340:        regs.srp_030 = regs.crp_030 = 0;
        !          1341:        regs.tt0_030 = regs.tt1_030 = regs.tc_030 = 0;
        !          1342:     }
        !          1343:     regs.mmusr_030 = 0;
        !          1344: 
        !          1345:     /* 68060 FPU is not compatible with 68040,
        !          1346:      * 68060 accelerators' boot ROM disables the FPU
        !          1347:      */
        !          1348:     regs.pcr = 0;
        !          1349:     if (currprefs.cpu_model == 68060) {
        !          1350:        regs.pcr = currprefs.fpu_model != 0 ? MC68060_PCR : MC68EC060_PCR;
        !          1351: #if 0
        !          1352:        regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
        !          1353: #endif
        !          1354:        regs.pcr |= 2;
        !          1355:     }
1.1.1.20  root     1356:     fill_prefetch_slow ();
1.1       root     1357: }
                   1358: 
1.1.1.4   root     1359: unsigned long REGPARAM2 op_illg (uae_u32 opcode)
1.1       root     1360: {
1.1.1.3   root     1361:     uaecptr pc = m68k_getpc ();
1.1.1.22  root     1362: 
1.1.1.3   root     1363:     if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
                   1364:        m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
                   1365:        m68k_incpc (2);
1.1.1.20  root     1366:        fill_prefetch_slow ();
1.1.1.4   root     1367:        return 4;
1.1.1.3   root     1368:     }
                   1369: 
                   1370:     if (opcode == 0x4E7B && get_long (0x10) == 0 && (pc & 0xF80000) == 0xF80000) {
1.1.1.4   root     1371:        write_log ("Your Kickstart requires a 68020 CPU. Giving up.\n");
1.1.1.3   root     1372:        broken_in = 1;
1.1.1.12  root     1373:        set_special (SPCFLAG_BRK);
1.1       root     1374:        quit_program = 1;
                   1375:     }
1.1.1.2   root     1376:     if (opcode == 0xFF0D) {
1.1.1.3   root     1377:        if ((pc & 0xF80000) == 0xF80000) {
1.1.1.2   root     1378:            /* This is from the dummy Kickstart replacement */
1.1.1.3   root     1379:            uae_u16 arg = get_iword (2);
                   1380:            m68k_incpc (4);
                   1381:            ersatz_perform (arg);
1.1.1.20  root     1382:            fill_prefetch_slow ();
1.1.1.4   root     1383:            return 4;
1.1.1.17  root     1384:        } else if ((pc & 0xFFFF0000) == RTAREA_BASE) {
1.1.1.2   root     1385:            /* User-mode STOP replacement */
1.1.1.3   root     1386:            m68k_setstopped (1);
1.1.1.4   root     1387:            return 4;
1.1.1.2   root     1388:        }
1.1       root     1389:     }
1.1.1.3   root     1390: 
1.1.1.17  root     1391:     if ((opcode & 0xF000) == 0xA000 && (pc & 0xFFFF0000) == RTAREA_BASE) {
1.1.1.3   root     1392:        /* Calltrap. */
1.1.1.24! root     1393:        m68k_incpc (2);
        !          1394:        m68k_handle_trap (opcode & 0xFFF);
1.1.1.20  root     1395:        fill_prefetch_slow ();
1.1.1.4   root     1396:        return 4;
1.1.1.3   root     1397:     }
                   1398: 
1.1       root     1399:     if ((opcode & 0xF000) == 0xF000) {
                   1400:        Exception(0xB,0);
1.1.1.4   root     1401:        return 4;
1.1       root     1402:     }
                   1403:     if ((opcode & 0xF000) == 0xA000) {
1.1.1.3   root     1404:        Exception(0xA,0);
1.1.1.4   root     1405:        return 4;
1.1       root     1406:     }
1.1.1.12  root     1407: #if 1
1.1.1.4   root     1408:     write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
1.1.1.10  root     1409: #endif
1.1.1.3   root     1410:     Exception (4,0);
1.1.1.4   root     1411:     return 4;
1.1       root     1412: }
                   1413: 
1.1.1.24! root     1414: static char *mmu30regs[] = { "TCR", "", "SRP", "CRP", "", "", "", "" };
        !          1415: 
        !          1416: static void mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          1417: {
        !          1418:     int preg = (next >> 10) & 31;
        !          1419:     int rw = (next >> 9) & 1;
        !          1420:     int fd = (next >> 8) & 1;
        !          1421:     char *reg = NULL;
        !          1422:     uae_u32 otc = regs.tc_030;
        !          1423:     int siz;
        !          1424: 
        !          1425:     switch (preg)
        !          1426:     {
        !          1427:     case 0x10: // TC
        !          1428:        reg = "TC";
        !          1429:        siz = 4;
        !          1430:        if (rw)
        !          1431:            put_long (extra, regs.tc_030);
        !          1432:        else
        !          1433:            regs.tc_030 = get_long (extra);
        !          1434:        break;
        !          1435:     case 0x12: // SRP
        !          1436:        reg = "SRP";
        !          1437:        siz = 8;
        !          1438:        if (rw) {
        !          1439:            put_long (extra, regs.srp_030 >> 32);
        !          1440:            put_long (extra + 4, regs.srp_030);
        !          1441:        } else {
        !          1442:            regs.srp_030 = (uae_u64)get_long (extra) << 32;
        !          1443:            regs.srp_030 |= get_long (extra + 4);
        !          1444:        }
        !          1445:        break;
        !          1446:     case 0x13: // CRP
        !          1447:        reg = "CRP";
        !          1448:        siz = 8;
        !          1449:        if (rw) {
        !          1450:            put_long (extra, regs.crp_030 >> 32);
        !          1451:            put_long (extra + 4, regs.crp_030);
        !          1452:        } else {
        !          1453:            regs.crp_030 = (uae_u64)get_long (extra) << 32;
        !          1454:            regs.crp_030 |= get_long (extra + 4);
        !          1455:        }
        !          1456:        break;
        !          1457:     case 0x18: // MMUSR
        !          1458:        reg = "MMUSR";
        !          1459:        siz = 2;
        !          1460:        if (rw)
        !          1461:            put_word (extra, regs.mmusr_030);
        !          1462:        else
        !          1463:            regs.mmusr_030 = get_word (extra);
        !          1464:        break;
        !          1465:     case 0x02: // TT0
        !          1466:        reg = "TT0";
        !          1467:        siz = 4;
        !          1468:        if (rw)
        !          1469:            put_long (extra, regs.tt0_030);
        !          1470:        else
        !          1471:            regs.tt0_030 = get_long (extra);
        !          1472:        break;
        !          1473:     case 0x03: // TT1
        !          1474:        reg = "TT1";
        !          1475:        siz = 4;
        !          1476:        if (rw)
        !          1477:            put_long (extra, regs.tt1_030);
        !          1478:        else
        !          1479:            regs.tt1_030 = get_long (extra);
        !          1480:        break;
        !          1481:     }
        !          1482: 
        !          1483:     if (!reg) {
        !          1484:        op_illg (opcode);
        !          1485:        return;
        !          1486:     }
        !          1487: #if MMUOP_DEBUG > 0
        !          1488:     {
        !          1489:        uae_u32 val;
        !          1490:        if (siz == 8) {
        !          1491:            uae_u32 val2 = get_long (extra);
        !          1492:            val = get_long (extra + 4);
        !          1493:            if (rw)
        !          1494:                write_log ("PMOVE %s,%08X%08X", reg, val2, val);
        !          1495:            else
        !          1496:                write_log ("PMOVE %08X%08X,%s", val2, val, reg);
        !          1497:        } else {
        !          1498:            if (siz == 4)
        !          1499:                val = get_long (extra);
        !          1500:            else
        !          1501:                val = get_word (extra);
        !          1502:            if (rw)
        !          1503:                write_log ("PMOVE %s,%08X", reg, val);
        !          1504:            else
        !          1505:                write_log ("PMOVE %08X,%s", val, reg);
        !          1506:        }
        !          1507:        write_log (" PC=%08X\n", pc);
        !          1508:     }
        !          1509: #endif
        !          1510: }
        !          1511: 
        !          1512: static void mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          1513: {
        !          1514: #if MMUOP_DEBUG > 0
        !          1515:     char tmp[10];
        !          1516: 
        !          1517:     tmp[0] = 0;
        !          1518:     if ((next >> 8) & 1)
        !          1519:        sprintf(tmp,",A%d", (next >> 4) & 15);
        !          1520:     write_log ("PTEST%c %02X,%08X,#%X%s PC=%08X\n",
        !          1521:        ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc); 
        !          1522: #endif
        !          1523:     //    mmusr_030 = 0;
        !          1524: }
        !          1525: 
        !          1526: static void mmu_op30_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
        !          1527: {
        !          1528: #if MMUOP_DEBUG > 0
        !          1529:     write_log ("PFLUSH PC=%08X\n", pc);
        !          1530: #endif
        !          1531: }
        !          1532: 
        !          1533: void mmu_op30 (uaecptr pc, uae_u32 opcode, int isnext, uaecptr extra)
        !          1534: {
        !          1535:     if (currprefs.cpu_model != 68030) {
        !          1536:        m68k_setpc (pc);
        !          1537:        op_illg (opcode);
        !          1538:        return;
        !          1539:     }
        !          1540:     if (isnext) {
        !          1541:        uae_u16 next = get_word (pc + 2);
        !          1542:        if (next & 0x8000)
        !          1543:            mmu_op30_ptest (pc, opcode, next, extra);
        !          1544:        else if (next & 0x2000)
        !          1545:            mmu_op30_pflush (pc, opcode, next, extra);
        !          1546:        else
        !          1547:            mmu_op30_pmove (pc, opcode, next, extra);
        !          1548:        m68k_setpc (m68k_getpc () + 2);
        !          1549:     } else {
        !          1550: #if MMUOP_DEBUG > 0
        !          1551:        write_log ("MMU030: %04x PC=%08x\n", opcode, m68k_getpc ());
        !          1552: #endif
        !          1553:     }
        !          1554:     return;
        !          1555: }
        !          1556: 
1.1.1.3   root     1557: void mmu_op(uae_u32 opcode, uae_u16 extra)
1.1       root     1558: {
1.1.1.24! root     1559: #if MMUOP_DEBUG > 1
        !          1560:     write_log ("mmu_op %04X PC=%08X\n", opcode, m68k_getpc ());
        !          1561: #endif
1.1.1.12  root     1562:     if ((opcode & 0xFE0) == 0x0500) {
                   1563:        /* PFLUSH */
1.1.1.24! root     1564:        regs.mmusr = 0;
        !          1565: #if MMUOP_DEBUG > 0
1.1.1.12  root     1566:        write_log ("PFLUSH\n");
1.1.1.24! root     1567: #endif
        !          1568:        return;
1.1.1.12  root     1569:     } else if ((opcode & 0x0FD8) == 0x548) {
1.1.1.24! root     1570:        if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
        !          1571:            /* PTEST */
        !          1572: #if MMUOP_DEBUG > 0
        !          1573:            write_log ("PTEST\n");
        !          1574: #endif
        !          1575:            return;
        !          1576:        }
        !          1577:     } else if ((opcode & 0x0FB8) == 0x588) {
        !          1578:        /* PLPA */
        !          1579:        if (currprefs.cpu_model == 68060) {
        !          1580: #if MMUOP_DEBUG > 0
        !          1581:            write_log ("PLPA\n");
        !          1582: #endif
        !          1583:            return;
        !          1584:        }
        !          1585:     } else if (opcode == 0xff00 && extra == 0x01c0) {
        !          1586:        /* LPSTOP */
        !          1587:        if (currprefs.cpu_model == 68060) {
        !          1588: #if MMUOP_DEBUG > 0
        !          1589:            write_log ("LPSTOP\n");
        !          1590: #endif
        !          1591:            return;
        !          1592:        }
        !          1593:     }
        !          1594: #if MMUOP_DEBUG > 0
        !          1595:     write_log ("Unknown MMU OP %04X\n", opcode);
        !          1596: #endif
        !          1597:     m68k_setpc (m68k_getpc () - 2);
        !          1598:     op_illg (opcode);
1.1       root     1599: }
                   1600: 
1.1.1.4   root     1601: static int n_insns = 0, n_spcinsns = 0;
1.1       root     1602: 
1.1.1.3   root     1603: static uaecptr last_trace_ad = 0;
1.1       root     1604: 
1.1.1.7   root     1605: static void do_trace (void)
1.1       root     1606: {
1.1.1.24! root     1607:     if (regs.t0 && currprefs.cpu_model >= 68020) {
1.1.1.7   root     1608:        uae_u16 opcode;
                   1609:        /* should also include TRAP, CHK, SR modification FPcc */
                   1610:        /* probably never used so why bother */
                   1611:        /* We can afford this to be inefficient... */
                   1612:        m68k_setpc (m68k_getpc ());
1.1.1.20  root     1613:        fill_prefetch_slow ();
1.1.1.7   root     1614:        opcode = get_word (regs.pc);
                   1615:        if (opcode == 0x4e72            /* RTE */
                   1616:            || opcode == 0x4e74                 /* RTD */
                   1617:            || opcode == 0x4e75                 /* RTS */
                   1618:            || opcode == 0x4e77                 /* RTR */
                   1619:            || opcode == 0x4e76                 /* TRAPV */
                   1620:            || (opcode & 0xffc0) == 0x4e80      /* JSR */
                   1621:            || (opcode & 0xffc0) == 0x4ec0      /* JMP */
                   1622:            || (opcode & 0xff00) == 0x6100  /* BSR */
                   1623:            || ((opcode & 0xf000) == 0x6000     /* Bcc */
                   1624:                && cctrue((opcode >> 8) & 0xf))
                   1625:            || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
                   1626:                && !cctrue((opcode >> 8) & 0xf)
1.1.1.24! root     1627:                && (uae_s16)m68k_dreg (regs, opcode & 7) != 0))
1.1.1.7   root     1628:        {
1.1.1.4   root     1629:            last_trace_ad = m68k_getpc ();
1.1.1.12  root     1630:            unset_special (SPCFLAG_TRACE);
                   1631:            set_special (SPCFLAG_DOTRACE);
1.1       root     1632:        }
1.1.1.7   root     1633:     } else if (regs.t1) {
                   1634:        last_trace_ad = m68k_getpc ();
1.1.1.12  root     1635:        unset_special (SPCFLAG_TRACE);
                   1636:        set_special (SPCFLAG_DOTRACE);
1.1       root     1637:     }
                   1638: }
                   1639: 
1.1.1.19  root     1640: static int do_specialties (int cycles)
1.1       root     1641: {
1.1.1.24! root     1642:     if (regs.spcflags & SPCFLAG_RESTORE_SANITY) {
        !          1643:        m68k_setpc (0xF0FFC0);
        !          1644:        fill_prefetch_slow ();
        !          1645:        unset_special (SPCFLAG_RESTORE_SANITY);
        !          1646:     }
1.1.1.9   root     1647:     if (regs.spcflags & SPCFLAG_COPPER)
                   1648:        do_copper ();
                   1649: 
1.1.1.3   root     1650:     /*n_spcinsns++;*/
1.1.1.19  root     1651:     while ((regs.spcflags & SPCFLAG_BLTNASTY) && cycles > 0) {
1.1.1.18  root     1652:        int c = blitnasty();
1.1.1.19  root     1653:        if (!c) {
                   1654:            cycles -= 2 * CYCLE_UNIT;
                   1655:            if (cycles < CYCLE_UNIT)
                   1656:                cycles = 0;
                   1657:            c = 1;
                   1658:        }
1.1.1.18  root     1659:        do_cycles (c * CYCLE_UNIT);
1.1.1.9   root     1660:        if (regs.spcflags & SPCFLAG_COPPER)
                   1661:            do_copper ();
1.1.1.3   root     1662:     }
1.1.1.9   root     1663: 
1.1.1.21  root     1664:     if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.4   root     1665:        Exception (9,last_trace_ad);
1.1.1.21  root     1666: 
1.1.1.3   root     1667:     while (regs.spcflags & SPCFLAG_STOP) {
1.1.1.13  root     1668:        do_cycles (4 * CYCLE_UNIT);
1.1.1.9   root     1669:        if (regs.spcflags & SPCFLAG_COPPER)
                   1670:            do_copper ();
1.1.1.21  root     1671:        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
1.1.1.4   root     1672:            int intr = intlev ();
1.1.1.12  root     1673:            unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
1.1.1.3   root     1674:            if (intr != -1 && intr > regs.intmask) {
1.1.1.4   root     1675:                Interrupt (intr);
1.1.1.3   root     1676:                regs.stopped = 0;
1.1.1.12  root     1677:                unset_special (SPCFLAG_STOP);
1.1.1.2   root     1678:            }
1.1.1.3   root     1679:        }
                   1680:     }
1.1.1.7   root     1681:     if (regs.spcflags & SPCFLAG_TRACE)
                   1682:        do_trace ();
1.1.1.4   root     1683: 
1.1.1.3   root     1684:     if (regs.spcflags & SPCFLAG_DOINT) {
1.1.1.4   root     1685:        int intr = intlev ();
1.1.1.12  root     1686:        unset_special (SPCFLAG_DOINT);
1.1.1.3   root     1687:        if (intr != -1 && intr > regs.intmask) {
1.1.1.4   root     1688:            Interrupt (intr);
1.1.1.3   root     1689:            regs.stopped = 0;
                   1690:        }
                   1691:     }
                   1692:     if (regs.spcflags & SPCFLAG_INT) {
1.1.1.12  root     1693:        unset_special (SPCFLAG_INT);
                   1694:        set_special (SPCFLAG_DOINT);
1.1.1.3   root     1695:     }
1.1.1.4   root     1696:     if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
1.1.1.12  root     1697:        unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
1.1.1.3   root     1698:        return 1;
1.1.1.2   root     1699:     }
1.1.1.3   root     1700:     return 0;
1.1.1.2   root     1701: }
                   1702: 
1.1.1.8   root     1703: /* It's really sad to have two almost identical functions for this, but we
                   1704:    do it all for performance... :( */
1.1.1.4   root     1705: static void m68k_run_1 (void)
1.1.1.2   root     1706: {
1.1.1.3   root     1707:     for (;;) {
1.1.1.4   root     1708:        int cycles;
1.1.1.20  root     1709:        uae_u32 opcode = regs.ir;
                   1710: 
1.1.1.8   root     1711:        /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
                   1712: /*     regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
                   1713: #if COUNT_INSTRS == 2
                   1714:        if (table68k[opcode].handler != -1)
                   1715:            instrcount[table68k[opcode].handler]++;
                   1716: #elif COUNT_INSTRS == 1
                   1717:        instrcount[opcode]++;
                   1718: #endif
                   1719:        cycles = (*cpufunctbl[opcode])(opcode);
                   1720:        /*n_insns++;*/
                   1721:        cycles &= cycles_mask;
                   1722:        cycles |= cycles_val;
                   1723:        do_cycles (cycles);
                   1724:        if (regs.spcflags) {
1.1.1.19  root     1725:            if (do_specialties (cycles))
1.1.1.8   root     1726:                return;
                   1727:        }
                   1728:     }
                   1729: }
                   1730: 
1.1.1.12  root     1731: #define DEBUG_PREFETCH
                   1732: 
1.1.1.8   root     1733: /* Same thing, but don't use prefetch to get opcode.  */
                   1734: static void m68k_run_2 (void)
                   1735: {
                   1736:     for (;;) {
                   1737:        int cycles;
                   1738:        uae_u32 opcode = get_iword (0);
1.1.1.12  root     1739: 
1.1.1.2   root     1740:        /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
                   1741: /*     regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
1.1.1.3   root     1742: #if COUNT_INSTRS == 2
1.1.1.8   root     1743:        if (table68k[opcode].handler != -1)
                   1744:            instrcount[table68k[opcode].handler]++;
1.1.1.3   root     1745: #elif COUNT_INSTRS == 1
1.1.1.2   root     1746:        instrcount[opcode]++;
                   1747: #endif
1.1.1.4   root     1748:        cycles = (*cpufunctbl[opcode])(opcode);
1.1.1.12  root     1749: 
1.1.1.2   root     1750:        /*n_insns++;*/
1.1.1.4   root     1751:        cycles &= cycles_mask;
                   1752:        cycles |= cycles_val;
1.1.1.21  root     1753:        do_cycles (cycles);
1.1.1.2   root     1754:        if (regs.spcflags) {
1.1.1.19  root     1755:            if (do_specialties (cycles))
1.1       root     1756:                return;
                   1757:        }
                   1758:     }
                   1759: }
                   1760: 
1.1.1.13  root     1761: #define m68k_run1(F) (F) ()
1.1.1.2   root     1762: 
1.1.1.3   root     1763: int in_m68k_go = 0;
1.1       root     1764: 
1.1.1.20  root     1765: static void exception2_handle (uaecptr addr, uaecptr fault)
                   1766: {
                   1767:     last_addr_for_exception_3 = addr;
                   1768:     last_fault_for_exception_3 = fault;
                   1769:     last_writeaccess_for_exception_3 = 0;
                   1770:     last_instructionaccess_for_exception_3 = 0;
                   1771:     Exception (2, addr);
                   1772: }
                   1773: 
1.1.1.4   root     1774: void m68k_go (int may_quit)
1.1       root     1775: {
1.1.1.3   root     1776:     if (in_m68k_go || !may_quit) {
1.1.1.4   root     1777:        write_log ("Bug! m68k_go is not reentrant.\n");
                   1778:        abort ();
1.1.1.3   root     1779:     }
1.1.1.4   root     1780: 
                   1781:     reset_frame_rate_hack ();
                   1782:     update_68k_cycles ();
                   1783: 
1.1.1.3   root     1784:     in_m68k_go++;
                   1785:     for (;;) {
                   1786:        if (quit_program > 0) {
                   1787:            if (quit_program == 1)
1.1       root     1788:                break;
1.1.1.3   root     1789:            quit_program = 0;
1.1.1.18  root     1790:            if (savestate_state == STATE_RESTORE) {
                   1791:                restore_state (savestate_filename);
                   1792: #if 0
                   1793:                activate_debugger ();
                   1794: #endif
                   1795:            }
1.1.1.4   root     1796:            reset_all_systems ();
                   1797:            customreset ();
1.1.1.24! root     1798:            m68k_reset ();
1.1.1.14  root     1799:            /* We may have been restoring state, but we're done now.  */
                   1800:            savestate_restore_finish ();
1.1.1.20  root     1801:            fill_prefetch_slow ();
1.1.1.14  root     1802:            handle_active_events ();
1.1.1.18  root     1803:            if (regs.spcflags)
1.1.1.19  root     1804:                do_specialties (0);
1.1.1.20  root     1805:            m68k_setpc (regs.pc);
1.1       root     1806:        }
1.1.1.14  root     1807: 
1.1.1.3   root     1808:        if (debugging)
1.1.1.4   root     1809:            debug ();
1.1.1.20  root     1810:        if (regs.panic) {
                   1811:            regs.panic = 0;
                   1812:            /* program jumped to non-existing memory and cpu was >= 68020 */
                   1813:            get_real_address (regs.isp); /* stack in no one's land? -> reboot */
                   1814:            if (regs.isp & 1)
                   1815:                regs.panic = 1;
                   1816:            if (!regs.panic)
                   1817:                exception2_handle (regs.panic_pc, regs.panic_addr);
                   1818:            if (regs.panic) {
                   1819:                /* system is very badly confused */
                   1820:                write_log ("double bus error or corrupted stack, forcing reboot..\n");
                   1821:                regs.panic = 0;
1.1.1.22  root     1822:                uae_reset (1);
1.1.1.20  root     1823:            }
                   1824:        }
1.1.1.24! root     1825:        m68k_run1 (currprefs.cpu_model == 68000 ? m68k_run_1 : m68k_run_2);
1.1       root     1826:     }
1.1.1.3   root     1827:     in_m68k_go--;
1.1       root     1828: }
                   1829: 
1.1.1.4   root     1830: static void m68k_verify (uaecptr addr, uaecptr *nextpc)
1.1       root     1831: {
1.1.1.3   root     1832:     uae_u32 opcode, val;
                   1833:     struct instr *dp;
                   1834: 
                   1835:     opcode = get_iword_1(0);
                   1836:     last_op_for_exception_3 = opcode;
                   1837:     m68kpc_offset = 2;
                   1838: 
1.1.1.8   root     1839:     if (cpufunctbl[opcode] == op_illg_1) {
1.1.1.3   root     1840:        opcode = 0x4AFC;
                   1841:     }
                   1842:     dp = table68k + opcode;
                   1843: 
                   1844:     if (dp->suse) {
                   1845:        if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
                   1846:            Exception (3, 0);
                   1847:            return;
                   1848:        }
                   1849:     }
                   1850:     if (dp->duse) {
                   1851:        if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
                   1852:            Exception (3, 0);
                   1853:            return;
                   1854:        }
                   1855:     }
                   1856: }
                   1857: 
1.1.1.11  root     1858: void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.3   root     1859: {
                   1860:     uaecptr newpc = 0;
1.1.1.4   root     1861:     m68kpc_offset = addr - m68k_getpc ();
                   1862:     while (cnt-- > 0) {
1.1       root     1863:        char instrname[20],*ccpt;
                   1864:        int opwords;
1.1.1.3   root     1865:        uae_u32 opcode;
1.1       root     1866:        struct mnemolookup *lookup;
                   1867:        struct instr *dp;
1.1.1.11  root     1868:        fprintf (f, "%08lx: ", m68k_getpc () + m68kpc_offset);
1.1.1.3   root     1869:        for (opwords = 0; opwords < 5; opwords++){
1.1.1.11  root     1870:            fprintf (f, "%04x ", get_iword_1 (m68kpc_offset + opwords*2));
1.1       root     1871:        }
1.1.1.4   root     1872:        opcode = get_iword_1 (m68kpc_offset);
1.1.1.3   root     1873:        m68kpc_offset += 2;
1.1.1.8   root     1874:        if (cpufunctbl[opcode] == op_illg_1) {
1.1       root     1875:            opcode = 0x4AFC;
                   1876:        }
                   1877:        dp = table68k + opcode;
                   1878:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   1879:            ;
1.1.1.3   root     1880: 
1.1.1.4   root     1881:        strcpy (instrname, lookup->name);
                   1882:        ccpt = strstr (instrname, "cc");
1.1       root     1883:        if (ccpt != 0) {
1.1.1.4   root     1884:            strncpy (ccpt, ccnames[dp->cc], 2);
1.1       root     1885:        }
1.1.1.11  root     1886:        fprintf (f, "%s", instrname);
1.1.1.3   root     1887:        switch (dp->size){
1.1.1.11  root     1888:         case sz_byte: fprintf (f, ".B "); break;
                   1889:         case sz_word: fprintf (f, ".W "); break;
                   1890:         case sz_long: fprintf (f, ".L "); break;
                   1891:         default: fprintf (f, "   "); break;
1.1       root     1892:        }
                   1893: 
                   1894:        if (dp->suse) {
1.1.1.4   root     1895:            newpc = m68k_getpc () + m68kpc_offset;
1.1.1.11  root     1896:            newpc += ShowEA (f, dp->sreg, dp->smode, dp->size, 0);
1.1       root     1897:        }
                   1898:        if (dp->suse && dp->duse)
1.1.1.11  root     1899:            fprintf (f, ",");
1.1       root     1900:        if (dp->duse) {
1.1.1.4   root     1901:            newpc = m68k_getpc () + m68kpc_offset;
1.1.1.11  root     1902:            newpc += ShowEA (f, dp->dreg, dp->dmode, dp->size, 0);
1.1       root     1903:        }
                   1904:        if (ccpt != 0) {
                   1905:            if (cctrue(dp->cc))
1.1.1.11  root     1906:                fprintf (f, " == %08lx (TRUE)", newpc);
1.1.1.3   root     1907:            else
1.1.1.11  root     1908:                fprintf (f, " == %08lx (FALSE)", newpc);
1.1       root     1909:        } else if ((opcode & 0xff00) == 0x6100) /* BSR */
1.1.1.11  root     1910:            fprintf (f, " == %08lx", newpc);
                   1911:        fprintf (f, "\n");
1.1       root     1912:     }
1.1.1.4   root     1913:     if (nextpc)
                   1914:        *nextpc = m68k_getpc () + m68kpc_offset;
1.1       root     1915: }
                   1916: 
1.1.1.11  root     1917: void m68k_dumpstate (FILE *f, uaecptr *nextpc)
1.1       root     1918: {
                   1919:     int i;
1.1.1.3   root     1920:     for (i = 0; i < 8; i++){
1.1.1.24! root     1921:        fprintf (f, "D%d: %08lx ", i, m68k_dreg (regs, i));
1.1.1.11  root     1922:        if ((i & 3) == 3) fprintf (f, "\n");
1.1.1.3   root     1923:     }
                   1924:     for (i = 0; i < 8; i++){
1.1.1.23  root     1925:        fprintf (f, "A%d: %08lx ", i, m68k_areg (regs, i));
1.1.1.11  root     1926:        if ((i & 3) == 3) fprintf (f, "\n");
1.1       root     1927:     }
1.1.1.23  root     1928:     if (regs.s == 0) regs.usp = m68k_areg (regs, 7);
                   1929:     if (regs.s && regs.m) regs.msp = m68k_areg (regs, 7);
                   1930:     if (regs.s && regs.m == 0) regs.isp = m68k_areg (regs, 7);
1.1.1.11  root     1931:     fprintf (f, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
                   1932:             regs.usp,regs.isp,regs.msp,regs.vbr);
                   1933:     fprintf (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
                   1934:             regs.t1, regs.t0, regs.s, regs.m,
                   1935:             GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask);
1.1.1.3   root     1936:     for (i = 0; i < 8; i++){
1.1.1.11  root     1937:        fprintf (f, "FP%d: %g ", i, regs.fp[i]);
                   1938:        if ((i & 3) == 3) fprintf (f, "\n");
1.1       root     1939:     }
1.1.1.11  root     1940:     fprintf (f, "N=%d Z=%d I=%d NAN=%d\n",
                   1941:             (regs.fpsr & 0x8000000) != 0,
                   1942:             (regs.fpsr & 0x4000000) != 0,
                   1943:             (regs.fpsr & 0x2000000) != 0,
                   1944:             (regs.fpsr & 0x1000000) != 0);
1.1.1.3   root     1945: 
1.1.1.11  root     1946:     m68k_disasm (f, m68k_getpc (), nextpc, 1);
1.1.1.4   root     1947:     if (nextpc)
1.1.1.11  root     1948:        fprintf (f, "next PC: %08lx\n", *nextpc);
1.1       root     1949: }
1.1.1.14  root     1950: 
                   1951: 
                   1952: /* CPU save/restore code */
                   1953: 
                   1954: #define CPUTYPE_EC 1
1.1.1.24! root     1955: #define PREFETCH_VALID 2
        !          1956: #define M68KSPEED_SAVED 0x8000000
        !          1957: #define DEFAULT_SAVE_FLAGS (M68KSPEED_SAVED | PREFETCH_VALID)
1.1.1.14  root     1958: #define CPUMODE_HALT 1
                   1959: 
1.1.1.23  root     1960: const uae_u8 *restore_cpu (const uae_u8 *src)
1.1.1.14  root     1961: {
1.1.1.24! root     1962:     int i, model, flags;
1.1.1.14  root     1963:     uae_u32 l;
                   1964: 
1.1.1.24! root     1965:     changed_prefs.cpu_model = model = restore_u32();
1.1.1.14  root     1966: 
                   1967:     flags = restore_u32();
1.1.1.24! root     1968:     changed_prefs.address_space_24 = 0;
1.1.1.14  root     1969:     if (flags & CPUTYPE_EC)
1.1.1.24! root     1970:        changed_prefs.address_space_24 = 1;
1.1.1.14  root     1971:     for (i = 0; i < 15; i++)
                   1972:        regs.regs[i] = restore_u32 ();
                   1973:     regs.pc = restore_u32 ();
1.1.1.20  root     1974:     regs.irc = restore_u16 ();
                   1975:     regs.ir = restore_u16 ();
1.1.1.14  root     1976:     regs.usp = restore_u32 ();
                   1977:     regs.isp = restore_u32 ();
                   1978:     regs.sr = restore_u16 ();
                   1979:     l = restore_u32();
1.1.1.18  root     1980:     if (l & CPUMODE_HALT) {
1.1.1.14  root     1981:        regs.stopped = 1;
1.1.1.18  root     1982:        set_special (SPCFLAG_STOP);
                   1983:     } else
1.1.1.14  root     1984:        regs.stopped = 0;
                   1985:     if (model >= 68010) {
                   1986:        regs.dfc = restore_u32 ();
                   1987:        regs.sfc = restore_u32 ();
                   1988:        regs.vbr = restore_u32 ();
                   1989:     }
                   1990:     if (model >= 68020) {
1.1.1.24! root     1991:        regs.caar = restore_u32 ();
        !          1992:        regs.cacr = restore_u32 ();
1.1.1.14  root     1993:        regs.msp = restore_u32 ();
                   1994:     }
1.1.1.24! root     1995:     if (model >= 68030) {
        !          1996:        regs.crp_030 = restore_u64 ();
        !          1997:        regs.srp_030 = restore_u64 ();
        !          1998:        regs.tt0_030 = restore_u32 ();
        !          1999:        regs.tt1_030 = restore_u32 ();
        !          2000:        regs.tc_030 = restore_u32 ();
        !          2001:        regs.mmusr_030 = restore_u16 ();
        !          2002:     }
        !          2003:     if (model >= 68040) {
        !          2004:        regs.itt0 = restore_u32 ();
        !          2005:        regs.itt1 = restore_u32 ();
        !          2006:        regs.dtt0 = restore_u32 ();
        !          2007:        regs.dtt1 = restore_u32 ();
        !          2008:        regs.tcr = restore_u32 ();
        !          2009:        regs.urp = restore_u32 ();
        !          2010:        regs.srp = restore_u32 ();
        !          2011:     }
        !          2012:     if (model >= 68060) {
        !          2013:        regs.buscr = restore_u32 ();
        !          2014:        regs.pcr = restore_u32 ();
        !          2015:     }
        !          2016:     if (flags & M68KSPEED_SAVED) {
        !          2017:        int khz = restore_u32 ();
        !          2018:        restore_u32 ();
        !          2019:        if (khz > 0 && khz < 800000)
        !          2020:            currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
        !          2021:     }
        !          2022: 
        !          2023:     if (!(flags & PREFETCH_VALID))
        !          2024:        fill_prefetch_slow ();
1.1.1.14  root     2025:     write_log ("CPU %d%s%03d, PC=%08.8X\n",
1.1.1.24! root     2026:               model / 1000, flags & 1 ? "EC" : "", model % 1000, regs.pc);
1.1.1.14  root     2027: 
                   2028:     return src;
                   2029: }
                   2030: 
1.1.1.22  root     2031: uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
1.1.1.14  root     2032: {
1.1.1.24! root     2033:     uae_u8 *dstbak, *dst;
        !          2034:     int model, i, khz;
1.1.1.14  root     2035: 
1.1.1.22  root     2036:     if (dstptr)
                   2037:        dstbak = dst = dstptr;
                   2038:     else
1.1.1.24! root     2039:        dstbak = dst = malloc (1000);
        !          2040:     model = currprefs.cpu_model;
1.1.1.14  root     2041:     save_u32 (model);                                  /* MODEL */
1.1.1.24! root     2042:     save_u32 (DEFAULT_SAVE_FLAGS | (currprefs.address_space_24 ? 1 : 0));      /* FLAGS */
        !          2043:     for (i = 0;i < 15; i++) save_u32 (regs.regs[i]);   /* D0-D7 A0-A6 */
1.1.1.14  root     2044:     save_u32 (m68k_getpc ());                          /* PC */
1.1.1.20  root     2045:     save_u16 (regs.irc);                               /* prefetch */
                   2046:     save_u16 (regs.ir);                                        /* instruction prefetch */
1.1.1.14  root     2047:     MakeSR ();
                   2048:     save_u32 (!regs.s ? regs.regs[15] : regs.usp);     /* USP */
                   2049:     save_u32 (regs.s ? regs.regs[15] : regs.isp);      /* ISP */
                   2050:     save_u16 (regs.sr);                                /* SR/CCR */
                   2051:     save_u32 (regs.stopped ? CPUMODE_HALT : 0);        /* flags */
1.1.1.24! root     2052:     if (model >= 68010) {
1.1.1.14  root     2053:        save_u32 (regs.dfc);                            /* DFC */
                   2054:        save_u32 (regs.sfc);                            /* SFC */
                   2055:        save_u32 (regs.vbr);                            /* VBR */
                   2056:     }
1.1.1.24! root     2057:     if (model >= 68020) {
        !          2058:        save_u32 (regs.caar);                           /* CAAR */
        !          2059:        save_u32 (regs.cacr);                           /* CACR */
1.1.1.14  root     2060:        save_u32 (regs.msp);                            /* MSP */
                   2061:     }
1.1.1.24! root     2062:     if (model >= 68030) {
        !          2063:        save_u64 (regs.crp_030);                        /* CRP */
        !          2064:        save_u64 (regs.srp_030);                        /* SRP */
        !          2065:        save_u32 (regs.tt0_030);                        /* TT0/AC0 */
        !          2066:        save_u32 (regs.tt1_030);                        /* TT1/AC1 */
        !          2067:        save_u32 (regs.tc_030);                         /* TCR */
        !          2068:        save_u16 (regs.mmusr_030);                      /* MMUSR/ACUSR */
        !          2069:     }
        !          2070:     if (model >= 68040) {
        !          2071:        save_u32 (regs.itt0);                           /* ITT0 */
        !          2072:        save_u32 (regs.itt1);                           /* ITT1 */
        !          2073:        save_u32 (regs.dtt0);                           /* DTT0 */
        !          2074:        save_u32 (regs.dtt1);                           /* DTT1 */
        !          2075:        save_u32 (regs.tcr);                            /* TCR */
        !          2076:        save_u32 (regs.urp);                            /* URP */
        !          2077:        save_u32 (regs.srp);                            /* SRP */
        !          2078:     }
        !          2079:     if (model >= 68060) {
        !          2080:        save_u32 (regs.buscr);                          /* BUSCR */
        !          2081:        save_u32 (regs.pcr);                            /* PCR */
        !          2082:     }
        !          2083:     khz = -1;
        !          2084:     if (currprefs.m68k_speed == 0) {
        !          2085:        khz = currprefs.ntscmode ? 715909 : 709379;
        !          2086:        if (currprefs.cpu_model >= 68020)
        !          2087:            khz *= 2;
        !          2088:     }
        !          2089:     save_u32 (khz); // clock rate in KHz: -1 = fastest possible
        !          2090:     save_u32 (0); // spare
1.1.1.14  root     2091:     *len = dst - dstbak;
                   2092:     return dstbak;
                   2093: }
1.1.1.20  root     2094: 
                   2095: static void exception3f (uae_u32 opcode, uaecptr addr, uaecptr fault, int writeaccess, int instructionaccess)
                   2096: {
                   2097:     last_addr_for_exception_3 = addr;
                   2098:     last_fault_for_exception_3 = fault;
                   2099:     last_op_for_exception_3 = opcode;
                   2100:     last_writeaccess_for_exception_3 = writeaccess;
                   2101:     last_instructionaccess_for_exception_3 = instructionaccess;
                   2102:     Exception (3, fault);
                   2103: }
                   2104: 
                   2105: void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault)
                   2106: {
                   2107:     exception3f (opcode, addr, fault, 0, 0);
                   2108: }
                   2109: 
                   2110: void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault)
                   2111: {
                   2112:     exception3f (opcode, addr, fault, 0, 1);
                   2113: }
                   2114: 
                   2115: void exception2 (uaecptr addr, uaecptr fault)
                   2116: {
                   2117:     write_log ("delayed exception2!\n");
1.1.1.24! root     2118:     regs.panic_pc = m68k_getpc ();
1.1.1.20  root     2119:     regs.panic_addr = addr;
                   2120:     regs.panic = 2;
                   2121:     set_special (SPCFLAG_BRK);
                   2122:     m68k_setpc (0xf80000);
                   2123:     fill_prefetch_slow ();
                   2124: }
                   2125: 
                   2126: void cpureset (void)
                   2127: {
1.1.1.24! root     2128:     uaecptr pc;
        !          2129:     uaecptr ksboot = 0xf80002 - 2; /* -2 = RESET hasn't increased PC yet */
1.1.1.20  root     2130:     uae_u16 ins;
1.1.1.24! root     2131: 
        !          2132: #if 0
        !          2133:     if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) {
        !          2134:        customreset (0);
        !          2135:        return;
        !          2136:     }
        !          2137: #endif
        !          2138:     pc = m68k_getpc ();
        !          2139:     if (pc >= currprefs.chipmem_size) {
        !          2140:        addrbank *b = &get_mem_bank (pc);
        !          2141:        if (b->check (pc, 2 + 2)) {
        !          2142:            /* We have memory, hope for the best.. */
        !          2143:            customreset ();
        !          2144:            return;
        !          2145:        }
        !          2146:        write_log ("M68K RESET PC=%x, rebooting..\n", pc);
1.1.1.20  root     2147:        customreset ();
1.1.1.24! root     2148:        m68k_setpc (ksboot);
1.1.1.20  root     2149:        return;
                   2150:     }
1.1.1.24! root     2151:     /* panic, RAM is going to disappear under PC */
        !          2152:     ins = get_word (pc + 2);
1.1.1.20  root     2153:     if ((ins & ~7) == 0x4ed0) {
                   2154:        int reg = ins & 7;
                   2155:        uae_u32 addr = m68k_areg (regs, reg);
1.1.1.24! root     2156:        write_log ("reset/jmp (ax) combination emulated -> %x\n", addr);
1.1.1.20  root     2157:        customreset ();
                   2158:        if (addr < 0x80000)
                   2159:            addr += 0xf80000;
1.1.1.24! root     2160:        m68k_setpc (addr - 2);
        !          2161:        return;
1.1.1.20  root     2162:     }
1.1.1.24! root     2163:     write_log ("M68K RESET PC=%x, rebooting..\n", pc);
        !          2164:     customreset ();
        !          2165:     m68k_setpc (ksboot);
1.1.1.20  root     2166: }

unix.superglobalmegacorp.com

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