Re: [rfc] Add some more floatformat types ....

Mark Kettenis
2001-08-17T06:08:00Z

Date: Thu, 16 Aug 2001 23:09:46 -0400
From: Andrew Cagney <ac131313@cygnus.com>

> Andrew Cagney <ac131313@cygnus.com> writes:
>
>
>> > The attached adds the floatformats:
>> >
>> > floatformat_i387_ext80;
>> > floatformat_i387_ext96;
>> >
>> > Explicitly sized x86 float formats.
>> >
>> > Depending on where/how it is stored,
>> > an i386 extended could use 80 (10 bytes)
>> > or 96 (12 bytes).
>
>
> Andrew, I thought I (implicitly) raised some objections to this
> change. See
>
> http://sources.redhat.com/ml/gdb/2001-07/msg00401.html

I am thinking of this as a separate but related patch.
Here I'm only trying to define all known ways that a floating point
value can be stored in memory.

That's fine, but I don't think we should introduce more types than we
absolutely need. And I think your patch does introduce too much new
types. I also think that when we cut down the number of
floating-point memory layouts we don't need the digits appended to them.

> To clarify things a bit: The ISA (that stands for Istruction Set
> Architecture doesn't it) defines a single 80-bit extended floating
> point format. On top of that floating point format most ABI's build a
> a 96-bit extended floating point type (e.g. GCC's `long double'). I'd
> like GDB to somehow maintain this concept, by *not* introducing the
> floatformat_i387_ext80 and floatformat_i387_ext96 types you propose.
> Instead we should make the distinction at the builtin_type_* level.
> By making the 80-bit and 96-bit builtin_type_* variants share the same
> underlying floatformat_* variable, we can easiliy check whether two
> floating point formats on the ABI level share the same encoding on the
> ISA level.

I think floatformat is something that exactly describes how an ISA
stores a floating-point value in memory. Remember, GDB stores register
values in memory.

Right!

The IA-64, for instance, has an 82 bit floating-point register. That
register is always represented in memory as 128 bits. Consequently, my
proposal includes ia64_ext128 and not ia64_ext82.

So we only need a single floatformat_ia64_ext. Why not keep the
floatformat_ia64_ext that we already have in ia64-tdep.c and move it
to ../libiberty/floatformat.c?

Similarly, the ARM has an 80 bit floating point register. That value is
stored in memory as using 96 bits ordered as either big or
littlebyte-bigword endian. The extra 16 bits are squeezed into the
middle of that memory value. Hence, arm_ext_big and
arm_ext_littlebyte_bigword. (I should probably make those ext96_...?)

So indeed we need those two different descriptions for the ARM.

Looking at the i387, I'd tend to suspect that it has been assuming a few
too many things. How often, for instance does the code sequence:

/* clear the entire 96 bit buffer. */
memset (size of type);
/* now store the float in the first 80 bits. */
doublest_to_floatformat (i387_ext);

appear? I think this code just happening to work because i387 is a
little endian architecture. All other targets (especially big endian
ones) have instead used a float-format that exactly described the full
96 bits of memory (big endian ones have little choice in this matter :-).

The i386/i387 ISA always stores values in memory as an 80-bit
quantity. All floating point instructions are defined to operate on
80-bit memory operands. As far as the ISA concerned there are no
96-bit or 128-bit floating point types. That's why I think we
shouldn't introduce the floatformat_i387_ext96 type you're proposing,
and just keep the floatformat_i387_ext we already have. I think
pretending that there are several different ways to store an extended
floating point number, would be wrong.

The confusion is caused by the dominant C ABI where `sizeof (long
double)' is 12. That's why we define TARGET_LONG_DOUBLE_BITS to 96.
That's what the coding fragment you see above is all about. It is
perfectly possible to create a compiler on the i386 where `sizeof
(long double)' would be 10. In fact there is a PASCAL compiler that
does exactly that. But this doesn't change the fact that the
underlying floating point layout is the same 80-bit format defined by
the ISA.

Looking in more detail at the i387/i386. I think, eventually, the
following changes can be made:

register_virtual_type(fp) return a type that specifies i387_ext80. This
exactly describes the contents of the floating-point register buffer.

I would simply introduce the builtin_type_i387_ext for the 80-bit
floating point type and keep builtin_type_long_double for the 96-bit
floating point type, both based on floatformat_i387_ext.
register_virtual_type would then indeed return builtin_type_i387_ext
for the floating-point registers.

register_convert_to/from_virtual() use the floatformat conversions to
convert robustly convert between the registers i387_ext80 and the
requested float-format (typically i387_ext96)

Yep.

floatformat for long-double on an i387 be set to i387_ext96.

I'd rather leave things as they are now.

For the short term, the floatformat code could also be tweeked to
recognize things like ext80 and ext96 as equivalent (provided things are
padded correctly). Someone might even get carried away and tweek it to
recognize ieee_double_big as byte swapped ieee_double_little ....

Hmm. The relevant IEEE standard leaves some things undfined, such as
details about denormals and NaNs, and I think that simply byte
swapping could lead to numbers that the host and/or target doesn't
understand.

Mark