From b9724ef30ec377d8dbf205b50dcfa8195e91b4cc Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Thu, 28 Mar 2024 18:05:07 +0000 Subject: [PATCH] RISC-V: enable F/D fadd test Implement fadd.*, fsub.*, fmul.*, fdiv.* --- src/risc_v/interpreter/src/interpreter.rs | 2 +- .../interpreter/src/interpreter/float.rs | 191 +++++++++++++++++- .../interpreter/src/interpreter/rv64d.rs | 53 +++++ .../interpreter/src/interpreter/rv64f.rs | 53 +++++ src/risc_v/interpreter/src/machine_state.rs | 14 +- src/risc_v/interpreter/src/parser.rs | 47 ++++- .../interpreter/src/parser/instruction.rs | 61 +++++- .../tests/test_suite_interpreter.rs | 4 +- 8 files changed, 413 insertions(+), 12 deletions(-) diff --git a/src/risc_v/interpreter/src/interpreter.rs b/src/risc_v/interpreter/src/interpreter.rs index 4496564dda2a..eb28260d12b3 100644 --- a/src/risc_v/interpreter/src/interpreter.rs +++ b/src/risc_v/interpreter/src/interpreter.rs @@ -4,7 +4,7 @@ // SPDX-License-Identifier: MIT mod common_memory; -mod float; +pub mod float; pub mod rv32a; pub mod rv32i; pub mod rv32m; diff --git a/src/risc_v/interpreter/src/interpreter/float.rs b/src/risc_v/interpreter/src/interpreter/float.rs index 3441da513194..75c72c623f2f 100644 --- a/src/risc_v/interpreter/src/interpreter/float.rs +++ b/src/risc_v/interpreter/src/interpreter/float.rs @@ -6,13 +6,15 @@ use crate::{ machine_state::{ - csregisters::{CSRegister, CSRegisters}, + csregisters::{CSRValue, CSRegister, CSRegisters}, hart_state::HartState, registers::{FRegister, FValue, XRegister}, }, + parser::instruction::InstrRoundingMode, state_backend as backend, + traps::Exception, }; -use rustc_apfloat::{ieee::Double, ieee::Single, Float}; +use rustc_apfloat::{ieee::Double, ieee::Single, Float, Round, Status, StatusAnd}; pub trait FloatExt: Float + Into + Copy where @@ -21,6 +23,15 @@ where /// The canonical NaN has a positive sign and all /// significand bits clear expect the MSB (the quiet bit). fn canonical_nan() -> Self; + + /// Canonicalise floating-point values to the canonical nan. + fn canonicalise(self) -> Self { + if self.is_nan() { + Self::canonical_nan() + } else { + self + } + } } impl FloatExt for Single { @@ -140,6 +151,78 @@ where self.xregisters.write(rd, res); } + /// `FADD.*` instruction. + /// + /// Adds `rs1` to `rs2`, writing the result in `rd`. + /// + /// Returns `Exception::IllegalInstruction` on an invalid rounding mode. + pub(super) fn run_fadd( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> + where + FValue: Into, + { + self.f_arith_2(rs1, rs2, rm, rd, F::add_r) + } + + /// `FSUB.*` instruction. + /// + /// Subtracts `rs2` from `rs1`, writing the result in `rd`. + /// + /// Returns `Exception::IllegalInstruction` on an invalid rounding mode. + pub(super) fn run_fsub( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> + where + FValue: Into, + { + self.f_arith_2(rs1, rs2, rm, rd, F::sub_r) + } + + /// `FMUL.*` instruction. + /// + /// Multiplies `rs1` by `rs2`, writing the result in `rd`. + /// + /// Returns `Exception::IllegalInstruction` on an invalid rounding mode. + pub(super) fn run_fmul( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> + where + FValue: Into, + { + self.f_arith_2(rs1, rs2, rm, rd, F::mul_r) + } + + /// `FDIV.*` instruction. + /// + /// Divides `rs1` by `rs2`, writing the result in `rd`. + /// + /// Returns `Exception::IllegalInstruction` on an invalid rounding mode. + pub(super) fn run_fdiv( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> + where + FValue: Into, + { + self.f_arith_2(rs1, rs2, rm, rd, F::div_r) + } + /// `FMIN.*` instruction. /// /// Writes the smaller of `rs1`, `rs2` to `rd`. **NB** `-0.0 < +0.0`. @@ -203,6 +286,42 @@ where self.f_sign_injection(rs1, rs2, rd, |x, y| x ^ y); } + // perform 2-argument floating-point arithmetic + fn f_arith_2( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + f: fn(F, F, Round) -> StatusAnd, + ) -> Result<(), Exception> + where + FValue: Into, + { + let rval1: F = self.fregisters.read(rs1).into(); + let rval2: F = self.fregisters.read(rs2).into(); + + let rm = self.f_rounding_mode(rm)?; + + let StatusAnd { status, value } = f(rval1, rval2, rm).map(F::canonicalise); + + if status != Status::OK { + self.csregisters.set_exception_flag_status(status); + } + + self.fregisters.write(rd, value.into()); + Ok(()) + } + + fn f_rounding_mode(&self, rm: InstrRoundingMode) -> Result { + let rm = match rm { + InstrRoundingMode::Static(rm) => rm, + InstrRoundingMode::Dynamic => self.csregisters.read(CSRegister::frm).try_into()?, + }; + + Ok(rm.into()) + } + fn f_sign_injection( &mut self, rs1: FRegister, @@ -259,6 +378,50 @@ where } } +/// There are 5 supported rounding modes +#[allow(clippy::upper_case_acronyms)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum RoundingMode { + /// Round to Nearest, ties to Even + RNE, + /// Round towards Zero + RTZ, + /// Round Down (towards -∞) + RDN, + /// Round Up (towrads +∞) + RUP, + /// Round to Nearest, ties to Max Magnitude + RMM, +} + +impl TryFrom for RoundingMode { + type Error = Exception; + + fn try_from(value: CSRValue) -> Result { + match value { + 0b000 => Ok(Self::RNE), + 0b001 => Ok(Self::RTZ), + 0b010 => Ok(Self::RDN), + 0b011 => Ok(Self::RUP), + 0b100 => Ok(Self::RMM), + _ => Err(Exception::IllegalInstruction), + } + } +} + +#[allow(clippy::from_over_into)] +impl Into for RoundingMode { + fn into(self) -> Round { + match self { + Self::RNE => Round::NearestTiesToEven, + Self::RTZ => Round::TowardZero, + Self::RUP => Round::TowardPositive, + Self::RDN => Round::TowardNegative, + Self::RMM => Round::NearestTiesToAway, + } + } +} + #[allow(unused)] pub enum Fflag { /// Inexact @@ -277,4 +440,28 @@ impl CSRegisters { fn set_exception_flag(&mut self, mask: Fflag) { self.set_bits(CSRegister::fflags, 1 << mask as usize); } + + fn set_exception_flag_status(&mut self, status: Status) { + let bits = status_to_bits(status); + self.set_bits(CSRegister::fflags, bits as u64); + } +} + +const fn status_to_bits(status: Status) -> u8 { + status.bits().reverse_bits() >> 3 +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_status_to_bits() { + assert_eq!(0, status_to_bits(Status::OK)); + assert_eq!(1 << Fflag::NX as usize, status_to_bits(Status::INEXACT)); + assert_eq!(1 << Fflag::UF as usize, status_to_bits(Status::UNDERFLOW)); + assert_eq!(1 << Fflag::OF as usize, status_to_bits(Status::OVERFLOW)); + assert_eq!(1 << Fflag::DZ as usize, status_to_bits(Status::DIV_BY_ZERO)); + assert_eq!(1 << Fflag::NV as usize, status_to_bits(Status::INVALID_OP)); + } } diff --git a/src/risc_v/interpreter/src/interpreter/rv64d.rs b/src/risc_v/interpreter/src/interpreter/rv64d.rs index eda4f550eb94..93d259f07ea3 100644 --- a/src/risc_v/interpreter/src/interpreter/rv64d.rs +++ b/src/risc_v/interpreter/src/interpreter/rv64d.rs @@ -13,6 +13,7 @@ use crate::{ registers::{FRegister, FValue, XRegister}, MachineState, }, + parser::instruction::InstrRoundingMode, state_backend as backend, traps::Exception, }; @@ -65,6 +66,58 @@ where self.run_flt::(rs1, rs2, rd); } + /// `FADD.D` R-type instruction. + /// + /// See [Self::run_fadd]. + pub fn run_fadd_d( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fadd::(rs1, rs2, rm, rd) + } + + /// `FSUB.D` R-type instruction. + /// + /// See [Self::run_fsub]. + pub fn run_fsub_d( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fsub::(rs1, rs2, rm, rd) + } + + /// `FMUL.D` R-type instruction. + /// + /// See [Self::run_fmul]. + pub fn run_fmul_d( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fmul::(rs1, rs2, rm, rd) + } + + /// `FDIV.D` R-type instruction. + /// + /// See [Self::run_fdiv]. + pub fn run_fdiv_d( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fdiv::(rs1, rs2, rm, rd) + } + /// `FMIN.D` R-type instruction. /// /// See [Self::run_fmin]. diff --git a/src/risc_v/interpreter/src/interpreter/rv64f.rs b/src/risc_v/interpreter/src/interpreter/rv64f.rs index c6ba1b7d82d3..4c272f651f2b 100644 --- a/src/risc_v/interpreter/src/interpreter/rv64f.rs +++ b/src/risc_v/interpreter/src/interpreter/rv64f.rs @@ -14,6 +14,7 @@ use crate::{ registers::{FRegister, FValue, XRegister}, MachineState, }, + parser::instruction::InstrRoundingMode, state_backend as backend, traps::Exception, }; @@ -73,6 +74,58 @@ where self.run_flt::(rs1, rs2, rd); } + /// `FADD.S` R-type instruction. + /// + /// See [Self::run_fadd]. + pub fn run_fadd_s( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fadd::(rs1, rs2, rm, rd) + } + + /// `FSUB.S` R-type instruction. + /// + /// See [Self::run_fsub]. + pub fn run_fsub_s( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fsub::(rs1, rs2, rm, rd) + } + + /// `FMUL.S` R-type instruction. + /// + /// See [Self::run_fmul]. + pub fn run_fmul_s( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fmul::(rs1, rs2, rm, rd) + } + + /// `FDIV.S` R-type instruction. + /// + /// See [Self::run_fdiv]. + pub fn run_fdiv_s( + &mut self, + rs1: FRegister, + rs2: FRegister, + rm: InstrRoundingMode, + rd: FRegister, + ) -> Result<(), Exception> { + self.run_fdiv::(rs1, rs2, rm, rd) + } + /// `FMIN.S` R-type instruction. /// /// See [Self::run_fmin]. diff --git a/src/risc_v/interpreter/src/machine_state.rs b/src/risc_v/interpreter/src/machine_state.rs index 58fffecc7028..e4bb1c60c45c 100644 --- a/src/risc_v/interpreter/src/machine_state.rs +++ b/src/risc_v/interpreter/src/machine_state.rs @@ -161,12 +161,16 @@ macro_rules! run_f_x_instr { }}; } -/// Runs a F/D instruction over the hart state, touching both F & X regisers. +/// Runs a F/D instruction over the hart state, touching both F & fcsr registers. macro_rules! run_f_r_instr { ($state: ident, $instr: ident, $args: ident, $run_fn: ident) => {{ $state.hart.$run_fn($args.rs1, $args.rs2, $args.rd); Ok(Add($instr.width())) }}; + ($state: ident, $instr: ident, $args: ident, $run_fn: ident, $($field: ident),+) => {{ + $state.hart.$run_fn($args.rs1, $($args.$field,)* $args.rd)?; + Ok(Add($instr.width())) + }}; } /// Runs an atomic instruction @@ -312,6 +316,10 @@ impl MachineState Instr::Feqs(args) => run_f_r_instr!(self, instr, args, run_feq_s), Instr::Fles(args) => run_f_r_instr!(self, instr, args, run_fle_s), Instr::Flts(args) => run_f_r_instr!(self, instr, args, run_flt_s), + Instr::Fadds(args) => run_f_r_instr!(self, instr, args, run_fadd_s, rs2, rm), + Instr::Fsubs(args) => run_f_r_instr!(self, instr, args, run_fsub_s, rs2, rm), + Instr::Fmuls(args) => run_f_r_instr!(self, instr, args, run_fmul_s, rs2, rm), + Instr::Fdivs(args) => run_f_r_instr!(self, instr, args, run_fdiv_s, rs2, rm), Instr::Fmins(args) => run_f_r_instr!(self, instr, args, run_fmin_s), Instr::Fmaxs(args) => run_f_r_instr!(self, instr, args, run_fmax_s), Instr::Flw(args) => run_load_instr!(self, instr, args, run_flw), @@ -327,6 +335,10 @@ impl MachineState Instr::Feqd(args) => run_f_r_instr!(self, instr, args, run_feq_d), Instr::Fled(args) => run_f_r_instr!(self, instr, args, run_fle_d), Instr::Fltd(args) => run_f_r_instr!(self, instr, args, run_flt_d), + Instr::Faddd(args) => run_f_r_instr!(self, instr, args, run_fadd_d, rs2, rm), + Instr::Fsubd(args) => run_f_r_instr!(self, instr, args, run_fsub_d, rs2, rm), + Instr::Fmuld(args) => run_f_r_instr!(self, instr, args, run_fmul_d, rs2, rm), + Instr::Fdivd(args) => run_f_r_instr!(self, instr, args, run_fdiv_d, rs2, rm), Instr::Fmind(args) => run_f_r_instr!(self, instr, args, run_fmin_d), Instr::Fmaxd(args) => run_f_r_instr!(self, instr, args, run_fmax_d), Instr::Fld(args) => run_load_instr!(self, instr, args, run_fld), diff --git a/src/risc_v/interpreter/src/parser.rs b/src/risc_v/interpreter/src/parser.rs index ea7c28dc780d..c1b6ec095787 100644 --- a/src/risc_v/interpreter/src/parser.rs +++ b/src/risc_v/interpreter/src/parser.rs @@ -258,6 +258,21 @@ macro_rules! f_r_instr { }; } +macro_rules! f_r_rm_2_instr { + ($enum_variant:ident, $instr:expr, $rs2_bits:expr, $rm:expr) => {{ + if let Some(rounding) = InstrRoundingMode::from_rm($rm) { + $enum_variant(instruction::FR2ArgsWithRounding { + rd: rd_f($instr), + rs1: rs1_f($instr), + rs2: parse_fregister($rs2_bits), + rm: rounding, + }) + } else { + Unknown { instr: $instr } + } + }}; +} + macro_rules! fence_instr { ($enum_variant:ident, $instr:expr) => { $enum_variant(instruction::FenceArgs { @@ -344,6 +359,8 @@ const F3_7: u32 = 0b111; const F5_0: u32 = 0b0_0000; const F5_1: u32 = 0b0_0001; +const F5_2: u32 = 0b0_0010; +const F5_3: u32 = 0b0_0011; const F5_4: u32 = 0b0_0100; const F5_5: u32 = 0b0_0101; const F5_8: u32 = 0b0_1000; @@ -368,9 +385,9 @@ const FMT_D: u32 = 0b01; const WIDTH_W: u32 = 0b010; const WIDTH_D: u32 = 0b011; -const RM_0: u32 = 0b0; -const RM_1: u32 = 0b1; -const RM_2: u32 = 0b10; +const RM_0: u32 = 0b000; +const RM_1: u32 = 0b001; +const RM_2: u32 = 0b010; const RM_EQ: u32 = RM_2; const RM_LT: u32 = RM_1; const RM_LE: u32 = RM_0; @@ -601,6 +618,18 @@ fn parse_uncompressed_instruction(instr: u32) -> Instr { // F/D-type instructions OP_FP => match fmt(instr) { FMT_S => match (funct5(instr), rm(instr), rs2_bits(instr)) { + (F5_0, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fadds, instr, rs2_bits, rounding) + } + (F5_1, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fsubs, instr, rs2_bits, rounding) + } + (F5_2, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fmuls, instr, rs2_bits, rounding) + } + (F5_3, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fdivs, instr, rs2_bits, rounding) + } (F5_4, RM_0, rs2_bits) => f_r_instr!(Fsgnjs, instr, rs2_bits), (F5_4, RM_1, rs2_bits) => f_r_instr!(Fsgnjns, instr, rs2_bits), (F5_4, RM_2, rs2_bits) => f_r_instr!(Fsgnjxs, instr, rs2_bits), @@ -624,6 +653,18 @@ fn parse_uncompressed_instruction(instr: u32) -> Instr { _ => Unknown { instr }, }, FMT_D => match (funct5(instr), rm(instr), rs2_bits(instr)) { + (F5_0, rounding, rs2_bits) => { + f_r_rm_2_instr!(Faddd, instr, rs2_bits, rounding) + } + (F5_1, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fsubd, instr, rs2_bits, rounding) + } + (F5_2, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fmuld, instr, rs2_bits, rounding) + } + (F5_3, rounding, rs2_bits) => { + f_r_rm_2_instr!(Fdivd, instr, rs2_bits, rounding) + } (F5_4, RM_0, rs2_bits) => f_r_instr!(Fsgnjd, instr, rs2_bits), (F5_4, RM_1, rs2_bits) => f_r_instr!(Fsgnjnd, instr, rs2_bits), (F5_4, RM_2, rs2_bits) => f_r_instr!(Fsgnjxd, instr, rs2_bits), diff --git a/src/risc_v/interpreter/src/parser/instruction.rs b/src/risc_v/interpreter/src/parser/instruction.rs index 512a9c530687..720153e4f38b 100644 --- a/src/risc_v/interpreter/src/parser/instruction.rs +++ b/src/risc_v/interpreter/src/parser/instruction.rs @@ -5,9 +5,12 @@ use std::fmt; -use crate::machine_state::{ - csregisters::CSRegister, - registers::{FRegister, XRegister}, +use crate::{ + interpreter::float::RoundingMode, + machine_state::{ + csregisters::CSRegister, + registers::{FRegister, XRegister}, + }, }; #[derive(Debug, PartialEq, Clone, Copy)] @@ -91,6 +94,34 @@ pub struct FRArgs { pub rd: FRegister, } +/// There are 6 supported rounding modes that an instruction may use. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum InstrRoundingMode { + Dynamic, + Static(RoundingMode), +} + +impl InstrRoundingMode { + /// Read the parsing mode from the byte given + pub fn from_rm(rm: u32) -> Option { + if rm == 0b111 { + Some(Self::Dynamic) + } else { + RoundingMode::try_from(rm as u64).map(Self::Static).ok() + } + } +} + +/// Floating-point R-type instruction, containing +/// rounding mode, and two input arguments. +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct FR2ArgsWithRounding { + pub rs1: FRegister, + pub rs2: FRegister, + pub rm: InstrRoundingMode, + pub rd: FRegister, +} + #[derive(Debug, PartialEq, Clone, Copy)] pub struct FStoreArgs { pub rs1: XRegister, @@ -217,6 +248,10 @@ pub enum Instr { Feqs(FCmpArgs), Fles(FCmpArgs), Flts(FCmpArgs), + Fadds(FR2ArgsWithRounding), + Fsubs(FR2ArgsWithRounding), + Fmuls(FR2ArgsWithRounding), + Fdivs(FR2ArgsWithRounding), Fmins(FRArgs), Fmaxs(FRArgs), Flw(FLoadArgs), @@ -232,6 +267,10 @@ pub enum Instr { Feqd(FCmpArgs), Fled(FCmpArgs), Fltd(FCmpArgs), + Faddd(FR2ArgsWithRounding), + Fsubd(FR2ArgsWithRounding), + Fmuld(FR2ArgsWithRounding), + Fdivd(FR2ArgsWithRounding), Fmind(FRArgs), Fmaxd(FRArgs), Fld(FLoadArgs), @@ -358,6 +397,10 @@ impl Instr { | Feqs(_) | Fles(_) | Flts(_) + | Fadds(_) + | Fsubs(_) + | Fmuls(_) + | Fdivs(_) | Fmins(_) | Fmaxs(_) | Flw(_) @@ -371,6 +414,10 @@ impl Instr { | Feqd(_) | Fled(_) | Fltd(_) + | Faddd(_) + | Fsubd(_) + | Fmuld(_) + | Fdivd(_) | Fmind(_) | Fmaxd(_) | Fld(_) @@ -632,6 +679,10 @@ impl fmt::Display for Instr { Feqs(args) => r_instr!(f, "feq.s", args), Fles(args) => r_instr!(f, "fle.s", args), Flts(args) => r_instr!(f, "flt.s", args), + Fadds(args) => r_instr!(f, "fadd.s", args), + Fsubs(args) => r_instr!(f, "fsub.s", args), + Fmuls(args) => r_instr!(f, "fmul.s", args), + Fdivs(args) => r_instr!(f, "fdiv.s", args), Fmins(args) => r_instr!(f, "fmin.s", args), Fmaxs(args) => r_instr!(f, "fmax.s", args), Flw(args) => i_instr_load!(f, "flw", args), @@ -647,6 +698,10 @@ impl fmt::Display for Instr { Feqd(args) => r_instr!(f, "feq.d", args), Fled(args) => r_instr!(f, "fle.d", args), Fltd(args) => r_instr!(f, "flt.d", args), + Faddd(args) => r_instr!(f, "fadd.d", args), + Fsubd(args) => r_instr!(f, "fsub.d", args), + Fmuld(args) => r_instr!(f, "fmul.d", args), + Fdivd(args) => r_instr!(f, "fdiv.d", args), Fmind(args) => r_instr!(f, "fmin.d", args), Fmaxd(args) => r_instr!(f, "fmax.d", args), Fld(args) => i_instr_load!(f, "fld", args), diff --git a/src/risc_v/interpreter/tests/test_suite_interpreter.rs b/src/risc_v/interpreter/tests/test_suite_interpreter.rs index 590602e1c61e..4429771e2085 100644 --- a/src/risc_v/interpreter/tests/test_suite_interpreter.rs +++ b/src/risc_v/interpreter/tests/test_suite_interpreter.rs @@ -125,7 +125,7 @@ test_case!(#[ignore], test_suite_rv64uc_p_rvc, "rv64uc-p-rvc"); test_case!(#[ignore], test_suite_rv64uc_v_rvc, "rv64uc-v-rvc"); // RV64-UD -test_case!(#[ignore], test_suite_rv64ud_p_fadd, "rv64ud-p-fadd"); +test_case!(test_suite_rv64ud_p_fadd, "rv64ud-p-fadd"); test_case!(test_suite_rv64ud_p_fclass, "rv64ud-p-fclass"); test_case!(test_suite_rv64ud_p_fcmp, "rv64ud-p-fcmp"); test_case!(#[ignore], test_suite_rv64ud_p_fcvt, "rv64ud-p-fcvt"); @@ -151,7 +151,7 @@ test_case!(#[ignore], test_suite_rv64ud_v_move, "rv64ud-v-move"); test_case!(#[ignore], test_suite_rv64ud_v_recoding, "rv64ud-v-recoding"); test_case!(#[ignore], test_suite_rv64ud_v_structural, "rv64ud-v-structural"); // RV64-UF -test_case!(#[ignore], test_suite_rv64uf_p_fadd, "rv64uf-p-fadd"); +test_case!(test_suite_rv64uf_p_fadd, "rv64uf-p-fadd"); test_case!(test_suite_rv64uf_p_fclass, "rv64uf-p-fclass"); test_case!(test_suite_rv64uf_p_fcmp, "rv64uf-p-fcmp"); test_case!(#[ignore], test_suite_rv64uf_p_fcvt, "rv64uf-p-fcvt"); -- GitLab