1use crate::sm83::bus::BusInterface; 2use crate::sm83::{Flags, Sm83}; 3 4impl Sm83 { 5 // ADD: Add without carry 6 pub(super) fn add_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 7 let operand = self.read_register(bus, opcode); 8 self.registers.a = add(self.registers.a, operand, false, &mut self.registers.f); 9 } 10 11 // ADD: Add without carry 12 pub(super) fn add_a_imm<B: BusInterface>(&mut self, bus: &mut B) { 13 let operand = self.fetch_operand(bus); 14 self.registers.a = add(self.registers.a, operand, false, &mut self.registers.f); 15 } 16 17 // ADC: Add with carry 18 pub(super) fn adc_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 19 let operand = self.read_register(bus, opcode); 20 self.registers.a = 21 add(self.registers.a, operand, self.registers.f.carry, &mut self.registers.f); 22 } 23 24 // ADC: Add with carry 25 pub(super) fn adc_a_imm<B: BusInterface>(&mut self, bus: &mut B) { 26 let operand = self.fetch_operand(bus); 27 self.registers.a = 28 add(self.registers.a, operand, self.registers.f.carry, &mut self.registers.f); 29 } 30 31 // SUB: Subtract without carry 32 pub(super) fn sub_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 33 let operand = self.read_register(bus, opcode); 34 self.registers.a = subtract(self.registers.a, operand, false, &mut self.registers.f); 35 } 36 37 // SUB: Subtract without carry 38 pub(super) fn sub_a_imm<B: BusInterface>(&mut self, bus: &mut B) { 39 let operand = self.fetch_operand(bus); 40 self.registers.a = subtract(self.registers.a, operand, false, &mut self.registers.f); 41 } 42 43 // SBC: Subtract with carry 44 pub(super) fn sbc_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 45 let operand = self.read_register(bus, opcode); 46 self.registers.a = 47 subtract(self.registers.a, operand, self.registers.f.carry, &mut self.registers.f); 48 } 49 50 // SBC: Subtract with carry 51 pub(super) fn sbc_a_imm<B: BusInterface>(&mut self, bus: &mut B) { 52 let operand = self.fetch_operand(bus); 53 self.registers.a = 54 subtract(self.registers.a, operand, self.registers.f.carry, &mut self.registers.f); 55 } 56 57 // CP: Compare 58 pub(super) fn cp_a_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 59 let operand = self.read_register(bus, opcode); 60 subtract(self.registers.a, operand, false, &mut self.registers.f); 61 } 62 63 // CP: Compare 64 pub(super) fn cp_a_imm<B: BusInterface>(&mut self, bus: &mut B) { 65 let operand = self.fetch_operand(bus); 66 subtract(self.registers.a, operand, false, &mut self.registers.f); 67 } 68 69 // INC r: Increment register 70 pub(super) fn inc_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 71 let value = self.read_register(bus, opcode >> 3).wrapping_add(1); 72 self.write_register(bus, opcode >> 3, value); 73 74 self.registers.f.zero = value == 0; 75 self.registers.f.subtract = false; 76 self.registers.f.half_carry = value & 0x0F == 0; 77 } 78 79 // DEC r: Decrement register 80 pub(super) fn dec_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 81 let value = self.read_register(bus, opcode >> 3).wrapping_sub(1); 82 self.write_register(bus, opcode >> 3, value); 83 84 self.registers.f.zero = value == 0; 85 self.registers.f.subtract = true; 86 self.registers.f.half_carry = value & 0x0F == 0x0F; 87 } 88 89 // INC rr: Increment register pair or SP 90 pub(super) fn inc_rr<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 91 match (opcode >> 4) & 0x3 { 92 0x0 => self.registers.increment_bc(), 93 0x1 => self.registers.increment_de(), 94 0x2 => self.registers.increment_hl(), 95 0x3 => self.registers.increment_sp(), 96 _ => unreachable!("value & 0x3 is always <= 0x3"), 97 } 98 99 // INC rr takes 2 M-cycles 100 bus.idle(); 101 } 102 103 // DEC rr: Decrement register pair or SP 104 pub(super) fn dec_rr<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 105 match (opcode >> 4) & 0x3 { 106 0x0 => self.registers.decrement_bc(), 107 0x1 => self.registers.decrement_de(), 108 0x2 => self.registers.decrement_hl(), 109 0x3 => self.registers.decrement_sp(), 110 _ => unreachable!("value & 0x3 is always <= 0x3"), 111 } 112 113 // DEC rr takes 2 M-cycles 114 bus.idle(); 115 } 116 117 // ADD HL, rr: 16-bit add 118 pub(super) fn add_hl_rr<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) { 119 let operand = match (opcode >> 4) & 0x3 { 120 0x0 => self.registers.bc(), 121 0x1 => self.registers.de(), 122 0x2 => self.registers.hl(), 123 0x3 => self.registers.sp, 124 _ => unreachable!("value & 0x3 is always <= 0x3"), 125 }; 126 127 let (sum, flags) = add_u16(self.registers.hl(), operand); 128 self.registers.set_hl(sum); 129 130 // 16-bit addition does not modify the Z flag 131 self.registers.f = Flags { zero: self.registers.f.zero, ..flags }; 132 133 // 16-bit addition takes 2 M-cycles 134 bus.idle(); 135 } 136 137 // ADD SP, i8: Add signed immediate value to stack pointer 138 pub(super) fn add_sp_e<B: BusInterface>(&mut self, bus: &mut B) { 139 let operand = self.fetch_operand(bus) as i8; 140 141 let (sum, flags) = add_sp(self.registers.sp, operand as u16); 142 self.registers.sp = sum; 143 144 // Adding to stack pointer always sets Z flag to false 145 self.registers.f = Flags { zero: false, ..flags }; 146 147 // This instruction takes 4 M-cycles: opcode read + operand read + 2 idle cycles 148 bus.idle(); 149 bus.idle(); 150 } 151 152 // DAA: Decimal adjust accumulator 153 pub(super) fn daa(&mut self) { 154 if self.registers.f.subtract { 155 // Last op was subtraction 156 let mut value = self.registers.a; 157 158 if self.registers.f.half_carry { 159 value = value.wrapping_sub(0x06); 160 } 161 162 if self.registers.f.carry { 163 value = value.wrapping_sub(0x60); 164 } 165 166 self.registers.a = value; 167 self.registers.f.zero = value == 0; 168 self.registers.f.half_carry = false; 169 } else { 170 // Last op was addition 171 let mut value = self.registers.a; 172 let mut carry = false; 173 174 if value > 0x99 || self.registers.f.carry { 175 value = value.wrapping_add(0x60); 176 carry = true; 177 } 178 179 if value & 0x0F > 0x09 || self.registers.f.half_carry { 180 value = value.wrapping_add(0x06); 181 } 182 183 self.registers.a = value; 184 self.registers.f.zero = value == 0; 185 self.registers.f.half_carry = false; 186 self.registers.f.carry = carry; 187 } 188 } 189 190 pub(super) fn ld_hl_sp_e<B: BusInterface>(&mut self, bus: &mut B) { 191 let operand = self.fetch_operand(bus) as i8; 192 let (sum, flags) = add_sp(self.registers.sp, operand as u16); 193 194 self.registers.set_hl(sum); 195 196 // Adding to stack pointer always sets Z flag to false 197 self.registers.f = Flags { zero: false, ..flags }; 198 199 bus.idle(); 200 } 201} 202 203fn add(accumulator: u8, operand: u8, carry_in: bool, flags: &mut Flags) -> u8 { 204 let carry_in: u8 = carry_in.into(); 205 206 let (partial_sum, carry1) = accumulator.overflowing_add(operand); 207 let (sum, carry2) = partial_sum.overflowing_add(carry_in); 208 let carry = carry1 || carry2; 209 210 let half_carry = (accumulator & 0x0F) + (operand & 0x0F) + carry_in > 0x0F; 211 212 *flags = Flags { zero: sum == 0, subtract: false, half_carry, carry }; 213 214 sum 215} 216 217fn add_u16(l_value: u16, r_value: u16) -> (u16, Flags) { 218 let [l_lsb, l_msb] = l_value.to_le_bytes(); 219 let [r_lsb, r_msb] = r_value.to_le_bytes(); 220 let mut flags = Flags { zero: false, subtract: false, half_carry: false, carry: false }; 221 222 let (sum_lsb, lsb_carry) = l_lsb.overflowing_add(r_lsb); 223 let sum_msb = add(l_msb, r_msb, lsb_carry, &mut flags); 224 let sum = u16::from_le_bytes([sum_lsb, sum_msb]); 225 226 (sum, flags) 227}
This differs from add_u16 in that it sets the flags based on the LSB addition instead of MSB
230fn add_sp(l_value: u16, r_value: u16) -> (u16, Flags) { 231 let [l_lsb, l_msb] = l_value.to_le_bytes(); 232 let [r_lsb, r_msb] = r_value.to_le_bytes(); 233 let mut flags = Flags { zero: false, subtract: false, half_carry: false, carry: false }; 234 235 let sum_lsb = add(l_lsb, r_lsb, false, &mut flags); 236 let sum_msb = l_msb.wrapping_add(r_msb).wrapping_add(flags.carry.into()); 237 let sum = u16::from_le_bytes([sum_lsb, sum_msb]); 238 239 (sum, flags) 240}
242fn subtract(accumulator: u8, operand: u8, carry_in: bool, flags: &mut Flags) -> u8 { 243 let carry_in: u8 = carry_in.into(); 244 245 let (partial_diff, borrow1) = accumulator.overflowing_sub(operand); 246 let (difference, borrow2) = partial_diff.overflowing_sub(carry_in); 247 let borrow = borrow1 || borrow2; 248 249 let half_borrow = accumulator & 0x0F < (operand & 0x0F) + carry_in; 250 251 *flags = 252 Flags { zero: difference == 0, subtract: true, half_carry: half_borrow, carry: borrow }; 253 254 difference 255}