1use crate::core::instructions::{ 2 BlockMode, InstructionExecutor, parity_flag, sign_flag, zero_flag, 3}; 4use crate::core::{Flags, IndexRegister, Register16}; 5use crate::debug::BusDebugExt; 6use crate::traits::BusInterface; 7use jgenesis_common::num::GetBit; 8 9macro_rules! impl_a_r_add_op { 10 ($name:ident, $op_fn:ident) => { 11 pub(super) fn $name( 12 &mut self, 13 opcode: u8, 14 index: Option<IndexRegister>, 15 with_carry: bool, 16 ) -> u32 { 17 let read_target = 18 super::parse_register_from_opcode(opcode, index).expect("invalid opcode"); 19 let operand = read_target.read_from(&self.cpu.registers); 20 21 self.cpu.registers.a = 22 $op_fn(self.cpu.registers.a, operand, with_carry, &mut self.cpu.registers.f); 23 24 4 25 } 26 }; 27} 28 29macro_rules! impl_a_immediate_add_op { 30 ($name:ident, $op_fn:ident) => { 31 pub(super) fn $name(&mut self, with_carry: bool) -> u32 { 32 let operand = self.fetch_operand(); 33 34 self.cpu.registers.a = 35 $op_fn(self.cpu.registers.a, operand, with_carry, &mut self.cpu.registers.f); 36 37 7 38 } 39 }; 40} 41 42macro_rules! impl_a_hl_add_op { 43 ($name:ident, $op_fn:ident) => { 44 pub(super) fn $name(&mut self, index: Option<IndexRegister>, with_carry: bool) -> u32 { 45 let address = self.fetch_indirect_hl_address(index); 46 let operand = self.bus.read_memory_debug(address, self.cpu); 47 48 self.cpu.registers.a = 49 $op_fn(self.cpu.registers.a, operand, with_carry, &mut self.cpu.registers.f); 50 51 match index { 52 Some(_) => 15, 53 None => 7, 54 } 55 } 56 }; 57} 58 59macro_rules! impl_a_r_bit_op { 60 ($name:ident, $op_fn:ident) => { 61 pub(super) fn $name(&mut self, opcode: u8, index: Option<IndexRegister>) -> u32 { 62 let read_target = 63 super::parse_register_from_opcode(opcode, index).expect("invalid opcode"); 64 let operand = read_target.read_from(&self.cpu.registers); 65 66 self.cpu.registers.a = $op_fn(self.cpu.registers.a, operand, &mut self.cpu.registers.f); 67 68 4 69 } 70 }; 71} 72 73macro_rules! impl_a_immediate_bit_op { 74 ($name:ident, $op_fn:ident) => { 75 pub(super) fn $name(&mut self) -> u32 { 76 let operand = self.fetch_operand(); 77 78 self.cpu.registers.a = $op_fn(self.cpu.registers.a, operand, &mut self.cpu.registers.f); 79 80 7 81 } 82 }; 83} 84 85macro_rules! impl_a_hl_bit_op { 86 ($name:ident, $op_fn:ident) => { 87 pub(super) fn $name(&mut self, index: Option<IndexRegister>) -> u32 { 88 let address = self.fetch_indirect_hl_address(index); 89 let operand = self.bus.read_memory_debug(address, self.cpu); 90 91 self.cpu.registers.a = $op_fn(self.cpu.registers.a, operand, &mut self.cpu.registers.f); 92 93 match index { 94 Some(_) => 15, 95 None => 7, 96 } 97 } 98 }; 99} 100 101macro_rules! impl_r_increment_op { 102 ($name:ident, $op_fn:ident) => { 103 pub(super) fn $name(&mut self, opcode: u8, index: Option<IndexRegister>) -> u32 { 104 let register = 105 super::parse_register_from_opcode(opcode >> 3, index).expect("invalid opcode"); 106 let original = register.read_from(&self.cpu.registers); 107 let modified = $op_fn(original, &mut self.cpu.registers.f); 108 109 register.write_to(modified, &mut self.cpu.registers); 110 111 4 112 } 113 }; 114} 115 116macro_rules! impl_hl_increment_op { 117 ($name:ident, $op_fn:ident) => { 118 pub(super) fn $name(&mut self, index: Option<IndexRegister>) -> u32 { 119 let address = self.fetch_indirect_hl_address(index); 120 let original = self.bus.read_memory_debug(address, self.cpu); 121 let modified = $op_fn(original, &mut self.cpu.registers.f); 122 123 self.bus.write_memory_debug(address, modified, self.cpu); 124 125 match index { 126 Some(_) => 19, 127 None => 11, 128 } 129 } 130 }; 131} 132 133macro_rules! impl_16_bit_increment_op { 134 ($name:ident, $op_fn:ident) => { 135 pub(super) fn $name(&mut self, opcode: u8, index: Option<IndexRegister>) -> u32 { 136 let register = super::parse_dd_register(opcode, index); 137 let original = register.read_from(&self.cpu.registers); 138 let modified = $op_fn(original); 139 140 register.write_to(modified, &mut self.cpu.registers); 141 142 6 143 } 144 }; 145} 146 147impl<B: BusInterface> InstructionExecutor<'_, '_, B> { 148 impl_a_r_add_op!(add_a_r, add); 149 impl_a_immediate_add_op!(add_a_immediate, add); 150 impl_a_hl_add_op!(add_a_hl, add); 151 152 impl_a_r_add_op!(sub_a_r, subtract); 153 impl_a_immediate_add_op!(sub_a_immediate, subtract); 154 impl_a_hl_add_op!(sub_a_hl, subtract); 155 156 impl_a_r_bit_op!(and_a_r, and); 157 impl_a_immediate_bit_op!(and_a_immediate, and); 158 impl_a_hl_bit_op!(and_a_hl, and); 159 160 impl_a_r_bit_op!(or_a_r, or); 161 impl_a_immediate_bit_op!(or_a_immediate, or); 162 impl_a_hl_bit_op!(or_a_hl, or); 163 164 impl_a_r_bit_op!(xor_a_r, xor); 165 impl_a_immediate_bit_op!(xor_a_immediate, xor); 166 impl_a_hl_bit_op!(xor_a_hl, xor); 167 168 impl_a_r_bit_op!(cp_a_r, compare); 169 impl_a_immediate_bit_op!(cp_a_immediate, compare); 170 impl_a_hl_bit_op!(cp_a_hl, compare); 171 172 impl_r_increment_op!(inc_r, increment); 173 impl_hl_increment_op!(inc_hl, increment); 174 175 impl_r_increment_op!(dec_r, decrement); 176 impl_hl_increment_op!(dec_hl, decrement); 177 178 impl_16_bit_increment_op!(inc_ss, increment_u16); 179 impl_16_bit_increment_op!(dec_ss, decrement_u16); 180 181 pub(super) fn add_hl_ss(&mut self, opcode: u8, index: Option<IndexRegister>) -> u32 { 182 let l_register = index.map_or(Register16::HL, IndexRegister::into); 183 let r_register = super::parse_dd_register(opcode, index); 184 185 let l_value = l_register.read_from(&self.cpu.registers); 186 let r_value = r_register.read_from(&self.cpu.registers); 187 188 let sum = add_u16(l_value, r_value, false, &mut self.cpu.registers.f); 189 l_register.write_to(sum, &mut self.cpu.registers); 190 191 11 192 } 193 194 pub(super) fn adc_hl_ss(&mut self, opcode: u8) -> u32 { 195 let register = super::parse_dd_register(opcode, None); 196 197 let l_value = Register16::HL.read_from(&self.cpu.registers); 198 let r_value = register.read_from(&self.cpu.registers); 199 200 let sum = add_u16(l_value, r_value, true, &mut self.cpu.registers.f); 201 Register16::HL.write_to(sum, &mut self.cpu.registers); 202 203 15 204 } 205 206 pub(super) fn sbc_hl_ss(&mut self, opcode: u8) -> u32 { 207 let register = super::parse_dd_register(opcode, None); 208 209 let l_value = Register16::HL.read_from(&self.cpu.registers); 210 let r_value = register.read_from(&self.cpu.registers); 211 212 let difference = sbc_u16(l_value, r_value, &mut self.cpu.registers.f); 213 Register16::HL.write_to(difference, &mut self.cpu.registers); 214 215 15 216 } 217 218 pub(super) fn daa(&mut self) -> u32 { 219 let a = self.cpu.registers.a; 220 let flags = self.cpu.registers.f; 221 222 let mut diff = 0; 223 if flags.half_carry || (a & 0x0F > 0x09) { 224 diff |= 0x06; 225 } 226 let carry = flags.carry || a > 0x99; 227 if carry { 228 diff |= 0x60; 229 } 230 231 let value = if flags.subtract { a.wrapping_sub(diff) } else { a.wrapping_add(diff) }; 232 233 let half_carry = a.bit(4) != value.bit(4); 234 235 self.cpu.registers.a = value; 236 self.cpu.registers.f = Flags { 237 sign: sign_flag(value), 238 zero: zero_flag(value), 239 half_carry, 240 overflow: parity_flag(value), 241 carry, 242 ..flags 243 }; 244 245 4 246 } 247 248 pub(super) fn cpl(&mut self) -> u32 { 249 self.cpu.registers.a = !self.cpu.registers.a; 250 self.cpu.registers.f = Flags { half_carry: true, subtract: true, ..self.cpu.registers.f }; 251 252 4 253 } 254 255 pub(super) fn neg(&mut self) -> u32 { 256 self.cpu.registers.a = subtract(0, self.cpu.registers.a, false, &mut self.cpu.registers.f); 257 258 8 259 } 260 261 pub(super) fn ccf(&mut self) -> u32 { 262 let prev_carry = self.cpu.registers.f.carry; 263 self.cpu.registers.f = Flags { 264 half_carry: prev_carry, 265 subtract: false, 266 carry: !prev_carry, 267 ..self.cpu.registers.f 268 }; 269 270 4 271 } 272 273 pub(super) fn scf(&mut self) -> u32 { 274 self.cpu.registers.f = 275 Flags { half_carry: false, subtract: false, carry: true, ..self.cpu.registers.f }; 276 277 4 278 } 279 280 pub(super) fn compare_block(&mut self, mode: BlockMode, repeat: bool) -> u32 { 281 let a = self.cpu.registers.a; 282 let bc = Register16::BC.read_from(&self.cpu.registers); 283 let hl = Register16::HL.read_from(&self.cpu.registers); 284 let operand = self.bus.read_memory_debug(hl, self.cpu); 285 286 let difference = a.wrapping_sub(operand); 287 let half_carry = a & 0x0F < operand & 0x0F; 288 289 Register16::HL.write_to(mode.apply(hl), &mut self.cpu.registers); 290 Register16::BC.write_to(bc.wrapping_sub(1), &mut self.cpu.registers); 291 292 self.cpu.registers.f = Flags { 293 sign: sign_flag(difference), 294 zero: zero_flag(difference), 295 half_carry, 296 overflow: bc != 1, 297 subtract: true, 298 ..self.cpu.registers.f 299 }; 300 301 let should_repeat = repeat && difference != 0 && bc != 1; 302 if should_repeat { 303 self.cpu.registers.pc -= 2; 304 21 305 } else { 306 16 307 } 308 } 309} 310 311fn add(l: u8, r: u8, with_carry: bool, flags: &mut Flags) -> u8 { 312 let carry_operand = if with_carry { u8::from(flags.carry) } else { 0 }; 313 314 let (sum, carry) = match l.overflowing_add(r) { 315 (sum, true) => (sum + carry_operand, true), 316 (sum, false) => sum.overflowing_add(carry_operand), 317 }; 318 319 let half_carry = (l & 0x0F) + (r & 0x0F) + carry_operand >= 0x10; 320 let bit_6_carry = (l & 0x7F) + (r & 0x7F) + carry_operand >= 0x80; 321 let overflow = bit_6_carry != carry; 322 323 *flags = Flags { 324 sign: sign_flag(sum), 325 zero: zero_flag(sum), 326 half_carry, 327 overflow, 328 subtract: false, 329 carry, 330 ..*flags 331 }; 332 333 sum 334} 335 336fn add_u16(l: u16, r: u16, with_carry: bool, flags: &mut Flags) -> u16 { 337 let carry_operand = if with_carry { u16::from(flags.carry) } else { 0 }; 338 339 let (sum, carry) = match l.overflowing_add(r) { 340 (sum, true) => (sum + carry_operand, true), 341 (sum, false) => sum.overflowing_add(carry_operand), 342 }; 343 344 let half_carry = (l & 0x0FFF) + (r & 0x0FFF) + carry_operand >= 0x1000; 345 346 *flags = Flags { half_carry, subtract: false, carry, ..*flags }; 347 348 if with_carry { 349 // S, Z, and P/V are only set in 16-bit ADC, not 16-bit ADD 350 let bit_14_carry = (l & 0x7FFF) + (r & 0x7FFF) + carry_operand >= 0x8000; 351 let overflow = bit_14_carry != carry; 352 353 *flags = Flags { sign: sum.bit(15), zero: sum == 0, overflow, ..*flags }; 354 } 355 356 sum 357} 358 359fn subtract(l: u8, r: u8, with_carry: bool, flags: &mut Flags) -> u8 { 360 let carry_operand = if with_carry { u8::from(flags.carry) } else { 0 }; 361 362 let (difference, carry) = match l.overflowing_sub(r) { 363 (difference, true) => (difference - carry_operand, true), 364 (difference, false) => difference.overflowing_sub(carry_operand), 365 }; 366 367 let half_carry = l & 0x0F < (r & 0x0F) + carry_operand; 368 let bit_6_borrow = l & 0x7F < (r & 0x7F) + carry_operand; 369 let overflow = bit_6_borrow != carry; 370 371 *flags = Flags { 372 sign: sign_flag(difference), 373 zero: zero_flag(difference), 374 half_carry, 375 overflow, 376 subtract: true, 377 carry, 378 ..*flags 379 }; 380 381 difference 382} 383 384fn sbc_u16(l: u16, r: u16, flags: &mut Flags) -> u16 { 385 let carry_operand = u16::from(flags.carry); 386 387 let (difference, carry) = match l.overflowing_sub(r) { 388 (difference, true) => (difference - carry_operand, true), 389 (difference, false) => difference.overflowing_sub(carry_operand), 390 }; 391 392 let half_carry = l & 0x0FFF < (r & 0x0FFF) + carry_operand; 393 let bit_14_borrow = l & 0x7FFF < (r & 0x7FFF) + carry_operand; 394 let overflow = bit_14_borrow != carry; 395 396 *flags = Flags { 397 sign: difference.bit(15), 398 zero: difference == 0, 399 half_carry, 400 overflow, 401 subtract: true, 402 carry, 403 ..*flags 404 }; 405 406 difference 407} 408 409fn and(l: u8, r: u8, flags: &mut Flags) -> u8 { 410 let value = l & r; 411 412 *flags = Flags { 413 sign: sign_flag(value), 414 zero: zero_flag(value), 415 half_carry: true, 416 overflow: parity_flag(value), 417 subtract: false, 418 carry: false, 419 ..*flags 420 }; 421 422 value 423} 424 425fn or(l: u8, r: u8, flags: &mut Flags) -> u8 { 426 let value = l | r; 427 428 *flags = Flags { 429 sign: sign_flag(value), 430 zero: zero_flag(value), 431 half_carry: false, 432 overflow: parity_flag(value), 433 subtract: false, 434 carry: false, 435 ..*flags 436 }; 437 438 value 439} 440 441fn xor(l: u8, r: u8, flags: &mut Flags) -> u8 { 442 let value = l ^ r; 443 444 *flags = Flags { 445 sign: sign_flag(value), 446 zero: zero_flag(value), 447 half_carry: false, 448 overflow: parity_flag(value), 449 subtract: false, 450 carry: false, 451 ..*flags 452 }; 453 454 value 455} 456 457fn compare(l: u8, r: u8, flags: &mut Flags) -> u8 { 458 let (difference, carry) = l.overflowing_sub(r); 459 460 let half_carry = l & 0x0F < r & 0x0F; 461 let bit_6_borrow = l & 0x7F < r & 0x7F; 462 let overflow = bit_6_borrow != carry; 463 464 *flags = Flags { 465 sign: sign_flag(difference), 466 zero: zero_flag(difference), 467 half_carry, 468 overflow, 469 subtract: true, 470 carry, 471 ..*flags 472 }; 473 474 l 475} 476 477fn increment(value: u8, flags: &mut Flags) -> u8 { 478 let half_carry = value & 0x0F == 0x0F; 479 let overflow = value == 0x7F; 480 481 let incremented = value.wrapping_add(1); 482 *flags = Flags { 483 sign: sign_flag(incremented), 484 zero: zero_flag(incremented), 485 half_carry, 486 overflow, 487 subtract: false, 488 ..*flags 489 }; 490 491 incremented 492} 493 494fn decrement(value: u8, flags: &mut Flags) -> u8 { 495 let half_carry = value & 0x0F == 0x00; 496 let overflow = value == 0x80; 497 498 let decremented = value.wrapping_sub(1); 499 *flags = Flags { 500 sign: sign_flag(decremented), 501 zero: zero_flag(decremented), 502 half_carry, 503 overflow, 504 subtract: true, 505 ..*flags 506 }; 507 508 decremented 509} 510 511fn increment_u16(value: u16) -> u16 { 512 value.wrapping_add(1) 513} 514 515fn decrement_u16(value: u16) -> u16 { 516 value.wrapping_sub(1) 517} 518 519#[cfg(test)] 520mod tests { 521 use super::*; 522 use crate::Z80; 523 use crate::traits::InMemoryBus; 524 525 #[test] 526 fn cpl() { 527 let mut cpu = Z80::new(); 528 let mut bus = InMemoryBus::new(); 529 530 cpu.registers.a = 0x37; 531 cpu.registers.f = 0_u8.into(); 532 533 InstructionExecutor::new(&mut cpu, &mut bus).cpl(); 534 535 assert_eq!(cpu.registers.a, 0xC8); 536 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0x12); 537 538 let value = rand::random(); 539 cpu.registers.a = value; 540 cpu.registers.f = 0xFF_u8.into(); 541 542 InstructionExecutor::new(&mut cpu, &mut bus).cpl(); 543 544 assert_eq!(cpu.registers.a, !value); 545 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0xD7); 546 } 547 548 #[test] 549 fn ccf() { 550 let mut cpu = Z80::new(); 551 let mut bus = InMemoryBus::new(); 552 553 cpu.registers.f = 0_u8.into(); 554 555 InstructionExecutor::new(&mut cpu, &mut bus).ccf(); 556 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0x01); 557 558 InstructionExecutor::new(&mut cpu, &mut bus).ccf(); 559 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0x10); 560 561 InstructionExecutor::new(&mut cpu, &mut bus).ccf(); 562 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0x01); 563 564 cpu.registers.f = 0xFF_u8.into(); 565 566 InstructionExecutor::new(&mut cpu, &mut bus).ccf(); 567 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0xD4); 568 569 InstructionExecutor::new(&mut cpu, &mut bus).ccf(); 570 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0xC5); 571 } 572 573 #[test] 574 fn scf() { 575 let mut cpu = Z80::new(); 576 let mut bus = InMemoryBus::new(); 577 578 cpu.registers.f = 0_u8.into(); 579 580 for _ in 0..2 { 581 InstructionExecutor::new(&mut cpu, &mut bus).scf(); 582 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0x01); 583 } 584 585 cpu.registers.f = 0xFF_u8.into(); 586 587 for _ in 0..2 { 588 InstructionExecutor::new(&mut cpu, &mut bus).scf(); 589 assert_eq!(u8::from(cpu.registers.f) & 0xD7, 0xC5); 590 } 591 } 592}