|
|
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(®s, 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(®s.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(®s.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(®s); ! 242: #endif ! 243: if (regs.s) ! 244: { ! 245: MemorySnapShot_Store(®s.usp, sizeof(regs.usp)); /* USP */ ! 246: MemorySnapShot_Store(®s.regs[15], sizeof(regs.regs[15])); /* ISP */ ! 247: } ! 248: else ! 249: { ! 250: MemorySnapShot_Store(®s.regs[15], sizeof(regs.regs[15])); /* USP */ ! 251: MemorySnapShot_Store(®s.isp, sizeof(regs.isp)); /* ISP */ ! 252: } ! 253: MemorySnapShot_Store(®s.sr, sizeof(regs.sr)); /* SR/CCR */ ! 254: } ! 255: else ! 256: { ! 257: MemorySnapShot_Store(®s.usp, sizeof(regs.usp)); ! 258: MemorySnapShot_Store(®s.isp, sizeof(regs.isp)); ! 259: MemorySnapShot_Store(®s.sr, sizeof(regs.sr)); ! 260: } ! 261: MemorySnapShot_Store(®s.stopped, sizeof(regs.stopped)); ! 262: MemorySnapShot_Store(®s.dfc, sizeof(regs.dfc)); /* DFC */ ! 263: MemorySnapShot_Store(®s.sfc, sizeof(regs.sfc)); /* SFC */ ! 264: MemorySnapShot_Store(®s.vbr, sizeof(regs.vbr)); /* VBR */ ! 265: MemorySnapShot_Store(&caar, sizeof(caar)); /* CAAR */ ! 266: MemorySnapShot_Store(&cacr, sizeof(cacr)); /* CACR */ ! 267: MemorySnapShot_Store(®s.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(®s); ! 283: /* set stack pointer */ ! 284: if (regs.s) ! 285: m68k_areg(®s, 7) = regs.isp; ! 286: else ! 287: m68k_areg(®s, 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, ®s, m68k_getpc(®s)); ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.