VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
PeddleExec_cpp.h
1// -----------------------------------------------------------------------------
2// This file is part of Peddle - A MOS 65xx CPU emulator
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// Published under the terms of the MIT License
6// -----------------------------------------------------------------------------
7
8// Loads a register and sets the Z and V flag
9#define loadA(v) { u8 u = (v); reg.a = u; reg.sr.n = u & 0x80; reg.sr.z = u == 0; }
10#define loadX(v) { u8 u = (v); reg.x = u; reg.sr.n = u & 0x80; reg.sr.z = u == 0; }
11#define loadY(v) { u8 u = (v); reg.y = u; reg.sr.n = u & 0x80; reg.sr.z = u == 0; }
12
13// Atomic CPU tasks
14#define FETCH_OPCODE \
15if (likely(rdyLine)) instr = read<C>(reg.pc++); else return;
16#define FETCH_ADDR_LO \
17if (likely(rdyLine)) reg.adl = read<C>(reg.pc++); else return;
18#define FETCH_ADDR_HI \
19if (likely(rdyLine)) reg.adh = read<C>(reg.pc++); else return;
20#define FETCH_POINTER_ADDR \
21if (likely(rdyLine)) reg.idl = read<C>(reg.pc++); else return;
22#define FETCH_ADDR_LO_INDIRECT \
23if (likely(rdyLine)) reg.adl = read<C>((u16)reg.idl++); else return;
24#define FETCH_ADDR_HI_INDIRECT \
25if (likely(rdyLine)) reg.adh = read<C>((u16)reg.idl++); else return;
26#define IDLE_FETCH \
27if (likely(rdyLine)) readIdle<C>(reg.pc); else return;
28
29#define READ_RELATIVE \
30if (likely(rdyLine)) reg.d = read<C>(reg.pc); else return;
31#define READ_IMMEDIATE \
32if (likely(rdyLine)) reg.d = read<C>(reg.pc++); else return;
33#define READ_FROM(x) \
34if (likely(rdyLine)) reg.d = read<C>(x); else return;
35#define READ_FROM_ADDRESS \
36if (likely(rdyLine)) reg.d = read<C>(HI_LO(reg.adh, reg.adl)); else return;
37#define READ_FROM_ZERO_PAGE \
38if (likely(rdyLine)) reg.d = readZeroPage<C>(reg.adl); else return;
39#define READ_FROM_ADDRESS_INDIRECT \
40if (likely(rdyLine)) reg.d = readZeroPage<C>(reg.dl); else return;
41
42#define IDLE_READ_IMPLIED \
43if (likely(rdyLine)) readIdle<C>(reg.pc); else return;
44#define IDLE_READ_IMMEDIATE \
45if (likely(rdyLine)) readIdle<C>(reg.pc++); else return;
46#define IDLE_READ_FROM(x) \
47if (likely(rdyLine)) readIdle<C>(x); else return;
48#define IDLE_READ_FROM_ADDRESS \
49if (likely(rdyLine)) readIdle<C>(HI_LO(reg.adh, reg.adl)); else return;
50#define IDLE_READ_FROM_ZERO_PAGE \
51if (likely(rdyLine)) readZeroPageIdle<C>(reg.adl); else return;
52#define IDLE_READ_FROM_ADDRESS_INDIRECT \
53if (likely(rdyLine)) readZeroPageIdle<C>(reg.idl); else return;
54
55#define WRITE_TO_ADDRESS \
56write<C>(HI_LO(reg.adh, reg.adl), reg.d);
57#define WRITE_TO_ADDRESS_AND_SET_FLAGS \
58write<C>(HI_LO(reg.adh, reg.adl), reg.d); setN(reg.d & 0x80); setZ(reg.d == 0);
59#define WRITE_TO_ZERO_PAGE \
60writeZeroPage<C>(reg.adl, reg.d);
61#define WRITE_TO_ZERO_PAGE_AND_SET_FLAGS \
62writeZeroPage<C>(reg.adl, reg.d); setN(reg.d & 0x80); setZ(reg.d == 0);
63
64#define ADD_INDEX_X reg.ovl = ((int)reg.adl + (int)reg.x > 0xFF); reg.adl += reg.x;
65#define ADD_INDEX_Y reg.ovl = ((int)reg.adl + (int)reg.y > 0xFF); reg.adl += reg.y;
66#define ADD_INDEX_X_INDIRECT reg.idl += reg.x;
67#define ADD_INDEX_Y_INDIRECT reg.idl += reg.y;
68
69#define SET_PCL(lo) reg.pc = (u16)((reg.pc & 0xff00) | (lo));
70#define SET_PCH(hi) reg.pc = (u16)((reg.pc & 0x00ff) | (hi) << 8);
71#define PUSH_PCL writeStack<C>(reg.sp--, LO_BYTE(reg.pc));
72#define PUSH_PCH writeStack<C>(reg.sp--, HI_BYTE(reg.pc));
73#define PUSH_P writeStack<C>(reg.sp--, getP());
74#define PUSH_P_WITH_B_SET writeStack<C>(reg.sp--, getP() | B_FLAG);
75#define PUSH_A writeStack<C>(reg.sp--, reg.a);
76#define PULL_PCL if (likely(rdyLine)) { SET_PCL(readStack<C>(reg.sp)); } else return;
77#define PULL_PCH if (likely(rdyLine)) { SET_PCH(readStack<C>(reg.sp)); } else return;
78#define PULL_P if (likely(rdyLine)) { setPWithoutB(readStack<C>(reg.sp)); } else return;
79#define PULL_A if (likely(rdyLine)) { loadA(readStack<C>(reg.sp)); } else return;
80#define IDLE_PULL if (likely(rdyLine)) { readStackIdle<C>(reg.sp); } else return;
81
82#define PAGE_BOUNDARY_CROSSED reg.ovl
83#define FIX_ADDR_HI reg.adh++;
84
85#define POLL_IRQ doIrq = (levelDetector.delayed() && !getI());
86#define POLL_NMI doNmi = edgeDetector.delayed();
87#define POLL_INT POLL_IRQ POLL_NMI
88#define POLL_INT_AGAIN doIrq |= (levelDetector.delayed() != 0 && !getI()); \
89doNmi |= (edgeDetector.delayed() != 0);
90#define CONTINUE next = (MicroInstruction)((int)next+1); return;
91#define DONE done<C>(); return;
92
93void
94Peddle::adc(u8 op)
95{
96 if (getD())
97 adcBcd(op);
98 else
99 adcBinary(op);
100}
101
102void
103Peddle::adcBinary(u8 op)
104{
105 u16 sum = reg.a + op + (getC() ? 1 : 0);
106
107 setC(sum > 255);
108 setV(!((reg.a ^ op) & 0x80) && ((reg.a ^ sum) & 0x80));
109 loadA((u8)sum);
110}
111
112void
113Peddle::adcBcd(u8 op)
114{
115 u16 sum = reg.a + op + (getC() ? 1 : 0);
116 u8 highDigit = (reg.a >> 4) + (op >> 4);
117 u8 lowDigit = (reg.a & 0x0F) + (op & 0x0F) + (getC() ? 1 : 0);
118
119 /* Check for overflow conditions. If an overflow occurs on a BCD digit, it
120 * needs to be fixed by adding the pseudo-tetrade 0110 (= 6)
121 */
122 if (lowDigit > 9) {
123 lowDigit = lowDigit + 6;
124 }
125 if (lowDigit > 0x0F) {
126 highDigit++;
127 }
128
129 setZ((sum & 0xFF) == 0);
130 setN(highDigit & 0x08);
131 setV((((highDigit << 4) ^ reg.a) & 0x80) && !((reg.a ^ op) & 0x80));
132
133 if (highDigit > 9) {
134 highDigit = (highDigit + 6);
135 }
136 if (highDigit > 0x0F) {
137 setC(1);
138 } else {
139 setC(0);
140 }
141
142 lowDigit &= 0x0F;
143 reg.a = (u8)((highDigit << 4) | lowDigit);
144}
145
146void
147Peddle::cmp(u8 op1, u8 op2)
148{
149 u8 tmp = op1 - op2;
150
151 setC(op1 >= op2);
152 setN(tmp & 128);
153 setZ(tmp == 0);
154}
155
156void
157Peddle::sbc(u8 op)
158{
159 if (getD())
160 sbcBcd(op);
161 else
162 sbcBinary(op);
163}
164
165void
166Peddle::sbcBinary(u8 op)
167{
168 u16 sum = reg.a - op - (getC() ? 0 : 1);
169
170 setC(sum <= 255);
171 setV(((reg.a ^ sum) & 0x80) && ((reg.a ^ op) & 0x80));
172 loadA((u8)sum);
173}
174
175void
176Peddle::sbcBcd(u8 op)
177{
178 u16 sum = reg.a - op - (getC() ? 0 : 1);
179 u8 highDigit = (reg.a >> 4) - (op >> 4);
180 u8 lowDigit = (reg.a & 0x0F) - (op & 0x0F) - (getC() ? 0 : 1);
181
182 /* Check for underflow conditions. If an overflow occurs on a BCD digit,
183 * it needs to be fixed by subtracting the pseudo-tetrade 0110 (=6)
184 */
185 if (lowDigit & 0x10) {
186 lowDigit = lowDigit - 6;
187 highDigit--;
188 }
189 if (highDigit & 0x10) {
190 highDigit = highDigit - 6;
191 }
192
193 setC(sum < 0x100);
194 setV(((reg.a ^ sum) & 0x80) && ((reg.a ^ op) & 0x80));
195 setZ((sum & 0xFF) == 0);
196 setN(sum & 0x80);
197
198 reg.a = (u8)((highDigit << 4) | (lowDigit & 0x0f));
199}
200
201isize
202Peddle::getLengthOfInstruction(u8 opcode) const
203{
204 switch(addressingMode[opcode]) {
205
206 case ADDR_IMPLIED:
207 case ADDR_ACCUMULATOR: return 1;
208 case ADDR_IMMEDIATE:
209 case ADDR_ZERO_PAGE:
210 case ADDR_ZERO_PAGE_X:
211 case ADDR_ZERO_PAGE_Y:
212 case ADDR_INDIRECT_X:
213 case ADDR_INDIRECT_Y:
214 case ADDR_RELATIVE: return 2;
215 case ADDR_ABSOLUTE:
216 case ADDR_ABSOLUTE_X:
217 case ADDR_ABSOLUTE_Y:
218 case ADDR_DIRECT:
219 case ADDR_INDIRECT: return 3;
220
221 default:
222 fatalError;
223 }
224}
225
226isize
227Peddle::getLengthOfInstructionAt(u16 addr) const
228{
229 return getLengthOfInstruction(readDasm(addr));
230}
231
232isize
233Peddle::getLengthOfCurrentInstruction() const
234{
235 return getLengthOfInstructionAt(getPC0());
236}
237
238u16
239Peddle::getAddressOfNextInstruction() const
240{
241 return (u16)(getPC0() + getLengthOfCurrentInstruction());
242}
243
244void
245Peddle::reset()
246{
247 switch (cpuModel) {
248
249 case MOS_6502: reset<MOS_6502>(); break;
250 case MOS_6507: reset<MOS_6507>(); break;
251 case MOS_6510: reset<MOS_6510>(); break;
252 case MOS_8502: reset<MOS_8502>(); break;
253
254 default:
255 fatalError;
256 }
257}
258
259template <CPURevision C> void
260Peddle::reset()
261{
262 clock = 0;
263 flags = 0;
264 next = fetch;
265 rdyLine = true;
266 rdyLineUp = 0;
267 rdyLineDown = 0;
268 nmiLine = 0;
269 irqLine = 0;
270 edgeDetector.reset(0);
271 levelDetector.reset(0);
272 doNmi = false;
273 doIrq = false;
274
275 reg = { };
276 reg.pport.data = 0xFF;
277 reg.pc = reg.pc0 = readResetVector();
278 setB(1);
279 setI(1);
280
281 debugger.reset();
282}
283
284void
285Peddle::execute()
286{
287 switch (cpuModel) {
288
289 case MOS_6502: execute<MOS_6502>(); break;
290 case MOS_6507: execute<MOS_6507>(); break;
291 case MOS_6510: execute<MOS_6510>(); break;
292 case MOS_8502: execute<MOS_8502>(); break;
293
294 default:
295 fatalError;
296 }
297}
298
299template <CPURevision C> void
300Peddle::execute()
301{
302 u8 instr;
303
304 switch (next) {
305
306 case fetch:
307
308 // Check interrupt lines
309 if (unlikely(doNmi)) {
310
311 nmiWillTrigger();
312 IDLE_FETCH
313 edgeDetector.clear();
314 next = nmi_2;
315 doNmi = false;
316 doIrq = false; // NMI wins
317 return;
318
319 } else if (unlikely(doIrq)) {
320
321 irqWillTrigger();
322 IDLE_FETCH
323 next = irq_2;
324 doIrq = false;
325 return;
326 }
327
328 // Execute the Fetch phase
329 FETCH_OPCODE
330 next = actionFunc[instr];
331 return;
332
333 //
334 // Illegal instructions
335 //
336
337 case JAM:
338
339 cpuDidJam();
340 CONTINUE
341
342 case JAM_2:
343
344 POLL_INT
345 DONE
346
347 //
348 // IRQ handling
349 //
350
351 case irq_2:
352
353 IDLE_READ_IMPLIED
354 CONTINUE
355
356 case irq_3:
357
358 PUSH_PCH
359 CONTINUE
360
361 case irq_4:
362
363 PUSH_PCL
364 // Check for interrupt hijacking
365 // If there is a positive edge on the NMI line ...
366 if (edgeDetector.current()) {
367
368 // ... jump to the NMI vector instead of the IRQ vector.
369 edgeDetector.clear();
370 next = nmi_5;
371 return;
372 }
373 CONTINUE
374
375 case irq_5:
376
377 write<C>(0x100+(reg.sp--), getPWithClearedB());
378 CONTINUE
379
380 case irq_6:
381
382 READ_FROM(0xFFFE)
383 SET_PCL(reg.d);
384 setI(1);
385 CONTINUE
386
387 case irq_7:
388
389 READ_FROM(0xFFFF)
390 SET_PCH(reg.d);
391 irqDidTrigger();
392 DONE
393
394 //
395 // NMI handling
396 //
397
398 case nmi_2:
399
400 IDLE_READ_IMPLIED
401 CONTINUE
402
403 case nmi_3:
404
405 PUSH_PCH
406 CONTINUE
407
408 case nmi_4:
409
410 PUSH_PCL
411 CONTINUE
412
413 case nmi_5:
414
415 write<C>(0x100+(reg.sp--), getPWithClearedB());
416 CONTINUE
417
418 case nmi_6:
419
420 READ_FROM(0xFFFA)
421 SET_PCL(reg.d);
422 setI(1);
423 CONTINUE
424
425 case nmi_7:
426
427 READ_FROM(0xFFFB)
428 SET_PCH(reg.d);
429 nmiDidTrigger();
430 DONE
431
432 //
433 // Adressing mode: Immediate (shared behavior)
434 //
435
436 case BRK: case RTI: case RTS:
437
438 IDLE_READ_IMMEDIATE
439 CONTINUE
440
441 //
442 // Adressing mode: Implied (shared behavior)
443 //
444
445 case PHA: case PHP: case PLA: case PLP:
446
447 IDLE_READ_IMPLIED
448 CONTINUE
449
450 //
451 // Adressing mode: Zero-Page (shared behavior)
452 //
453
454 case ADC_zpg: case AND_zpg: case ASL_zpg: case BIT_zpg:
455 case CMP_zpg: case CPX_zpg: case CPY_zpg: case DEC_zpg:
456 case EOR_zpg: case INC_zpg: case LDA_zpg: case LDX_zpg:
457 case LDY_zpg: case LSR_zpg: case NOP_zpg: case ORA_zpg:
458 case ROL_zpg: case ROR_zpg: case SBC_zpg: case STA_zpg:
459 case STX_zpg: case STY_zpg: case DCP_zpg: case ISC_zpg:
460 case LAX_zpg: case RLA_zpg: case RRA_zpg: case SAX_zpg:
461 case SLO_zpg: case SRE_zpg:
462
463 FETCH_ADDR_LO
464 CONTINUE
465
466 case ASL_zpg_2: case DEC_zpg_2: case INC_zpg_2: case LSR_zpg_2:
467 case ROL_zpg_2: case ROR_zpg_2: case DCP_zpg_2: case ISC_zpg_2:
468 case RLA_zpg_2: case RRA_zpg_2: case SLO_zpg_2: case SRE_zpg_2:
469
470 READ_FROM_ZERO_PAGE
471 CONTINUE
472
473 //
474 // Adressing mode: Zero-Page Indexed (shared behavior)
475 //
476
477 case ADC_zpg_x: case AND_zpg_x: case ASL_zpg_x: case CMP_zpg_x:
478 case DEC_zpg_x: case EOR_zpg_x: case INC_zpg_x: case LDA_zpg_x:
479 case LDY_zpg_x: case LSR_zpg_x: case NOP_zpg_x: case ORA_zpg_x:
480 case ROL_zpg_x: case ROR_zpg_x: case SBC_zpg_x: case STA_zpg_x:
481 case STY_zpg_x: case DCP_zpg_x: case ISC_zpg_x: case RLA_zpg_x:
482 case RRA_zpg_x: case SLO_zpg_x: case SRE_zpg_x:
483
484 case LDX_zpg_y: case STX_zpg_y: case LAX_zpg_y: case SAX_zpg_y:
485
486 FETCH_ADDR_LO
487 CONTINUE
488
489 case ADC_zpg_x_2: case AND_zpg_x_2: case ASL_zpg_x_2: case CMP_zpg_x_2:
490 case DEC_zpg_x_2: case EOR_zpg_x_2: case INC_zpg_x_2: case LDA_zpg_x_2:
491 case LDY_zpg_x_2: case LSR_zpg_x_2: case NOP_zpg_x_2: case ORA_zpg_x_2:
492 case ROL_zpg_x_2: case ROR_zpg_x_2: case SBC_zpg_x_2: case DCP_zpg_x_2:
493 case ISC_zpg_x_2: case RLA_zpg_x_2: case RRA_zpg_x_2: case SLO_zpg_x_2:
494 case SRE_zpg_x_2: case STA_zpg_x_2: case STY_zpg_x_2:
495
496 READ_FROM_ZERO_PAGE
497 ADD_INDEX_X
498 CONTINUE
499
500 case LDX_zpg_y_2: case LAX_zpg_y_2: case STX_zpg_y_2: case SAX_zpg_y_2:
501
502 READ_FROM_ZERO_PAGE
503 ADD_INDEX_Y
504 CONTINUE
505
506 case ASL_zpg_x_3: case DEC_zpg_x_3: case INC_zpg_x_3: case LSR_zpg_x_3:
507 case ROL_zpg_x_3: case ROR_zpg_x_3: case DCP_zpg_x_3: case ISC_zpg_x_3:
508 case RLA_zpg_x_3: case RRA_zpg_x_3: case SLO_zpg_x_3: case SRE_zpg_x_3:
509
510 READ_FROM_ZERO_PAGE
511 CONTINUE
512
513
514 //
515 // Adressing mode: Absolute (shared behavior)
516 //
517
518 case ADC_abs: case AND_abs: case ASL_abs: case BIT_abs:
519 case CMP_abs: case CPX_abs: case CPY_abs: case DEC_abs:
520 case EOR_abs: case INC_abs: case LDA_abs: case LDX_abs:
521 case LDY_abs: case LSR_abs: case NOP_abs: case ORA_abs:
522 case ROL_abs: case ROR_abs: case SBC_abs: case STA_abs:
523 case STX_abs: case STY_abs: case DCP_abs: case ISC_abs:
524 case LAX_abs: case RLA_abs: case RRA_abs: case SAX_abs:
525 case SLO_abs: case SRE_abs:
526
527 FETCH_ADDR_LO
528 CONTINUE
529
530 case ADC_abs_2: case AND_abs_2: case ASL_abs_2: case BIT_abs_2:
531 case CMP_abs_2: case CPX_abs_2: case CPY_abs_2: case DEC_abs_2:
532 case EOR_abs_2: case INC_abs_2: case LDA_abs_2: case LDX_abs_2:
533 case LDY_abs_2: case LSR_abs_2: case NOP_abs_2: case ORA_abs_2:
534 case ROL_abs_2: case ROR_abs_2: case SBC_abs_2: case STA_abs_2:
535 case STX_abs_2: case STY_abs_2: case DCP_abs_2: case ISC_abs_2:
536 case LAX_abs_2: case RLA_abs_2: case RRA_abs_2: case SAX_abs_2:
537 case SLO_abs_2: case SRE_abs_2:
538
539 FETCH_ADDR_HI
540 CONTINUE
541
542 case ASL_abs_3: case DEC_abs_3: case INC_abs_3: case LSR_abs_3:
543 case ROL_abs_3: case ROR_abs_3: case DCP_abs_3: case ISC_abs_3:
544 case RLA_abs_3: case RRA_abs_3: case SLO_abs_3: case SRE_abs_3:
545
546 READ_FROM_ADDRESS
547 CONTINUE
548
549 //
550 // Adressing mode: Absolute Indexed (shared behavior)
551 //
552
553 case ADC_abs_x: case AND_abs_x: case ASL_abs_x: case CMP_abs_x:
554 case DEC_abs_x: case EOR_abs_x: case INC_abs_x: case LDA_abs_x:
555 case LDY_abs_x: case LSR_abs_x: case NOP_abs_x: case ORA_abs_x:
556 case ROL_abs_x: case ROR_abs_x: case SBC_abs_x: case STA_abs_x:
557 case DCP_abs_x: case ISC_abs_x: case RLA_abs_x: case RRA_abs_x:
558 case SHY_abs_x: case SLO_abs_x: case SRE_abs_x:
559
560 case ADC_abs_y: case AND_abs_y: case CMP_abs_y: case EOR_abs_y:
561 case LDA_abs_y: case LDX_abs_y: case LSR_abs_y: case ORA_abs_y:
562 case SBC_abs_y: case STA_abs_y: case DCP_abs_y: case ISC_abs_y:
563 case LAS_abs_y: case LAX_abs_y: case RLA_abs_y: case RRA_abs_y:
564 case SHA_abs_y: case SHX_abs_y: case SLO_abs_y: case SRE_abs_y:
565 case TAS_abs_y:
566
567 FETCH_ADDR_LO
568 CONTINUE
569
570 case ADC_abs_x_2: case AND_abs_x_2: case ASL_abs_x_2: case CMP_abs_x_2:
571 case DEC_abs_x_2: case EOR_abs_x_2: case INC_abs_x_2: case LDA_abs_x_2:
572 case LDY_abs_x_2: case LSR_abs_x_2: case NOP_abs_x_2: case ORA_abs_x_2:
573 case ROL_abs_x_2: case ROR_abs_x_2: case SBC_abs_x_2: case STA_abs_x_2:
574 case DCP_abs_x_2: case ISC_abs_x_2: case RLA_abs_x_2: case RRA_abs_x_2:
575 case SHY_abs_x_2: case SLO_abs_x_2: case SRE_abs_x_2:
576
577 FETCH_ADDR_HI
578 ADD_INDEX_X
579 CONTINUE
580
581 case ADC_abs_y_2: case AND_abs_y_2: case CMP_abs_y_2: case EOR_abs_y_2:
582 case LDA_abs_y_2: case LDX_abs_y_2: case LSR_abs_y_2: case ORA_abs_y_2:
583 case SBC_abs_y_2: case STA_abs_y_2: case DCP_abs_y_2: case ISC_abs_y_2:
584 case LAS_abs_y_2: case LAX_abs_y_2: case RLA_abs_y_2: case RRA_abs_y_2:
585 case SHA_abs_y_2: case SHX_abs_y_2: case SLO_abs_y_2: case SRE_abs_y_2:
586 case TAS_abs_y_2:
587
588 FETCH_ADDR_HI
589 ADD_INDEX_Y
590 CONTINUE
591
592 case ASL_abs_x_3: case DEC_abs_x_3: case INC_abs_x_3: case LSR_abs_x_3:
593 case ROL_abs_x_3: case ROR_abs_x_3: case DCP_abs_x_3: case ISC_abs_x_3:
594 case RLA_abs_x_3: case RRA_abs_x_3: case STA_abs_x_3: case SLO_abs_x_3:
595 case SRE_abs_x_3:
596
597 case LSR_abs_y_3: case STA_abs_y_3: case DCP_abs_y_3: case ISC_abs_y_3:
598 case RLA_abs_y_3: case RRA_abs_y_3: case SLO_abs_y_3: case SRE_abs_y_3:
599
600 READ_FROM_ADDRESS
601 if (PAGE_BOUNDARY_CROSSED) { FIX_ADDR_HI }
602 CONTINUE
603
604 case ASL_abs_x_4: case DEC_abs_x_4: case INC_abs_x_4: case LSR_abs_x_4:
605 case ROL_abs_x_4: case ROR_abs_x_4: case DCP_abs_x_4: case ISC_abs_x_4:
606 case RLA_abs_x_4: case RRA_abs_x_4: case SLO_abs_x_4: case SRE_abs_x_4:
607
608 case DCP_abs_y_4: case LSR_abs_y_4: case ISC_abs_y_4: case RLA_abs_y_4:
609 case RRA_abs_y_4: case SLO_abs_y_4: case SRE_abs_y_4:
610
611 READ_FROM_ADDRESS
612 CONTINUE
613
614 //
615 // Adressing mode: Indexed Indirect (shared behavior)
616 //
617
618 case ADC_ind_x: case AND_ind_x: case ASL_ind_x: case CMP_ind_x:
619 case DEC_ind_x: case EOR_ind_x: case INC_ind_x: case LDA_ind_x:
620 case LDX_ind_x: case LDY_ind_x: case LSR_ind_x: case ORA_ind_x:
621 case ROL_ind_x: case ROR_ind_x: case SBC_ind_x: case STA_ind_x:
622 case DCP_ind_x: case ISC_ind_x: case LAX_ind_x: case RLA_ind_x:
623 case RRA_ind_x: case SAX_ind_x: case SLO_ind_x: case SRE_ind_x:
624
625 FETCH_POINTER_ADDR
626 CONTINUE
627
628 case ADC_ind_x_2: case AND_ind_x_2: case ASL_ind_x_2: case CMP_ind_x_2:
629 case DEC_ind_x_2: case EOR_ind_x_2: case INC_ind_x_2: case LDA_ind_x_2:
630 case LDX_ind_x_2: case LDY_ind_x_2: case LSR_ind_x_2: case ORA_ind_x_2:
631 case ROL_ind_x_2: case ROR_ind_x_2: case SBC_ind_x_2: case STA_ind_x_2:
632 case DCP_ind_x_2: case ISC_ind_x_2: case LAX_ind_x_2: case RLA_ind_x_2:
633 case RRA_ind_x_2: case SAX_ind_x_2: case SLO_ind_x_2: case SRE_ind_x_2:
634
635 IDLE_READ_FROM_ADDRESS_INDIRECT
636 ADD_INDEX_X_INDIRECT
637 CONTINUE
638
639 case ADC_ind_x_3: case AND_ind_x_3: case ASL_ind_x_3: case CMP_ind_x_3:
640 case DEC_ind_x_3: case EOR_ind_x_3: case INC_ind_x_3: case LDA_ind_x_3:
641 case LDX_ind_x_3: case LDY_ind_x_3: case LSR_ind_x_3: case ORA_ind_x_3:
642 case ROL_ind_x_3: case ROR_ind_x_3: case SBC_ind_x_3: case STA_ind_x_3:
643 case DCP_ind_x_3: case ISC_ind_x_3: case LAX_ind_x_3: case RLA_ind_x_3:
644 case RRA_ind_x_3: case SAX_ind_x_3: case SLO_ind_x_3: case SRE_ind_x_3:
645
646 FETCH_ADDR_LO_INDIRECT
647 CONTINUE
648
649 case ADC_ind_x_4: case AND_ind_x_4: case ASL_ind_x_4: case CMP_ind_x_4:
650 case DEC_ind_x_4: case EOR_ind_x_4: case INC_ind_x_4: case LDA_ind_x_4:
651 case LDX_ind_x_4: case LDY_ind_x_4: case LSR_ind_x_4: case ORA_ind_x_4:
652 case ROL_ind_x_4: case ROR_ind_x_4: case SBC_ind_x_4: case STA_ind_x_4:
653 case DCP_ind_x_4: case ISC_ind_x_4: case LAX_ind_x_4: case RLA_ind_x_4:
654 case RRA_ind_x_4: case SAX_ind_x_4: case SLO_ind_x_4: case SRE_ind_x_4:
655
656 FETCH_ADDR_HI_INDIRECT
657 CONTINUE
658
659 case ASL_ind_x_5: case DEC_ind_x_5: case INC_ind_x_5: case LSR_ind_x_5:
660 case ROL_ind_x_5: case ROR_ind_x_5: case DCP_ind_x_5: case ISC_ind_x_5:
661 case RLA_ind_x_5: case RRA_ind_x_5: case SLO_ind_x_5: case SRE_ind_x_5:
662
663 READ_FROM_ADDRESS
664 CONTINUE
665
666 //
667 // Adressing mode: Indirect Indexed (shared behavior)
668 //
669
670 case ADC_ind_y: case AND_ind_y: case CMP_ind_y: case EOR_ind_y:
671 case LDA_ind_y: case LDX_ind_y: case LDY_ind_y: case LSR_ind_y:
672 case ORA_ind_y: case SBC_ind_y: case STA_ind_y: case DCP_ind_y:
673 case ISC_ind_y: case LAX_ind_y: case RLA_ind_y: case RRA_ind_y:
674 case SHA_ind_y: case SLO_ind_y: case SRE_ind_y:
675
676 FETCH_POINTER_ADDR
677 CONTINUE
678
679 case ADC_ind_y_2: case AND_ind_y_2: case CMP_ind_y_2: case EOR_ind_y_2:
680 case LDA_ind_y_2: case LDX_ind_y_2: case LDY_ind_y_2: case LSR_ind_y_2:
681 case ORA_ind_y_2: case SBC_ind_y_2: case STA_ind_y_2: case DCP_ind_y_2:
682 case ISC_ind_y_2: case LAX_ind_y_2: case RLA_ind_y_2: case RRA_ind_y_2:
683 case SHA_ind_y_2: case SLO_ind_y_2: case SRE_ind_y_2:
684
685 FETCH_ADDR_LO_INDIRECT
686 CONTINUE
687
688 case ADC_ind_y_3: case AND_ind_y_3: case CMP_ind_y_3: case EOR_ind_y_3:
689 case LDA_ind_y_3: case LDX_ind_y_3: case LDY_ind_y_3: case LSR_ind_y_3:
690 case ORA_ind_y_3: case SBC_ind_y_3: case STA_ind_y_3: case DCP_ind_y_3:
691 case ISC_ind_y_3: case LAX_ind_y_3: case RLA_ind_y_3: case RRA_ind_y_3:
692 case SHA_ind_y_3: case SLO_ind_y_3: case SRE_ind_y_3:
693
694 FETCH_ADDR_HI_INDIRECT
695 ADD_INDEX_Y
696 CONTINUE
697
698 case LSR_ind_y_4: case STA_ind_y_4: case DCP_ind_y_4: case ISC_ind_y_4:
699 case RLA_ind_y_4: case RRA_ind_y_4: case SLO_ind_y_4: case SRE_ind_y_4:
700
701 READ_FROM_ADDRESS
702 if (PAGE_BOUNDARY_CROSSED) { FIX_ADDR_HI }
703 CONTINUE
704
705 case LSR_ind_y_5: case DCP_ind_y_5: case ISC_ind_y_5: case RLA_ind_y_5:
706 case RRA_ind_y_5: case SLO_ind_y_5: case SRE_ind_y_5:
707
708 READ_FROM_ADDRESS
709 CONTINUE
710
711 //
712 // Adressing mode: Relative (shared behavior)
713 //
714
715 case BCC_rel_2: case BCS_rel_2: case BEQ_rel_2: case BMI_rel_2:
716 case BNE_rel_2: case BPL_rel_2: case BVC_rel_2: case BVS_rel_2:
717 {
718 IDLE_READ_IMPLIED
719 u8 pc_hi = HI_BYTE(reg.pc);
720 reg.pc += (i8)reg.d;
721
722 if (unlikely(pc_hi != HI_BYTE(reg.pc))) {
723 next = (reg.d & 0x80) ? branch_3_underflow : branch_3_overflow;
724 return;
725 }
726 DONE
727 }
728
729 case branch_3_underflow:
730
731 IDLE_READ_FROM(reg.pc + 0x100)
732 POLL_INT_AGAIN
733 DONE
734
735 case branch_3_overflow:
736
737 IDLE_READ_FROM(reg.pc - 0x100)
738 POLL_INT_AGAIN
739 DONE
740
741
742 // Instruction: ADC
743 //
744 // Operation: A,C := A+M+C
745 //
746 // Flags: N Z C I D V
747 // / / / - - /
748
749 case ADC_imm:
750
751 READ_IMMEDIATE
752 adc(reg.d);
753 POLL_INT
754 DONE
755
756 case ADC_zpg_2:
757 case ADC_zpg_x_3:
758
759 READ_FROM_ZERO_PAGE
760 adc(reg.d);
761 POLL_INT
762 DONE
763
764 case ADC_abs_x_3:
765 case ADC_abs_y_3:
766 case ADC_ind_y_4:
767
768 READ_FROM_ADDRESS
769 if (PAGE_BOUNDARY_CROSSED) {
770 FIX_ADDR_HI
771 CONTINUE
772 } else {
773 adc(reg.d);
774 POLL_INT
775 DONE
776 }
777
778 case ADC_abs_3:
779 case ADC_abs_x_4:
780 case ADC_abs_y_4:
781 case ADC_ind_x_5:
782 case ADC_ind_y_5:
783
784 READ_FROM_ADDRESS
785 adc(reg.d);
786 POLL_INT
787 DONE
788
789
790 // Instruction: AND
791 //
792 // Operation: A := A AND M
793 //
794 // Flags: N Z C I D V
795 // / / - - - -
796
797 case AND_imm:
798
799 READ_IMMEDIATE
800 loadA(reg.a & reg.d);
801 POLL_INT
802 DONE
803
804 case AND_zpg_2:
805 case AND_zpg_x_3:
806
807 READ_FROM_ZERO_PAGE
808 loadA(reg.a & reg.d);
809 POLL_INT
810 DONE
811
812 case AND_abs_x_3:
813 case AND_abs_y_3:
814 case AND_ind_y_4:
815
816 READ_FROM_ADDRESS
817 if (PAGE_BOUNDARY_CROSSED) {
818 FIX_ADDR_HI
819 CONTINUE
820 } else {
821 loadA(reg.a & reg.d);
822 POLL_INT
823 DONE
824 }
825
826 case AND_abs_3:
827 case AND_abs_x_4:
828 case AND_abs_y_4:
829 case AND_ind_x_5:
830 case AND_ind_y_5:
831
832 READ_FROM_ADDRESS
833 loadA(reg.a & reg.d);
834 POLL_INT
835 DONE
836
837
838 // Instruction: ASL
839 //
840 // Operation: C <- (A|M << 1) <- 0
841 //
842 // Flags: N Z C I D V
843 // / / / - - -
844
845#define DO_ASL_ACC setC(reg.a & 0x80); loadA((u8)(reg.a << 1));
846#define DO_ASL setC(reg.d & 0x80); reg.d = (u8)(reg.d << 1);
847
848 case ASL_acc:
849
850 IDLE_READ_IMPLIED
851 DO_ASL_ACC
852 POLL_INT
853 DONE
854
855 case ASL_zpg_3:
856 case ASL_zpg_x_4:
857
858 WRITE_TO_ZERO_PAGE
859 DO_ASL
860 CONTINUE
861
862 case ASL_abs_4:
863 case ASL_abs_x_5:
864 case ASL_ind_x_6:
865
866 WRITE_TO_ADDRESS
867 DO_ASL
868 CONTINUE
869
870 case ASL_zpg_4:
871 case ASL_zpg_x_5:
872
873 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
874 POLL_INT
875 DONE
876
877 case ASL_abs_5:
878 case ASL_abs_x_6:
879 case ASL_ind_x_7:
880
881 WRITE_TO_ADDRESS_AND_SET_FLAGS
882 POLL_INT
883 DONE
884
885
886 // Instruction: BCC
887 //
888 // Operation: Branch on C = 0
889 //
890 // Flags: N Z C I D V
891 // - - - - - -
892
893 case BCC_rel:
894
895 READ_IMMEDIATE
896 POLL_INT
897
898 if (!getC()) {
899 CONTINUE
900 } else {
901 DONE
902 }
903
904
905 // Instruction: BCS
906 //
907 // Operation: Branch on C = 1
908 //
909 // Flags: N Z C I D V
910 // - - - - - -
911
912 case BCS_rel:
913
914 READ_IMMEDIATE
915 POLL_INT
916
917 if (getC()) {
918 CONTINUE
919 } else {
920 DONE
921 }
922
923
924 // Instruction: BEQ
925 //
926 // Operation: Branch on Z = 1
927 //
928 // Flags: N Z C I D V
929 // - - - - - -
930
931 case BEQ_rel:
932
933 READ_IMMEDIATE
934 POLL_INT
935
936 if (getZ()) {
937 CONTINUE
938 } else {
939 DONE
940 }
941
942
943 // Instruction: BIT
944 //
945 // Operation: A AND M, N := M7, V := M6
946 //
947 // Flags: N Z C I D V
948 // / / - - - /
949
950 case BIT_zpg_2:
951
952 READ_FROM_ZERO_PAGE
953 setN(reg.d & 128);
954 setV(reg.d & 64);
955 setZ((reg.d & reg.a) == 0);
956 POLL_INT
957 DONE
958
959 case BIT_abs_3:
960
961 READ_FROM_ADDRESS
962 setN(reg.d & 128);
963 setV(reg.d & 64);
964 setZ((reg.d & reg.a) == 0);
965 POLL_INT
966 DONE
967
968
969 // Instruction: BMI
970 //
971 // Operation: Branch on N = 1
972 //
973 // Flags: N Z C I D V
974 // - - - - - -
975
976 case BMI_rel:
977
978 READ_IMMEDIATE
979 POLL_INT
980
981 if (getN()) {
982 CONTINUE
983 } else {
984 DONE
985 }
986
987
988 // Instruction: BNE
989 //
990 // Operation: Branch on Z = 0
991 //
992 // Flags: N Z C I D V
993 // - - - - - -
994
995 case BNE_rel:
996
997 READ_IMMEDIATE
998 POLL_INT
999
1000 if (!getZ()) {
1001 CONTINUE
1002 } else {
1003 DONE
1004 }
1005
1006
1007 // Instruction: BPL
1008 //
1009 // Operation: Branch on N = 0
1010 //
1011 // Flags: N Z C I D V
1012 // - - - - - -
1013
1014 case BPL_rel:
1015
1016 READ_IMMEDIATE
1017 POLL_INT
1018
1019 if (!getN()) {
1020 CONTINUE
1021 } else {
1022 DONE
1023 }
1024
1025
1026 // Instruction: BRK
1027 //
1028 // Operation: Forced Interrupt (Break)
1029 //
1030 // Flags: N Z C I D V B
1031 // - - - 1 - - 1
1032
1033 case BRK_2:
1034
1035 setB(1);
1036 PUSH_PCH
1037 CONTINUE
1038
1039 case BRK_3:
1040
1041 PUSH_PCL
1042
1043 // Check for interrupt hijacking
1044 // If there is a positive edge on the NMI line, ...
1045 if (edgeDetector.current()) {
1046
1047 // ... jump to the NMI vector instead of the IRQ vector.
1048 edgeDetector.clear();
1049 next = BRK_nmi_4;
1050 return;
1051
1052 } else {
1053 CONTINUE
1054 }
1055
1056 case BRK_4:
1057
1058 PUSH_P
1059 CONTINUE
1060
1061 case BRK_5:
1062
1063 READ_FROM(0xFFFE);
1064 SET_PCL(reg.d);
1065 setI(1);
1066 CONTINUE
1067
1068 case BRK_6:
1069
1070 READ_FROM(0xFFFF);
1071 SET_PCH(reg.d);
1072 POLL_INT
1073 doNmi = false; // Only the level detector is polled here. This is
1074 // the reason why only IRQs can be triggered right
1075 // after a BRK command, but not NMIs.
1076 DONE
1077
1078 case BRK_nmi_4:
1079
1080 PUSH_P
1081 CONTINUE
1082
1083 case BRK_nmi_5:
1084
1085 READ_FROM(0xFFFA);
1086 SET_PCL(reg.d);
1087 setI(1);
1088 CONTINUE
1089
1090 case BRK_nmi_6:
1091
1092 READ_FROM(0xFFFB);
1093 SET_PCH(reg.d);
1094 POLL_INT
1095 DONE
1096
1097
1098 // Instruction: BVC
1099 //
1100 // Operation: Branch on V = 0
1101 //
1102 // Flags: N Z C I D V
1103 // - - - - - -
1104
1105 case BVC_rel:
1106
1107 READ_IMMEDIATE
1108 POLL_INT
1109
1110 if (!getV()) {
1111 CONTINUE
1112 } else {
1113 DONE
1114 }
1115
1116
1117 // Instruction: BVS
1118 //
1119 // Operation: Branch on V = 1
1120 //
1121 // Flags: N Z C I D V
1122 // - - - - - -
1123
1124 case BVS_rel:
1125
1126 READ_IMMEDIATE
1127 POLL_INT
1128
1129 if (getV()) {
1130 CONTINUE
1131 } else {
1132 DONE
1133 }
1134
1135
1136 // Instruction: CLC
1137 //
1138 // Operation: C := 0
1139 //
1140 // Flags: N Z C I D V
1141 // - - 0 - - -
1142
1143 case CLC:
1144
1145 IDLE_READ_IMPLIED
1146 setC(0);
1147 POLL_INT
1148 DONE
1149
1150
1151 // Instruction: CLD
1152 //
1153 // Operation: D := 0
1154 //
1155 // Flags: N Z C I D V
1156 // - - - - 0 -
1157
1158 case CLD:
1159
1160 IDLE_READ_IMPLIED
1161 setD(0);
1162 POLL_INT
1163 DONE
1164
1165
1166 // Instruction: CLI
1167 //
1168 // Operation: I := 0
1169 //
1170 // Flags: N Z C I D V
1171 // - - - 0 - -
1172
1173 case CLI:
1174
1175 POLL_INT
1176 setI(0);
1177 IDLE_READ_IMPLIED
1178 DONE
1179
1180
1181 // Instruction: CLV
1182 //
1183 // Operation: V := 0
1184 //
1185 // Flags: N Z C I D V
1186 // - - - - - 0
1187
1188 case CLV:
1189
1190 IDLE_READ_IMPLIED
1191 setV(0);
1192 POLL_INT
1193 DONE
1194
1195
1196 // Instruction: CMP
1197 //
1198 // Operation: A-M
1199 //
1200 // Flags: N Z C I D V
1201 // / / / - - -
1202
1203 case CMP_imm:
1204
1205 READ_IMMEDIATE
1206 cmp(reg.a, reg.d);
1207 POLL_INT
1208 DONE
1209
1210 case CMP_zpg_2:
1211 case CMP_zpg_x_3:
1212
1213 READ_FROM_ZERO_PAGE
1214 cmp(reg.a, reg.d);
1215 POLL_INT
1216 DONE
1217
1218 case CMP_abs_x_3:
1219 case CMP_abs_y_3:
1220 case CMP_ind_y_4:
1221
1222 READ_FROM_ADDRESS
1223 if (PAGE_BOUNDARY_CROSSED) {
1224 FIX_ADDR_HI
1225 CONTINUE
1226 } else {
1227 cmp(reg.a, reg.d);
1228 POLL_INT
1229 DONE
1230 }
1231
1232 case CMP_abs_3:
1233 case CMP_abs_x_4:
1234 case CMP_abs_y_4:
1235 case CMP_ind_x_5:
1236 case CMP_ind_y_5:
1237
1238 READ_FROM_ADDRESS
1239 cmp(reg.a, reg.d);
1240 POLL_INT
1241 DONE
1242
1243
1244 // Instruction: CPX
1245 //
1246 // Operation: X-M
1247 //
1248 // Flags: N Z C I D V
1249 // / / / - - -
1250
1251 case CPX_imm:
1252
1253 READ_IMMEDIATE
1254 cmp(reg.x, reg.d);
1255 POLL_INT
1256 DONE
1257
1258 case CPX_zpg_2:
1259
1260 READ_FROM_ZERO_PAGE
1261 cmp(reg.x, reg.d);
1262 POLL_INT
1263 DONE
1264
1265 case CPX_abs_3:
1266
1267 READ_FROM_ADDRESS
1268 cmp(reg.x, reg.d);
1269 POLL_INT
1270 DONE
1271
1272
1273 // Instruction: CPY
1274 //
1275 // Operation: Y-M
1276 //
1277 // Flags: N Z C I D V
1278 // / / / - - -
1279
1280 case CPY_imm:
1281
1282 READ_IMMEDIATE
1283 cmp(reg.y, reg.d);
1284 POLL_INT
1285 DONE
1286
1287 case CPY_zpg_2:
1288
1289 READ_FROM_ZERO_PAGE
1290 cmp(reg.y, reg.d);
1291 POLL_INT
1292 DONE
1293
1294 case CPY_abs_3:
1295
1296 READ_FROM_ADDRESS
1297 cmp(reg.y, reg.d);
1298 POLL_INT
1299 DONE
1300
1301
1302 // Instruction: DEC
1303 //
1304 // Operation: M := : M - 1
1305 //
1306 // Flags: N Z C I D V
1307 // / / - - - -
1308
1309#define DO_DEC reg.d--;
1310
1311 case DEC_zpg_3:
1312 case DEC_zpg_x_4:
1313
1314 WRITE_TO_ZERO_PAGE
1315 DO_DEC
1316 CONTINUE
1317
1318 case DEC_zpg_4:
1319 case DEC_zpg_x_5:
1320
1321 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
1322 POLL_INT
1323 DONE
1324
1325 case DEC_abs_4:
1326 case DEC_abs_x_5:
1327 case DEC_ind_x_6:
1328
1329 WRITE_TO_ADDRESS
1330 DO_DEC
1331 CONTINUE
1332
1333 case DEC_abs_5:
1334 case DEC_abs_x_6:
1335 case DEC_ind_x_7:
1336
1337 WRITE_TO_ADDRESS_AND_SET_FLAGS
1338 POLL_INT
1339 DONE
1340
1341
1342 // Instruction: DEX
1343 //
1344 // Operation: X := X - 1
1345 //
1346 // Flags: N Z C I D V
1347 // / / - - - -
1348
1349 case DEX:
1350
1351 IDLE_READ_IMPLIED
1352 loadX(reg.x - 1);
1353 POLL_INT
1354 DONE
1355
1356
1357 // Instruction: DEY
1358 //
1359 // Operation: Y := Y - 1
1360 //
1361 // Flags: N Z C I D V
1362 // / / - - - -
1363
1364 case DEY:
1365
1366 IDLE_READ_IMPLIED
1367 loadY(reg.y - 1);
1368 POLL_INT
1369 DONE
1370
1371
1372 // Instruction: EOR
1373 //
1374 // Operation: A := A XOR M
1375 //
1376 // Flags: N Z C I D V
1377 // / / - - - -
1378
1379#define DO_EOR loadA(reg.a ^ reg.d);
1380
1381 case EOR_imm:
1382
1383 READ_IMMEDIATE
1384 DO_EOR
1385 POLL_INT
1386 DONE
1387
1388 case EOR_zpg_2:
1389 case EOR_zpg_x_3:
1390
1391 READ_FROM_ZERO_PAGE
1392 DO_EOR
1393 POLL_INT
1394 DONE
1395
1396 case EOR_abs_x_3:
1397 case EOR_abs_y_3:
1398 case EOR_ind_y_4:
1399
1400 READ_FROM_ADDRESS
1401 if (PAGE_BOUNDARY_CROSSED) {
1402 FIX_ADDR_HI
1403 CONTINUE
1404 } else {
1405 DO_EOR
1406 POLL_INT
1407 DONE
1408 }
1409
1410 case EOR_abs_3:
1411 case EOR_abs_x_4:
1412 case EOR_abs_y_4:
1413 case EOR_ind_x_5:
1414 case EOR_ind_y_5:
1415
1416 READ_FROM_ADDRESS
1417 DO_EOR
1418 POLL_INT
1419 DONE
1420
1421
1422 // Instruction: INC
1423 //
1424 // Operation: M := M + 1
1425 //
1426 // Flags: N Z C I D V
1427 // / / - - - -
1428
1429#define DO_INC reg.d++;
1430
1431 case INC_zpg_3:
1432 case INC_zpg_x_4:
1433
1434 WRITE_TO_ZERO_PAGE
1435 DO_INC
1436 CONTINUE
1437
1438 case INC_zpg_4:
1439 case INC_zpg_x_5:
1440
1441 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
1442 POLL_INT
1443 DONE
1444
1445 case INC_abs_4:
1446 case INC_abs_x_5:
1447 case INC_ind_x_6:
1448
1449 WRITE_TO_ADDRESS
1450 DO_INC
1451 CONTINUE
1452
1453 case INC_abs_5:
1454 case INC_abs_x_6:
1455 case INC_ind_x_7:
1456
1457 WRITE_TO_ADDRESS_AND_SET_FLAGS
1458 POLL_INT
1459 DONE
1460
1461
1462 // Instruction: INX
1463 //
1464 // Operation: X := X + 1
1465 //
1466 // Flags: N Z C I D V
1467 // / / - - - -
1468
1469 case INX:
1470
1471 IDLE_READ_IMPLIED
1472 loadX(reg.x + 1);
1473 POLL_INT
1474 DONE
1475
1476
1477 // Instruction: INY
1478 //
1479 // Operation: Y := Y + 1
1480 //
1481 // Flags: N Z C I D V
1482 // / / - - - -
1483
1484 case INY:
1485
1486 IDLE_READ_IMPLIED
1487 loadY(reg.y + 1);
1488 POLL_INT
1489 DONE
1490
1491
1492 // Instruction: JMP
1493 //
1494 // Operation: PC := Operand
1495 //
1496 // Flags: N Z C I D V
1497 // - - - - - -
1498
1499 case JMP_abs:
1500
1501 FETCH_ADDR_LO
1502 CONTINUE
1503
1504 case JMP_abs_2:
1505
1506 FETCH_ADDR_HI
1507 reg.pc = LO_HI(reg.adl, reg.adh);
1508 POLL_INT
1509 DONE
1510
1511 case JMP_abs_ind:
1512
1513 FETCH_ADDR_LO
1514 CONTINUE
1515
1516 case JMP_abs_ind_2:
1517
1518 FETCH_ADDR_HI
1519 CONTINUE
1520
1521 case JMP_abs_ind_3:
1522
1523 READ_FROM_ADDRESS
1524 SET_PCL(reg.d);
1525 reg.adl++;
1526 CONTINUE
1527
1528 case JMP_abs_ind_4:
1529
1530 READ_FROM_ADDRESS
1531 SET_PCH(reg.d);
1532 POLL_INT
1533 DONE
1534
1535
1536 // Instruction: JSR
1537 //
1538 // Operation: PC to stack, PC := Operand
1539 //
1540 // Flags: N Z C I D V
1541 // - - - - - -
1542
1543 case JSR:
1544
1545 FETCH_ADDR_LO
1546 CONTINUE
1547
1548 case JSR_2:
1549
1550 IDLE_PULL
1551 CONTINUE
1552
1553 case JSR_3:
1554
1555 PUSH_PCH
1556 CONTINUE
1557
1558 case JSR_4:
1559
1560 PUSH_PCL
1561 CONTINUE
1562
1563 case JSR_5:
1564
1565 FETCH_ADDR_HI
1566 reg.pc = LO_HI(reg.adl, reg.adh);
1567 POLL_INT
1568 DONE
1569
1570
1571 // Instruction: LDA
1572 //
1573 // Operation: A := M
1574 //
1575 // Flags: N Z C I D V
1576 // / / - - - -
1577
1578 case LDA_imm:
1579
1580 READ_IMMEDIATE
1581 loadA(reg.d);
1582 POLL_INT
1583 DONE
1584
1585 case LDA_zpg_2:
1586 case LDA_zpg_x_3:
1587
1588 READ_FROM_ZERO_PAGE
1589 loadA(reg.d);
1590 POLL_INT
1591 DONE
1592
1593 case LDA_abs_x_3:
1594 case LDA_abs_y_3:
1595 case LDA_ind_y_4:
1596
1597 READ_FROM_ADDRESS
1598 if (PAGE_BOUNDARY_CROSSED) {
1599 FIX_ADDR_HI
1600 CONTINUE
1601 } else {
1602 loadA(reg.d);
1603 POLL_INT
1604 DONE
1605 }
1606
1607 case LDA_abs_3:
1608 case LDA_abs_x_4:
1609 case LDA_abs_y_4:
1610 case LDA_ind_x_5:
1611 case LDA_ind_y_5:
1612
1613 READ_FROM_ADDRESS
1614 loadA(reg.d);
1615 POLL_INT
1616 DONE
1617
1618
1619 // Instruction: LDX
1620 //
1621 // Operation: X := M
1622 //
1623 // Flags: N Z C I D V
1624 // / / - - - -
1625
1626 case LDX_imm:
1627
1628 READ_IMMEDIATE
1629 loadX(reg.d);
1630 POLL_INT
1631 DONE
1632
1633 case LDX_zpg_2:
1634 case LDX_zpg_y_3:
1635
1636 READ_FROM_ZERO_PAGE
1637 loadX(reg.d);
1638 POLL_INT
1639 DONE
1640
1641 case LDX_abs_y_3:
1642 case LDX_ind_y_4:
1643
1644 READ_FROM_ADDRESS
1645 if (PAGE_BOUNDARY_CROSSED) {
1646 FIX_ADDR_HI
1647 CONTINUE
1648 } else {
1649 loadX(reg.d);
1650 POLL_INT
1651 DONE
1652 }
1653
1654 case LDX_abs_3:
1655 case LDX_abs_y_4:
1656 case LDX_ind_x_5:
1657 case LDX_ind_y_5:
1658
1659 READ_FROM_ADDRESS
1660 loadX(reg.d);
1661 POLL_INT
1662 DONE
1663
1664
1665 // Instruction: LDY
1666 //
1667 // Operation: Y := M
1668 //
1669 // Flags: N Z C I D V
1670 // / / - - - -
1671
1672 case LDY_imm:
1673
1674 READ_IMMEDIATE
1675 loadY(reg.d);
1676 POLL_INT
1677 DONE
1678
1679 case LDY_zpg_2:
1680 case LDY_zpg_x_3:
1681
1682 READ_FROM_ZERO_PAGE
1683 loadY(reg.d);
1684 POLL_INT
1685 DONE
1686
1687 case LDY_abs_x_3:
1688 case LDY_ind_y_4:
1689
1690 READ_FROM_ADDRESS
1691 if (PAGE_BOUNDARY_CROSSED) {
1692 FIX_ADDR_HI
1693 CONTINUE
1694 } else {
1695 loadY(reg.d);
1696 POLL_INT
1697 DONE
1698 }
1699
1700 case LDY_abs_3:
1701 case LDY_abs_x_4:
1702 case LDY_ind_x_5:
1703 case LDY_ind_y_5:
1704
1705 READ_FROM_ADDRESS
1706 loadY(reg.d);
1707 POLL_INT
1708 DONE
1709
1710
1711 // Instruction: LSR
1712 //
1713 // Operation: 0 -> (A|M >> 1) -> C
1714 //
1715 // Flags: N Z C I D V
1716 // 0 / / - - -
1717
1718 case LSR_acc:
1719
1720 IDLE_READ_IMPLIED
1721 setC(reg.a & 1); loadA(reg.a >> 1);
1722 POLL_INT
1723 DONE
1724
1725 case LSR_zpg_3:
1726 case LSR_zpg_x_4:
1727
1728 WRITE_TO_ZERO_PAGE
1729 setC(reg.d & 1); reg.d = reg.d >> 1;
1730 CONTINUE
1731
1732 case LSR_zpg_4:
1733 case LSR_zpg_x_5:
1734
1735 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
1736 POLL_INT
1737 DONE
1738
1739 case LSR_abs_4:
1740 case LSR_abs_x_5:
1741 case LSR_abs_y_5:
1742 case LSR_ind_x_6:
1743 case LSR_ind_y_6:
1744
1745 WRITE_TO_ADDRESS
1746 setC(reg.d & 1); reg.d = reg.d >> 1;
1747 CONTINUE
1748
1749 case LSR_abs_5:
1750 case LSR_abs_x_6:
1751 case LSR_abs_y_6:
1752 case LSR_ind_x_7:
1753 case LSR_ind_y_7:
1754
1755 WRITE_TO_ADDRESS_AND_SET_FLAGS
1756 POLL_INT
1757 DONE
1758
1759
1760 // Instruction: NOP
1761 //
1762 // Operation: No operation
1763 //
1764 // Flags: N Z C I D V
1765 // - - - - - -
1766
1767 case NOP:
1768
1769 IDLE_READ_IMPLIED
1770 POLL_INT
1771 DONE
1772
1773 case NOP_imm:
1774
1775 IDLE_READ_IMMEDIATE
1776 POLL_INT
1777 DONE
1778
1779 case NOP_zpg_2:
1780 case NOP_zpg_x_3:
1781
1782 IDLE_READ_FROM_ZERO_PAGE
1783 POLL_INT
1784 DONE
1785
1786 case NOP_abs_x_3:
1787
1788 IDLE_READ_FROM_ADDRESS
1789 if (PAGE_BOUNDARY_CROSSED) {
1790 FIX_ADDR_HI
1791 CONTINUE
1792 } else {
1793 POLL_INT
1794 DONE
1795 }
1796
1797 case NOP_abs_3:
1798 case NOP_abs_x_4:
1799
1800 IDLE_READ_FROM_ADDRESS
1801 POLL_INT
1802 DONE
1803
1804
1805 // Instruction: ORA
1806 //
1807 // Operation: A := A v M
1808 //
1809 // Flags: N Z C I D V
1810 // / / - - - -
1811
1812 case ORA_imm:
1813
1814 READ_IMMEDIATE
1815 loadA(reg.a | reg.d);
1816 POLL_INT
1817 DONE
1818
1819 case ORA_zpg_2:
1820 case ORA_zpg_x_3:
1821
1822 READ_FROM_ZERO_PAGE
1823 loadA(reg.a | reg.d);
1824 POLL_INT
1825 DONE
1826
1827 case ORA_abs_x_3:
1828 case ORA_abs_y_3:
1829 case ORA_ind_y_4:
1830
1831 READ_FROM_ADDRESS
1832 if (PAGE_BOUNDARY_CROSSED) {
1833 FIX_ADDR_HI
1834 CONTINUE
1835 } else {
1836 loadA(reg.a | reg.d);
1837 POLL_INT
1838 DONE
1839 }
1840
1841 case ORA_abs_3:
1842 case ORA_abs_x_4:
1843 case ORA_abs_y_4:
1844 case ORA_ind_x_5:
1845 case ORA_ind_y_5:
1846
1847 READ_FROM_ADDRESS
1848 loadA(reg.a | reg.d);
1849 POLL_INT
1850 DONE
1851
1852
1853 // Instruction: PHA
1854 //
1855 // Operation: A to stack
1856 //
1857 // Flags: N Z C I D V
1858 // - - - - - -
1859
1860 case PHA_2:
1861
1862 PUSH_A
1863 POLL_INT
1864 DONE
1865
1866
1867 // Instruction: PHA
1868 //
1869 // Operation: P to stack
1870 //
1871 // Flags: N Z C I D V
1872 // - - - - - -
1873
1874 case PHP_2:
1875
1876 PUSH_P
1877 POLL_INT
1878 DONE
1879
1880
1881 // Instruction: PLA
1882 //
1883 // Operation: Stack to A
1884 //
1885 // Flags: N Z C I D V
1886 // - - - - - -
1887
1888 case PLA_2:
1889
1890 reg.sp++;
1891 CONTINUE
1892
1893 case PLA_3:
1894
1895 PULL_A
1896 POLL_INT
1897 DONE
1898
1899
1900 // Instruction: PLP
1901 //
1902 // Operation: Stack to p
1903 //
1904 // Flags: N Z C I D V
1905 // / / / / / /
1906
1907 case PLP_2:
1908
1909 IDLE_PULL
1910 reg.sp++;
1911 CONTINUE
1912
1913 case PLP_3:
1914
1915 POLL_INT // Interrupts are polled before P is pulled
1916 PULL_P
1917 DONE
1918
1919
1920 // Instruction: ROL
1921 //
1922 // -----------------------
1923 // | |
1924 // Operation: ---(A|M << 1) <- C <---
1925 //
1926 // Flags: N Z C I D V
1927 // / / / - - -
1928
1929#define DO_ROL_ACC { u8 c = !!getC(); setC(reg.a & 0x80); loadA((u8)(reg.a << 1 | c)); }
1930#define DO_ROL { u8 c = !!getC(); setC(reg.d & 0x80); reg.d = (u8)(reg.d << 1 | c); }
1931
1932 case ROL_acc:
1933
1934 IDLE_READ_IMPLIED
1935 DO_ROL_ACC
1936 POLL_INT
1937 DONE
1938
1939 case ROL_zpg_3:
1940 case ROL_zpg_x_4:
1941
1942 WRITE_TO_ZERO_PAGE
1943 DO_ROL
1944 CONTINUE
1945
1946 case ROL_zpg_4:
1947 case ROL_zpg_x_5:
1948
1949 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
1950 POLL_INT
1951 DONE
1952
1953 case ROL_abs_4:
1954 case ROL_abs_x_5:
1955 case ROL_ind_x_6:
1956
1957 WRITE_TO_ADDRESS
1958 DO_ROL
1959 CONTINUE
1960
1961 case ROL_abs_5:
1962 case ROL_abs_x_6:
1963 case ROL_ind_x_7:
1964
1965 WRITE_TO_ADDRESS_AND_SET_FLAGS
1966 POLL_INT
1967 DONE
1968
1969
1970 // Instruction: ROR
1971 //
1972 // -----------------------
1973 // | |
1974 // Operation: --->(A|M >> 1) -> C ---
1975 //
1976 // Flags: N Z C I D V
1977 // / / / - - -
1978
1979#define DO_ROR_ACC { u8 c = !!getC(); setC(reg.a & 0x1); loadA((u8)(reg.a >> 1 | c << 7)); }
1980#define DO_ROR { u8 c = !!getC(); setC(reg.d & 0x1); reg.d = (u8)(reg.d >> 1 | c << 7); }
1981
1982 case ROR_acc:
1983
1984 IDLE_READ_IMPLIED
1985 DO_ROR_ACC
1986 POLL_INT
1987 DONE
1988
1989 case ROR_zpg_3:
1990 case ROR_zpg_x_4:
1991
1992 WRITE_TO_ZERO_PAGE
1993 DO_ROR
1994 CONTINUE
1995
1996 case ROR_zpg_4:
1997 case ROR_zpg_x_5:
1998
1999 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
2000 POLL_INT
2001 DONE
2002
2003 case ROR_abs_4:
2004 case ROR_abs_x_5:
2005 case ROR_ind_x_6:
2006
2007 WRITE_TO_ADDRESS
2008 DO_ROR
2009 CONTINUE
2010
2011 case ROR_abs_5:
2012 case ROR_abs_x_6:
2013 case ROR_ind_x_7:
2014
2015 WRITE_TO_ADDRESS_AND_SET_FLAGS
2016 POLL_INT
2017 DONE
2018
2019
2020 // Instruction: RTI
2021 //
2022 // Operation: P from Stack, PC from Stack
2023 //
2024 // Flags: N Z C I D V
2025 // / / / / / /
2026
2027 case RTI_2:
2028
2029 IDLE_PULL
2030 reg.sp++;
2031 CONTINUE
2032
2033 case RTI_3:
2034
2035 PULL_P
2036 reg.sp++;
2037 CONTINUE
2038
2039 case RTI_4:
2040
2041 PULL_PCL
2042 reg.sp++;
2043 CONTINUE
2044
2045 case RTI_5:
2046
2047 PULL_PCH
2048 POLL_INT
2049 DONE
2050
2051
2052 // Instruction: RTS
2053 //
2054 // Operation: PC from Stack
2055 //
2056 // Flags: N Z C I D V
2057 // - - - - - -
2058
2059 case RTS_2:
2060
2061 IDLE_PULL
2062 reg.sp++;
2063 CONTINUE
2064
2065 case RTS_3:
2066
2067 PULL_PCL
2068 reg.sp++;
2069 CONTINUE
2070
2071 case RTS_4:
2072
2073 PULL_PCH
2074 CONTINUE
2075
2076 case RTS_5:
2077
2078 IDLE_READ_IMMEDIATE
2079 POLL_INT
2080 DONE
2081
2082
2083 // Instruction: SBC
2084 //
2085 // Operation: A := A - M - (~C)
2086 //
2087 // Flags: N Z C I D V
2088 // / / / - - /
2089
2090 case SBC_imm:
2091
2092 READ_IMMEDIATE
2093 sbc(reg.d);
2094 POLL_INT
2095 DONE
2096
2097 case SBC_zpg_2:
2098 case SBC_zpg_x_3:
2099
2100 READ_FROM_ZERO_PAGE
2101 sbc(reg.d);
2102 POLL_INT
2103 DONE
2104
2105 case SBC_abs_x_3:
2106 case SBC_abs_y_3:
2107 case SBC_ind_y_4:
2108
2109 READ_FROM_ADDRESS
2110 if (PAGE_BOUNDARY_CROSSED) {
2111 FIX_ADDR_HI
2112 CONTINUE
2113 } else {
2114 sbc(reg.d);
2115 POLL_INT
2116 DONE
2117 }
2118
2119 case SBC_abs_3:
2120 case SBC_abs_x_4:
2121 case SBC_abs_y_4:
2122 case SBC_ind_x_5:
2123 case SBC_ind_y_5:
2124
2125 READ_FROM_ADDRESS
2126 sbc(reg.d);
2127 POLL_INT
2128 DONE
2129
2130
2131 // Instruction: SEC
2132 //
2133 // Operation: C := 1
2134 //
2135 // Flags: N Z C I D V
2136 // - - 1 - - -
2137
2138 case SEC:
2139
2140 IDLE_READ_IMPLIED
2141 setC(1);
2142 POLL_INT
2143 DONE
2144
2145
2146 // Instruction: SED
2147 //
2148 // Operation: D := 1
2149 //
2150 // Flags: N Z C I D V
2151 // - - - - 1 -
2152
2153 case SED:
2154
2155 IDLE_READ_IMPLIED
2156 setD(1);
2157 POLL_INT
2158 DONE
2159
2160
2161 // Instruction: SEI
2162 //
2163 // Operation: I := 1
2164 //
2165 // Flags: N Z C I D V
2166 // - - - 1 - -
2167
2168 case SEI:
2169
2170 POLL_IRQ
2171 setI(1);
2172 [[fallthrough]];
2173
2174 case SEI_cont:
2175
2176 next = SEI_cont;
2177 IDLE_READ_IMPLIED
2178 POLL_NMI
2179 DONE
2180
2181
2182 // Instruction: STA
2183 //
2184 // Operation: M := A
2185 //
2186 // Flags: N Z C I D V
2187 // - - - - - -
2188
2189 case STA_zpg_2:
2190 case STA_zpg_x_3:
2191
2192 reg.d = reg.a;
2193 WRITE_TO_ZERO_PAGE
2194 POLL_INT
2195 DONE
2196
2197 case STA_abs_3:
2198 case STA_abs_x_4:
2199
2200 reg.d = reg.a;
2201 WRITE_TO_ADDRESS
2202 POLL_INT
2203 DONE
2204
2205 case STA_abs_y_4:
2206 case STA_ind_x_5:
2207 case STA_ind_y_5:
2208
2209 reg.d = reg.a;
2210 WRITE_TO_ADDRESS
2211 POLL_INT
2212 DONE
2213
2214
2215 // Instruction: STX
2216 //
2217 // Operation: M := X
2218 //
2219 // Flags: N Z C I D V
2220 // - - - - - -
2221
2222 case STX_zpg_2:
2223 case STX_zpg_y_3:
2224
2225 reg.d = reg.x;
2226 WRITE_TO_ZERO_PAGE
2227 POLL_INT
2228 DONE
2229
2230 case STX_abs_3:
2231
2232 reg.d = reg.x;
2233 WRITE_TO_ADDRESS
2234 POLL_INT
2235 DONE
2236
2237
2238 // Instruction: STY
2239 //
2240 // Operation: M := Y
2241 //
2242 // Flags: N Z C I D V
2243 // - - - - - -
2244
2245 case STY_zpg_2:
2246 case STY_zpg_x_3:
2247
2248 reg.d = reg.y;
2249 WRITE_TO_ZERO_PAGE
2250 POLL_INT
2251 DONE
2252
2253 case STY_abs_3:
2254
2255 reg.d = reg.y;
2256 WRITE_TO_ADDRESS
2257 POLL_INT
2258 DONE
2259
2260
2261 // Instruction: TAX
2262 //
2263 // Operation: X := A
2264 //
2265 // Flags: N Z C I D V
2266 // / / - - - -
2267
2268 case TAX:
2269
2270 IDLE_READ_IMPLIED
2271 loadX(reg.a);
2272 POLL_INT
2273 DONE
2274
2275
2276 // Instruction: TAY
2277 //
2278 // Operation: Y := A
2279 //
2280 // Flags: N Z C I D V
2281 // / / - - - -
2282
2283 case TAY:
2284
2285 IDLE_READ_IMPLIED
2286 loadY(reg.a);
2287 POLL_INT
2288 DONE
2289
2290
2291 // Instruction: TSX
2292 //
2293 // Operation: X := Stack pointer
2294 //
2295 // Flags: N Z C I D V
2296 // / / - - - -
2297
2298 case TSX:
2299
2300 IDLE_READ_IMPLIED
2301 loadX(reg.sp);
2302 POLL_INT
2303 DONE
2304
2305
2306 // Instruction: TXA
2307 //
2308 // Operation: A := X
2309 //
2310 // Flags: N Z C I D V
2311 // / / - - - -
2312
2313 case TXA:
2314
2315 IDLE_READ_IMPLIED
2316 loadA(reg.x);
2317 POLL_INT
2318 DONE
2319
2320
2321 // Instruction: TXS
2322 //
2323 // Operation: Stack pointer := X
2324 //
2325 // Flags: N Z C I D V
2326 // - - - - - -
2327
2328 case TXS:
2329
2330 IDLE_READ_IMPLIED
2331 reg.sp = reg.x;
2332 POLL_INT
2333 DONE
2334
2335
2336 // Instruction: TYA
2337 //
2338 // Operation: A := Y
2339 //
2340 // Flags: N Z C I D V
2341 // / / - - - -
2342
2343 case TYA:
2344
2345 IDLE_READ_IMPLIED
2346 loadA(reg.y);
2347 POLL_INT
2348 DONE
2349
2350
2351 //
2352 // Illegal instructions
2353 //
2354
2355
2356 // Instruction: ALR
2357 //
2358 // Operation: AND, followed by LSR
2359 //
2360 // Flags: N Z C I D V
2361 // / / / - - -
2362
2363 case ALR_imm:
2364
2365 READ_IMMEDIATE
2366 reg.a = reg.a & reg.d;
2367 setC(reg.a & 1);
2368 loadA(reg.a >> 1);
2369 POLL_INT
2370 DONE
2371
2372
2373 // Instruction: ANC
2374 //
2375 // Operation: A := A & op, N flag is copied to C
2376 //
2377 // Flags: N Z C I D V
2378 // / / / - - -
2379
2380 case ANC_imm:
2381
2382 READ_IMMEDIATE
2383 loadA(reg.a & reg.d);
2384 setC(getN());
2385 POLL_INT
2386 DONE
2387
2388
2389 // Instruction: ARR
2390 //
2391 // Operation: AND, followed by ROR
2392 //
2393 // Flags: N Z C I D V
2394 // / / / - - /
2395
2396 case ARR_imm:
2397 {
2398 READ_IMMEDIATE
2399
2400 u8 tmp2 = reg.a & reg.d;
2401
2402 // Taken from Frodo...
2403 reg.a = (getC() ? (tmp2 >> 1) | 0x80 : tmp2 >> 1);
2404 if (!getD()) {
2405 setN(reg.a & 0x80);
2406 setZ(reg.a == 0);
2407 setC(reg.a & 0x40);
2408 setV((reg.a & 0x40) ^ ((reg.a & 0x20) << 1));
2409 } else {
2410 int c_flag;
2411
2412 setN(getC());
2413 setZ(reg.a == 0);
2414 setV((tmp2 ^ reg.a) & 0x40);
2415 if ((tmp2 & 0x0f) + (tmp2 & 0x01) > 5)
2416 reg.a = (reg.a & 0xf0) | ((reg.a + 6) & 0x0f);
2417 c_flag = (tmp2 + (tmp2 & 0x10)) & 0x1f0;
2418 if (c_flag > 0x50) {
2419 setC(1);
2420 reg.a += 0x60;
2421 } else {
2422 setC(0);
2423 }
2424 }
2425 POLL_INT
2426 DONE
2427 }
2428
2429
2430 // Instruction: AXS
2431 //
2432 // Operation: X = (A & X) - op
2433 //
2434 // Flags: N Z C I D V
2435 // / / / - - -
2436
2437 case AXS_imm:
2438 {
2439 READ_IMMEDIATE
2440
2441 u8 op2 = reg.a & reg.x;
2442 u8 tmp = op2 - reg.d;
2443
2444 setC(op2 >= reg.d);
2445 loadX(tmp);
2446 POLL_INT
2447 DONE
2448 }
2449
2450
2451 // Instruction: DCP
2452 //
2453 // Operation: DEC followed by CMP
2454 //
2455 // Flags: N Z C I D V
2456 // / / / - - -
2457
2458 case DCP_zpg_3:
2459 case DCP_zpg_x_4:
2460
2461 WRITE_TO_ZERO_PAGE
2462 reg.d--;
2463 CONTINUE
2464
2465 case DCP_zpg_4:
2466 case DCP_zpg_x_5:
2467
2468 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
2469 cmp(reg.a, reg.d);
2470 POLL_INT
2471 DONE
2472
2473 case DCP_abs_4:
2474 case DCP_abs_x_5:
2475 case DCP_abs_y_5:
2476 case DCP_ind_x_6:
2477 case DCP_ind_y_6:
2478
2479 WRITE_TO_ADDRESS
2480 reg.d--;
2481 CONTINUE
2482
2483 case DCP_abs_5:
2484 case DCP_abs_x_6:
2485 case DCP_abs_y_6:
2486 case DCP_ind_x_7:
2487 case DCP_ind_y_7:
2488
2489 WRITE_TO_ADDRESS_AND_SET_FLAGS
2490 cmp(reg.a, reg.d);
2491 POLL_INT
2492 DONE
2493
2494
2495 // Instruction: ISC
2496 //
2497 // Operation: INC followed by SBC
2498 //
2499 // Flags: N Z C I D V
2500 // / / / - - /
2501
2502 case ISC_zpg_3:
2503 case ISC_zpg_x_4:
2504
2505 WRITE_TO_ZERO_PAGE
2506 reg.d++;
2507 CONTINUE
2508
2509 case ISC_zpg_4:
2510 case ISC_zpg_x_5:
2511
2512 WRITE_TO_ZERO_PAGE_AND_SET_FLAGS
2513 sbc(reg.d);
2514 POLL_INT
2515 DONE
2516
2517 case ISC_abs_4:
2518 case ISC_abs_x_5:
2519 case ISC_abs_y_5:
2520 case ISC_ind_x_6:
2521 case ISC_ind_y_6:
2522
2523 WRITE_TO_ADDRESS
2524 reg.d++;
2525 CONTINUE
2526
2527 case ISC_abs_5:
2528 case ISC_abs_x_6:
2529 case ISC_abs_y_6:
2530 case ISC_ind_x_7:
2531 case ISC_ind_y_7:
2532
2533 WRITE_TO_ADDRESS_AND_SET_FLAGS
2534 sbc(reg.d);
2535 POLL_INT
2536 DONE
2537
2538
2539 // Instruction: LAS
2540 //
2541 // Operation: SP,X,A = op & SP
2542 //
2543 // Flags: N Z C I D V
2544 // / / - - - -
2545
2546 case LAS_abs_y_3:
2547
2548 READ_FROM_ADDRESS
2549 if (PAGE_BOUNDARY_CROSSED) {
2550 FIX_ADDR_HI
2551 CONTINUE
2552 } else {
2553 reg.d &= reg.sp;
2554 reg.sp = reg.d;
2555 reg.x = reg.d;
2556 loadA(reg.d);
2557 POLL_INT
2558 DONE
2559 }
2560
2561 case LAS_abs_y_4:
2562
2563 READ_FROM_ADDRESS
2564 reg.d &= reg.sp;
2565 reg.sp = reg.d;
2566 reg.x = reg.d;
2567 loadA(reg.d);
2568 POLL_INT
2569 DONE
2570
2571
2572 // Instruction: LAX
2573 //
2574 // Operation: LDA, followed by LDX
2575 //
2576 // Flags: N Z C I D V
2577 // / / - - - -
2578
2579 case LAX_zpg_2:
2580 case LAX_zpg_y_3:
2581
2582 READ_FROM_ZERO_PAGE
2583 loadA(reg.d);
2584 loadX(reg.d);
2585 POLL_INT
2586 DONE
2587
2588 case LAX_abs_y_3:
2589 case LAX_ind_y_4:
2590
2591 READ_FROM_ADDRESS
2592 if (PAGE_BOUNDARY_CROSSED) {
2593 FIX_ADDR_HI
2594 CONTINUE
2595 } else {
2596 loadA(reg.d);
2597 loadX(reg.d);
2598 POLL_INT
2599 DONE
2600 }
2601
2602 case LAX_abs_3:
2603 case LAX_abs_y_4:
2604 case LAX_ind_x_5:
2605 case LAX_ind_y_5:
2606
2607 READ_FROM_ADDRESS;
2608 loadA(reg.d);
2609 loadX(reg.d);
2610 POLL_INT
2611 DONE
2612
2613
2614 // Instruction: RLA
2615 //
2616 // Operation: ROL, followed by AND
2617 //
2618 // Flags: N Z C I D V
2619 // / / / - - -
2620
2621 case RLA_zpg_3:
2622 case RLA_zpg_x_4:
2623
2624 WRITE_TO_ZERO_PAGE
2625 DO_ROL
2626 CONTINUE
2627
2628 case RLA_zpg_4:
2629 case RLA_zpg_x_5:
2630
2631 WRITE_TO_ZERO_PAGE
2632 loadA(reg.a & reg.d);
2633 POLL_INT
2634 DONE
2635
2636 case RLA_abs_4:
2637 case RLA_abs_x_5:
2638 case RLA_abs_y_5:
2639 case RLA_ind_x_6:
2640 case RLA_ind_y_6:
2641
2642 WRITE_TO_ADDRESS
2643 DO_ROL
2644 CONTINUE
2645
2646 case RLA_abs_5:
2647 case RLA_abs_x_6:
2648 case RLA_abs_y_6:
2649 case RLA_ind_x_7:
2650 case RLA_ind_y_7:
2651
2652 WRITE_TO_ADDRESS
2653 loadA(reg.a & reg.d);
2654 POLL_INT
2655 DONE
2656
2657 // Instruction: RRA
2658 //
2659 // Operation: ROR, followed by ADC
2660 //
2661 // Flags: N Z C I D V
2662 // / / / - - /
2663
2664 case RRA_zpg_3:
2665 case RRA_zpg_x_4:
2666
2667 WRITE_TO_ZERO_PAGE
2668 DO_ROR
2669 CONTINUE
2670
2671 case RRA_zpg_4:
2672 case RRA_zpg_x_5:
2673
2674 WRITE_TO_ZERO_PAGE
2675 adc(reg.d);
2676 POLL_INT
2677 DONE
2678
2679 case RRA_abs_4:
2680 case RRA_abs_x_5:
2681 case RRA_abs_y_5:
2682 case RRA_ind_x_6:
2683 case RRA_ind_y_6:
2684
2685 WRITE_TO_ADDRESS
2686 DO_ROR
2687 CONTINUE
2688
2689 case RRA_abs_5:
2690 case RRA_abs_x_6:
2691 case RRA_abs_y_6:
2692 case RRA_ind_x_7:
2693 case RRA_ind_y_7:
2694
2695 WRITE_TO_ADDRESS
2696 adc(reg.d);
2697 POLL_INT
2698 DONE
2699
2700
2701 // Instruction: SAX
2702 //
2703 // Operation: Mem := A & X
2704 //
2705 // Flags: N Z C I D V
2706 // - - - - - -
2707
2708 case SAX_zpg_2:
2709 case SAX_zpg_y_3:
2710
2711 reg.d = reg.a & reg.x;
2712 WRITE_TO_ZERO_PAGE
2713 POLL_INT
2714 DONE
2715
2716 case SAX_abs_3:
2717 case SAX_ind_x_5:
2718
2719 reg.d = reg.a & reg.x;
2720 WRITE_TO_ADDRESS
2721 POLL_INT
2722 DONE
2723
2724
2725 // Instruction: SHA
2726 //
2727 // Operation: Mem := A & X & (M + 1)
2728 //
2729 // Flags: N Z C I D V
2730 // - - - - - -
2731
2732 case SHA_abs_y_3:
2733
2734 IDLE_READ_FROM_ADDRESS
2735
2736 /* "There are two unstable conditions, the first is when a DMA is
2737 * going on while the instruction executes (the CPU is halted by
2738 * the VIC-II) then the & M+1 part drops off."
2739 */
2740
2741 reg.d = reg.a & reg.x & (rdyLineUp == clock ? 0xFF : reg.adh + 1);
2742
2743 /* "The other unstable condition is when the addressing/indexing
2744 * causes a page boundary crossing, in that case the highbyte of
2745 * the target address may become equal to the value stored."
2746 */
2747
2748 if (PAGE_BOUNDARY_CROSSED) {
2749 FIX_ADDR_HI;
2750 reg.adh = reg.a & reg.x & reg.adh;
2751 }
2752
2753 CONTINUE
2754
2755 case SHA_abs_y_4:
2756
2757 WRITE_TO_ADDRESS
2758 POLL_INT
2759 DONE
2760
2761 case SHA_ind_y_4:
2762
2763 IDLE_READ_FROM_ADDRESS
2764
2765 /* "There are two unstable conditions, the first is when a DMA is
2766 * going on while the instruction executes (the CPU is halted by
2767 * the VIC-II) then the & M+1 part drops off."
2768 */
2769
2770 reg.d = reg.a & reg.x & (rdyLineUp == clock ? 0xFF : reg.adh + 1);
2771
2772 /* "The other unstable condition is when the addressing/indexing
2773 * causes a page boundary crossing, in that case the highbyte of
2774 * the target address may become equal to the value stored."
2775 */
2776
2777 if (PAGE_BOUNDARY_CROSSED) {
2778 FIX_ADDR_HI;
2779 reg.adh = reg.a & reg.x & reg.adh;
2780 }
2781
2782 CONTINUE
2783
2784 case SHA_ind_y_5:
2785
2786 WRITE_TO_ADDRESS
2787 POLL_INT
2788 DONE
2789
2790
2791 // Instruction: SHX
2792 //
2793 // Operation: Mem := X & (HI_BYTE(op) + 1)
2794 //
2795 // Flags: N Z C I D V
2796 // - - - - - -
2797
2798 case SHX_abs_y_3:
2799
2800 IDLE_READ_FROM_ADDRESS
2801
2802 /* "There are two unstable conditions, the first is when a DMA is
2803 * going on while the instruction executes (the CPU is halted by
2804 * the VIC-II) then the & M+1 part drops off."
2805 */
2806
2807 reg.d = reg.x & (rdyLineUp == clock ? 0xFF : reg.adh + 1);
2808
2809 /* "The other unstable condition is when the addressing/indexing
2810 * causes a page boundary crossing, in that case the highbyte of
2811 * the target address may become equal to the value stored."
2812 */
2813
2814 if (PAGE_BOUNDARY_CROSSED) {
2815 FIX_ADDR_HI;
2816 reg.adh = reg.x & reg.adh;
2817 }
2818
2819 CONTINUE
2820
2821 case SHX_abs_y_4:
2822
2823 WRITE_TO_ADDRESS
2824 POLL_INT
2825 DONE
2826
2827
2828 // Instruction: SHY
2829 //
2830 // Operation: Mem := Y & (HI_BYTE(op) + 1)
2831 //
2832 // Flags: N Z C I D V
2833 // - - - - - -
2834
2835 case SHY_abs_x_3:
2836
2837 IDLE_READ_FROM_ADDRESS
2838
2839 /* "There are two unstable conditions, the first is when a DMA is
2840 * going on while the instruction executes (the CPU is halted by
2841 * the VIC-II) then the & M+1 part drops off."
2842 */
2843
2844 reg.d = reg.y & (rdyLineUp == clock ? 0xFF : reg.adh + 1);
2845
2846 /* "The other unstable condition is when the addressing/indexing
2847 * causes a page boundary crossing, in that case the highbyte of
2848 * the target address may become equal to the value stored."
2849 */
2850
2851 if (PAGE_BOUNDARY_CROSSED) {
2852 FIX_ADDR_HI;
2853 reg.adh = reg.y & reg.adh;
2854 }
2855
2856 CONTINUE
2857
2858 case SHY_abs_x_4:
2859
2860 WRITE_TO_ADDRESS
2861 POLL_INT
2862 DONE
2863
2864
2865 // Instruction: SLO (ASO)
2866 //
2867 // Operation: ASL memory location, followed by OR on accumulator
2868 //
2869 // Flags: N Z C I D V
2870 // / / / - - -
2871
2872#define DO_SLO setC(reg.d & 128); reg.d <<= 1;
2873
2874 case SLO_zpg_3:
2875 case SLO_zpg_x_4:
2876
2877 WRITE_TO_ZERO_PAGE
2878 DO_SLO
2879 CONTINUE
2880
2881 case SLO_zpg_4:
2882 case SLO_zpg_x_5:
2883
2884 WRITE_TO_ZERO_PAGE
2885 loadA(reg.a | reg.d);
2886 POLL_INT
2887 DONE
2888
2889 case SLO_abs_4:
2890 case SLO_abs_x_5:
2891 case SLO_abs_y_5:
2892 case SLO_ind_x_6:
2893 case SLO_ind_y_6:
2894
2895 WRITE_TO_ADDRESS
2896 DO_SLO
2897 CONTINUE
2898
2899 case SLO_abs_5:
2900 case SLO_abs_x_6:
2901 case SLO_abs_y_6:
2902 case SLO_ind_x_7:
2903 case SLO_ind_y_7:
2904
2905 WRITE_TO_ADDRESS
2906 loadA(reg.a | reg.d);
2907 POLL_INT
2908 DONE
2909
2910
2911 // Instruction: SRE (LSE)
2912 //
2913 // Operation: LSR, followed by EOR
2914 //
2915 // Flags: N Z C I D V
2916 // / / / - - -
2917
2918#define DO_SRE setC(reg.d & 1); reg.d >>= 1;
2919
2920 case SRE_zpg_3:
2921 case SRE_zpg_x_4:
2922
2923 WRITE_TO_ZERO_PAGE
2924 DO_SRE
2925 CONTINUE
2926
2927 case SRE_zpg_4:
2928 case SRE_zpg_x_5:
2929
2930 WRITE_TO_ZERO_PAGE
2931 loadA(reg.a ^ reg.d);
2932 POLL_INT
2933 DONE
2934
2935 case SRE_abs_4:
2936 case SRE_abs_x_5:
2937 case SRE_abs_y_5:
2938 case SRE_ind_x_6:
2939 case SRE_ind_y_6:
2940
2941 WRITE_TO_ADDRESS
2942 DO_SRE
2943 CONTINUE
2944
2945 case SRE_abs_5:
2946 case SRE_abs_x_6:
2947 case SRE_abs_y_6:
2948 case SRE_ind_x_7:
2949 case SRE_ind_y_7:
2950
2951 WRITE_TO_ADDRESS
2952 loadA(reg.a ^ reg.d);
2953 POLL_INT
2954 DONE
2955
2956
2957 // Instruction: TAS (SHS)
2958 //
2959 // Operation: SP := A & X, Mem := SP & (HI_BYTE(op) + 1)
2960 //
2961 // Flags: N Z C I D V
2962 // - - - - - -
2963
2964 case TAS_abs_y_3:
2965
2966 IDLE_READ_FROM_ADDRESS
2967
2968 reg.sp = reg.a & reg.x;
2969
2970 /* "There are two unstable conditions, the first is when a DMA is
2971 * going on while the instruction executes (the CPU is halted by
2972 * the VIC-II) then the & M+1 part drops off."
2973 */
2974
2975 reg.d = reg.a & reg.x & (rdyLineUp == clock ? 0xFF : reg.adh + 1);
2976
2977 /* "The other unstable condition is when the addressing/indexing
2978 * causes a page boundary crossing, in that case the highbyte of
2979 * the target address may become equal to the value stored."
2980 */
2981
2982 if (PAGE_BOUNDARY_CROSSED) {
2983 FIX_ADDR_HI;
2984 reg.adh = reg.a & reg.x & reg.adh;
2985 }
2986
2987 CONTINUE
2988
2989 case TAS_abs_y_4:
2990
2991 WRITE_TO_ADDRESS
2992 POLL_INT
2993 DONE
2994
2995 // Instruction: ANE
2996 //
2997 // Operation: A = X & op & (A | 0xEE) (taken from Frodo)
2998 //
2999 // Flags: N Z C I D V
3000 // / / - - - -
3001
3002 case ANE_imm:
3003
3004 READ_IMMEDIATE
3005 loadA(reg.x & reg.d & (reg.a | 0xEE));
3006 POLL_INT
3007 DONE
3008
3009
3010 // Instruction: LXA
3011 //
3012 // Operation: A = X = op & (A | 0xEE) (taken from Frodo)
3013 //
3014 // Flags: N Z C I D V
3015 // / / - - - -
3016
3017 case LXA_imm:
3018
3019 READ_IMMEDIATE
3020 reg.x = reg.d & (reg.a | 0xEE);
3021 loadA(reg.x);
3022 POLL_INT
3023 DONE
3024
3025 default:
3026
3027 fatalError;
3028 }
3029}
3030
3031void
3032Peddle::execute(int count)
3033{
3034 switch (cpuModel) {
3035
3036 case MOS_6502: execute<MOS_6502>(count); break;
3037 case MOS_6507: execute<MOS_6507>(count); break;
3038 case MOS_6510: execute<MOS_6510>(count); break;
3039 case MOS_8502: execute<MOS_8502>(count); break;
3040
3041 default:
3042 fatalError;
3043 }
3044}
3045
3046template <CPURevision C> void
3047Peddle::execute(int count)
3048{
3049 for (int j = 0; j < count; j++) { execute<C>(); }
3050}
3051
3052void
3053Peddle::executeInstruction()
3054{
3055 switch (cpuModel) {
3056
3057 case MOS_6502: executeInstruction<MOS_6502>(); break;
3058 case MOS_6507: executeInstruction<MOS_6507>(); break;
3059 case MOS_6510: executeInstruction<MOS_6510>(); break;
3060 case MOS_8502: executeInstruction<MOS_8502>(); break;
3061
3062 default:
3063 fatalError;
3064 }
3065}
3066
3067template <CPURevision C> void
3068Peddle::executeInstruction()
3069{
3070 // Execute a singe cycle
3071 execute<C>();
3072
3073 // Execute more cycles until we reach the fetch phase
3074 finishInstruction<C>();
3075}
3076
3077void
3078Peddle::executeInstruction(int count)
3079{
3080 switch (cpuModel) {
3081
3082 case MOS_6502: executeInstruction<MOS_6502>(count); break;
3083 case MOS_6507: executeInstruction<MOS_6507>(count); break;
3084 case MOS_6510: executeInstruction<MOS_6510>(count); break;
3085 case MOS_8502: executeInstruction<MOS_8502>(count); break;
3086
3087 default:
3088 fatalError;
3089 }
3090}
3091
3092template <CPURevision C> void
3093Peddle::executeInstruction(int count)
3094{
3095 for (int j = 0; j < count; j++) { executeInstruction<C>(); }
3096}
3097
3098void
3099Peddle::finishInstruction()
3100{
3101 switch (cpuModel) {
3102
3103 case MOS_6502: finishInstruction<MOS_6502>(); break;
3104 case MOS_6507: finishInstruction<MOS_6507>(); break;
3105 case MOS_6510: finishInstruction<MOS_6510>(); break;
3106 case MOS_8502: finishInstruction<MOS_8502>(); break;
3107
3108 default:
3109 fatalError;
3110 }
3111}
3112
3113template <CPURevision C> void
3114Peddle::finishInstruction()
3115{
3116 while (!inFetchPhase()) execute<C>();
3117}
3118
3119template <CPURevision C> void
3120Peddle::done() {
3121
3122 if (flags) {
3123
3124 if (flags & CPU_LOG_INSTRUCTION) {
3125
3126 debugger.logInstruction();
3127 instructionLogged();
3128 }
3129
3130 if ((flags & CPU_CHECK_BP) && debugger.breakpointMatches(reg.pc)) {
3131
3132 breakpointReached(reg.pc);
3133 }
3134 }
3135
3136 reg.pc0 = reg.pc;
3137 next = fetch;
3138}