From 6858c9e7c97f772eb357e3eee0c1fcfb8adcb699 Mon Sep 17 00:00:00 2001 From: Nathan Lee Date: Fri, 25 Sep 2026 22:39:01 -0500 Subject: scaffold emulator from wrv32em --- website-emu/src/core.rs | 291 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 website-emu/src/core.rs (limited to 'website-emu/src/core.rs') 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 -- cgit v1.2.3