|
|
1.1 root 1: /*
1.1.1.5 root 2: Hatari - m68000.h
3:
1.1.1.16! root 4: This file is distributed under the GNU General Public License, version 2
! 5: or at 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,
1.1.1.16! root 47: REG_A7 /* ..A7 (also SP) */
1.1.1.11 root 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.16! root 102: /* Illegal opcodes used for Native Features emulation:
! 103: * http://wiki.aranym.org/natfeats/proposal#special_opcodes
! 104: */
! 105: #define NATFEAT_ID_OPCODE 0x7300
! 106: #define NATFEAT_CALL_OPCODE 0x7301
1.1.1.10 root 107:
108:
109: /* Ugly hacks to adapt the main code to the different CPU cores: */
110:
111: #define Regs regs.regs
112:
113:
114: # define M68000_GetPC() m68k_getpc()
115: # define M68000_SetPC(val) m68k_setpc(val)
116:
117: static inline Uint16 M68000_GetSR(void)
118: {
119: MakeSR();
120: return regs.sr;
121: }
122: static inline void M68000_SetSR(Uint16 v)
123: {
124: regs.sr = v;
125: MakeFromSR();
126: }
127:
128: # define M68000_SetSpecial(flags) set_special(flags)
129: # define M68000_UnsetSpecial(flags) unset_special(flags)
130:
131:
1.1.1.9 root 132: /* bus error mode */
133: #define BUS_ERROR_WRITE 0
134: #define BUS_ERROR_READ 1
135:
1.1.1.10 root 136:
1.1.1.15 root 137: /* bus access mode */
1.1.1.12 root 138: #define BUS_MODE_CPU 0 /* bus is owned by the cpu */
139: #define BUS_MODE_BLITTER 1 /* bus is owned by the blitter */
140:
141:
1.1.1.16! root 142: /* Notes on IACK :
! 143: * When an interrupt happens, it's possible a similar interrupt happens again
! 144: * between the start of the exception and the IACK sequence. In that case, we
! 145: * might have to set pending bit twice and change the interrupt vector.
! 146: * From the 68000's doc, IACK start after 12 cycles. Then in an Atari STF, it takes
! 147: * 12 extra cycles to fetch the vector number.
! 148: * This means we have at max 24 cycles at the start of the exception where some
! 149: * changes can happen. The values we use were not measured on real hardware, they
! 150: * were adjusted to get the correct behaviour in some games/demos relying on this.
! 151: */
! 152: #define CPU_IACK_CYCLES_MFP 12 /* vector sent by the MFP */
! 153: #define CPU_IACK_CYCLES_VIDEO 20 /* auto vectored */
! 154:
! 155:
! 156: /* information about current CPU instruction */
! 157: typedef struct {
! 158: /* these are provided only by WinUAE CPU core */
! 159: int iCacheMisses;
! 160: int iSave_instr_tail;
! 161:
! 162: /* TODO: move other instruction specific Hatari variables here */
! 163: } cpu_instruction_t;
! 164:
! 165: extern cpu_instruction_t CpuInstruction;
! 166:
1.1.1.7 root 167: extern Uint32 BusErrorAddress;
1.1.1.5 root 168: extern Uint32 BusErrorPC;
1.1.1.11 root 169: extern bool bBusErrorReadWrite;
1.1.1.7 root 170: extern int nCpuFreqShift;
1.1.1.9 root 171: extern int nWaitStateCycles;
1.1.1.12 root 172: extern int BusMode;
1.1.1.16! root 173: extern bool CPU_IACK;
1.1.1.6 root 174:
1.1.1.10 root 175: extern int LastOpcodeFamily;
176: extern int LastInstrCycles;
177: extern int Pairing;
178: extern char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
179: extern const char *OpcodeName[];
180:
1.1.1.6 root 181:
182: /*-----------------------------------------------------------------------*/
1.1.1.10 root 183: /**
184: * Add CPU cycles.
185: * NOTE: All times are rounded up to nearest 4 cycles.
186: */
1.1.1.6 root 187: static inline void M68000_AddCycles(int cycles)
188: {
1.1.1.10 root 189: cycles = (cycles + 3) & ~3;
190: cycles = cycles >> nCpuFreqShift;
191:
192: PendingInterruptCount -= INT_CONVERT_TO_INTERNAL(cycles, INT_CPU_CYCLE);
1.1.1.9 root 193: nCyclesMainCounter += cycles;
1.1.1.16! root 194: CyclesGlobalClockCounter += cycles;
1.1.1.6 root 195: }
1.1.1.5 root 196:
1.1.1.10 root 197:
198: /*-----------------------------------------------------------------------*/
199: /**
1.1.1.14 root 200: * Add CPU cycles, take cycles pairing into account. Pairing will make
201: * some specific instructions take 4 cycles less when run one after the other.
202: * Pairing happens when the 2 instructions are "aligned" on different bus accesses.
203: * Candidates are :
204: * - 2 instructions taking 4n+2 cycles
205: * - 1 instruction taking 4n+2 cycles, followed by 1 instruction using d8(an,ix)
206: *
207: * Not all the candidate instructions can pair, only the opcodes listed in PairingArray.
208: * On ST, when using d8(an,ix), we get an extra 2 cycle penalty for misaligned bus access.
209: * The only instruction that can generate BusCyclePenalty=4 is move d8(an,ix),d8(an,ix)
210: * and although it takes 4n cycles (24 for .b/.w or 32 for .l) it can pair with
211: * a previous 4n+2 instruction (but it will still have 1 misaligned bus access in the end).
212: *
213: * Verified pairing on an STF :
214: * - lsl.w #4,d1 + move.w 0(a4,d2.w),d1 motorola=14+14=28 stf=28
215: * - lsl.w #4,d1 + move.w 0(a4,d2.w),(a4) motorola=14+18=32 stf=32
216: * - lsl.w #4,d1 + move.w 0(a4,d2.w),0(a4,d2.w) motorola=14+24=38 stf=40
217: * - add.l (a5,d1.w),d0 + move.b 7(a5,d1.w),d5) motorola=20+14=34 stf=36
218: *
219: * d8(an,ix) timings without pairing (2 cycles penalty) :
220: * - add.l 0(a4,d2.w),a1 motorola=20 stf=24
221: * - move.w 0(a4,d2.w),d1 motorola=14 stf=16
222: * - move.w 0(a4,d2.w),(a4) motorola=18 stf=20
223: * - move.w 0(a4,d2.w),0(a4,d2.w) motorola=24 stf=28
224: *
1.1.1.10 root 225: * NOTE: All times are rounded up to nearest 4 cycles.
226: */
227: static inline void M68000_AddCyclesWithPairing(int cycles)
228: {
229: Pairing = 0;
230: /* Check if number of cycles for current instr and for */
231: /* the previous one is of the form 4+2n */
232: /* If so, a pairing could be possible depending on the opcode */
1.1.1.14 root 233: /* A pairing is also possible if current instr is 4n but with BusCyclePenalty > 0 */
1.1.1.10 root 234: if ( ( PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1 )
1.1.1.14 root 235: && ( ( LastInstrCycles & 3 ) == 2 )
236: && ( ( ( cycles & 3 ) == 2 ) || ( BusCyclePenalty > 0 ) ) )
1.1.1.10 root 237: {
238: Pairing = 1;
1.1.1.13 root 239: LOG_TRACE(TRACE_CPU_PAIRING,
240: "cpu pairing detected pc=%x family %s/%s cycles %d/%d\n",
241: m68k_getpc(), OpcodeName[LastOpcodeFamily],
242: OpcodeName[OpcodeFamily], LastInstrCycles, cycles);
1.1.1.10 root 243: }
244:
1.1.1.11 root 245: /* [NP] This part is only needed to track possible pairing instructions, */
246: /* we can keep it disabled most of the time */
247: #if 0
248: if ( (LastOpcodeFamily!=OpcodeFamily) && ( Pairing == 0 )
249: && ( ( cycles & 3 ) == 2 ) && ( ( LastInstrCycles & 3 ) == 2 ) )
250: {
1.1.1.13 root 251: LOG_TRACE(TRACE_CPU_PAIRING,
252: "cpu could pair pc=%x family %s/%s cycles %d/%d\n",
253: m68k_getpc(), OpcodeName[LastOpcodeFamily],
254: OpcodeName[OpcodeFamily], LastInstrCycles, cycles);
1.1.1.11 root 255: }
256: #endif
257:
1.1.1.10 root 258: /* Store current instr (not rounded) to check next time */
1.1.1.14 root 259: LastInstrCycles = cycles + BusCyclePenalty;
1.1.1.10 root 260: LastOpcodeFamily = OpcodeFamily;
261:
1.1.1.16! root 262: /* If pairing is true, we need to subtract 2 cycles for the */
1.1.1.10 root 263: /* previous instr which was rounded to 4 cycles while it wasn't */
264: /* needed (and we don't round the current one) */
265: /* -> both instr will take 4 cycles less on the ST than if ran */
266: /* separately. */
267: if (Pairing == 1)
1.1.1.14 root 268: {
269: if ( ( cycles & 3 ) == 2 ) /* pairing between 4n+2 and 4n+2 instructions */
270: cycles -= 2; /* if we have a pairing, we should not count the misaligned bus access */
271:
272: else /* this is the case of move d8(an,ix),d8(an,ix) where BusCyclePenalty=4 */
273: /*do nothing */; /* we gain 2 cycles for the pairing with 1st d8(an,ix) */
274: /* and we have 1 remaining misaligned access for the 2nd d8(an,ix). So in the end, we keep */
275: /* cycles unmodified as 4n cycles (eg lsl.w #4,d1 + move.w 0(a4,d2.w),0(a4,d2.w) takes 40 cycles) */
276: }
1.1.1.10 root 277: else
1.1.1.14 root 278: {
279: cycles += BusCyclePenalty; /* >0 if d8(an,ix) was used */
280: cycles = (cycles + 3) & ~3; /* no pairing, round current instr to 4 cycles */
281: }
1.1.1.10 root 282:
283: cycles = cycles >> nCpuFreqShift;
284:
285: PendingInterruptCount -= INT_CONVERT_TO_INTERNAL ( cycles , INT_CPU_CYCLE );
286:
287: nCyclesMainCounter += cycles;
1.1.1.16! root 288: CyclesGlobalClockCounter += cycles;
1.1.1.14 root 289: BusCyclePenalty = 0;
1.1.1.10 root 290: }
291:
292:
1.1.1.14 root 293: extern void M68000_Init(void);
1.1.1.11 root 294: extern void M68000_Reset(bool bCold);
1.1.1.10 root 295: extern void M68000_Start(void);
1.1.1.15 root 296: extern void M68000_CheckCpuSettings(void);
1.1.1.11 root 297: extern void M68000_MemorySnapShot_Capture(bool bSave);
298: extern void M68000_BusError(Uint32 addr, bool bReadWrite);
299: extern void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource);
1.1.1.9 root 300: extern void M68000_WaitState(int nCycles);
1.1.1.16! root 301: extern int M68000_WaitEClock ( void );
1.1.1.5 root 302:
303: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.