bits.rsannotatedbits.rssource208 lines · 7.3 KB · raw
1use crate::sm83::bus::BusInterface;
2use crate::sm83::{Flags, Sm83};
3use jgenesis_common::num::GetBit;
4
5macro_rules! impl_rla_op {
6    ($name:ident, thru_carry: $thru_carry:expr) => {
7        pub(super) fn $name(&mut self) {
8            let carry = self.registers.a.bit(7);
9            self.registers.a = if $thru_carry {
10                (self.registers.a << 1) | u8::from(self.registers.f.carry)
11            } else {
12                self.registers.a.rotate_left(1)
13            };
14            self.registers.f = Flags { zero: false, subtract: false, half_carry: false, carry };
15        }
16    };
17}
18
19macro_rules! impl_rra_op {
20    ($name:ident, thru_carry: $thru_carry:expr) => {
21        pub(super) fn $name(&mut self) {
22            let carry = self.registers.a.bit(0);
23            self.registers.a = if $thru_carry {
24                (self.registers.a >> 1) | (u8::from(self.registers.f.carry) << 7)
25            } else {
26                self.registers.a.rotate_right(1)
27            };
28            self.registers.f = Flags { zero: false, subtract: false, half_carry: false, carry };
29        }
30    };
31}
32
33impl Sm83 {
34    // AND: Bitwise and
35    pub(super) fn and_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
36        let operand = self.read_register(bus, opcode);
37        self.registers.a = and(self.registers.a, operand, &mut self.registers.f);
38    }
39
40    // AND: Bitwise and
41    pub(super) fn and_a_imm<B: BusInterface>(&mut self, bus: &mut B) {
42        let operand = self.fetch_operand(bus);
43        self.registers.a = and(self.registers.a, operand, &mut self.registers.f);
44    }
45
46    // OR: Bitwise inclusive or
47    pub(super) fn or_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
48        let operand = self.read_register(bus, opcode);
49        self.registers.a = or(self.registers.a, operand, &mut self.registers.f);
50    }
51
52    // OR: Bitwise inclusive or
53    pub(super) fn or_a_imm<B: BusInterface>(&mut self, bus: &mut B) {
54        let operand = self.fetch_operand(bus);
55        self.registers.a = or(self.registers.a, operand, &mut self.registers.f);
56    }
57
58    // XOR: Bitwise exclusive or
59    pub(super) fn xor_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
60        let operand = self.read_register(bus, opcode);
61        self.registers.a = xor(self.registers.a, operand, &mut self.registers.f);
62    }
63
64    // XOR: Bitwise exclusive or
65    pub(super) fn xor_a_imm<B: BusInterface>(&mut self, bus: &mut B) {
66        let operand = self.fetch_operand(bus);
67        self.registers.a = xor(self.registers.a, operand, &mut self.registers.f);
68    }
69
70    // CPL: Complement accumulator
71    pub(super) fn cpl(&mut self) {
72        self.registers.a = !self.registers.a;
73
74        self.registers.f.subtract = true;
75        self.registers.f.half_carry = true;
76    }
77
78    // RLCA: Rotate accumulator left
79    impl_rla_op!(rlca, thru_carry: false);
80
81    // RRCA: Rotate accumualtor right
82    impl_rra_op!(rrca, thru_carry: false);
83
84    // RLA: Rotate accumulator left through carry
85    impl_rla_op!(rla, thru_carry: true);
86
87    // RRA: Rotate accumulator right through carry
88    impl_rra_op!(rra, thru_carry: true);
89
90    // RLC: Rotate register left
91    pub(super) fn rlc_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
92        let value = self.read_register(bus, opcode);
93        let rotated = value.rotate_left(1);
94        self.write_register(bus, opcode, rotated);
95
96        self.registers.f = flags_for_shift_op(rotated, value.bit(7));
97    }
98
99    // RRC: Rotate register right
100    pub(super) fn rrc_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
101        let value = self.read_register(bus, opcode);
102        let rotated = value.rotate_right(1);
103        self.write_register(bus, opcode, rotated);
104
105        self.registers.f = flags_for_shift_op(rotated, value.bit(0));
106    }
107
108    // RL: Rotate register left through carry
109    pub(super) fn rl_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
110        let value = self.read_register(bus, opcode);
111        let rotated = (value << 1) | u8::from(self.registers.f.carry);
112        self.write_register(bus, opcode, rotated);
113
114        self.registers.f = flags_for_shift_op(rotated, value.bit(7));
115    }
116
117    // RR: Rotate register right through carry
118    pub(super) fn rr_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
119        let value = self.read_register(bus, opcode);
120        let rotated = (value >> 1) | (u8::from(self.registers.f.carry) << 7);
121        self.write_register(bus, opcode, rotated);
122
123        self.registers.f = flags_for_shift_op(rotated, value.bit(0));
124    }
125
126    // SLA: Shift left
127    pub(super) fn sla<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
128        let value = self.read_register(bus, opcode);
129        let shifted = value << 1;
130        self.write_register(bus, opcode, shifted);
131
132        self.registers.f = flags_for_shift_op(shifted, value.bit(7));
133    }
134
135    // SRA: Arithmetic shift right
136    pub(super) fn sra<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
137        let value = self.read_register(bus, opcode);
138        let shifted = (value >> 1) | (value & 0x80);
139        self.write_register(bus, opcode, shifted);
140
141        self.registers.f = flags_for_shift_op(shifted, value.bit(0));
142    }
143
144    // SRL: Logical shift right
145    pub(super) fn srl<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
146        let value = self.read_register(bus, opcode);
147        let shifted = value >> 1;
148        self.write_register(bus, opcode, shifted);
149
150        self.registers.f = flags_for_shift_op(shifted, value.bit(0));
151    }
152
153    // SWAP: Swap nibbles
154    pub(super) fn swap<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
155        let value = self.read_register(bus, opcode);
156        self.write_register(bus, opcode, value.rotate_left(4));
157
158        self.registers.f =
159            Flags { zero: value == 0, subtract: false, half_carry: false, carry: false };
160    }
161
162    // BIT: Test bit
163    pub(super) fn bit<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
164        let value = self.read_register(bus, opcode);
165        let bit = (opcode >> 3) & 0x7;
166
167        self.registers.f.zero = !value.bit(bit);
168        self.registers.f.subtract = false;
169        self.registers.f.half_carry = true;
170    }
171
172    // SET: Set bit
173    pub(super) fn set<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
174        let value = self.read_register(bus, opcode);
175        let bit = (opcode >> 3) & 0x7;
176        self.write_register(bus, opcode, value | (1 << bit));
177    }
178
179    // RES: Reset bit
180    pub(super) fn res<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
181        let value = self.read_register(bus, opcode);
182        let bit = (opcode >> 3) & 0x7;
183        self.write_register(bus, opcode, value & !(1 << bit));
184    }
185}
186
187fn flags_for_shift_op(value: u8, carry: bool) -> Flags {
188    Flags { zero: value == 0, subtract: false, half_carry: false, carry }
189}
190
191macro_rules! impl_bitwise_op {
192    ($name:ident, $op:tt, half_carry: $half_carry:expr) => {
193        fn $name(accumulator: u8, operand: u8, flags: &mut Flags) -> u8 {
194            let value = accumulator $op operand;
195            *flags = Flags {
196                zero: value == 0,
197                subtract: false,
198                half_carry: $half_carry,
199                carry: false,
200            };
201            value
202        }
203    }
204}
205
206impl_bitwise_op!(and, &, half_carry: true);
207impl_bitwise_op!(or, |, half_carry: false);
208impl_bitwise_op!(xor, ^, half_carry: false);