|
|
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 "nextMemory.h" ! 18: ! 19: #include "mmu_common.h" ! 20: ! 21: Uint32 BusErrorAddress; /* Stores the offending address for bus-/address errors */ ! 22: Uint32 BusErrorPC; /* Value of the PC when bus error occurs */ ! 23: bool bBusErrorReadWrite; /* 0 for write error, 1 for read error */ ! 24: int BusMode = BUS_MODE_CPU; /* Used to tell which part is owning the bus (cpu, blitter, ...) */ ! 25: ! 26: int LastOpcodeFamily = i_NOP; /* see the enum in readcpu.h i_XXX */ ! 27: int LastInstrCycles = 0; /* number of cycles for previous instr. (not rounded to 4) */ ! 28: int Pairing = 0; /* set to 1 if the latest 2 intr paired */ ! 29: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ]; ! 30: ! 31: ! 32: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */ ! 33: const char *OpcodeName[] = { "ILLG", ! 34: "OR","AND","EOR","ORSR","ANDSR","EORSR", ! 35: "SUB","SUBA","SUBX","SBCD", ! 36: "ADD","ADDA","ADDX","ABCD", ! 37: "NEG","NEGX","NBCD","CLR","NOT","TST", ! 38: "BTST","BCHG","BCLR","BSET", ! 39: "CMP","CMPM","CMPA", ! 40: "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR", ! 41: "SWAP","EXG","EXT","MVMEL","MVMLE", ! 42: "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD", ! 43: "LINK","UNLK", ! 44: "RTS","TRAPV","RTR", ! 45: "JSR","JMP","BSR","Bcc", ! 46: "LEA","PEA","DBcc","Scc", ! 47: "DIVU","DIVS","MULU","MULS", ! 48: "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR", ! 49: "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW", ! 50: "CHK","CHK2", ! 51: "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL", ! 52: "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS", ! 53: "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES", ! 54: "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE", ! 55: "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16", ! 56: "MMUOP" ! 57: }; ! 58: ! 59: ! 60: /*-----------------------------------------------------------------------*/ ! 61: /** ! 62: * Add pairing between all the bit shifting instructions and a given Opcode ! 63: */ ! 64: ! 65: static void M68000_InitPairing_BitShift ( int OpCode ) ! 66: { ! 67: PairingArray[ i_ASR ][ OpCode ] = 1; ! 68: PairingArray[ i_ASL ][ OpCode ] = 1; ! 69: PairingArray[ i_LSR ][ OpCode ] = 1; ! 70: PairingArray[ i_LSL ][ OpCode ] = 1; ! 71: PairingArray[ i_ROL ][ OpCode ] = 1; ! 72: PairingArray[ i_ROR ][ OpCode ] = 1; ! 73: PairingArray[ i_ROXR ][ OpCode ] = 1; ! 74: PairingArray[ i_ROXL ][ OpCode ] = 1; ! 75: } ! 76: ! 77: ! 78: /** ! 79: * Init the pairing matrix ! 80: * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1 ! 81: */ ! 82: static void M68000_InitPairing(void) ! 83: { ! 84: /* First, clear the matrix (pairing is false) */ ! 85: memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY); ! 86: ! 87: /* Set all valid pairing combinations to 1 */ ! 88: PairingArray[ i_EXG ][ i_DBcc ] = 1; ! 89: PairingArray[ i_EXG ][ i_MOVE ] = 1; ! 90: PairingArray[ i_EXG ][ i_MOVEA] = 1; ! 91: ! 92: PairingArray[ i_CMPA ][ i_Bcc ] = 1; ! 93: PairingArray[ i_CMP ][ i_Bcc ] = 1; ! 94: ! 95: M68000_InitPairing_BitShift ( i_DBcc ); ! 96: M68000_InitPairing_BitShift ( i_MOVE ); ! 97: M68000_InitPairing_BitShift ( i_MOVEA ); ! 98: M68000_InitPairing_BitShift ( i_LEA ); ! 99: M68000_InitPairing_BitShift ( i_JMP ); ! 100: ! 101: PairingArray[ i_MULU ][ i_MOVEA] = 1; ! 102: PairingArray[ i_MULS ][ i_MOVEA] = 1; ! 103: PairingArray[ i_MULU ][ i_MOVE ] = 1; ! 104: PairingArray[ i_MULS ][ i_MOVE ] = 1; ! 105: ! 106: PairingArray[ i_MULU ][ i_DIVU ] = 1; ! 107: PairingArray[ i_MULU ][ i_DIVS ] = 1; ! 108: PairingArray[ i_MULS ][ i_DIVU ] = 1; ! 109: PairingArray[ i_MULS ][ i_DIVS ] = 1; ! 110: ! 111: PairingArray[ i_BTST ][ i_Bcc ] = 1; ! 112: ! 113: M68000_InitPairing_BitShift ( i_ADD ); ! 114: M68000_InitPairing_BitShift ( i_SUB ); ! 115: M68000_InitPairing_BitShift ( i_OR ); ! 116: M68000_InitPairing_BitShift ( i_AND ); ! 117: M68000_InitPairing_BitShift ( i_EOR ); ! 118: M68000_InitPairing_BitShift ( i_NOT ); ! 119: M68000_InitPairing_BitShift ( i_CLR ); ! 120: M68000_InitPairing_BitShift ( i_NEG ); ! 121: M68000_InitPairing_BitShift ( i_ADDX ); ! 122: M68000_InitPairing_BitShift ( i_SUBX ); ! 123: M68000_InitPairing_BitShift ( i_ABCD ); ! 124: M68000_InitPairing_BitShift ( i_SBCD ); ! 125: ! 126: PairingArray[ i_ADD ][ i_MOVE ] = 1; /* when using xx(an,dn) addr mode */ ! 127: PairingArray[ i_SUB ][ i_MOVE ] = 1; ! 128: } ! 129: ! 130: ! 131: /** ! 132: * One-time CPU initialization. ! 133: */ ! 134: void M68000_Init(void) ! 135: { ! 136: /* Init UAE CPU core */ ! 137: Init680x0(); ! 138: ! 139: /* Init the pairing matrix */ ! 140: M68000_InitPairing(); ! 141: } ! 142: ! 143: static int pendingInterrupts = 0; ! 144: ! 145: /*-----------------------------------------------------------------------*/ ! 146: /** ! 147: * Reset CPU 68000 variables ! 148: */ ! 149: void M68000_Reset(bool bCold) { ! 150: pendingInterrupts = 0; ! 151: if (bCold) { ! 152: /* Clear registers, but we need to keep SPCFLAG_MODE_CHANGE and SPCFLAG_BRK unchanged */ ! 153: int spcFlags = regs.spcflags & (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK); ! 154: memset(®s, 0, sizeof(regs)); ! 155: regs.spcflags = spcFlags; ! 156: } ! 157: /* Now reset the WINUAE CPU core */ ! 158: m68k_reset(bCold); ! 159: BusMode = BUS_MODE_CPU; ! 160: } ! 161: ! 162: ! 163: /*-----------------------------------------------------------------------*/ ! 164: /** ! 165: * Stop 680x0 emulation ! 166: */ ! 167: void M68000_Stop(void) ! 168: { ! 169: M68000_SetSpecial(SPCFLAG_BRK); ! 170: } ! 171: ! 172: ! 173: /*-----------------------------------------------------------------------*/ ! 174: /** ! 175: * Start 680x0 emulation ! 176: */ ! 177: void M68000_Start(void) ! 178: { ! 179: m68k_go(true); ! 180: } ! 181: ! 182: ! 183: /*-----------------------------------------------------------------------*/ ! 184: /** ! 185: * Check whether CPU settings have been changed. ! 186: */ ! 187: void M68000_CheckCpuSettings(void) ! 188: { ! 189: if (ConfigureParams.System.nCpuFreq < 20) ! 190: { ! 191: ConfigureParams.System.nCpuFreq = 16; ! 192: } ! 193: else if (ConfigureParams.System.nCpuFreq < 24) ! 194: { ! 195: ConfigureParams.System.nCpuFreq = 20; ! 196: } ! 197: else if (ConfigureParams.System.nCpuFreq < 32) ! 198: { ! 199: ConfigureParams.System.nCpuFreq = 25; ! 200: } ! 201: else if (ConfigureParams.System.nCpuFreq < 40) ! 202: { ! 203: ConfigureParams.System.nCpuFreq = 33; ! 204: } else { ! 205: if (ConfigureParams.System.bTurbo) { ! 206: ConfigureParams.System.nCpuFreq = 40; ! 207: } else { ! 208: ConfigureParams.System.nCpuFreq = 33; ! 209: } ! 210: } ! 211: changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel; ! 212: changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu; ! 213: ! 214: switch (changed_prefs.cpu_level) { ! 215: case 0 : changed_prefs.cpu_model = 68000; break; ! 216: case 1 : changed_prefs.cpu_model = 68010; break; ! 217: case 2 : changed_prefs.cpu_model = 68020; break; ! 218: case 3 : changed_prefs.cpu_model = 68030; break; ! 219: case 4 : changed_prefs.cpu_model = 68040; break; ! 220: case 5 : changed_prefs.cpu_model = 68060; break; ! 221: default: fprintf (stderr, "Init680x0() : Error, cpu_level unknown\n"); ! 222: } ! 223: ! 224: changed_prefs.fpu_model = ConfigureParams.System.n_FPUType; ! 225: switch (changed_prefs.fpu_model) { ! 226: case 68881: changed_prefs.fpu_revision = 0x1f; break; ! 227: case 68882: changed_prefs.fpu_revision = 0x20; break; ! 228: case 68040: ! 229: if (ConfigureParams.System.bTurbo) ! 230: changed_prefs.fpu_revision = 0x41; ! 231: else ! 232: changed_prefs.fpu_revision = 0x40; ! 233: break; ! 234: default: fprintf (stderr, "Init680x0() : Error, fpu_model unknown\n"); ! 235: } ! 236: ! 237: changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU; ! 238: changed_prefs.mmu_model = ConfigureParams.System.bMMU?changed_prefs.cpu_model:0; ! 239: ! 240: if (table68k) ! 241: check_prefs_changed_cpu(); ! 242: } ! 243: ! 244: /*-----------------------------------------------------------------------*/ ! 245: /** ! 246: * BUSERROR - Access outside valid memory range. ! 247: * Use bRead = 0 for write errors and bRead = 1 for read errors! ! 248: */ ! 249: void M68000_BusError(Uint32 addr, bool bRead) ! 250: { ! 251: exception2 (addr, bRead, 0, regs.s ? 5 : 1); /* assumes data access, ! 252: size not set */ ! 253: } ! 254: #if 0 ! 255: void M68000_BusError(Uint32 addr, bool bRead) ! 256: { ! 257: /* FIXME: In prefetch mode, m68k_getpc() seems already to point to the next instruction */ ! 258: // BusErrorPC = M68000_GetPC(); /* [NP] We set BusErrorPC in m68k_run_1 */ ! 259: ! 260: ! 261: if ((regs.spcflags & SPCFLAG_BUSERROR) == 0) /* [NP] Check that the opcode has not already generated a read bus error */ ! 262: { ! 263: regs.mmu_fault_addr = addr; ! 264: BusErrorAddress = addr; /* Store for exception frame */ ! 265: bBusErrorReadWrite = bRead; ! 266: ! 267: if (currprefs.mmu_model) { ! 268: /* This is a hack for the special status word, this needs to be corrected later */ ! 269: if (ConfigureParams.System.nCpuLevel==3) { /* CPU 68030 */ ! 270: int fc = 5; /* hack */ ! 271: regs.mmu_ssw = (fc&1) ? MMU030_SSW_DF : (MMU030_SSW_FB|MMU030_SSW_RB); ! 272: regs.mmu_ssw |= bRead ? MMU030_SSW_RW : 0; ! 273: regs.mmu_ssw |= fc&MMU030_SSW_FC_MASK; ! 274: /*switch (size) { ! 275: case 4: regs.mmu_ssw |= MMU030_SSW_SIZE_L; break; ! 276: case 2: regs.mmu_ssw |= MMU030_SSW_SIZE_W; break; ! 277: case 1: regs.mmu_ssw |= MMU030_SSW_SIZE_B; break; ! 278: default: break; ! 279: }*/ ! 280: printf("Bus Error: Warning! Using hacked SSW (%04X)!\n", regs.mmu_ssw); ! 281: } ! 282: THROW(2); ! 283: return; ! 284: } ! 285: ! 286: M68000_SetSpecial(SPCFLAG_BUSERROR); /* The exception will be done in newcpu.c */ ! 287: } ! 288: } ! 289: #endif ! 290: ! 291: /*-----------------------------------------------------------------------*/ ! 292: /** ! 293: * Exception handler ! 294: */ ! 295: void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource) ! 296: { ! 297: int exceptionNr = ExceptionVector/4; ! 298: ! 299: if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC) ! 300: && (exceptionNr>24 && exceptionNr<32)) /* 68k autovector interrupt? */ ! 301: { ! 302: /* Handle autovector interrupts the UAE's way ! 303: * (see intlev() and do_specialties() in UAE CPU core) */ ! 304: int intnr = exceptionNr - 24; ! 305: pendingInterrupts |= (1 << intnr); ! 306: M68000_SetSpecial(SPCFLAG_INT); ! 307: } ! 308: ! 309: else /* direct CPU exceptions */ ! 310: { ! 311: Uint16 SR; ! 312: ! 313: /* Was the CPU stopped, i.e. by a STOP instruction? */ ! 314: if (regs.spcflags & SPCFLAG_STOP) ! 315: { ! 316: regs.stopped = 0; ! 317: M68000_UnsetSpecial(SPCFLAG_STOP); /* All is go,go,go! */ ! 318: } ! 319: ! 320: /* 68k exceptions are handled by Exception() of the UAE CPU core */ ! 321: Exception(exceptionNr/*, m68k_getpc(), ExceptionSource*/); ! 322: ! 323: SR = M68000_GetSR(); ! 324: ! 325: /* Set Status Register so interrupt can ONLY be stopped by another interrupt ! 326: * of higher priority! */ ! 327: ! 328: SR = (SR&SR_CLEAR_IPL)|0x0600; /* DSP, level 6 */ ! 329: ! 330: M68000_SetSR(SR); ! 331: } ! 332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.