1 /*
2 Hatari - m68000.h
3
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.
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 /* 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
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
M68000_GetSR(void)117 static inline Uint16 M68000_GetSR(void)
118 {
119 MakeSR();
120 return regs.sr;
121 }
M68000_SetSR(Uint16 v)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
132 /* bus error mode */
133 #define BUS_ERROR_WRITE 0
134 #define BUS_ERROR_READ 1
135
136
137 /* bus access mode */
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
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
167 extern Uint32 BusErrorAddress;
168 extern Uint32 BusErrorPC;
169 extern bool bBusErrorReadWrite;
170 extern int nCpuFreqShift;
171 extern int nWaitStateCycles;
172 extern int BusMode;
173 extern bool CPU_IACK;
174
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
181
182 /*-----------------------------------------------------------------------*/
183 /**
184 * Add CPU cycles.
185 * NOTE: All times are rounded up to nearest 4 cycles.
186 */
M68000_AddCycles(int cycles)187 static inline void M68000_AddCycles(int cycles)
188 {
189 cycles = (cycles + 3) & ~3;
190 cycles = cycles >> nCpuFreqShift;
191
192 PendingInterruptCount -= INT_CONVERT_TO_INTERNAL(cycles, INT_CPU_CYCLE);
193 nCyclesMainCounter += cycles;
194 CyclesGlobalClockCounter += cycles;
195 }
196
197
198 /*-----------------------------------------------------------------------*/
199 /**
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 *
225 * NOTE: All times are rounded up to nearest 4 cycles.
226 */
M68000_AddCyclesWithPairing(int cycles)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 */
233 /* A pairing is also possible if current instr is 4n but with BusCyclePenalty > 0 */
234 if ( ( PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1 )
235 && ( ( LastInstrCycles & 3 ) == 2 )
236 && ( ( ( cycles & 3 ) == 2 ) || ( BusCyclePenalty > 0 ) ) )
237 {
238 Pairing = 1;
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);
243 }
244
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 {
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);
255 }
256 #endif
257
258 /* Store current instr (not rounded) to check next time */
259 LastInstrCycles = cycles + BusCyclePenalty;
260 LastOpcodeFamily = OpcodeFamily;
261
262 /* If pairing is true, we need to subtract 2 cycles for the */
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)
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 }
277 else
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 }
282
283 cycles = cycles >> nCpuFreqShift;
284
285 PendingInterruptCount -= INT_CONVERT_TO_INTERNAL ( cycles , INT_CPU_CYCLE );
286
287 nCyclesMainCounter += cycles;
288 CyclesGlobalClockCounter += cycles;
289 BusCyclePenalty = 0;
290 }
291
292
293 extern void M68000_Init(void);
294 extern void M68000_Reset(bool bCold);
295 extern void M68000_Start(void);
296 extern void M68000_CheckCpuSettings(void);
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);
300 extern void M68000_WaitState(int nCycles);
301 extern int M68000_WaitEClock ( void );
302
303 #endif
304