unsigned operations

This commit is contained in:
2022-01-05 18:31:41 -05:00
parent ca1fc4d12c
commit f710134faf

View File

@@ -57,12 +57,12 @@ impl CPU {
// DADDU
0b000_0010_1101 => {
let (rd, rs, rt) = params_rd_rs_rt(opcode);
let _ = self.dadd(rd, rs, rt);
self.daddu(rd, rs, rt);
},
// ADDU
0b000_0010_0001 => {
let (rd, rs, rt) = params_rd_rs_rt(opcode);
let _ = self.add(rd, rs, rt);
self.addu(rd, rs, rt);
},
// SUB
0b000_0010_0010 => {
@@ -75,7 +75,7 @@ impl CPU {
// SUBU
0b000_0010_0011 => {
let (rd, rs, rt) = params_rd_rs_rt(opcode);
let _ = self.sub(rd, rs, rt);
self.subu(rd, rs, rt);
},
// DSUB
0b000_0010_1110 => {
@@ -88,7 +88,7 @@ impl CPU {
// DSUBU
0b000_0010_1111 => {
let (rd, rs, rt) = params_rd_rs_rt(opcode);
let _ = self.dsub(rd, rs, rt);
self.dsubu(rd, rs, rt);
},
// DIV
0b000_0001_1010 => {
@@ -158,8 +158,8 @@ impl CPU {
_ => unimplemented!(),
};
},
// DADDI | DADDIU
0b0110_00 | 0b0110_01 => {
// DADDI
0b0110_00 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
let res = self.daddi(rt, rs, immediate);
if inst == 0b0110_00 {
@@ -168,8 +168,13 @@ impl CPU {
}
}
},
// ADDI | ADDIU
0b0010_00 | 0b0010_01 => {
// DADDIU
0b0110_01 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
self.daddiu(rt, rs, immediate);
},
// ADDI
0b0010_00 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
let res = self.addi(rt, rs, immediate);
if inst == 0b0010_00 {
@@ -178,6 +183,11 @@ impl CPU {
}
}
},
// ADDIU
0b0010_01 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
self.addiu(rt, rs, immediate);
},
// ANDI
0b0011_00 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
@@ -188,6 +198,16 @@ impl CPU {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
self.ori(rt, rs, immediate);
},
// SLTI
0b0010_10 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
self.slti(rt, rs, immediate);
},
// SLTIU
0b0010_11 => {
let (rt, rs, immediate) = params_rt_rs_immediate(opcode);
self.sltiu(rt, rs, immediate);
},
_ => unimplemented!(),
}
}
@@ -204,6 +224,13 @@ impl CPU {
}
}
pub fn addu(&mut self, rd: usize, rs: usize, rt: usize) {
let s = (self.registers.get_by_number(rs) as i32) as u32;
let t = (self.registers.get_by_number(rt) as i32) as u32;
let result = s.wrapping_add(t) as u64;
self.registers.set_by_number(rd, result 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;
@@ -216,6 +243,13 @@ impl CPU {
}
}
pub fn addiu(&mut self, rt: usize, rs: usize, immediate: i16) {
let s = (self.registers.get_by_number(rs) as i32) as u32;
let immediate = (immediate as i32) as u32;
let result = s.wrapping_add(immediate) as u64;
self.registers.set_by_number(rt, result as i64);
}
pub fn dadd(&mut self, rd: usize, rs: usize, rt: usize) -> Result<i64, i64> {
let s = self.registers.get_by_number(rs);
let t = self.registers.get_by_number(rt);
@@ -228,6 +262,13 @@ impl CPU {
}
}
pub fn daddu(&mut self, rd: usize, rs: usize, rt: usize) {
let s = self.registers.get_by_number(rs) as u64;
let t = self.registers.get_by_number(rt) as u64;
let result = s.wrapping_add(t);
self.registers.set_by_number(rd, result as i64);
}
pub fn daddi(&mut self, rt: usize, rs: usize, immediate: i16) -> Result<i64, i64> {
let s = self.registers.get_by_number(rs);
let immediate = immediate as i64;
@@ -240,6 +281,13 @@ impl CPU {
}
}
pub fn daddiu(&mut self, rt: usize, rs: usize, immediate: i16) {
let s = self.registers.get_by_number(rs) as u64;
let immediate = (immediate as u16) as u64;
let result = s.wrapping_add(immediate);
self.registers.set_by_number(rt, result as i64);
}
pub fn sub(&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;
@@ -252,6 +300,13 @@ impl CPU {
}
}
pub fn subu(&mut self, rd: usize, rs: usize, rt: usize) {
let s = (self.registers.get_by_number(rs) as i32) as u32;
let t = (self.registers.get_by_number(rt) as i32) as u32;
let result = s.wrapping_sub(t) as u64;
self.registers.set_by_number(rd, result as i64);
}
pub fn dsub(&mut self, rd: usize, rs: usize, rt: usize) -> Result<i64, i64> {
let s = self.registers.get_by_number(rs);
let t = self.registers.get_by_number(rt);
@@ -264,6 +319,13 @@ impl CPU {
}
}
pub fn dsubu(&mut self, rd: usize, rs: usize, rt: usize) {
let s = self.registers.get_by_number(rs) as u64;
let t = self.registers.get_by_number(rt) as u64;
let result = s.wrapping_sub(t);
self.registers.set_by_number(rd, result as i64);
}
pub fn div(&mut self, rs: usize, rt: usize) {
let s = self.registers.get_by_number(rs) as i32;
let t = self.registers.get_by_number(rt) as i32;
@@ -382,6 +444,20 @@ impl CPU {
let result = (self.registers.get_by_number(rs) as u64) < (self.registers.get_by_number(rt) as u64);
self.registers.set_by_number(rd, if result {1} else {0});
}
pub fn slti(&mut self, rt: usize, rs: usize, immediate: i16) {
let s = self.registers.get_by_number(rs);
let immediate = immediate as i64;
let result = s < immediate;
self.registers.set_by_number(rt, if result {1} else {0});
}
pub fn sltiu(&mut self, rt: usize, rs: usize, immediate: i16) {
let s = self.registers.get_by_number(rs) as u64;
let immediate = (immediate as u16) as u64;
let result = s < immediate;
self.registers.set_by_number(rt, if result {1} else {0});
}
}
#[cfg(test)]
@@ -711,29 +787,34 @@ mod cpu_instructions_tests {
}
#[test]
fn test_sltu() {
fn test_slti() {
let mut cpu = CPU::new();
let reg_dest = 10;
let reg_s = 15;
let reg_t = 20;
let reg_s = 15;
cpu.registers.set_by_number(reg_s, 123);
cpu.registers.set_by_number(reg_t, 123);
cpu.sltu(reg_dest, reg_s, reg_t);
assert_eq!(cpu.registers.get_by_number(reg_dest), 0);
cpu.slti(reg_t, reg_s, 123);
assert_eq!(cpu.registers.get_by_number(reg_t), 0);
cpu.registers.set_by_number(reg_s, 123);
cpu.registers.set_by_number(reg_t, 321);
cpu.sltu(reg_dest, reg_s, reg_t);
assert_eq!(cpu.registers.get_by_number(reg_dest), 1);
cpu.slti(reg_t, reg_s, -123);
assert_eq!(cpu.registers.get_by_number(reg_t), 0);
cpu.registers.set_by_number(reg_s, 321);
cpu.registers.set_by_number(reg_t, 123);
cpu.sltu(reg_dest, reg_s, reg_t);
assert_eq!(cpu.registers.get_by_number(reg_dest), 0);
cpu.registers.set_by_number(reg_s, -123);
cpu.slti(reg_t, reg_s, 123);
assert_eq!(cpu.registers.get_by_number(reg_t), 1);
}
cpu.registers.set_by_number(reg_s, i64::MAX);
cpu.registers.set_by_number(reg_t, i64::MIN);
cpu.sltu(reg_dest, reg_s, reg_t);
assert_eq!(cpu.registers.get_by_number(reg_dest), 1);
#[test]
fn test_sltiu() {
let mut cpu = CPU::new();
let reg_t = 20;
let reg_s = 15;
cpu.registers.set_by_number(reg_s, 123);
cpu.sltiu(reg_t, reg_s, 123);
assert_eq!(cpu.registers.get_by_number(reg_t), 0);
cpu.registers.set_by_number(reg_s, 123);
cpu.sltiu(reg_t, reg_s, 321);
assert_eq!(cpu.registers.get_by_number(reg_t), 1);
}
}