2 // Virtual 65C02 Emulator v1.1
5 // (c) 2005-2018 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -----------------------------------------------------------
11 // JLH 01/04/2006 Added changelog ;-)
12 // JLH 01/18/2009 Fixed EA_ABS_* macros
15 //OK, the wraparound bug exists in both the Apple and Atari versions of Ultima
16 //II. However, the Atari version *does* occassionally pick strength while the
17 //Apple versions do not--which would seem to indicate a bug either in the RNG
18 //algorithm, the 65C02 core, or the Apple hardware. Need to investigate all
22 //#define __DEBUGMON__
32 // Various helper macros
34 #define CLR_Z (regs->cc &= ~FLAG_Z)
35 #define CLR_ZN (regs->cc &= ~(FLAG_Z | FLAG_N))
36 #define CLR_ZNC (regs->cc &= ~(FLAG_Z | FLAG_N | FLAG_C))
37 #define CLR_V (regs->cc &= ~FLAG_V)
38 #define CLR_N (regs->cc &= ~FLAG_N)
39 #define CLR_D (regs->cc &= ~FLAG_D)
40 #define SET_Z(r) (regs->cc = ((r) == 0 ? regs->cc | FLAG_Z : regs->cc & ~FLAG_Z))
41 #define SET_N(r) (regs->cc = ((r) & 0x80 ? regs->cc | FLAG_N : regs->cc & ~FLAG_N))
42 #define SET_I (regs->cc |= FLAG_I)
44 //Not sure that this code is computing the carry correctly... Investigate! [Seems to be]
45 #define SET_C_ADD(a,b) (regs->cc = ((uint8_t)(b) > (uint8_t)(~(a)) ? regs->cc | FLAG_C : regs->cc & ~FLAG_C))
46 #define SET_C_CMP(a,b) (regs->cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs->cc | FLAG_C : regs->cc & ~FLAG_C))
47 #define SET_ZN(r) SET_N(r); SET_Z(r)
48 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
49 #define SET_ZNC_CMP(a,b,r) SET_N(r); SET_Z(r); SET_C_CMP(a,b)
51 #define EA_IMM regs->pc++
52 #define EA_ZP regs->RdMem(regs->pc++)
53 #define EA_ZP_X (regs->RdMem(regs->pc++) + regs->x) & 0xFF
54 #define EA_ZP_Y (regs->RdMem(regs->pc++) + regs->y) & 0xFF
55 #define EA_ABS FetchMemW(regs->pc)
56 #define EA_ABS_X FetchMemW(regs->pc) + regs->x
57 #define EA_ABS_Y FetchMemW(regs->pc) + regs->y
58 #define EA_IND_ZP_X RdMemW((regs->RdMem(regs->pc++) + regs->x) & 0xFF)
59 #define EA_IND_ZP_Y RdMemW(regs->RdMem(regs->pc++)) + regs->y
60 #define EA_IND_ZP RdMemW(regs->RdMem(regs->pc++))
62 #define READ_IMM regs->RdMem(EA_IMM)
63 #define READ_ZP regs->RdMem(EA_ZP)
64 #define READ_ZP_X regs->RdMem(EA_ZP_X)
65 #define READ_ZP_Y regs->RdMem(EA_ZP_Y)
66 #define READ_ABS regs->RdMem(EA_ABS)
67 #define READ_ABS_X regs->RdMem(EA_ABS_X)
68 #define READ_ABS_Y regs->RdMem(EA_ABS_Y)
69 #define READ_IND_ZP_X regs->RdMem(EA_IND_ZP_X)
70 #define READ_IND_ZP_Y regs->RdMem(EA_IND_ZP_Y)
71 #define READ_IND_ZP regs->RdMem(EA_IND_ZP)
73 #define READ_IMM_WB(v) uint16_t addr = EA_IMM; v = regs->RdMem(addr)
74 #define READ_ZP_WB(v) uint16_t addr = EA_ZP; v = regs->RdMem(addr)
75 #define READ_ZP_X_WB(v) uint16_t addr = EA_ZP_X; v = regs->RdMem(addr)
76 #define READ_ABS_WB(v) uint16_t addr = EA_ABS; v = regs->RdMem(addr)
77 #define READ_ABS_X_WB(v) uint16_t addr = EA_ABS_X; v = regs->RdMem(addr)
78 #define READ_ABS_Y_WB(v) uint16_t addr = EA_ABS_Y; v = regs->RdMem(addr)
79 #define READ_IND_ZP_X_WB(v) uint16_t addr = EA_IND_ZP_X; v = regs->RdMem(addr)
80 #define READ_IND_ZP_Y_WB(v) uint16_t addr = EA_IND_ZP_Y; v = regs->RdMem(addr)
81 #define READ_IND_ZP_WB(v) uint16_t addr = EA_IND_ZP; v = regs->RdMem(addr)
83 #define WRITE_BACK(d) regs->WrMem(addr, (d))
86 // Private global variables
88 static V65C02REGS * regs;
91 //This is probably incorrect, at least WRT to the $x7 and $xF opcodes... !!! FIX !!!
92 //Also this doesn't take into account the extra cycle it takes when an indirect
93 //fetch (ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD
95 #warning "Cycle counts are not 100% accurate--!!! FIX !!!"
96 static uint8_t CPUCycles[256] = {
98 7, 6, 1, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1,
99 2, 5, 5, 1, 5, 4, 6, 1, 2, 4, 2, 1, 6, 4, 6, 1,
100 6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 4, 4, 6, 1,
101 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 2, 1, 4, 4, 6, 1,
102 6, 6, 1, 1, 1, 3, 5, 1, 3, 2, 2, 1, 3, 4, 6, 1,
103 2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,
104 6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 6, 4, 6, 1,
105 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 4, 1, 6, 4, 6, 1,
106 2, 6, 1, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,
107 2, 6, 5, 1, 4, 4, 4, 1, 2, 5, 2, 1, 4, 5, 5, 1,
108 2, 6, 2, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,
109 2, 5, 5, 1, 4, 4, 4, 1, 2, 4, 2, 1, 4, 4, 4, 1,
110 2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,
111 2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,
112 2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,
113 2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 4, 1, 1, 4, 6, 1 };
115 7, 6, 2, 2, 5, 3, 5, 2, 3, 2, 2, 2, 6, 4, 6, 2,
116 2, 5, 5, 2, 5, 4, 6, 2, 2, 4, 2, 2, 6, 4, 6, 2,
117 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 4, 2, 6, 2,
118 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 2, 2, 4, 4, 6, 2,
119 6, 6, 2, 2, 3, 3, 5, 2, 3, 2, 2, 2, 3, 4, 6, 2,
120 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 8, 4, 6, 2,
121 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 6, 4, 6, 2,
122 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 6, 4, 6, 2,
123 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
124 2, 6, 5, 2, 4, 4, 4, 2, 2, 5, 2, 2, 4, 5, 5, 2,
125 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
126 2, 5, 5, 2, 4, 4, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2,
127 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 5, 2,
128 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 4, 4, 6, 2,
129 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 6, 2,
130 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 };
134 static uint8_t _6502Cycles[256] = {
135 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6,
136 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
137 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 2, 6, 6,
138 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
139 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6,
140 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
141 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 6, 4, 6, 6,
142 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
143 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,
144 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5,
145 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,
146 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4,
147 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 5, 6,
148 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
149 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,
150 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7 };
152 static uint8_t _65C02Cycles[256] = {
153 7, 6, 2, 2, 5, 3, 5, 2, 3, 2, 2, 2, 6, 4, 6, 2,
154 2, 5, 5, 2, 5, 4, 6, 2, 2, 4, 2, 2, 6, 4, 6, 2,
155 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 4, 2, 6, 2,
156 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 2, 2, 4, 4, 6, 2,
157 6, 6, 2, 2, 3, 3, 5, 2, 3, 2, 2, 2, 3, 4, 6, 2,
158 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 8, 4, 6, 2,
159 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 6, 4, 6, 2,
160 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 6, 4, 6, 2,
161 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
162 2, 6, 5, 2, 4, 4, 4, 2, 2, 5, 2, 2, 4, 5, 5, 2,
163 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
164 2, 5, 5, 2, 4, 4, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2,
165 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 5, 2,
166 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 4, 4, 6, 2,
167 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 6, 2,
168 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 };
173 6502 cycles (includes illegal opcodes):
175 case 0x00: BRK CYC(7) break;
176 case 0x01: INDX ORA CYC(6) break;
177 case 0x02: INV HLT CYC(2) break;
178 case 0x03: INV INDX ASO CYC(8) break;
179 case 0x04: INV ZPG NOP CYC(3) break;
180 case 0x05: ZPG ORA CYC(3) break;
181 case 0x06: ZPG ASL_NMOS CYC(5) break;
182 case 0x07: INV ZPG ASO CYC(5) break;
183 case 0x08: PHP CYC(3) break;
184 case 0x09: IMM ORA CYC(2) break;
185 case 0x0A: ASLA CYC(2) break;
186 case 0x0B: INV IMM ANC CYC(2) break;
187 case 0x0C: INV ABSX NOP CYC(4) break;
188 case 0x0D: ABS ORA CYC(4) break;
189 case 0x0E: ABS ASL_NMOS CYC(6) break;
190 case 0x0F: INV ABS ASO CYC(6) break;
191 case 0x10: REL BPL CYC(2) break;
192 case 0x11: INDY ORA CYC(5) break;
193 case 0x12: INV HLT CYC(2) break;
194 case 0x13: INV INDY ASO CYC(8) break;
195 case 0x14: INV ZPGX NOP CYC(4) break;
196 case 0x15: ZPGX ORA CYC(4) break;
197 case 0x16: ZPGX ASL_NMOS CYC(6) break;
198 case 0x17: INV ZPGX ASO CYC(6) break;
199 case 0x18: CLC CYC(2) break;
200 case 0x19: ABSY ORA CYC(4) break;
201 case 0x1A: INV NOP CYC(2) break;
202 case 0x1B: INV ABSY ASO CYC(7) break;
203 case 0x1C: INV ABSX NOP CYC(4) break;
204 case 0x1D: ABSX ORA CYC(4) break;
205 case 0x1E: ABSX ASL_NMOS CYC(6) break;
206 case 0x1F: INV ABSX ASO CYC(7) break;
207 case 0x20: ABS JSR CYC(6) break;
208 case 0x21: INDX AND CYC(6) break;
209 case 0x22: INV HLT CYC(2) break;
210 case 0x23: INV INDX RLA CYC(8) break;
211 case 0x24: ZPG BIT CYC(3) break;
212 case 0x25: ZPG AND CYC(3) break;
213 case 0x26: ZPG ROL_NMOS CYC(5) break;
214 case 0x27: INV ZPG RLA CYC(5) break;
215 case 0x28: PLP CYC(4) break;
216 case 0x29: IMM AND CYC(2) break;
217 case 0x2A: ROLA CYC(2) break;
218 case 0x2B: INV IMM ANC CYC(2) break;
219 case 0x2C: ABS BIT CYC(4) break;
220 case 0x2D: ABS AND CYC(2) break;
221 case 0x2E: ABS ROL_NMOS CYC(6) break;
222 case 0x2F: INV ABS RLA CYC(6) break;
223 case 0x30: REL BMI CYC(2) break;
224 case 0x31: INDY AND CYC(5) break;
225 case 0x32: INV HLT CYC(2) break;
226 case 0x33: INV INDY RLA CYC(8) break;
227 case 0x34: INV ZPGX NOP CYC(4) break;
228 case 0x35: ZPGX AND CYC(4) break;
229 case 0x36: ZPGX ROL_NMOS CYC(6) break;
230 case 0x37: INV ZPGX RLA CYC(6) break;
231 case 0x38: SEC CYC(2) break;
232 case 0x39: ABSY AND CYC(4) break;
233 case 0x3A: INV NOP CYC(2) break;
234 case 0x3B: INV ABSY RLA CYC(7) break;
235 case 0x3C: INV ABSX NOP CYC(4) break;
236 case 0x3D: ABSX AND CYC(4) break;
237 case 0x3E: ABSX ROL_NMOS CYC(6) break;
238 case 0x3F: INV ABSX RLA CYC(7) break;
239 case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
240 case 0x41: INDX EOR CYC(6) break;
241 case 0x42: INV HLT CYC(2) break;
242 case 0x43: INV INDX LSE CYC(8) break;
243 case 0x44: INV ZPG NOP CYC(3) break;
244 case 0x45: ZPG EOR CYC(3) break;
245 case 0x46: ZPG LSR_NMOS CYC(5) break;
246 case 0x47: INV ZPG LSE CYC(5) break;
247 case 0x48: PHA CYC(3) break;
248 case 0x49: IMM EOR CYC(2) break;
249 case 0x4A: LSRA CYC(2) break;
250 case 0x4B: INV IMM ALR CYC(2) break;
251 case 0x4C: ABS JMP CYC(3) break;
252 case 0x4D: ABS EOR CYC(4) break;
253 case 0x4E: ABS LSR_NMOS CYC(6) break;
254 case 0x4F: INV ABS LSE CYC(6) break;
255 case 0x50: REL BVC CYC(2) break;
256 case 0x51: INDY EOR CYC(5) break;
257 case 0x52: INV HLT CYC(2) break;
258 case 0x53: INV INDY LSE CYC(8) break;
259 case 0x54: INV ZPGX NOP CYC(4) break;
260 case 0x55: ZPGX EOR CYC(4) break;
261 case 0x56: ZPGX LSR_NMOS CYC(6) break;
262 case 0x57: INV ZPGX LSE CYC(6) break;
263 case 0x58: CLI CYC(2) break;
264 case 0x59: ABSY EOR CYC(4) break;
265 case 0x5A: INV NOP CYC(2) break;
266 case 0x5B: INV ABSY LSE CYC(7) break;
267 case 0x5C: INV ABSX NOP CYC(4) break;
268 case 0x5D: ABSX EOR CYC(4) break;
269 case 0x5E: ABSX LSR_NMOS CYC(6) break;
270 case 0x5F: INV ABSX LSE CYC(7) break;
271 case 0x60: RTS CYC(6) break;
272 case 0x61: INDX ADC_NMOS CYC(6) break;
273 case 0x62: INV HLT CYC(2) break;
274 case 0x63: INV INDX RRA CYC(8) break;
275 case 0x64: INV ZPG NOP CYC(3) break;
276 case 0x65: ZPG ADC_NMOS CYC(3) break;
277 case 0x66: ZPG ROR_NMOS CYC(5) break;
278 case 0x67: INV ZPG RRA CYC(5) break;
279 case 0x68: PLA CYC(4) break;
280 case 0x69: IMM ADC_NMOS CYC(2) break;
281 case 0x6A: RORA CYC(2) break;
282 case 0x6B: INV IMM ARR CYC(2) break;
283 case 0x6C: IABSNMOS JMP CYC(6) break;
284 case 0x6D: ABS ADC_NMOS CYC(4) break;
285 case 0x6E: ABS ROR_NMOS CYC(6) break;
286 case 0x6F: INV ABS RRA CYC(6) break;
287 case 0x70: REL BVS CYC(2) break;
288 case 0x71: INDY ADC_NMOS CYC(5) break;
289 case 0x72: INV HLT CYC(2) break;
290 case 0x73: INV INDY RRA CYC(8) break;
291 case 0x74: INV ZPGX NOP CYC(4) break;
292 case 0x75: ZPGX ADC_NMOS CYC(4) break;
293 case 0x76: ZPGX ROR_NMOS CYC(6) break;
294 case 0x77: INV ZPGX RRA CYC(6) break;
295 case 0x78: SEI CYC(2) break;
296 case 0x79: ABSY ADC_NMOS CYC(4) break;
297 case 0x7A: INV NOP CYC(2) break;
298 case 0x7B: INV ABSY RRA CYC(7) break;
299 case 0x7C: INV ABSX NOP CYC(4) break;
300 case 0x7D: ABSX ADC_NMOS CYC(4) break;
301 case 0x7E: ABSX ROR_NMOS CYC(6) break;
302 case 0x7F: INV ABSX RRA CYC(7) break;
303 case 0x80: INV IMM NOP CYC(2) break;
304 case 0x81: INDX STA CYC(6) break;
305 case 0x82: INV IMM NOP CYC(2) break;
306 case 0x83: INV INDX AXS CYC(6) break;
307 case 0x84: ZPG STY CYC(3) break;
308 case 0x85: ZPG STA CYC(3) break;
309 case 0x86: ZPG STX CYC(3) break;
310 case 0x87: INV ZPG AXS CYC(3) break;
311 case 0x88: DEY CYC(2) break;
312 case 0x89: INV IMM NOP CYC(2) break;
313 case 0x8A: TXA CYC(2) break;
314 case 0x8B: INV IMM XAA CYC(2) break;
315 case 0x8C: ABS STY CYC(4) break;
316 case 0x8D: ABS STA CYC(4) break;
317 case 0x8E: ABS STX CYC(4) break;
318 case 0x8F: INV ABS AXS CYC(4) break;
319 case 0x90: REL BCC CYC(2) break;
320 case 0x91: INDY STA CYC(6) break;
321 case 0x92: INV HLT CYC(2) break;
322 case 0x93: INV INDY AXA CYC(6) break;
323 case 0x94: ZPGX STY CYC(4) break;
324 case 0x95: ZPGX STA CYC(4) break;
325 case 0x96: ZPGY STX CYC(4) break;
326 case 0x97: INV ZPGY AXS CYC(4) break;
327 case 0x98: TYA CYC(2) break;
328 case 0x99: ABSY STA CYC(5) break;
329 case 0x9A: TXS CYC(2) break;
330 case 0x9B: INV ABSY TAS CYC(5) break;
331 case 0x9C: INV ABSX SAY CYC(5) break;
332 case 0x9D: ABSX STA CYC(5) break;
333 case 0x9E: INV ABSY XAS CYC(5) break;
334 case 0x9F: INV ABSY AXA CYC(5) break;
335 case 0xA0: IMM LDY CYC(2) break;
336 case 0xA1: INDX LDA CYC(6) break;
337 case 0xA2: IMM LDX CYC(2) break;
338 case 0xA3: INV INDX LAX CYC(6) break;
339 case 0xA4: ZPG LDY CYC(3) break;
340 case 0xA5: ZPG LDA CYC(3) break;
341 case 0xA6: ZPG LDX CYC(3) break;
342 case 0xA7: INV ZPG LAX CYC(3) break;
343 case 0xA8: TAY CYC(2) break;
344 case 0xA9: IMM LDA CYC(2) break;
345 case 0xAA: TAX CYC(2) break;
346 case 0xAB: INV IMM OAL CYC(2) break;
347 case 0xAC: ABS LDY CYC(4) break;
348 case 0xAD: ABS LDA CYC(4) break;
349 case 0xAE: ABS LDX CYC(4) break;
350 case 0xAF: INV ABS LAX CYC(4) break;
351 case 0xB0: REL BCS CYC(2) break;
352 case 0xB1: INDY LDA CYC(5) break;
353 case 0xB2: INV HLT CYC(2) break;
354 case 0xB3: INV INDY LAX CYC(5) break;
355 case 0xB4: ZPGX LDY CYC(4) break;
356 case 0xB5: ZPGX LDA CYC(4) break;
357 case 0xB6: ZPGY LDX CYC(4) break;
358 case 0xB7: INV ZPGY LAX CYC(4) break;
359 case 0xB8: CLV CYC(2) break;
360 case 0xB9: ABSY LDA CYC(4) break;
361 case 0xBA: TSX CYC(2) break;
362 case 0xBB: INV ABSY LAS CYC(4) break;
363 case 0xBC: ABSX LDY CYC(4) break;
364 case 0xBD: ABSX LDA CYC(4) break;
365 case 0xBE: ABSY LDX CYC(4) break;
366 case 0xBF: INV ABSY LAX CYC(4) break;
367 case 0xC0: IMM CPY CYC(2) break;
368 case 0xC1: INDX CMP CYC(6) break;
369 case 0xC2: INV IMM NOP CYC(2) break;
370 case 0xC3: INV INDX DCM CYC(8) break;
371 case 0xC4: ZPG CPY CYC(3) break;
372 case 0xC5: ZPG CMP CYC(3) break;
373 case 0xC6: ZPG DEC_NMOS CYC(5) break;
374 case 0xC7: INV ZPG DCM CYC(5) break;
375 case 0xC8: INY CYC(2) break;
376 case 0xC9: IMM CMP CYC(2) break;
377 case 0xCA: DEX CYC(2) break;
378 case 0xCB: INV IMM SAX CYC(2) break;
379 case 0xCC: ABS CPY CYC(4) break;
380 case 0xCD: ABS CMP CYC(4) break;
381 case 0xCE: ABS DEC_NMOS CYC(5) break;
382 case 0xCF: INV ABS DCM CYC(6) break;
383 case 0xD0: REL BNE CYC(2) break;
384 case 0xD1: INDY CMP CYC(5) break;
385 case 0xD2: INV HLT CYC(2) break;
386 case 0xD3: INV INDY DCM CYC(8) break;
387 case 0xD4: INV ZPGX NOP CYC(4) break;
388 case 0xD5: ZPGX CMP CYC(4) break;
389 case 0xD6: ZPGX DEC_NMOS CYC(6) break;
390 case 0xD7: INV ZPGX DCM CYC(6) break;
391 case 0xD8: CLD CYC(2) break;
392 case 0xD9: ABSY CMP CYC(4) break;
393 case 0xDA: INV NOP CYC(2) break;
394 case 0xDB: INV ABSY DCM CYC(7) break;
395 case 0xDC: INV ABSX NOP CYC(4) break;
396 case 0xDD: ABSX CMP CYC(4) break;
397 case 0xDE: ABSX DEC_NMOS CYC(6) break;
398 case 0xDF: INV ABSX DCM CYC(7) break;
399 case 0xE0: IMM CPX CYC(2) break;
400 case 0xE1: INDX SBC_NMOS CYC(6) break;
401 case 0xE2: INV IMM NOP CYC(2) break;
402 case 0xE3: INV INDX INS CYC(8) break;
403 case 0xE4: ZPG CPX CYC(3) break;
404 case 0xE5: ZPG SBC_NMOS CYC(3) break;
405 case 0xE6: ZPG INC_NMOS CYC(5) break;
406 case 0xE7: INV ZPG INS CYC(5) break;
407 case 0xE8: INX CYC(2) break;
408 case 0xE9: IMM SBC_NMOS CYC(2) break;
409 case 0xEA: NOP CYC(2) break;
410 case 0xEB: INV IMM SBC_NMOS CYC(2) break;
411 case 0xEC: ABS CPX CYC(4) break;
412 case 0xED: ABS SBC_NMOS CYC(4) break;
413 case 0xEE: ABS INC_NMOS CYC(6) break;
414 case 0xEF: INV ABS INS CYC(6) break;
415 case 0xF0: REL BEQ CYC(2) break;
416 case 0xF1: INDY SBC_NMOS CYC(5) break;
417 case 0xF2: INV HLT CYC(2) break;
418 case 0xF3: INV INDY INS CYC(8) break;
419 case 0xF4: INV ZPGX NOP CYC(4) break;
420 case 0xF5: ZPGX SBC_NMOS CYC(4) break;
421 case 0xF6: ZPGX INC_NMOS CYC(6) break;
422 case 0xF7: INV ZPGX INS CYC(6) break;
423 case 0xF8: SED CYC(2) break;
424 case 0xF9: ABSY SBC_NMOS CYC(4) break;
425 case 0xFA: INV NOP CYC(2) break;
426 case 0xFB: INV ABSY INS CYC(7) break;
427 case 0xFC: INV ABSX NOP CYC(4) break;
428 case 0xFD: ABSX SBC_NMOS CYC(4) break;
429 case 0xFE: ABSX INC_NMOS CYC(6) break;
430 case 0xFF: INV ABSX INS CYC(7) break;
433 65C02 opcodes: (all illegal are NOP, but have cycle counts)
435 case 0x00: BRK CYC(7) break;
436 case 0x01: INDX ORA CYC(6) break;
437 case 0x02: INV IMM NOP CYC(2) break;
438 case 0x03: INV NOP CYC(2) break;
439 case 0x04: ZPG TSB CYC(5) break;
440 case 0x05: ZPG ORA CYC(3) break;
441 case 0x06: ZPG ASL_CMOS CYC(5) break;
442 case 0x07: INV NOP CYC(2) break;
443 case 0x08: PHP CYC(3) break;
444 case 0x09: IMM ORA CYC(2) break;
445 case 0x0A: ASLA CYC(2) break;
446 case 0x0B: INV NOP CYC(2) break;
447 case 0x0C: ABS TSB CYC(6) break;
448 case 0x0D: ABS ORA CYC(4) break;
449 case 0x0E: ABS ASL_CMOS CYC(6) break;
450 case 0x0F: INV NOP CYC(2) break;
451 case 0x10: REL BPL CYC(2) break;
452 case 0x11: INDY ORA CYC(5) break;
453 case 0x12: IZPG ORA CYC(5) break;
454 case 0x13: INV NOP CYC(2) break;
455 case 0x14: ZPG TRB CYC(5) break;
456 case 0x15: ZPGX ORA CYC(4) break;
457 case 0x16: ZPGX ASL_CMOS CYC(6) break;
458 case 0x17: INV NOP CYC(2) break;
459 case 0x18: CLC CYC(2) break;
460 case 0x19: ABSY ORA CYC(4) break;
461 case 0x1A: INA CYC(2) break;
462 case 0x1B: INV NOP CYC(2) break;
463 case 0x1C: ABS TRB CYC(6) break;
464 case 0x1D: ABSX ORA CYC(4) break;
465 case 0x1E: ABSX ASL_CMOS CYC(6) break;
466 case 0x1F: INV NOP CYC(2) break;
467 case 0x20: ABS JSR CYC(6) break;
468 case 0x21: INDX AND CYC(6) break;
469 case 0x22: INV IMM NOP CYC(2) break;
470 case 0x23: INV NOP CYC(2) break;
471 case 0x24: ZPG BIT CYC(3) break;
472 case 0x25: ZPG AND CYC(3) break;
473 case 0x26: ZPG ROL_CMOS CYC(5) break;
474 case 0x27: INV NOP CYC(2) break;
475 case 0x28: PLP CYC(4) break;
476 case 0x29: IMM AND CYC(2) break;
477 case 0x2A: ROLA CYC(2) break;
478 case 0x2B: INV NOP CYC(2) break;
479 case 0x2C: ABS BIT CYC(4) break;
480 case 0x2D: ABS AND CYC(2) break;
481 case 0x2E: ABS ROL_CMOS CYC(6) break;
482 case 0x2F: INV NOP CYC(2) break;
483 case 0x30: REL BMI CYC(2) break;
484 case 0x31: INDY AND CYC(5) break;
485 case 0x32: IZPG AND CYC(5) break;
486 case 0x33: INV NOP CYC(2) break;
487 case 0x34: ZPGX BIT CYC(4) break;
488 case 0x35: ZPGX AND CYC(4) break;
489 case 0x36: ZPGX ROL_CMOS CYC(6) break;
490 case 0x37: INV NOP CYC(2) break;
491 case 0x38: SEC CYC(2) break;
492 case 0x39: ABSY AND CYC(4) break;
493 case 0x3A: DEA CYC(2) break;
494 case 0x3B: INV NOP CYC(2) break;
495 case 0x3C: ABSX BIT CYC(4) break;
496 case 0x3D: ABSX AND CYC(4) break;
497 case 0x3E: ABSX ROL_CMOS CYC(6) break;
498 case 0x3F: INV NOP CYC(2) break;
499 case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
500 case 0x41: INDX EOR CYC(6) break;
501 case 0x42: INV IMM NOP CYC(2) break;
502 case 0x43: INV NOP CYC(2) break;
503 case 0x44: INV ZPG NOP CYC(3) break;
504 case 0x45: ZPG EOR CYC(3) break;
505 case 0x46: ZPG LSR_CMOS CYC(5) break;
506 case 0x47: INV NOP CYC(2) break;
507 case 0x48: PHA CYC(3) break;
508 case 0x49: IMM EOR CYC(2) break;
509 case 0x4A: LSRA CYC(2) break;
510 case 0x4B: INV NOP CYC(2) break;
511 case 0x4C: ABS JMP CYC(3) break;
512 case 0x4D: ABS EOR CYC(4) break;
513 case 0x4E: ABS LSR_CMOS CYC(6) break;
514 case 0x4F: INV NOP CYC(2) break;
515 case 0x50: REL BVC CYC(2) break;
516 case 0x51: INDY EOR CYC(5) break;
517 case 0x52: IZPG EOR CYC(5) break;
518 case 0x53: INV NOP CYC(2) break;
519 case 0x54: INV ZPGX NOP CYC(4) break;
520 case 0x55: ZPGX EOR CYC(4) break;
521 case 0x56: ZPGX LSR_CMOS CYC(6) break;
522 case 0x57: INV NOP CYC(2) break;
523 case 0x58: CLI CYC(2) break;
524 case 0x59: ABSY EOR CYC(4) break;
525 case 0x5A: PHY CYC(3) break;
526 case 0x5B: INV NOP CYC(2) break;
527 case 0x5C: INV ABSX NOP CYC(8) break;
528 case 0x5D: ABSX EOR CYC(4) break;
529 case 0x5E: ABSX LSR_CMOS CYC(6) break;
530 case 0x5F: INV NOP CYC(2) break;
531 case 0x60: RTS CYC(6) break;
532 case 0x61: INDX ADC_CMOS CYC(6) break;
533 case 0x62: INV IMM NOP CYC(2) break;
534 case 0x63: INV NOP CYC(2) break;
535 case 0x64: ZPG STZ CYC(3) break;
536 case 0x65: ZPG ADC_CMOS CYC(3) break;
537 case 0x66: ZPG ROR_CMOS CYC(5) break;
538 case 0x67: INV NOP CYC(2) break;
539 case 0x68: PLA CYC(4) break;
540 case 0x69: IMM ADC_CMOS CYC(2) break;
541 case 0x6A: RORA CYC(2) break;
542 case 0x6B: INV NOP CYC(2) break;
543 case 0x6C: IABSCMOS JMP CYC(6) break;
544 case 0x6D: ABS ADC_CMOS CYC(4) break;
545 case 0x6E: ABS ROR_CMOS CYC(6) break;
546 case 0x6F: INV NOP CYC(2) break;
547 case 0x70: REL BVS CYC(2) break;
548 case 0x71: INDY ADC_CMOS CYC(5) break;
549 case 0x72: IZPG ADC_CMOS CYC(5) break;
550 case 0x73: INV NOP CYC(2) break;
551 case 0x74: ZPGX STZ CYC(4) break;
552 case 0x75: ZPGX ADC_CMOS CYC(4) break;
553 case 0x76: ZPGX ROR_CMOS CYC(6) break;
554 case 0x77: INV NOP CYC(2) break;
555 case 0x78: SEI CYC(2) break;
556 case 0x79: ABSY ADC_CMOS CYC(4) break;
557 case 0x7A: PLY CYC(4) break;
558 case 0x7B: INV NOP CYC(2) break;
559 case 0x7C: IABSX JMP CYC(6) break;
560 case 0x7D: ABSX ADC_CMOS CYC(4) break;
561 case 0x7E: ABSX ROR_CMOS CYC(6) break;
562 case 0x7F: INV NOP CYC(2) break;
563 case 0x80: REL BRA CYC(2) break;
564 case 0x81: INDX STA CYC(6) break;
565 case 0x82: INV IMM NOP CYC(2) break;
566 case 0x83: INV NOP CYC(2) break;
567 case 0x84: ZPG STY CYC(3) break;
568 case 0x85: ZPG STA CYC(3) break;
569 case 0x86: ZPG STX CYC(3) break;
570 case 0x87: INV NOP CYC(2) break;
571 case 0x88: DEY CYC(2) break;
572 case 0x89: IMM BITI CYC(2) break;
573 case 0x8A: TXA CYC(2) break;
574 case 0x8B: INV NOP CYC(2) break;
575 case 0x8C: ABS STY CYC(4) break;
576 case 0x8D: ABS STA CYC(4) break;
577 case 0x8E: ABS STX CYC(4) break;
578 case 0x8F: INV NOP CYC(2) break;
579 case 0x90: REL BCC CYC(2) break;
580 case 0x91: INDY STA CYC(6) break;
581 case 0x92: IZPG STA CYC(5) break;
582 case 0x93: INV NOP CYC(2) break;
583 case 0x94: ZPGX STY CYC(4) break;
584 case 0x95: ZPGX STA CYC(4) break;
585 case 0x96: ZPGY STX CYC(4) break;
586 case 0x97: INV NOP CYC(2) break;
587 case 0x98: TYA CYC(2) break;
588 case 0x99: ABSY STA CYC(5) break;
589 case 0x9A: TXS CYC(2) break;
590 case 0x9B: INV NOP CYC(2) break;
591 case 0x9C: ABS STZ CYC(4) break;
592 case 0x9D: ABSX STA CYC(5) break;
593 case 0x9E: ABSX STZ CYC(5) break;
594 case 0x9F: INV NOP CYC(2) break;
595 case 0xA0: IMM LDY CYC(2) break;
596 case 0xA1: INDX LDA CYC(6) break;
597 case 0xA2: IMM LDX CYC(2) break;
598 case 0xA3: INV NOP CYC(2) break;
599 case 0xA4: ZPG LDY CYC(3) break;
600 case 0xA5: ZPG LDA CYC(3) break;
601 case 0xA6: ZPG LDX CYC(3) break;
602 case 0xA7: INV NOP CYC(2) break;
603 case 0xA8: TAY CYC(2) break;
604 case 0xA9: IMM LDA CYC(2) break;
605 case 0xAA: TAX CYC(2) break;
606 case 0xAB: INV NOP CYC(2) break;
607 case 0xAC: ABS LDY CYC(4) break;
608 case 0xAD: ABS LDA CYC(4) break;
609 case 0xAE: ABS LDX CYC(4) break;
610 case 0xAF: INV NOP CYC(2) break;
611 case 0xB0: REL BCS CYC(2) break;
612 case 0xB1: INDY LDA CYC(5) break;
613 case 0xB2: IZPG LDA CYC(5) break;
614 case 0xB3: INV NOP CYC(2) break;
615 case 0xB4: ZPGX LDY CYC(4) break;
616 case 0xB5: ZPGX LDA CYC(4) break;
617 case 0xB6: ZPGY LDX CYC(4) break;
618 case 0xB7: INV NOP CYC(2) break;
619 case 0xB8: CLV CYC(2) break;
620 case 0xB9: ABSY LDA CYC(4) break;
621 case 0xBA: TSX CYC(2) break;
622 case 0xBB: INV NOP CYC(2) break;
623 case 0xBC: ABSX LDY CYC(4) break;
624 case 0xBD: ABSX LDA CYC(4) break;
625 case 0xBE: ABSY LDX CYC(4) break;
626 case 0xBF: INV NOP CYC(2) break;
627 case 0xC0: IMM CPY CYC(2) break;
628 case 0xC1: INDX CMP CYC(6) break;
629 case 0xC2: INV IMM NOP CYC(2) break;
630 case 0xC3: INV NOP CYC(2) break;
631 case 0xC4: ZPG CPY CYC(3) break;
632 case 0xC5: ZPG CMP CYC(3) break;
633 case 0xC6: ZPG DEC_CMOS CYC(5) break;
634 case 0xC7: INV NOP CYC(2) break;
635 case 0xC8: INY CYC(2) break;
636 case 0xC9: IMM CMP CYC(2) break;
637 case 0xCA: DEX CYC(2) break;
638 case 0xCB: INV NOP CYC(2) break;
639 case 0xCC: ABS CPY CYC(4) break;
640 case 0xCD: ABS CMP CYC(4) break;
641 case 0xCE: ABS DEC_CMOS CYC(5) break;
642 case 0xCF: INV NOP CYC(2) break;
643 case 0xD0: REL BNE CYC(2) break;
644 case 0xD1: INDY CMP CYC(5) break;
645 case 0xD2: IZPG CMP CYC(5) break;
646 case 0xD3: INV NOP CYC(2) break;
647 case 0xD4: INV ZPGX NOP CYC(4) break;
648 case 0xD5: ZPGX CMP CYC(4) break;
649 case 0xD6: ZPGX DEC_CMOS CYC(6) break;
650 case 0xD7: INV NOP CYC(2) break;
651 case 0xD8: CLD CYC(2) break;
652 case 0xD9: ABSY CMP CYC(4) break;
653 case 0xDA: PHX CYC(3) break;
654 case 0xDB: INV NOP CYC(2) break;
655 case 0xDC: INV ABSX NOP CYC(4) break;
656 case 0xDD: ABSX CMP CYC(4) break;
657 case 0xDE: ABSX DEC_CMOS CYC(6) break;
658 case 0xDF: INV NOP CYC(2) break;
659 case 0xE0: IMM CPX CYC(2) break;
660 case 0xE1: INDX SBC_CMOS CYC(6) break;
661 case 0xE2: INV IMM NOP CYC(2) break;
662 case 0xE3: INV NOP CYC(2) break;
663 case 0xE4: ZPG CPX CYC(3) break;
664 case 0xE5: ZPG SBC_CMOS CYC(3) break;
665 case 0xE6: ZPG INC_CMOS CYC(5) break;
666 case 0xE7: INV NOP CYC(2) break;
667 case 0xE8: INX CYC(2) break;
668 case 0xE9: IMM SBC_CMOS CYC(2) break;
669 case 0xEA: NOP CYC(2) break;
670 case 0xEB: INV NOP CYC(2) break;
671 case 0xEC: ABS CPX CYC(4) break;
672 case 0xED: ABS SBC_CMOS CYC(4) break;
673 case 0xEE: ABS INC_CMOS CYC(6) break;
674 case 0xEF: INV NOP CYC(2) break;
675 case 0xF0: REL BEQ CYC(2) break;
676 case 0xF1: INDY SBC_CMOS CYC(5) break;
677 case 0xF2: IZPG SBC_CMOS CYC(5) break;
678 case 0xF3: INV NOP CYC(2) break;
679 case 0xF4: INV ZPGX NOP CYC(4) break;
680 case 0xF5: ZPGX SBC_CMOS CYC(4) break;
681 case 0xF6: ZPGX INC_CMOS CYC(6) break;
682 case 0xF7: INV NOP CYC(2) break;
683 case 0xF8: SED CYC(2) break;
684 case 0xF9: ABSY SBC_CMOS CYC(4) break;
685 case 0xFA: PLX CYC(4) break;
686 case 0xFB: INV NOP CYC(2) break;
687 case 0xFC: INV ABSX NOP CYC(4) break;
688 case 0xFD: ABSX SBC_CMOS CYC(4) break;
689 case 0xFE: ABSX INC_CMOS CYC(6) break;
690 case 0xFF: INV NOP CYC(2) break;
695 // Read a uint16_t out of 65C02 memory (big endian format)
697 static inline uint16_t RdMemW(uint16_t address)
699 return (uint16_t)(regs->RdMem(address + 1) << 8) | regs->RdMem(address + 0);
704 // Read a uint16_t out of 65C02 memory (big endian format) and increment PC
706 static inline uint16_t FetchMemW(uint16_t address)
709 return (uint16_t)(regs->RdMem(address + 1) << 8) | regs->RdMem(address + 0);
714 // 65C02 OPCODE IMPLEMENTATION
716 // NOTE: Lots of macros are used here to save a LOT of typing. Also
717 // helps speed the debugging process. :-) Because of this, combining
718 // certain lines may look like a good idea but would end in disaster.
719 // You have been warned! ;-)
723 Mnemonic Addressing mode Form Opcode Size Timing
725 ADC Immediate ADC #Oper 69 2 2
726 Zero Page ADC Zpg 65 2 3
727 Zero Page,X ADC Zpg,X 75 2 4
728 Absolute ADC Abs 6D 3 4
729 Absolute,X ADC Abs,X 7D 3 4
730 Absolute,Y ADC Abs,Y 79 3 4
731 (Zero Page,X) ADC (Zpg,X) 61 2 6
732 (Zero Page),Y ADC (Zpg),Y 71 2 5
733 (Zero Page) ADC (Zpg) 72 2 5
738 //This is non-optimal, but it works--optimize later. :-)
739 #define OP_ADC_HANDLER(m) \
740 uint16_t sum = (uint16_t)regs->a + (m) + (uint16_t)(regs->cc & FLAG_C); \
742 if (regs->cc & FLAG_D) \
744 if ((sum & 0x0F) > 0x09) \
747 if ((sum & 0xF0) > 0x90) \
751 regs->cc = (regs->cc & ~FLAG_C) | (sum >> 8); \
752 regs->cc = (~(regs->a ^ (m)) & (regs->a ^ sum) & 0x80 ? regs->cc | FLAG_V : regs->cc & ~FLAG_V); \
753 regs->a = sum & 0xFF; \
756 static void Op69(void) // ADC #
758 uint16_t m = READ_IMM;
762 static void Op65(void) // ADC ZP
764 uint16_t m = READ_ZP;
768 static void Op75(void) // ADC ZP, X
770 uint16_t m = READ_ZP_X;
774 static void Op6D(void) // ADC ABS
776 uint16_t m = READ_ABS;
780 static void Op7D(void) // ADC ABS, X
782 uint16_t m = READ_ABS_X;
786 static void Op79(void) // ADC ABS, Y
788 uint16_t m = READ_ABS_Y;
792 static void Op61(void) // ADC (ZP, X)
794 uint16_t m = READ_IND_ZP_X;
798 static void Op71(void) // ADC (ZP), Y
800 uint16_t m = READ_IND_ZP_Y;
804 static void Op72(void) // ADC (ZP)
806 uint16_t m = READ_IND_ZP;
811 AND Immediate AND #Oper 29 2 2
812 Zero Page AND Zpg 25 2 3
813 Zero Page,X AND Zpg,X 35 2 4
814 Absolute AND Abs 2D 3 4
815 Absolute,X AND Abs,X 3D 3 4
816 Absolute,Y AND Abs,Y 39 3 4
817 (Zero Page,X) AND (Zpg,X) 21 2 6
818 (Zero Page),Y AND (Zpg),Y 31 2 5
819 (Zero Page) AND (Zpg) 32 2 5
824 #define OP_AND_HANDLER(m) \
828 static void Op29(void) // AND #
830 uint8_t m = READ_IMM;
834 static void Op25(void) // AND ZP
840 static void Op35(void) // AND ZP, X
842 uint8_t m = READ_ZP_X;
846 static void Op2D(void) // AND ABS
848 uint8_t m = READ_ABS;
852 static void Op3D(void) // AND ABS, X
854 uint8_t m = READ_ABS_X;
858 static void Op39(void) // AND ABS, Y
860 uint8_t m = READ_ABS_Y;
864 static void Op21(void) // AND (ZP, X)
866 uint8_t m = READ_IND_ZP_X;
870 static void Op31(void) // AND (ZP), Y
872 uint8_t m = READ_IND_ZP_Y;
876 static void Op32(void) // AND (ZP)
878 uint8_t m = READ_IND_ZP;
883 ASL Accumulator ASL A 0A 1 2
884 Zero Page ASL Zpg 06 2 5
885 Zero Page,X ASL Zpg,X 16 2 6
886 Absolute ASL Abs 0E 3 6
887 Absolute,X ASL Abs,X 1E 3 7
892 #define OP_ASL_HANDLER(m) \
893 regs->cc = ((m) & 0x80 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
897 static void Op0A(void) // ASL A
899 OP_ASL_HANDLER(regs->a);
902 static void Op06(void) // ASL ZP
910 static void Op16(void) // ASL ZP, X
918 static void Op0E(void) // ASL ABS
926 static void Op1E(void) // ASL ABS, X
935 BBR0 Relative BBR0 Oper 0F 2 2
936 BBR1 Relative BBR1 Oper 1F 2 2
937 BBR2 Relative BBR2 Oper 2F 2 2
938 BBR3 Relative BBR3 Oper 3F 2 2
939 BBR4 Relative BBR4 Oper 4F 2 2
940 BBR5 Relative BBR5 Oper 5F 2 2
941 BBR6 Relative BBR6 Oper 6F 2 2
942 BBR7 Relative BBR7 Oper 7F 2 2
943 BBS0 Relative BBS0 Oper 8F 2 2
944 BBS1 Relative BBS1 Oper 9F 2 2
945 BBS2 Relative BBS2 Oper AF 2 2
946 BBS3 Relative BBS3 Oper BF 2 2
947 BBS4 Relative BBS4 Oper CF 2 2
948 BBS5 Relative BBS5 Oper DF 2 2
949 BBS6 Relative BBS6 Oper EF 2 2
950 BBS7 Relative BBS7 Oper FF 2 2
955 static void Op0F(void) // BBR0
957 int16_t m = (int16_t)(int8_t)READ_IMM;
959 if (!(regs->a & 0x01))
963 static void Op1F(void) // BBR1
965 int16_t m = (int16_t)(int8_t)READ_IMM;
967 if (!(regs->a & 0x02))
971 static void Op2F(void) // BBR2
973 int16_t m = (int16_t)(int8_t)READ_IMM;
975 if (!(regs->a & 0x04))
979 static void Op3F(void) // BBR3
981 int16_t m = (int16_t)(int8_t)READ_IMM;
983 if (!(regs->a & 0x08))
987 static void Op4F(void) // BBR4
989 int16_t m = (int16_t)(int8_t)READ_IMM;
991 if (!(regs->a & 0x10))
995 static void Op5F(void) // BBR5
997 int16_t m = (int16_t)(int8_t)READ_IMM;
999 if (!(regs->a & 0x20))
1003 static void Op6F(void) // BBR6
1005 int16_t m = (int16_t)(int8_t)READ_IMM;
1007 if (!(regs->a & 0x40))
1011 static void Op7F(void) // BBR7
1013 int16_t m = (int16_t)(int8_t)READ_IMM;
1015 if (!(regs->a & 0x80))
1019 static void Op8F(void) // BBS0
1021 int16_t m = (int16_t)(int8_t)READ_IMM;
1027 static void Op9F(void) // BBS1
1029 int16_t m = (int16_t)(int8_t)READ_IMM;
1035 static void OpAF(void) // BBS2
1037 int16_t m = (int16_t)(int8_t)READ_IMM;
1043 static void OpBF(void) // BBS3
1045 int16_t m = (int16_t)(int8_t)READ_IMM;
1051 static void OpCF(void) // BBS4
1053 int16_t m = (int16_t)(int8_t)READ_IMM;
1059 static void OpDF(void) // BBS5
1061 int16_t m = (int16_t)(int8_t)READ_IMM;
1067 static void OpEF(void) // BBS6
1069 int16_t m = (int16_t)(int8_t)READ_IMM;
1075 static void OpFF(void) // BBS7
1077 int16_t m = (int16_t)(int8_t)READ_IMM;
1084 BCC Relative BCC Oper 90 2 2
1085 BCS Relative BCS Oper B0 2 2
1086 BEQ Relative BEQ Oper F0 2 2
1089 // Branch taken adds a cycle, crossing page adds one more
1091 #define HANDLE_BRANCH_TAKEN(m) \
1093 uint16_t oldpc = regs->pc; \
1097 if ((oldpc ^ regs->pc) & 0xFF00) \
1103 static void Op90(void) // BCC
1105 int16_t m = (int16_t)(int8_t)READ_IMM;
1107 if (!(regs->cc & FLAG_C))
1108 HANDLE_BRANCH_TAKEN(m)
1111 static void OpB0(void) // BCS
1113 int16_t m = (int16_t)(int8_t)READ_IMM;
1115 if (regs->cc & FLAG_C)
1116 HANDLE_BRANCH_TAKEN(m)
1119 static void OpF0(void) // BEQ
1121 int16_t m = (int16_t)(int8_t)READ_IMM;
1123 if (regs->cc & FLAG_Z)
1124 HANDLE_BRANCH_TAKEN(m)
1128 BIT Immediate BIT #Oper 89 2 2
1129 Zero Page BIT Zpg 24 2 3
1130 Zero Page,X BIT Zpg,X 34 2 4
1131 Absolute BIT Abs 2C 3 4
1132 Absolute,X BIT Abs,X 3C 3 4
1137 /* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag
1138 (except in immediate addressing mode where V & N are untouched.) The
1139 accumulator and the operand are ANDed and the Z flag is set
1142 #define OP_BIT_HANDLER(m) \
1143 int8_t result = regs->a & (m); \
1144 regs->cc &= ~(FLAG_N | FLAG_V); \
1145 regs->cc |= ((m) & 0xC0); \
1148 static void Op89(void) // BIT #
1150 int8_t m = READ_IMM;
1151 int8_t result = regs->a & m;
1155 static void Op24(void) // BIT ZP
1161 static void Op34(void) // BIT ZP, X
1163 uint8_t m = READ_ZP_X;
1167 static void Op2C(void) // BIT ABS
1169 uint8_t m = READ_ABS;
1173 static void Op3C(void) // BIT ABS, X
1175 uint8_t m = READ_ABS_X;
1180 BMI Relative BMI Oper 30 2 2
1181 BNE Relative BNE Oper D0 2 2
1182 BPL Relative BPL Oper 10 2 2
1183 BRA Relative BRA Oper 80 2 3
1186 // More branch opcodes
1188 static void Op30(void) // BMI
1190 int16_t m = (int16_t)(int8_t)READ_IMM;
1192 if (regs->cc & FLAG_N)
1193 HANDLE_BRANCH_TAKEN(m)
1196 static void OpD0(void) // BNE
1198 int16_t m = (int16_t)(int8_t)READ_IMM;
1200 if (!(regs->cc & FLAG_Z))
1201 HANDLE_BRANCH_TAKEN(m)
1204 static void Op10(void) // BPL
1206 int16_t m = (int16_t)(int8_t)READ_IMM;
1208 if (!(regs->cc & FLAG_N))
1209 HANDLE_BRANCH_TAKEN(m)
1212 static void Op80(void) // BRA
1214 int16_t m = (int16_t)(int8_t)READ_IMM;
1215 HANDLE_BRANCH_TAKEN(m)
1219 BRK Implied BRK 00 1 7
1222 static void Op00(void) // BRK
1226 WriteLog("\n*** BRK ***\n\n");
1227 WriteLog(" [PC=%04X, SP=%04X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
1228 regs->pc, 0x0100 + regs->sp,
1229 (regs->cc & FLAG_N ? "N" : "-"), (regs->cc & FLAG_V ? "V" : "-"),
1230 (regs->cc & FLAG_B ? "B" : "-"), (regs->cc & FLAG_D ? "D" : "-"),
1231 (regs->cc & FLAG_I ? "I" : "-"), (regs->cc & FLAG_Z ? "Z" : "-"),
1232 (regs->cc & FLAG_C ? "C" : "-"), regs->a, regs->x, regs->y);
1234 regs->cc |= FLAG_B; // Set B
1235 regs->pc++; // RTI comes back to the instruction one byte after the BRK
1236 regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); // Save PC and CC
1237 regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
1238 regs->WrMem(0x0100 + regs->sp--, regs->cc);
1239 regs->cc |= FLAG_I; // Set I
1240 regs->cc &= ~FLAG_D; // & clear D
1241 regs->pc = RdMemW(0xFFFE); // Grab the IRQ vector & go...
1245 BVC Relative BVC Oper 50 2 2
1246 BVS Relative BVS Oper 70 2 2
1249 // Even more branch opcodes
1251 static void Op50(void) // BVC
1253 int16_t m = (int16_t)(int8_t)READ_IMM;
1255 if (!(regs->cc & FLAG_V))
1256 HANDLE_BRANCH_TAKEN(m)
1259 static void Op70(void) // BVS
1261 int16_t m = (int16_t)(int8_t)READ_IMM;
1263 if (regs->cc & FLAG_V)
1264 HANDLE_BRANCH_TAKEN(m)
1268 CLC Implied CLC 18 1 2
1271 static void Op18(void) // CLC
1273 regs->cc &= ~FLAG_C;
1277 CLD Implied CLD D8 1 2
1280 static void OpD8(void) // CLD
1286 CLI Implied CLI 58 1 2
1289 static void Op58(void) // CLI
1291 regs->cc &= ~FLAG_I;
1295 CLV Implied CLV B8 1 2
1298 static void OpB8(void) // CLV
1300 regs->cc &= ~FLAG_V;
1304 CMP Immediate CMP #Oper C9 2 2
1305 Zero Page CMP Zpg C5 2 3
1306 Zero Page,X CMP Zpg D5 2 4
1307 Absolute CMP Abs CD 3 4
1308 Absolute,X CMP Abs,X DD 3 4
1309 Absolute,Y CMP Abs,Y D9 3 4
1310 (Zero Page,X) CMP (Zpg,X) C1 2 6
1311 (Zero Page),Y CMP (Zpg),Y D1 2 5
1312 (Zero Page) CMP (Zpg) D2 2 5
1317 #define OP_CMP_HANDLER(m) \
1318 uint8_t result = regs->a - (m); \
1319 SET_ZNC_CMP(m, regs->a, result)
1321 static void OpC9(void) // CMP #
1323 uint8_t m = READ_IMM;
1327 static void OpC5(void) // CMP ZP
1329 uint8_t m = READ_ZP;
1333 static void OpD5(void) // CMP ZP, X
1335 uint8_t m = READ_ZP_X;
1339 static void OpCD(void) // CMP ABS
1341 uint8_t m = READ_ABS;
1345 static void OpDD(void) // CMP ABS, X
1347 uint8_t m = READ_ABS_X;
1351 static void OpD9(void) // CMP ABS, Y
1353 uint8_t m = READ_ABS_Y;
1357 static void OpC1(void) // CMP (ZP, X)
1359 uint8_t m = READ_IND_ZP_X;
1363 static void OpD1(void) // CMP (ZP), Y
1365 uint8_t m = READ_IND_ZP_Y;
1369 static void OpD2(void) // CMP (ZP)
1371 uint8_t m = READ_IND_ZP;
1376 CPX Immediate CPX #Oper E0 2 2
1377 Zero Page CPX Zpg E4 2 3
1378 Absolute CPX Abs EC 3 4
1383 #define OP_CPX_HANDLER(m) \
1384 uint8_t result = regs->x - (m); \
1385 SET_ZNC_CMP(m, regs->x, result)
1387 static void OpE0(void) // CPX #
1389 uint8_t m = READ_IMM;
1393 static void OpE4(void) // CPX ZP
1395 uint8_t m = READ_ZP;
1399 static void OpEC(void) // CPX ABS
1401 uint8_t m = READ_ABS;
1406 CPY Immediate CPY #Oper C0 2 2
1407 Zero Page CPY Zpg C4 2 3
1408 Absolute CPY Abs CC 3 4
1413 #define OP_CPY_HANDLER(m) \
1414 uint8_t result = regs->y - (m); \
1415 SET_ZNC_CMP(m, regs->y, result)
1417 static void OpC0(void) // CPY #
1419 uint8_t m = READ_IMM;
1423 static void OpC4(void) // CPY ZP
1425 uint8_t m = READ_ZP;
1429 static void OpCC(void) // CPY ABS
1431 uint8_t m = READ_ABS;
1436 DEA Accumulator DEA 3A 1 2
1439 static void Op3A(void) // DEA
1446 DEC Zero Page DEC Zpg C6 2 5
1447 Zero Page,X DEC Zpg,X D6 2 6
1448 Absolute DEC Abs CE 3 6
1449 Absolute,X DEC Abs,X DE 3 7
1454 #define OP_DEC_HANDLER(m) \
1458 static void OpC6(void) // DEC ZP
1466 static void OpD6(void) // DEC ZP, X
1474 static void OpCE(void) // DEC ABS
1482 static void OpDE(void) // DEC ABS, X
1491 DEX Implied DEX CA 1 2
1494 static void OpCA(void) // DEX
1501 DEY Implied DEY 88 1 2
1504 static void Op88(void) // DEY
1511 EOR Immediate EOR #Oper 49 2 2
1512 Zero Page EOR Zpg 45 2 3
1513 Zero Page,X EOR Zpg,X 55 2 4
1514 Absolute EOR Abs 4D 3 4
1515 Absolute,X EOR Abs,X 5D 3 4
1516 Absolute,Y EOR Abs,Y 59 3 4
1517 (Zero Page,X) EOR (Zpg,X) 41 2 6
1518 (Zero Page),Y EOR (Zpg),Y 51 2 5
1519 (Zero Page) EOR (Zpg) 52 2 5
1524 #define OP_EOR_HANDLER(m) \
1528 static void Op49(void) // EOR #
1530 uint8_t m = READ_IMM;
1534 static void Op45(void) // EOR ZP
1536 uint8_t m = READ_ZP;
1540 static void Op55(void) // EOR ZP, X
1542 uint8_t m = READ_ZP_X;
1546 static void Op4D(void) // EOR ABS
1548 uint8_t m = READ_ABS;
1552 static void Op5D(void) // EOR ABS, X
1554 uint8_t m = READ_ABS_X;
1558 static void Op59(void) // EOR ABS, Y
1560 uint8_t m = READ_ABS_Y;
1564 static void Op41(void) // EOR (ZP, X)
1566 uint8_t m = READ_IND_ZP_X;
1570 static void Op51(void) // EOR (ZP), Y
1572 uint8_t m = READ_IND_ZP_Y;
1576 static void Op52(void) // EOR (ZP)
1578 uint8_t m = READ_IND_ZP;
1583 INA Accumulator INA 1A 1 2
1586 static void Op1A(void) // INA
1593 INC Zero Page INC Zpg E6 2 5
1594 Zero Page,X INC Zpg,X F6 2 6
1595 Absolute INC Abs EE 3 6
1596 Absolute,X INC Abs,X FE 3 7
1601 #define OP_INC_HANDLER(m) \
1605 static void OpE6(void) // INC ZP
1613 static void OpF6(void) // INC ZP, X
1621 static void OpEE(void) // INC ABS
1629 static void OpFE(void) // INC ABS, X
1638 INX Implied INX E8 1 2
1641 static void OpE8(void) // INX
1648 INY Implied INY C8 1 2
1651 static void OpC8(void) // INY
1658 JMP Absolute JMP Abs 4C 3 3
1659 (Absolute) JMP (Abs) 6C 3 5
1660 (Absolute,X) JMP (Abs,X) 7C 3 6
1665 static void Op4C(void) // JMP ABS
1667 regs->pc = RdMemW(regs->pc);
1670 static void Op6C(void) // JMP (ABS)
1672 regs->pc = RdMemW(RdMemW(regs->pc));
1675 static void Op7C(void) // JMP (ABS, X)
1677 regs->pc = RdMemW(RdMemW(regs->pc) + regs->x);
1681 JSR Absolute JSR Abs 20 3 6
1684 static void Op20(void) // JSR
1686 uint16_t addr = RdMemW(regs->pc);
1687 regs->pc++; // Since it pushes return address - 1...
1688 regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8);
1689 regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
1694 LDA Immediate LDA #Oper A9 2 2
1695 Zero Page LDA Zpg A5 2 3
1696 Zero Page,X LDA Zpg,X B5 2 4
1697 Absolute LDA Abs AD 3 4
1698 Absolute,X LDA Abs,X BD 3 4
1699 Absolute,Y LDA Abs,Y B9 3 4
1700 (Zero Page,X) LDA (Zpg,X) A1 2 6
1701 (Zero Page),Y LDA (Zpg),Y B1 2 5
1702 (Zero Page) LDA (Zpg) B2 2 5
1707 #define OP_LDA_HANDLER(m) \
1711 static void OpA9(void) // LDA #
1713 uint8_t m = READ_IMM;
1717 static void OpA5(void) // LDA ZP
1719 uint8_t m = READ_ZP;
1723 static void OpB5(void) // LDA ZP, X
1725 uint8_t m = READ_ZP_X;
1729 static void OpAD(void) // LDA ABS
1731 uint8_t m = READ_ABS;
1735 static void OpBD(void) // LDA ABS, X
1737 uint8_t m = READ_ABS_X;
1741 static void OpB9(void) // LDA ABS, Y
1743 uint8_t m = READ_ABS_Y;
1747 static void OpA1(void) // LDA (ZP, X)
1749 uint8_t m = READ_IND_ZP_X;
1753 static void OpB1(void) // LDA (ZP), Y
1755 uint8_t m = READ_IND_ZP_Y;
1759 static void OpB2(void) // LDA (ZP)
1761 uint8_t m = READ_IND_ZP;
1766 LDX Immediate LDX #Oper A2 2 2
1767 Zero Page LDX Zpg A6 2 3
1768 Zero Page,Y LDX Zpg,Y B6 2 4
1769 Absolute LDX Abs AE 3 4
1770 Absolute,Y LDX Abs,Y BE 3 4
1775 #define OP_LDX_HANDLER(m) \
1779 static void OpA2(void) // LDX #
1781 uint8_t m = READ_IMM;
1785 static void OpA6(void) // LDX ZP
1787 uint8_t m = READ_ZP;
1791 static void OpB6(void) // LDX ZP, Y
1793 uint8_t m = READ_ZP_Y;
1797 static void OpAE(void) // LDX ABS
1799 uint8_t m = READ_ABS;
1803 static void OpBE(void) // LDX ABS, Y
1805 uint8_t m = READ_ABS_Y;
1810 LDY Immediate LDY #Oper A0 2 2
1811 Zero Page LDY Zpg A4 2 3
1812 Zero Page,Y LDY Zpg,X B4 2 4
1813 Absolute LDY Abs AC 3 4
1814 Absolute,Y LDY Abs,X BC 3 4
1819 #define OP_LDY_HANDLER(m) \
1823 static void OpA0(void) // LDY #
1825 uint8_t m = READ_IMM;
1829 static void OpA4(void) // LDY ZP
1831 uint8_t m = READ_ZP;
1835 static void OpB4(void) // LDY ZP, X
1837 uint8_t m = READ_ZP_X;
1841 static void OpAC(void) // LDY ABS
1843 uint8_t m = READ_ABS;
1847 static void OpBC(void) // LDY ABS, X
1849 uint8_t m = READ_ABS_X;
1854 LSR Accumulator LSR A 4A 1 2
1855 Zero Page LSR Zpg 46 2 5
1856 Zero Page,X LSR Zpg,X 56 2 6
1857 Absolute LSR Abs 4E 3 6
1858 Absolute,X LSR Abs,X 5E 3 7
1863 #define OP_LSR_HANDLER(m) \
1864 regs->cc = ((m) & 0x01 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
1868 static void Op4A(void) // LSR A
1870 OP_LSR_HANDLER(regs->a);
1873 static void Op46(void) // LSR ZP
1881 static void Op56(void) // LSR ZP, X
1889 static void Op4E(void) // LSR ABS
1897 static void Op5E(void) // LSR ABS, X
1906 NOP Implied NOP EA 1 2
1909 static void OpEA(void) // NOP
1914 ORA Immediate ORA #Oper 09 2 2
1915 Zero Page ORA Zpg 05 2 3
1916 Zero Page,X ORA Zpg,X 15 2 4
1917 Absolute ORA Abs 0D 3 4
1918 Absolute,X ORA Abs,X 1D 3 4
1919 Absolute,Y ORA Abs,Y 19 3 4
1920 (Zero Page,X) ORA (Zpg,X) 01 2 6
1921 (Zero Page),Y ORA (Zpg),Y 11 2 5
1922 (Zero Page) ORA (Zpg) 12 2 5
1927 #define OP_ORA_HANDLER(m) \
1931 static void Op09(void) // ORA #
1933 uint8_t m = READ_IMM;
1937 static void Op05(void) // ORA ZP
1939 uint8_t m = READ_ZP;
1943 static void Op15(void) // ORA ZP, X
1945 uint8_t m = READ_ZP_X;
1949 static void Op0D(void) // ORA ABS
1951 uint8_t m = READ_ABS;
1955 static void Op1D(void) // ORA ABS, X
1957 uint8_t m = READ_ABS_X;
1961 static void Op19(void) // ORA ABS, Y
1963 uint8_t m = READ_ABS_Y;
1967 static void Op01(void) // ORA (ZP, X)
1969 uint8_t m = READ_IND_ZP_X;
1973 static void Op11(void) // ORA (ZP), Y
1975 uint8_t m = READ_IND_ZP_Y;
1979 static void Op12(void) // ORA (ZP)
1981 uint8_t m = READ_IND_ZP;
1986 PHA Implied PHA 48 1 3
1989 static void Op48(void) // PHA
1991 regs->WrMem(0x0100 + regs->sp--, regs->a);
1994 static void Op08(void) // PHP
1996 regs->cc |= FLAG_UNK; // Make sure that the unused bit is always set
1997 regs->WrMem(0x0100 + regs->sp--, regs->cc);
2001 PHX Implied PHX DA 1 3
2004 static void OpDA(void) // PHX
2006 regs->WrMem(0x0100 + regs->sp--, regs->x);
2010 PHY Implied PHY 5A 1 3
2013 static void Op5A(void) // PHY
2015 regs->WrMem(0x0100 + regs->sp--, regs->y);
2019 PLA Implied PLA 68 1 4
2022 static void Op68(void) // PLA
2024 regs->a = regs->RdMem(0x0100 + ++regs->sp);
2028 static void Op28(void) // PLP
2030 regs->cc = regs->RdMem(0x0100 + ++regs->sp);
2034 PLX Implied PLX FA 1 4
2037 static void OpFA(void) // PLX
2039 regs->x = regs->RdMem(0x0100 + ++regs->sp);
2044 PLY Implied PLY 7A 1 4
2047 static void Op7A(void) // PLY
2049 regs->y = regs->RdMem(0x0100 + ++regs->sp);
2054 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
2055 RMB0 RMB1 RMB2 RMB3 RMB4 RMB5 RMB6 RMB7
2056 zp 07 17 27 37 47 57 67 77
2057 SMB0 SMB1 SMB2 SMB3 SMB4 SMB5 SMB6 SMB7
2058 zp 87 97 A7 B7 C7 D7 E7 F7
2063 static void Op07(void) // RMB0 ZP
2071 static void Op17(void) // RMB1 ZP
2079 static void Op27(void) // RMB2 ZP
2087 static void Op37(void) // RMB3 ZP
2095 static void Op47(void) // RMB4 ZP
2103 static void Op57(void) // RMB5 ZP
2111 static void Op67(void) // RMB6 ZP
2119 static void Op77(void) // RMB7 ZP
2128 ROL Accumulator ROL A 2A 1 2
2129 Zero Page ROL Zpg 26 2 5
2130 Zero Page,X ROL Zpg,X 36 2 6
2131 Absolute ROL Abs 2E 3 6
2132 Absolute,X ROL Abs,X 3E 3 7
2137 #define OP_ROL_HANDLER(m) \
2138 uint8_t tmp = regs->cc & 0x01; \
2139 regs->cc = ((m) & 0x80 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
2140 (m) = ((m) << 1) | tmp; \
2143 static void Op2A(void) // ROL A
2145 OP_ROL_HANDLER(regs->a);
2148 static void Op26(void) // ROL ZP
2156 static void Op36(void) // ROL ZP, X
2164 static void Op2E(void) // ROL ABS
2172 static void Op3E(void) // ROL ABS, X
2181 ROR Accumulator ROR A 6A 1 2
2182 Zero Page ROR Zpg 66 2 5
2183 Zero Page,X ROR Zpg,X 76 2 6
2184 Absolute ROR Abs 6E 3 6
2185 Absolute,X ROR Abs,X 7E 3 7
2190 #define OP_ROR_HANDLER(m) \
2191 uint8_t tmp = (regs->cc & 0x01) << 7; \
2192 regs->cc = ((m) & 0x01 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
2193 (m) = ((m) >> 1) | tmp; \
2196 static void Op6A(void) // ROR A
2198 OP_ROR_HANDLER(regs->a);
2201 static void Op66(void) // ROR ZP
2209 static void Op76(void) // ROR ZP, X
2217 static void Op6E(void) // ROR ABS
2225 static void Op7E(void) // ROR ABS, X
2234 RTI Implied RTI 40 1 6
2237 static void Op40(void) // RTI
2239 regs->cc = regs->RdMem(0x0100 + ++regs->sp);
2240 regs->pc = regs->RdMem(0x0100 + ++regs->sp);
2241 regs->pc |= (uint16_t)(regs->RdMem(0x0100 + ++regs->sp)) << 8;
2245 RTS Implied RTS 60 1 6
2248 static void Op60(void) // RTS
2250 regs->pc = regs->RdMem(0x0100 + ++regs->sp);
2251 regs->pc |= (uint16_t)(regs->RdMem(0x0100 + ++regs->sp)) << 8;
2252 regs->pc++; // Since it pushes return address - 1...
2256 SBC Immediate SBC #Oper E9 2 2
2257 Zero Page SBC Zpg E5 2 3
2258 Zero Page,X SBC Zpg,X F5 2 4
2259 Absolute SBC Abs ED 3 4
2260 Absolute,X SBC Abs,X FD 3 4
2261 Absolute,Y SBC Abs,Y F9 3 4
2262 (Zero Page,X) SBC (Zpg,X) E1 2 6
2263 (Zero Page),Y SBC (Zpg),Y F1 2 5
2264 (Zero Page) SBC (Zpg) F2 2 5
2269 //This is non-optimal, but it works--optimize later. :-)
2270 //This is correct except for the BCD handling... !!! FIX !!! [Possibly DONE]
2271 #define OP_SBC_HANDLER(m) \
2272 uint16_t sum = (uint16_t)regs->a - (m) - (uint16_t)((regs->cc & FLAG_C) ^ 0x01); \
2274 if (regs->cc & FLAG_D) \
2276 if ((sum & 0x0F) > 0x09) \
2279 if ((sum & 0xF0) > 0x90) \
2283 regs->cc = (regs->cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \
2284 regs->cc = ((regs->a ^ (m)) & (regs->a ^ sum) & 0x80 ? regs->cc | FLAG_V : regs->cc & ~FLAG_V); \
2285 regs->a = sum & 0xFF; \
2288 static void OpE9(void) // SBC #
2290 uint16_t m = READ_IMM;
2294 static void OpE5(void) // SBC ZP
2296 uint16_t m = READ_ZP;
2300 static void OpF5(void) // SBC ZP, X
2302 uint16_t m = READ_ZP_X;
2306 static void OpED(void) // SBC ABS
2308 uint16_t m = READ_ABS;
2312 static void OpFD(void) // SBC ABS, X
2314 uint16_t m = READ_ABS_X;
2318 static void OpF9(void) // SBC ABS, Y
2320 uint16_t m = READ_ABS_Y;
2324 static void OpE1(void) // SBC (ZP, X)
2326 uint16_t m = READ_IND_ZP_X;
2330 static void OpF1(void) // SBC (ZP), Y
2332 uint16_t m = READ_IND_ZP_Y;
2336 static void OpF2(void) // SBC (ZP)
2338 uint16_t m = READ_IND_ZP;
2343 SEC Implied SEC 38 1 2
2346 static void Op38(void) // SEC
2352 SED Implied SED F8 1 2
2355 static void OpF8(void) // SED
2361 SEI Implied SEI 78 1 2
2364 static void Op78(void) // SEI
2370 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
2371 RMB0 RMB1 RMB2 RMB3 RMB4 RMB5 RMB6 RMB7
2372 zp 07 17 27 37 47 57 67 77
2373 SMB0 SMB1 SMB2 SMB3 SMB4 SMB5 SMB6 SMB7
2374 zp 87 97 A7 B7 C7 D7 E7 F7
2379 static void Op87(void) // SMB0 ZP
2387 static void Op97(void) // SMB1 ZP
2395 static void OpA7(void) // SMB2 ZP
2403 static void OpB7(void) // SMB3 ZP
2411 static void OpC7(void) // SMB4 ZP
2419 static void OpD7(void) // SMB5 ZP
2427 static void OpE7(void) // SMB6 ZP
2435 static void OpF7(void) // SMB7 ZP
2444 STA Zero Page STA Zpg 85 2 3
2445 Zero Page,X STA Zpg,X 95 2 4
2446 Absolute STA Abs 8D 3 4
2447 Absolute,X STA Abs,X 9D 3 5
2448 Absolute,Y STA Abs,Y 99 3 5
2449 (Zero Page,X) STA (Zpg,X) 81 2 6
2450 (Zero Page),Y STA (Zpg),Y 91 2 6
2451 (Zero Page) STA (Zpg) 92 2 5
2456 static void Op85(void)
2458 regs->WrMem(EA_ZP, regs->a);
2461 static void Op95(void)
2463 regs->WrMem(EA_ZP_X, regs->a);
2466 static void Op8D(void)
2468 regs->WrMem(EA_ABS, regs->a);
2471 static void Op9D(void)
2473 regs->WrMem(EA_ABS_X, regs->a);
2476 static void Op99(void)
2478 regs->WrMem(EA_ABS_Y, regs->a);
2481 static void Op81(void)
2483 regs->WrMem(EA_IND_ZP_X, regs->a);
2486 static void Op91(void)
2488 regs->WrMem(EA_IND_ZP_Y, regs->a);
2491 static void Op92(void)
2493 regs->WrMem(EA_IND_ZP, regs->a);
2497 STX Zero Page STX Zpg 86 2 3
2498 Zero Page,Y STX Zpg,Y 96 2 4
2499 Absolute STX Abs 8E 3 4
2504 static void Op86(void)
2506 regs->WrMem(EA_ZP, regs->x);
2509 static void Op96(void)
2511 regs->WrMem(EA_ZP_Y, regs->x);
2514 static void Op8E(void)
2516 regs->WrMem(EA_ABS, regs->x);
2520 STY Zero Page STY Zpg 84 2 3
2521 Zero Page,X STY Zpg,X 94 2 4
2522 Absolute STY Abs 8C 3 4
2527 static void Op84(void)
2529 regs->WrMem(EA_ZP, regs->y);
2532 static void Op94(void)
2534 regs->WrMem(EA_ZP_X, regs->y);
2537 static void Op8C(void)
2539 regs->WrMem(EA_ABS, regs->y);
2543 STZ Zero Page STZ Zpg 64 2 3
2544 Zero Page,X STZ Zpg,X 74 2 4
2545 Absolute STZ Abs 9C 3 4
2546 Absolute,X STZ Abs,X 9E 3 5
2551 static void Op64(void)
2553 regs->WrMem(EA_ZP, 0x00);
2556 static void Op74(void)
2558 regs->WrMem(EA_ZP_X, 0x00);
2561 static void Op9C(void)
2563 regs->WrMem(EA_ABS, 0x00);
2566 static void Op9E(void)
2568 regs->WrMem(EA_ABS_X, 0x00);
2572 TAX Implied TAX AA 1 2
2575 static void OpAA(void) // TAX
2582 TAY Implied TAY A8 1 2
2585 static void OpA8(void) // TAY
2592 TRB Zero Page TRB Zpg 14 2 5
2593 Absolute TRB Abs 1C 3 6
2598 #define OP_TRB_HANDLER(m) \
2599 SET_Z(m & regs->a); \
2602 static void Op14(void) // TRB ZP
2610 static void Op1C(void) // TRB ABS
2619 TSB Zero Page TSB Zpg 04 2 5
2620 Absolute TSB Abs 0C 3 6
2625 #define OP_TSB_HANDLER(m) \
2626 SET_Z(m & regs->a); \
2629 static void Op04(void) // TSB ZP
2637 static void Op0C(void) // TSB ABS
2646 TSX Implied TSX BA 1 2
2649 static void OpBA(void) // TSX
2656 TXA Implied TXA 8A 1 2
2659 static void Op8A(void) // TXA
2666 TXS Implied TXS 9A 1 2
2669 static void Op9A(void) // TXS
2675 TYA Implied TYA 98 1 2
2677 static void Op98(void) // TYA
2683 static void Op__(void)
2685 regs->cpuFlags |= V65C02_STATE_ILLEGAL_INST;
2690 // Ok, the exec_op[] array is globally defined here basically to save
2691 // a LOT of unnecessary typing. Sure it's ugly, but hey, it works!
2693 static void (* exec_op[256])() = {
2694 Op00, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op__, Op0C, Op0D, Op0E, Op0F,
2695 Op10, Op11, Op12, Op__, Op14, Op15, Op16, Op17, Op18, Op19, Op1A, Op__, Op1C, Op1D, Op1E, Op1F,
2696 Op20, Op21, Op__, Op__, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op__, Op2C, Op2D, Op2E, Op2F,
2697 Op30, Op31, Op32, Op__, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op__, Op3C, Op3D, Op3E, Op3F,
2698 Op40, Op41, Op__, Op__, Op__, Op45, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op4E, Op4F,
2699 Op50, Op51, Op52, Op__, Op__, Op55, Op56, Op57, Op58, Op59, Op5A, Op__, Op__, Op5D, Op5E, Op5F,
2700 Op60, Op61, Op__, Op__, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op__, Op6C, Op6D, Op6E, Op6F,
2701 Op70, Op71, Op72, Op__, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op__, Op7C, Op7D, Op7E, Op7F,
2702 Op80, Op81, Op__, Op__, Op84, Op85, Op86, Op87, Op88, Op89, Op8A, Op__, Op8C, Op8D, Op8E, Op8F,
2703 Op90, Op91, Op92, Op__, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op__, Op9C, Op9D, Op9E, Op9F,
2704 OpA0, OpA1, OpA2, Op__, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, Op__, OpAC, OpAD, OpAE, OpAF,
2705 OpB0, OpB1, OpB2, Op__, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, Op__, OpBC, OpBD, OpBE, OpBF,
2706 OpC0, OpC1, Op__, Op__, OpC4, OpC5, OpC6, OpC7, OpC8, OpC9, OpCA, Op__, OpCC, OpCD, OpCE, OpCF,
2707 OpD0, OpD1, OpD2, Op__, Op__, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, Op__, Op__, OpDD, OpDE, OpDF,
2708 OpE0, OpE1, Op__, Op__, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, Op__, OpEC, OpED, OpEE, OpEF,
2709 OpF0, OpF1, OpF2, Op__, Op__, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, Op__, Op__, OpFD, OpFE, OpFF
2714 FCA8: 38 698 WAIT SEC
2715 FCA9: 48 699 WAIT2 PHA
2716 FCAA: E9 01 700 WAIT3 SBC #$01
2717 FCAC: D0 FC 701 BNE WAIT3 ;1.0204 USEC
2718 FCAE: 68 702 PLA ;(13+27/2*A+5/2*A*A)
2719 FCAF: E9 01 703 SBC #$01
2720 FCB1: D0 F6 704 BNE WAIT2
2723 FBD9: C9 87 592 BELL1 CMP #$87 ;BELL CHAR? (CNTRL-G)
2724 FBDB: D0 12 593 BNE RTS2B ; NO, RETURN
2725 FBDD: A9 40 594 LDA #$40 ;DELAY .01 SECONDS
2726 FBDF: 20 A8 FC 595 JSR WAIT
2727 FBE2: A0 C0 596 LDY #$C0
2728 FBE4: A9 0C 597 BELL2 LDA #$0C ;TOGGLE SPEAKER AT
2729 FBE6: 20 A8 FC 598 JSR WAIT ; 1 KHZ FOR .1 SEC.
2730 FBE9: AD 30 C0 599 LDA SPKR
2732 FBED: D0 F5 601 BNE BELL2
2733 FBEF: 60 602 RTS2B RTS
2735 //int instCount[256];
2737 bool dumpDis = false;
2738 //bool dumpDis = true;
2742 On //e, $FCAA is the delay routine. (seems to not have changed from ][+)
2745 #define DO_BACKTRACE
2747 #define BACKTRACE_SIZE 16384
2748 uint32_t btQueuePtr = 0;
2749 V65C02REGS btQueue[BACKTRACE_SIZE];
2750 uint8_t btQueueInst[BACKTRACE_SIZE][4];
2755 // Function to execute 65C02 for "cycles" cycles
2757 void Execute65C02(V65C02REGS * context, uint32_t cycles)
2761 // Calculate number of clock cycles to run for
2762 uint64_t endCycles = regs->clock + (uint64_t)cycles - regs->overflow;
2764 while (regs->clock < endCycles)
2767 static bool weGo = false;
2768 if (regs->pc == 0x80AE)
2773 else if (regs->pc == 0xFCA8 && weGo)
2776 WriteLog("\n*** DELAY (A=$%02X)\n\n", regs->a);
2778 else if (regs->pc == 0xFCB3 && weGo)
2784 /*if (regs->pc == 0x4007)
2788 if (regs->pc == 0x444B)
2790 WriteLog("\n*** End of wait...\n\n");
2793 if (regs->pc == 0x444E)
2795 WriteLog("\n*** Start of wait...\n\n");
2799 /*if (regs->pc >= 0xC600 && regs->pc <=0xC6FF)
2804 dumpDis = false;//*/
2805 /*if (regs->pc == 0xE039)
2811 /*if (regs->pc == 0x0801)
2813 WriteLog("\n*** DISK BOOT subroutine...\n\n");
2816 if (regs->pc == 0xE000)
2819 WriteLog("\n*** Dump of $E000 routine ***\n\n");
2821 for(uint32_t addr=0xE000; addr<0xF000;)
2823 addr += Decode65C02(addr);
2827 WriteLog("\n*** DISK part II subroutine...\n\n");
2830 if (regs->pc == 0xD000)
2832 WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2835 if (regs->pc == 0xD1BE)
2837 // WriteLog("\n*** DISK part II subroutine...\n\n");
2840 if (regs->pc == 0xD200)
2842 WriteLog("\n*** CUSTOM SCREEN subroutine...\n\n");
2845 if (regs->pc == 0xD269)
2847 // WriteLog("\n*** DISK part II subroutine...\n\n");
2851 //if (regs->pc == 0xE08E)
2852 /*if (regs->pc == 0xAD33)
2854 WriteLog("\n*** After loader ***\n\n");
2857 /*if (regs->pc == 0x0418)
2859 WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2862 if (regs->pc == 0x0)
2867 //WAIT is commented out here because it's called by BELL1...
2868 if (regs->pc == 0xFCA8)
2870 WriteLog("\n*** WAIT subroutine...\n\n");
2873 if (regs->pc == 0xFBD9)
2875 WriteLog("\n*** BELL1 subroutine...\n\n");
2878 if (regs->pc == 0xFC58)
2880 WriteLog("\n*** HOME subroutine...\n\n");
2883 if (regs->pc == 0xFDED)
2885 WriteLog("\n*** COUT subroutine...\n\n");
2891 if (regs->pc == 0x2000)
2896 static char disbuf[80];
2899 Decode65C02(regs, disbuf, regs->pc);
2900 WriteLog("%s", disbuf);
2903 uint8_t opcode = regs->RdMem(regs->pc++);
2905 //if (!(regs->cpuFlags & V65C02_STATE_ILLEGAL_INST))
2906 //instCount[opcode]++;
2908 // We need this because the opcode function could add 1 or 2 cycles
2909 // which aren't accounted for in CPUCycles[].
2910 uint64_t clockSave = regs->clock;
2912 // Execute that opcode...
2914 regs->clock += CPUCycles[opcode];
2916 // Tell the timer function (if any) how many PHI2s have elapsed...
2918 regs->Timer(regs->clock - clockSave);
2922 WriteLog(" [SP=01%02X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
2924 (regs->cc & FLAG_N ? "N" : "-"), (regs->cc & FLAG_V ? "V" : "-"),
2925 (regs->cc & FLAG_B ? "B" : "-"), (regs->cc & FLAG_D ? "D" : "-"),
2926 (regs->cc & FLAG_I ? "I" : "-"), (regs->cc & FLAG_Z ? "Z" : "-"),
2927 (regs->cc & FLAG_C ? "C" : "-"), regs->a, regs->x, regs->y);
2931 if (regs->pc == 0xFCB3) // WAIT exit point
2935 /*if (regs->pc == 0xFBEF) // BELL1 exit point
2939 /*if (regs->pc == 0xFC22) // HOME exit point
2943 if (regs->pc == 0xFDFF) // COUT exit point
2947 if (regs->pc == 0xFBD8)
2949 WriteLog("\n*** BASCALC set BASL/H = $%04X\n\n", RdMemW(0x0028));
2953 //These should be correct now...
2954 if (regs->cpuFlags & V65C02_ASSERT_LINE_RESET)
2956 // Not sure about this...
2958 regs->cc = FLAG_I; // Reset the CC register
2959 regs->pc = RdMemW(0xFFFC); // And load PC with RESET vector
2961 regs->cpuFlags = 0; // Clear CPU flags...
2963 WriteLog("\n*** RESET *** (PC = $%04X)\n\n", regs->pc);
2966 else if (regs->cpuFlags & V65C02_ASSERT_LINE_NMI)
2969 WriteLog("\n*** NMI ***\n\n");
2971 regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); // Save PC & CC
2972 regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
2973 regs->WrMem(0x0100 + regs->sp--, regs->cc);
2976 regs->pc = RdMemW(0xFFFA); // Jump to NMI vector
2979 regs->cpuFlags &= ~V65C02_ASSERT_LINE_NMI; // Reset NMI line
2981 else if ((regs->cpuFlags & V65C02_ASSERT_LINE_IRQ)
2982 // IRQs are maskable, so check if the I flag is clear
2983 && (!(regs->cc & FLAG_I)))
2986 WriteLog("\n*** IRQ ***\n\n");
2987 WriteLog("Clock=$%X\n", regs->clock);
2990 regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); // Save PC & CC
2991 regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
2992 regs->WrMem(0x0100 + regs->sp--, regs->cc);
2995 regs->pc = RdMemW(0xFFFE); // Jump to IRQ vector
2998 regs->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ; // Reset IRQ line
3002 // If we went longer than the passed in cycles, make a note of it so we can
3003 // subtract it out from a subsequent run. It's guaranteed to be non-
3004 // negative, because the condition that exits the main loop above is
3005 // written such that regs->clock has to be equal or larger than endCycles
3007 regs->overflow = regs->clock - endCycles;