diff options
Diffstat (limited to 'src/core.rs')
| -rw-r--r-- | src/core.rs | 245 |
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(®isters[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); +} |
