hercules-390 / hyperion

Hercules 390
Other
252 stars 68 forks source link

Softfloat 2b NaN propagation inconsistent with IBM z/Arch PoP #132

Closed srorso closed 8 years ago

srorso commented 8 years ago

This issue has been confirmed by testing the DIVIDE instruction, but other instructions use the same Softfloat code for NaN propagation.

Operations involving one or two NaNs go through softfloat_propagateNaNxxx, where xxx is replaced by the precision of the NaN(s) being propagated.

In all cases, if a signalling NaN is selected for return, it is converted to a quiet NaN. This is consistent with z/Arch PoP -10.

z/Arch PoP (SA22-7832-10) rules if either or both A and B are NaNs and IEEE Xi off (FPC0.0).

Each instruction with the potential to have NaNs as operands has a separate table in the PoP, but the tables boil down to the same result:

If A is SNaN, return QNaN(A) Elseif B is SNaN, return QNaN(B) Elseif A is QNaN, return A Else return B (By this point A is not a NaN so B must be)

In tabluar form:

                B       B        B
               SNaN    QNaN    Not NaN
A SNaN          A       A        A 
A QNaN          B       A        A
A Not NaN       B       B       N/A

Softfloat 2b and 3a non-SSE NaN results if either or both A and B are NaNs:

If A and B are SNaN, return QNaN(A) or QNaN(B), whichever has the larger fraction. (IBM z/Arch PoP requires QNaN(A) to be returned) If A is SNaN and B is QNaN, return B (IBM z/Arch PoP requires QNaN(A) to be returned) Else if A is QNaN, return A else return B. (IBM z/Arch PoP requires QNaN(B) to be returned if B is an SNaN)

Softfloat 3a 32-bit SSE and 64-bit results if either or both A and B are NaNs:

If A is SNaN, return QNaN(A) Elseif A is NaN, return A (IBM z/Arch PoP requires QNaN(B) to be returned if B is an SNaN) Else return B

It is not clear that this is an error in Softfloat. NaN propagation may be one part of the IEEE-754-2008 specification that has implementation options or is not specific as to how NaNs should be propagated. The IBM z/Arch PoP does not cite IEEE-754-2008 in its description of NaN propagation. And I am not an IEEE member, so I do not have access to the specification.

It would not be difficult to modify Softfloat 2b or 3a to be consistent with IBM NaN propagation, but I'm loathe to modify 3a if I can help it; I would like as pure a Softfloat 3a as I can get. Modification of instruction emulation in ieee.c would not be difficult either.

I will think about this and I welcome feedback and suggestions.

ghost commented 8 years ago

On 31 May 2016, at 15:18, srorso notifications@github.com wrote:

… but I'm loathe to modify 3a if I can help it; I would like as pure a Softfloat 3a as I can get. …

could not agree more ! congratulations for the wonderful job, anyway enrico

srorso commented 8 years ago

This is definitely not an error in Softfloat. Even when two versions of Softfloat provide different NaN propagation results.

Section 6.2.3 NaN Propagation on p.35 of the IEEE-754-2008 standard says:

If two or more inputs are NaN, then the payload of the resulting NaN should be identical to the payload of one of the input NaNs if representable in the destination format. This standard does not specify which of the input NaNs will provide the payload. [Emphasis added]

So, for Softfloat 3a, we will have to modify the NaN propagation routines in Softfloat (in a separate directory) or code around the issue in ieee.c

A correction to Softfloat 2b will not be much work--even less if John H. already did one. :-)

With thanks to Fish for finding a copy of the standard.

jphartmann commented 8 years ago

Make it two, but the double case is still giving me grief. As it is, I have done what hacks to softfloat that are needed not to rebuild the world if I change something in softfloats.

Fish: I've sent you a number of mails recently to softdevlabs for which I've had no reaction. Spam filter?

On 06/02/2016 07:18 PM, srorso wrote:

even less if John H. already did one. :-

jphartmann commented 8 years ago

