aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaditya Dhruv <[email protected]>2025-04-16 23:26:06 -0500
committerAaditya Dhruv <[email protected]>2025-04-16 23:26:06 -0500
commit27276271a8950811ee6c3f4fc59ded2500ad8b7d (patch)
tree1cf3f744c8ec5bb5b24d00b95e4e9e9d98b0d80e
parentf28105008434fd2f08218aa2f9ec3fb221dd00e3 (diff)
Added ALU A R8 support, cleaned up carry helper functions, removed old code
-rw-r--r--src/cpu/chip.rs165
1 files changed, 101 insertions, 64 deletions
diff --git a/src/cpu/chip.rs b/src/cpu/chip.rs
index 847840c..c6a6609 100644
--- a/src/cpu/chip.rs
+++ b/src/cpu/chip.rs
@@ -201,6 +201,19 @@ impl Chip {
}
}
+ // Return the half-carry and carry of adding two u8s
+ fn check_carry_add_u8(&self, lhs: u8, rhs: u8) -> (bool, bool) {
+ let (_, carry) = lhs.overflowing_add(rhs);
+ let half_carry = ((lhs & 0xf).wrapping_add(rhs & 0xf)) & 0x10 == 0x10;
+ return (half_carry, carry);
+ }
+ // Return the half-carry and carry of subtracting two u8s
+ fn check_carry_sub_u8(&self, lhs: u8, rhs: u8) -> (bool, bool) {
+ let (_, carry) = lhs.overflowing_sub(rhs);
+ let half_carry = ((lhs & 0xf).wrapping_sub(rhs & 0xf)) & 0x10 == 0x10; //NOTE: This might need a rework
+ return (half_carry, carry);
+ }
+
pub fn execute(&mut self) {
let mut next = 0;
@@ -251,14 +264,6 @@ impl Chip {
_ => { println!("Error: 0x{:02X} not implemented!", self.instr); std::process::exit(1); },
}
-// match self.instr {
-// 0x00 => { println!("NOOP!") }
-// 0x32 => { self.ldd_hl_a() }
-// 0x0e | 0x06 => { self.ld_rr(); next = 1; }
-// 0xa8..=0xaf => { self.xor_a_r8() }
-// 0x01 | 0x11 | 0x21 | 0x31 => { self.ld_rr_nn(); next = 2; },
-// _ => { println!("Error: 0x{:02X} not implemented!", self.instr); std::process::exit(1); }
-// }
self.pc += next;
}
@@ -270,18 +275,16 @@ impl Chip {
self.set_r8_register(dst_r8, value);
}
+
//TODO - Respond to interrupt
fn halt(&mut self) {
}
+
//TODO
fn special_opcodes(&mut self, opcode: u8) {
}
- fn ld_r8_n8(&mut self, r8: u8) {
- self.set_r8_register(r8, self.byte2);
- }
-
//Increment value in register r8 by 1
fn inc_r8(&mut self, register_lookup: u8) {
@@ -289,7 +292,8 @@ impl Chip {
let sum = register.wrapping_add(1);
if sum == 0 { self.flags.zero = 0 }
self.flags.n = 0;
- if ((0xf & register).wrapping_add(0xf & 1)) & 0x10 == 0x10 { self.flags.h = 1 }
+ let (half_carry, _) = self.check_carry_add_u8(register, 1);
+ if half_carry { self.flags.h = 1 }
self.set_r8_register(register_lookup, sum);
}
@@ -299,7 +303,8 @@ impl Chip {
let sum = register.wrapping_sub(1);
if sum == 0 { self.flags.zero = 0 }
self.flags.n = 1;
- if ((0xf & register).wrapping_sub(0xf & 1)) & 0x10 == 0x10 { self.flags.h = 1 }
+ let (half_carry, _) = self.check_carry_sub_u8(register, 1);
+ if half_carry{ self.flags.h = 1 }
self.set_r8_register(register_lookup, sum);
}
@@ -317,6 +322,11 @@ impl Chip {
self.set_r16_register_address(register_lookup, register);
}
+ //Load value n8 into register r8
+ fn ld_r8_n8(&mut self, r8: u8) {
+ self.set_r8_register(r8, self.byte2);
+ }
+
//Load value pointed in memory by r16 register pair into register A
fn ld_a_r16_addr(&mut self, register_lookup: u8) {
let memory_address = self.get_r16_register_memory_address(register_lookup);
@@ -334,14 +344,15 @@ impl Chip {
let r16 = self.get_r16_register_address(register_lookup);
let hl = self.get_r16_register_address(0b101); //0b101 == HL register pair
let (sum, overflow_high) = r16.overflowing_add(hl);
- self.set_r16_register_address(0b101, sum);
//Additions reset the n flag
self.flags.n = 0;
//Check 11th to 12th bit overflow
- if (r16 & 0xfff).overflowing_add(hl & 0xfff).1 as u8 == 1 { self.flags.h = 1 };
+ if (r16 & 0xfff).overflowing_add(hl & 0xfff).1 as u8 == 1 { self.flags.h = 1 }
//Check 15th to 16th bit overflow
- if overflow_high { self.flags.carry = overflow_high as u8 };
+ if overflow_high { self.flags.carry = 1 }
+
+ self.set_r16_register_address(0b101, sum);
}
//Load value u16 into register r16
@@ -390,65 +401,91 @@ impl Chip {
0b101 => { self.xor_a_r8(r8) },
0b110 => { self.or_a_r8(r8) },
0b111 => { self.cp_a_r8(r8) },
- _ => {}
+ _ => { panic!("Invalid ALU A R8 Operation: opcode: {}, register: {}", opcode, r8)}
}
}
+ //Add the value in r8 to the a register
fn add_a_r8(&mut self, r8: u8) {
+ let reg_val = self.get_r8_register(r8);
+ let (half_carry, carry) = self.check_carry_add_u8(self.a, reg_val);
+ self.a = self.a.wrapping_add(reg_val);
+ if half_carry { self.flags.h = 1 }
+ if carry { self.flags.carry = 1 }
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 0;
}
+ //Add the value in r8 to the a register, along with the value of the carry flag
fn adc_a_r8(&mut self, r8: u8) {
- self.a += self.flags.carry + r8;
+ let sum = self.get_r8_register(r8).wrapping_add(self.flags.carry);
+ let (half_carry, carry) = self.check_carry_add_u8(self.a, sum);
+ self.a = self.a.wrapping_add(sum);
+
+ if half_carry { self.flags.h = 1 }
+ if carry { self.flags.carry = 1 }
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 0;
+
}
+ //Sub the value in r8 from the a register
+ fn sub_a_r8(&mut self, r8: u8) {
+ let reg_val = self.get_r8_register(r8);
+ let (half_carry, carry) = self.check_carry_sub_u8(self.a, reg_val);
+ self.a = self.a.wrapping_sub(reg_val);
- fn xor_a_r8(&mut self, r8: u8) {
- let value = match r8 {
- 0 => { self.b },
- 1 => { self.c },
- 2 => { self.d },
- 3 => { self.e },
- 4 => { self.h },
- 5 => { self.l },
- 6 => {
- let ptr = ((self.h as u16) << 8) as u16 | self.l as u16;
- self.read_memory(ptr)
- },
- 7 => { self.a },
- _ => { panic!("Wrong register read for XOR_R") }
- };
- self.a = self.a ^ value;
- self.flags.zero = (self.a == 0) as u8
- }
-
- fn ld_rr(&mut self) {
- match self.instr {
- 0x0e => { self.c = self.byte2 },
- 0x06 => { self.b = self.byte2 },
- _ => {},
- }
+ if half_carry { self.flags.h = 1 }
+ if carry { self.flags.carry = 1 }
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 1;
+ }
+ //Sub the value in r8 from the a register along with the value of the carry flag
+ fn sbc_a_r8(&mut self, r8: u8) {
+ let sum = self.get_r8_register(r8).wrapping_add(self.flags.carry);
+ let (half_carry, carry) = self.check_carry_sub_u8(self.a, sum);
+ self.a = self.a.wrapping_sub(sum);
+
+ if half_carry { self.flags.h = 1 }
+ if carry { self.flags.carry = 1 }
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 1;
}
-
- fn ldd_hl_a(&mut self) {
- let mut pc = ((self.h as u16) << 8) as u16 | self.l as u16;
- self.write_memory(pc, self.a);
- pc -= 1;
- self.h = (pc >> 8) as u8;
- self.l = (pc << 8 >> 8) as u8;
+
+ //Bitwise AND between r8 value and A
+ fn and_a_r8(&mut self, r8: u8) {
+ self.a = self.a & self.get_r8_register(r8);
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 0;
+ self.flags.h = 1;
+ self.flags.carry = 0;
}
- fn jmp_nn(&mut self) {
- println!("{:02X}, {:02X}", self.byte2, self.byte3);
- self.pc = ((self.byte3 as u16) << 8) as u16 | self.byte2 as u16;
- println!("Jumping to 0x{:02X}", self.pc);
+ //Bitwise XOR between r8 value and A
+ fn xor_a_r8(&mut self, r8: u8) {
+ self.a = self.a ^ self.get_r8_register(r8);
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 0;
+ self.flags.h = 0;
+ self.flags.carry = 0;
}
- fn ld_rr_nn(&mut self) {
- match self.instr {
- 0x01 => { self.b = self.byte3; self.c = self.byte2; }, //BC = nn (nn = MSB << 8 | LSB)
- 0x11 => { self.d = self.byte3; self.e = self.byte2; }, //DE = nn (nn = MSB << 8 | LSB)
- 0x21 => { self.h = self.byte3; self.l = self.byte2; }, //HL = nn (nn = MSB << 8 | LSB)
- 0x31 => { self.sp = ((self.byte3 as u16) << 8) as u16 | self.byte2 as u16 }, //HL = nn (nn = MSB << 8 | LSB)
- _ => { },
- }
+ //Bitwise OR between r8 value and A
+ fn or_a_r8(&mut self, r8: u8) {
+ self.a = self.a | self.get_r8_register(r8);
+ if self.a == 0 { self.flags.zero = 0 }
+ self.flags.n = 0;
+ self.flags.h = 0;
+ self.flags.carry = 0;
+ }
+
+ //Subtract value in r8 from A, but don't store the result, only set flags
+ fn cp_a_r8(&mut self, r8: u8) {
+ let reg_val = self.get_r8_register(r8);
+ let (half_carry, carry) = self.check_carry_sub_u8(self.a, reg_val);
+ let tmp = self.a.wrapping_sub(reg_val);
+
+ if half_carry { self.flags.h = 1 }
+ if carry { self.flags.carry = 1 }
+ if tmp == 0 { self.flags.zero = 0 }
+ self.flags.n = 1;
}
-
}