editing changelog
[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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
47 {
48     long OpAddress = icpu->ShiftedPB + cpu->PC - cpu->PCBase;
49     cpu->PC++;
50         return OpAddress;
51 }
52
53 STATIC INLINE long FASTCALL Immediate16 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
86 {
87 #ifdef FAST_LSB_WORD_ACCESS
88     long OpAddress = (reg->X.W + *(uint16 *) cpu->PC) & 0xffff;
89 #else
90     long OpAddress = (reg->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, cpu);
97 }
98
99 STATIC INLINE long FASTCALL AbsoluteIndirectLong (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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, cpu) | (S9xGetByte (OpAddress + 2, cpu) << 16);
112 }
113
114 STATIC INLINE long FASTCALL AbsoluteIndirect (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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, cpu) + icpu->ShiftedPB;
127 }
128
129 STATIC INLINE long FASTCALL Absolute (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
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(struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
158 {
159     long OpAddress = (*cpu->PC++ + reg->D.W) & 0xffff;
160 #ifdef VAR_CYCLES
161     cpu->Cycles += cpu->MemSpeed;
162 #endif
163 //    if (reg->DL != 0) cpu->Cycles += ONE_CYCLE;
164         return OpAddress;
165 }
166
167 STATIC INLINE long FASTCALL DirectIndirectIndexed (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
168 {
169     long OpAddress = (*cpu->PC++ + reg->D.W) & 0xffff;
170 #ifdef VAR_CYCLES
171     cpu->Cycles += cpu->MemSpeed;
172 #endif
173
174     OpAddress = icpu->ShiftedDB + S9xGetWord (OpAddress, cpu) + reg->Y.W;
175
176 //    if (reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
183 {
184     long OpAddress = (*cpu->PC++ + reg->D.W) & 0xffff;
185 #ifdef VAR_CYCLES
186     cpu->Cycles += cpu->MemSpeed;
187 #endif
188
189     OpAddress = S9xGetWord (OpAddress, cpu) + (S9xGetByte (OpAddress + 2, cpu) << 16) +
190                 reg->Y.W;
191 //    if (reg->DL != 0) cpu->Cycles += ONE_CYCLE;
192         return OpAddress;
193 }
194
195 STATIC INLINE long FASTCALL DirectIndexedIndirect(struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
196 {
197     long OpAddress = (*cpu->PC++ + reg->D.W + reg->X.W) & 0xffff;
198 #ifdef VAR_CYCLES
199     cpu->Cycles += cpu->MemSpeed;
200 #endif
201
202     OpAddress = S9xGetWord (OpAddress, cpu) + icpu->ShiftedDB;
203
204 #ifdef VAR_CYCLES
205 //    if (reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
214 {
215     long OpAddress = (*cpu->PC++ + reg->D.W + reg->X.W) & 0xffff;
216 #ifdef VAR_CYCLES
217     cpu->Cycles += cpu->MemSpeed;
218 #endif
219
220 #ifdef VAR_CYCLES
221 //    if (reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
230 {
231     long OpAddress = (*cpu->PC++ + reg->D.W + reg->Y.W) & 0xffff;
232 #ifdef VAR_CYCLES
233     cpu->Cycles += cpu->MemSpeed;
234 #endif
235
236 #ifdef VAR_CYCLES
237 //    if (reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
246 {
247 #ifdef FAST_LSB_WORD_ACCESS
248     long OpAddress = icpu->ShiftedDB + *(uint16 *) cpu->PC + reg->X.W;
249 #else
250     long OpAddress = icpu->ShiftedDB + *cpu->PC + (*(cpu->PC + 1) << 8) +
251                 reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
263 {
264 #ifdef FAST_LSB_WORD_ACCESS
265     long OpAddress = icpu->ShiftedDB + *(uint16 *) cpu->PC + reg->Y.W;
266 #else
267     long OpAddress = icpu->ShiftedDB + *cpu->PC + (*(cpu->PC + 1) << 8) +
268                 reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
280 {
281 #ifdef FAST_LSB_WORD_ACCESS
282     long OpAddress = (*(uint32 *) cpu->PC + reg->X.W) & 0xffffff;
283 #else
284     long OpAddress = (*cpu->PC + (*(cpu->PC + 1) << 8) + (*(cpu->PC + 2) << 16) + reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
294 {
295     long OpAddress = (*cpu->PC++ + reg->D.W) & 0xffff;
296 #ifdef VAR_CYCLES
297     cpu->Cycles += cpu->MemSpeed;
298 #endif
299     OpAddress = S9xGetWord (OpAddress, cpu) + icpu->ShiftedDB;
300
301 //    if (reg->DL != 0) cpu->Cycles += ONE_CYCLE;
302         return OpAddress;
303 }
304
305 STATIC INLINE long FASTCALL DirectIndirectLong (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
306 {
307     long OpAddress = (*cpu->PC++ + reg->D.W) & 0xffff;
308 #ifdef VAR_CYCLES
309     cpu->Cycles += cpu->MemSpeed;
310 #endif
311     OpAddress = S9xGetWord (OpAddress, cpu) +
312                 (S9xGetByte (OpAddress + 2, cpu) << 16);
313 //    if (reg->DL != 0) cpu->Cycles += ONE_CYCLE;
314         return OpAddress;
315 }
316
317 STATIC INLINE long FASTCALL StackRelative (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
318 {
319     long OpAddress = (*cpu->PC++ + reg->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 (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
328 {
329     long OpAddress = (*cpu->PC++ + reg->S.W) & 0xffff;
330 #ifdef VAR_CYCLES
331     cpu->Cycles += cpu->MemSpeed;
332     cpu->Cycles += TWO_CYCLES;
333 #endif
334     OpAddress = (S9xGetWord (OpAddress, cpu) + icpu->ShiftedDB +
335                  reg->Y.W) & 0xffffff;
336         return OpAddress;
337 }
338 #endif