Annotation of previous/src/m68000.c, revision 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.