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

1.1       root        1:  /* 
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   * 
                      4:   * MC68000 emulation
                      5:   *
                      6:   * (c) 1995 Bernd Schmidt
                      7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include "config.h"
                     13: #include "options.h"
1.1.1.2 ! root       14: #include "machdep/m68k.h"
1.1       root       15: #include "events.h"
                     16: #include "gui.h"
                     17: #include "memory.h"
                     18: #include "custom.h"
1.1.1.2 ! root       19: #include "readcpu.h"
1.1       root       20: #include "newcpu.h"
                     21: #include "autoconf.h"
                     22: #include "ersatz.h"
                     23: #include "blitter.h"
                     24: #include "debug.h"
                     25: #include "compiler.h"
                     26: 
                     27: int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
                     28: int imm8_table[] = { 8,1,2,3,4,5,6,7 };
                     29: 
                     30: int movem_index1[256];
                     31: int movem_index2[256];
                     32: int movem_next[256];
                     33: 
                     34: int fpp_movem_index1[256];
                     35: int fpp_movem_index2[256];
                     36: int fpp_movem_next[256];
                     37: 
                     38: cpuop_func *cpufunctbl[65536];
1.1.1.2 ! root       39: #if USER_PROGRAMS_BEHAVE > 0
        !            40: cpuop_func *cpufunctbl_behaved[65536];
1.1       root       41: #endif
                     42: 
                     43: #define COUNT_INSTRS   0
                     44: 
                     45: #if COUNT_INSTRS
                     46: static unsigned long int instrcount[65536];
                     47: static UWORD opcodenums[65536];
                     48: 
                     49: static int compfn(const void *el1, const void *el2)
                     50: {
                     51:     return instrcount[*(const UWORD *)el1] < instrcount[*(const UWORD *)el2];
                     52: }
                     53: 
                     54: void dump_counts(void)
                     55: {
                     56:     FILE *f = fopen(getenv("INSNCOUNT") ? getenv("INSNCOUNT") : "insncount", "w");
                     57:     unsigned long int total = 0;
                     58:     int i;
                     59:     
                     60:     for(i=0; i < 65536; i++) {
                     61:        opcodenums[i] = i;
                     62:        total += instrcount[i];
                     63:     }
                     64:     qsort(opcodenums, 65536, sizeof(UWORD), compfn);
                     65:     
                     66:     fprintf(f, "Total: %lu\n", total);
                     67:     for(i=0; i < 65536; i++) {
                     68:        unsigned long int cnt = instrcount[opcodenums[i]];
                     69:        struct instr *dp;
                     70:        struct mnemolookup *lookup;
                     71:        if (!cnt)
                     72:            break;
                     73:        dp = table68k + opcodenums[i];
                     74:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) ;
                     75:        fprintf(f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
                     76:     }
                     77:     fclose(f);
                     78: }
                     79: #else
                     80: void dump_counts(void)
                     81: {
                     82: }
                     83: #endif
                     84: 
                     85: int broken_in;
                     86: 
                     87: void init_m68k (void)
                     88: {
                     89:     long int opcode;
                     90:     int i,j;
                     91:     
                     92:     for (i = 0 ; i < 256 ; i++) {
                     93:        for (j = 0 ; j < 8 ; j++) {
                     94:                if (i & (1 << j)) break;
                     95:        }
                     96:        movem_index1[i] = j;
                     97:        movem_index2[i] = 7-j;
                     98:        movem_next[i] = i & (~(1 << j));
                     99:     }
                    100:     for (i = 0 ; i < 256 ; i++) {
                    101:        for (j = 7 ; j >= 0 ; j--) {
                    102:                if (i & (1 << j)) break;
                    103:        }
                    104:        fpp_movem_index1[i] = j;
                    105:        fpp_movem_index2[i] = 7-j;
                    106:        fpp_movem_next[i] = i & (~(1 << j));
                    107:     }
                    108: #if COUNT_INSTRS
                    109:     {
                    110:         FILE *f = fopen("insncount", "r");
                    111:        memset(instrcount, 0, sizeof instrcount);
                    112:        if (f) {
                    113:            ULONG opcode, count, total;
                    114:            char name[20];
                    115:            fscanf(f,"Total: %lu\n",&total);
                    116:            while(fscanf(f,"%lx: %lu %s\n",&opcode,&count,name)==3) {
                    117:                instrcount[opcode] = count;
                    118:            }
                    119:            fclose(f);
                    120:        }
                    121:     }
                    122: #endif
                    123:     printf("Building CPU table...\n");
                    124:     read_table68k ();
                    125:     do_merges ();
                    126:     for (opcode = 0; opcode < 65536; opcode++)
                    127:        cpufunctbl[opcode] = op_illg;
1.1.1.2 ! root      128:     for (i = 0; op_smalltbl[i].handler != NULL; i++) {
        !           129:        if (!op_smalltbl[i].specific)
        !           130:            cpufunctbl[op_smalltbl[i].opcode] = op_smalltbl[i].handler;
1.1       root      131:     }
                    132:     for (opcode = 0; opcode < 65536; opcode++) {
                    133:        cpuop_func *f;
                    134:        
                    135:        if (table68k[opcode].mnemo == i_ILLG)
                    136:            continue;
                    137:        
                    138:        if (table68k[opcode].handler != -1) {
                    139:            f = cpufunctbl[table68k[opcode].handler];
                    140:            if (f == op_illg)
                    141:                abort();
                    142:            cpufunctbl[opcode] = f;
                    143:        }
                    144:     }  
1.1.1.2 ! root      145:     for (i = 0; op_smalltbl[i].handler != NULL; i++) {
        !           146:        if (op_smalltbl[i].specific)
        !           147:            cpufunctbl[op_smalltbl[i].opcode] = op_smalltbl[i].handler;
        !           148:     }
        !           149: #if USER_PROGRAMS_BEHAVE > 0
        !           150:     for (opcode = 0; opcode < 65536; opcode++)
        !           151:        cpufunctbl_behaved[opcode] = op_illg;
        !           152: 
        !           153:     for (i = 0; op_direct_smalltbl[i].handler != NULL; i++) {
        !           154:        if (!op_direct_smalltbl[i].specific)
        !           155:            cpufunctbl_behaved[op_direct_smalltbl[i].opcode] = op_direct_smalltbl[i].handler;
        !           156:     }
        !           157:     for (opcode = 0; opcode < 65536; opcode++) {
        !           158:        cpuop_func *f;
        !           159:        
        !           160:        if (table68k[opcode].mnemo == i_ILLG)
        !           161:            continue;
        !           162:        
        !           163:        if (table68k[opcode].handler != -1) {
        !           164:            f = cpufunctbl_behaved[table68k[opcode].handler];
        !           165:            if (f == op_illg)
        !           166:                abort();
        !           167:            cpufunctbl_behaved[opcode] = f;
        !           168:        }
        !           169:     }  
        !           170:     for (i = 0; op_direct_smalltbl[i].handler != NULL; i++) {
        !           171:        if (op_direct_smalltbl[i].specific)
        !           172:            cpufunctbl_behaved[op_direct_smalltbl[i].opcode] = op_direct_smalltbl[i].handler;
1.1       root      173:     }
1.1.1.2 ! root      174: #endif
1.1       root      175: }
                    176: 
                    177: struct regstruct regs, lastint_regs;
                    178: static struct regstruct regs_backup[16];
                    179: static int backup_pointer = 0;
                    180: int lastint_no;
                    181: 
1.1.1.2 ! root      182: LONG ShowEA(int reg, amodes mode, wordsizes size, char *buf)
1.1       root      183: {
                    184:     UWORD dp;
                    185:     BYTE disp8;
                    186:     WORD disp16;
                    187:     int r;
                    188:     ULONG dispreg;
                    189:     CPTR addr;
                    190:     LONG offset = 0;
1.1.1.2 ! root      191:     char buffer[80];
1.1       root      192:     
                    193:     switch(mode){
                    194:      case Dreg:
1.1.1.2 ! root      195:        sprintf(buffer,"D%d", reg);
1.1       root      196:        break;
                    197:      case Areg:
1.1.1.2 ! root      198:        sprintf(buffer,"A%d", reg);
1.1       root      199:        break;
                    200:      case Aind:
1.1.1.2 ! root      201:        sprintf(buffer,"(A%d)", reg);
1.1       root      202:        break;
                    203:      case Aipi:
1.1.1.2 ! root      204:        sprintf(buffer,"(A%d)+", reg);
1.1       root      205:        break;
                    206:      case Apdi:
1.1.1.2 ! root      207:        sprintf(buffer,"-(A%d)", reg);
1.1       root      208:        break;
                    209:      case Ad16:
                    210:        disp16 = nextiword();
1.1.1.2 ! root      211:        addr = m68k_areg(regs,reg) + (WORD)disp16;
        !           212:        sprintf(buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff,
1.1       root      213:                                        (long unsigned int)addr);
                    214:        break;
                    215:      case Ad8r:
                    216:        dp = nextiword();
                    217:        disp8 = dp & 0xFF;
                    218:        r = (dp & 0x7000) >> 12;
1.1.1.2 ! root      219:        dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);  
1.1       root      220:        if (!(dp & 0x800)) dispreg = (LONG)(WORD)(dispreg);
                    221:        dispreg <<= (dp >> 9) & 3;
                    222:        
                    223:        if (dp & 0x100) {
                    224:                LONG outer = 0, disp = 0;
1.1.1.2 ! root      225:                LONG base = m68k_areg(regs,reg);
1.1       root      226:                char name[10];
                    227:                sprintf(name,"A%d, ",reg);
                    228:                if (dp & 0x80) { base = 0; name[0] = 0; }
                    229:                if (dp & 0x40) dispreg = 0;
                    230:                if ((dp & 0x30) == 0x20) disp = (LONG)(WORD)nextiword();
                    231:                if ((dp & 0x30) == 0x30) disp = nextilong();
                    232:                base += disp;
                    233:                
                    234:                if ((dp & 0x3) == 0x2) outer = (LONG)(WORD)nextiword();
                    235:                if ((dp & 0x3) == 0x3) outer = nextilong();
                    236:                
                    237:                if (!(dp & 4)) base += dispreg;
                    238:                if (dp & 3) base = get_long (base);
                    239:                if (dp & 4) base += dispreg;
                    240:                
                    241:                addr = base + outer;
1.1.1.2 ! root      242:                sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name, 
1.1       root      243:                       dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    244:                       1 << ((dp >> 9) & 3),
                    245:                       disp,outer,
                    246:                       (long unsigned int)addr);
                    247:        }
                    248:        else {
1.1.1.2 ! root      249:          addr = m68k_areg(regs,reg) + (LONG)((BYTE)disp8) + dispreg;
        !           250:          sprintf(buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, 
1.1       root      251:               dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    252:               1 << ((dp >> 9) & 3), disp8,
                    253:               (long unsigned int)addr);
                    254:        }
                    255:        break;
                    256:      case PC16:
                    257:        addr = m68k_getpc();
                    258:        disp16 = nextiword();
                    259:        addr += (WORD)disp16;
1.1.1.2 ! root      260:        sprintf(buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(long unsigned int)addr);
1.1       root      261:        break;
                    262:      case PC8r:
                    263:        addr = m68k_getpc();
                    264:        dp = nextiword();
                    265:        disp8 = dp & 0xFF;
                    266:        r = (dp & 0x7000) >> 12;
1.1.1.2 ! root      267:        dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
1.1       root      268:        if (!(dp & 0x800)) dispreg = (LONG)(WORD)(dispreg);
                    269:        dispreg <<= (dp >> 9) & 3;
                    270:        
                    271:        if (dp & 0x100) {
                    272:                LONG outer = 0,disp = 0;
                    273:                LONG base = addr;
                    274:                char name[10];
                    275:                sprintf(name,"PC, ");
                    276:                if (dp & 0x80) { base = 0; name[0] = 0; }
                    277:                if (dp & 0x80) base = 0;
                    278:                if (dp & 0x40) dispreg = 0;
                    279:                if ((dp & 0x30) == 0x20) disp = (LONG)(WORD)nextiword();
                    280:                if ((dp & 0x30) == 0x30) disp = nextilong();
                    281:                base += disp;
                    282:                
                    283:                if ((dp & 0x3) == 0x2) outer = (LONG)(WORD)nextiword();
                    284:                if ((dp & 0x3) == 0x3) outer = nextilong();
                    285:                
                    286:                if (!(dp & 4)) base += dispreg;
                    287:                if (dp & 3) base = get_long (base);
                    288:                if (dp & 4) base += dispreg;
                    289:                
                    290:                addr = base + outer;
1.1.1.2 ! root      291:                sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
1.1       root      292:                       dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
                    293:                       1 << ((dp >> 9) & 3),
                    294:                       disp,outer,
                    295:                       (long unsigned int)addr);
1.1.1.2 ! root      296:        } else {
1.1       root      297:          addr += (LONG)((BYTE)disp8) + dispreg;
1.1.1.2 ! root      298:          sprintf(buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', 
1.1       root      299:                (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
                    300:                disp8, (long unsigned int)addr);
                    301:        }
                    302:        break;
                    303:      case absw:
1.1.1.2 ! root      304:        sprintf(buffer,"$%08lx", (long unsigned int)(LONG)(WORD)nextiword());
1.1       root      305:        break;
                    306:      case absl:
1.1.1.2 ! root      307:        sprintf(buffer,"$%08lx", (long unsigned int)nextilong());
1.1       root      308:        break;
                    309:      case imm:
                    310:        switch(size){
                    311:         case sz_byte:
1.1.1.2 ! root      312:            sprintf(buffer,"#$%02x", (unsigned int)(nextiword() & 0xff)); break;
1.1       root      313:         case sz_word:
1.1.1.2 ! root      314:            sprintf(buffer,"#$%04x", (unsigned int)(nextiword() & 0xffff)); break;
1.1       root      315:         case sz_long:
1.1.1.2 ! root      316:            sprintf(buffer,"#$%08lx", (long unsigned int)(nextilong())); break;
1.1       root      317:         default:
                    318:            break;
                    319:        }
                    320:        break;
                    321:      case imm0:
                    322:        offset = (LONG)(BYTE)nextiword();
1.1.1.2 ! root      323:        sprintf(buffer,"#$%02x", (unsigned int)(offset & 0xff));
1.1       root      324:        break;
                    325:      case imm1:
                    326:        offset = (LONG)(WORD)nextiword();
1.1.1.2 ! root      327:        sprintf(buffer,"#$%04x", (unsigned int)(offset & 0xffff));
1.1       root      328:        break;
                    329:      case imm2:
                    330:        offset = (LONG)nextilong();
1.1.1.2 ! root      331:        sprintf(buffer,"#$%08lx", (long unsigned int)offset);
1.1       root      332:        break;
                    333:      case immi:
                    334:        offset = (LONG)(BYTE)(reg & 0xff);
1.1.1.2 ! root      335:        sprintf(buffer,"#$%08lx", (long unsigned int)offset);
1.1       root      336:        break;
                    337:      default:
                    338:        break;
                    339:     }
1.1.1.2 ! root      340:     if (buf == 0)
        !           341:        printf("%s", buffer);
        !           342:     else
        !           343:        strcat(buf, buffer);
        !           344:     return offset;
1.1       root      345: }
                    346: 
                    347: void MakeSR(void)
                    348: {
                    349: #if 0
                    350:     assert((regs.t1 & 1) == regs.t1);
                    351:     assert((regs.t0 & 1) == regs.t0);
                    352:     assert((regs.s & 1) == regs.s);
                    353:     assert((regs.m & 1) == regs.m);
                    354:     assert((XFLG & 1) == XFLG);
                    355:     assert((NFLG & 1) == NFLG);
                    356:     assert((ZFLG & 1) == ZFLG);
                    357:     assert((VFLG & 1) == VFLG);
                    358:     assert((CFLG & 1) == CFLG);
                    359: #endif
                    360:     regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
                    361:               | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
                    362:               | (XFLG << 4) | (NFLG << 3) | (ZFLG << 2) | (VFLG << 1) 
                    363:               |  CFLG);
                    364: }
                    365: 
                    366: void MakeFromSR(void)
                    367: {
                    368:     int oldm = regs.m;
                    369:     int olds = regs.s;
                    370: 
                    371:     regs.t1 = (regs.sr >> 15) & 1;
                    372:     regs.t0 = (regs.sr >> 14) & 1;
                    373:     regs.s = (regs.sr >> 13) & 1;
                    374:     regs.m = (regs.sr >> 12) & 1;
                    375:     regs.intmask = (regs.sr >> 8) & 7;
                    376:     XFLG = (regs.sr >> 4) & 1;
                    377:     NFLG = (regs.sr >> 3) & 1;
                    378:     ZFLG = (regs.sr >> 2) & 1;
                    379:     VFLG = (regs.sr >> 1) & 1;
                    380:     CFLG = regs.sr & 1;
                    381:     if (CPU_LEVEL >= 2) {
                    382:        if (olds != regs.s) {
                    383:            if (olds) {
                    384:                if (oldm)
1.1.1.2 ! root      385:                    regs.msp = m68k_areg(regs, 7);
1.1       root      386:                else
1.1.1.2 ! root      387:                    regs.isp = m68k_areg(regs, 7);
        !           388:                m68k_areg(regs, 7) = regs.usp;
        !           389:            } else {
        !           390:                regs.usp = m68k_areg(regs, 7);
        !           391:                m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
1.1       root      392:            }
                    393:        } else if (olds && oldm != regs.m) {
                    394:            if (oldm) {
1.1.1.2 ! root      395:                regs.msp = m68k_areg(regs, 7);
        !           396:                m68k_areg(regs, 7) = regs.isp;
        !           397:            } else {
        !           398:                regs.isp = m68k_areg(regs, 7);
        !           399:                m68k_areg(regs, 7) = regs.msp;
1.1       root      400:            }
                    401:        }
                    402:     } else {
                    403:        if (olds != regs.s) {
                    404:            if (olds) {
1.1.1.2 ! root      405:                regs.isp = m68k_areg(regs, 7);
        !           406:                m68k_areg(regs, 7) = regs.usp;
1.1       root      407:            } else {
1.1.1.2 ! root      408:                regs.usp = m68k_areg(regs, 7);
        !           409:                m68k_areg(regs, 7) = regs.isp;
1.1       root      410:            }
                    411:        }
                    412:     }
                    413:     
                    414:     regs.spcflags |= SPCFLAG_INT;
                    415:     if (regs.t1 || regs.t0)
                    416:        regs.spcflags |= SPCFLAG_TRACE;
                    417:     else
                    418:        regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                    419: }
                    420: 
                    421: void Exception(int nr, CPTR oldpc)
                    422: {
1.1.1.2 ! root      423:     compiler_flush_jsr_stack();
1.1       root      424:     MakeSR();
                    425:     if (!regs.s) {
1.1.1.2 ! root      426:        regs.usp = m68k_areg(regs, 7);
1.1       root      427:        if (CPU_LEVEL >= 2)
1.1.1.2 ! root      428:            m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
1.1       root      429:        else
1.1.1.2 ! root      430:            m68k_areg(regs, 7) = regs.isp;
1.1       root      431:        regs.s = 1;
                    432:     }
                    433:     if (CPU_LEVEL > 0) {
                    434:        if (nr == 2 || nr == 3) {
                    435:            int i;
                    436:            for (i = 0 ; i < 12 ; i++) {
1.1.1.2 ! root      437:                m68k_areg(regs, 7) -= 2;
        !           438:                put_word (m68k_areg(regs, 7), 0);
1.1       root      439:            }
1.1.1.2 ! root      440:            m68k_areg(regs, 7) -= 2;
        !           441:            put_word (m68k_areg(regs, 7), 0xa000 + nr * 4);
1.1       root      442:        } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
1.1.1.2 ! root      443:            m68k_areg(regs, 7) -= 4;
        !           444:            put_long (m68k_areg(regs, 7), oldpc);
        !           445:            m68k_areg(regs, 7) -= 2;
        !           446:            put_word (m68k_areg(regs, 7), 0x2000 + nr * 4);
1.1       root      447:        } else if (regs.m && nr >= 24 && nr < 32) {
1.1.1.2 ! root      448:            m68k_areg(regs, 7) -= 2;
        !           449:            put_word (m68k_areg(regs, 7), nr * 4);
        !           450:            m68k_areg(regs, 7) -= 4;
        !           451:            put_long (m68k_areg(regs, 7), m68k_getpc ());
        !           452:            m68k_areg(regs, 7) -= 2;
        !           453:            put_word (m68k_areg(regs, 7), regs.sr);
1.1       root      454:            regs.sr |= (1 << 13);
1.1.1.2 ! root      455:            regs.msp = m68k_areg(regs, 7);
        !           456:            m68k_areg(regs, 7) = regs.isp;
        !           457:            m68k_areg(regs, 7) -= 2;
        !           458:            put_word (m68k_areg(regs, 7), 0x1000 + nr * 4);
1.1       root      459:        } else {
1.1.1.2 ! root      460:            m68k_areg(regs, 7) -= 2;
        !           461:            put_word (m68k_areg(regs, 7), nr * 4);
1.1       root      462:        }
                    463:     }
1.1.1.2 ! root      464:     m68k_areg(regs, 7) -= 4;
        !           465:     put_long (m68k_areg(regs, 7), m68k_getpc ());
        !           466:     m68k_areg(regs, 7) -= 2;
        !           467:     put_word (m68k_areg(regs, 7), regs.sr);
1.1       root      468:     m68k_setpc(get_long(regs.vbr + 4*nr));
                    469:     regs.t1 = regs.t0 = regs.m = 0;
                    470:     regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
                    471: }
                    472: 
                    473: static void Interrupt(int nr)
                    474: {
                    475:     assert(nr < 8 && nr >= 0);
                    476:     lastint_regs = regs;
                    477:     lastint_no = nr;
                    478:     Exception(nr+24, 0);
                    479:     
                    480:     regs.intmask = nr;
                    481:     regs.spcflags |= SPCFLAG_INT;
                    482: }
                    483: 
                    484: static int caar, cacr;
                    485: 
                    486: void m68k_move2c (int regno, ULONG *regp)
                    487: {
                    488:     if (CPU_LEVEL == 1 && (regno & 0x7FF) > 1)
                    489:        op_illg (0x4E7B);
                    490:     else
                    491:        switch (regno) {
                    492:         case 0: regs.sfc = *regp & 7; break;
                    493:         case 1: regs.dfc = *regp & 7; break;
                    494:         case 2: cacr = *regp & 0x3; break;     /* ignore C and CE */
                    495:         case 0x800: regs.usp = *regp; break;
                    496:         case 0x801: regs.vbr = *regp; break;
                    497:         case 0x802: caar = *regp &0xfc; break;
