load.rsannotatedload.rssource1335 lines · 43.7 KB · raw
1#[allow(clippy::wildcard_imports)]
2use super::*;

LDA: Load accumulator (8-bit)

5impl_read_op_u8!(
6    [
7        immediate -> lda_immediate_u8,
8        direct_page -> lda_direct_page_u8,
9        direct_page_x -> lda_direct_page_x_u8,
10        direct_page_indirect -> lda_direct_page_indirect_u8,
11        direct_page_indexed_indirect -> lda_direct_page_indexed_indirect_u8,
12        direct_page_indirect_indexed -> lda_direct_page_indirect_indexed_u8,
13        direct_page_indirect_long -> lda_direct_page_indirect_long_u8,
14        direct_page_indirect_long_indexed -> lda_direct_page_indirect_long_indexed_u8,
15        absolute -> lda_absolute_u8,
16        absolute_x -> lda_absolute_x_u8,
17        absolute_y -> lda_absolute_y_u8,
18        absolute_long -> lda_absolute_long_u8,
19        absolute_long_x -> lda_absolute_long_x_u8,
20        stack_relative -> lda_stack_relative_u8,
21        stack_relative_indirect_indexed -> lda_stack_relative_indirect_indexed_u8,
22    ]
23    (|registers, value| {
24        registers.a.set_lsb(value);
25
26        registers.p.zero = value == 0;
27        registers.p.negative = value.sign_bit();
28    })
29);

LDA: Load accumulator (16-bit)

32impl_read_op_u16!(
33    [
34        immediate -> lda_immediate_u16,
35        direct_page -> lda_direct_page_u16,
36        direct_page_x -> lda_direct_page_x_u16,
37        direct_page_indirect -> lda_direct_page_indirect_u16,
38        direct_page_indexed_indirect -> lda_direct_page_indexed_indirect_u16,
39        direct_page_indirect_indexed -> lda_direct_page_indirect_indexed_u16,
40        direct_page_indirect_long -> lda_direct_page_indirect_long_u16,
41        direct_page_indirect_long_indexed -> lda_direct_page_indirect_long_indexed_u16,
42        absolute -> lda_absolute_u16,
43        absolute_x -> lda_absolute_x_u16,
44        absolute_y -> lda_absolute_y_u16,
45        absolute_long -> lda_absolute_long_u16,
46        absolute_long_x -> lda_absolute_long_x_u16,
47        stack_relative -> lda_stack_relative_u16,
48        stack_relative_indirect_indexed -> lda_stack_relative_indirect_indexed_u16,
49    ]
50    (|registers, value| {
51        registers.a = value;
52
53        registers.p.zero = value == 0;
54        registers.p.negative = value.sign_bit();
55    })
56);

LDX: Load X register (8-bit)

59impl_read_op_u8!(
60    [
61        immediate -> ldx_immediate_u8,
62        direct_page -> ldx_direct_page_u8,
63        direct_page_y -> ldx_direct_page_y_u8,
64        absolute -> ldx_absolute_u8,
65        absolute_y -> ldx_absolute_y_u8,
66    ]
67    (|registers, value| {
68        registers.x = value.into();
69
70        registers.p.zero = value == 0;
71        registers.p.negative = value.sign_bit();
72    })
73);

LDX: Load X register (16-bit)

76impl_read_op_u16!(
77    [
78        immediate -> ldx_immediate_u16,
79        direct_page -> ldx_direct_page_u16,
80        direct_page_y -> ldx_direct_page_y_u16,
81        absolute -> ldx_absolute_u16,
82        absolute_y -> ldx_absolute_y_u16,
83    ]
84    (|registers, value| {
85        registers.x = value;
86
87        registers.p.zero = value == 0;
88        registers.p.negative = value.sign_bit();
89    })
90);

LDY: Load Y register (8-bit)

93impl_read_op_u8!(
94    [
95        immediate -> ldy_immediate_u8,
96        direct_page -> ldy_direct_page_u8,
97        direct_page_x -> ldy_direct_page_x_u8,
98        absolute -> ldy_absolute_u8,
99        absolute_x -> ldy_absolute_x_u8,
100    ]
101    (|registers, value| {
102        registers.y = value.into();
103
104        registers.p.zero = value == 0;
105        registers.p.negative = value.sign_bit();
106    })
107);

LDY: Load Y register (16-bit)

110impl_read_op_u16!(
111    [
112        immediate -> ldy_immediate_u16,
113        direct_page -> ldy_direct_page_u16,
114        direct_page_x -> ldy_direct_page_x_u16,
115        absolute -> ldy_absolute_u16,
116        absolute_x -> ldy_absolute_x_u16,
117    ]
118    (|registers, value| {
119        registers.y = value;
120
121        registers.p.zero = value == 0;
122        registers.p.negative = value.sign_bit();
123    })
124);
126macro_rules! impl_transfer_op {
127    (u8: $u8_name:ident, u16: $u16_name:ident, $from:ident -> $to:ident) => {
128        impl_registers_op!($u8_name, |registers| {
129            let value = registers.$from as u8;
130            registers.$to.set_lsb(value);
131
132            registers.p.zero = value == 0;
133            registers.p.negative = value.sign_bit();
134        });
135
136        impl_registers_op!($u16_name, |registers| {
137            let value = registers.$from;
138            registers.$to = value;
139
140            registers.p.zero = value == 0;
141            registers.p.negative = value.sign_bit();
142        });
143    };
144}

TAX: Transfer A to X

