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