This is the mail archive of the gdb@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Unifying the x86 FPU register sets



> 1) Comment no.1:
> 
> + #define FIRST_FPU_CTRL_REGNUM 24
> + #define FCTRL_REGNUM 24	        /* FPU control word */
> + #define FPC_REGNUM   24		/* old name for FCTRL_REGNUM */
> + #define FSTAT_REGNUM 25		/* FPU status word */
> + #define FTAG_REGNUM  26		/* FPU register tag word */
> + #define FCS_REGNUM   27		/* FPU instruction's code segment selector
> 
> Why does this define an old name for the FP control register, but not
> for the rest?  If back-compatibility (a Good Idea, IMHO), then let's
> be consistent.  tm-go32.h has these:
> 
> #define FPCWD_REGNUM FPC_REGNUM
> #define FPSWD_REGNUM 25		/* 80387 status register */
> #define FPTWD_REGNUM 26		/* 80387 tag register */
> #define FPIPO_REGNUM 29		/* 80387 instruction pointer offset reg */
> #define FPIPS_REGNUM 27		/* 80387 instruction pointer selector reg */
> #define FPOOS_REGNUM 30		/* 80387 operand pointer offset reg */
> #define FPOPS_REGNUM 28		/* 80387 operand pointer selector reg */
> 
> However, if DJGPP is the only platform which defines anything beyond
> FPC_REGNUM, then we may stop bothering about the rest (DJGPP itself
> doesn't use any of the rest, even though they are defined).

The patch is somewhat deceptive.  I didn't _add_ FPC_REGNUM; I
_retained_ it.  The old tm-i386.h #defined it too, so deleting it
would break targets for which we have no active maintainers.

Keep in mind that the goal is not to eliminate tm-go32.h and the
others; I expect each target will always need to make some tweaks to
the base definition provided by tm-i386.h.

(Does that answer the question?  Not sure...)


> 2) Comment no.2:
>   
> ! #define REGISTER_VIRTUAL_TYPE(N)				\
> !   (((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM)	\
> !    ? lookup_pointer_type (builtin_type_void)			\
> !    : IS_FP_REGNUM(N) ? builtin_type_double			\
> !    : IS_SSE_REGNUM(N) ? builtin_type_v4sf			\
> !    : builtin_type_int)
> 
> Why are FP registers treated as type `double'?  x87 uses long double,
> not double, and tm-go32.h says this:
> 
> #define REGISTER_VIRTUAL_TYPE(N) \
>   ((N < FP0_REGNUM) ? builtin_type_int : \
>    (N < FPC_REGNUM) ? builtin_type_long_double : builtin_type_int)
> 
> i386-tdep.c clearly uses 10 bytes when it initializes
> i386_register_byte[], so I gather that other x86 targets also support
> the full 80-bit width of FP registers, right?  Don't we want all the
> 80 bits in "info float"?

The 80-bit floating point format goes all the way back to the
8087, I'm pretty sure.  So every target with an FPU uses the 80-bit
floating-point format.

When you're cross-debugging an x86 target, the host may not have long
double, or may not use the same long double format.  In this case,
GDB stores the full 80 bits in the register file (that's the "raw"
format), but converts it to a host double when it needs to produce a
`struct value' object.  libiberty/floatformat.c has routines for
ripping apart floats and reassembling them, which GDB uses.

The generic `info float' implementation should do the best it can,
without requiring that host == target.

What happens at present is this:
- tm-i386.h provides everything you need to get (lossy) float
  handling on any host.
- the more specific i386/tm-*.h files might use further knowledge
  about the host to get better behavior, by redefining the
  REGISTER_VIRTUAL_TYPE, REGISTER_CONVERTIBLE, etc. macros.

The tm-linux.h header does this now --- look for LD_I387.

Perhaps the ideal solution would be for configure to determine which
floating-point formats the host supports, and #define some symbol like
HOST_X86_EXTENDED_REAL_TYPE.  Then, tm-i386.h could use that as the
virtual type for FPU registers.

But this is an issue which can be dealt with separately.  For now, I
think it's fine for the more specific i386/tm-*.h files to override
REGISTER_VIRTUAL_TYPE in order to get the full precision.

> 3) Comment no.3:
> 
> ! 
> ! #define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO)	\
> ! {								\
> !   double val;							\
> !   i387_to_double ((FROM), (char *)&val);			\
> !   store_floating ((TO), TYPE_LENGTH (TYPE), val);		\
> ! }
> 
> Same here: long double is not supported.
> 
> Also, if REGISTER_CONVERTIBLE(REGNUM) is zero, you could simply use
> memcpy, it is faster.
> 
> This also applies to REGISTER_CONVERT_TO_RAW.

If REGISTER_CONVERTIBLE(i) is zero, you should never call
REGISTER_CONVERT_TO_VIRTUAL or REGISTER_CONVERT_TO_RAW on the value of
that register.  I see that go32-nat.c does this, but that's incorrect.

I'll reply to the other stuff in a separate message.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]