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



Sorry for the late start, but you guys caught me off-guard: this issue
lays dormant for such a long time that I began reading the messages
once every other day, then every third day...

Anyway, these comments are only by inspection of Jim's patch for now
(I will try to actually build GDB with these changes later this week):

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).

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"?

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.

4) Several comments to Jim's message and the discussion that ensued:

  Jim> Since we're doing our own layout, we have the opportunity to set
  Jim> aside the weird packing used by the FSAVE instruction, and have the
  Jim> registers hold something more meaningful.  Thus, I've split out the
  Jim> instruction segment selector and the opcode bits, previously
  Jim> different bitfields of the $fcs register, into two separate
  Jim> registers.

I think we need to discuss this a bit.  Please note that the FP
registers are printed by GDB in two different ways: one is with the
command "info float", the other with "info all-registers".  I agree
that "info float" should present the information in a manner suitable
for debugging numerical code, i.e., the opcode should be separated
from the instruction selector, and its missing 5 bits should be added
to the printed value; but I think that "info all-registers" should
print the registers *exactly* as the CPU stores them.

Of course, this comment is only relevant to how we _print_ the
registers, not how we maintain them internally.

  Jim> The instruction (code) segment and offset are $fcs and $fcoff.
  Jim> The data operand       segment and offset are $fds and $fdoff.

I suggest $fcseg and $fcoff, $fdseg and $fdoff, instead.  People who
work a lot with seg:off pairs will recofnise `seg', but not `s'.

  Jim> I have not included support for the MMX or 3DNow! registers.
  Jim> [...]  I want to leave taht for a separate discussion.

I agree that MMX etc. is a separate problem.  I would think that they
deserve a separate command, e.g. "info mmx", just like the FP
registers do.

(FWIW, the DJGPP debug infrastructure already supports MMX, it just
isn't exposed to GDB, since GDB doesn't yet know about MMX.)

  Jim> We could make the control registers (except $fdoff and $fcoff)
  Jim> sixteen-bit values.  But that makes more work for platforms that do
  Jim> use FSAVE's 32-bit format; I assume those are the majority.

AFAIK, FSAVE does use 32 bits to store the control, status and tag
words, but the high 16 bits are undefined.  Isn't it dangerous to copy
all 32 bits to GDB's structures?  The DJGPP version doesn't copy the
high 16 bits from the buffer stored by FSAVE; if other platforms do
that as well, we already have, in effect, 16-bit control registers.

  Mark> For now, GDB on the Hurd will happily display what's in the
  Mark> reserved bits that follow the control, status, and tag word
  Mark> and the operand pointer segment selector in the data structure
  Mark> used by FSAVE and FRESTOR

I don't think this is right.  A user should see only the bits that are
defined by the CPU spec.  For all we know, the rest might be random
junk.

The DJGPP version displays 16 bits only for these registers.

  Jim> [...] the new SSE FXSAVE and FXRSTOR instructions save state in
  Jim> a different format, incompatible with FSAVE and FRSTOR, so
  Jim> either the OS interfaces will be changing, or the old ones will
  Jim> be emulated by code which changes from day to day.

There's another possibility: to use FXSAVE/FXRSTOR only for commands
that handle the SSE XMMi registers, and leave the current code for the
rest.  That way, we don't need to bother about reconciling the two
formats.

  Mark> So Intel has come up with yet another set of special purpose
  Mark> instructions that diddle with the floating point stuff?

Not only FXSAVE uses a different layout of the saved state, it also
does NOT perform the equivalent of FINIT.  In other words, it saves
the state without changing it, so you don't need to FXRSTOR right
after it, in case you need to preserve the state.

  Jim> I'm curious what Linux decides to do with the P-III support.

I'm confused--why is this relevant?  Are you talking about changes
that could affect how ptrace lays out the FP registers?  If not, what
do we care about Linux support of Pentium III?

  Mark> What remains to be written is the function that prints the
  Mark> output for the "info float" command.

  Jim> I'm easy to please here, but Eli Zaretskii had opinions on how
  Jim> this ought to work

I suggest to look at the thread we had discussing this back then.  If
memory serves, I posted a suggestion for the format of "info float",
based on Bill Metzenthen's code originally written for i387-tdep.c.

And let's not forget that "info all-registers" also prints the FP
registers, but in a different form.


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