1.1.1.2 ! root      498:         case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
        !           499:         case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
1.1       root      500:         default:
                    501:            op_illg (0x4E7B);
                    502:            break;
                    503:        }
                    504: }
                    505: 
                    506: void m68k_movec2 (int regno, ULONG *regp)
                    507: {
                    508:     if (CPU_LEVEL == 1 && (regno & 0x7FF) > 1)
                    509:        op_illg (0x4E7A);
                    510:     else
                    511:        switch (regno) {
                    512:         case 0: *regp = regs.sfc; break;
                    513:         case 1: *regp = regs.dfc; break;
                    514:         case 2: *regp = cacr; break;
                    515:         case 0x800: *regp = regs.usp; break;
                    516:         case 0x801: *regp = regs.vbr; break;
                    517:         case 0x802: *regp = caar; break;
1.1.1.2 ! root      518:         case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
        !           519:         case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
1.1       root      520:         default:
                    521:            op_illg (0x4E7A);
                    522:            break;
                    523:        }
                    524: }
                    525: 
                    526: static __inline__ int
                    527: div_unsigned(ULONG src_hi, ULONG src_lo, ULONG div, ULONG *quot, ULONG *rem)
                    528: {
                    529:        ULONG q = 0, cbit = 0;
                    530:        int i;
                    531: 
                    532:        if (div <= src_hi) {
                    533:            return(1);
                    534:        }
                    535:        for (i = 0 ; i < 32 ; i++) {
1.1.1.2 ! root      536:                cbit = src_hi & 0x80000000ul;
1.1       root      537:                src_hi <<= 1;
1.1.1.2 ! root      538:                if (src_lo & 0x80000000ul) src_hi++;
1.1       root      539:                src_lo <<= 1;
                    540:                q = q << 1;
                    541:                if (cbit || div <= src_hi) {
                    542:                        q |= 1;
                    543:                        src_hi -= div;
                    544:                }
                    545:        }
                    546:        *quot = q;
                    547:        *rem = src_hi;
                    548:        return(0);
                    549: }
                    550: 
                    551: void m68k_divl (ULONG opcode, ULONG src, UWORD extra, CPTR oldpc)
                    552: {
                    553: #if defined(INT_64BIT)
                    554:     if (src == 0) {
                    555:        Exception(5,oldpc-2);
                    556:        return;
                    557:     }
                    558:     if (extra & 0x800) {
                    559:        /* signed variant */
1.1.1.2 ! root      560:        INT_64BIT a = (INT_64BIT)(LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      561:        INT_64BIT quot, rem;
                    562:        
                    563:        if (extra & 0x400) {
                    564:            a &= 0xffffffffLL;
1.1.1.2 ! root      565:            a |= (INT_64BIT)m68k_dreg(regs, extra & 7) << 32;
1.1       root      566:        }
                    567:        rem = a % (INT_64BIT)(LONG)src;
                    568:        quot = a / (INT_64BIT)(LONG)src;
1.1.1.2 ! root      569:        if ((quot & 0xffffffff80000000uLL) != 0 &&
        !           570:            (quot & 0xffffffff80000000uLL) != 0xffffffff80000000uLL) {
1.1       root      571:            VFLG = NFLG = 1;
                    572:            CFLG = 0;
                    573:        }
                    574:        else {
                    575:            if (((LONG)rem < 0) != ((INT_64BIT)a < 0)) rem = -rem;
                    576:            VFLG = CFLG = 0;
                    577:            ZFLG = ((LONG)quot) == 0;
                    578:            NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root      579:            m68k_dreg(regs, extra & 7) = rem;
        !           580:            m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1       root      581:        }
                    582:     } else {
                    583:        /* unsigned */
1.1.1.2 ! root      584:        unsigned INT_64BIT a = (unsigned INT_64BIT)(ULONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      585:        unsigned INT_64BIT quot, rem;
                    586:        
                    587:        if (extra & 0x400) {
                    588:            a &= 0xffffffffLL;
1.1.1.2 ! root      589:            a |= (unsigned INT_64BIT)m68k_dreg(regs, extra & 7) << 32;
1.1       root      590:        }
                    591:        rem = a % (unsigned INT_64BIT)src;
                    592:        quot = a / (unsigned INT_64BIT)src;
                    593:        if (quot > 0xffffffffLL) {
                    594:            VFLG = NFLG = 1;
                    595:            CFLG = 0;
                    596:        }
                    597:        else {
                    598:            VFLG = CFLG = 0;
                    599:            ZFLG = ((LONG)quot) == 0;
                    600:            NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root      601:            m68k_dreg(regs, extra & 7) = rem;
        !           602:            m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1       root      603:        }
                    604:     }
                    605: #else
                    606:     if (src == 0) {
                    607:        Exception(5,oldpc-2);
                    608:        return;
                    609:     }
                    610:     if (extra & 0x800) {
                    611:        /* signed variant */
1.1.1.2 ! root      612:        LONG lo = (LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      613:        LONG hi = lo < 0 ? -1 : 0;
                    614:        LONG save_high;
                    615:        ULONG quot, rem;
                    616:        ULONG sign;
                    617:        
                    618:        if (extra & 0x400) {
1.1.1.2 ! root      619:            hi = (LONG)m68k_dreg(regs, extra & 7);
1.1       root      620:        }
                    621:        save_high = hi;
                    622:        sign = (hi ^ src);
                    623:        if (hi < 0) {
                    624:                hi = ~hi;
                    625:                lo = -lo;
                    626:                if (lo == 0) hi++;
                    627:        }
                    628:        if ((LONG)src < 0) src = -src;
                    629:        if (div_unsigned(hi, lo, src, &quot, &rem) ||
                    630:            (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
                    631:            VFLG = NFLG = 1;
                    632:            CFLG = 0;
                    633:        }
                    634:        else {
                    635:            if (sign & 0x80000000) quot = -quot;
                    636:            if (((LONG)rem < 0) != (save_high < 0)) rem = -rem;
                    637:            VFLG = CFLG = 0;
                    638:            ZFLG = ((LONG)quot) == 0;
                    639:            NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root      640:            m68k_dreg(regs, extra & 7) = rem;
        !           641:            m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1       root      642:        }
                    643:     } else {
                    644:        /* unsigned */
1.1.1.2 ! root      645:        ULONG lo = (ULONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      646:        ULONG hi = 0;
                    647:        ULONG quot, rem;
                    648:        
                    649:        if (extra & 0x400) {
1.1.1.2 ! root      650:            hi = (ULONG)m68k_dreg(regs, extra & 7);
1.1       root      651:        }
                    652:        if (div_unsigned(hi, lo, src, &quot, &rem)) {
                    653:            VFLG = NFLG = 1;
                    654:            CFLG = 0;
                    655:        }
                    656:        else {
                    657:            VFLG = CFLG = 0;
                    658:            ZFLG = ((LONG)quot) == 0;
                    659:            NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root      660:            m68k_dreg(regs, extra & 7) = rem;
        !           661:            m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1       root      662:        }
                    663:     }
                    664: #endif
                    665: }
                    666: 
                    667: static __inline__ void
                    668: mul_unsigned(ULONG src1, ULONG src2, ULONG *dst_hi, ULONG *dst_lo)
                    669: {
                    670:         ULONG r0 = (src1 & 0xffff) * (src2 & 0xffff);
                    671:         ULONG r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
                    672:         ULONG r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
                    673:         ULONG r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
                    674:        ULONG lo;
                    675: 
1.1.1.2 ! root      676:         lo = r0 + ((r1 << 16) & 0xffff0000ul);
1.1       root      677:         if (lo < r0) r3++;
                    678:         r0 = lo;
1.1.1.2 ! root      679:         lo = r0 + ((r2 << 16) & 0xffff0000ul);
1.1       root      680:         if (lo < r0) r3++;
                    681:         r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
                    682:        *dst_lo = lo;
                    683:        *dst_hi = r3;
                    684: }
                    685: 
                    686: void m68k_mull (ULONG opcode, ULONG src, UWORD extra)
                    687: {
                    688: #if defined(INT_64BIT)
                    689:     if (extra & 0x800) {
                    690:        /* signed variant */
1.1.1.2 ! root      691:        INT_64BIT a = (INT_64BIT)(LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      692: 
                    693:        a *= (INT_64BIT)(LONG)src;
                    694:        VFLG = CFLG = 0;
                    695:        ZFLG = a == 0;
                    696:        NFLG = a < 0;
                    697:        if (extra & 0x400)
1.1.1.2 ! root      698:            m68k_dreg(regs, extra & 7) = a >> 32;
        !           699:        else if ((a & 0xffffffff80000000uLL) != 0 &&
        !           700:                 (a & 0xffffffff80000000uLL) != 0xffffffff80000000uLL) {
1.1       root      701:            VFLG = 1;
                    702:        }
1.1.1.2 ! root      703:        m68k_dreg(regs, (extra >> 12) & 7) = (ULONG)a;
1.1       root      704:     } else {
                    705:        /* unsigned */
1.1.1.2 ! root      706:        unsigned INT_64BIT a = (unsigned INT_64BIT)(ULONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      707:        
                    708:        a *= (unsigned INT_64BIT)src;
                    709:        VFLG = CFLG = 0;
                    710:        ZFLG = a == 0;
                    711:        NFLG = ((INT_64BIT)a) < 0;
                    712:        if (extra & 0x400)
1.1.1.2 ! root      713:            m68k_dreg(regs, extra & 7) = a >> 32;
        !           714:        else if ((a & 0xffffffff00000000uLL) != 0) {
1.1       root      715:            VFLG = 1;
                    716:        }
1.1.1.2 ! root      717:        m68k_dreg(regs, (extra >> 12) & 7) = (ULONG)a;
1.1       root      718:     }
                    719: #else
                    720:     if (extra & 0x800) {
                    721:        /* signed variant */
                    722:        LONG src1,src2;
                    723:        ULONG dst_lo,dst_hi;
                    724:        ULONG sign;
                    725: 
                    726:        src1 = (LONG)src;
1.1.1.2 ! root      727:        src2 = (LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1       root      728:        sign = (src1 ^ src2);
                    729:        if (src1 < 0) src1 = -src1;
                    730:        if (src2 < 0) src2 = -src2;
                    731:        mul_unsigned((ULONG)src1,(ULONG)src2,&dst_hi,&dst_lo);
                    732:        if (sign & 0x80000000) {
                    733:                dst_hi = ~dst_hi;
                    734:                dst_lo = -dst_lo;
                    735:                if (dst_lo == 0) dst_hi++;
                    736:        }
                    737:        VFLG = CFLG = 0;
                    738:        ZFLG = dst_hi == 0 && dst_lo == 0;
                    739:        NFLG = ((LONG)dst_hi) < 0;
                    740:        if (extra & 0x400)
1.1.1.2 ! root      741:            m68k_dreg(regs, extra & 7) = dst_hi;
1.1       root      742:        else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) &&
                    743:                 ((dst_hi & 0xffffffff) != 0xffffffff ||
                    744:                  (dst_lo & 0x80000000) != 0x80000000)) {
                    745:            VFLG = 1;
                    746:        }
1.1.1.2 ! root      747:        m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1.1       root      748:     } else {
                    749:        /* unsigned */
                    750:        ULONG dst_lo,dst_hi;
                    751: 
1.1.1.2 ! root      752:        mul_unsigned(src,(ULONG)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
1.1       root      753:        
                    754:        VFLG = CFLG = 0;
                    755:        ZFLG = dst_hi == 0 && dst_lo == 0;
                    756:        NFLG = ((LONG)dst_hi) < 0;
                    757:        if (extra & 0x400)
1.1.1.2 ! root      758:            m68k_dreg(regs, extra & 7) = dst_hi;
1.1       root      759:        else if (dst_hi != 0) {
                    760:            VFLG = 1;
                    761:        }
1.1.1.2 ! root      762:        m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1.1       root      763:     }
                    764: #endif
                    765: }
                    766: static char* ccnames[] =
                    767: { "T ","F ","HI","LS","CC","CS","NE","EQ",
                    768:   "VC","VS","PL","MI","GE","LT","GT","LE" };
                    769: 
                    770: void m68k_reset(void)
                    771: {
1.1.1.2 ! root      772:     m68k_areg(regs, 7) = get_long(0x00f80000);
1.1       root      773:     m68k_setpc(get_long(0x00f80004));
1.1.1.2 ! root      774:     regs.kick_mask = 0xF80000;
1.1       root      775:     regs.s = 1;
                    776:     regs.m = 0;
                    777:     regs.stopped = 0;
                    778:     regs.t1 = 0;
                    779:     regs.t0 = 0;
                    780:     ZFLG = CFLG = NFLG = VFLG = 0;
                    781:     regs.spcflags = 0;
                    782:     regs.intmask = 7;
                    783:     regs.vbr = regs.sfc = regs.dfc = 0;
                    784:     regs.fpcr = regs.fpsr = regs.fpiar = 0;
                    785:     customreset();
                    786: }
                    787: 
1.1.1.2 ! root      788: void REGPARAM2 op_illg(ULONG opcode)
1.1       root      789: {
1.1.1.2 ! root      790:     compiler_flush_jsr_stack();
1.1       root      791:     if (opcode == 0x4E7B && get_long(0x10) == 0 
                    792:        && (m68k_getpc() & 0xF80000) == 0xF80000) 
                    793:     {
                    794:        fprintf(stderr, "Your Kickstart requires a 68020 CPU. Giving up.\n");
                    795:        broken_in = 1; 
                    796:        regs.spcflags |= SPCFLAG_BRK;
                    797:        quit_program = 1;
                    798:     }
1.1.1.2 ! root      799:     if (opcode == 0xFF0D) {
        !           800:        if ((m68k_getpc() & 0xF80000) == 0xF80000) {
        !           801:            /* This is from the dummy Kickstart replacement */
        !           802:            ersatz_perform (nextiword ());
        !           803:            return;
        !           804:        } else if ((m68k_getpc() & 0xF80000) == 0xF00000) {
        !           805:            /* User-mode STOP replacement */
        !           806:            m68k_setstopped(1);
        !           807:            return;
        !           808:        }
1.1       root      809:     }
                    810: #ifdef USE_POINTER
                    811:     regs.pc_p -= 2;
                    812: #else
                    813:     regs.pc -= 2;
                    814: #endif
                    815:     if ((opcode & 0xF000) == 0xF000) {
                    816:        Exception(0xB,0);
                    817:        return;
                    818:     }
                    819:     if ((opcode & 0xF000) == 0xA000) {
                    820:        Exception(0xA,0);
                    821:        return;
                    822:     }
                    823:     fprintf(stderr, "Illegal instruction: %04x at %08lx\n", opcode, m68k_getpc());
                    824:     Exception(4,0);
                    825: }
                    826: 
                    827: void mmu_op(ULONG opcode, UWORD extra)
                    828: {
                    829:     if ((extra & 0xB000) == 0) { /* PMOVE instruction */
                    830: 
                    831:     } else if ((extra & 0xF000) == 0x2000) { /* PLOAD instruction */
                    832:     } else if ((extra & 0xF000) == 0x8000) { /* PTEST instruction */
                    833:     } else
                    834:        op_illg(opcode);
                    835: }
                    836: 
                    837: static int n_insns=0, n_spcinsns=0;
                    838: 
                    839: static CPTR last_trace_ad = 0;
                    840: 
                    841: static __inline__ void do_trace(void)
                    842: {
                    843:     if (regs.spcflags & SPCFLAG_TRACE) {               /* 6 */
                    844:        if (regs.t0) {
                    845:            UWORD opcode;
                    846:            /* should also include TRAP, CHK, SR modification FPcc */
                    847:            /* probably never used so why bother */
                    848:            /* We can afford this to be inefficient... */
                    849:            m68k_setpc(m68k_getpc());
                    850:            opcode = get_word(regs.pc);
                    851:            if (opcode == 0x4e72                /* RTE */
                    852:                || opcode == 0x4e74             /* RTD */
                    853:                || opcode == 0x4e75             /* RTS */
                    854:                || opcode == 0x4e77             /* RTR */
                    855:                || opcode == 0x4e76             /* TRAPV */
                    856:                || (opcode & 0xffc0) == 0x4e80  /* JSR */
                    857:                || (opcode & 0xffc0) == 0x4ec0  /* JMP */
                    858:                || (opcode & 0xff00) == 0x6100  /* BSR */
                    859:                || ((opcode & 0xf000) == 0x6000 /* Bcc */
                    860:                    && cctrue((opcode >> 8) & 0xf)) 
                    861:                || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
                    862:                    && !cctrue((opcode >> 8) & 0xf) 
1.1.1.2 ! root      863:                    && (WORD)m68k_dreg(regs, opcode & 7) != 0)) 
1.1       root      864:            {
                    865:                last_trace_ad = m68k_getpc();
                    866:                regs.spcflags &= ~SPCFLAG_TRACE;
                    867:                regs.spcflags |= SPCFLAG_DOTRACE;
                    868:            }
                    869:        } else if (regs.t1) {
                    870:            last_trace_ad = m68k_getpc();
                    871:            regs.spcflags &= ~SPCFLAG_TRACE;
                    872:            regs.spcflags |= SPCFLAG_DOTRACE;
                    873:        }
                    874:     }
                    875: }
                    876: 
1.1.1.2 ! root      877: static void m68k_run_1(void)
1.1       root      878: {
                    879:     regs.spcflags &= ~(SPCFLAG_EMULTRAP);
                    880:     for(;;) {
                    881: 
                    882:        /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
                    883: /*     regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
                    884: #if COUNT_INSTRS
                    885:        instrcount[opcode]++;
                    886: #endif
                    887: #if defined(X86_ASSEMBLY)
1.1.1.2 ! root      888:        {
        !           889:            ULONG opcode = nextiword();
        !           890:            __asm__ __volatile__("\tcall *%%ebx"
        !           891:                                 : : "b" (cpufunctbl[opcode]), "a" (opcode)
        !           892:                                 : "%eax", "%ebx", "%edx", "%ecx", 
        !           893:                                 "%esi", "%edi", "%ebp", "memory", "cc");
        !           894:        }
1.1       root      895: #else
                    896:        {
1.1.1.2 ! root      897:            ULONG opcode = nextiword();
1.1       root      898:            (*cpufunctbl[opcode])(opcode);
                    899:        }
                    900: #endif
                    901: #ifndef NO_EXCEPTION_3
                    902:        if (buserr) {
                    903:            Exception(3,0);
                    904:            buserr = 0;
                    905:        }
                    906: #endif
                    907:        if (regs.spcflags & SPCFLAG_EMULTRAP)
                    908:            return;
                    909:        /*n_insns++;*/
                    910:        do_cycles();    
                    911:        if (regs.spcflags) {
                    912:            /*n_spcinsns++;*/
1.1.1.2 ! root      913:            while (regs.spcflags & SPCFLAG_BLTNASTY) {
        !           914:                do_cycles();
        !           915:                if (regs.spcflags & SPCFLAG_DISK)
        !           916:                    do_disk();
        !           917:            }
        !           918:            run_compiled_code();
        !           919:            if (regs.spcflags & SPCFLAG_DOTRACE) {
        !           920:                Exception(9,last_trace_ad);
        !           921:            }
        !           922:            while (regs.spcflags & SPCFLAG_STOP) {
        !           923:                do_cycles();
        !           924:                if (regs.spcflags & SPCFLAG_DISK)
        !           925:                    do_disk();
        !           926:                if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT | SPCFLAG_TIMER)){
        !           927:                    int intr = intlev();
        !           928:                    regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT);
        !           929:                    if (intr != -1 && intr > regs.intmask) {
        !           930:                        Interrupt(intr);
        !           931:                        regs.stopped = 0;
        !           932:                        regs.spcflags &= ~SPCFLAG_STOP;
        !           933:                    }       
        !           934:                }               
        !           935:            }
        !           936:            do_trace();
        !           937: #ifdef WANT_SLOW_MULTIPLY
        !           938:            /* Kludge for Hardwired demo. The guys who wrote it should be
        !           939:             * mutilated. */
        !           940:            if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
        !           941:                do_cycles (); do_cycles (); do_cycles (); do_cycles ();
        !           942:                regs.spcflags &= ~SPCFLAG_EXTRA_CYCLES;
        !           943:            }
        !           944: #endif
        !           945:            if (regs.spcflags & SPCFLAG_DISK)
        !           946:                do_disk();
        !           947:            
        !           948:            if (regs.spcflags & (SPCFLAG_DOINT|SPCFLAG_TIMER)) {
        !           949:                int intr = intlev();
        !           950:                regs.spcflags &= ~SPCFLAG_DOINT;
        !           951:                if (intr != -1 && intr > regs.intmask) {
        !           952:                    Interrupt(intr);
        !           953:                    regs.stopped = 0;
        !           954:                }           
        !           955:            }
        !           956:            if (regs.spcflags & SPCFLAG_INT) {
        !           957:                regs.spcflags &= ~SPCFLAG_INT;
        !           958:                regs.spcflags |= SPCFLAG_DOINT;
        !           959:            }
        !           960:            if (regs.spcflags & (SPCFLAG_BRK|SPCFLAG_MODE_CHANGE)) {
        !           961:                regs.spcflags &= ~(SPCFLAG_BRK|SPCFLAG_MODE_CHANGE);
        !           962:                return;
        !           963:            }
        !           964:        }
        !           965:     }
        !           966: }
        !           967: 
        !           968: #if USER_PROGRAMS_BEHAVE > 0
        !           969: static void m68k_run_2(void)
        !           970: {
        !           971:     regs.spcflags &= ~(SPCFLAG_EMULTRAP);
        !           972:     for(;;) {
        !           973: 
        !           974:        /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
        !           975: /*     regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
        !           976: #if COUNT_INSTRS
        !           977:        instrcount[opcode]++;
        !           978: #endif
        !           979: #if defined(X86_ASSEMBLY)
        !           980:        {
        !           981:            ULONG opcode = nextiword();
        !           982:            __asm__ __volatile__("\tcall *%%ebx"
        !           983:                                 : : "b" (cpufunctbl_behaved[opcode]), "a" (opcode)
        !           984:                                 : "%eax", "%ebx", "%edx", "%ecx", 
        !           985:                                 "%esi", "%edi", "%ebp", "memory", "cc");
        !           986:        }
        !           987: #else
        !           988:        {
        !           989:            ULONG opcode = nextiword();
        !           990:            (*cpufunctbl_behaved[opcode])(opcode);
        !           991:        }
        !           992: #endif
        !           993: #ifndef NO_EXCEPTION_3
        !           994:        if (buserr) {
        !           995:            Exception(3,0);
        !           996:            buserr = 0;
        !           997:        }
        !           998: #endif
        !           999:        if (regs.spcflags & SPCFLAG_EMULTRAP)
        !          1000:            return;
        !          1001:        /*n_insns++;*/
        !          1002:        do_cycles();    
        !          1003:        if (regs.spcflags) {
        !          1004:            /*n_spcinsns++;*/
        !          1005:            while (regs.spcflags & SPCFLAG_BLTNASTY) {
1.1       root     1006:                do_cycles();
1.1.1.2 ! root     1007:                if (regs.spcflags & SPCFLAG_DISK)
        !          1008:                    do_disk();
1.1       root     1009:            }
                   1010:            run_compiled_code();
1.1.1.2 ! root     1011:            if (regs.spcflags & SPCFLAG_DOTRACE) {
1.1       root     1012:                Exception(9,last_trace_ad);
                   1013:            }
1.1.1.2 ! root     1014:            while (regs.spcflags & SPCFLAG_STOP) {
1.1       root     1015:                do_cycles();
1.1.1.2 ! root     1016:                if (regs.spcflags & SPCFLAG_DISK)
        !          1017:                    do_disk();
        !          1018:                if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT | SPCFLAG_TIMER)){
1.1       root     1019:                    int intr = intlev();
                   1020:                    regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT);
                   1021:                    if (intr != -1 && intr > regs.intmask) {
                   1022:                        Interrupt(intr);
                   1023:                        regs.stopped = 0;
                   1024:                        regs.spcflags &= ~SPCFLAG_STOP;
                   1025:                    }       
                   1026:                }               
                   1027:            }
                   1028:            do_trace();
                   1029: #ifdef WANT_SLOW_MULTIPLY
                   1030:            /* Kludge for Hardwired demo. The guys who wrote it should be
                   1031:             * mutilated. */
1.1.1.2 ! root     1032:            if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
1.1       root     1033:                do_cycles (); do_cycles (); do_cycles (); do_cycles ();
                   1034:                regs.spcflags &= ~SPCFLAG_EXTRA_CYCLES;
                   1035:            }
                   1036: #endif
1.1.1.2 ! root     1037:            if (regs.spcflags & SPCFLAG_DISK)
        !          1038:                do_disk();
1.1       root     1039:            
1.1.1.2 ! root     1040:            if (regs.spcflags & (SPCFLAG_DOINT|SPCFLAG_TIMER)) {
1.1       root     1041:                int intr = intlev();
                   1042:                regs.spcflags &= ~SPCFLAG_DOINT;
                   1043:                if (intr != -1 && intr > regs.intmask) {
                   1044:                    Interrupt(intr);
                   1045:                    regs.stopped = 0;
                   1046:                }           
                   1047:            }
1.1.1.2 ! root     1048:            if (regs.spcflags & SPCFLAG_INT) {
1.1       root     1049:                regs.spcflags &= ~SPCFLAG_INT;
                   1050:                regs.spcflags |= SPCFLAG_DOINT;
                   1051:            }
1.1.1.2 ! root     1052:            if (regs.spcflags & (SPCFLAG_BRK|SPCFLAG_MODE_CHANGE)) {
        !          1053:                regs.spcflags &= ~(SPCFLAG_BRK|SPCFLAG_MODE_CHANGE);
1.1       root     1054:                return;
                   1055:            }
                   1056:        }
                   1057:     }
                   1058: }