147impl_transfer_op!(u8: tax_u8, u16: tax_u16, a -> x);

TAY: Transfer A to Y

150impl_transfer_op!(u8: tay_u8, u16: tay_u16, a -> y);

TSX: Transfer S to X

153impl_transfer_op!(u8: tsx_u8, u16: tsx_u16, s -> x);

TXA: Transfer X to A

156impl_transfer_op!(u8: txa_u8, u16: txa_u16, x -> a);

TXY: Transfer X to Y

159impl_transfer_op!(u8: txy_u8, u16: txy_u16, x -> y);

TYA: Transfer Y to A

162impl_transfer_op!(u8: tya_u8, u16: tya_u16, y -> a);

TYX: Transfer Y to X

165impl_transfer_op!(u8: tyx_u8, u16: tyx_u16, y -> x);

TXS: Transfer X to S Does not use impl_transfer_op! because it is always a 16-bit operation unless in emulation mode, and because it does not set flags

170impl_registers_op!(txs, |registers| {
171    if registers.emulation_mode {
172        // S MSB is forced to $01 in emulation mode
173        registers.s = 0x0100 | (registers.x & 0x00FF);
174    } else {
175        registers.s = registers.x;
176    }
177});

TCD: Transfer C (16-bit accumulator) to D

180impl_registers_op!(tcd, |registers| {
181    let value = registers.a;
182    registers.d = value;
183
184    registers.p.zero = value == 0;
185    registers.p.negative = value.sign_bit();
186});

TCS: Transfer C (16-bit accumulator) to S

189impl_registers_op!(tcs, |registers| {
190    if registers.emulation_mode {
191        // TCS is an 8-bit operation when in emulation mode because S MSB is forced to $01
192        registers.s = 0x0100 | (registers.a & 0x00FF);
193    } else {
194        registers.s = registers.a;
195    }
196});

TDC: Transfer D to C (16-bit accumulator)

199impl_registers_op!(tdc, |registers| {
200    let value = registers.d;
201    registers.a = value;
202
203    registers.p.zero = value == 0;
204    registers.p.negative = value.sign_bit();
205});

TSC: Transfer S to C (16-bit accumulator)

208impl_registers_op!(tsc, |registers| {
209    let value = registers.s;
210    registers.a = value;
211
212    registers.p.zero = value == 0;
213    registers.p.negative = value.sign_bit();
214});

XBA: Exchange B and A accumulator bytes Not using impl_registers_op! because this instruction takes 3 cycles, not 2

