|
|
1.1 root 1: /*
1.1.1.5 root 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.
1.1 root 6: */
7:
1.1.1.10 root 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) */
1.1.1.14! root 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:
1.1.1.10 root 18:
1.1.1.5 root 19: #ifndef HATARI_M68000_H
20: #define HATARI_M68000_H
21:
1.1.1.9 root 22: #include "cycles.h" /* for nCyclesMainCounter */
1.1.1.6 root 23: #include "sysdeps.h"
24: #include "memory.h"
1.1.1.9 root 25: #include "newcpu.h" /* for regs */
1.1.1.14! root 26: #include "cycInt.h"
1.1.1.11 root 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:
1.1.1.10 root 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)
1.1.1.6 root 131:
1.1.1.10 root 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:
1.1.1.9 root 149: /* bus error mode */
150: #define BUS_ERROR_WRITE 0
151: #define BUS_ERROR_READ 1
152:
1.1.1.10 root 153:
1.1.1.12 root 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:
1.1.1.7 root 159: extern Uint32 BusErrorAddress;
1.1.1.5 root 160: extern Uint32 BusErrorPC;
1.1.1.11 root 161: extern bool bBusErrorReadWrite;
1.1.1.7 root 162: extern int nCpuFreqShift;
1.1.1.9 root 163: extern int nWaitStateCycles;
1.1.1.12 root 164: extern int BusMode;
1.1.1.6 root 165:
1.1.1.10 root 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:
1.1.1.6 root 172:
173: /*-----------------------------------------------------------------------*/
1.1.1.10 root 174: /**
175: * Add CPU cycles.
176: * NOTE: All times are rounded up to nearest 4 cycles.
177: */
1.1.1.6 root 178: static inline void M68000_AddCycles(int cycles)
179: {
1.1.1.10 root 180: cycles = (cycles + 3) & ~3;
181: cycles = cycles >> nCpuFreqShift;
182:
183: PendingInterruptCount -= INT_CONVERT_TO_INTERNAL(cycles, INT_CPU_CYCLE);
1.1.1.9 root 184: nCyclesMainCounter += cycles;
1.1.1.6 root 185: }
1.1.1.5 root 186:
1.1.1.10 root 187:
188: /*-----------------------------------------------------------------------*/
189: /**
1.1.1.14! root 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: *
1.1.1.10 root 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 */
1.1.1.14! root 223: /* A pairing is also possible if current instr is 4n but with BusCyclePenalty > 0 */
1.1.1.10 root 224: if ( ( PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1 )
1.1.1.14! root 225: && ( ( LastInstrCycles & 3 ) == 2 )
! 226: && ( ( ( cycles & 3 ) == 2 ) || ( BusCyclePenalty > 0 ) ) )
1.1.1.10 root 227: {
228: Pairing = 1;
1.1.1.13 root 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);
1.1.1.10 root 233: }
234:
1.1.1.11 root 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: {
1.1.1.13 root 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);
1.1.1.11 root 245: }
246: #endif
247:
1.1.1.10 root 248: /* Store current instr (not rounded) to check next time */
1.1.1.14! root 249: LastInstrCycles = cycles + BusCyclePenalty;
1.1.1.10 root 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)
1.1.1.14! root 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: }
1.1.1.10 root 267: else
1.1.1.14! root 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: }
1.1.1.10 root 272:
273: cycles = cycles >> nCpuFreqShift;
274:
275: PendingInterruptCount -= INT_CONVERT_TO_INTERNAL ( cycles , INT_CPU_CYCLE );
276:
277: nCyclesMainCounter += cycles;
1.1.1.14! root 278: BusCyclePenalty = 0;
1.1.1.10 root 279: }
280:
281:
1.1.1.14! root 282: extern void M68000_Init(void);
1.1.1.11 root 283: extern void M68000_Reset(bool bCold);
1.1.1.10 root 284: extern void M68000_Start(void);
285: extern void M68000_CheckCpuLevel(void);
1.1.1.11 root 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);
1.1.1.9 root 289: extern void M68000_WaitState(int nCycles);
1.1.1.5 root 290:
291: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.