1#[allow(clippy::wildcard_imports)]
2use super::*;
3use std::mem;
4
5macro_rules! impl_flag_op {
6    ($name:ident, $flag:ident = $value:expr) => {
7        impl_registers_op!($name, |registers| {
8            registers.p.$flag = $value;
9        });
10    };
11}

CLC: Clear carry flag

14impl_flag_op!(clc, carry = false);

CLD: Clear decimal mode flag

17impl_flag_op!(cld, decimal_mode = false);

CLI: Clear interrupt disable flag

20impl_flag_op!(cli, irq_disabled = false);

CLV: Clear overflow flag

23impl_flag_op!(clv, overflow = false);

SEC: Set carry flag

26impl_flag_op!(sec, carry = true);

SED: Set decimal mode flag

29impl_flag_op!(sed, decimal_mode = true);

SEI: Set interrupt disable flag

32impl_flag_op!(sei, irq_disabled = true);

XCE: Exchange carry and emulation mode flags

35impl_registers_op!(xce, |registers| {
36    mem::swap(&mut registers.p.carry, &mut registers.emulation_mode);
37
38    if registers.emulation_mode {
39        // Force on m and x flags, and force stack to page 1
40        registers.p.accumulator_size = SizeBits::Eight;
41        registers.p.index_size = SizeBits::Eight;
42        ensure_page_1_stack(registers);
43
44        // Force index registers to 8 bits
45        registers.x &= 0x00FF;
46        registers.y &= 0x00FF;
47    }
48});

REP: Reset processor status bits

51pub(crate) fn rep<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
52    match cpu.state.cycle {
53        1 => {
54            cpu.state.t0 = fetch_operand(cpu, bus);
55        }
56        2 => {
57            final_cycle(cpu, bus);
58
59            bus.idle();
60
61            let mask = if cpu.registers.emulation_mode {
62                // Cannot clear m or x flag while in emulation mode
63                !cpu.state.t0 | 0x30
64            } else {
65                !cpu.state.t0
66            };
67            cpu.registers.p = (u8::from(cpu.registers.p) & mask).into();
68        }
69        _ => invalid_cycle!(cpu),
70    }
71}

SEP: Set processor status bits

74pub(crate) fn sep<B: BusInterface>(cpu: &mut Wdc65816, bus: &mut B) {
75    match cpu.state.cycle {
76        1 => {
77            cpu.state.t0 = fetch_operand(cpu, bus);
78        }
79        2 => {
80            final_cycle(cpu, bus);
81
82            bus.idle();
83
84            let mask = cpu.state.t0;
85            cpu.registers.p = (u8::from(cpu.registers.p) | mask).into();
86
87            if cpu.registers.p.index_size == SizeBits::Eight {
88                // Force X and Y registers to 8 bits
89                cpu.registers.x &= 0x00FF;
90                cpu.registers.y &= 0x00FF;
91            }
92        }
93        _ => invalid_cycle!(cpu),
94    }
95}