218pub(crate) fn xba<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
219    match cpu.state.cycle {
220        1 => {
221            bus.idle();
222        }
223        2 => {
224            final_cycle(cpu, bus);
225
226            bus.idle();
227
228            cpu.registers.a = cpu.registers.a.swap_bytes();
229
230            // Flags are always based on low byte
231            cpu.registers.p.zero = cpu.registers.a & 0x00FF == 0;
232            cpu.registers.p.negative = cpu.registers.a.bit(7);
233        }
234        _ => invalid_cycle!(cpu),
235    }
236}
238macro_rules! store_register {
239    ($registers:expr, zero) => {
240        0_u16
241    };
242    ($registers:expr, $register:ident) => {
243        $registers.$register
244    };
245}
246
247macro_rules! impl_store_direct_page_u8 {
248    ($name:ident, $register:ident) => {
249        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
250            match cpu.state.cycle {
251                1 => {
252                    cpu.state.t0 = fetch_operand(cpu, bus);
253                    check_direct_page_low_byte(cpu);
254                }
255                2 => {
256                    // Idle cycle if D LSB is non-zero
257                    bus.idle();
258                }
259                3 => {
260                    final_cycle(cpu, bus);
261
262                    let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
263                    let value = store_register!(cpu.registers, $register);
264                    bus.write(address.into(), value as u8);
265                }
266                _ => invalid_cycle!(cpu),
267            }
268        }
269    };
270}
271
272macro_rules! impl_store_direct_page_u16 {
273    ($name:ident, $register:ident) => {
274        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
275            match cpu.state.cycle {
276                1 => {
277                    cpu.state.t0 = fetch_operand(cpu, bus);
278                    check_direct_page_low_byte(cpu);
279                }
280                2 => {
281                    // Idle cycle if D LSB is non-zero
282                    bus.idle();
283                }
284                3 => {
285                    let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
286                    let value = store_register!(cpu.registers, $register);
287                    bus.write(address.into(), value.lsb());
288                }
289                4 => {
290                    final_cycle(cpu, bus);
291
292                    let address = cpu.registers.d.wrapping_add(cpu.state.t0.into()).wrapping_add(1);
293                    let value = store_register!(cpu.registers, $register);
294                    bus.write(address.into(), value.msb());
295                }
296                _ => invalid_cycle!(cpu),
297            }
298        }
299    };
300}
301
302macro_rules! impl_store_direct_page_indexed_u8 {
303    ($name:ident, $register:ident, index: $index:ident) => {
304        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
305            match cpu.state.cycle {
306                1 => {
307                    cpu.state.t0 = fetch_operand(cpu, bus);
308                    check_direct_page_low_byte(cpu);
309                }
310                2 => {
311                    // Idle cycle if D LSB is non-zero
312                    bus.idle();
313                }
314                3 => {
315                    // Idle cycle for indexing
316                    bus.idle();
317                }
318                4 => {
319                    final_cycle(cpu, bus);
320
321                    let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.$index);
322                    let value = store_register!(cpu.registers, $register);
323                    bus.write(address.into(), value as u8);
324                }
325                _ => invalid_cycle!(cpu),
326            }
327        }
328    };
329}
330
331macro_rules! impl_store_direct_page_indexed_u16 {
332    ($name:ident, $register:ident, index: $index:ident) => {
333        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
334            match cpu.state.cycle {
335                1 => {
336                    cpu.state.t0 = fetch_operand(cpu, bus);
337                    check_direct_page_low_byte(cpu);
338                }
339                2 => {
340                    // Idle cycle if D LSB is non-zero
341                    bus.idle();
342                }
343                3 => {
344                    // Idle cycle for indexing
345                    bus.idle();
346                }
347                4 => {
348                    let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.$index);
349                    let value = store_register!(cpu.registers, $register);
350                    bus.write(address.into(), value.lsb());
351                }
352                5 => {
353                    final_cycle(cpu, bus);
354
355                    let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.$index);
356                    let value = store_register!(cpu.registers, $register);
357                    bus.write(address.wrapping_add(1).into(), value.msb());
358                }
359                _ => invalid_cycle!(cpu),
360            }
361        }
362    };
363}
364
365macro_rules! impl_store_absolute_u8 {
366    ($name:ident, $register:ident) => {
367        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
368            match cpu.state.cycle {
369                1 => {
370                    cpu.state.t0 = fetch_operand(cpu, bus);
371                }
372                2 => {
373                    cpu.state.t1 = fetch_operand(cpu, bus);
374                }
375                3 => {
376                    final_cycle(cpu, bus);
377
378                    let address =
379                        u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.registers.dbr, 0]);
380                    let value = store_register!(cpu.registers, $register);
381                    bus.write(address, value as u8);
382                }
383                _ => invalid_cycle!(cpu),
384            }
385        }
386    };
387}
388
389macro_rules! impl_store_absolute_u16 {
390    ($name:ident, $register:ident) => {
391        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
392            match cpu.state.cycle {
393                1 => {
394                    cpu.state.t0 = fetch_operand(cpu, bus);
395                }
396                2 => {
397                    cpu.state.t1 = fetch_operand(cpu, bus);
398                }
399                3 => {
400                    let address =
401                        u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.registers.dbr, 0]);
402                    let value = store_register!(cpu.registers, $register);
403                    bus.write(address, value.lsb());
404                }
405                4 => {
406                    final_cycle(cpu, bus);
407
408                    let base_addr =
409                        u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.registers.dbr, 0]);
410                    let address = (base_addr + 1) & B::ADDRESS_MASK;
411                    let value = store_register!(cpu.registers, $register);
412                    bus.write(address, value.msb());
413                }
414                _ => invalid_cycle!(cpu),
415            }
416        }
417    };
418}
419
420macro_rules! impl_store_absolute_indexed_u8 {
421    ($name:ident, $register:ident, index: $index:ident) => {
422        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
423            match cpu.state.cycle {
424                1 => {
425                    cpu.state.t0 = fetch_operand(cpu, bus);
426                }
427                2 => {
428                    cpu.state.t1 = fetch_operand(cpu, bus);
429                }
430                3 => {
431                    // Idle cycle for indexing
432                    bus.idle();
433                }
434                4 => {
435                    final_cycle(cpu, bus);
436
437                    let base_addr =
438                        u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.registers.dbr, 0]);
439                    let index: u32 = cpu.registers.$index.into();
440                    let address = (base_addr + index) & B::ADDRESS_MASK;
441                    let value = store_register!(cpu.registers, $register);
442                    bus.write(address, value as u8);
443                }
444                _ => invalid_cycle!(cpu),
445            }
446        }
447    };
448}
449
450macro_rules! impl_store_absolute_indexed_u16 {
451    ($name:ident, $register:ident, index: $index:ident) => {
452        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
453            match cpu.state.cycle {
454                1 => {
455                    cpu.state.t0 = fetch_operand(cpu, bus);
456                }
457                2 => {
458                    cpu.state.t1 = fetch_operand(cpu, bus);
459                }
460                3 => {
461                    // Idle cycle for indexing
462                    bus.idle();
463                }
464                4 => {
465                    let base_addr =
466                        u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.registers.dbr, 0]);
467                    let index: u32 = cpu.registers.$index.into();
468                    let address = (base_addr + index) & B::ADDRESS_MASK;
469                    let value = store_register!(cpu.registers, $register);
470                    bus.write(address, value.lsb());
471                }
472                5 => {
473                    final_cycle(cpu, bus);
474
475                    let base_addr =
476                        u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.registers.dbr, 0]);
477                    let index: u32 = cpu.registers.$index.into();
478                    let address = (base_addr + index + 1) & B::ADDRESS_MASK;
479                    let value = store_register!(cpu.registers, $register);
480                    bus.write(address, value.msb());
481                }
482                _ => invalid_cycle!(cpu),
483            }
484        }
485    };
486}

STA: Store accumulator

489impl_store_direct_page_u8!(sta_direct_page_u8, a);
490impl_store_direct_page_u16!(sta_direct_page_u16, a);
491impl_store_direct_page_indexed_u8!(sta_direct_page_x_u8, a, index: x);
492impl_store_direct_page_indexed_u16!(sta_direct_page_x_u16, a, index: x);
493impl_store_absolute_u8!(sta_absolute_u8, a);
494impl_store_absolute_u16!(sta_absolute_u16, a);
495impl_store_absolute_indexed_u8!(sta_absolute_x_u8, a, index: x);
496impl_store_absolute_indexed_u16!(sta_absolute_x_u16, a, index: x);
497impl_store_absolute_indexed_u8!(sta_absolute_y_u8, a, index: y);
498impl_store_absolute_indexed_u16!(sta_absolute_y_u16, a, index: y);

