From mboxrd@z Thu Jan 1 00:00:00 1970 From: hjl@lucon.org (H.J. Lu) To: shebs@cygnus.com (Stan Shebs) Cc: jtc@redback.com, gdb@sourceware.cygnus.com Subject: Re: x86 fpu Date: Thu, 21 Oct 1999 07:50:00 -0000 Message-id: <19991021145036.E76601B493@ocean.lucon.org> References: <199910210657.XAA08245@andros.cygnus.com> X-SW-Source: 1999-q4/msg00093.html > > > Date: Wed, 20 Oct 1999 23:06:00 -0700 (PDT) > From: hjl@lucon.org (H.J. Lu) > > [...] It is a pain for me to maintain my > private versions. But I hate to see the Linux people nowhere to > go for help. Do you really honestly believe that a new official > version should be made whenever a serious Linux related bug is > fixed or we have to live with the bug which mainly affects Linux? > > That's not necessarily a bad idea... If one were to look at which > platform has the largest number of GDB-using programmers these days, > it would most likely be GNU/Linux by far. Why can't the GDB release Please also remember that the GNU tools are the only ones GNU/Linux get. If they don't work for us, we have to find a workaround one way or the other. > schedule be adjusted to accommodate the majority of users? I am glad to see it is happening for gdb. Finally I can get rid of my Linux version of gdb. I wish I could say the same for other tools. BTW, I have sent in a patch for cplus-dem.c to the gcc patches mailing list. It is/will be used by some of GNU/Linux tools. However, I have a feeling that it will take forever to get accepted. > > I have been sending my patches to the appropriate people. But they > don't work only for Linux. My patches have to wait, but Linux cann't. > It is not that unusual to take a few months or more for my patches > to be installed. What do we do? > > This is the genesis of the situation. Patch submissions should be > acted upon promptly, whether to accept or reject. It's my > responsibility to see that this happens, and if I fail at that, > I'm not going to fault anyone for coming up with workarounds like > splinter versions. Sometimes, it takes a splinter version to get things done and we have to take the consequences. I am not proud of the Linux C library 5. I wish it had never happened. But without it, we may never have Linux nor glibc 2 today. > > I hope everybody agrees that patch turnaround has improved over the > past several months. It's still not where it should be; if you feel a > worthy patch is being ignored, please send me mail with lots of > capital letters and exclamation points, or call me on the phone at > +1 408 542 9678. I will send in a few patches after x86 fpu is resolved. > > I will work with everyone to merge my changes. But it doesn't mean > I will stop working for the Linux community. We have different > priorities. That is life. > > This should not be true however. I used to think this myself, until > RMS pointed out that since Linux is one of the official kernels for > the GNU system, GDB support for it ought to be a higher priority than > support for non-GNU systems. Of course, GDB is still free software > like always, and I still want to encourage people to contribute > improvements for non-GNU systems as well. > > Lately, Jim Blandy and Jim Kingdon have stepped up to the task of > making sure the FSF version of GDB is fully functional for GNU/Linux, > and there has been considerable progress, as witness the discussion of > x86 float support. Also, Scott Bambrough has been hard at work on > Netwinder (ARM) support, and Kevin Buettner is on PowerPC. At this > rate, I expect that the upcoming 5.0 release will be the version of > choice for GNU/Linux. First is glibc, now is gdb. What are the next? binutils and gcc? I am not holding my breath. Thanks. -- H.J. Lu (hjl@gnu.org) >From eliz@gnu.org Thu Oct 21 08:20:00 1999 From: Eli Zaretskii To: Mark Kettenis Cc: jtc@redback.com, jimb@cygnus.com, gdb@sourceware.cygnus.com Subject: Re: Unifying the x86 FPU register sets Date: Thu, 21 Oct 1999 08:20:00 -0000 Message-id: <199910211520.LAA21979@mescaline.gnu.org> References: <199910151716.MAA03441@zwingli.cygnus.com> <5mwvsjoyu0.fsf@jtc.redbacknetworks.com> <199910211332.PAA00729@delius.kettenis.local> X-SW-Source: 1999-q4/msg00094.html Content-length: 822 > Note that in `tm-go32.h' there is a > > #undef TARGET_LONG_DOUBLE_BIT > #define TARGET_LONG_DOUBLE_BIT 96 > > So DJGPP is already treating the 80-bit extended types as a 96-bit > type. Why, of course! ;-) That's because somebody noticed, a long time ago, that this is required in order to get 80-bit registers supported. > Then it will be very easy to support the i387 data registers as `long > doubles' on hosts that have an equivalent type, without the LD_387 > kludge that's now used by DJGPP and Linux/i386. I'm not sure. There's a related issue of whether the library supports long double in scanf and printf families of functions. (There's also the issue of the compiler support for long double, but it's a non-issue for DJGPP and Linux ;-) Would your suggestion handle all of these considerations? >From Grant.Edwards@comtrol.com Thu Oct 21 09:03:00 1999 From: Grant.Edwards@comtrol.com To: gdb@sourceware.cygnus.com Subject: RDI target issues Date: Thu, 21 Oct 1999 09:03:00 -0000 Message-id: <19991021110315.A3542@comtrol.com> X-SW-Source: 1999-q4/msg00095.html Content-length: 1431 I've been working on getting gdb 4.18 (arm-elf) to work with the rdi target. I've had to make some changes to the rdi library code from ARM (in the rdi-share directory): 1) Disable heartbeat functionality, since it makes the JTAG interface boxes from both ARM and EPI fall over.. 2) Fix the code that was throwing away error codes returned by the JTAG boxes with the "stopped" message. 3) Added a considerable amount of logging functionality (this still needs to be cleaned up and made run-timeconfigurable). I've also had to make changes to gdb code in remote-rdi.c:: 1) Make sure the ADP device is closed before attempting to open it. 2) Allow target options to be passed to Adp_OpenDevice. 3) Changed the way that log messages from remote are handled (this goes along with #3 above, and still needs work). 4) Disable automatic setting of breakpoints on interrupt vectors. Question: Change 4 only needs to happen if the target platform has ROM at address 0. Otherwise, (RAM ad address 0) the old behavior is probably best. How should this option be configured by the user? Right now, the parameters to the "target rdi" gdb command are just passed on to the Adp_OpenDevice routine from ARM. I could parse those options and strip out the ones I want to handle in remote-rdi.c before passing them on to the RDI library. Comments? -- Grant Edwards Grant.Edwards@comtrol.com >From kettenis@wins.uva.nl Thu Oct 21 09:13:00 1999 From: Mark Kettenis To: eliz@gnu.org Cc: jtc@redback.com, jimb@cygnus.com, gdb@sourceware.cygnus.com Subject: Re: Unifying the x86 FPU register sets Date: Thu, 21 Oct 1999 09:13:00 -0000 Message-id: <199910211613.SAA03931@delius.kettenis.local> References: <199910211504.LAA20217@mescaline.gnu.org> X-SW-Source: 1999-q4/msg00096.html Content-length: 1991 [ Sorry Eli, but I guess you know why you receive this message another time ;-)] Date: Thu, 21 Oct 1999 11:04:53 -0400 From: Eli Zaretskii < 5mwvsjoyu0.fsf@jtc.redbacknetworks.com > < 199910211332.PAA00729@delius.kettenis.local > Subject: Re: Unifying the x86 FPU register sets --text follows this line-- > Note that in `tm-go32.h' there is a > > #undef TARGET_LONG_DOUBLE_BIT > #define TARGET_LONG_DOUBLE_BIT 96 > > So DJGPP is already treating the 80-bit extended types as a 96-bit > type. Why, of course! ;-) That's because somebody noticed, a long time ago, that this is required in order to get 80-bit registers supported. Apparently the Linux people didn't notice it ;-). > Then it will be very easy to support the i387 data registers as `long > doubles' on hosts that have an equivalent type, without the LD_387 > kludge that's now used by DJGPP and Linux/i386. I'm not sure. There's a related issue of whether the library supports long double in scanf and printf families of functions. (There's also the issue of the compiler support for long double, but it's a non-issue for DJGPP and Linux ;-) Would your suggestion handle all of these considerations? Yes! The nice thing is that GDB already has all the code that is necessary to handle this. If the compiler doesn't support a 80/96-bit `long double' type, the registers are converted to ordinary doubles right away. Printing those should be no problem. If the compiler does support a 80/96-bit `long double' type, the registers are padded to 96-bits. Before printing, these are converted to the representation the host uses, taking in account endianness and other representation details. If the library on the host supports printing long double (PRINTF_HAS_LONG_DOUBLE) it is printed with full precision. If not, then the result is converted to double before printing. See valprint.c:print_floating() for details. Mark >From kettenis@wins.uva.nl Thu Oct 21 09:34:00 1999 From: Mark Kettenis To: gdb@sourceware.cygnus.com Cc: jtc@redback.com, jimb@cygnus.com, eliz@gnu.org, gdb-patches@sourceware.cygnus.com Subject: x86 FPU support: "info float" and `long double' Date: Thu, 21 Oct 1999 09:34:00 -0000 Message-id: <199910211634.SAA03952@delius.kettenis.local> X-SW-Source: 1999-q4/msg00097.html Content-length: 17926 OK, here is my attempt at implementing the "info float" comment and prividing proper long double support without any hacks. Once this is in we should remove the Linux-specific TARGET_{EXTRACT|STORE}_FLOATING hooks that were introduced in findvar.c, and try to find a better solution for TARGET_ANALYZE_FLOATING. The output for "info float" is almost identical to DJGPP. The FP registers are printed in physical order with "=>" indicating the top of stack. Printing the opcode mnemonic is not so easy. I looked at libopcode, but I could not find an appropriate entry-point. Anyway, the output looks like: (gdb) info float status 0x3800: flags 0000; top 7; control 0x37f: 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER LOS; last FP instruction: opcode 0xdd05; pc 0x23:0x8048495; operand 0x2b:0x8048f04 regno tag msb lsb value => 7: valid 4000c90fdaa22168c000 3.141592653589793116 6: empty 3ff7d100000000000000 0.006378173828125 5: empty 40098000000000000000 1024 4: empty 3fff8000000000000000 1 3: empty 3fff8000000000000000 1 2: empty 3ffb9d8909ff2e48e8c0 0.076921537494659423997 1: empty 3ffbdaf3e93361992eb3 0.10691053569844352396 0: empty 00000000000000000000 0 (gdb) Suggestions for improvement are welcome! I don't know if this stuff is ready for inclusion yet. Given the size of the patch a copyright assignment is probably needed. I'll try to assign past and future changes as soon as possible. If Jim is still making changes to the register file layout, I'll keep track of his changes and resend the patch. Mark 1999-10-21 Mark Kettenis * i387-tdep.c: Strip PARAMS. (i387_float_info): New function. (i387_register_virtual_type): New function. (i387_register_convert_to_virtual, i387_register_convert_to_raw): New functions. (i387_extract_floating, i387_store_floating): Removed. * config/i386/tm-i386.h (TARGET_LONG_DOUBLE_BIT, TARGET_LONG_DOUBLE_FORMAT): New definitions. TARGET_ANALYZE_FLOATING: Moved here from config/i386/tm-linux.h. (i387_register_virtual_type): New declaration. (REGISTER_VIRTUAL_TYPE): Call i387_register_virtual_type to get data type of FP data registers. (i387_to_double, double_to_i387): Removed declarations. (i387_register_convert_to_virtual, i387_register_convert_to_raw): New declarations. (REGISTER_CONVERT_TO_VIRTUAL): Let i387_register_convert_to_virtual handle the conversion. (REGISTER_CONVERT_TO_RAW): Let i387_register_convert_to_raw handle the conversion. [HAVE_I387_REGS] (i387_float_info): New declaration. [HAVE_I387_REGS] (FLOAT_INFO): New define. * config/i386/tm-linux.h (TARGET_LONG_DOUBLE_BIT, TARGET_EXTRACT_FLOATING, TARGET_STORE_FLOATING, REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW, REGISTER_VIRTUAL_TYPE): Remove definitions. (TARGET_ANALYZE_FLOATING): Moved to config/i386/tm-i386.h. (i387_extract_floating, i387_store_floating): Remove declarations. (LD_I387): Do not define. Index: gdb/gdb/i387-tdep.c =================================================================== RCS file: /var/cvsroot/gdb/gdb/i387-tdep.c,v retrieving revision 1.1.1.4 diff -u -r1.1.1.4 i387-tdep.c --- gdb/gdb/i387-tdep.c 1999/10/02 19:51:09 1.1.1.4 +++ gdb/gdb/i387-tdep.c 1999/10/21 15:57:28 @@ -1,5 +1,5 @@ /* Intel 387 floating point stuff. - Copyright (C) 1988, 1989, 1991, 1998 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1991, 1998, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -26,34 +26,31 @@ #include "gdbcore.h" #include "floatformat.h" -void i387_to_double PARAMS ((char *, char *)); -void double_to_i387 PARAMS ((char *, char *)); +static void print_387_control_bits (unsigned int control); +static void print_387_status_bits (unsigned int status); -static void print_387_control_bits PARAMS ((unsigned int control)); -static void print_387_status_bits PARAMS ((unsigned int status)); + +/* FIXME: Eliminate the next two functions when we have the time to + change all the callers. */ -/* FIXME: Eliminate these routines when we have the time to change all - the callers. */ +void i387_to_double (char *from, char *to); +void double_to_i387 (char *from, char *to); void -i387_to_double (from, to) - char *from; - char *to; +i387_to_double (char *from, char *to) { floatformat_to_double (&floatformat_i387_ext, from, (double *) to); } void -double_to_i387 (from, to) - char *from; - char *to; +double_to_i387 (char *from, char *to) { floatformat_from_double (&floatformat_i387_ext, (double *) from, to); } + static void -print_387_control_bits (control) - unsigned int control; +print_387_control_bits (unsigned int control) { switch ((control >> 8) & 3) { @@ -108,9 +105,10 @@ local_hex_string (control & 0xe080)); } +/* FIXME: Make this static once we have converted all i386 targets to + use the GDB register file. */ void -print_387_control_word (control) - unsigned int control; +print_387_control_word (unsigned int control) { printf_filtered ("control %s:", local_hex_string(control & 0xffff)); print_387_control_bits (control); @@ -118,8 +116,7 @@ } static void -print_387_status_bits (status) - unsigned int status; +print_387_status_bits (unsigned int status) { printf_unfiltered (" flags %d%d%d%d; ", (status & 0x4000) != 0, @@ -140,53 +137,141 @@ } } +/* FIXME: Make this static once we have converted all i386 targets to + use the GDB register file. */ void -print_387_status_word (status) - unsigned int status; +print_387_status_word (unsigned int status) { printf_filtered ("status %s:", local_hex_string (status & 0xffff)); print_387_status_bits (status); puts_unfiltered ("\n"); } -#ifdef LD_I387 -int -i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr) +/* Print out the i387 floating poin state. */ +void +i387_float_info (void) { - if (len == TARGET_LONG_DOUBLE_BIT / 8) + unsigned int fctrl; + unsigned int fstat; + unsigned int ftag; + unsigned int fcs; + unsigned int fcoff; + unsigned int fds; + unsigned int fdoff; + unsigned int fop; + int fpreg; + int top; + + read_register_gen (FCTRL_REGNUM, (char *) &fctrl); + read_register_gen (FSTAT_REGNUM, (char *) &fstat); + read_register_gen (FTAG_REGNUM, (char *) &ftag); + read_register_gen (FCS_REGNUM, (char *) &fcs); + read_register_gen (FCOFF_REGNUM, (char *) &fcoff); + read_register_gen (FDS_REGNUM, (char *) &fds); + read_register_gen (FDOFF_REGNUM, (char *) &fdoff); + read_register_gen (FOP_REGNUM, (char *) &fop); + + print_387_status_word (fstat); + print_387_control_word (fctrl); + printf_unfiltered ("last FP instruction: "); + printf_unfiltered ("opcode %s; ", + local_hex_string (fop ? (fop | 0xd800) : 0)); + printf_unfiltered ("pc %s:", local_hex_string (fcs)); + printf_unfiltered ("%s; ", local_hex_string (fcoff)); + printf_unfiltered ("operand %s", local_hex_string (fds)); + printf_unfiltered (":%s\n", local_hex_string (fdoff)); + + top = ((fstat >> 11) & 7); + + printf_unfiltered ("regno tag msb lsb value\n"); + for (fpreg = 7; fpreg >= 0; fpreg--) { - if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) - { - DOUBLEST retval; + unsigned char raw[FPU_REG_RAW_SIZE]; + DOUBLEST value; + int i; + + printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg); - memcpy (dretptr, addr, sizeof (retval)); + switch ((ftag >> (fpreg * 2)) & 3) + { + case 0: + printf_unfiltered ("valid "); + break; + case 1: + printf_unfiltered ("zero "); + break; + case 2: + printf_unfiltered ("special "); + break; + case 3: + printf_unfiltered ("empty "); + break; } - else - floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr); - return 1; + read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw); + + for (i = 9; i >= 0; i--) + printf_unfiltered ("%02x", raw[i]); + + floatformat_to_doublest (&floatformat_i387_ext, raw, &value); + +#ifdef PRINTF_HAS_LONG_DOUBLE + printf_unfiltered (" %.20Lg\n", (long double) value); +#else + printf_unfiltered (" %.20g\n", (double) value); +#endif } - else - return 0; } -int -i387_store_floating (PTR addr, int len, DOUBLEST val) + +/* Return the "standard" data type of data in the FPU data registers. + We use `long double' if the host has them in a representation + equivalent with the i387 extended format, and `double' otherwise. */ +struct type * +i387_register_virtual_type (void) { - if (len == TARGET_LONG_DOUBLE_BIT / 8) - { - /* This `if' may be totally stupid. I just put it in here to be - absolutely sure I'm preserving the semantics of the code I'm - frobbing, while I try to maintain portability boundaries; I - don't actually know exactly what it's doing. -JimB, May 1999 */ - if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) - memcpy (addr, &val, sizeof (val)); - else - floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr); +#ifdef HAVE_LONG_DOUBLE + if (sizeof (long double) == (TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT)) + return builtin_type_long_double; +#endif + return builtin_type_double; +} - return 1; +/* Convert REGNUM, which raw contents are stored in FROM to "standard" + data type TYPE and store the result into TO. */ +void +i387_register_convert_to_virtual (int regnum, struct type *type, + char *from, char *to) +{ +#ifdef HAVE_LONG_DOUBLE + if (type == builtin_type_long_double) + { + memset (to, 0, REGISTER_VIRTUAL_SIZE (regnum)); + memcpy (to, from, REGISTER_RAW_SIZE (regnum)); } + else +#endif + { + double val; + floatformat_to_double (&floatformat_i387_ext, from, &val); + floatformat_from_double (&floatformat_ieee_double_little, &val, to); + } +} + +/* Convert the "standard" data type TYPE stored in FROM and store the + result in REGNUM whose raw contents live at TO. */ +void +i387_register_convert_to_raw (struct type *type, int regnum, + char *from, char *to) +{ +#ifdef HAVE_LONG_DOUBLE + if (type == builtin_type_long_double) + memcpy (to, from, REGISTER_RAW_SIZE (regnum)); else - return 0; +#endif + { + double val; + floatformat_to_double (&floatformat_ieee_double_little, from, &val); + floatformat_from_double (&floatformat_i387_ext, &val, to); + } } -#endif /* LD_I387 */ Index: gdb/gdb/config/i386/tm-i386.h =================================================================== RCS file: /var/cvsroot/gdb/gdb/config/i386/tm-i386.h,v retrieving revision 1.1.1.7 diff -u -r1.1.1.7 tm-i386.h --- gdb/gdb/config/i386/tm-i386.h 1999/10/20 10:44:05 1.1.1.7 +++ gdb/gdb/config/i386/tm-i386.h 1999/10/21 15:08:56 @@ -1,5 +1,5 @@ /* Macro definitions for GDB on an Intel i[345]86. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -222,43 +222,75 @@ /* Largest value REGISTER_VIRTUAL_SIZE can have. */ #define MAX_REGISTER_VIRTUAL_SIZE 16 +/* Although the i387 has a 80-bit extended floating point type, almost + all systems supported by GCC use 96-bit and extra padding for + alignment. The exception seems to be OSF/1, where `long double' is + the same as `double', but there is no OSF/1 support in GDB. */ +#define TARGET_LONG_DOUBLE_BIT 96 +#define TARGET_LONG_DOUBLE_FORMAT &floatformat_i387_ext + +/* Detect NaNs for the i387 extended floating point format. + FIXME: This is not very well hought out and should be replaced by + NaN classification based on floatformat.h, fully integrated in GDB. */ +#define TARGET_ANALYZE_FLOATING \ + do \ + { \ + if (len == 10) \ + { \ + unsigned expon; \ + \ + low = extract_unsigned_integer (valaddr, 4); \ + high = extract_unsigned_integer (valaddr + 4, 4); \ + expon = extract_unsigned_integer (valaddr + 8, 2); \ + \ + nonnegative = ((expon & 0x8000) == 0); \ + is_nan = ((expon & 0x7fff) == 0x7fff) \ + && ((high & 0x80000000) == 0x80000000) \ + && (((high & 0x7fffffff) | low) != 0); \ + } \ + else \ + is_nan = 0; \ + } \ + while (0) + /* Return the GDB type object for the "standard" data type of data in register N. Perhaps si and di should go here, but potentially they could be used for things other than address. */ +/* Return the "standard" data type of data in the FPU data registers. + We use `long double' if the host has them in a representation + equivalent with the i387 extended format, and `double' otherwise. */ +extern struct type *i387_register_virtual_type (void); + #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_FP_REGNUM(N) ? i387_register_virtual_type () \ : IS_SSE_REGNUM(N) ? builtin_type_v4sf \ : builtin_type_int) + +/* Convert the 80-bit FPU data registers to the "standard" data type + and back. */ +extern void i387_register_convert_to_virtual (int regnum, struct type *type, + char *from, char *to); +extern void i387_register_convert_to_raw (struct type *type, int regnum, + char *from, char *to); + +#undef REGISTER_CONVERT_TO_VIRTUAL +#define REGISTER_CONVERT_TO_VIRTUAL(regnum, type, from, to) \ + i387_register_convert_to_virtual ((regnum), (type), (from), (to)) + +#undef REGISTER_CONVERT_TO_RAW +#define REGISTER_CONVERT_TO_RAW(type, regnum, from, to) \ + i387_register_convert_to_raw ((type), (regnum), (from), (to)) -/* REGISTER_CONVERTIBLE(N) is true iff register N's virtual format is - different from its raw format. Note that this definition assumes - that the host supports IEEE 32-bit floats, since it doesn't say - that SSE registers need conversion. Even if we can't find a - counterexample, this is still sloppy. */ -#define REGISTER_CONVERTIBLE(n) (IS_FP_REGNUM (n)) - -/* Convert data from raw format for register REGNUM in buffer FROM - to virtual format with type TYPE in buffer TO. */ -extern void i387_to_double (char *, char *); - -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ -{ \ - double val; \ - i387_to_double ((FROM), (char *)&val); \ - store_floating ((TO), TYPE_LENGTH (TYPE), val); \ -} - -extern void double_to_i387 (char *, char *); - -#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ -{ \ - double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ - double_to_i387((char *)&val, (TO)); \ -} +/* Print out the i387 floating point state. */ +#ifdef HAVE_I387_REGS +extern void i387_float_info (void); +#define FLOAT_INFO { i387_float_info (); } +#endif + /* Store the address of the place in which to copy the structure the subroutine will return. This is called from call_function. */ Index: gdb/gdb/config/i386/tm-linux.h =================================================================== RCS file: /var/cvsroot/gdb/gdb/config/i386/tm-linux.h,v retrieving revision 1.1.1.5 diff -u -r1.1.1.5 tm-linux.h --- gdb/gdb/config/i386/tm-linux.h 1999/10/20 10:44:05 1.1.1.5 +++ gdb/gdb/config/i386/tm-linux.h 1999/10/21 15:09:22 @@ -1,5 +1,5 @@ /* Definitions to target GDB to GNU/Linux on 386. - Copyright 1992, 1993 Free Software Foundation, Inc. + Copyright 1992, 1993, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -41,59 +41,6 @@ #define LOW_RETURN_REGNUM 0 /* holds low four bytes of result */ #define HIGH_RETURN_REGNUM 2 /* holds high four bytes of result */ - -/* This should probably move to tm-i386.h. */ -#define TARGET_LONG_DOUBLE_BIT 80 - -#if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386) -/* The host and target are i386 machines and the compiler supports - long doubles. Long doubles on the host therefore have the same - layout as a 387 FPU stack register. */ -#define LD_I387 - -extern int i387_extract_floating (PTR addr, int len, long double *dretptr); -extern int i387_store_floating (PTR addr, int len, long double val); - -#define TARGET_EXTRACT_FLOATING i387_extract_floating -#define TARGET_STORE_FLOATING i387_store_floating - -#define TARGET_ANALYZE_FLOATING \ - do \ - { \ - unsigned expon; \ - \ - low = extract_unsigned_integer (valaddr, 4); \ - high = extract_unsigned_integer (valaddr + 4, 4); \ - expon = extract_unsigned_integer (valaddr + 8, 2); \ - \ - nonnegative = ((expon & 0x8000) == 0); \ - is_nan = ((expon & 0x7fff) == 0x7fff) \ - && ((high & 0x80000000) == 0x80000000) \ - && (((high & 0x7fffffff) | low) != 0); \ - } \ - while (0) - -#undef REGISTER_CONVERT_TO_VIRTUAL -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ -{ \ - long double val = *((long double *)FROM); \ - store_floating ((TO), TYPE_LENGTH (TYPE), val); \ -} - -#undef REGISTER_CONVERT_TO_RAW -#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ -{ \ - long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ - *((long double *)TO) = val; \ -} - -/* Return the GDB type object for the "standard" data type - of data in register N. */ -#undef REGISTER_VIRTUAL_TYPE -#define REGISTER_VIRTUAL_TYPE(N) \ - (IS_FP_REGNUM (N) ? builtin_type_long_double : builtin_type_int) - -#endif /* The following works around a problem with /usr/include/sys/procfs.h */ #define sys_quotactl 1 >From hjl@lucon.org Thu Oct 21 10:13:00 1999 From: hjl@lucon.org (H.J. Lu) To: kettenis@wins.uva.nl (Mark Kettenis) Cc: gdb@sourceware.cygnus.com, jtc@redback.com, jimb@cygnus.com, eliz@gnu.org, gdb-patches@sourceware.cygnus.com Subject: Re: x86 FPU support: "info float" and `long double' Date: Thu, 21 Oct 1999 10:13:00 -0000 Message-id: <19991021171307.87FEC1B493@ocean.lucon.org> References: <199910211634.SAA03952@delius.kettenis.local> X-SW-Source: 1999-q4/msg00098.html Content-length: 2762 > (gdb) info float > status 0x3800: flags 0000; top 7; > control 0x37f: 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER LOS; > last FP instruction: opcode 0xdd05; pc 0x23:0x8048495; operand 0x2b:0x8048f04 > regno tag msb lsb value > => 7: valid 4000c90fdaa22168c000 3.141592653589793116 > 6: empty 3ff7d100000000000000 0.006378173828125 > 5: empty 40098000000000000000 1024 > 4: empty 3fff8000000000000000 1 > 3: empty 3fff8000000000000000 1 > 2: empty 3ffb9d8909ff2e48e8c0 0.076921537494659423997 > 1: empty 3ffbdaf3e93361992eb3 0.10691053569844352396 > 0: empty 00000000000000000000 0 > (gdb) > > Suggestions for improvement are welcome! > My current gdb has (gdb) info float st0: 0x3ffed6d6d6d6d6d6d800 Empty Normal 0.8392156862745098200307 st1: 0x00000000000000000000 Empty Zero 0 st2: 0x00000000000000000000 Empty Zero 0 st3: 0x00000000000000000000 Empty Zero 0 st4: 0x00000000000000000000 Empty Zero 0 st5: 0x3ffe8000000000000000 Empty Normal 0.5 st6: 0x4003b000000000000000 Empty Normal 22 st7: 0x4003b000000000000000 Empty Normal 22 fctrl: 0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER LOS; fstat: 0x0000 flags 0000; top 0; ftag: 0xffff fip: 0x00000000 fcs: 0x00000000 fopoff: 0x00000000 fopsel: 0x0000 It is also the same as yours. However, I have an extra field for stack register: st0: 0x3ffed6d6d6d6d6d6d800 Empty Normal 0.8392156862745098200307 ^^^^^^ It shouldn't be hard to add. I am enclosing the relevant code here. H.J. ---- expon = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) + 8, 2); sign = expon & 0x8000; expon &= 0x7fff; ms = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) + 4, 4); ls = extract_signed_integer (raw_regs + REGISTER_BYTE (regnum), 4); norm = ms & 0x80000000; if ( expon == 0 ) { if ( ms | ls ) { /* Denormal or Pseudodenormal. */ if ( norm ) puts_unfiltered ("Pseudo "); else puts_unfiltered ("Denorm "); } else { /* Zero. */ puts_unfiltered ("Zero "); } } else if ( expon == 0x7fff ) { /* Infinity, NaN or unsupported. */ if ( (ms == 0x80000000) && (ls == 0) ) { puts_unfiltered ("Infty "); } else if ( norm ) { if ( ms & 0x40000000 ) puts_unfiltered ("QNaN "); else puts_unfiltered ("SNaN "); } else { puts_unfiltered ("Unsupp "); } } else { /* Normal or unsupported. */ if ( norm ) puts_unfiltered ("Normal "); else puts_unfiltered ("Unsupp "); }