1.1.1.2 ! root     1059: #endif
1.1       root     1060: 
                   1061: #ifdef X86_ASSEMBLY
1.1.1.2 ! root     1062: static __inline__ void m68k_run1(void)
1.1       root     1063: {
                   1064:     /* Work around compiler bug: GCC doesn't push %ebp in m68k_run_1. */
                   1065:     __asm__ __volatile__ ("pushl %%ebp\n\tcall *%%eax\n\tpopl %%ebp" : : "a" (m68k_run_1) : "%eax", "%edx", "%ecx", "memory", "cc");
                   1066: }
1.1.1.2 ! root     1067: #if USER_PROGRAMS_BEHAVE > 0
        !          1068: static __inline__ void m68k_run2(void)
1.1       root     1069: {
1.1.1.2 ! root     1070:     /* Work around compiler bug: GCC doesn't push %ebp in m68k_run_1. */
        !          1071:     __asm__ __volatile__ ("pushl %%ebp\n\tcall *%%eax\n\tpopl %%ebp" : : "a" (m68k_run_2) : "%eax", "%edx", "%ecx", "memory", "cc");
1.1       root     1072: }
                   1073: #endif
1.1.1.2 ! root     1074: #else
        !          1075: #define m68k_run1 m68k_run_1
        !          1076: #define m68k_run2 m68k_run_2
        !          1077: #endif
        !          1078: 
        !          1079: int may_run_compiled;