Remaining STA addressing modes do not use macros because they're unique to STA

502pub(crate) fn sta_direct_page_indirect_u8<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
503    match cpu.state.cycle {
504        1 => {
505            cpu.state.t0 = fetch_operand(cpu, bus);
506            check_direct_page_low_byte(cpu);
507        }
508        2 => {
509            // Idle cycle if D LSB is non-zero
510            bus.idle();
511        }
512        3 => {
513            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
514            cpu.state.t1 = bus.read(address.into());
515        }
516        4 => {
517            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
518            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
519        }
520        5 => {
521            final_cycle(cpu, bus);
522
523            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
524            bus.write(address, cpu.registers.a as u8);
525        }
526        _ => invalid_cycle!(cpu),
527    }
528}
530pub(crate) fn sta_direct_page_indirect_u16<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
531    match cpu.state.cycle {
532        1 => {
533            cpu.state.t0 = fetch_operand(cpu, bus);
534            check_direct_page_low_byte(cpu);
535        }
536        2 => {
537            // Idle cycle if D LSB is non-zero
538            bus.idle();
539        }
540        3 => {
541            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
542            cpu.state.t1 = bus.read(address.into());
543        }
544        4 => {
545            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
546            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
547        }
548        5 => {
549            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
550            bus.write(address, cpu.registers.a.lsb());
551        }
552        6 => {
553            final_cycle(cpu, bus);
554
555            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
556            bus.write((address + 1) & B::ADDRESS_MASK, cpu.registers.a.msb());
557        }
558        _ => invalid_cycle!(cpu),
559    }
560}
561
562pub(crate) fn sta_direct_page_indexed_indirect_u8<B: BusInterface>(
563    cpu: &mut Wdc65816,
564    bus: &mut B,
565) {
566    match cpu.state.cycle {
567        1 => {
568            cpu.state.t0 = fetch_operand(cpu, bus);
569            check_direct_page_low_byte(cpu);
570        }
571        2 | 3 => {
572            // Idle cycles if D LSB is non-zero (2) and for indexing (3)
573            bus.idle();
574        }
575        4 => {
576            let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.x);
577            cpu.state.t1 = bus.read(address.into());
578        }
579        5 => {
580            let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.x);
581            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
582        }
583        6 => {
584            final_cycle(cpu, bus);
585
586            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
587            bus.write(address, cpu.registers.a as u8);
588        }
589        _ => invalid_cycle!(cpu),
590    }
591}
592
593pub(crate) fn sta_direct_page_indexed_indirect_u16<B: BusInterface>(
594    cpu: &mut Wdc65816,
595    bus: &mut B,
596) {
597    match cpu.state.cycle {
598        1 => {
599            cpu.state.t0 = fetch_operand(cpu, bus);
600            check_direct_page_low_byte(cpu);
601        }
602        2 | 3 => {
603            // Idle cycles if D LSB is non-zero (2) and for indexing (3)
604            bus.idle();
605        }
606        4 => {
607            let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.x);
608            cpu.state.t1 = bus.read(address.into());
609        }
610        5 => {
611            let address = index_direct_page(cpu, cpu.state.t0, cpu.registers.x);
612            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
613        }
614        6 => {
615            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
616            bus.write(address, cpu.registers.a.lsb());
617        }
618        7 => {
619            final_cycle(cpu, bus);
620
621            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
622            bus.write((address + 1) & B::ADDRESS_MASK, cpu.registers.a.msb());
623        }
624        _ => invalid_cycle!(cpu),
625    }
626}
627
628pub(crate) fn sta_direct_page_indirect_indexed_u8<B: BusInterface>(
629    cpu: &mut Wdc65816,
630    bus: &mut B,
631) {
632    match cpu.state.cycle {
633        1 => {
634            cpu.state.t0 = fetch_operand(cpu, bus);
635            check_direct_page_low_byte(cpu);
636        }
637        2 | 5 => {
638            // Idle cycles for if D LSB is non-zero (2) and for indexing (5)
639            bus.idle();
640        }
641        3 => {
642            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
643            cpu.state.t1 = bus.read(address.into());
644        }
645        4 => {
646            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
647            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
648        }
649        6 => {
650            final_cycle(cpu, bus);
651
652            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
653            let address = (base_addr + u32::from(cpu.registers.y)) & B::ADDRESS_MASK;
654            bus.write(address, cpu.registers.a as u8);
655        }
656        _ => invalid_cycle!(cpu),
657    }
658}
659
660pub(crate) fn sta_direct_page_indirect_indexed_u16<B: BusInterface>(
661    cpu: &mut Wdc65816,
662    bus: &mut B,
663) {
664    match cpu.state.cycle {
665        1 => {
666            cpu.state.t0 = fetch_operand(cpu, bus);
667            check_direct_page_low_byte(cpu);
668        }
669        2 | 5 => {
670            // Idle cycles for if D LSB is non-zero (2) and for indexing (5)
671            bus.idle();
672        }
673        3 => {
674            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
675            cpu.state.t1 = bus.read(address.into());
676        }
677        4 => {
678            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
679            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
680        }
681        6 => {
682            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
683            let address = (base_addr + u32::from(cpu.registers.y)) & B::ADDRESS_MASK;
684            bus.write(address, cpu.registers.a.lsb());
685        }
686        7 => {
687            final_cycle(cpu, bus);
688
689            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
690            let address = (base_addr + u32::from(cpu.registers.y) + 1) & B::ADDRESS_MASK;
691            bus.write(address, cpu.registers.a.msb());
692        }
693        _ => invalid_cycle!(cpu),
694    }
695}
696
697pub(crate) fn sta_direct_page_indirect_long_u8<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
698    match cpu.state.cycle {
699        1 => {
700            cpu.state.t0 = fetch_operand(cpu, bus);
701            check_direct_page_low_byte(cpu);
702        }
703        2 => {
704            // Idle cycle if D LSB is non-zero
705            bus.idle();
706        }
707        3 => {
708            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
709            cpu.state.t1 = bus.read(address.into());
710        }
711        4 => {
712            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
713            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
714        }
715        5 => {
716            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
717            cpu.state.t3 = bus.read(address.wrapping_add(2).into());
718        }
719        6 => {
720            final_cycle(cpu, bus);
721
722            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.state.t3, 0]);
723            bus.write(address, cpu.registers.a as u8);
724        }
725        _ => invalid_cycle!(cpu),
726    }
727}
728
729pub(crate) fn sta_direct_page_indirect_long_u16<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
730    match cpu.state.cycle {
731        1 => {
732            cpu.state.t0 = fetch_operand(cpu, bus);
733            check_direct_page_low_byte(cpu);
734        }
735        2 => {
736            // Idle cycle if D LSB is non-zero
737            bus.idle();
738        }
739        3 => {
740            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
741            cpu.state.t1 = bus.read(address.into());
742        }
743        4 => {
744            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
745            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
746        }
747        5 => {
748            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
749            cpu.state.t3 = bus.read(address.wrapping_add(2).into());
750        }
751        6 => {
752            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.state.t3, 0]);
753            bus.write(address, cpu.registers.a.lsb());
754        }
755        7 => {
756            final_cycle(cpu, bus);
757
758            let address = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.state.t3, 0]);
759            bus.write((address + 1) & B::ADDRESS_MASK, cpu.registers.a.msb());
760        }
761        _ => invalid_cycle!(cpu),
762    }
763}
764
765pub(crate) fn sta_direct_page_indirect_long_indexed_u8<B: BusInterface>(
766    cpu: &mut Wdc65816,
767    bus: &mut B,
768) {
769    match cpu.state.cycle {
770        1 => {
771            cpu.state.t0 = fetch_operand(cpu, bus);
772            check_direct_page_low_byte(cpu);
773        }
774        2 => {
775            // Idle cycle if D LSB is non-zero
776            bus.idle();
777        }
778        3 => {
779            let address = index_direct_page(cpu, cpu.state.t0, 0);
780            cpu.state.t1 = bus.read(address.into());
781        }
782        4 => {
783            let address = index_direct_page(cpu, cpu.state.t0, 1);
784            cpu.state.t2 = bus.read(address.into());
785        }
786        5 => {
787            let address = index_direct_page(cpu, cpu.state.t0, 2);
788            cpu.state.t3 = bus.read(address.into());
789        }
790        6 => {
791            final_cycle(cpu, bus);
792
793            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.state.t3, 0]);
794            let address = (base_addr + u32::from(cpu.registers.y)) & B::ADDRESS_MASK;
795            bus.write(address, cpu.registers.a as u8);
796        }
797        _ => invalid_cycle!(cpu),
798    }
799}
800
801pub(crate) fn sta_direct_page_indirect_long_indexed_u16<B: BusInterface>(
802    cpu: &mut Wdc65816,
803    bus: &mut B,
804) {
805    match cpu.state.cycle {
806        1 => {
807            cpu.state.t0 = fetch_operand(cpu, bus);
808            check_direct_page_low_byte(cpu);
809        }
810        2 => {
811            // Idle cycle if D LSB is non-zero
812            bus.idle();
813        }
814        3 => {
815            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
816            cpu.state.t1 = bus.read(address.into());
817        }
818        4 => {
819            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
820            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
821        }
822        5 => {
823            let address = cpu.registers.d.wrapping_add(cpu.state.t0.into());
824            cpu.state.t3 = bus.read(address.wrapping_add(2).into());
825        }
826        6 => {
827            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.state.t3, 0]);
828            let address = (base_addr + u32::from(cpu.registers.y)) & B::ADDRESS_MASK;
829            bus.write(address, cpu.registers.a.lsb());
830        }
831        7 => {
832            final_cycle(cpu, bus);
833
834            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.state.t3, 0]);
835            let address = (base_addr + u32::from(cpu.registers.y) + 1) & B::ADDRESS_MASK;
836            bus.write(address, cpu.registers.a.msb());
837        }
838        _ => invalid_cycle!(cpu),
839    }
840}
841
842pub(crate) fn sta_absolute_long_u8<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
843    match cpu.state.cycle {
844        1 => {
845            cpu.state.t0 = fetch_operand(cpu, bus);
846        }
847        2 => {
848            cpu.state.t1 = fetch_operand(cpu, bus);
849        }
850        3 => {
851            cpu.state.t2 = fetch_operand(cpu, bus);
852        }
853        4 => {
854            final_cycle(cpu, bus);
855
856            let address = u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.state.t2, 0]);
857            bus.write(address, cpu.registers.a as u8);
858        }
859        _ => invalid_cycle!(cpu),
860    }
861}
862
863pub(crate) fn sta_absolute_long_u16<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
864    match cpu.state.cycle {
865        1 => {
866            cpu.state.t0 = fetch_operand(cpu, bus);
867        }
868        2 => {
869            cpu.state.t1 = fetch_operand(cpu, bus);
870        }
871        3 => {
872            cpu.state.t2 = fetch_operand(cpu, bus);
873        }
874        4 => {
875            let address = u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.state.t2, 0]);
876            bus.write(address, cpu.registers.a.lsb());
877        }
878        5 => {
879            final_cycle(cpu, bus);
880
881            let base_addr = u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.state.t2, 0]);
882            let address = (base_addr + 1) & B::ADDRESS_MASK;
883            bus.write(address, cpu.registers.a.msb());
884        }
885        _ => invalid_cycle!(cpu),
886    }
887}
888
889pub(crate) fn sta_absolute_long_x_u8<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
890    match cpu.state.cycle {
891        1 => {
892            cpu.state.t0 = fetch_operand(cpu, bus);
893        }
894        2 => {
895            cpu.state.t1 = fetch_operand(cpu, bus);
896        }
897        3 => {
898            cpu.state.t2 = fetch_operand(cpu, bus);
899        }
900        4 => {
901            final_cycle(cpu, bus);
902
903            let base_addr = u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.state.t2, 0]);
904            let index: u32 = cpu.registers.x.into();
905            let address = (base_addr + index) & B::ADDRESS_MASK;
906            bus.write(address, cpu.registers.a as u8);
907        }
908        _ => invalid_cycle!(cpu),
909    }
910}
911
912pub(crate) fn sta_absolute_long_x_u16<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
913    match cpu.state.cycle {
914        1 => {
915            cpu.state.t0 = fetch_operand(cpu, bus);
916        }
917        2 => {
918            cpu.state.t1 = fetch_operand(cpu, bus);
919        }
920        3 => {
921            cpu.state.t2 = fetch_operand(cpu, bus);
922        }
923        4 => {
924            let base_addr = u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.state.t2, 0]);
925            let index: u32 = cpu.registers.x.into();
926            let address = (base_addr + index) & B::ADDRESS_MASK;
927            bus.write(address, cpu.registers.a.lsb());
928        }
929        5 => {
930            final_cycle(cpu, bus);
931
932            let base_addr = u32::from_le_bytes([cpu.state.t0, cpu.state.t1, cpu.state.t2, 0]);
933            let index: u32 = cpu.registers.x.into();
934            let address = (base_addr + index + 1) & B::ADDRESS_MASK;
935            bus.write(address, cpu.registers.a.msb());
936        }
937        _ => invalid_cycle!(cpu),
938    }
939}
940
941pub(crate) fn sta_stack_relative_u8<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
942    match cpu.state.cycle {
943        1 => {
944            cpu.state.t0 = fetch_operand(cpu, bus);
945        }
946        2 => {
947            // Idle cycle for indexing
948            bus.idle();
949        }
950        3 => {
951            final_cycle(cpu, bus);
952
953            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
954            bus.write(address.into(), cpu.registers.a as u8);
955        }
956        _ => invalid_cycle!(cpu),
957    }
958}
959
960pub(crate) fn sta_stack_relative_u16<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
961    match cpu.state.cycle {
962        1 => {
963            cpu.state.t0 = fetch_operand(cpu, bus);
964        }
965        2 => {
966            // Idle cycle for indexing
967            bus.idle();
968        }
969        3 => {
970            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
971            bus.write(address.into(), cpu.registers.a.lsb());
972        }
973        4 => {
974            final_cycle(cpu, bus);
975
976            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
977            bus.write(address.wrapping_add(1).into(), cpu.registers.a.msb());
978        }
979        _ => invalid_cycle!(cpu),
980    }
981}
982
983pub(crate) fn sta_stack_relative_indirect_indexed_u8<B: BusInterface>(
984    cpu: &mut Wdc65816,
985    bus: &mut B,
986) {
987    match cpu.state.cycle {
988        1 => {
989            cpu.state.t0 = fetch_operand(cpu, bus);
990        }
991        2 | 5 => {
992            // Idle cycles for stack indexing (2) and for address indexing (5)
993            bus.idle();
994        }
995        3 => {
996            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
997            cpu.state.t1 = bus.read(address.into());
998        }
999        4 => {
1000            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
1001            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
1002        }
1003        6 => {
1004            final_cycle(cpu, bus);
1005
1006            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
1007            let address = (base_addr + u32::from(cpu.registers.y)) & B::ADDRESS_MASK;
1008            bus.write(address, cpu.registers.a as u8);
1009        }
1010        _ => invalid_cycle!(cpu),
1011    }
1012}
1013
1014pub(crate) fn sta_stack_relative_indirect_indexed_u16<B: BusInterface>(
1015    cpu: &mut Wdc65816,
1016    bus: &mut B,
1017) {
1018    match cpu.state.cycle {
1019        1 => {
1020            cpu.state.t0 = fetch_operand(cpu, bus);
1021        }
1022        2 | 5 => {
1023            // Idle cycles for stack indexing (2) and for address indexing (5)
1024            bus.idle();
1025        }
1026        3 => {
1027            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
1028            cpu.state.t1 = bus.read(address.into());
1029        }
1030        4 => {
1031            let address = cpu.registers.s.wrapping_add(cpu.state.t0.into());
1032            cpu.state.t2 = bus.read(address.wrapping_add(1).into());
1033        }
1034        6 => {
1035            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
1036            let address = (base_addr + u32::from(cpu.registers.y)) & B::ADDRESS_MASK;
1037            bus.write(address, cpu.registers.a.lsb());
1038        }
1039        7 => {
1040            final_cycle(cpu, bus);
1041
1042            let base_addr = u32::from_le_bytes([cpu.state.t1, cpu.state.t2, cpu.registers.dbr, 0]);
1043            let address = (base_addr + u32::from(cpu.registers.y) + 1) & B::ADDRESS_MASK;
1044            bus.write(address, cpu.registers.a.msb());
1045        }
1046        _ => invalid_cycle!(cpu),
1047    }
1048}

