This is the mail archive of the
gdb@sourceware.cygnus.com
mailing list for the GDB project.
Re: Unifying the x86 FPU register sets
I agree that the floating-point stuff in tm-linux.h is not the way it
should be. Yes, the way LD_I387 and the conversion stuff are defined
isn't correct. But for now, we should focus on getting tm-i386.h the
way we all want it. If we do that right, then tm-linux.h will be
straightforward to fix.
I'm having a hard time following a lot of the discussion about
floating-point formats. Here is my present understanding of
how things work; please correct me if I say something wrong.
There are three forms floating-point values can take on as they pass
through GDB:
- the register file form
- the `struct value' form
- the host DOUBLEST form
The register file form should be bit-for-bit identical with the way
the processor stores them, because the register file's role is to be a
direct reflection of the processor's state. The REGISTER_RAW_SIZE
macro gives the number of bytes a floating-point value occupies in
this form. GDB has no macro describing the types of registers in the
register file.
GDB uses the `struct value' form for variable values, intermediate
values in expression evaluation, and so on. REGISTER_VIRTUAL_TYPE
gives the type of this form; REGISTER_CONVERTIBLE,
REGISTER_CONVERT_TO_VIRTUAL, and REGISTER_CONVERT_TO_RAW control the
conversion between the register file form and this form, done by
value_of_register, value_from_register, and value_assign.
GDB converts a `struct value' to the host DOUBLEST form whenever it
actually wants to operate on a floating-point value. This conversion
is controlled by {TARGET,HOST}_LONG_DOUBLE_FORMAT and
TARGET_{EXTRACT,STORE}_FLOATING, and carried out by functions like
value_as_double, unpack_double, extract_floating, and store_floating.
(This last conversion is controversial, since it loses information;
ideally, GDB would perform the operations in the target's format,
using some software implementation of IEEE floating point arithmetic.)
It's worth noting that the first conversions, to and from the `struct
value' form, never need to be lossy, because `struct value' can hold
the value in raw target format. REGISTER_VIRTUAL_TYPE just needs to
correctly describe the registers.
So, here's my understanding of folks' suggestions about tm-i386.h:
- REGISTER_VIRTUAL_TYPE should be some type from tm-i387.c, dedicated
to describing FPU registers. That way, it's not dependent on today's
compiler's interpretation of `long double'.
- REGISTER_VIRTUAL_TYPE should be 12 bytes long, and
REGISTER_CONVERT_TO_{VIRTUAL,RAW} should simply account for the
position of the 10-byte value within the 12-byte space.
It makes me a little uncomfortable to have REGISTER_VIRTUAL_TYPE
specify a 12-byte size, while floatformat_i387_ext is a ten-byte
format, but I think it should work fine.
- {TARGET,HOST}_LONG_DOUBLE_{FORMAT,BITS} should be defined as
appropriate in the right tm-*.h and xm-*.h files, not in tm-i386.h.
The latter doesn't know what compiler you're using, and so can't say
how long its types are.
The implications carry on to Linux as follows:
- Once those definitions are corrected in tm-linux.h, the
TARGET_{EXTRACT,STORE}_FLOATING macros will never be used, because
the earlier clauses in extract_floating and store_floating will
apply, so we can delete the TARGET_{EXTRACT,STORE}_FLOATING
definitions from tm-linux.h.
- But tm-linux.h is the only target in GDB that defines them, so we
can remove all references to them from GDB completely.
It looks like Mark's patch has already done this. I'll take a look.