random bug fixes
[drnoksnes] / cpuaddr.h
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #ifndef _CPUADDR_H_
42 #define _CPUADDR_H_
43
44 //EXTERN_C long OpAddress;
45
46 STATIC INLINE long FASTCALL Immediate8 ()
47 {
48     long OpAddress = ICPU.ShiftedPB + CPU.PC - CPU.PCBase;
49     CPU.PC++;
50         return OpAddress;
51 }
52
53 STATIC INLINE long FASTCALL Immediate16 ()
54 {
55     long OpAddress = ICPU.ShiftedPB + CPU.PC - CPU.PCBase;
56     CPU.PC += 2;
57         return OpAddress;
58 }
59
60 STATIC INLINE long FASTCALL Relative ()
61 {
62     int8 Int8 = *CPU.PC++;
63 #ifdef VAR_CYCLES
64     CPU.Cycles += CPU.MemSpeed;
65 #endif    
66         return ((int) (CPU.PC - CPU.PCBase) + Int8) & 0xffff;
67 }
68
69 STATIC INLINE long FASTCALL RelativeLong ()
70 {
71 #ifdef FAST_LSB_WORD_ACCESS
72     long OpAddress = *(uint16 *) CPU.PC;
73 #else
74     long OpAddress = *CPU.PC + (*(CPU.PC + 1) << 8);
75 #endif
76 #ifdef VAR_CYCLES
77     CPU.Cycles += CPU.MemSpeedx2 + ONE_CYCLE;
78 #endif
79     CPU.PC += 2;
80     OpAddress += (CPU.PC - CPU.PCBase);
81     OpAddress &= 0xffff;
82         return OpAddress;
83 }
84
85 STATIC INLINE long FASTCALL AbsoluteIndexedIndirect ()
86 {
87 #ifdef FAST_LSB_WORD_ACCESS
88     long OpAddress = (Registers.X.W + *(uint16 *) CPU.PC) & 0xffff;
89 #else
90     long OpAddress = (Registers.X.W + *CPU.PC + (*(CPU.PC + 1) << 8)) & 0xffff;
91 #endif
92 #ifdef VAR_CYCLES
93     CPU.Cycles += CPU.MemSpeedx2;
94 #endif
95     CPU.PC += 2;
96     return S9xGetWord (ICPU.ShiftedPB + OpAddress);
97 }
98
99 STATIC INLINE long FASTCALL AbsoluteIndirectLong ()
100 {
101 #ifdef FAST_LSB_WORD_ACCESS
102     long OpAddress = *(uint16 *) CPU.PC;
103 #else
104     long OpAddress = *CPU.PC + (*(CPU.PC + 1) << 8);
105 #endif
106
107 #ifdef VAR_CYCLES
108     CPU.Cycles += CPU.MemSpeedx2;
109 #endif
110     CPU.PC += 2;
111     return S9xGetWord (OpAddress) | (S9xGetByte (OpAddress + 2) << 16);
112 }
113
114 STATIC INLINE long FASTCALL AbsoluteIndirect ()
115 {
116 #ifdef FAST_LSB_WORD_ACCESS
117     long OpAddress = *(uint16 *) CPU.PC;
118 #else
119     long OpAddress = *CPU.PC + (*(CPU.PC + 1) << 8);
120 #endif
121
122 #ifdef VAR_CYCLES
123     CPU.Cycles += CPU.MemSpeedx2;
124 #endif
125     CPU.PC += 2;
126     return S9xGetWord (OpAddress) + ICPU.ShiftedPB;
127 }
128
129 STATIC INLINE long FASTCALL Absolute ()
130 {
131 #ifdef FAST_LSB_WORD_ACCESS
132     long OpAddress = *(uint16 *) CPU.PC + ICPU.ShiftedDB;
133 #else
134     long OpAddress = *CPU.PC + (*(CPU.PC + 1) << 8) + ICPU.ShiftedDB;
135 #endif
136     CPU.PC += 2;
137 #ifdef VAR_CYCLES
138     CPU.Cycles += CPU.MemSpeedx2;
139 #endif
140         return OpAddress;
141 }
142
143 STATIC INLINE long FASTCALL AbsoluteLong ()
144 {
145 #ifdef FAST_LSB_WORD_ACCESS
146     long OpAddress = (*(uint32 *) CPU.PC) & 0xffffff;
147 #else
148     long OpAddress = *CPU.PC + (*(CPU.PC + 1) << 8) + (*(CPU.PC + 2) << 16);
149 #endif
150     CPU.PC += 3;
151 #ifdef VAR_CYCLES
152     CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed;
153 #endif
154         return OpAddress;
155 }
156
157 STATIC INLINE long FASTCALL Direct()
158 {
159     long OpAddress = (*CPU.PC++ + Registers.D.W) & 0xffff;
160 #ifdef VAR_CYCLES
161     CPU.Cycles += CPU.MemSpeed;
162 #endif
163 //    if (Registers.DL != 0) CPU.Cycles += ONE_CYCLE;
164         return OpAddress;
165 }
166
167 STATIC INLINE long FASTCALL DirectIndirectIndexed ()
168 {
169     long OpAddress = (*CPU.PC++ + Registers.D.W) & 0xffff;
170 #ifdef VAR_CYCLES
171     CPU.Cycles += CPU.MemSpeed;
172 #endif
173
174     OpAddress = ICPU.ShiftedDB + S9xGetWord (OpAddress) + Registers.Y.W;
175
176 //    if (Registers.DL != 0) CPU.Cycles += ONE_CYCLE;
177     // XXX: always add one if STA
178     // XXX: else Add one cycle if crosses page boundary
179         return OpAddress;
180 }
181
182 STATIC INLINE long FASTCALL DirectIndirectIndexedLong ()
183 {
184     long OpAddress = (*CPU.PC++ + Registers.D.W) & 0xffff;
185 #ifdef VAR_CYCLES
186     CPU.Cycles += CPU.MemSpeed;
187 #endif
188
189     OpAddress = S9xGetWord (OpAddress) + (S9xGetByte (OpAddress + 2) << 16) +
190                 Registers.Y.W;
191 //    if (Registers.DL != 0) CPU.Cycles += ONE_CYCLE;
192         return OpAddress;
193 }
194
195 STATIC INLINE long FASTCALL DirectIndexedIndirect()
196 {
197     long OpAddress = (*CPU.PC++ + Registers.D.W + Registers.X.W) & 0xffff;
198 #ifdef VAR_CYCLES
199     CPU.Cycles += CPU.MemSpeed;
200 #endif
201
202     OpAddress = S9xGetWord (OpAddress) + ICPU.ShiftedDB;
203
204 #ifdef VAR_CYCLES
205 //    if (Registers.DL != 0)
206 //      CPU.Cycles += TWO_CYCLES;
207 //    else
208         CPU.Cycles += ONE_CYCLE;
209 #endif
210         return OpAddress;
211 }
212
213 STATIC INLINE long FASTCALL DirectIndexedX ()
214 {
215     long OpAddress = (*CPU.PC++ + Registers.D.W + Registers.X.W) & 0xffff;
216 #ifdef VAR_CYCLES
217     CPU.Cycles += CPU.MemSpeed;
218 #endif
219
220 #ifdef VAR_CYCLES
221 //    if (Registers.DL != 0)
222 //      CPU.Cycles += TWO_CYCLES;
223 //    else
224         CPU.Cycles += ONE_CYCLE;
225 #endif
226         return OpAddress;
227 }
228
229 STATIC INLINE long FASTCALL DirectIndexedY ()
230 {
231     long OpAddress = (*CPU.PC++ + Registers.D.W + Registers.Y.W) & 0xffff;
232 #ifdef VAR_CYCLES
233     CPU.Cycles += CPU.MemSpeed;
234 #endif
235
236 #ifdef VAR_CYCLES
237 //    if (Registers.DL != 0)
238 //      CPU.Cycles += TWO_CYCLES;
239 //    else
240         CPU.Cycles += ONE_CYCLE;
241 #endif
242         return OpAddress;
243 }
244
245 STATIC INLINE long FASTCALL AbsoluteIndexedX ()
246 {
247 #ifdef FAST_LSB_WORD_ACCESS
248     long OpAddress = ICPU.ShiftedDB + *(uint16 *) CPU.PC + Registers.X.W;
249 #else
250     long OpAddress = ICPU.ShiftedDB + *CPU.PC + (*(CPU.PC + 1) << 8) +
251                 Registers.X.W;
252 #endif
253     CPU.PC += 2;
254 #ifdef VAR_CYCLES
255     CPU.Cycles += CPU.MemSpeedx2;
256 #endif
257     // XXX: always add one cycle for ROL, LSR, etc
258     // XXX: else is cross page boundary add one cycle
259         return OpAddress;
260 }
261
262 STATIC INLINE long FASTCALL AbsoluteIndexedY ()
263 {
264 #ifdef FAST_LSB_WORD_ACCESS
265     long OpAddress = ICPU.ShiftedDB + *(uint16 *) CPU.PC + Registers.Y.W;
266 #else
267     long OpAddress = ICPU.ShiftedDB + *CPU.PC + (*(CPU.PC + 1) << 8) +
268                 Registers.Y.W;
269 #endif    
270     CPU.PC += 2;
271 #ifdef VAR_CYCLES
272     CPU.Cycles += CPU.MemSpeedx2;
273 #endif
274     // XXX: always add cycle for STA
275     // XXX: else is cross page boundary add one cycle
276         return OpAddress;
277 }
278
279 STATIC INLINE long FASTCALL AbsoluteLongIndexedX ()
280 {
281 #ifdef FAST_LSB_WORD_ACCESS
282     long OpAddress = (*(uint32 *) CPU.PC + Registers.X.W) & 0xffffff;
283 #else
284     long OpAddress = (*CPU.PC + (*(CPU.PC + 1) << 8) + (*(CPU.PC + 2) << 16) + Registers.X.W) & 0xffffff;
285 #endif
286     CPU.PC += 3;
287 #ifdef VAR_CYCLES
288     CPU.Cycles += CPU.MemSpeedx2 + CPU.MemSpeed;
289 #endif
290         return OpAddress;
291 }
292
293 STATIC INLINE long FASTCALL DirectIndirect ()
294 {
295     long OpAddress = (*CPU.PC++ + Registers.D.W) & 0xffff;
296 #ifdef VAR_CYCLES
297     CPU.Cycles += CPU.MemSpeed;
298 #endif
299     OpAddress = S9xGetWord (OpAddress) + ICPU.ShiftedDB;
300
301 //    if (Registers.DL != 0) CPU.Cycles += ONE_CYCLE;
302         return OpAddress;
303 }
304
305 STATIC INLINE long FASTCALL DirectIndirectLong ()
306 {
307     long OpAddress = (*CPU.PC++ + Registers.D.W) & 0xffff;
308 #ifdef VAR_CYCLES
309     CPU.Cycles += CPU.MemSpeed;
310 #endif
311     OpAddress = S9xGetWord (OpAddress) +
312                 (S9xGetByte (OpAddress + 2) << 16);
313 //    if (Registers.DL != 0) CPU.Cycles += ONE_CYCLE;
314         return OpAddress;
315 }
316
317 STATIC INLINE long FASTCALL StackRelative ()
318 {
319     long OpAddress = (*CPU.PC++ + Registers.S.W) & 0xffff;
320 #ifdef VAR_CYCLES
321     CPU.Cycles += CPU.MemSpeed;
322     CPU.Cycles += ONE_CYCLE;
323 #endif
324         return OpAddress;
325 }
326
327 STATIC INLINE long FASTCALL StackRelativeIndirectIndexed ()
328 {
329     long OpAddress = (*CPU.PC++ + Registers.S.W) & 0xffff;
330 #ifdef VAR_CYCLES
331     CPU.Cycles += CPU.MemSpeed;
332     CPU.Cycles += TWO_CYCLES;
333 #endif
334     OpAddress = (S9xGetWord (OpAddress) + ICPU.ShiftedDB +
335                  Registers.Y.W) & 0xffffff;
336         return OpAddress;
337 }
338 #endif