mod addr;
mod decode;
mod reg;
pub mod memory;
pub use crate::decode::{decode, DecodeError};
pub use crate::memory::Memory;
pub use addr::Addr;
pub use reg::{Reg, RegVal};
use std::fmt;
pub use decode::Instruction;
pub struct RiscV {
program_counter: Addr,
registers: [RegVal; 32],
}
#[derive(Debug)]
pub enum StepResult {
Ok,
Call,
Break,
DecodeError(decode::DecodeError),
}
impl RiscV {
pub fn new() -> Self {
RiscV {
program_counter: Addr::new(0x0),
registers: [RegVal::from_u32(0); 32],
}
}
pub fn step<M: Memory>(&mut self, memory: &mut M) -> StepResult {
self.step_with_retired(memory).0
}
pub fn step_with_retired<M: Memory>(&mut self, memory: &mut M) -> (StepResult, Option<Instruction>) {
let instruction_opt = decode::decode(memory.load_word(self.program_counter));
match instruction_opt {
Ok(instruction) => (self.step_instruction(instruction.clone(), memory), Some(instruction)),
Err(invalid_instruction) => (StepResult::DecodeError(invalid_instruction), None),
}
}
fn step_instruction<M: Memory>(&mut self, instruction: Instruction, memory: &mut M) -> StepResult {
match instruction {
Instruction::Beq { rs1, rs2, imm } => {
let v1 = self.reg(rs1);
let v2 = self.reg(rs2);
if v1 == v2 {
self.program_counter += imm.val();
} else {
self.program_counter += 4;
}
StepResult::Ok
}
Instruction::Bne { rs1, rs2, imm } => {
let v1 = self.reg(rs1);
let v2 = self.reg(rs2);
if v1 != v2 {
self.program_counter += imm.val();
} else {
self.program_counter += 4;
}
StepResult::Ok
}
Instruction::Blt { rs1, rs2, imm } => {
let v1 = self.reg(rs1);
let v2 = self.reg(rs2);
if v1.less_than_signed(v2) {
self.program_counter += imm.val();
} else {
self.program_counter += 4;
}
StepResult::Ok
}
Instruction::Bge { rs1, rs2, imm } => {
let v1 = self.reg(rs1);
let v2 = self.reg(rs2);
if v1.greater_than_equal_to_signed(v2) {
self.program_counter += imm.val();
} else {
self.program_counter += 4;
}
StepResult::Ok
}
Instruction::Bltu { rs1, rs2, imm } => {
let v1 = self.reg(rs1);
let v2 = self.reg(rs2);
if v1.less_than_unsigned(v2) {
self.program_counter += imm.val();
} else {
self.program_counter += 4;
}
StepResult::Ok
}
Instruction::Bgeu { rs1, rs2, imm } => {
let v1 = self.reg(rs1);
let v2 = self.reg(rs2);
if v1.greater_than_equal_to_unsigned(v2) {
self.program_counter += imm.val();
} else {
self.program_counter += 4;
}
StepResult::Ok
}
Instruction::Jalr { rd, rs1, imm } => {
let target_addr = (self.reg(rs1).to_addr() + imm.val()).align_to_halfword();
self.set_reg(rd, RegVal::from_addr(self.program_counter + 4));
self.program_counter = target_addr;
StepResult::Ok
}
Instruction::Jal { rd, imm } => {
let target_addr = (self.program_counter + imm.val()).align_to_halfword();
self.set_reg(rd, RegVal::from_addr(self.program_counter + 4));
self.program_counter = target_addr;
StepResult::Ok
}
Instruction::Lui { rd, imm } => {
self.set_reg(rd, imm.val());
self.program_counter += 4;
StepResult::Ok
}
Instruction::Auipc { rd, imm } => {
self.set_reg(rd, RegVal::from_addr(self.program_counter) + imm.val());
self.program_counter += 4;
StepResult::Ok
}
Instruction::Addi { rd, rs1, imm } => {
self.set_reg(rd, self.reg(rs1) + imm.val());
self.program_counter += 4;
StepResult::Ok
}
Instruction::Slti { rd, rs1, imm } => {
if self.reg(rs1).less_than_signed(imm.val()) {
self.set_reg(rd, RegVal::from_u32(1));
} else {
self.set_reg(rd, RegVal::from_u32(0));
}
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sltiu { rd, rs1, imm } => {
if self.reg(rs1).less_than_unsigned(imm.val()) {
self.set_reg(rd, RegVal::from_u32(1));
} else {
self.set_reg(rd, RegVal::from_u32(0));
}
self.program_counter += 4;
StepResult::Ok
}
Instruction::Xori { rd, rs1, imm } => {
self.set_reg(rd, self.reg(rs1) ^ imm.val());
self.program_counter += 4;
StepResult::Ok
}
Instruction::Ori { rd, rs1, imm } => {
self.set_reg(rd, self.reg(rs1) | imm.val());
self.program_counter += 4;
StepResult::Ok
}
Instruction::Andi { rd, rs1, imm } => {
self.set_reg(rd, self.reg(rs1) & imm.val());
self.program_counter += 4;
StepResult::Ok
}
Instruction::Slli { rd, rs1, shamt } => {
self.set_reg(rd, self.reg(rs1).shift_left_logical(shamt.val()));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Srli { rd, rs1, shamt } => {
self.set_reg(rd, self.reg(rs1).shift_right_logical(shamt.val()));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Srai { rd, rs1, shamt } => {
self.set_reg(rd, self.reg(rs1).shift_right_arithmetic(shamt.val()));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Add { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1) + self.reg(rs2));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sub { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1) - self.reg(rs2));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sll { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1).shift_left_logical(self.reg(rs2)));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Slt { rd, rs1, rs2 } => {
if self.reg(rs1).less_than_signed(self.reg(rs2)) {
self.set_reg(rd, RegVal::from_u32(1));
} else {
self.set_reg(rd, RegVal::from_u32(0));
}
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sltu { rd, rs1, rs2 } => {
if self.reg(rs1).less_than_unsigned(self.reg(rs2)) {
self.set_reg(rd, RegVal::from_u32(1));
} else {
self.set_reg(rd, RegVal::from_u32(0));
}
self.program_counter += 4;
StepResult::Ok
}
Instruction::Xor { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1) ^ self.reg(rs2));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Srl { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1).shift_right_logical(self.reg(rs2)));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sra { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1).shift_right_arithmetic(self.reg(rs2)));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Or { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1) | self.reg(rs2));
self.program_counter += 4;
StepResult::Ok
}
Instruction::And { rd, rs1, rs2 } => {
self.set_reg(rd, self.reg(rs1) & self.reg(rs2));
self.program_counter += 4;
StepResult::Ok
}
Instruction::Lb { rd, rs1, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = RegVal::from_i32(memory.load_byte(addr) as i32);
self.set_reg(rd, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Lh { rd, rs1, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = RegVal::from_i32(memory.load_halfword(addr) as i32);
self.set_reg(rd, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Lw { rd, rs1, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = RegVal::from_i32(memory.load_word(addr) as i32);
self.set_reg(rd, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Lbu { rd, rs1, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = RegVal::from_u32(memory.load_byte(addr) as u32);
self.set_reg(rd, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Lhu { rd, rs1, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = RegVal::from_u32(memory.load_halfword(addr) as u32);
self.set_reg(rd, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Lwu { rd, rs1, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = RegVal::from_u32(memory.load_word(addr) as u32);
self.set_reg(rd, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sb { rs1, rs2, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = self.reg(rs2).to_u32() as u8;
memory.store_byte(addr, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sh { rs1, rs2, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = self.reg(rs2).to_u32() as u16;
memory.store_halfword(addr, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Sw { rs1, rs2, imm } => {
let addr = self.reg(rs1).to_addr() + imm.val();
let val = self.reg(rs2).to_u32() as u32;
memory.store_word(addr, val);
self.program_counter += 4;
StepResult::Ok
}
Instruction::Fence { rd } => {
let _ = rd;
unimplemented!()
}
Instruction::FenceI { rd } => {
let _ = rd;
unimplemented!()
}
Instruction::ECall => StepResult::Call,
Instruction::EBreak => StepResult::Break,
}
}
pub fn set_reg<R: Into<Reg>>(&mut self, reg: R, reg_val: RegVal) {
let Reg(reg_number) = reg.into();
if reg_number != 0 {
self.registers[reg_number as usize] = reg_val;
}
}
pub fn reg<R: Into<Reg>>(&self, reg: R) -> RegVal {
let Reg(reg_number) = reg.into();
self.registers[reg_number as usize]
}
pub fn set_pc(&mut self, addr: Addr) {
self.program_counter = addr;
}
pub fn pc(&self) -> Addr {
self.program_counter
}
}
impl fmt::Display for RiscV {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for row in 0..8 {
for col in 0..4 {
let reg = Reg(8 * col + row);
let reg_val = self.reg(reg).to_u32();
write!(f, "{:<3} = {:8x} ", reg.to_string(), reg_val)?;
}
write!(f, "\n")?;
}
Ok(())
}
}