View Issue Details

IDProjectCategoryView StatusLast Update
0038832FPCRTLpublic2021-05-05 20:21
ReporterBenjamin Rosseaux Assigned ToFlorian  
PrioritynormalSeverityminorReproducibilityhave not tried
Status resolvedResolutionfixed 
Platformx86_64OSWindows 
Product Version3.3.1 
Fixed in Version3.3.1 
Summary0038832: x86_64 mathu.inc missing handling of softfloat_rounding_mode and softfloat_exception_mask
DescriptionThe x86_64 mathu.inc (and some of the other targets also, which depends on softfloat-partly-fallback-functions) is missing handling of softfloat_rounding_mode and softfloat_exception_mask. Patch is attached at least for x86_64, and a testcase.

Following code is failing in the moment, since it raises a div-by-zero exception, although it shouldn't:

var x:double;

...

 SetExceptionMask([exInvalidOp,exDenormalized,exZeroDivide,exOverflow,exUnderflow,exPrecision]);
 x:=0;
 writeln(ln(x));
 writeln(1/x);
 
TagsNo tags attached.
Fixed in Revision49328
FPCOldBugId
FPCTarget-
Attached Files

Activities

Benjamin Rosseaux

2021-04-30 21:48

reporter  

mathu.inc.patch (539 bytes)   
Index: x86_64/mathu.inc
===================================================================
--- x86_64/mathu.inc	(revision 49298)
+++ x86_64/mathu.inc	(working copy)
@@ -209,6 +209,7 @@
 {$else}
   Result:=TFPURoundingMode((SSECSR shr 13) and 3);
 {$endif FPC_HAS_TYPE_EXTENDED}
+  softfloat_rounding_mode:=RoundMode;
 end;
 
 function GetPrecisionMode: TFPUPrecisionMode;
@@ -248,6 +249,7 @@
 {$else}
   Result:=TFPUExceptionMask((SSECSR shr 7) and $3F);
 {$endif FPC_HAS_TYPE_EXTENDED}
+  softfloat_exception_mask:=Mask;
 end;
 
 
mathu.inc.patch (539 bytes)   
test.pas (348 bytes)   
program Math1;

{$mode delphi}{$H+}

uses
 {$IFDEF UNIX}
 cthreads,
 {$ENDIF}
 Classes,
 Math
 { you can add units after this };

var x:double;
begin
 SetExceptionMask([exInvalidOp,exDenormalized,exZeroDivide,exOverflow,exUnderflow,exPrecision]);
 x:=0;
 writeln(ln(x));
 writeln(1/x);
 writeln;
 readln;
end.                   
test.pas (348 bytes)   

Sergei Gorelkin

2021-05-01 01:32

developer   ~0130691

In the past (r27182), I had compelely removed all softfloat stuff from i386 and x86_64 code.
The idea was that 'partially-softfloat' functions execute appropriate FPU instructions if they need to raise an exception, and then exception is handled using the hardware mask. In particular, Calculating ln(0) should indeed execute division by zero. Why this is not masked is a diffrent question.

Benjamin Rosseaux

2021-05-01 01:59

reporter   ~0130692

I think because softfloat_exception_mask isn't set by SetExceptionMask.

Benjamin Rosseaux

2021-05-01 02:22

reporter   ~0130694

In the x86_64\mathu.inc is

  {$ifndef FPC_SYSTEM_HAS_LN}
    {$define FPC_SYSTEM_HAS_LN}
    function fpc_ln_real(d : ValReal) : ValReal;compilerproc;
.,.

by a "{$ifdef FPC_HAS_TYPE_EXTENDED}" arounded

where FPC_HAS_TYPE_EXTENDED isn't defined on the Win64 target, due to the wrong misconception that one may not use the x87 with x86_64 code under Windows. This was only once in early non-final reports and docs etc., where Microsoft has retracted this in the final release of the first 64-bit capable x86_64 Windows version, so that x87 is also allowed with x86_64 code. Quote from Wikipedia:

"Early reports claimed that the operating system scheduler would not save and restore the x87 FPU machine state across thread context switches. Observed behavior shows that this is not the case: the x87 state is saved and restored, except for kernel mode-only threads (a limitation that exists in the 32-bit version as well). The most recent documentation available from Microsoft states that the x87/MMX/3DNow! instructions may be used in long mode, but that they are deprecated and may cause compatibility problems in the future"

And a quote from Angor Fgor from his Calling conventions manual:

