Skip to content

Commit

Permalink
Merge pull request #14 from Alignof/feature/new_inst_structure
Browse files Browse the repository at this point in the history
Update `Instruction` structure
  • Loading branch information
Alignof authored Aug 9, 2024
2 parents c461ce0 + 58846d6 commit b16f27f
Show file tree
Hide file tree
Showing 17 changed files with 1,385 additions and 1,255 deletions.
9 changes: 4 additions & 5 deletions src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
mod inst_16;
mod inst_32;

use crate::instruction::{Extensions, Instruction, OpcodeKind};
use crate::instruction::{Extensions, Instruction, Opcode, OpcodeKind};
use crate::Isa;

/// Return Err if given opcode is only available on Rv64.
fn only_rv64(opcode: OpcodeKind, isa: Isa) -> Result<OpcodeKind, DecodingError> {
fn only_rv64<T: Opcode>(opcode: T, isa: Isa) -> Result<T, DecodingError> {
match isa {
Isa::Rv32 => Err(DecodingError::OnlyRv64Inst),
Isa::Rv64 => Ok(opcode),
Expand Down Expand Up @@ -73,6 +73,8 @@ pub enum DecodingError {
pub trait Decode {
/// Decode an instruction from u16/u32.
fn decode(&self, isa: Isa) -> Result<Instruction, DecodingError>;
/// Parse extension from a u16/u32 value.
fn parse_extension(self) -> Result<Extensions, DecodingError>;
/// Parse opcode.
fn parse_opcode(self, isa: Isa) -> Result<OpcodeKind, DecodingError>;
/// Parse destination register.
Expand Down Expand Up @@ -111,9 +113,6 @@ trait DecodeUtil {
/// * `mask` - It contain the bit order.
fn set(self, mask: &[u32]) -> u32;

/// Get `Extensions` from a u16/u32 value.
fn extension(self) -> Result<Extensions, DecodingError>;

/// Convert i32 to a sign-extended any size number.
/// # Arguments
/// * `imm32` - The value to be converted.
Expand Down
135 changes: 106 additions & 29 deletions src/decode/inst_16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ impl Decode for u16 {
let new_rs1: Option<usize> = self.parse_rs1(&new_opc)?;
let new_rs2: Option<usize> = self.parse_rs2(&new_opc)?;
let new_imm: Option<i32> = self.parse_imm(&new_opc, isa)?;
let new_ext: Extensions = new_opc.get_extension();
let new_fmt: InstFormat = new_opc.get_format();

Ok(Instruction {
Expand All @@ -25,42 +24,47 @@ impl Decode for u16 {
rs1: new_rs1,
rs2: new_rs2,
imm: new_imm,
extension: new_ext,
inst_format: new_fmt,
})
}

fn parse_extension(self) -> Result<Extensions, DecodingError> {
Ok(Extensions::C)
}

fn parse_opcode(self, isa: Isa) -> Result<OpcodeKind, DecodingError> {
match self.extension() {
Ok(Extensions::C) => c_extension::parse_opcode(self, isa),
let extension = self.parse_extension();

match extension {
Ok(Extensions::C) => Ok(OpcodeKind::C(c_extension::parse_opcode(self, isa)?)),
_ => Err(DecodingError::Not16BitInst),
}
}

fn parse_rd(self, opkind: &OpcodeKind) -> Result<Option<usize>, DecodingError> {
match self.extension() {
Ok(Extensions::C) => c_extension::parse_rd(self, opkind),
match opkind {
OpcodeKind::C(opc) => c_extension::parse_rd(self, opc),
_ => Err(DecodingError::Not16BitInst),
}
}

fn parse_rs1(self, opkind: &OpcodeKind) -> Result<Option<usize>, DecodingError> {
match self.extension() {
Ok(Extensions::C) => c_extension::parse_rs1(self, opkind),
match opkind {
OpcodeKind::C(opc) => c_extension::parse_rs1(self, opc),
_ => Err(DecodingError::Not16BitInst),
}
}

fn parse_rs2(self, opkind: &OpcodeKind) -> Result<Option<usize>, DecodingError> {
match self.extension() {
Ok(Extensions::C) => c_extension::parse_rs2(self, opkind),
match opkind {
OpcodeKind::C(opc) => c_extension::parse_rs2(self, opc),
_ => Err(DecodingError::Not16BitInst),
}
}

fn parse_imm(self, opkind: &OpcodeKind, _isa: Isa) -> Result<Option<i32>, DecodingError> {
match self.extension() {
Ok(Extensions::C) => c_extension::parse_imm(self, opkind),
match opkind {
OpcodeKind::C(opc) => c_extension::parse_imm(self, opc),
_ => Err(DecodingError::Not16BitInst),
}
}
Expand All @@ -79,10 +83,6 @@ impl DecodeUtil for u16 {

inst
}

fn extension(self) -> Result<Extensions, DecodingError> {
Ok(Extensions::C)
}
}

#[cfg(test)]
Expand All @@ -91,7 +91,7 @@ mod decode_16 {
#[test]
fn decoding_16bit_test() {
use super::*;
use OpcodeKind::*;
use crate::instruction::c_extension::COpcode;
let test_16 = |inst_16: u16,
op: OpcodeKind,
rd: Option<usize>,
Expand All @@ -106,24 +106,101 @@ mod decode_16 {
assert_eq!(inst_16.parse_imm(&op_16, Isa::Rv64).unwrap(), imm);
};

test_16(0b0000_0000_0000_0001, C_NOP, None, None, None, Some(0));
test_16(0b0110_0011_1000_0001, C_LUI, Some(7), None, None, Some(0));
test_16(
0b0000_0000_0000_0001,
OpcodeKind::C(COpcode::NOP),
None,
None,
None,
Some(0),
);
test_16(
0b0110_0011_1000_0001,
OpcodeKind::C(COpcode::LUI),
Some(7),
None,
None,
Some(0),
);
test_16(
0b1000_0010_1100_0001,
C_SRAI,
OpcodeKind::C(COpcode::SRAI),
Some(13),
Some(13),
None,
Some(16),
);
test_16(0x4521, C_LI, Some(10), None, None, Some(8));
test_16(0xb5e5, C_J, None, None, None, Some(-280));
test_16(0x6105, C_ADDI, Some(2), Some(2), None, Some(32));
test_16(0x8082, C_JR, None, Some(1), Some(0), None);
test_16(0xe29d, C_BNEZ, None, Some(13), None, Some(38));
test_16(0xc05c, C_SW, None, Some(8), Some(15), Some(4));
test_16(0x9002, C_EBREAK, None, None, None, None);
test_16(0x880a, C_MV, Some(16), None, Some(2), None);
test_16(0x8585, C_SRAI, Some(11), Some(11), None, Some(1));
test_16(
0x4521,
OpcodeKind::C(COpcode::LI),
Some(10),
None,
None,
Some(8),
);
test_16(
0xb5e5,
OpcodeKind::C(COpcode::J),
None,
None,
None,
Some(-280),
);
test_16(
0x6105,
OpcodeKind::C(COpcode::ADDI),
Some(2),
Some(2),
None,
Some(32),
);
test_16(
0x8082,
OpcodeKind::C(COpcode::JR),
None,
Some(1),
Some(0),
None,
);
test_16(
0xe29d,
OpcodeKind::C(COpcode::BNEZ),
None,
Some(13),
None,
Some(38),
);
test_16(
0xc05c,
OpcodeKind::C(COpcode::SW),
None,
Some(8),
Some(15),
Some(4),
);
test_16(
0x9002,
OpcodeKind::C(COpcode::EBREAK),
None,
None,
None,
None,
);
test_16(
0x880a,
OpcodeKind::C(COpcode::MV),
Some(16),
None,
Some(2),
None,
);
test_16(
0x8585,
OpcodeKind::C(COpcode::SRAI),
Some(11),
Some(11),
None,
Some(1),
);
}
}
Loading

0 comments on commit b16f27f

Please sign in to comment.