diff --git a/Cargo.toml b/Cargo.toml index e5d1a77..a0c2a27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raki" -version = "1.0.1" +version = "1.1.0" edition = "2021" authors = ["Norimasa Takana "] repository = "https://github.com/Alignof/raki" diff --git a/README.md b/README.md index b4c5ac7..b3c3f0b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ fn main() { - [x] M - [x] A - [ ] D -- [ ] G - [ ] Q - [x] C - [ ] B @@ -39,6 +38,8 @@ fn main() { - [ ] H - [x] Zicsr - [x] Zifencei +- [x] Zicntr +- [x] Zicfiss - [ ] Priv (Now only supports `mret`, `sret`, `wfi`, `sfence.vma`) ## License diff --git a/src/decode/inst_16.rs b/src/decode/inst_16.rs index 6cb0113..735da43 100644 --- a/src/decode/inst_16.rs +++ b/src/decode/inst_16.rs @@ -1,5 +1,6 @@ #[allow(non_snake_case)] mod c_extension; +mod zicfiss_extension; use super::{Decode, DecodeUtil, DecodingError}; use crate::instruction::{InstFormat, Instruction, OpcodeKind}; @@ -33,6 +34,9 @@ impl Decode for u16 { match extension { Ok(Extensions::C) => Ok(OpcodeKind::C(c_extension::parse_opcode(self, isa)?)), + Ok(Extensions::Zicfiss) => Ok(OpcodeKind::Zicfiss(zicfiss_extension::parse_opcode( + self, isa, + )?)), _ => Err(DecodingError::Not16BitInst), } } @@ -40,6 +44,7 @@ impl Decode for u16 { fn parse_rd(self, opkind: &OpcodeKind) -> Result, DecodingError> { match opkind { OpcodeKind::C(opc) => Ok(c_extension::parse_rd(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_rd(self, opc)), _ => Err(DecodingError::Not16BitInst), } } @@ -47,6 +52,7 @@ impl Decode for u16 { fn parse_rs1(self, opkind: &OpcodeKind) -> Result, DecodingError> { match opkind { OpcodeKind::C(opc) => Ok(c_extension::parse_rs1(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_rs1(self, opc)), _ => Err(DecodingError::Not16BitInst), } } @@ -54,6 +60,7 @@ impl Decode for u16 { fn parse_rs2(self, opkind: &OpcodeKind) -> Result, DecodingError> { match opkind { OpcodeKind::C(opc) => Ok(c_extension::parse_rs2(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_rs2(self, opc)), _ => Err(DecodingError::Not16BitInst), } } @@ -61,6 +68,7 @@ impl Decode for u16 { fn parse_imm(self, opkind: &OpcodeKind, _isa: Isa) -> Result, DecodingError> { match opkind { OpcodeKind::C(opc) => Ok(c_extension::parse_imm(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_imm(self, opc)), _ => Err(DecodingError::Not16BitInst), } } @@ -73,7 +81,10 @@ impl DecodeUtil for u16 { } fn parse_extension(self) -> Result { - Ok(Extensions::C) + match self { + 0b0110_0000_1000_0001 | 0b0110_0010_1000_0001 => Ok(Extensions::Zicfiss), + _ => Ok(Extensions::C), + } } fn set(self, mask: &[u32]) -> u32 { diff --git a/src/decode/inst_16/zicfiss_extension.rs b/src/decode/inst_16/zicfiss_extension.rs new file mode 100644 index 0000000..7432d09 --- /dev/null +++ b/src/decode/inst_16/zicfiss_extension.rs @@ -0,0 +1,77 @@ +use super::super::DecodingError; +use crate::instruction::zicfiss_extension::ZicfissOpcode; +use crate::Isa; + +pub fn parse_opcode(inst: u16, _isa: Isa) -> Result { + match inst { + 0b0110_0000_1000_0001 => Ok(ZicfissOpcode::C_SSPUSH), + 0b0110_0010_1000_0001 => Ok(ZicfissOpcode::C_SSPOPCHK), + _ => Err(DecodingError::InvalidOpcode), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rd(_inst: u16, opkind: &ZicfissOpcode) -> Option { + match opkind { + ZicfissOpcode::C_SSPUSH => Some(1), + ZicfissOpcode::C_SSPOPCHK => Some(5), + _ => unreachable!(), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rs1(_inst: u16, _opkind: &ZicfissOpcode) -> Option { + None +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rs2(_inst: u16, _opkind: &ZicfissOpcode) -> Option { + None +} + +#[allow(clippy::cast_possible_wrap, clippy::unnecessary_wraps)] +pub fn parse_imm(_inst: u16, _opkind: &ZicfissOpcode) -> Option { + None +} + +#[cfg(test)] +#[allow(unused_variables)] +mod test_zicfiss { + #[test] + #[allow(overflowing_literals)] + fn zicfiss_16() { + use super::*; + use crate::{Decode, Isa, OpcodeKind}; + let test_16 = |inst_16: u16, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option| { + let op_16 = inst_16.parse_opcode(Isa::Rv64).unwrap(); + assert!(matches!(&op_16, op)); + assert_eq!(inst_16.parse_rd(&op_16).unwrap(), rd); + assert_eq!(inst_16.parse_rs1(&op_16).unwrap(), rs1); + assert_eq!(inst_16.parse_rs2(&op_16).unwrap(), rs2); + assert_eq!(inst_16.parse_imm(&op_16, Isa::Rv64).unwrap(), imm); + }; + + test_16( + 0x6081, + OpcodeKind::Zicfiss(ZicfissOpcode::C_SSPUSH), + Some(1), + None, + None, + None, + ); + + test_16( + 0x6281, + OpcodeKind::Zicfiss(ZicfissOpcode::C_SSPOPCHK), + Some(5), + None, + None, + None, + ); + } +} diff --git a/src/decode/inst_32.rs b/src/decode/inst_32.rs index f250c81..5a4567f 100644 --- a/src/decode/inst_32.rs +++ b/src/decode/inst_32.rs @@ -2,6 +2,7 @@ mod a_extension; mod base_i; mod m_extension; mod priv_extension; +mod zicfiss_extension; mod zicntr_extension; mod zicsr_extension; mod zifencei_extension; @@ -41,6 +42,9 @@ impl Decode for u32 { self, )?)), Ok(Extensions::Zicsr) => Ok(OpcodeKind::Zicsr(zicsr_extension::parse_opcode(self)?)), + Ok(Extensions::Zicfiss) => { + Ok(OpcodeKind::Zicfiss(zicfiss_extension::parse_opcode(self)?)) + } Ok(Extensions::Zicntr) => Ok(OpcodeKind::Zicntr(zicntr_extension::parse_opcode(self)?)), Ok(Extensions::Priv) => Ok(OpcodeKind::Priv(priv_extension::parse_opcode(self)?)), Ok(Extensions::C) => Err(DecodingError::Not32BitInst), @@ -55,6 +59,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_rd(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_rd(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_rd(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_rd(self, opc)), OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_rd(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_rd(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), @@ -68,6 +73,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_rs1(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_rs1(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_rs1(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_rs1(self, opc)), OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_rs1(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_rs1(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), @@ -81,6 +87,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_rs2(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_rs2(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_rs2(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_rs2(self, opc)), OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_rs2(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_rs2(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), @@ -94,6 +101,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_imm(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_imm(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_imm(self, opc)), + OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::parse_imm(self, opc)), OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_imm(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_imm(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), @@ -110,12 +118,18 @@ impl DecodeUtil for u32 { fn parse_extension(self) -> Result { let opmap: u8 = u8::try_from(self.slice(6, 0)).unwrap(); let funct3: u8 = u8::try_from(self.slice(14, 12)).unwrap(); + let funct5: u8 = u8::try_from(self.slice(31, 27)).unwrap(); let funct7: u8 = u8::try_from(self.slice(31, 25)).unwrap(); let csr: u16 = u16::try_from(self.slice(31, 20)).unwrap(); match opmap { 0b000_1111 => Ok(Extensions::Zifencei), - 0b010_1111 => Ok(Extensions::A), + 0b010_1111 => match funct5 { + 0b00000 | 0b00001 | 0b00010 | 0b00011 | 0b00100 | 0b01000 | 0b01100 | 0b10000 + | 0b10100 | 0b11000 | 0b11100 => Ok(Extensions::A), + 0b01001 => Ok(Extensions::Zicfiss), + _ => Err(DecodingError::UnknownExtension), + }, 0b011_0011 => match funct7 { 0b000_0001 => Ok(Extensions::M), _ => Ok(Extensions::BaseI), @@ -135,6 +149,7 @@ impl DecodeUtil for u32 { 0xc00..=0xc02 | 0xc80..=0xc82 => Ok(Extensions::Zicntr), _ => Ok(Extensions::Zicsr), }, + 0b100 => Ok(Extensions::Zicfiss), _ => Ok(Extensions::Zicsr), }, _ => Ok(Extensions::BaseI), diff --git a/src/decode/inst_32/zicfiss_extension.rs b/src/decode/inst_32/zicfiss_extension.rs new file mode 100644 index 0000000..6d118ea --- /dev/null +++ b/src/decode/inst_32/zicfiss_extension.rs @@ -0,0 +1,164 @@ +use super::super::{DecodeUtil, DecodingError}; +use crate::instruction::zicfiss_extension::ZicfissOpcode; + +pub fn parse_opcode(inst: u32) -> Result { + let opmap: u8 = u8::try_from(inst.slice(6, 0)).unwrap(); + let funct3: u8 = u8::try_from(inst.slice(14, 12)).unwrap(); + let rs1: u8 = u8::try_from(inst.slice(19, 15)).unwrap(); + let funct7_rs2: u16 = u16::try_from(inst.slice(31, 20)).unwrap(); + + match opmap { + 0b111_0011 => match funct3 { + 0b100 => match funct7_rs2 { + 0b1100_1110_0001 | 0b1100_1110_0101 => Ok(ZicfissOpcode::SSPUSH), + 0b1100_1101_1100 => match rs1 { + 0b0_0000 => Ok(ZicfissOpcode::SSRDP), + _ => Ok(ZicfissOpcode::SSPOPCHK), + }, + _ => Err(DecodingError::InvalidOpcode), + }, + _ => Err(DecodingError::InvalidFunct3), + }, + 0b010_1111 => match funct3 { + 0b010 => Ok(ZicfissOpcode::SSAMOSWAP_W), + 0b011 => Ok(ZicfissOpcode::SSAMOSWAP_D), + _ => Err(DecodingError::InvalidFunct3), + }, + _ => Err(DecodingError::InvalidOpcode), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rd(inst: u32, opkind: &ZicfissOpcode) -> Option { + let rd: usize = inst.slice(11, 7) as usize; + match opkind { + ZicfissOpcode::SSPUSH | ZicfissOpcode::SSPOPCHK => Some(0), + ZicfissOpcode::SSRDP | ZicfissOpcode::SSAMOSWAP_W | ZicfissOpcode::SSAMOSWAP_D => Some(rd), + ZicfissOpcode::C_SSPUSH | ZicfissOpcode::C_SSPOPCHK => unreachable!(), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rs1(inst: u32, opkind: &ZicfissOpcode) -> Option { + let rs1: usize = inst.slice(19, 15) as usize; + match opkind { + ZicfissOpcode::SSPUSH => Some(0), + ZicfissOpcode::SSPOPCHK | ZicfissOpcode::SSAMOSWAP_W | ZicfissOpcode::SSAMOSWAP_D => { + Some(rs1) + } + ZicfissOpcode::SSRDP => None, + ZicfissOpcode::C_SSPUSH | ZicfissOpcode::C_SSPOPCHK => unreachable!(), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rs2(inst: u32, opkind: &ZicfissOpcode) -> Option { + let rs2: usize = inst.slice(24, 20) as usize; + match opkind { + ZicfissOpcode::SSPUSH | ZicfissOpcode::SSAMOSWAP_W | ZicfissOpcode::SSAMOSWAP_D => { + Some(rs2) + } + ZicfissOpcode::SSPOPCHK | ZicfissOpcode::SSRDP => None, + ZicfissOpcode::C_SSPUSH | ZicfissOpcode::C_SSPOPCHK => unreachable!(), + } +} + +#[allow(clippy::cast_possible_wrap, clippy::unnecessary_wraps)] +pub fn parse_imm(_inst: u32, opkind: &ZicfissOpcode) -> Option { + match opkind { + ZicfissOpcode::SSPUSH + | ZicfissOpcode::SSPOPCHK + | ZicfissOpcode::SSRDP + | ZicfissOpcode::SSAMOSWAP_W + | ZicfissOpcode::SSAMOSWAP_D => None, + ZicfissOpcode::C_SSPUSH | ZicfissOpcode::C_SSPOPCHK => unreachable!(), + } +} + +#[cfg(test)] +#[allow(unused_variables)] +mod test_zicfiss { + #[test] + #[allow(overflowing_literals)] + fn zicfiss_32bit_decode_test() { + use super::*; + use crate::{Decode, Isa, OpcodeKind}; + + let test_32 = |inst_32: u32, + expected_op: OpcodeKind, + expected_rd: Option, + expected_rs1: Option, + expected_rs2: Option, + expected_imm: Option| { + let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); + assert_eq!(op_32, expected_op); + assert_eq!(inst_32.parse_rd(&op_32).unwrap(), expected_rd); + assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), expected_rs1); + assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), expected_rs2); + assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), expected_imm); + }; + + test_32( + 0b1100_1110_0101_0000_0100_0000_0111_0011, + OpcodeKind::Zicfiss(ZicfissOpcode::SSPUSH), + Some(0), + Some(0), + Some(5), + None, + ); + + test_32( + 0b1100_1110_0001_0000_0100_0000_0111_0011, + OpcodeKind::Zicfiss(ZicfissOpcode::SSPUSH), + Some(0), + Some(0), + Some(1), + None, + ); + + test_32( + 0b1100_1101_1100_0000_1100_0000_0111_0011, + OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK), + Some(0), + Some(1), + None, + None, + ); + + test_32( + 0b1100_1101_1100_0010_1100_0000_0111_0011, + OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK), + Some(0), + Some(5), + None, + None, + ); + + test_32( + 0b0100_1000_1100_0010_1010_0001_1010_1111, + OpcodeKind::Zicfiss(ZicfissOpcode::SSAMOSWAP_W), + Some(3), + Some(5), + Some(12), + None, + ); + + test_32( + 0b0100_1000_1100_0111_0011_0001_1010_1111, + OpcodeKind::Zicfiss(ZicfissOpcode::SSAMOSWAP_D), + Some(3), + Some(14), + Some(12), + None, + ); + + test_32( + 0xcdc0c073, + OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK), + Some(0), + Some(1), + None, + None, + ); + } +} diff --git a/src/instruction.rs b/src/instruction.rs index 90781f5..d55d2da 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -5,6 +5,7 @@ pub mod base_i; pub mod c_extension; pub mod m_extension; pub mod priv_extension; +pub mod zicfiss_extension; pub mod zicntr_extension; pub mod zicsr_extension; pub mod zifencei_extension; @@ -16,6 +17,7 @@ use base_i::BaseIOpcode; use c_extension::COpcode; use m_extension::MOpcode; use priv_extension::PrivOpcode; +use zicfiss_extension::ZicfissOpcode; use zicntr_extension::ZicntrOpcode; use zicsr_extension::ZicsrOpcode; use zifencei_extension::ZifenceiOpcode; @@ -196,10 +198,16 @@ impl Display for Instruction { self.imm.unwrap(), ) } - InstFormat::CsrCntrFormat => { + InstFormat::OnlyRd => { write!(f, "{} {}", self.opc, reg2str(self.rd.unwrap()),) } - InstFormat::Uncategorized => match self.opc { + InstFormat::OnlyRs1 => { + write!(f, "{} {}", self.opc, reg2str(self.rs1.unwrap()),) + } + InstFormat::OnlyRs2 => { + write!(f, "{} {}", self.opc, reg2str(self.rs2.unwrap()),) + } + InstFormat::NoOperand => match self.opc { OpcodeKind::BaseI(BaseIOpcode::ECALL | BaseIOpcode::EBREAK) | OpcodeKind::Zifencei(ZifenceiOpcode::FENCE) | OpcodeKind::C(COpcode::NOP | COpcode::EBREAK) @@ -369,12 +377,6 @@ pub enum InstFormat { /// ``` CsrUiFormat, - /// Zicntr extension format - /// ```ignore - /// rdtime rd - /// ``` - CsrCntrFormat, - /// M-extension instruction format /// ```ignore /// mul rd, rs1, rs2 @@ -393,14 +395,33 @@ pub enum InstFormat { /// ``` ALrFormat, - /// Uncategorized format + /// No operand /// ```ignore /// ecall /// wfi /// mret /// c.ebreak /// ``` - Uncategorized, + NoOperand, + + /// Only rd name + /// ```ignore + /// rdtime rd + /// ssrdp rd + /// ``` + OnlyRd, + + /// Only rs1 name + /// ```ignore + /// sspush ra + /// ``` + OnlyRs1, + + /// Only rs2 name + /// ```ignore + /// sspopchk t0 + /// ``` + OnlyRs2, } /// Trait for `OpcodeKind` @@ -425,6 +446,8 @@ pub enum OpcodeKind { Zifencei(ZifenceiOpcode), /// Control and Status Register Instructions Zicsr(ZicsrOpcode), + /// CFI Shadow Stack + Zicfiss(ZicfissOpcode), /// Base Counters and Timers Zicntr(ZicntrOpcode), /// Privileged Instructions @@ -440,6 +463,7 @@ impl Display for OpcodeKind { Self::C(opc) => write!(f, "{opc}"), Self::Zifencei(opc) => write!(f, "{opc}"), Self::Zicsr(opc) => write!(f, "{opc}"), + Self::Zicfiss(opc) => write!(f, "{opc}"), Self::Zicntr(opc) => write!(f, "{opc}"), Self::Priv(opc) => write!(f, "{opc}"), } @@ -456,6 +480,7 @@ impl OpcodeKind { Self::C(opc) => opc.get_format(), Self::Zifencei(opc) => opc.get_format(), Self::Zicsr(opc) => opc.get_format(), + Self::Zicfiss(opc) => opc.get_format(), Self::Zicntr(opc) => opc.get_format(), Self::Priv(opc) => opc.get_format(), } diff --git a/src/instruction/base_i.rs b/src/instruction/base_i.rs index fb9103b..6d34b28 100644 --- a/src/instruction/base_i.rs +++ b/src/instruction/base_i.rs @@ -170,7 +170,7 @@ impl Opcode for BaseIOpcode { } BaseIOpcode::JAL => InstFormat::JFormat, BaseIOpcode::LUI | BaseIOpcode::AUIPC => InstFormat::UFormat, - BaseIOpcode::ECALL | BaseIOpcode::EBREAK => InstFormat::Uncategorized, + BaseIOpcode::ECALL | BaseIOpcode::EBREAK => InstFormat::NoOperand, } } } diff --git a/src/instruction/c_extension.rs b/src/instruction/c_extension.rs index b1f8e6a..7e29697 100644 --- a/src/instruction/c_extension.rs +++ b/src/instruction/c_extension.rs @@ -103,7 +103,7 @@ impl Opcode for COpcode { COpcode::LI | COpcode::ADDI | COpcode::ADDIW | COpcode::ADDI16SP | COpcode::LUI => { InstFormat::CiFormat } - COpcode::NOP => InstFormat::Uncategorized, + COpcode::NOP => InstFormat::NoOperand, COpcode::SUB | COpcode::XOR | COpcode::OR @@ -115,7 +115,7 @@ impl Opcode for COpcode { COpcode::LDSP | COpcode::SLLI | COpcode::LWSP => InstFormat::CiFormat, COpcode::SDSP | COpcode::SWSP => InstFormat::CssFormat, COpcode::JR | COpcode::JALR | COpcode::MV | COpcode::ADD => InstFormat::CrFormat, - COpcode::EBREAK => InstFormat::Uncategorized, + COpcode::EBREAK => InstFormat::NoOperand, } } } diff --git a/src/instruction/opcode.rs b/src/instruction/opcode.rs index e3afaae..bc9c7db 100644 --- a/src/instruction/opcode.rs +++ b/src/instruction/opcode.rs @@ -53,14 +53,14 @@ impl OpcodeKind { } OpcodeKind::JAL => InstFormat::Jformat, OpcodeKind::LUI | OpcodeKind::AUIPC => InstFormat::Uformat, - OpcodeKind::ECALL | OpcodeKind::FENCE | OpcodeKind::EBREAK => InstFormat::Uncategorized, + OpcodeKind::ECALL | OpcodeKind::FENCE | OpcodeKind::EBREAK => InstFormat::NoOperand, // Zicsr OpcodeKind::CSRRW | OpcodeKind::CSRRS | OpcodeKind::CSRRC => InstFormat::CSRformat, OpcodeKind::CSRRWI | OpcodeKind::CSRRSI | OpcodeKind::CSRRCI => InstFormat::CSRuiformat, // Privileged - OpcodeKind::SRET | OpcodeKind::MRET | OpcodeKind::WFI => InstFormat::Uncategorized, + OpcodeKind::SRET | OpcodeKind::MRET | OpcodeKind::WFI => InstFormat::NoOperand, OpcodeKind::SFENCE_VMA => InstFormat::Rformat, // Multiplication and Division @@ -119,7 +119,7 @@ impl OpcodeKind { | OpcodeKind::C_ADDIW | OpcodeKind::C_ADDI16SP | OpcodeKind::C_LUI => InstFormat::CIformat, - OpcodeKind::C_NOP => InstFormat::Uncategorized, + OpcodeKind::C_NOP => InstFormat::NoOperand, OpcodeKind::C_SUB | OpcodeKind::C_XOR | OpcodeKind::C_OR @@ -132,7 +132,7 @@ impl OpcodeKind { OpcodeKind::C_JR | OpcodeKind::C_JALR | OpcodeKind::C_MV | OpcodeKind::C_ADD => { InstFormat::CRformat } - OpcodeKind::C_EBREAK => InstFormat::Uncategorized, + OpcodeKind::C_EBREAK => InstFormat::NoOperand, } } diff --git a/src/instruction/priv_extension.rs b/src/instruction/priv_extension.rs index e7025a7..dcb1cbc 100644 --- a/src/instruction/priv_extension.rs +++ b/src/instruction/priv_extension.rs @@ -27,7 +27,7 @@ impl Display for PrivOpcode { impl Opcode for PrivOpcode { fn get_format(&self) -> InstFormat { match self { - PrivOpcode::SRET | PrivOpcode::MRET | PrivOpcode::WFI => InstFormat::Uncategorized, + PrivOpcode::SRET | PrivOpcode::MRET | PrivOpcode::WFI => InstFormat::NoOperand, PrivOpcode::SFENCE_VMA => InstFormat::RFormat, } } diff --git a/src/instruction/zicfiss_extension.rs b/src/instruction/zicfiss_extension.rs new file mode 100644 index 0000000..b3ccb51 --- /dev/null +++ b/src/instruction/zicfiss_extension.rs @@ -0,0 +1,50 @@ +//! Zicfiss extension Instruction. + +use super::{InstFormat, Opcode}; +use core::fmt::{self, Display, Formatter}; + +/// Insturctions in Zicntr Extension. +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +#[derive(Debug, PartialEq)] +pub enum ZicfissOpcode { + /// Shadow stack push. + SSPUSH, + /// Shadow stack push (compressed). + C_SSPUSH, + /// Shadow stack pop and check. + SSPOPCHK, + /// Shadow stack pop and check (compressed). + C_SSPOPCHK, + /// Shadow stack read pointer. + SSRDP, + /// Shadow stack AMO swap (word). + SSAMOSWAP_W, + /// Shadow stack AMO swap (double word). + SSAMOSWAP_D, +} + +impl Display for ZicfissOpcode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + ZicfissOpcode::SSPUSH => write!(f, "sspush"), + ZicfissOpcode::C_SSPUSH => write!(f, "c.sspush"), + ZicfissOpcode::SSPOPCHK => write!(f, "sspopchk"), + ZicfissOpcode::C_SSPOPCHK => write!(f, "c.sspopchk"), + ZicfissOpcode::SSRDP => write!(f, "ssrdp"), + ZicfissOpcode::SSAMOSWAP_W => write!(f, "ssamoswap.w"), + ZicfissOpcode::SSAMOSWAP_D => write!(f, "ssamoswap.d"), + } + } +} + +impl Opcode for ZicfissOpcode { + fn get_format(&self) -> InstFormat { + match self { + ZicfissOpcode::SSPUSH => InstFormat::OnlyRs1, + ZicfissOpcode::SSPOPCHK => InstFormat::OnlyRs2, + ZicfissOpcode::SSRDP => InstFormat::OnlyRd, + ZicfissOpcode::SSAMOSWAP_W | ZicfissOpcode::SSAMOSWAP_D => InstFormat::AFormat, + ZicfissOpcode::C_SSPUSH | ZicfissOpcode::C_SSPOPCHK => InstFormat::NoOperand, + } + } +} diff --git a/src/instruction/zicntr_extension.rs b/src/instruction/zicntr_extension.rs index 96b51e3..3b38463 100644 --- a/src/instruction/zicntr_extension.rs +++ b/src/instruction/zicntr_extension.rs @@ -41,7 +41,7 @@ impl Opcode for ZicntrOpcode { | ZicntrOpcode::RDINSTRET_H | ZicntrOpcode::RDCYCLE | ZicntrOpcode::RDTIME - | ZicntrOpcode::RDINSTRET => InstFormat::CsrCntrFormat, + | ZicntrOpcode::RDINSTRET => InstFormat::OnlyRd, } } } diff --git a/src/instruction/zifencei_extension.rs b/src/instruction/zifencei_extension.rs index e3169b7..cba0e63 100644 --- a/src/instruction/zifencei_extension.rs +++ b/src/instruction/zifencei_extension.rs @@ -21,7 +21,7 @@ impl Display for ZifenceiOpcode { impl Opcode for ZifenceiOpcode { fn get_format(&self) -> InstFormat { match self { - ZifenceiOpcode::FENCE => InstFormat::Uncategorized, + ZifenceiOpcode::FENCE => InstFormat::NoOperand, } } } diff --git a/src/lib.rs b/src/lib.rs index dc84d4f..f85b559 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,8 @@ enum Extensions { Zifencei, /// Control and Status Register Instructions Zicsr, + /// Shadow Stack + Zicfiss, /// Base Counters and Timers Zicntr, /// Privileged Instructions