ADD instruction bug

This commit is contained in:
Franco Colmenarez 2021-10-18 18:18:57 -05:00
parent ac91f8f50d
commit eeeba76ebd

View File

@ -233,8 +233,8 @@ pub enum Opcode {
OR(OpcodeParameter), OR(OpcodeParameter),
XOR(OpcodeParameter), XOR(OpcodeParameter),
CP(OpcodeParameter), CP(OpcodeParameter),
INC(bool, Register), INC(bool, bool, Register),
DEC(bool, Register), DEC(bool, bool, Register),
DAA, DAA,
CPL, CPL,
CCF, CCF,
@ -528,6 +528,7 @@ impl CPU {
if reg1.is_8bit() && reg2.is_8bit() { if reg1.is_8bit() && reg2.is_8bit() {
self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(self.registers.get_8bit(reg1), self.registers.get_8bit(reg2))); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(self.registers.get_8bit(reg1), self.registers.get_8bit(reg2)));
self.registers.set(reg1, self.registers.get(reg1) + self.registers.get(reg2)); self.registers.set(reg1, self.registers.get(reg1) + self.registers.get(reg2));
self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0);
} else if reg1.is_16bit() && reg2.is_16bit() { } else if reg1.is_16bit() && reg2.is_16bit() {
self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry_16bit(self.registers.get(reg1), self.registers.get(reg2))); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry_16bit(self.registers.get(reg1), self.registers.get(reg2)));
self.registers.set(reg1, self.registers.get(reg1) + self.registers.get(reg2)); self.registers.set(reg1, self.registers.get(reg1) + self.registers.get(reg2));
@ -536,8 +537,8 @@ impl CPU {
let val2 = bus.read(self.registers.get(reg2)) as u16; let val2 = bus.read(self.registers.get(reg2)) as u16;
self.registers.set(reg1, val1 + val2); self.registers.set(reg1, val1 + val2);
self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(val1.to_be_bytes()[1], val2.to_be_bytes()[1])); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(val1.to_be_bytes()[1], val2.to_be_bytes()[1]));
self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0);
} }
self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0);
self.registers.set_flag(FlagRegister::Carry, self.registers.get(reg1) == 0); self.registers.set_flag(FlagRegister::Carry, self.registers.get(reg1) == 0);
}, },
OpcodeParameter::Register_U8(reg1, val) => { OpcodeParameter::Register_U8(reg1, val) => {
@ -638,45 +639,59 @@ impl CPU {
_ => {}, _ => {},
}, },
// Increment by 1 // Increment by 1
Opcode::INC(affect_flags, register) => { Opcode::INC(affect_flags, on_address, register) => {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
let mut prev_value = 0; if on_address {
let mut result = 0;
if register.is_8bit() {
prev_value = self.registers.get_8bit(register);
self.registers.increment(register, 1);
result = self.registers.get_8bit(register);
} else {
let addr = self.registers.get(register); let addr = self.registers.get(register);
prev_value = bus.read(addr); let prev_value = bus.read(addr);
bus.write(addr, prev_value + 1); bus.write(addr, prev_value + 1);
result = bus.read(addr); if affect_flags {
} self.registers.set_flag(FlagRegister::Substract, false);
if affect_flags { self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(prev_value, 1));
self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::Zero, bus.read(addr) == 0);
self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(prev_value, 1)); }
self.registers.set_flag(FlagRegister::Zero, result == 0); } else {
let prev_value = self.registers.get(register);
self.registers.increment(register, 1);
if affect_flags {
let mut byte_compare = 0;
match register.is_8bit() {
true => byte_compare = prev_value.to_be_bytes()[1],
false => byte_compare = prev_value.to_be_bytes()[0],
}
let result = self.registers.get(register);
self.registers.set_flag(FlagRegister::Substract, false);
self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(byte_compare, 1));
self.registers.set_flag(FlagRegister::Zero, result == 0);
}
} }
}, },
// Decrement by 1 // Decrement by 1
Opcode::DEC(affect_flags, register) => { Opcode::DEC(affect_flags, on_address, register) => {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
let mut prev_value = 0; if on_address {
let mut result = 0;
if register.is_8bit() {
prev_value = self.registers.get_8bit(register);
self.registers.decrement(register, 1);
result = self.registers.get_8bit(register);
} else {
let addr = self.registers.get(register); let addr = self.registers.get(register);
prev_value = bus.read(addr); let prev_value = bus.read(addr);
bus.write(addr, prev_value - 1); bus.write(addr, prev_value - 1);
result = bus.read(addr); if affect_flags {
} self.registers.set_flag(FlagRegister::Substract, true);
if affect_flags { self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(prev_value, 1));
self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::Zero, bus.read(addr) == 0);
self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(prev_value, 1)); }
self.registers.set_flag(FlagRegister::Zero, result == 0); } else {
let prev_value = self.registers.get(register);
self.registers.decrement(register, 1);
if affect_flags {
let mut byte_compare = 0;
match register.is_8bit() {
true => byte_compare = prev_value.to_be_bytes()[1],
false => byte_compare = prev_value.to_be_bytes()[0],
}
let result = self.registers.get(register);
self.registers.set_flag(FlagRegister::Substract, true);
self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(byte_compare, 1));
self.registers.set_flag(FlagRegister::Zero, result == 0);
}
} }
}, },
// Jump to address // Jump to address
@ -1119,30 +1134,30 @@ impl CPU {
0xBD => Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::L)), 0xBD => Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::L)),
0xBE => Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::HL)), 0xBE => Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::HL)),
0xFE => Opcode::CP(OpcodeParameter::Register_U8(Register::A, params.1)), 0xFE => Opcode::CP(OpcodeParameter::Register_U8(Register::A, params.1)),
0x3C => Opcode::INC(true, Register::A), 0x3C => Opcode::INC(true, false, Register::A),
0x04 => Opcode::INC(true, Register::B), 0x04 => Opcode::INC(true, false, Register::B),
0x0C => Opcode::INC(true, Register::C), 0x0C => Opcode::INC(true, false, Register::C),
0x14 => Opcode::INC(true, Register::D), 0x14 => Opcode::INC(true, false, Register::D),
0x1C => Opcode::INC(true, Register::E), 0x1C => Opcode::INC(true, false, Register::E),
0x24 => Opcode::INC(true, Register::H), 0x24 => Opcode::INC(true, false, Register::H),
0x2C => Opcode::INC(true, Register::L), 0x2C => Opcode::INC(true, false, Register::L),
0x34 => Opcode::INC(true, Register::HL), 0x34 => Opcode::INC(true, true, Register::HL),
0x03 => Opcode::INC(false, Register::BC), 0x03 => Opcode::INC(false, false, Register::BC),
0x13 => Opcode::INC(false, Register::DE), 0x13 => Opcode::INC(false, false, Register::DE),
0x23 => Opcode::INC(false, Register::HL), 0x23 => Opcode::INC(false, false, Register::HL),
0x33 => Opcode::INC(false, Register::SP), 0x33 => Opcode::INC(false, false, Register::SP),
0x3D => Opcode::DEC(true, Register::A), 0x3D => Opcode::DEC(true, false, Register::A),
0x05 => Opcode::DEC(true, Register::B), 0x05 => Opcode::DEC(true, false, Register::B),
0x0D => Opcode::DEC(true, Register::C), 0x0D => Opcode::DEC(true, false, Register::C),
0x15 => Opcode::DEC(true, Register::D), 0x15 => Opcode::DEC(true, false, Register::D),
0x1D => Opcode::DEC(true, Register::E), 0x1D => Opcode::DEC(true, false, Register::E),
0x25 => Opcode::DEC(true, Register::H), 0x25 => Opcode::DEC(true, false, Register::H),
0x2D => Opcode::DEC(true, Register::L), 0x2D => Opcode::DEC(true, false, Register::L),
0x35 => Opcode::DEC(true, Register::HL), 0x35 => Opcode::DEC(true, true, Register::HL),
0x0B => Opcode::DEC(false, Register::BC), 0x0B => Opcode::DEC(false, false, Register::BC),
0x1B => Opcode::DEC(false, Register::DE), 0x1B => Opcode::DEC(false, false, Register::DE),
0x2B => Opcode::DEC(false, Register::HL), 0x2B => Opcode::DEC(false, false, Register::HL),
0x3B => Opcode::DEC(false, Register::SP), 0x3B => Opcode::DEC(false, false, Register::SP),
0x27 => Opcode::DAA, 0x27 => Opcode::DAA,
0x2F => Opcode::CPL, 0x2F => Opcode::CPL,
0x3F => Opcode::CCF, 0x3F => Opcode::CCF,
@ -2273,7 +2288,6 @@ mod tests {
cpu.registers.set(Register::BC, 0b0000100000000000); cpu.registers.set(Register::BC, 0b0000100000000000);
cpu.registers.set(Register::HL, 0b0000100000000000); cpu.registers.set(Register::HL, 0b0000100000000000);
cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::BC, Register::HL)), &mut bus); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::BC, Register::HL)), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
assert_eq!(cpu.registers.get(Register::BC), 0b0001000000000000); assert_eq!(cpu.registers.get(Register::BC), 0b0001000000000000);
assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::PC), 0x101);
@ -2330,14 +2344,14 @@ mod tests {
let mut bus = Bus::new(); let mut bus = Bus::new();
let mut cpu = CPU::new(); let mut cpu = CPU::new();
cpu.registers.set(Register::A, 0); cpu.registers.set(Register::A, 0);
cpu.exec(Opcode::INC(true, Register::A), &mut bus); cpu.exec(Opcode::INC(true, false, Register::A), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false);
assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::PC), 0x101);
let mut cpu = CPU::new(); let mut cpu = CPU::new();
cpu.registers.set(Register::A, 0b00001111); cpu.registers.set(Register::A, 0b00001111);
cpu.exec(Opcode::INC(true, Register::A), &mut bus); cpu.exec(Opcode::INC(true, false, Register::A), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
@ -2346,12 +2360,20 @@ mod tests {
let addr = 0xC000; let addr = 0xC000;
cpu.registers.set(Register::HL, addr); cpu.registers.set(Register::HL, addr);
bus.write(addr, 0b00001111); bus.write(addr, 0b00001111);
cpu.exec(Opcode::INC(true, Register::HL), &mut bus); cpu.exec(Opcode::INC(true, true, Register::HL), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
assert_eq!(bus.read(addr), 0b00010000); assert_eq!(bus.read(addr), 0b00010000);
assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::PC), 0x101);
let mut cpu = CPU::new();
cpu.registers.set(Register::BC, 0b0000111111111111);
cpu.exec(Opcode::INC(true, false, Register::BC), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
assert_eq!(cpu.registers.get(Register::BC), 0b0001000000000000);
assert_eq!(cpu.registers.get(Register::PC), 0x101);
} }
#[test] #[test]
@ -2359,7 +2381,7 @@ mod tests {
let mut bus = Bus::new(); let mut bus = Bus::new();
let mut cpu = CPU::new(); let mut cpu = CPU::new();
cpu.registers.set(Register::A, 1); cpu.registers.set(Register::A, 1);
cpu.exec(Opcode::DEC(true, Register::A), &mut bus); cpu.exec(Opcode::DEC(true, false, Register::A), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false);
@ -2367,7 +2389,7 @@ mod tests {
assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::PC), 0x101);
let mut cpu = CPU::new(); let mut cpu = CPU::new();
cpu.registers.set(Register::A, 0b00010000); cpu.registers.set(Register::A, 0b00010000);
cpu.exec(Opcode::DEC(true, Register::A), &mut bus); cpu.exec(Opcode::DEC(true, false, Register::A), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
@ -2377,12 +2399,20 @@ mod tests {
let addr = 0xC000; let addr = 0xC000;
cpu.registers.set(Register::HL, addr); cpu.registers.set(Register::HL, addr);
bus.write(addr, 0b00010000); bus.write(addr, 0b00010000);
cpu.exec(Opcode::DEC(true, Register::HL), &mut bus); cpu.exec(Opcode::DEC(true, true, Register::HL), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
assert_eq!(bus.read(addr), 0b00001111); assert_eq!(bus.read(addr), 0b00001111);
assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::PC), 0x101);
let mut cpu = CPU::new();
cpu.registers.set(Register::BC, 0b0001000000000000);
cpu.exec(Opcode::DEC(true, false, Register::BC), &mut bus);
assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false);
assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true);
assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true);
assert_eq!(cpu.registers.get(Register::BC), 0b0000111111111111);
assert_eq!(cpu.registers.get(Register::PC), 0x101);
} }
#[test] #[test]