From 3b176bd214851f6fd66c2116d19846fc2a11b682 Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Mon, 16 Sep 2024 17:57:41 +0100 Subject: [PATCH] RISC-V: fix C.Nop parsing --- src/riscv/lib/src/interpreter/float.rs | 2 +- .../lib/src/machine_state/csregisters.rs | 1 + src/riscv/lib/src/machine_state/registers.rs | 4 +- src/riscv/lib/src/parser.rs | 29 ++++++++-- src/riscv/lib/src/parser/instruction.rs | 58 +++++++++---------- 5 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/riscv/lib/src/interpreter/float.rs b/src/riscv/lib/src/interpreter/float.rs index 85371f78558e..38339cdde50d 100644 --- a/src/riscv/lib/src/interpreter/float.rs +++ b/src/riscv/lib/src/interpreter/float.rs @@ -523,7 +523,7 @@ where /// There are 5 supported rounding modes #[allow(clippy::upper_case_acronyms)] -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum RoundingMode { /// Round to Nearest, ties to Even RNE, diff --git a/src/riscv/lib/src/machine_state/csregisters.rs b/src/riscv/lib/src/machine_state/csregisters.rs index 12a5ff8e9f59..020571c56272 100644 --- a/src/riscv/lib/src/machine_state/csregisters.rs +++ b/src/riscv/lib/src/machine_state/csregisters.rs @@ -55,6 +55,7 @@ pub enum Privilege { strum::EnumIter, TryFromPrimitive, strum::Display, + Hash, )] #[repr(usize)] pub enum CSRegister { diff --git a/src/riscv/lib/src/machine_state/registers.rs b/src/riscv/lib/src/machine_state/registers.rs index d3b17231acdb..fc9400f61ecc 100644 --- a/src/riscv/lib/src/machine_state/registers.rs +++ b/src/riscv/lib/src/machine_state/registers.rs @@ -13,7 +13,7 @@ use std::fmt; /// Integer register index #[allow(non_camel_case_types)] // To make names consistent with specification #[repr(u8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum XRegister { // The `usize` representation of these constructors shall be used as an // index into the 31-element array holding the registers. @@ -210,7 +210,7 @@ impl XRegisters { /// Floating-point number register index #[allow(non_camel_case_types)] // To make names consistent with specification #[repr(usize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, strum::EnumIter)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, strum::EnumIter, Hash)] pub enum FRegister { f0 = 0, f1, diff --git a/src/riscv/lib/src/parser.rs b/src/riscv/lib/src/parser.rs index 6606ab4b6909..2eb1bae9bbf1 100644 --- a/src/riscv/lib/src/parser.rs +++ b/src/riscv/lib/src/parser.rs @@ -1136,10 +1136,10 @@ const fn parse_compressed_instruction_inner(instr: u16) -> Instr { OP_C1 => match c_funct3(instr) { C_F3_0 => match (ci_imm(instr), c_rd_rs1(instr)) { // "C.ADDI is only valid when rd != x0 and nzimm != 0. - // The code points with rd == x0 encode the C.NOP instruction; - // the remaining code points with nzimm == 0 encode HINTs." - (_, x0) => CNop, - (0, _) => UnknownCompressed { instr }, + // The code points with rd == x0 and nzimm == 0 encode the C.NOP instruction; + // the remaining code points with nzimm != 0 encode HINTs." + (0, x0) => CNop, + (0, _) | (_, x0) => UnknownCompressed { instr }, (imm, rd_rs1) => CAddi(CIBTypeArgs { rd_rs1, imm }), }, C_F3_1 => match (ci_imm(instr), c_rd_rs1(instr)) { @@ -1288,6 +1288,8 @@ pub fn parse_segment(contents: &[u8], range: Range) -> Vec { #[cfg(test)] mod tests { + use std::collections::HashMap; + use super::{ instruction::{CsrArgs, ITypeArgs, Instr::*, SBTypeArgs, UJTypeArgs}, parse_block, @@ -1444,4 +1446,23 @@ mod tests { ); } } + + // Ensure parsing correctly is 1:2:1. + #[test] + fn test_unparse_compressed() { + let mut reverse = HashMap::new(); + + for i in 0..=u16::MAX { + reverse.insert(parse_compressed_instruction(i), i); + } + + for i in 0..=u16::MAX { + assert_eq!( + Some(&i), + reverse.get(&parse_compressed_instruction(i)), + "Failed {i} {}", + parse_compressed_instruction(i) + ); + } + } } diff --git a/src/riscv/lib/src/parser/instruction.rs b/src/riscv/lib/src/parser/instruction.rs index f28bd1e0bbe5..b463c35705b8 100644 --- a/src/riscv/lib/src/parser/instruction.rs +++ b/src/riscv/lib/src/parser/instruction.rs @@ -13,48 +13,48 @@ use crate::{ use enum_tag::EnumTag; use std::fmt; -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct RTypeArgs { pub rd: XRegister, pub rs1: XRegister, pub rs2: XRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct ITypeArgs { pub rd: XRegister, pub rs1: XRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct SBTypeArgs { pub rs1: XRegister, pub rs2: XRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct UJTypeArgs { pub rd: XRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CsrArgs { pub rd: XRegister, pub rs1: XRegister, pub csr: CSRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CsriArgs { pub rd: XRegister, pub imm: i64, pub csr: CSRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FenceSet { pub i: bool, pub o: bool, @@ -62,46 +62,46 @@ pub struct FenceSet { pub w: bool, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FenceArgs { pub pred: FenceSet, pub succ: FenceSet, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FRegToXRegArgs { pub rd: XRegister, pub rs1: FRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct XRegToFRegArgs { pub rd: FRegister, pub rs1: XRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct XRegToFRegArgsWithRounding { pub rd: FRegister, pub rs1: XRegister, pub rm: InstrRoundingMode, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FRegToXRegArgsWithRounding { pub rd: XRegister, pub rs1: FRegister, pub rm: InstrRoundingMode, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FCmpArgs { pub rs1: FRegister, pub rs2: FRegister, pub rd: XRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FRArgs { pub rs1: FRegister, pub rs2: FRegister, @@ -109,7 +109,7 @@ pub struct FRArgs { } /// There are 6 supported rounding modes that an instruction may use. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum InstrRoundingMode { Dynamic, Static(RoundingMode), @@ -131,7 +131,7 @@ impl InstrRoundingMode { /// Floating-point R-type instruction, containing /// rounding mode, and one input argument. -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FR1ArgWithRounding { pub rs1: FRegister, pub rm: InstrRoundingMode, @@ -140,7 +140,7 @@ pub struct FR1ArgWithRounding { /// Floating-point R-type instruction, containing /// rounding mode, and two input arguments. -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FR2ArgsWithRounding { pub rs1: FRegister, pub rs2: FRegister, @@ -150,7 +150,7 @@ pub struct FR2ArgsWithRounding { /// Floating-point R-type instruction, containing /// rounding mode, and three input arguments. -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FR3ArgsWithRounding { pub rs1: FRegister, pub rs2: FRegister, @@ -159,14 +159,14 @@ pub struct FR3ArgsWithRounding { pub rd: FRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FStoreArgs { pub rs1: XRegister, pub rs2: FRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FLoadArgs { pub rs1: XRegister, pub rd: FRegister, @@ -175,7 +175,7 @@ pub struct FLoadArgs { // R-type instructions with 2 additional bits which specify memory ordering // constraints as viewed by other RISC-V harts -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct AmoArgs { pub rd: XRegister, pub rs1: XRegister, @@ -186,41 +186,41 @@ pub struct AmoArgs { // Compressed instruction types -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CRTypeArgs { pub rd_rs1: XRegister, pub rs2: XRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CRJTypeArgs { pub rs1: XRegister, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CJTypeArgs { pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CIBTypeArgs { pub rd_rs1: XRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CIBDTypeArgs { pub rd_rs1: FRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CSSTypeArgs { pub rs2: XRegister, pub imm: i64, } -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CSSDTypeArgs { pub rs2: FRegister, pub imm: i64, @@ -229,7 +229,7 @@ pub struct CSSDTypeArgs { /// RISC-V parsed instructions. Along with legal instructions, potentially /// illegal instructions are parsed as `Unknown` or `UnknownCompressed`. /// These instructions are successfully parsed, but must not be interpreted. -#[derive(Debug, PartialEq, Clone, Copy, EnumTag)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, EnumTag, Hash)] pub enum Instr { // RV64I R-type instructions Add(RTypeArgs), -- GitLab