diff --git a/src/asm.rs b/src/asm.rs index 5503e328bbaf99dbdc10a100c50116f30cf62e36..ce25398da83ae3d1c35e49d7adefe197b400ad34 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -8,6 +8,8 @@ pub mod rv64b; pub mod rv64i; pub mod rv64k; pub mod rvzicsr; +pub mod rv32f; +pub mod rv64f; use crate::value::{IntSigned, IntUnsigned}; use core::fmt; @@ -156,8 +158,8 @@ impl fmt::Debug for UType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - ".insn u {opcode6:?}, {rd:?}, {simm20:?}", - opcode6 = self.opcode(), + ".insn u {opcode7:?}, {rd:?}, {simm20:?}", + opcode7 = self.opcode(), rd = self.rd(), simm20 = self.simm20() ) @@ -255,8 +257,8 @@ impl fmt::Debug for IType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - ".insn i {opcode6:?}, {funct3:?}, {rd:?}, {rs1:?}, {simm12:?}", - opcode6 = self.opcode(), + ".insn i {opcode7:?}, {funct3:?}, {rd:?}, {rs1:?}, {simm12:?}", + opcode7 = self.opcode(), funct3 = self.funct3(), rd = self.rd(), rs1 = self.rs1(), @@ -317,8 +319,8 @@ impl fmt::Debug for SType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - ".insn s {opcode6:?}, {funct3:?}, {rs2:?}, {simm12:?}({rs1:?})", - opcode6 = self.opcode(), + ".insn s {opcode7:?}, {funct3:?}, {rs2:?}, {simm12:?}({rs1:?})", + opcode7 = self.opcode(), funct3 = self.funct3(), rs1 = self.rs1(), rs2 = self.rs2(), @@ -410,8 +412,8 @@ impl fmt::Debug for RType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - ".insn r {opcode6:?}, {funct3:?}, {funct7:?}, {rd:?}, {rs1:?}, {rs2:?}", - opcode6 = self.opcode(), + ".insn r {opcode7:?}, {funct3:?}, {funct7:?}, {rd:?}, {rs1:?}, {rs2:?}", + opcode7 = self.opcode(), funct3 = self.funct3(), funct7 = self.funct7(), rd = self.rd(), @@ -421,7 +423,73 @@ impl fmt::Debug for RType { } } -// TODO: R4Type .insn r4 opcode6, funct3, funct2, rd, rs1, rs2, rs3 +// TODO: R4Type .insn r4 opcode7, funct3, funct2, rd, rs1, rs2, rs3 +#[derive(Clone, Copy)] +pub struct R4Type(u32); +impl R4Type { + pub fn new( + opcode: Opcode, + funct2: Funct2, + funct3: Funct3, + rd: RegInteger, + rs1: RegInteger, + rs2: RegInteger, + rs3: RegInteger, + ) -> Self { + Self( + ((rs3 as u32) << 27) + | ((funct2.bits() as u32) << 25) + | ((rs2 as u32) << 20) + | ((rs1 as u32) << 15) + | ((funct3.bits() as u32) << 12) + | ((rd as u32) << 7) + | opcode.bits() as u32, + ) + } + pub const fn from_bits(bits: u32) -> Self { + Self(bits) + } + pub const fn bits(self) -> u32 { + self.0 + } + pub const fn opcode(self) -> Opcode { + Opcode::from_bits((self.0 & 0b111_1111) as u8) + } + pub const fn funct2(self) -> Funct2 { + Funct2::from_bits(((self.0 >> 25) & 0b11) as u8) + } + pub const fn funct3(self) -> Funct3 { + Funct3::from_bits(((self.0 >> 12) & 0b111) as u8) + } + pub const fn rd(self) -> RegInteger { + RegInteger::new(((self.0 >> 7) & 0b1_1111) as u8) + } + pub const fn rs1(self) -> RegInteger { + RegInteger::new(((self.0 >> 15) & 0b1_1111) as u8) + } + pub const fn rs2(self) -> RegInteger { + RegInteger::new(((self.0 >> 20) & 0b1_1111) as u8) + } + pub const fn rs3(self) -> RegInteger { + RegInteger::new(((self.0 >> 27) & 0b1_1111) as u8) + } +} +impl fmt::Debug for R4Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + ".insn r4 {opcode7:?}, {funct3:?},{funct2:?}, {rd:?}, {rs1:?}, {rs2:?} ,{rs3:?}", + opcode7 = self.opcode(), + funct3 = self.funct3(), + funct2 = self.funct2(), + rd = self.rd(), + rs1 = self.rs1(), + rs2 = self.rs2(), + rs3 = self.rs3(), + ) + } +} + #[derive(Clone, Copy)] pub struct BType(u32); @@ -481,8 +549,8 @@ impl fmt::Debug for BType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - ".insn b {opcode6:?}, {funct3:?}, {rs1:?}, {rs2:?}, {offset:?}", - opcode6 = self.opcode(), + ".insn b {opcode7:?}, {funct3:?}, {rs1:?}, {rs2:?}, {offset:?}", + opcode7 = self.opcode(), funct3 = self.funct3(), rs1 = self.rs1(), rs2 = self.rs2(), @@ -537,8 +605,8 @@ impl fmt::Debug for JType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - ".insn j {opcode6:?}, {rd:?}, {offset:?}", - opcode6 = self.opcode(), + ".insn j {opcode7:?}, {rd:?}, {offset:?}", + opcode7 = self.opcode(), rd = self.rd(), offset = self.offset(), ) @@ -564,6 +632,25 @@ impl Opcode { } } +#[derive(Clone, Copy)] +pub struct Funct2(u8); + +impl fmt::Debug for Funct2 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "0x{:01x}", self.0) + } +} + +impl Funct2 { + const fn from_bits(bits: u8) -> Self { + assert!(bits <= 0x3); + Self(bits) + } + const fn bits(self) -> u8 { + self.0 + } +} + #[derive(Clone, Copy)] pub struct Funct3(u8); diff --git a/src/asm/rv32f.rs b/src/asm/rv32f.rs new file mode 100644 index 0000000000000000000000000000000000000000..b2a2e28f46ec68b41bc3d58b68e87cf892ad6d53 --- /dev/null +++ b/src/asm/rv32f.rs @@ -0,0 +1,540 @@ +use super::{ + Funct2, Funct3, Funct5, Funct7, IType, Opcode, RType, RegInteger, SType,R4Type +}; +use crate::value::IntSigned; +use core::fmt; + +const OPCODE_FLW: Opcode = Opcode::from_bits(0b000_0111); +const OPCODE_FSW: Opcode = Opcode::from_bits(0b010_0111); +pub(crate) const OPCODE_OP_FP: Opcode = Opcode::from_bits(0b10_10011); +const OPCODE_FMADD: Opcode = Opcode::from_bits(0b1000011); +const OPCODE_FMSUB: Opcode = Opcode::from_bits(0b1000111); +const OPCODE_FNMSUB: Opcode = Opcode::from_bits(0b1001011); +const OPCODE_FNMADD: Opcode = Opcode::from_bits(0b1001111); + +const FUNCT2_OP_FMADD: Funct2 = Funct2::from_bits(0b00); +const FUNCT2_OP_FMSUB: Funct2 = Funct2::from_bits(0b00); +const FUNCT2_OP_FNMSUB: Funct2 = Funct2::from_bits(0b00); +const FUNCT2_OP_FNMADD: Funct2 = Funct2::from_bits(0b00); + +const FUNCT3_OP_FLW: Funct3 = Funct3::from_bits(0b010); +const FUNCT3_OP_FSW: Funct3 = Funct3::from_bits(0b010); +const FUNCT3_OP_FSGNJ: Funct3 = Funct3::from_bits(0b000); +const FUNCT3_OP_FSGNJN: Funct3 = Funct3::from_bits(0b001); +const FUNCT3_OP_FSGNJX: Funct3 = Funct3::from_bits(0b010); +const FUNCT3_OP_FMIN: Funct3 = Funct3::from_bits(0b000); +const FUNCT3_OP_FMAX: Funct3 = Funct3::from_bits(0b001); +const FUNCT3_OP_FMV: Funct3 = Funct3::from_bits(0b000); +const FUNCT3_OP_FEQ: Funct3 = Funct3::from_bits(0b010); +const FUNCT3_OP_FLT: Funct3 = Funct3::from_bits(0b001); +const FUNCT3_OP_FLE: Funct3 = Funct3::from_bits(0b000); +const FUNCT3_OP_FCLASS: Funct3 = Funct3::from_bits(0b001); + +const FUNCT5_OP_FSQRT: Funct5 = Funct5::from_bits(0b0_0000); +const FUNCT5_OP_FCVT_W_S: Funct5 = Funct5::from_bits(0b0_0000); +const FUNCT5_OP_FCVT_WU_S: Funct5 = Funct5::from_bits(0b0_0001); +const FUNCT5_OP_FMV: Funct5 = Funct5::from_bits(0b0_0000); +const FUNCT5_OP_FCLASS: Funct5 = Funct5::from_bits(0b0_0000); +const FUNCT5_OP_FCVT_S_W: Funct5 = Funct5::from_bits(0b0_0000); +const FUNCT5_OP_FCVT_S_WU: Funct5 = Funct5::from_bits(0b0_0001); + +const FUNCT7_OP_FADD: Funct7 = Funct7::from_bits(0b000_0000); +const FUNCT7_OP_FSUB: Funct7 = Funct7::from_bits(0b000_0100); +const FUNCT7_OP_FMUL: Funct7 = Funct7::from_bits(0b000_1000); +const FUNCT7_OP_FDIV: Funct7 = Funct7::from_bits(0b000_1100); +const FUNCT7_OP_FSQRT: Funct7 = Funct7::from_bits(0b000_1100); +const FUNCT7_OP_FSGNJ: Funct7 = Funct7::from_bits(0b001_0000); +const FUNCT7_OP_FMIN: Funct7 = Funct7::from_bits(0b001_0100); +const FUNCT7_OP_FMAX: Funct7 = Funct7::from_bits(0b001_0100); +const FUNCT7_OP_FCVT_W_S: Funct7 = Funct7::from_bits(0b110_0000); +const FUNCT7_OP_FMV_X_W: Funct7 = Funct7::from_bits(0b111_0000); +const FUNCT7_OP_FEQ: Funct7 = Funct7::from_bits(0b101_0000); +const FUNCT7_OP_FLT: Funct7 = Funct7::from_bits(0b101_0000); +const FUNCT7_OP_FLE: Funct7 = Funct7::from_bits(0b101_0000); +const FUNCT7_OP_FCLASS: Funct7 = Funct7::from_bits(0b111_0000); +const FUNCT7_OP_FCVT_S_W: Funct7 = Funct7::from_bits(0b110_1000); +const FUNCT7_OP_FMV_W_X: Funct7 = Funct7::from_bits(0b111_1000); + + +#[derive(Clone, Copy)] +pub enum InsnRV32F{ + Flw(IType), + Fsw(SType), + + FmaddS(R4Type), + FmsubS(R4Type), + FnmsubS(R4Type), + FnmaddS(R4Type), + + FaddS(RType), + FsubS(RType), + FmulS(RType), + FdivS(RType), + FsqrtS(RType), + FsgnjS(RType), + FsgnjnS(RType), + FsgnjxS(RType), + FminS(RType), + FmaxS(RType), + FcvtWS(RType), + FcvtWuS(RType), + FmvXW(RType), + FeqS(RType), + FltS(RType), + FleS(RType), + FclassS(RType), + FcvtSW(RType), + FcvtSWu(RType), + FmvWX(RType) +} + +#[derive(Clone, Copy)] +pub enum RoundingMode{ + Rne, + Rtz, + Rdn, + Rup, + Rmm, + Dyn, + Invalid +} + +impl RoundingMode{ + pub fn get_func3_value(&self) -> Funct3{ + match self { + RoundingMode::Rne => Funct3::from_bits(0b000), + RoundingMode::Rtz => Funct3::from_bits(0b001), + RoundingMode::Rdn => Funct3::from_bits(0b010), + RoundingMode::Rup => Funct3::from_bits(0b011), + RoundingMode::Rmm => Funct3::from_bits(0b100), + RoundingMode::Dyn => Funct3::from_bits(0b111), + _ => unreachable!(), + } + } +} + +impl fmt::Debug for InsnRV32F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Flw(i) => write!(f, "flw {:?}, {:?}({:?})", i.rd(), i.simm12(), i.rs1()), + Self::Fsw(s) => write!(f, "fsw {:?}, {:?}({:?})", s.rs2(), s.simm12(), s.rs1()), + + Self::FmaddS(r4) => write!(f, "fmadd.s {:?}, {:?}, {:?}, {:?}", r4.rd(), r4.rs1(), r4.rs2(), r4.rs3()), + Self::FmsubS(r4) => write!(f, "fmsub.s {:?}, {:?}, {:?}, {:?}", r4.rd(), r4.rs1(), r4.rs2(), r4.rs3()), + Self::FnmsubS(r4) => write!(f, "fnmsub.s {:?}, {:?}, {:?}, {:?}", r4.rd(), r4.rs1(), r4.rs2(), r4.rs3()), + Self::FnmaddS(r4) => write!(f, "fnmadd.s {:?}, {:?}, {:?}, {:?}", r4.rd(), r4.rs1(), r4.rs2(), r4.rs3()), + + Self::FaddS(r) => write!(f, "fadd.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FsubS(r) => write!(f, "fsub.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FmulS(r) => write!(f, "fmul.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FdivS(r) => write!(f, "fdiv.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FsqrtS(r) => write!(f, "fsqrt.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FsgnjS(r) => write!(f, "fsjnj.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FsgnjnS(r) => write!(f, "fsjnjn.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FsgnjxS(r) => write!(f, "fsjnjx.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FminS(r) => write!(f, "fmin.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FmaxS(r) => write!(f, "fmax.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtWS(r) => write!(f, "fcvt.w.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtWuS(r) => write!(f, "fcvt.wu.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FmvXW(r) => write!(f, "fmv.x.w {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FeqS(r) => write!(f, "feq.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FltS(r) => write!(f, "flt.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FleS(r) => write!(f, "fle.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FclassS(r) => write!(f, "fclass.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtSW(r) => write!(f, "fcvt.s.w {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtSWu(r) => write!(f, "fcvt.s.wu {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FmvWX(r) => write!(f, "fmv.w.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + } + } +} + +pub fn flw(rd: RegInteger, rs1: RegInteger, offset: impl Into>) -> T +where + InsnRV32F: Into, +{ + InsnRV32F::Flw(IType::new( + OPCODE_FLW, + FUNCT3_OP_FLW, + rd, + rs1, + offset.into() + )) + .into() +} + +pub fn fsw(rs1: RegInteger, rs2: RegInteger, offset: impl Into>) -> T +where + InsnRV32F: Into, +{ + InsnRV32F::Fsw(SType::new( + OPCODE_FSW, + FUNCT3_OP_FSW, + rs1, + rs2, + offset.into() + )) + .into() +} + +pub fn fmadd_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rs3: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FmaddS(R4Type::new( + OPCODE_FMADD, + FUNCT2_OP_FMADD, + rm.get_func3_value(), + rd, + rs1, + rs2, + rs3 + )) + .into() +} + +pub fn fmsub_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rs3: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FmsubS(R4Type::new( + OPCODE_FMSUB, + FUNCT2_OP_FMSUB, + rm.get_func3_value(), + rd, + rs1, + rs2, + rs3 + )) + .into() +} + +pub fn fnmsub_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rs3: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FnmsubS(R4Type::new( + OPCODE_FNMSUB, + FUNCT2_OP_FNMSUB, + rm.get_func3_value(), + rd, + rs1, + rs2, + rs3 + )) + .into() +} + +pub fn fnmadd_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rs3: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FnmaddS(R4Type::new( + OPCODE_FNMADD, + FUNCT2_OP_FNMADD, + rm.get_func3_value(), + rd, + rs1, + rs2, + rs3 + )) + .into() +} + +pub fn fadd_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FaddS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FADD, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fsub_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FsubS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FSUB, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fmul_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FmulS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FMUL, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fdiv_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FdivS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FDIV, + rd, + rs1, + rs2, + )) + .into() +} +pub fn fsqrt_s(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FsqrtS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FSQRT, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FSQRT.bits()) + )) + .into() +} + +pub fn fsgnj_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FsgnjS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FSGNJ, + FUNCT7_OP_FSGNJ, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fsgnjn_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FsgnjnS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FSGNJN, + FUNCT7_OP_FSGNJ, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fsgnjx_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FsgnjxS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FSGNJX, + FUNCT7_OP_FSGNJ, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fmin_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FminS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FMIN, + FUNCT7_OP_FMIN, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fmax_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FmaxS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FMAX, + FUNCT7_OP_FMAX, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fcvt_w_s(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FcvtWS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_W_S, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_W_S.bits()) + )) + .into() +} + +pub fn fcvt_wu_s(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FcvtWuS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_W_S, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_WU_S.bits()) + )) + .into() +} + +pub fn fcvt_s_w(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FcvtSW(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_S_W, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_S_W.bits()) + )) + .into() +} + +pub fn fcvt_s_wu(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FcvtSWu(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_S_W, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_S_WU.bits()) + )) + .into() +} + +pub fn fmv_x_w(rd: RegInteger, rs1: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FmvXW(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FMV, + FUNCT7_OP_FMV_X_W, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FMV.bits()) + )) + .into() +} + +pub fn fmv_w_x(rd: RegInteger, rs1: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FmvWX(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FMV, + FUNCT7_OP_FMV_W_X, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FMV.bits()) + )) + .into() +} + +pub fn feq_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FeqS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FEQ, + FUNCT7_OP_FEQ, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn flt_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FltS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FLT, + FUNCT7_OP_FLT, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fle_s(rd: RegInteger, rs1: RegInteger, rs2: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FleS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FLE, + FUNCT7_OP_FLE, + rd, + rs1, + rs2, + )) + .into() +} + +pub fn fclass_s(rd: RegInteger, rs1: RegInteger) -> T +where + InsnRV32F: Into +{ + InsnRV32F::FclassS(RType::new( + OPCODE_OP_FP, + FUNCT3_OP_FCLASS, + FUNCT7_OP_FCLASS, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCLASS.bits()) + )) + .into() +} \ No newline at end of file diff --git a/src/asm/rv64f.rs b/src/asm/rv64f.rs new file mode 100644 index 0000000000000000000000000000000000000000..921f553e693170554adba13524863ec04c88037f --- /dev/null +++ b/src/asm/rv64f.rs @@ -0,0 +1,94 @@ +use super::{ + Funct5, Funct7, RType, RegInteger, +}; +use crate::asm::rv32f::{ + OPCODE_OP_FP, RoundingMode +}; +use core::fmt; + +const FUNCT5_OP_FCVT_L_S: Funct5 = Funct5::from_bits(0b0_0010); +const FUNCT5_OP_FCVT_LU_S: Funct5 = Funct5::from_bits(0b0_0011); +const FUNCT5_OP_FCVT_S_L: Funct5 = Funct5::from_bits(0b0_0010); +const FUNCT5_OP_FCVT_S_LU: Funct5 = Funct5::from_bits(0b0_0011); + +const FUNCT7_OP_FCVT_L_S: Funct7 = Funct7::from_bits(0b110_0000); +const FUNCT7_OP_FCVT_S_L: Funct7 = Funct7::from_bits(0b110_0100); + +#[derive(Clone, Copy)] +pub enum InsnRV64F{ + FcvtLS(RType), + FcvtLuS(RType), + FcvtSL(RType), + FcvtSLu(RType) +} + +impl fmt::Debug for InsnRV64F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::FcvtLS(r) => write!(f, "fcvt.l.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtLuS(r) => write!(f, "fcvt.lu.s {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtSL(r) => write!(f, "fcvt.s.l {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + Self::FcvtSLu(r) => write!(f, "fcvt.s.lu {:?}, {:?}, {:?}", r.rd(), r.rs1(), r.rs2()), + } + } +} + +pub fn fcvt_l_s(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV64F: Into +{ + InsnRV64F::FcvtLS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_L_S, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_L_S.bits()) + )) + .into() +} + +pub fn fcvt_lu_s(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV64F: Into +{ + InsnRV64F::FcvtLuS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_L_S, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_LU_S.bits()) + )) + .into() +} + +pub fn fcvt_s_l(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV64F: Into +{ + InsnRV64F::FcvtSL(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_S_L, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_S_L.bits()) + )) + .into() +} + +pub fn fcvt_s_lu(rd: RegInteger, rs1: RegInteger, rm: RoundingMode) -> T +where + InsnRV64F: Into +{ + InsnRV64F::FcvtLuS(RType::new( + OPCODE_OP_FP, + rm.get_func3_value(), + FUNCT7_OP_FCVT_S_L, + rd, + rs1, + RegInteger::new(FUNCT5_OP_FCVT_S_LU.bits()) + )) + .into() +} \ No newline at end of file