Annotation of previous/src/m68000.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   Hatari - m68000.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7: */
                      8: 
                      9: 
                     10: const char M68000_fileid[] = "Hatari m68000.c : " __DATE__ " " __TIME__;
                     11: 
                     12: #include "main.h"
                     13: #include "configuration.h"
                     14: #include "hatari-glue.h"
                     15: #include "cycInt.h"
                     16: #include "m68000.h"
                     17: #include "memorySnapShot.h"
                     18: #include "options.h"
                     19: #include "savestate.h"
                     20: #include "nextMemory.h"
                     21: 
                     22: 
                     23: Uint32 BusErrorAddress;         /* Stores the offending address for bus-/address errors */
                     24: Uint32 BusErrorPC;              /* Value of the PC when bus error occurs */
                     25: bool bBusErrorReadWrite;        /* 0 for write error, 1 for read error */
                     26: int nCpuFreqShift;              /* Used to emulate higher CPU frequencies: 0=8MHz, 1=16MHz, 2=32Mhz */
                     27: int nWaitStateCycles;           /* Used to emulate the wait state cycles of certain IO registers */
                     28: int BusMode = BUS_MODE_CPU;    /* Used to tell which part is owning the bus (cpu, blitter, ...) */
                     29: 
                     30: int LastOpcodeFamily = i_NOP;  /* see the enum in readcpu.h i_XXX */
                     31: int LastInstrCycles = 0;       /* number of cycles for previous instr. (not rounded to 4) */
                     32: int Pairing = 0;               /* set to 1 if the latest 2 intr paired */
                     33: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
                     34: 
                     35: 
                     36: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */
                     37: const char *OpcodeName[] = { "ILLG",
                     38:        "OR","AND","EOR","ORSR","ANDSR","EORSR",
                     39:        "SUB","SUBA","SUBX","SBCD",
                     40:        "ADD","ADDA","ADDX","ABCD",
                     41:        "NEG","NEGX","NBCD","CLR","NOT","TST",
                     42:        "BTST","BCHG","BCLR","BSET",
                     43:        "CMP","CMPM","CMPA",
                     44:        "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR",
                     45:        "SWAP","EXG","EXT","MVMEL","MVMLE",
                     46:        "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD",
                     47:        "LINK","UNLK",
                     48:        "RTS","TRAPV","RTR",
                     49:        "JSR","JMP","BSR","Bcc",
                     50:        "LEA","PEA","DBcc","Scc",
                     51:        "DIVU","DIVS","MULU","MULS",
                     52:        "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR",
                     53:        "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW",
                     54:        "CHK","CHK2",
                     55:        "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL",
                     56:        "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS",
                     57:        "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES",
                     58:        "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE",
                     59:        "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16",
                     60:        "MMUOP"
                     61: };
                     62: 
                     63: 
                     64: /*-----------------------------------------------------------------------*/
                     65: /**
                     66:  * Add pairing between all the bit shifting instructions and a given Opcode
                     67:  */
                     68: 
                     69: static void M68000_InitPairing_BitShift ( int OpCode )
                     70: {
                     71:        PairingArray[  i_ASR ][ OpCode ] = 1; 
                     72:        PairingArray[  i_ASL ][ OpCode ] = 1; 
                     73:        PairingArray[  i_LSR ][ OpCode ] = 1; 
                     74:        PairingArray[  i_LSL ][ OpCode ] = 1; 
                     75:        PairingArray[  i_ROL ][ OpCode ] = 1; 
                     76:        PairingArray[  i_ROR ][ OpCode ] = 1; 
                     77:        PairingArray[ i_ROXR ][ OpCode ] = 1; 
                     78:        PairingArray[ i_ROXL ][ OpCode ] = 1; 
                     79: }
                     80: 
                     81: 
                     82: /**
                     83:  * Init the pairing matrix
                     84:  * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1
                     85:  */
                     86: static void M68000_InitPairing(void)
                     87: {
                     88:        /* First, clear the matrix (pairing is false) */
                     89:        memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY);
                     90: 
                     91:        /* Set all valid pairing combinations to 1 */
                     92:        PairingArray[  i_EXG ][ i_DBcc ] = 1;
                     93:        PairingArray[  i_EXG ][ i_MOVE ] = 1;
                     94:        PairingArray[  i_EXG ][ i_MOVEA] = 1;
                     95: 
                     96:        PairingArray[ i_CMPA ][  i_Bcc ] = 1;
                     97:        PairingArray[  i_CMP ][  i_Bcc ] = 1;
                     98: 
                     99:        M68000_InitPairing_BitShift ( i_DBcc );
                    100:        M68000_InitPairing_BitShift ( i_MOVE );
                    101:        M68000_InitPairing_BitShift ( i_MOVEA );
                    102:        M68000_InitPairing_BitShift ( i_LEA );
                    103: 
                    104:        PairingArray[ i_MULU ][ i_MOVEA] = 1; 
                    105:        PairingArray[ i_MULS ][ i_MOVEA] = 1; 
                    106:        PairingArray[ i_MULU ][ i_MOVE ] = 1; 
                    107:        PairingArray[ i_MULS ][ i_MOVE ] = 1; 
                    108: 
                    109:        PairingArray[ i_MULU ][ i_DIVU ] = 1;
                    110:        PairingArray[ i_MULU ][ i_DIVS ] = 1;
                    111:        PairingArray[ i_MULS ][ i_DIVU ] = 1;
                    112:        PairingArray[ i_MULS ][ i_DIVS ] = 1;
                    113: 
                    114:        PairingArray[ i_BTST ][  i_Bcc ] = 1;
                    115: 
                    116:        M68000_InitPairing_BitShift ( i_ADD );
                    117:        M68000_InitPairing_BitShift ( i_SUB );
                    118:        M68000_InitPairing_BitShift ( i_OR );
                    119:        M68000_InitPairing_BitShift ( i_AND );
                    120:        M68000_InitPairing_BitShift ( i_EOR );
                    121:        M68000_InitPairing_BitShift ( i_NOT );
                    122:        M68000_InitPairing_BitShift ( i_CLR );
                    123:        M68000_InitPairing_BitShift ( i_NEG );
                    124:        M68000_InitPairing_BitShift ( i_ADDX );
                    125:        M68000_InitPairing_BitShift ( i_SUBX );
                    126:        M68000_InitPairing_BitShift ( i_ABCD );
                    127:        M68000_InitPairing_BitShift ( i_SBCD );
                    128: 
                    129:        PairingArray[ i_ADD ][ i_MOVE ] = 1;            /* when using xx(an,dn) addr mode */
                    130:        PairingArray[ i_SUB ][ i_MOVE ] = 1;
                    131: }
                    132: 
                    133: 
                    134: /**
                    135:  * One-time CPU initialization.
                    136:  */
                    137: void M68000_Init(void)
                    138: {
                    139:        /* Init UAE CPU core */
                    140:        Init680x0();
                    141: 
                    142:        /* Init the pairing matrix */
                    143:        M68000_InitPairing();
                    144: }
                    145: 
                    146: 
                    147: /*-----------------------------------------------------------------------*/
                    148: /**
                    149:  * Reset CPU 68000 variables
                    150:  */
                    151: void M68000_Reset(bool bCold)
                    152: {
                    153:        /* Clear registers */
                    154:        if (bCold)
                    155:        {
                    156:                memset(&regs, 0, sizeof(regs));
                    157:        }
                    158: 
                    159:        /* Now directly reset the UAE CPU core: */
                    160:        m68k_reset();
                    161: 
                    162:        BusMode = BUS_MODE_CPU;
                    163: }
                    164: 
                    165: 
                    166: /*-----------------------------------------------------------------------*/
                    167: /**
                    168:  * Start 680x0 emulation
                    169:  */
                    170: void M68000_Start(void)
                    171: {
                    172:        /* Load initial memory snapshot */
                    173:        if (bLoadMemorySave)
                    174:        {
                    175:                MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, false);
                    176:        }
                    177:        else if (bLoadAutoSave)
                    178:        {
                    179:                MemorySnapShot_Restore(ConfigureParams.Memory.szAutoSaveFileName, false);
                    180:        }
                    181: 
                    182:        m68k_go(true);
                    183: }
                    184: 
                    185: 
                    186: /*-----------------------------------------------------------------------*/
                    187: /**
                    188:  * Check wether the CPU mode has been changed.
                    189:  */
                    190: void M68000_CheckCpuLevel(void)
                    191: {
                    192:        changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
                    193:        changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
                    194: #ifndef UAE_NEWCPU_H
                    195:        changed_prefs.cpu_cycle_exact = 0;  // TODO
                    196: #endif
                    197:        if (table68k)
                    198:                check_prefs_changed_cpu();
                    199: }
                    200: 
                    201: 
                    202: /*-----------------------------------------------------------------------*/
                    203: /**
                    204:  * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type)
                    205:  */
                    206: void M68000_MemorySnapShot_Capture(bool bSave)
                    207: {
                    208:        Uint32 savepc;
                    209: 
                    210:        /* For the UAE CPU core: */
                    211:        MemorySnapShot_Store(&currprefs.address_space_24,
                    212:                             sizeof(currprefs.address_space_24));
                    213:        MemorySnapShot_Store(&regs.regs[0], sizeof(regs.regs));       /* D0-D7 A0-A6 */
                    214: 
                    215:        if (bSave)
                    216:        {
                    217:                savepc = M68000_GetPC();
                    218:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    219:        }
                    220:        else
                    221:        {
                    222:                MemorySnapShot_Store(&savepc, sizeof(savepc));            /* PC */
                    223:                regs.pc = savepc;
                    224: #ifdef UAE_NEWCPU_H
                    225:                regs.prefetch_pc = regs.pc + 128;
                    226: #endif
                    227:        }
                    228: 
                    229: #ifdef UAE_NEWCPU_H
                    230:        MemorySnapShot_Store(&regs.prefetch, sizeof(regs.prefetch));  /* prefetch */
                    231: #else
                    232:        uae_u32 prefetch_dummy;
                    233:        MemorySnapShot_Store(&prefetch_dummy, sizeof(prefetch_dummy));
                    234: #endif
                    235: 
                    236:        if (bSave)
                    237:        {
                    238: #ifdef UAE_NEWCPU_H
                    239:                MakeSR();
                    240: #else
                    241:                MakeSR(&regs);
                    242: #endif
                    243:                if (regs.s)
                    244:                {
                    245:                        MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));    /* USP */
                    246:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* ISP */
                    247:                }
                    248:                else
                    249:                {
                    250:                        MemorySnapShot_Store(&regs.regs[15], sizeof(regs.regs[15]));  /* USP */
                    251:                        MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));    /* ISP */
                    252:                }
                    253:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));          /* SR/CCR */
                    254:        }
                    255:        else
                    256:        {
                    257:                MemorySnapShot_Store(&regs.usp, sizeof(regs.usp));
                    258:                MemorySnapShot_Store(&regs.isp, sizeof(regs.isp));
                    259:                MemorySnapShot_Store(&regs.sr, sizeof(regs.sr));
                    260:        }
                    261:        MemorySnapShot_Store(&regs.stopped, sizeof(regs.stopped));
                    262:        MemorySnapShot_Store(&regs.dfc, sizeof(regs.dfc));            /* DFC */
                    263:        MemorySnapShot_Store(&regs.sfc, sizeof(regs.sfc));            /* SFC */
                    264:        MemorySnapShot_Store(&regs.vbr, sizeof(regs.vbr));            /* VBR */
                    265:        MemorySnapShot_Store(&caar, sizeof(caar));                    /* CAAR */
                    266:        MemorySnapShot_Store(&cacr, sizeof(cacr));                    /* CACR */
                    267:        MemorySnapShot_Store(&regs.msp, sizeof(regs.msp));            /* MSP */
                    268: 
                    269:        if (!bSave)
                    270:        {
                    271:                M68000_SetPC(regs.pc);
                    272:                /* MakeFromSR() must not swap stack pointer */
                    273:                regs.s = (regs.sr >> 13) & 1;
                    274: #ifdef UAE_NEWCPU_H
                    275:                MakeFromSR();
                    276:                /* set stack pointer */
                    277:                if (regs.s)
                    278:                        m68k_areg(regs, 7) = regs.isp;
                    279:                else
                    280:                        m68k_areg(regs, 7) = regs.usp;
                    281: #else
                    282:                MakeFromSR(&regs);
                    283:                /* set stack pointer */
                    284:                if (regs.s)
                    285:                        m68k_areg(&regs, 7) = regs.isp;
                    286:                else
                    287:                        m68k_areg(&regs, 7) = regs.usp;
                    288: #endif
                    289:        }
                    290: 
                    291:        if (bSave)
                    292:                save_fpu();
                    293:        else
                    294:                restore_fpu();
                    295: }
                    296: 
                    297: 
                    298: /*-----------------------------------------------------------------------*/
                    299: /**
                    300:  * BUSERROR - Access outside valid memory range.
                    301:  * Use bReadWrite = 0 for write errors and bReadWrite = 1 for read errors!
                    302:  */
                    303: void M68000_BusError(Uint32 addr, bool bReadWrite)
                    304: {
                    305:        /* FIXME: In prefetch mode, m68k_getpc() seems already to point to the next instruction */
                    306:        // BusErrorPC = M68000_GetPC();         /* [NP] We set BusErrorPC in m68k_run_1 */
                    307: 
                    308:                fprintf(stderr, "M68000 Bus Error at address $%x.\n", addr);
                    309: 
                    310:        if ((regs.spcflags & SPCFLAG_BUSERROR) == 0)    /* [NP] Check that the opcode has not already generated a read bus error */
                    311:        {
                    312:                BusErrorAddress = addr;                         /* Store for exception frame */
                    313:                bBusErrorReadWrite = bReadWrite;
                    314:                M68000_SetSpecial(SPCFLAG_BUSERROR);            /* The exception will be done in newcpu.c */
                    315:        }
                    316: }
                    317: 
                    318: 
                    319: /*-----------------------------------------------------------------------*/
                    320: /**
                    321:  * Exception handler
                    322:  */
                    323: void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource)
                    324: {
                    325:        int exceptionNr = ExceptionVector/4;
                    326: 
                    327:        if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC)
                    328:                && (exceptionNr>24 && exceptionNr<32))  /* 68k autovector interrupt? */
                    329:        {
                    330:                /* Handle autovector interrupts the UAE's way
                    331:                 * (see intlev() and do_specialties() in UAE CPU core) */
                    332:                /* In our case, this part is only called for HBL and VBL interrupts */
                    333:                int intnr = exceptionNr - 24;
                    334:                pendingInterrupts |= (1 << intnr);
                    335:                M68000_SetSpecial(SPCFLAG_INT);
                    336:        }
                    337: 
                    338:        else                                                    /* MFP or direct CPU exceptions */
                    339:        {
                    340:                Uint16 SR;
                    341: 
                    342:                /* Was the CPU stopped, i.e. by a STOP instruction? */
                    343:                if (regs.spcflags & SPCFLAG_STOP)
                    344:                {
                    345:                        regs.stopped = 0;
                    346:                        M68000_UnsetSpecial(SPCFLAG_STOP);    /* All is go,go,go! */
                    347:                }
                    348: 
                    349:                /* 68k exceptions are handled by Exception() of the UAE CPU core */
                    350: #ifdef UAE_NEWCPU_H
                    351:                Exception(exceptionNr, m68k_getpc(), ExceptionSource);
                    352: #else
                    353:                Exception(exceptionNr, &regs, m68k_getpc(&regs));
                    354: #endif
                    355: 
                    356:                SR = M68000_GetSR();
                    357: 
                    358:                /* Set Status Register so interrupt can ONLY be stopped by another interrupt
                    359:                 * of higher priority! */
                    360:                SR = (SR&SR_CLEAR_IPL)|0x0600;     /* DSP, level 6 */
                    361: 
                    362:                M68000_SetSR(SR);
                    363:        }
                    364: }
                    365: 
                    366: 
                    367: /*-----------------------------------------------------------------------*/
                    368: /**
                    369:  * There seem to be wait states when a program accesses certain hardware
                    370:  * registers on the ST. Use this function to simulate these wait states.
                    371:  * [NP] with some instructions like CLR, we have a read then a write at the
                    372:  * same location, so we may have 2 wait states (read and write) to add
                    373:  * (nWaitStateCycles should be reset to 0 after the cycles were added).
                    374:  */
                    375: void M68000_WaitState(int nCycles)
                    376: {
                    377:        M68000_SetSpecial(SPCFLAG_EXTRA_CYCLES);
                    378: 
                    379:        nWaitStateCycles += nCycles;    /* add all the wait states for this instruction */
                    380: }

unix.superglobalmegacorp.com

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