summaryrefslogtreecommitdiff
path: root/src/core.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/core.rs')
-rw-r--r--src/core.rs245
1 files changed, 245 insertions, 0 deletions
diff --git a/src/core.rs b/src/core.rs
new file mode 100644
index 0000000..ff6bb52
--- /dev/null
+++ b/src/core.rs
@@ -0,0 +1,245 @@
+pub fn add(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1].wrapping_add(registers[rs2]);
+}
+
+pub fn sub(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1].wrapping_sub(registers[rs2]);
+}
+
+pub fn xor(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1] ^ registers[rs2];
+}
+
+pub fn or(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1] | registers[rs2];
+}
+
+pub fn and(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1] & registers[rs2];
+}
+
+pub fn sll(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1] << (registers[rs2] & 0b11111);
+}
+
+pub fn srl(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1] >> (registers[rs2] & 0b11111);
+}
+
+pub fn sra(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = ((registers[rs1] as i32) >> (registers[rs2] & 0b11111)) as u32;
+}
+
+pub fn slt(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ let rs1_signed = registers[rs1] as i32;
+ let rs2_signed = registers[rs2] as i32;
+
+ registers[rd] = if rs1_signed < rs2_signed { 1 } else { 0 };
+}
+
+pub fn sltu(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = if registers[rs1] < registers[rs2] {
+ 1
+ } else {
+ 0
+ };
+}
+
+pub fn mul(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = registers[rs1].wrapping_mul(registers[rs2]);
+}
+
+pub fn mulh(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] =
+ (((registers[rs1] as i32 as i64) * (registers[rs2] as i32 as i64)) >> 32) as u32;
+}
+
+pub fn mulhsu(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ let rs1_signed = (registers[rs1] as i32) as i64;
+ let rs2_unsigned = registers[rs2] as i64;
+
+ registers[rd] = ((rs1_signed * rs2_unsigned) >> 32) as u32;
+}
+
+pub fn mulhu(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = ((registers[rs1] as u64 * registers[rs2] as u64) >> 32) as u32;
+}
+
+pub fn div(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ let a = registers[rs1] as i32;
+ let b = registers[rs2] as i32;
+
+ registers[rd] = if b == 0 {
+ u32::MAX
+ } else if a == i32::MIN && b == -1 {
+ a as u32
+ } else {
+ (a / b) as u32
+ };
+}
+
+pub fn divu(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = if registers[rs2] == 0 {
+ u32::MAX
+ } else {
+ registers[rs1] / registers[rs2]
+ };
+}
+
+pub fn rem(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ let a = registers[rs1] as i32;
+ let b = registers[rs2] as i32;
+
+ registers[rd] = if b == 0 {
+ a as u32
+ } else if a == i32::MIN && b == -1 {
+ 0
+ } else {
+ (a % b) as u32
+ };
+}
+
+pub fn remu(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) {
+ registers[rd] = if registers[rs2] == 0 {
+ registers[rs1]
+ } else {
+ registers[rs1] % registers[rs2]
+ };
+}
+
+pub fn addi(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = registers[rs1].wrapping_add(imm);
+}
+
+pub fn xori(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = registers[rs1] ^ imm;
+}
+
+pub fn ori(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = registers[rs1] | imm;
+}
+
+pub fn andi(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = registers[rs1] & imm;
+}
+
+pub fn slli(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = registers[rs1] << (imm & 0b11111);
+}
+pub fn srli(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = registers[rs1] >> (imm & 0b11111);
+}
+pub fn srai(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = ((registers[rs1] as i32) >> (imm & 0b11111)) as u32;
+}
+
+pub fn slti(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = if (registers[rs1] as i32) < (imm as i32) {
+ 1
+ } else {
+ 0
+ };
+}
+
+pub fn sltiu(registers: &mut [u32; 32], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = if registers[rs1] < imm { 1 } else { 0 };
+}
+pub fn lb(registers: &mut [u32; 32], memory: &[u8], rd: usize, rs1: usize, imm: u32) {
+ let byte = memory[(registers[rs1] + imm) as usize];
+ registers[rd] = (byte as i8) as u32;
+}
+
+pub fn lh(registers: &mut [u32; 32], memory: &[u8], rd: usize, rs1: usize, imm: u32) {
+ let low = memory[(registers[rs1] + imm) as usize];
+ let high = memory[(registers[rs1] + imm + 1) as usize];
+
+ registers[rd] = (((high as u16) << 8 | low as u16) as i16) as u32;
+}
+
+pub fn lw(registers: &mut [u32; 32], memory: &[u8], rd: usize, rs1: usize, imm: u32) {
+ let addr = (registers[rs1] + imm) as usize;
+ let slice = memory.get(addr..addr + 4).unwrap();
+ let number = u32::from_le_bytes(slice.try_into().unwrap());
+
+ registers[rd] = number;
+}
+
+pub fn lbu(registers: &mut [u32; 32], memory: &[u8], rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = memory[(registers[rs1] + imm) as usize] as u32;
+}
+
+pub fn lhu(registers: &mut [u32; 32], memory: &[u8], rd: usize, rs1: usize, imm: u32) {
+ let low = memory[(registers[rs1] + imm) as usize];
+ let high = memory[(registers[rs1] + imm + 1) as usize];
+
+ registers[rd] = ((high as u16) << 8 | low as u16) as u32;
+}
+pub fn sb(registers: &[u32; 32], memory: &mut [u8], rs1: usize, rs2: usize, imm: u32) {
+ memory[(registers[rs1] + imm) as usize] = registers[rs2] as u8;
+}
+
+pub fn sh(registers: &[u32; 32], memory: &mut [u8], rs1: usize, rs2: usize, imm: u32) {
+ let halfword = registers[rs2] & 0xFFFF;
+ let index = (registers[rs1] + imm) as usize;
+
+ memory[index] = (halfword & 0xFF) as u8;
+ memory[index + 1] = (halfword >> 8) as u8;
+}
+
+pub fn sw(registers: &[u32; 32], memory: &mut [u8], rs1: usize, rs2: usize, imm: u32) {
+ let index = (registers[rs1] + imm) as usize;
+
+ memory[index..index + 4].copy_from_slice(&registers[rs2].to_le_bytes());
+}
+
+pub fn beq(registers: &[u32; 32], pc: &mut u32, rs1: usize, rs2: usize, imm: u32) {
+ if registers[rs1] == registers[rs2] {
+ *pc += imm;
+ }
+}
+
+pub fn bne(registers: &[u32; 32], pc: &mut u32, rs1: usize, rs2: usize, imm: u32) {
+ if registers[rs1] != registers[rs2] {
+ *pc += imm;
+ }
+}
+
+pub fn blt(registers: &[u32; 32], pc: &mut u32, rs1: usize, rs2: usize, imm: u32) {
+ if (registers[rs1] as i32) < (registers[rs2] as i32) {
+ *pc += imm;
+ }
+}
+
+pub fn bge(registers: &[u32; 32], pc: &mut u32, rs1: usize, rs2: usize, imm: u32) {
+ if (registers[rs1] as i32) >= (registers[rs2] as i32) {
+ *pc += imm;
+ }
+}
+
+pub fn bltu(registers: &[u32; 32], pc: &mut u32, rs1: usize, rs2: usize, imm: u32) {
+ if registers[rs1] < registers[rs2] {
+ *pc += imm;
+ }
+}
+
+pub fn bgeu(registers: &[u32; 32], pc: &mut u32, rs1: usize, rs2: usize, imm: u32) {
+ if registers[rs1] >= registers[rs2] {
+ *pc += imm;
+ }
+}
+pub fn jal(registers: &mut [u32; 32], pc: &mut u32, rd: usize, imm: u32) {
+ registers[rd] = *pc + 4;
+ *pc += imm;
+}
+
+pub fn jalr(registers: &mut [u32; 32], pc: &mut u32, rd: usize, rs1: usize, imm: u32) {
+ registers[rd] = *pc + 4;
+ *pc = registers[rs1] + imm;
+}
+pub fn lui(registers: &mut [u32; 32], rd: usize, imm: u32) {
+ registers[rd] = imm << 12;
+}
+
+pub fn auipc(registers: &mut [u32; 32], pc: u32, rd: usize, imm: u32) {
+ registers[rd] = pc + (imm << 12);
+}