diff --git a/src/asm/mod.rs b/src/asm/mod.rs index 278a33e..9fff147 100644 --- a/src/asm/mod.rs +++ b/src/asm/mod.rs @@ -168,31 +168,23 @@ pub enum Instruction { Pseudo(Pseudo), } -/// If the enum variant contains `Option`, -/// it means that the instructions used may vary according to `DataSize`. -/// Use 'Some' if RISC-V ISA provides instruction to support a specific 'DataSize', -/// if not, 'None' which means to use default instruction. -/// Because KECC uses RV64 (RISC-V ISA for 64-bit architecture), -/// KECC uses `Some` if `DataSize` is `Word`, if not, use `None`. -/// https://riscv.org/specifications/isa-spec-pdf/ (35p) -/// /// If the enum variant contains `bool`, /// It means that different instructions exist /// depending on whether the operand is signed or not. #[derive(Debug, Clone, PartialEq)] pub enum RType { - Add(Option), - Sub(Option), - Sll(Option), - Srl(Option), - Sra(Option), - Mul(Option), + Add(DataSize), + Sub(DataSize), + Sll(DataSize), + Srl(DataSize), + Sra(DataSize), + Mul(DataSize), Div { - data_size: Option, + data_size: DataSize, is_signed: bool, }, Rem { - data_size: Option, + data_size: DataSize, is_signed: bool, }, Slt { @@ -218,7 +210,7 @@ pub enum RType { /// fcvt.s.l(u) or fcvt.d.l(u) /// fcvt.s.w(u) or fcvt.d.w(u) FcvtIntToFloat { - int_data_size: Option, + int_data_size: DataSize, float_data_size: DataSize, is_signed: bool, }, @@ -226,7 +218,7 @@ pub enum RType { /// fcvt.w(u).s or fcvt.w(u).d FcvtFloatToInt { float_data_size: DataSize, - int_data_size: Option, + int_data_size: DataSize, is_signed: bool, }, /// fcvt.s.d or fcvt.d.s @@ -240,58 +232,58 @@ impl RType { pub fn add(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Add(data_size.word()) + Self::Add(data_size) } pub fn sub(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Sub(data_size.word()) + Self::Sub(data_size) } pub fn sll(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Sll(data_size.word()) + Self::Sll(data_size) } pub fn srl(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Srl(data_size.word()) + Self::Srl(data_size) } pub fn sra(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Sra(data_size.word()) + Self::Sra(data_size) } pub fn mul(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Mul(data_size.word()) + Self::Mul(data_size) } pub fn div(dtype: ir::Dtype, is_signed: bool) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); Self::Div { - data_size: data_size.word(), + data_size, is_signed, } } @@ -299,10 +291,10 @@ impl RType { pub fn rem(dtype: ir::Dtype, is_signed: bool) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); Self::Rem { - data_size: data_size.word(), + data_size, is_signed, } } @@ -375,14 +367,14 @@ impl RType { let is_signed = from.is_int_signed(); let int_data_size = DataSize::try_from(from).expect("`data_size` must be derived from `dtype`"); - assert!(int_data_size.is_integer()); + assert!(matches!(int_data_size, DataSize::Word | DataSize::Double)); let float_data_size = DataSize::try_from(to).expect("`data_size` must be derived from `dtype`"); assert!(float_data_size.is_floating_point()); Self::FcvtIntToFloat { - int_data_size: int_data_size.word(), + int_data_size, float_data_size, is_signed, } @@ -396,36 +388,29 @@ impl RType { let is_signed = to.is_int_signed(); let int_data_size = DataSize::try_from(to).expect("`data_size` must be derived from `dtype`"); - assert!(int_data_size.is_integer()); + assert!(matches!(int_data_size, DataSize::Word | DataSize::Double)); Self::FcvtFloatToInt { float_data_size, - int_data_size: int_data_size.word(), + int_data_size, is_signed, } } } -/// If the enum variant contains `Option`, -/// it means that the instructions used may vary according to `DataSize`. -/// Use 'Some' if RISC-V ISA provides instruction to support a specific 'DataSize', -/// if not, 'None' which means to use default instruction. -/// Because KECC uses RV64 (RISC-V ISA for 64-bit architecture), -/// KECC uses `Some` if `DataSize` is `Word`, if not, use `None`. -/// https://riscv.org/specifications/isa-spec-pdf/ (35p) #[derive(Debug, Clone, PartialEq)] pub enum IType { Load { data_size: DataSize, is_signed: bool, }, - Addi(Option), + Addi(DataSize), Xori, Ori, Andi, - Slli(Option), - Srli(Option), - Srai(Option), + Slli(DataSize), + Srli(DataSize), + Srai(DataSize), Slti { is_signed: bool, }, @@ -440,7 +425,7 @@ impl IType { data_size: DataSize::Double, is_signed: true, }; - pub const ADDI: Self = Self::Addi(None); + pub const ADDI: Self = Self::Addi(DataSize::Double); pub fn load(dtype: ir::Dtype) -> Self { let data_size = @@ -467,25 +452,25 @@ impl IType { pub fn slli(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Slli(data_size.word()) + Self::Slli(data_size) } pub fn srli(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Srli(data_size.word()) + Self::Srli(data_size) } pub fn srai(dtype: ir::Dtype) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - assert!(data_size.is_integer()); + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); - Self::Srai(data_size.word()) + Self::Srai(data_size) } } @@ -543,7 +528,7 @@ pub enum Pseudo { }, /// neg(w) rd, rs Neg { - data_size: Option, + data_size: DataSize, rd: Register, rs: Register, }, @@ -575,11 +560,7 @@ impl Pseudo { pub fn neg(dtype: ir::Dtype, rd: Register, rs: Register) -> Self { let data_size = DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); - let data_size = if data_size == DataSize::Word { - Some(data_size) - } else { - None - }; + assert!(matches!(data_size, DataSize::Word | DataSize::Double)); Self::Neg { data_size, rd, rs } } @@ -633,7 +614,7 @@ impl Label { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum DataSize { Byte, Half, diff --git a/src/asm/write_asm.rs b/src/asm/write_asm.rs index 440205f..c64b6b8 100644 --- a/src/asm/write_asm.rs +++ b/src/asm/write_asm.rs @@ -205,19 +205,19 @@ impl WriteString for Instruction { impl WriteString for RType { fn write_string(&self) -> String { match self { - Self::Add(data_size) => format!("add{}", data_size.write_string()), - Self::Sub(data_size) => format!("sub{}", data_size.write_string()), - Self::Sll(data_size) => format!("sll{}", data_size.write_string()), - Self::Srl(data_size) => format!("srl{}", data_size.write_string()), - Self::Sra(data_size) => format!("sra{}", data_size.write_string()), - Self::Mul(data_size) => format!("mul{}", data_size.write_string()), + Self::Add(data_size) => format!("add{}", data_size.word().write_string()), + Self::Sub(data_size) => format!("sub{}", data_size.word().write_string()), + Self::Sll(data_size) => format!("sll{}", data_size.word().write_string()), + Self::Srl(data_size) => format!("srl{}", data_size.word().write_string()), + Self::Sra(data_size) => format!("sra{}", data_size.word().write_string()), + Self::Mul(data_size) => format!("mul{}", data_size.word().write_string()), Self::Div { data_size, is_signed, } => format!( "div{}{}", if *is_signed { "" } else { "u" }, - data_size.write_string() + data_size.word().write_string() ), Self::Rem { data_size, @@ -225,7 +225,7 @@ impl WriteString for RType { } => format!( "rem{}{}", if *is_signed { "" } else { "u" }, - data_size.write_string() + data_size.word().write_string() ), Self::Slt { is_signed } => format!("slt{}", if *is_signed { "" } else { "u" }), Self::Xor => "xor".to_string(), @@ -265,10 +265,10 @@ impl WriteString for RType { is_signed, } => { assert!(float_data_size.is_floating_point()); + assert!(matches!(int_data_size, DataSize::Word | DataSize::Double)); format!( "fcvt.{}{}.{}", - if let Some(int_data_size) = int_data_size { - assert_eq!(*int_data_size, DataSize::Word); + if matches!(int_data_size, DataSize::Word) { "w" } else { "l" @@ -284,11 +284,11 @@ impl WriteString for RType { is_signed, } => { assert!(float_data_size.is_floating_point()); + assert!(matches!(int_data_size, DataSize::Word | DataSize::Double)); format!( "fcvt.{}.{}{}", float_data_size.write_string(), - if let Some(int_data_size) = int_data_size { - assert_eq!(*int_data_size, DataSize::Word); + if matches!(int_data_size, DataSize::Word) { "w" } else { "l" @@ -330,13 +330,13 @@ impl WriteString for IType { ) } } - Self::Addi(data_size) => format!("addi{}", data_size.write_string()), + Self::Addi(data_size) => format!("addi{}", data_size.word().write_string()), Self::Xori => "xori".to_string(), Self::Ori => "ori".to_string(), Self::Andi => "andi".to_string(), - Self::Slli(data_size) => format!("slli{}", data_size.write_string()), - Self::Srli(data_size) => format!("srli{}", data_size.write_string()), - Self::Srai(data_size) => format!("srai{}", data_size.write_string()), + Self::Slli(data_size) => format!("slli{}", data_size.word().write_string()), + Self::Srli(data_size) => format!("srli{}", data_size.word().write_string()), + Self::Srai(data_size) => format!("srai{}", data_size.word().write_string()), Self::Slti { is_signed } => format!("slti{}", if *is_signed { "" } else { "u" }), } } @@ -396,7 +396,7 @@ impl WriteString for Pseudo { ), Self::Neg { data_size, rd, rs } => format!( "neg{}\t{},{}", - data_size.write_string(), + data_size.word().write_string(), rd.write_string(), rs.write_string() ),