From ebee6f7dce48cdd54acb985bc223417684b2c88a Mon Sep 17 00:00:00 2001
From: Stuart Swales <stuart.swales@croftnuisk.co.uk>
Date: Mon, 22 Nov 2021 13:41:26 +0000
Subject: [PATCH] [535] fminf(x,y) / fmaxf(x,y) corrupt result for equal
 non-zero parameters

Detail:
  fminf(x,y) / fmaxf(x,y) corrupted the result when x==y and x!=0.0 due to
  ANDing/ORRing a single precision register with the high word of a double
  precision register pair when fixing up signs for mixed +/- 0 parameters
  in an analogous fashion to fmax/fmin (which are correct).

Version 6.11. Tagged as 'RISC_OSLib-6_11'
---
 VersionASM     | 12 ++++++------
 VersionNum     | 20 ++++++++++----------
 clib/s/cl_body | 28 ++++++++++++++++++++++------
 3 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/VersionASM b/VersionASM
index 7d4ce40..6c2e915 100644
--- a/VersionASM
+++ b/VersionASM
@@ -9,12 +9,12 @@
                         GBLS    Module_ApplicationDate
                         GBLS    Module_HelpVersion
                         GBLS    Module_ComponentName
-Module_MajorVersion     SETS    "6.10"
-Module_Version          SETA    610
+Module_MajorVersion     SETS    "6.11"
+Module_Version          SETA    611
 Module_MinorVersion     SETS    ""
-Module_Date             SETS    "13 Nov 2021"
-Module_ApplicationDate  SETS    "13-Nov-21"
+Module_Date             SETS    "22 Nov 2021"
+Module_ApplicationDate  SETS    "22-Nov-21"
 Module_ComponentName    SETS    "RISC_OSLib"
-Module_FullVersion      SETS    "6.10"
-Module_HelpVersion      SETS    "6.10 (13 Nov 2021)"
+Module_FullVersion      SETS    "6.11"
+Module_HelpVersion      SETS    "6.11 (22 Nov 2021)"
                         END
diff --git a/VersionNum b/VersionNum
index 3e41257..7166149 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,21 +1,21 @@
-/* (6.10)
+/* (6.11)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG        6.10
+#define Module_MajorVersion_CMHG        6.11
 #define Module_MinorVersion_CMHG
-#define Module_Date_CMHG                13 Nov 2021
+#define Module_Date_CMHG                22 Nov 2021
 
-#define Module_MajorVersion             "6.10"
-#define Module_Version                  610
+#define Module_MajorVersion             "6.11"
+#define Module_Version                  611
 #define Module_MinorVersion             ""
-#define Module_Date                     "13 Nov 2021"
+#define Module_Date                     "22 Nov 2021"
 
-#define Module_ApplicationDate          "13-Nov-21"
+#define Module_ApplicationDate          "22-Nov-21"
 
 #define Module_ComponentName            "RISC_OSLib"
 
-#define Module_FullVersion              "6.10"
-#define Module_HelpVersion              "6.10 (13 Nov 2021)"
-#define Module_LibraryVersionInfo       "6:10"
+#define Module_FullVersion              "6.11"
+#define Module_HelpVersion              "6.11 (22 Nov 2021)"
+#define Module_LibraryVersionInfo       "6:11"
diff --git a/clib/s/cl_body b/clib/s/cl_body
index ae7ad9a..8668fe8 100644
--- a/clib/s/cl_body
+++ b/clib/s/cl_body
@@ -1241,11 +1241,18 @@ fmaxf
         [ FloatingPointArgsInRegs
         STFS    f1, [sp, #-4]!
         STFS    f0, [sp, #-4]!
-        LDMIA   sp!, {r0-r1}
-        ]
-        AND     r0, r0, r1
+        LDMIA   sp!, {r0, r2} ; restore *narrowed* x & y to ARM regs
+        AND     r0, r0, r2    ; this works like fmax case as both are narrow
         STR     r0, [sp, #-4]!
         LDFS    f0, [sp], #4
+        |
+        ; EQ -> f0 (result) is still (narrowed) x from {r0,r1}
+        ; NB r0 and r2 are not narrow! (Sign.Expt.MantHi word of x and y respectively)
+        ; if x==y, then for fmaxf(-0,+0), return +0
+        EOR     r1, r0, r2          ; were signs of x and y mixed?
+        TST     r1, #1 :SHL: 31
+        MVFNES  f0, #0              ; if so, result := +0
+        ]
         Return  ,LinkNotStacked
 
 fcmpnanf
@@ -1290,13 +1297,22 @@ fminf
         [ FloatingPointArgsInRegs
         STFS    f1, [sp, #-4]!
         STFS    f0, [sp, #-4]!
-        LDMIA   sp!, {r0-r1}
-        ]
-        ORR     r0, r0, r2
+        LDMIA   sp!, {r0, r2} ; restore *narrowed* x & y to ARM regs
+        ORR     r0, r0, r2    ; this works like fmin case as both are narrow
         STR     r0, [sp, #-4]!
         LDFS    f0, [sp], #4
+        |
+        ; EQ -> f0 (result) is still (narrowed) x from {r0,r1}
+        ; if x==y, then for fminf(+0,-0), return -0
+        ; NB r0 and r2 are not narrow! (Sign.Expt.MantHi word of x and y respectively)
+        EOR     r1, r0, r2          ; were signs of x and y mixed?
+        TST     r1, #1 :SHL: 31
+        LDFNES  f0, =-0.0           ; if so, result := -0 (doesn't fit in immediate constant)
+        ]
         Return  ,LinkNotStacked
 
+        LTORG
+
 nearbyint
         [ :LNOT:FloatingPointArgsInRegs
         STMFD   sp!, {r0,r1}
-- 
GitLab