STX: Store X register

1051impl_store_direct_page_u8!(stx_direct_page_u8, x);
1052impl_store_direct_page_u16!(stx_direct_page_u16, x);
1053impl_store_direct_page_indexed_u8!(stx_direct_page_y_u8, x, index: y);
1054impl_store_direct_page_indexed_u16!(stx_direct_page_y_u16, x, index: y);
1055impl_store_absolute_u8!(stx_absolute_u8, x);
1056impl_store_absolute_u16!(stx_absolute_u16, x);

STY: Store Y register

1059impl_store_direct_page_u8!(sty_direct_page_u8, y);
1060impl_store_direct_page_u16!(sty_direct_page_u16, y);
1061impl_store_direct_page_indexed_u8!(sty_direct_page_x_u8, y, index: x);
1062impl_store_direct_page_indexed_u16!(sty_direct_page_x_u16, y, index: x);
1063impl_store_absolute_u8!(sty_absolute_u8, y);
1064impl_store_absolute_u16!(sty_absolute_u16, y);

STZ: Store zero

1067impl_store_direct_page_u8!(stz_direct_page_u8, zero);
1068impl_store_direct_page_u16!(stz_direct_page_u16, zero);
1069impl_store_direct_page_indexed_u8!(stz_direct_page_x_u8, zero, index: x);
1070impl_store_direct_page_indexed_u16!(stz_direct_page_x_u16, zero, index: x);
1071impl_store_absolute_u8!(stz_absolute_u8, zero);
1072impl_store_absolute_u16!(stz_absolute_u16, zero);
1073impl_store_absolute_indexed_u8!(stz_absolute_x_u8, zero, index: x);
1074impl_store_absolute_indexed_u16!(stz_absolute_x_u16, zero, index: x);
1076macro_rules! impl_push_u8 {
1077    ($name:ident, $register:ident) => {
1078        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1079            match cpu.state.cycle {
1080                1 => {
1081                    bus.idle();
1082                }
1083                2 => {
1084                    final_cycle(cpu, bus);
1085
1086                    bus.write(cpu.registers.s.into(), cpu.registers.$register as u8);
1087                    cpu.registers.s = cpu.registers.s.wrapping_sub(1);
1088
1089                    if cpu.registers.emulation_mode {
1090                        ensure_page_1_stack(&mut cpu.registers);
1091                    }
1092                }
1093                _ => invalid_cycle!(cpu),
1094            }
1095        }
1096    };
1097}
1098
1099macro_rules! impl_push_u16 {
1100    ($name:ident, $register:ident) => {
1101        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1102            match cpu.state.cycle {
1103                1 => {
1104                    bus.idle();
1105                }
1106                2 => {
1107                    bus.write(cpu.registers.s.into(), cpu.registers.$register.msb());
1108                    cpu.registers.s = cpu.registers.s.wrapping_sub(1);
1109                }
1110                3 => {
1111                    final_cycle(cpu, bus);
1112
1113                    bus.write(cpu.registers.s.into(), cpu.registers.$register as u8);
1114                    cpu.registers.s = cpu.registers.s.wrapping_sub(1);
1115
1116                    // Emulation mode check necessary for PHD
1117                    // The second write is allowed to go outside of page 1 in emulation mode, but
1118                    // the stack gets forced back into page 1 afterwards
1119                    if cpu.registers.emulation_mode {
1120                        ensure_page_1_stack(&mut cpu.registers);
1121                    }
1122                }
1123                _ => invalid_cycle!(cpu),
1124            }
1125        }
1126    };
1127}