"There has been widespread confusion about whether 64-bit Windows allows the use of the floating point registers ST(0)-ST(7) and the MM0 - MM7 registers that are aliased upon these. One early technical document found at Microsoft's website says x87/MMX registers are unavailable to Native Windows64 applications" (Rich Brunner: Technical Details Of Microsoft® Windows® For The AMD64 Platform, Dec. 2003). An AMD document says: "64-bit Microsoft Windows does not strongly support MMX and 3Dnow! instruction sets in the 64-bit native mode" (Porting and Optimizing Multimedia Codecs for AMD64 architecture on Microsoft® Windows®, July 21, 2004). A document in Microsoft's MSDN says: "A caller must also handle the following issues when calling a callee: [...] Legacy Floating-Point Support: The MMX and floating-point stack registers (MM0-MM7/ST0-ST7) are volatile. That is, these legacy floating-point stack registers do not have their state preserved across context switches" (MSDN: Kernel-Mode Driver Architecture: Windows DDK: Other Calling Convention Process Issues. Preliminary, June 14, 2004; February 18, 2005)."

"This description is nonsense because it confuses saving registers across function calls and saving registers across context switches. Some versions of the Microsoft assembler ml64 (e.g. v. 8.00.40310) gives the following message when attempts are made to use floating point registers in 64 bit mode: "error A2222: x87 and MMX instructions disallowed; legacy FP state not saved in Win64". However, a public discussion forum quotes the following answers from Microsoft engineers regarding this issue: "From: Program Manager in Visual C++ Group, Sent: Thursday, May 26, 2005 10:38 AM. It does preserve the state. It's the DDK page that has stale information, which I've requested it to be changed. Let them know that the OS does preserve state of x87 and MMX registers on context switches." and "From: Software Engineer in Windows Kernel Group, Sent: Thursday, May 26, 2005 11:06 AM. For user threads the state of legacy floating point is preserved at context switch. But it is not true for kernel threads. Kernel mode drivers can not use legacy floating point instructions."

"The issue has finally been resolved with the long overdue publication of a more detailed ABI for x64 Windows in the form of a document entitled "x64 Software Conventions", well hidden in the bin directory (not the help directory) of some compiler packages. This document says: "The MMX and floating-point stack registers (MM0-MM7/ST0-ST7) are preserved across context switches. There is no explicit calling convention for these registers. The use of these registers is strictly prohibited in kernel mode code." The same text has later appeared at the Microsoft website [4]."
 

Therefore I find it slightly stupid that fpc does not define FPC_HAS_TYPE_EXTENDED on the Win64 target because of this misconception/misblief from the past.

nanobit

2021-05-01 06:55

reporter   ~0130697

Last edited: 2021-05-01 09:46

View 4 revisions

This topic is not new, see:
https://bugs.freepascal.org/view.php?id=37905

The essence is that Win ABI never changed their support (at least not in a relevant way, and kernel mode restriction was not new), but other developments contributed to the loss of 80 bit: the dominant adoption of SSE (but without 80bit), lack of support in several other compilers (Microsoft Compiler, Delphi 64), softfloat's potential for more precisions (128bit), probably shortage of developer resources to support "all" together.

Note: It could be useful to test x87 (FPU) on ARM64:
Win10 has emulator for x86-apps (since 201x) and x64-apps (since 2020) on ARM64.
If Windows fully supports Win ABI as it claims, then emulation should also include x87 on ARM64.

Florian

2021-05-02 20:51

administrator   ~0130725

> Therefore I find it slightly stupid that fpc does not define FPC_HAS_TYPE_EXTENDED on the Win64 target because of this misconception/misblief from the past.

It is a good thing because if it is defined, a lot of operations are carried out by the x87 fpu (due to excess precision) which is much slower than the sse. Just compare the code generated for linux and for win64.

Issue History

Date Modified Username Field Change
2021-04-30 21:48 Benjamin Rosseaux New Issue
2021-04-30 21:48 Benjamin Rosseaux File Added: mathu.inc.patch
2021-04-30 21:48 Benjamin Rosseaux File Added: test.pas
2021-05-01 01:32 Sergei Gorelkin Note Added: 0130691
2021-05-01 01:59 Benjamin Rosseaux Note Added: 0130692
2021-05-01 02:22 Benjamin Rosseaux Note Added: 0130694
2021-05-01 06:55 nanobit Note Added: 0130697
2021-05-01 09:43 nanobit Note Edited: 0130697 View Revisions
2021-05-01 09:45 nanobit Note Edited: 0130697 View Revisions
2021-05-01 09:46 nanobit Note Edited: 0130697 View Revisions
2021-05-02 20:51 Florian Note Added: 0130725
2021-05-05 20:21 Florian Assigned To => Florian
2021-05-05 20:21 Florian Status new => resolved
2021-05-05 20:21 Florian Resolution open => fixed
2021-05-05 20:21 Florian Fixed in Version => 3.3.1
2021-05-05 20:21 Florian Fixed in Revision => 49328
2021-05-05 20:21 Florian FPCTarget => -