mirror of
https://github.com/FranLMSP/rultra64.git
synced 2026-01-01 07:51:34 -05:00
Exceptions for ADD and ADDI and AND instruction
This commit is contained in:
84
src/cpu.rs
84
src/cpu.rs
@@ -20,35 +20,59 @@ impl CPU {
|
||||
let rd = (opcode >> 11) & 0b11111;
|
||||
let rs = (opcode >> 21) & 0b11111;
|
||||
let rt = (opcode >> 16) & 0b11111;
|
||||
self.add(rd as usize, rs as usize, rt as usize);
|
||||
let res = self.add(rd as usize, rs as usize, rt as usize);
|
||||
// ADDU
|
||||
if (opcode & 0b11111111111) == 0b00000100000 {
|
||||
todo!("Throw exception for add overflow ADDU");
|
||||
if let Err(_) = res {
|
||||
todo!("Throw exception for add overflow ADDU");
|
||||
}
|
||||
}
|
||||
},
|
||||
0b001000 | 0b001001 => {
|
||||
let rt = (opcode >> 11) & 0b11111;
|
||||
let rs = (opcode >> 21) & 0b11111;
|
||||
let immediate = (opcode & 0xFFFF) as i16;
|
||||
self.addi(rt as usize, rs as usize, immediate);
|
||||
if inst == 0b001001 {
|
||||
todo!("Throw exception for add overflow ADDIU");
|
||||
let res = self.addi(rt as usize, rs as usize, immediate);
|
||||
// ADDIU
|
||||
if inst == 0b001000 {
|
||||
if let Err(_) = res {
|
||||
todo!("Throw exception for add overflow ADDIU");
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, rd: usize, rs: usize, rt: usize) {
|
||||
let s = self.registers.get_by_number(rs);
|
||||
let t = self.registers.get_by_number(rt);
|
||||
let result = s.wrapping_add(t);
|
||||
pub fn add(&mut self, rd: usize, rs: usize, rt: usize) -> Result<i64, i64> {
|
||||
let s = self.registers.get_by_number(rs) as i32;
|
||||
let t = self.registers.get_by_number(rt) as i32;
|
||||
let result = s.wrapping_add(t) as i64;
|
||||
let will_overflow = s.checked_add(t);
|
||||
self.registers.set_by_number(rd, result);
|
||||
match will_overflow {
|
||||
Some(_) => Ok(result),
|
||||
None => Err(result),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addi(&mut self, rt: usize, rs: usize, immediate: i16) {
|
||||
let s = self.registers.get_by_number(rs);
|
||||
let result = s.wrapping_add(immediate as i64);
|
||||
pub fn addi(&mut self, rt: usize, rs: usize, immediate: i16) -> Result<i64, i64> {
|
||||
let s = self.registers.get_by_number(rs) as i32;
|
||||
let immediate = immediate as i32;
|
||||
let result = s.wrapping_add(immediate) as i64;
|
||||
let will_overflow = s.checked_add(immediate);
|
||||
self.registers.set_by_number(rt, result);
|
||||
match will_overflow {
|
||||
Some(_) => Ok(result),
|
||||
None => Err(result),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn and(&mut self, rd: usize, rs: usize, rt: usize) {
|
||||
let s = self.registers.get_by_number(rs);
|
||||
let t = self.registers.get_by_number(rt);
|
||||
let result = s & t;
|
||||
self.registers.set_by_number(rd, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,13 +88,19 @@ mod cpu_instructions_tests {
|
||||
let reg_t = 20;
|
||||
cpu.registers.set_by_number(reg_s, 80);
|
||||
cpu.registers.set_by_number(reg_t, 80);
|
||||
cpu.add(reg_dest, reg_s, reg_t);
|
||||
let _ = cpu.add(reg_dest, reg_s, reg_t);
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest), 160);
|
||||
|
||||
cpu.registers.set_by_number(reg_s, 40);
|
||||
cpu.registers.set_by_number(reg_t, -80);
|
||||
cpu.add(reg_dest, reg_s, reg_t);
|
||||
let _ = cpu.add(reg_dest, reg_s, reg_t);
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest), -40);
|
||||
|
||||
cpu.registers.set_by_number(reg_s, i32::MAX as i64);
|
||||
cpu.registers.set_by_number(reg_t, 1);
|
||||
let res = cpu.add(reg_dest, reg_s, reg_t);
|
||||
assert!(res.is_err());
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest) as i32, i32::MIN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -79,11 +109,33 @@ mod cpu_instructions_tests {
|
||||
let reg_dest = 10;
|
||||
let reg_s = 15;
|
||||
cpu.registers.set_by_number(reg_s, 80);
|
||||
cpu.addi(reg_dest, reg_s, 80);
|
||||
let _ = cpu.addi(reg_dest, reg_s, 80);
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest), 160);
|
||||
|
||||
cpu.registers.set_by_number(reg_s, 80);
|
||||
cpu.addi(reg_dest, reg_s, -40);
|
||||
let _ = cpu.addi(reg_dest, reg_s, -40);
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest), 40);
|
||||
|
||||
cpu.registers.set_by_number(reg_s, i32::MAX as i64);
|
||||
let res = cpu.addi(reg_dest, reg_s, 1);
|
||||
assert!(res.is_err());
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest) as i32, i32::MIN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_and() {
|
||||
let mut cpu = CPU::new();
|
||||
let reg_dest = 10;
|
||||
let reg_s = 15;
|
||||
let reg_t = 20;
|
||||
cpu.registers.set_by_number(reg_s, 123);
|
||||
cpu.registers.set_by_number(reg_t, 123);
|
||||
cpu.and(reg_dest, reg_s, reg_t);
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest), 123);
|
||||
|
||||
cpu.registers.set_by_number(reg_s, 123);
|
||||
cpu.registers.set_by_number(reg_t, 321);
|
||||
cpu.and(reg_dest, reg_s, reg_t);
|
||||
assert_eq!(cpu.registers.get_by_number(reg_dest), 65);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user