watch:

 dumpStorageReversed(&a, sizeof(a), "a");
 dumpStorageReversed(&b, sizeof(b), "b");
 logmsg("a nan %d b nan % a snan %d b snan %d\n",
    aIsNaN, bIsNaN ,aIsSignalingNaN , bIsSignalingNaN );

a: 000000 7ffc2000 00000000 b: 000000 7ff83000 00000000 a nan 1 b nan 1 a snan 0 b snan 0

I'd say that b is a signalling NaN and a is a quiet one.

If I'm right on this, there is definitely a problem in float64_is_signaling_nan in SoftFloat-specialise, but the way it is written, I haven't the foggiest.

Anyone have an Idea?

srorso commented 8 years ago

I do....I am sorry to say.

First, a and b above are QNaNs. In float64, 1 bit of sign, 11 bits of biased exponent, completing the first three nibbles. The next bit is the Quiet bit, 1=quiet. If zero, then any bit on in the rest of the fraction makes it an SNaN (if all bits were off, then it would be infinity).

DDB/DDBR failed in test case five because of my coding error in the loop: the hand-coded LA instruction at 0x700 was 41200004, and it should have been 41200005. No result was calculated for the fifth test case.

line   377: Storage at R:0000000000000480 compare mismatch.  DDB/DDBR NaN 5/8
... Want: 7FF83000 00000000 7FF83000 00000000
... Have: 7FF84000 00000000 7FF84000 00000000

Expect a commit. And then I'll mod Softfloat 2b NaN propagation (three routines) to conform to PoP.

Best Regards, Steve Orso

srorso commented 8 years ago

I see John's recent commit d1dabb includes conforming NaN propagation to PoP. But I cannot build:

Warning C4005 'LITTLEENDIAN': macro redefinition Hercules_VS2012 C:\Program Files\Windows Kits\10\include\10.0.10586.0\um\winsock2.h 1030

Aw, nuts.

jphartmann commented 8 years ago

Having looked at SoftFloat, I am left with a feeling that most of the processors Hyperion supports have hardware that is ieee conformant for float and double types (though this was no doubt not the case when SoftFloat was written).

I can see that NaN handling may need handholding to conform to PoO, but an add in general ought to map directly to the float type with suitable compiler options or #defines. That should speed up binary floating point significantly, except for 128 bit.

Has anyone researched this?

Fish-Git commented 8 years ago

As it is, I have done what hacks to softfloat that are needed not to rebuild the world if I change something in softfloats.

Which wasn't quite done correctly, but no worries; I managed to straigten it out. :)

Fish: I've sent you a number of mails recently to softdevlabs for which I've had no reaction. Spam filter?

Nope. I received them. Two (a2c and Running a test from home) didn't really need to be replied to IMO, so I didn't bother to.

The last one (Softfloat-specialize) I replied to just now.

I receive a LOT of email from people and I'm working on a LOT of different things so I may not immediately reply to emails that are sent to me.

If an email is urgent and needs an immediate response then just say so in the email or subject line.

Cool?

Fish-Git commented 8 years ago

But I cannot build: [...] Aw, nuts.

Fixed by commit 38c248b62041fab2b47a8dc66e967fd4c0769a4a.

Fish-Git commented 8 years ago

Has anyone researched this?

Not that I know of.

jphartmann commented 8 years ago

https://gcc.gnu.org/wiki/FloatingPointMath says that -mfpmath=sse -msse2 gives you ieee compliant float and doubles.

I made a signalling NaN (-fsignaling-nans) and added to it and got a quiet NaN result. It also makes me an INF when I add to the largest number.

I have not looked into signals for signalling NaN. It does not seem to be enabled by default since I got the quiet NaN result. I don't think it would make the implementation simpler. -frounding-math did not seem to make a difference.

So it looks like this could be useful. It still leaves the extended precision to be dealt with.

jphartmann commented 8 years ago

https://software.intel.com/sites/default/files/article/326703/fp-control-2012-08.pdf

srorso commented 8 years ago

Successfully built (thanks, Fish); ran test case with good results (thanks, John).

The PDF is fascinating....thanks for finding it.