Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Instruction structure #14

Merged
merged 11 commits into from
Aug 9, 2024
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