PHA: Push accumulator

1130impl_push_u8!(pha_u8, a);
1131impl_push_u16!(pha_u16, a);

PHX: Push X register

1134impl_push_u8!(phx_u8, x);
1135impl_push_u16!(phx_u16, x);

PHY: Push Y register

1138impl_push_u8!(phy_u8, y);
1139impl_push_u16!(phy_u16, y);

PHB: Push data bank register

1142impl_push_u8!(phb, dbr);

PHD: Push direct page register

1145impl_push_u16!(phd, d);

PHK: Push K register (program bank register)

1148impl_push_u8!(phk, pbr);

PHP: Push processor status register

1151pub(crate) fn php<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1152    match cpu.state.cycle {
1153        1 => {
1154            bus.idle();
1155        }
1156        2 => {
1157            final_cycle(cpu, bus);
1158
1159            bus.write(cpu.registers.s.into(), cpu.registers.p.into());
1160            cpu.registers.s = cpu.registers.s.wrapping_sub(1);
1161
1162            if cpu.registers.emulation_mode {
1163                ensure_page_1_stack(&mut cpu.registers);
1164            }
1165        }
1166        _ => invalid_cycle!(cpu),
1167    }
1168}
1170macro_rules! impl_pull_u8 {
1171    (@write dbr, $registers:expr, $value:expr) => {
1172        $registers.dbr = $value;
1173    };
1174    (@write $register:ident, $registers:expr, $value:expr) => {
1175        $registers.$register.set_lsb($value);
1176    };
1177    ($name:ident, $register:ident) => {
1178        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1179            match cpu.state.cycle {
1180                1 | 2 => {
1181                    bus.idle();
1182                }
1183                3 => {
1184                    final_cycle(cpu, bus);
1185
1186                    cpu.registers.s = cpu.registers.s.wrapping_add(1);
1187
1188                    if cpu.registers.emulation_mode {
1189                        ensure_page_1_stack(&mut cpu.registers);
1190                    }
1191
1192                    let value = bus.read(cpu.registers.s.into());
1193                    impl_pull_u8!(@write $register, cpu.registers, value);
1194
1195                    cpu.registers.p.zero = value == 0;
1196                    cpu.registers.p.negative = value.sign_bit();
1197                }
1198                _ => invalid_cycle!(cpu)
1199            }
1200        }
1201    }
1202}
1203
1204macro_rules! impl_pull_u16 {
1205    ($name:ident, $register:ident) => {
1206        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1207            match cpu.state.cycle {
1208                1 | 2 => {
1209                    bus.idle();
1210                }
1211                3 => {
1212                    cpu.registers.s = cpu.registers.s.wrapping_add(1);
1213                    cpu.state.t0 = bus.read(cpu.registers.s.into());
1214                }
1215                4 => {
1216                    final_cycle(cpu, bus);
1217
1218                    cpu.registers.s = cpu.registers.s.wrapping_add(1);
1219                    let value_msb = bus.read(cpu.registers.s.into());
1220                    let value = u16::from_le_bytes([cpu.state.t0, value_msb]);
1221                    cpu.registers.$register = value;
1222
1223                    cpu.registers.p.zero = value == 0;
1224                    cpu.registers.p.negative = value.sign_bit();
1225
1226                    // Emulation mode check necessary for PLD, similar to PHD
1227                    if cpu.registers.emulation_mode {
1228                        ensure_page_1_stack(&mut cpu.registers);
1229                    }
1230                }
1231                _ => invalid_cycle!(cpu),
1232            }
1233        }
1234    };
1235}

