|
|
1.1 ! root 1: /* ! 2: Hatari - m68000.h ! 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: /* 2007/11/10 [NP] Add pairing for lsr / dbcc (and all variants */ ! 9: /* working on register, not on memory). */ ! 10: /* 2008/01/07 [NP] Use PairingArray to store all valid pairing */ ! 11: /* combinations (in m68000.c) */ ! 12: /* 2010/04/05 [NP] Rework the pairing code to take BusCyclePenalty */ ! 13: /* into account when using d8(an,ix). */ ! 14: /* 2010/05/07 [NP] Add BusCyclePenalty to LastInstrCycles to detect*/ ! 15: /* a possible pairing between add.l (a5,d1.w),d0 */ ! 16: /* and move.b 7(a5,d1.w),d5. */ ! 17: ! 18: ! 19: #ifndef HATARI_M68000_H ! 20: #define HATARI_M68000_H ! 21: ! 22: #include "cycles.h" /* for nCyclesMainCounter */ ! 23: #include "sysdeps.h" ! 24: #include "memory.h" ! 25: #include "newcpu.h" /* for regs */ ! 26: #include "cycInt.h" ! 27: #include "log.h" ! 28: ! 29: ! 30: /* 68000 Register defines */ ! 31: enum { ! 32: REG_D0, /* D0.. */ ! 33: REG_D1, ! 34: REG_D2, ! 35: REG_D3, ! 36: REG_D4, ! 37: REG_D5, ! 38: REG_D6, ! 39: REG_D7, /* ..D7 */ ! 40: REG_A0, /* A0.. */ ! 41: REG_A1, ! 42: REG_A2, ! 43: REG_A3, ! 44: REG_A4, ! 45: REG_A5, ! 46: REG_A6, ! 47: REG_A7, /* ..A7 (also SP) */ ! 48: }; ! 49: ! 50: /* 68000 Condition code's */ ! 51: #define SR_AUX 0x0010 ! 52: #define SR_NEG 0x0008 ! 53: #define SR_ZERO 0x0004 ! 54: #define SR_OVERFLOW 0x0002 ! 55: #define SR_CARRY 0x0001 ! 56: ! 57: #define SR_CLEAR_AUX 0xffef ! 58: #define SR_CLEAR_NEG 0xfff7 ! 59: #define SR_CLEAR_ZERO 0xfffb ! 60: #define SR_CLEAR_OVERFLOW 0xfffd ! 61: #define SR_CLEAR_CARRY 0xfffe ! 62: ! 63: #define SR_CCODE_MASK (SR_AUX|SR_NEG|SR_ZERO|SR_OVERFLOW|SR_CARRY) ! 64: #define SR_MASK 0xFFE0 ! 65: ! 66: #define SR_TRACEMODE 0x8000 ! 67: #define SR_SUPERMODE 0x2000 ! 68: #define SR_IPL 0x0700 ! 69: ! 70: #define SR_CLEAR_IPL 0xf8ff ! 71: #define SR_CLEAR_TRACEMODE 0x7fff ! 72: #define SR_CLEAR_SUPERMODE 0xdfff ! 73: ! 74: /* Exception vectors */ ! 75: #define EXCEPTION_BUSERROR 0x00000008 ! 76: #define EXCEPTION_ADDRERROR 0x0000000c ! 77: #define EXCEPTION_ILLEGALINS 0x00000010 ! 78: #define EXCEPTION_DIVZERO 0x00000014 ! 79: #define EXCEPTION_CHK 0x00000018 ! 80: #define EXCEPTION_TRAPV 0x0000001c ! 81: #define EXCEPTION_TRACE 0x00000024 ! 82: #define EXCEPTION_LINE_A 0x00000028 ! 83: #define EXCEPTION_LINE_F 0x0000002c ! 84: #define EXCEPTION_HBLANK 0x00000068 ! 85: #define EXCEPTION_VBLANK 0x00000070 ! 86: #define EXCEPTION_TRAP0 0x00000080 ! 87: #define EXCEPTION_TRAP1 0x00000084 ! 88: #define EXCEPTION_TRAP2 0x00000088 ! 89: #define EXCEPTION_TRAP13 0x000000B4 ! 90: #define EXCEPTION_TRAP14 0x000000B8 ! 91: ! 92: ! 93: /* Size of 68000 instructions */ ! 94: #define MAX_68000_INSTRUCTION_SIZE 10 /* Longest 68000 instruction is 10 bytes(6+4) */ ! 95: #define MIN_68000_INSTRUCTION_SIZE 2 /* Smallest 68000 instruction is 2 bytes(ie NOP) */ ! 96: ! 97: /* Illegal Opcode used to help emulation. eg. free entries are 8 to 15 inc' */ ! 98: #define GEMDOS_OPCODE 8 /* Free op-code to intercept GemDOS trap */ ! 99: #define SYSINIT_OPCODE 10 /* Free op-code to initialize system (connected drives etc.) */ ! 100: #define VDI_OPCODE 12 /* Free op-code to call VDI handlers AFTER Trap#2 */ ! 101: ! 102: ! 103: ! 104: /* Ugly hacks to adapt the main code to the different CPU cores: */ ! 105: ! 106: #define Regs regs.regs ! 107: ! 108: #if defined(UAE_NEWCPU_H) ! 109: ! 110: # define M68000_GetPC() m68k_getpc() ! 111: # define M68000_SetPC(val) m68k_setpc(val) ! 112: ! 113: static inline Uint16 M68000_GetSR(void) ! 114: { ! 115: MakeSR(); ! 116: return regs.sr; ! 117: } ! 118: static inline void M68000_SetSR(Uint16 v) ! 119: { ! 120: regs.sr = v; ! 121: MakeFromSR(); ! 122: } ! 123: ! 124: # define M68000_SetSpecial(flags) set_special(flags) ! 125: # define M68000_UnsetSpecial(flags) unset_special(flags) ! 126: ! 127: #else /* following code is for WinUAE CPU: */ ! 128: ! 129: # define M68000_GetPC() m68k_getpc(®s) ! 130: # define M68000_SetPC(val) m68k_setpc(®s,val) ! 131: ! 132: static inline Uint16 M68000_GetSR(void) ! 133: { ! 134: MakeSR(®s); ! 135: return regs.sr; ! 136: } ! 137: static inline void M68000_SetSR(Uint16 v) ! 138: { ! 139: regs.sr = v; ! 140: MakeFromSR(®s); ! 141: } ! 142: ! 143: # define M68000_SetSpecial(flags) set_special(®s,flags) ! 144: # define M68000_UnsetSpecial(flags) unset_special(®s,flags) ! 145: ! 146: #endif /* defined(UAE_NEWCPU_H) */ ! 147: ! 148: ! 149: /* bus error mode */ ! 150: #define BUS_ERROR_WRITE 0 ! 151: #define BUS_ERROR_READ 1 ! 152: ! 153: ! 154: /* bus acces mode */ ! 155: #define BUS_MODE_CPU 0 /* bus is owned by the cpu */ ! 156: #define BUS_MODE_BLITTER 1 /* bus is owned by the blitter */ ! 157: ! 158: ! 159: extern Uint32 BusErrorAddress; ! 160: extern Uint32 BusErrorPC; ! 161: extern bool bBusErrorReadWrite; ! 162: extern int nCpuFreqShift; ! 163: extern int nWaitStateCycles; ! 164: extern int BusMode; ! 165: ! 166: extern int LastOpcodeFamily; ! 167: extern int LastInstrCycles; ! 168: extern int Pairing; ! 169: extern char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ]; ! 170: extern const char *OpcodeName[]; ! 171: ! 172: ! 173: /*-----------------------------------------------------------------------*/ ! 174: /** ! 175: * Add CPU cycles. ! 176: * NOTE: All times are rounded up to nearest 4 cycles. ! 177: */ ! 178: static inline void M68000_AddCycles(int cycles) ! 179: { ! 180: cycles = (cycles + 3) & ~3; ! 181: cycles = cycles >> nCpuFreqShift; ! 182: ! 183: PendingInterruptCount -= INT_CONVERT_TO_INTERNAL(cycles, INT_CPU_CYCLE); ! 184: nCyclesMainCounter += cycles; ! 185: } ! 186: ! 187: ! 188: /*-----------------------------------------------------------------------*/ ! 189: /** ! 190: * Add CPU cycles, take cycles pairing into account. Pairing will make ! 191: * some specific instructions take 4 cycles less when run one after the other. ! 192: * Pairing happens when the 2 instructions are "aligned" on different bus accesses. ! 193: * Candidates are : ! 194: * - 2 instructions taking 4n+2 cycles ! 195: * - 1 instruction taking 4n+2 cycles, followed by 1 instruction using d8(an,ix) ! 196: * ! 197: * Not all the candidate instructions can pair, only the opcodes listed in PairingArray. ! 198: * On ST, when using d8(an,ix), we get an extra 2 cycle penalty for misaligned bus access. ! 199: * The only instruction that can generate BusCyclePenalty=4 is move d8(an,ix),d8(an,ix) ! 200: * and although it takes 4n cycles (24 for .b/.w or 32 for .l) it can pair with ! 201: * a previous 4n+2 instruction (but it will still have 1 misaligned bus access in the end). ! 202: * ! 203: * Verified pairing on an STF : ! 204: * - lsl.w #4,d1 + move.w 0(a4,d2.w),d1 motorola=14+14=28 stf=28 ! 205: * - lsl.w #4,d1 + move.w 0(a4,d2.w),(a4) motorola=14+18=32 stf=32 ! 206: * - lsl.w #4,d1 + move.w 0(a4,d2.w),0(a4,d2.w) motorola=14+24=38 stf=40 ! 207: * - add.l (a5,d1.w),d0 + move.b 7(a5,d1.w),d5) motorola=20+14=34 stf=36 ! 208: * ! 209: * d8(an,ix) timings without pairing (2 cycles penalty) : ! 210: * - add.l 0(a4,d2.w),a1 motorola=20 stf=24 ! 211: * - move.w 0(a4,d2.w),d1 motorola=14 stf=16 ! 212: * - move.w 0(a4,d2.w),(a4) motorola=18 stf=20 ! 213: * - move.w 0(a4,d2.w),0(a4,d2.w) motorola=24 stf=28 ! 214: * ! 215: * NOTE: All times are rounded up to nearest 4 cycles. ! 216: */ ! 217: static inline void M68000_AddCyclesWithPairing(int cycles) ! 218: { ! 219: Pairing = 0; ! 220: /* Check if number of cycles for current instr and for */ ! 221: /* the previous one is of the form 4+2n */ ! 222: /* If so, a pairing could be possible depending on the opcode */ ! 223: /* A pairing is also possible if current instr is 4n but with BusCyclePenalty > 0 */ ! 224: if ( ( PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1 ) ! 225: && ( ( LastInstrCycles & 3 ) == 2 ) ! 226: && ( ( ( cycles & 3 ) == 2 ) || ( BusCyclePenalty > 0 ) ) ) ! 227: { ! 228: Pairing = 1; ! 229: LOG_TRACE(TRACE_CPU_PAIRING, ! 230: "cpu pairing detected pc=%x family %s/%s cycles %d/%d\n", ! 231: m68k_getpc(), OpcodeName[LastOpcodeFamily], ! 232: OpcodeName[OpcodeFamily], LastInstrCycles, cycles); ! 233: } ! 234: ! 235: /* [NP] This part is only needed to track possible pairing instructions, */ ! 236: /* we can keep it disabled most of the time */ ! 237: #if 0 ! 238: if ( (LastOpcodeFamily!=OpcodeFamily) && ( Pairing == 0 ) ! 239: && ( ( cycles & 3 ) == 2 ) && ( ( LastInstrCycles & 3 ) == 2 ) ) ! 240: { ! 241: LOG_TRACE(TRACE_CPU_PAIRING, ! 242: "cpu could pair pc=%x family %s/%s cycles %d/%d\n", ! 243: m68k_getpc(), OpcodeName[LastOpcodeFamily], ! 244: OpcodeName[OpcodeFamily], LastInstrCycles, cycles); ! 245: } ! 246: #endif ! 247: ! 248: /* Store current instr (not rounded) to check next time */ ! 249: LastInstrCycles = cycles + BusCyclePenalty; ! 250: LastOpcodeFamily = OpcodeFamily; ! 251: ! 252: /* If pairing is true, we need to substract 2 cycles for the */ ! 253: /* previous instr which was rounded to 4 cycles while it wasn't */ ! 254: /* needed (and we don't round the current one) */ ! 255: /* -> both instr will take 4 cycles less on the ST than if ran */ ! 256: /* separately. */ ! 257: if (Pairing == 1) ! 258: { ! 259: if ( ( cycles & 3 ) == 2 ) /* pairing between 4n+2 and 4n+2 instructions */ ! 260: cycles -= 2; /* if we have a pairing, we should not count the misaligned bus access */ ! 261: ! 262: else /* this is the case of move d8(an,ix),d8(an,ix) where BusCyclePenalty=4 */ ! 263: /*do nothing */; /* we gain 2 cycles for the pairing with 1st d8(an,ix) */ ! 264: /* and we have 1 remaining misaligned access for the 2nd d8(an,ix). So in the end, we keep */ ! 265: /* cycles unmodified as 4n cycles (eg lsl.w #4,d1 + move.w 0(a4,d2.w),0(a4,d2.w) takes 40 cycles) */ ! 266: } ! 267: else ! 268: { ! 269: cycles += BusCyclePenalty; /* >0 if d8(an,ix) was used */ ! 270: cycles = (cycles + 3) & ~3; /* no pairing, round current instr to 4 cycles */ ! 271: } ! 272: ! 273: cycles = cycles >> nCpuFreqShift; ! 274: ! 275: PendingInterruptCount -= INT_CONVERT_TO_INTERNAL ( cycles , INT_CPU_CYCLE ); ! 276: ! 277: nCyclesMainCounter += cycles; ! 278: BusCyclePenalty = 0; ! 279: } ! 280: ! 281: ! 282: extern void M68000_Init(void); ! 283: extern void M68000_Reset(bool bCold); ! 284: extern void M68000_Start(void); ! 285: extern void M68000_CheckCpuLevel(void); ! 286: extern void M68000_MemorySnapShot_Capture(bool bSave); ! 287: extern void M68000_BusError(Uint32 addr, bool bReadWrite); ! 288: extern void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource); ! 289: extern void M68000_WaitState(int nCycles); ! 290: ! 291: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.