Prevent panic on adding or sub with overflow on CPU

This commit is contained in:
Franco Colmenarez 2021-10-19 13:17:14 -05:00
parent f928207a8d
commit 6b1d50ba76
3 changed files with 21 additions and 19 deletions

View File

@ -43,7 +43,7 @@ pub struct Bus {
impl Bus { impl Bus {
pub fn new() -> Self { pub fn new() -> Self {
let game_rom = match ROM::load_file("roms/cpu_instrs_individual/02-interrupts.gb".to_string()) { let game_rom = match ROM::load_file("roms/cpu_instrs_individual/03-op sp,hl.gb".to_string()) {
Ok(rom) => rom, Ok(rom) => rom,
_ => ROM::from_bytes(&[0; 0xFFFF]) _ => ROM::from_bytes(&[0; 0xFFFF])
}; };

View File

@ -25,7 +25,7 @@ impl Console {
self.cpu.run(&mut self.bus); self.cpu.run(&mut self.bus);
// thread::sleep(time::Duration::from_millis(100)); // thread::sleep(time::Duration::from_millis(100));
exit = self.cpu.get_exec_calls_count() >= 1258895; exit = self.cpu.get_exec_calls_count() >= 1068422;
} }
} }
} }

View File

@ -163,12 +163,14 @@ impl Registers {
} }
} }
pub fn increment(&mut self, register: Register, times: u8) { pub fn increment(&mut self, register: Register, times: u16) {
self.set(register, self.get(register) + (times as u16)); let val = self.get(register);
self.set(register, val.wrapping_add(times));
} }
pub fn decrement(&mut self, register: Register, times: u8) { pub fn decrement(&mut self, register: Register, times: u16) {
self.set(register, self.get(register) - (times as u16)); let val = self.get(register);
self.set(register, val.wrapping_sub(times));
} }
} }
@ -323,7 +325,7 @@ impl CPU {
OpcodeParameter::Register_Register(reg1, reg2) => { OpcodeParameter::Register_Register(reg1, reg2) => {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
if reg1.is_16bit() && reg2.is_8bit() { if reg1.is_16bit() && reg2.is_8bit() {
let val = self.registers.get(reg2).to_be_bytes()[1]; let val = self.registers.get_8bit(reg2);
let addr = self.registers.get(reg1); let addr = self.registers.get(reg1);
bus.write(addr, val); bus.write(addr, val);
} else if reg1.is_8bit() && reg2.is_16bit() { } else if reg1.is_8bit() && reg2.is_16bit() {
@ -360,13 +362,13 @@ impl CPU {
OpcodeParameter::FF00plusU8_Register(val, register) => { OpcodeParameter::FF00plusU8_Register(val, register) => {
self.registers.increment(Register::PC, 2); self.registers.increment(Register::PC, 2);
match register.is_8bit() { match register.is_8bit() {
true => bus.write(0xFF00 + (val as u16), self.registers.get(register).to_be_bytes()[1]), true => bus.write(0xFF00 + (val as u16), self.registers.get_8bit(register)),
false => bus.write_16bit(0xFF00 + (val as u16), self.registers.get(register)), false => bus.write_16bit(0xFF00 + (val as u16), self.registers.get(register)),
} }
}, },
OpcodeParameter::Register_RegisterPlusI8(reg1, reg2, val) => { OpcodeParameter::Register_RegisterPlusI8(reg1, reg2, val) => {
self.registers.increment(Register::PC, 2); self.registers.increment(Register::PC, 2);
let res = (self.registers.get(reg2) as i16) + (val as i16); let res = (self.registers.get(reg2) as i16).wrapping_add(val as i16);
self.registers.set(reg1, res as u16); self.registers.set(reg1, res as u16);
}, },
_ => {}, _ => {},
@ -406,7 +408,7 @@ impl CPU {
}, },
OpcodeParameter::RegisterIncrement_Register(reg1, reg2) => { OpcodeParameter::RegisterIncrement_Register(reg1, reg2) => {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
let val = self.registers.get(reg2).to_be_bytes()[1]; let val = self.registers.get_8bit(reg2);
bus.write(self.registers.get(reg1), val); bus.write(self.registers.get(reg1), val);
self.registers.increment(reg1, 1); self.registers.increment(reg1, 1);
}, },
@ -422,7 +424,7 @@ impl CPU {
}, },
OpcodeParameter::RegisterDecrement_Register(reg1, reg2) => { OpcodeParameter::RegisterDecrement_Register(reg1, reg2) => {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
let val = self.registers.get(reg2).to_be_bytes()[1]; let val = self.registers.get_8bit(reg2);
bus.write(self.registers.get(reg1), val); bus.write(self.registers.get(reg1), val);
self.registers.decrement(reg1, 1); self.registers.decrement(reg1, 1);
}, },
@ -532,15 +534,15 @@ impl CPU {
OpcodeParameter::Register_Register(reg1, reg2) => { OpcodeParameter::Register_Register(reg1, reg2) => {
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.increment(reg1, self.registers.get(reg2));
self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); 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.increment(reg1, self.registers.get(reg2));
} else if reg1.is_8bit() && reg2.is_16bit() { } else if reg1.is_8bit() && reg2.is_16bit() {
let val1 = self.registers.get(reg1); let val1 = self.registers.get(reg1);
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.increment(reg1, 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);
} }
@ -550,7 +552,7 @@ impl CPU {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
let val1 = self.registers.get(reg1); let val1 = self.registers.get(reg1);
let val2 = val as u16; let val2 = val as u16;
self.registers.set(reg1, val1 + val2); self.registers.increment(reg1, 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);
@ -559,7 +561,7 @@ impl CPU {
self.registers.increment(Register::PC, 1); self.registers.increment(Register::PC, 1);
let val1 = self.registers.get(reg1) as i16; let val1 = self.registers.get(reg1) as i16;
let val2 = value as i16; let val2 = value as i16;
self.registers.set(reg1, (val1 + val2) as u16); self.registers.increment(reg1, val2 as u16);
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);
@ -615,7 +617,7 @@ impl CPU {
if carry { if carry {
val1 = val1 | 0x100; val1 = val1 | 0x100;
} }
let result = val1 - val2; let result = val1.wrapping_sub(val2);
self.registers.set(register, result); self.registers.set(register, result);
self.registers.set_flag(FlagRegister::Zero, self.registers.get(register) == 0); self.registers.set_flag(FlagRegister::Zero, self.registers.get(register) == 0);
self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::Substract, true);
@ -649,7 +651,7 @@ impl CPU {
if on_address { if on_address {
let addr = self.registers.get(register); let addr = self.registers.get(register);
let prev_value = bus.read(addr); let prev_value = bus.read(addr);
bus.write(addr, prev_value + 1); bus.write(addr, prev_value.wrapping_add(1));
if affect_flags { if affect_flags {
self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::Substract, false);
self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(prev_value, 1)); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(prev_value, 1));
@ -677,7 +679,7 @@ impl CPU {
if on_address { if on_address {
let addr = self.registers.get(register); let addr = self.registers.get(register);
let prev_value = bus.read(addr); let prev_value = bus.read(addr);
bus.write(addr, prev_value - 1); bus.write(addr, prev_value.wrapping_sub(1));
if affect_flags { if affect_flags {
self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::Substract, true);
self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(prev_value, 1)); self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(prev_value, 1));