PLA: Pull accumulator

1238impl_pull_u8!(pla_u8, a);
1239impl_pull_u16!(pla_u16, a);

PLX: Pull X register

1242impl_pull_u8!(plx_u8, x);
1243impl_pull_u16!(plx_u16, x);

PLY: Pull Y register

1246impl_pull_u8!(ply_u8, y);
1247impl_pull_u16!(ply_u16, y);

PLB: Pull data bank register

1250impl_pull_u8!(plb, dbr);

PLD: Pull direct page register

1253impl_pull_u16!(pld, d);

PLP: Pull processor status register

1256pub(crate) fn plp<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1257    match cpu.state.cycle {
1258        1 | 2 => {
1259            bus.idle();
1260        }
1261        3 => {
1262            final_cycle(cpu, bus);
1263
1264            cpu.registers.s = cpu.registers.s.wrapping_add(1);
1265
1266            if cpu.registers.emulation_mode {
1267                ensure_page_1_stack(&mut cpu.registers);
1268
1269                // m and x flags are forced to 1 in emulation mode
1270                let value = 0x30 | bus.read(cpu.registers.s.into());
1271                cpu.registers.p = value.into();
1272            } else {
1273                cpu.registers.p = bus.read(cpu.registers.s.into()).into();
1274
1275                if cpu.registers.p.index_size == SizeBits::Eight {
1276                    // Immediately truncate index registers to 8 bits
1277                    cpu.registers.x &= 0x00FF;
1278                    cpu.registers.y &= 0x00FF;
1279                }
1280            }
1281        }
1282        _ => invalid_cycle!(cpu),
1283    }
1284}
1286macro_rules! impl_move {
1287    ($name:ident, $index_inc_method:ident) => {
1288        pub(crate) fn $name<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
1289            match cpu.state.cycle {
1290                1 => {
1291                    cpu.registers.dbr = fetch_operand(cpu, bus);
1292                }
1293                2 => {
1294                    cpu.state.t0 = fetch_operand(cpu, bus);
1295                }
1296                3 => {
1297                    let address = u24_address(cpu.state.t0, cpu.registers.x);
1298                    cpu.state.t1 = bus.read(address);
1299                }
1300                4 => {
1301                    let address = u24_address(cpu.registers.dbr, cpu.registers.y);
1302                    bus.write(address, cpu.state.t1);
1303                }
1304                5 => {
1305                    bus.idle();
1306                }
1307                6 => {
1308                    final_cycle(cpu, bus);
1309
1310                    bus.idle();
1311
1312                    cpu.registers.a = cpu.registers.a.wrapping_sub(1);
1313                    if cpu.registers.a != 0xFFFF {
1314                        cpu.registers.pc = cpu.registers.pc.wrapping_sub(3);
1315                    }
1316
1317                    cpu.registers.x = cpu.registers.x.$index_inc_method(1);
1318                    cpu.registers.y = cpu.registers.y.$index_inc_method(1);
1319
1320                    if cpu.registers.p.index_size == SizeBits::Eight {
1321                        cpu.registers.x &= 0x00FF;
1322                        cpu.registers.y &= 0x00FF;
1323                    }
1324                }
1325                _ => invalid_cycle!(cpu),
1326            }
1327        }
1328    };
1329}

MVN: Move memory negative

1332impl_move!(mvn, wrapping_add);

MVP: Move memory positive

1335impl_move!(mvp, wrapping_sub);