Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/instruction_formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub const OPCODE_BRANCH: u32 = 0x63;
pub const OPCODE_JALR: u32 = 0x67;
pub const OPCODE_JAL: u32 = 0x6f;
pub const OPCODE_SYSTEM: u32 = 0x73;
pub const OPCODE_OP_IMM_32: u32 = 0x1b;
pub const OPCODE_OP_32: u32 = 0x3b;

#[derive(Debug, PartialEq)]
pub struct RType {
Expand Down
32 changes: 32 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
pub mod instruction_formats;
pub mod process_instruction;

use crate::instruction_formats::{IType, ITypeShamt, RType};
use downcast_rs::{impl_downcast, Downcast};

pub use process_instruction::process_instruction;
Expand All @@ -33,6 +34,12 @@ pub trait InstructionProcessor {
fn process_sra(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_or(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_and(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
// RV64I
fn process_addw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_subw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_sllw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_srlw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_sraw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;

fn process_addi(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_slli(
Expand All @@ -52,6 +59,20 @@ pub trait InstructionProcessor {
) -> Self::InstructionResult;
fn process_ori(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_andi(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
// RV64I
fn process_addiw(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_slliw(
&mut self,
dec_insn: instruction_formats::ITypeShamt,
) -> Self::InstructionResult;
fn process_srliw(
&mut self,
dec_insn: instruction_formats::ITypeShamt,
) -> Self::InstructionResult;
fn process_sraiw(
&mut self,
dec_insn: instruction_formats::ITypeShamt,
) -> Self::InstructionResult;

fn process_lui(&mut self, dec_insn: instruction_formats::UType) -> Self::InstructionResult;
fn process_auipc(&mut self, dec_insn: instruction_formats::UType) -> Self::InstructionResult;
Expand All @@ -68,6 +89,10 @@ pub trait InstructionProcessor {
fn process_lh(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_lhu(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_lw(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
// RV64I
fn process_lwu(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_ld(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
fn process_sd(&mut self, dec_insn: instruction_formats::SType) -> Self::InstructionResult;

fn process_sb(&mut self, dec_insn: instruction_formats::SType) -> Self::InstructionResult;
fn process_sh(&mut self, dec_insn: instruction_formats::SType) -> Self::InstructionResult;
Expand All @@ -80,11 +105,18 @@ pub trait InstructionProcessor {
fn process_mulh(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_mulhu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_mulhsu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
// RV64M
fn process_mulw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;

fn process_div(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_divu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_rem(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_remu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
// RV64M
fn process_divw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_divuw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_remw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
fn process_remuw(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;

fn process_fence(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;

Expand Down
63 changes: 63 additions & 0 deletions src/process_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ fn process_opcode_op_imm<T: InstructionProcessor>(
match dec_insn_shamt.funct7 {
0b000_0000 => Some(processor.process_srli(dec_insn_shamt)),
0b010_0000 => Some(processor.process_srai(dec_insn_shamt)),
// RV64I
0b000_0001 => Some(processor.process_srli(dec_insn_shamt)),
0b010_0001 => Some(processor.process_srai(dec_insn_shamt)),
_ => None,
}
}
Expand Down Expand Up @@ -113,6 +116,9 @@ fn process_opcode_load<T: InstructionProcessor>(
0b010 => Some(processor.process_lw(dec_insn)),
0b100 => Some(processor.process_lbu(dec_insn)),
0b101 => Some(processor.process_lhu(dec_insn)),
// RV64I
0b110 => Some(processor.process_lwu(dec_insn)),
0b011 => Some(processor.process_ld(dec_insn)),
_ => None,
}
}
Expand All @@ -127,6 +133,8 @@ fn process_opcode_store<T: InstructionProcessor>(
0b000 => Some(processor.process_sb(dec_insn)),
0b001 => Some(processor.process_sh(dec_insn)),
0b010 => Some(processor.process_sw(dec_insn)),
// RV64I
0b011 => Some(processor.process_sd(dec_insn)),
_ => None,
}
}
Expand Down Expand Up @@ -161,6 +169,59 @@ fn process_opcode_system<T: InstructionProcessor>(
}
}

fn process_opcode_op_imm_32<T: InstructionProcessor>(
processor: &mut T,
insn_bits: u32,
) -> Option<T::InstructionResult> {
let dec_insn = instruction_formats::IType::new(insn_bits);

match dec_insn.funct3 {
// RV64I
0b000 => Some(processor.process_addiw(dec_insn)),
0b001 => Some(processor.process_slliw(instruction_formats::ITypeShamt::new(insn_bits))),
0b101 => {
let dec_insn_shamt = instruction_formats::ITypeShamt::new(insn_bits);
match dec_insn_shamt.funct7 {
0b000_0000 => Some(processor.process_srliw(dec_insn_shamt)),
0b010_0000 => Some(processor.process_sraiw(dec_insn_shamt)),
_ => None,
}
}
_ => None,
}
}

fn process_opcode_op_32<T: InstructionProcessor>(
processor: &mut T,
insn_bits: u32,
) -> Option<T::InstructionResult> {
let dec_insn = instruction_formats::RType::new(insn_bits);

match dec_insn.funct3 {
// RV64I
0b000 => match dec_insn.funct7 {
0b000_0000 => Some(processor.process_addw(dec_insn)),
0b010_0000 => Some(processor.process_subw(dec_insn)),
// RV64M
0b000_0001 => Some(processor.process_mulw(dec_insn)),
_ => None,
},
0b001 => Some(processor.process_sllw(dec_insn)),
0b100 => Some(processor.process_divw(dec_insn)),
0b101 => match dec_insn.funct7 {
0b000_0000 => Some(processor.process_srlw(dec_insn)),
0b010_0000 => Some(processor.process_sraw(dec_insn)),
// RV64M
0b000_0001 => Some(processor.process_divuw(dec_insn)),
_ => None,
},
// RV64M
0b110 => Some(processor.process_remw(dec_insn)),
0b111 => Some(processor.process_remuw(dec_insn)),
_ => None,
}
}

/// Decodes instruction in `insn_bits` calling the appropriate function in `processor` returning
/// the result it produces.
///
Expand Down Expand Up @@ -197,6 +258,8 @@ pub fn process_instruction<T: InstructionProcessor>(
}
}
instruction_formats::OPCODE_SYSTEM => process_opcode_system(processor, insn_bits),
instruction_formats::OPCODE_OP_IMM_32 => process_opcode_op_imm_32(processor, insn_bits),
instruction_formats::OPCODE_OP_32 => process_opcode_op_32(processor, insn_bits),
_ => None,
}
}