From 7ffa7667b6f31d27cda7c2c15a7e330055eb0385 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Mon, 29 Jul 2024 21:07:54 +0200 Subject: [PATCH] fixes concerning FMADD_S, FMSUB_S, FNMADD_S, and FNSUB_S mostly about ensuring correct sign --- softfloat/source/s_mulAddF32.c | 8 ++++++-- src/vm/fp_functions.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/softfloat/source/s_mulAddF32.c b/softfloat/source/s_mulAddF32.c index 805517c..94c21eb 100644 --- a/softfloat/source/s_mulAddF32.c +++ b/softfloat/source/s_mulAddF32.c @@ -92,11 +92,14 @@ float32_t goto infProdArg; } if ( expC == 0xFF ) { + // expC indicates special value if ( sigC ) { + //uiC is quiet NaN uiZ = 0; goto propagateNaN_ZC; } - uiZ = uiC; + //uiC is +- infinity + uiZ = (uiC & ~(1UL << 31)) | ((unsigned long)signC << 31); //set sign bit goto uiZ; } /*------------------------------------------------------------------------ @@ -209,12 +212,13 @@ float32_t /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zeroProd: - uiZ = uiC; + uiZ = (uiC & ~(1UL << 31)) | ((unsigned long)signC << 31); //set sign bit if ( ! (expC | sigC) && (signProd != signC) ) { completeCancellation: uiZ = packToF32UI( (softfloat_roundingMode == softfloat_round_min), 0, 0 ); + uiZ = (uiZ & ~(1UL << 31)) | ((unsigned long)(signC|signProd) << 31); //set sign bit } uiZ: uZ.ui = uiZ; diff --git a/src/vm/fp_functions.cpp b/src/vm/fp_functions.cpp index cad3b06..ad340b5 100644 --- a/src/vm/fp_functions.cpp +++ b/src/vm/fp_functions.cpp @@ -149,11 +149,17 @@ uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) { } uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) { + // Used values for op are: + // FMADD_S: 0b00 + // FMSUB_S: 0b01 + // FNMADD_S: 0b10 + // FNMSUB_S: 0b11 // op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)} softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_exceptionFlags = 0; float32_t res = softfloat_mulAddF32(v1, v2, v3, op & 0x1); - if(op > 1) + // Do not invert quiet NaN + if((op & 0b10) && (res.v != quiet_nan32)) res.v ^= 1ULL << 31; return res.v; }