1.1       root     1080: 
                   1081: void m68k_go(int may_quit)
                   1082: {
1.1.1.2 ! root     1083:     int old_mrc = may_run_compiled;
        !          1084:     
        !          1085:     may_run_compiled = may_quit;
1.1       root     1086:     for(;;) {
                   1087:        if (may_quit && quit_program)
                   1088:            return;
                   1089:        if (debugging)
                   1090:            debug();
1.1.1.2 ! root     1091: #if USER_PROGRAMS_BEHAVE > 0
        !          1092:        if ((regs.kick_mask & 0xF00000) != 0xF00000)
        !          1093:            m68k_run2();
        !          1094:        else
        !          1095: #endif
        !          1096:            m68k_run1();
        !          1097:        
1.1       root     1098:        /* 
                   1099:         * We make sure in the above functions that this is never
                   1100:         * set together with SPCFLAG_INT and similar flags
                   1101:         */
                   1102:        if (regs.spcflags & SPCFLAG_EMULTRAP) {
                   1103:            regs.spcflags &= ~SPCFLAG_EMULTRAP;
                   1104:            if (lasttrap == 0)
                   1105:                break;
                   1106:            do_emultrap(lasttrap);
                   1107:        }
                   1108:     }
1.1.1.2 ! root     1109:     may_run_compiled = old_mrc;
1.1       root     1110: }
                   1111: 
                   1112: void m68k_disasm(CPTR addr, CPTR *nextpc, int cnt)
                   1113: {
                   1114:     CPTR pc = m68k_getpc();
                   1115:     CPTR newpc = 0;
                   1116:     m68k_setpc(addr);
                   1117:     for (;cnt--;){
                   1118:        char instrname[20],*ccpt;
                   1119:        int opwords;
                   1120:        ULONG opcode;
                   1121:        struct mnemolookup *lookup;
                   1122:        struct instr *dp;
                   1123:        printf("%08lx: ", m68k_getpc());
                   1124:        for(opwords = 0; opwords < 5; opwords++){
                   1125:            printf("%04x ", get_word(m68k_getpc() + opwords*2));
                   1126:        }
                   1127:        
                   1128:        opcode = nextiword();
                   1129:        if (cpufunctbl[opcode] == op_illg) {
                   1130:            opcode = 0x4AFC;
                   1131:        }
                   1132:        dp = table68k + opcode;
                   1133:        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
                   1134:            ;
                   1135:        
                   1136:        strcpy(instrname,lookup->name);
                   1137:        ccpt = strstr(instrname,"cc");
                   1138:        if (ccpt != 0) {
                   1139:            strncpy(ccpt,ccnames[dp->cc],2);
                   1140:        }
                   1141:        printf("%s", instrname);
                   1142:        switch(dp->size){
                   1143:         case sz_byte: printf(".B "); break;
                   1144:         case sz_word: printf(".W "); break;
                   1145:         case sz_long: printf(".L "); break;
                   1146:         default: printf("   ");break;
                   1147:        }
                   1148: 
                   1149:        if (dp->suse) {
1.1.1.2 ! root     1150:            newpc = m68k_getpc() + ShowEA(dp->sreg, dp->smode, dp->size, 0);
1.1       root     1151:        }
                   1152:        if (dp->suse && dp->duse)
                   1153:            printf(",");
                   1154:        if (dp->duse) {
1.1.1.2 ! root     1155:            newpc = m68k_getpc() + ShowEA(dp->dreg, dp->dmode, dp->size, 0);
1.1       root     1156:        }
                   1157:        if (ccpt != 0) {
                   1158:            if (cctrue(dp->cc))
                   1159:                printf(" == %08lx (TRUE)",newpc);
                   1160:            else 
                   1161:                printf(" == %08lx (FALSE)",newpc);
                   1162:        } else if ((opcode & 0xff00) == 0x6100) /* BSR */
                   1163:            printf(" == %08lx",newpc);
                   1164:        printf("\n");
                   1165:     }
                   1166:     if (nextpc) *nextpc = m68k_getpc();
                   1167:     m68k_setpc(pc);
                   1168: }
                   1169: 
                   1170: void m68k_dumpstate(CPTR *nextpc)
                   1171: {
                   1172:     int i;
                   1173:     for(i = 0; i < 8; i++){
1.1.1.2 ! root     1174:        printf("D%d: %08lx ", i, m68k_dreg(regs, i));
1.1       root     1175:        if ((i & 3) == 3) printf("\n");
                   1176:     }
                   1177:     for(i = 0; i < 8; i++){
1.1.1.2 ! root     1178:        printf("A%d: %08lx ", i, m68k_areg(regs, i));
1.1       root     1179:        if ((i & 3) == 3) printf("\n");
                   1180:     }
1.1.1.2 ! root     1181:     if (regs.s == 0) regs.usp = m68k_areg(regs, 7);
        !          1182:     if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7);
        !          1183:     if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7);
1.1       root     1184:     printf("USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
                   1185:            regs.usp,regs.isp,regs.msp,regs.vbr);
                   1186:     printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
                   1187:            regs.t1, regs.t0, regs.s, regs.m,
                   1188:            XFLG, NFLG, ZFLG, VFLG, CFLG, regs.intmask);
                   1189:     for(i = 0; i < 8; i++){
                   1190:        printf("FP%d: %g ", i, regs.fp[i]);
                   1191:        if ((i & 3) == 3) printf("\n");
                   1192:     }
                   1193:     printf("N=%d Z=%d I=%d NAN=%d\n",
                   1194:                (regs.fpsr & 0x8000000) != 0,
                   1195:                (regs.fpsr & 0x4000000) != 0,
                   1196:                (regs.fpsr & 0x2000000) != 0,
                   1197:                (regs.fpsr & 0x1000000) != 0);
                   1198:     m68k_disasm(m68k_getpc(), nextpc, 1);
                   1199:     if (nextpc) printf("next PC: %08lx\n", *nextpc);
                   1200: }

unix.superglobalmegacorp.com

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