Port-vax archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Thoughts about IEEE floating point (-ish) on vax
Hi all, and a good saturday morning,
I thought I should describe how I was thinking of implementing IEEE
floating point to make it reasonable fast for common programs. First a
VERY long description, then a few points that are for discussion :-)
-------
At first; here is a brief overview what differs between vax and ieee
floating point:
* +Inf/-Inf: vax do not have infinity
* +NaN/-NaN: vax do have "illegal number" which traps.
Not really NaN.
* Vax do not have subnormal numbers.
* IEEE have a round, guard and sticky bit in calculations.
Vax only have two guard bits.
* Vax exponent bias is (for F-float) 128, IEEE (for single) 127.
* Vax hidden bit is 0.5, IEEE is 1.
That is the basics. Now getting to how it may look bit-wise.
The number of bits in F- and G-float are the same as in IEEE754 single
and double, and the IEEE754 format ("interchange format") allows for
endian-specific layouts, so using the existing F/G-float formats as IEEE
formats should be OK (using the PDP_ENDIAN layout).
We note that the difference in bias and mantissa is a factor of 4.0.
So; what happens if we just consider a vax float to be an IEEE float?
* For add and sub it works just as well; since there is no
dependency in these ops what the bias is.
* For mul the result must be multiplied by 4.0.
* For div the result must be divided by 4.0.
This is for virtually all normal cases where floating point is used.
But - the quirky parts of the IEEE standard is still there. To handle
those we must check for inf/nan/subnormal before and after all floating
point instructions.
These are active when the exponent has either all bits set or all bits
zero. so, this must be checked both before and after the fp instructions.
Simplest way to do this would be to (as I can think of):
* tell the compiler that floating point instructions must have
their arguments in r0 + r2, return value in r0, r4 clobbered.
* Replace the operation with something like "jsb ieee_add"
* In ieee_add, do something like this (for a single):
# check for obscure input
bicw3 $0x807f,r0,r4 # extract exponent
jeql fix_float # exp == 0 then special handling
xorw2 $0x807f,r4 # all exponent bits set?
jeql fix_float # Yes, special handling
...do the same for the other input
addf2 r2,r0
# check output. Can be skipped if input is to another
# instructions input
...
rsb
* To detect underflow in calculations the underflow trap bit
should always be set (overflow cannot be disabled). In this
way subnormals would be found during calculations and handled
correct by catching the floating point faults.
fix_float is a routine that do not get called unless there is one of the
ieee-specific quirks involved (so, like "slow-path" for floats :-) ).
The rounding modes required by the C standard (except for tonearest)
cannot be easily implemented, and regarding tonearest: There is a
potential edge-case rounding error that may occur due to the difference
in extra bits, but such precision mathematics that would get any problem
out of this is unlikely to ever occur on a vax.
The status bits required can be easily implemented except for the
inexact bit.
-------- Bottom line. Comments below.
- The IEEE standard gives the format of the floating point number as the
"interchange format". I haven't found what it actually means, and
whether it is OK to use another format in some circumstances? (being
able to use the vax reserved fp could ease the implimentation). Note
that the NetBSD common code expects the interchange format.
- Skipping the checks for the IEEE quirks would replace the call with
just the floating point instruction(s). Maybe a flag to the compiler
for this?
- Using D-float for all evaluations could help with the calculations and
missing precision bits (and be fully compliant) but requires a separate
handling of the exponent (adding a few extra instructions for this). I
looked at this but it seemed to get too much overhead.
- It would be possible to do the same thing by using vax H-float to get
IEEE 128-bit floating point (as long double). Unsure if it is worth it,
but quite some VAX archs implemented H-float in hardware.
- As of now I suggested to use the native vax layout in memory of
floating point (pdp11-style), which is OK based on the standard. But if
there is a reason for it then some rotl/movl could be added to get
"true" little-endian layout in memory. NetBSD do not have pdp-endian
support in the common code, but it is probably trivial to add it (like
big- and little-endian).
-------------
So, that is all for now :-)
-- R
Home |
Main Index |
Thread Index |
Old Index