summaryrefslogtreecommitdiff
path: root/website-emu/src/core.rs
diff options
context:
space:
mode:
Diffstat (limited to 'website-emu/src/core.rs')
-rw-r--r--website-emu/src/core.rs291
1 files changed, 291 insertions, 0 deletions
diff --git a/website-emu/src/core.rs b/website-emu/src/core.rs
new file mode 100644
index 0000000..6817c94
--- /dev/null
+++ b/website-emu/src/core.rs
@@ -0,0 +1,291 @@
+use crate::state::CpuState;
+
+pub fn add(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1].wrapping_add(state.registers[rs2]);
+}
+
+pub fn sub(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1].wrapping_sub(state.registers[rs2]);
+}
+
+pub fn xor(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1] ^ state.registers[rs2];
+}
+
+pub fn or(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1] | state.registers[rs2];
+}
+
+pub fn and(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1] & state.registers[rs2];
+}
+
+pub fn sll(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1] << (state.registers[rs2] & 0b11111);
+}
+
+pub fn srl(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1] >> (state.registers[rs2] & 0b11111);
+}
+
+pub fn sra(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] =
+ ((state.registers[rs1] as i32) >> (state.registers[rs2] & 0b11111)) as u32;
+}
+
+pub fn slt(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ let rs1_signed = state.registers[rs1] as i32;
+ let rs2_signed = state.registers[rs2] as i32;
+
+ state.registers[rd] = if rs1_signed < rs2_signed { 1 } else { 0 };
+}
+
+pub fn sltu(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = if state.registers[rs1] < state.registers[rs2] {
+ 1
+ } else {
+ 0
+ };
+}
+
+pub fn mul(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = state.registers[rs1].wrapping_mul(state.registers[rs2]);
+}
+
+pub fn mulh(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = (((state.registers[rs1] as i32 as i64)
+ * (state.registers[rs2] as i32 as i64))
+ >> 32) as u32;
+}
+
+pub fn mulhsu(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ let rs1_signed = (state.registers[rs1] as i32) as i64;
+ let rs2_unsigned = state.registers[rs2] as i64;
+
+ state.registers[rd] = ((rs1_signed * rs2_unsigned) >> 32) as u32;
+}
+
+pub fn mulhu(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] =
+ ((state.registers[rs1] as u64 * state.registers[rs2] as u64) >> 32) as u32;
+}
+
+pub fn div(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ let a = state.registers[rs1] as i32;
+ let b = state.registers[rs2] as i32;
+
+ state.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(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = if state.registers[rs2] == 0 {
+ u32::MAX
+ } else {
+ state.registers[rs1] / state.registers[rs2]
+ };
+}
+
+pub fn rem(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ let a = state.registers[rs1] as i32;
+ let b = state.registers[rs2] as i32;
+
+ state.registers[rd] = if b == 0 {
+ a as u32
+ } else if a == i32::MIN && b == -1 {
+ 0
+ } else {
+ (a % b) as u32
+ };
+}
+
+pub fn remu(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) {
+ state.registers[rd] = if state.registers[rs2] == 0 {
+ state.registers[rs1]
+ } else {
+ state.registers[rs1] % state.registers[rs2]
+ };
+}
+
+pub fn addi(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.registers[rs1].wrapping_add(imm);
+}
+
+pub fn xori(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.registers[rs1] ^ imm;
+}
+
+pub fn ori(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.registers[rs1] | imm;
+}
+
+pub fn andi(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.registers[rs1] & imm;
+}
+
+pub fn slli(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.registers[rs1] << (imm & 0b11111);
+}
+pub fn srli(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.registers[rs1] >> (imm & 0b11111);
+}
+pub fn srai(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = ((state.registers[rs1] as i32) >> (imm & 0b11111)) as u32;
+}
+
+pub fn slti(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = if (state.registers[rs1] as i32) < (imm as i32) {
+ 1
+ } else {
+ 0
+ };
+}
+
+pub fn sltiu(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = if state.registers[rs1] < imm { 1 } else { 0 };
+}
+pub fn lb(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ let byte = state.memory.read(state.registers[rs1] + imm).unwrap();
+ state.registers[rd] = (byte as i8) as u32;
+}
+
+pub fn lh(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ let halfword = state.memory.read_halfword(state.registers[rs1] + imm).unwrap();
+ state.registers[rd] = (halfword as i16) as u32;
+}
+
+pub fn lw(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ let addr = state.registers[rs1].wrapping_add(imm);
+ let word = state.memory.read_word(addr).unwrap();
+ state.registers[rd] = word;
+}
+
+pub fn lbu(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state
+ .memory
+ .read(state.registers[rs1].wrapping_add(imm))
+ .unwrap() as u32;
+}
+
+pub fn lhu(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.memory.read_halfword(state.registers[rs1] + imm).unwrap() as u32;
+}
+pub fn sb(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ let addr = state.registers[rs1] + imm;
+ state
+ .memory
+ .write(addr, state.registers[rs2] as u8)
+ .unwrap();
+}
+
+pub fn sh(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ let addr = (state.registers[rs1] + imm) as usize;
+
+ let halfword= (state.registers[rs2] & 0xFFFF) as u16;
+
+ state.memory.write_halfword(addr as u32, halfword).unwrap();
+}
+
+pub fn sw(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ let addr = (state.registers[rs1] + imm) as usize;
+
+ state.memory.write_word(addr as u32, state.registers[rs2]).unwrap();
+}
+
+pub fn beq(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ if state.registers[rs1] == state.registers[rs2] {
+ state.pc = state.pc.wrapping_add(imm);
+ } else {
+ state.pc += 4;
+ }
+}
+
+pub fn bne(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ if state.registers[rs1] != state.registers[rs2] {
+ state.pc = state.pc.wrapping_add(imm);
+ } else {
+ state.pc += 4;
+ }
+}
+
+pub fn blt(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ if (state.registers[rs1] as i32) < (state.registers[rs2] as i32) {
+ state.pc = state.pc.wrapping_add(imm);
+ } else {
+ state.pc += 4;
+ }
+}
+
+pub fn bge(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ if (state.registers[rs1] as i32) >= (state.registers[rs2] as i32) {
+ state.pc = state.pc.wrapping_add(imm);
+ } else {
+ state.pc += 4;
+ }
+}
+
+pub fn bltu(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ if state.registers[rs1] < state.registers[rs2] {
+ state.pc = state.pc.wrapping_add(imm);
+ } else {
+ state.pc += 4;
+ }
+}
+
+pub fn bgeu(state: &mut CpuState, rs1: usize, rs2: usize, imm: u32) {
+ if state.registers[rs1] >= state.registers[rs2] {
+ state.pc = state.pc.wrapping_add(imm);
+ } else {
+ state.pc += 4;
+ }
+}
+pub fn jal(state: &mut CpuState, rd: usize, imm: u32) {
+ state.registers[rd] = state.pc + 4;
+ state.pc = state.pc.wrapping_add(imm);
+}
+
+pub fn jalr(state: &mut CpuState, rd: usize, rs1: usize, imm: u32) {
+ state.registers[rd] = state.pc + 4;
+ state.pc = state.registers[rs1] + imm;
+}
+pub fn lui(state: &mut CpuState, rd: usize, imm: u32) {
+ state.registers[rd] = imm << 12;
+}
+pub fn auipc(state: &mut CpuState, rd: usize, imm: u32) {
+ state.registers[rd] = state.pc + (imm << 12);
+}
+
+pub fn csrrw(state: &mut CpuState, rd: usize, rs1: usize, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] = state.registers[rs1];
+}
+
+pub fn csrrwi(state: &mut CpuState, rd: usize, imm: u32, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] = imm;
+}
+
+pub fn csrrc(state: &mut CpuState, rd: usize, rs1: usize, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] &= !state.registers[rs1];
+}
+
+pub fn csrrci(state: &mut CpuState, rd: usize, imm: u32, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] &= !imm;
+}
+
+pub fn csrrs(state: &mut CpuState, rd: usize, rs1: usize, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] |= state.registers[rs1];
+}
+
+pub fn csrrsi(state: &mut CpuState, rd: usize, imm: u32, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] |= imm;
+} \ No newline at end of file