diff options
Diffstat (limited to 'gdb/i387-tdep.c')
-rw-r--r-- | gdb/i387-tdep.c | 281 |
1 files changed, 235 insertions, 46 deletions
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 253bc26..0621bdf 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -22,13 +22,16 @@ #include "frame.h" #include "inferior.h" #include "language.h" +#include "value.h" #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 PARAMS ((unsigned int control)); +static void print_387_status_bits PARAMS ((unsigned int status)); + /* FIXME: Eliminate these routines when we have the time to change all the callers. */ @@ -48,95 +51,281 @@ double_to_i387 (from, to) floatformat_from_double (&floatformat_i387_ext, (double *) from, to); } -void -print_387_control_word (control) +static void +print_387_control_bits (control) unsigned int control; { - printf_unfiltered ("control %s: ", local_hex_string (control)); - printf_unfiltered ("compute to "); switch ((control >> 8) & 3) { case 0: - printf_unfiltered ("24 bits; "); + puts_unfiltered (" 24 bit; "); break; case 1: - printf_unfiltered ("(bad); "); + puts_unfiltered (" (bad); "); break; case 2: - printf_unfiltered ("53 bits; "); + puts_unfiltered (" 53 bit; "); break; case 3: - printf_unfiltered ("64 bits; "); + puts_unfiltered (" 64 bit; "); break; } - printf_unfiltered ("round "); switch ((control >> 10) & 3) { case 0: - printf_unfiltered ("NEAREST; "); + puts_unfiltered ("NEAR; "); break; case 1: - printf_unfiltered ("DOWN; "); + puts_unfiltered ("DOWN; "); break; case 2: - printf_unfiltered ("UP; "); + puts_unfiltered ("UP; "); break; case 3: - printf_unfiltered ("CHOP; "); + puts_unfiltered ("CHOP; "); break; } if (control & 0x3f) { - printf_unfiltered ("mask:"); + puts_unfiltered ("mask"); if (control & 0x0001) - printf_unfiltered (" INVALID"); + puts_unfiltered (" INVAL"); if (control & 0x0002) - printf_unfiltered (" DENORM"); + puts_unfiltered (" DENOR"); if (control & 0x0004) - printf_unfiltered (" DIVZ"); + puts_unfiltered (" DIVZ"); if (control & 0x0008) - printf_unfiltered (" OVERF"); + puts_unfiltered (" OVERF"); if (control & 0x0010) - printf_unfiltered (" UNDERF"); + puts_unfiltered (" UNDER"); if (control & 0x0020) - printf_unfiltered (" LOS"); - printf_unfiltered (";"); + puts_unfiltered (" LOS"); + puts_unfiltered (";"); } printf_unfiltered ("\n"); if (control & 0xe080) - warning ("reserved bits on: %s\n", + warning ("\nreserved bits on: %s", local_hex_string (control & 0xe080)); } void -print_387_status_word (status) +print_387_control_word (control) + unsigned int control; +{ + printf_filtered ("control %s:", local_hex_string(control & 0xffff)); + print_387_control_bits (control); + puts_unfiltered ("\n"); +} + +static void +print_387_status_bits (status) unsigned int status; { - printf_unfiltered ("status %s: ", local_hex_string (status)); - if (status & 0xff) - { - printf_unfiltered ("exceptions:"); - if (status & 0x0001) - printf_unfiltered (" INVALID"); - if (status & 0x0002) - printf_unfiltered (" DENORM"); - if (status & 0x0004) - printf_unfiltered (" DIVZ"); - if (status & 0x0008) - printf_unfiltered (" OVERF"); - if (status & 0x0010) - printf_unfiltered (" UNDERF"); - if (status & 0x0020) - printf_unfiltered (" LOS"); - if (status & 0x0040) - printf_unfiltered (" FPSTACK"); - printf_unfiltered ("; "); - } - printf_unfiltered ("flags: %d%d%d%d; ", + printf_unfiltered (" flags %d%d%d%d; ", (status & 0x4000) != 0, (status & 0x0400) != 0, (status & 0x0200) != 0, (status & 0x0100) != 0); + printf_unfiltered ("top %d; ", (status >> 11) & 7); + if (status & 0xff) + { + puts_unfiltered ("excep"); + if (status & 0x0001) puts_unfiltered (" INVAL"); + if (status & 0x0002) puts_unfiltered (" DENOR"); + if (status & 0x0004) puts_unfiltered (" DIVZ"); + if (status & 0x0008) puts_unfiltered (" OVERF"); + if (status & 0x0010) puts_unfiltered (" UNDER"); + if (status & 0x0020) puts_unfiltered (" LOS"); + if (status & 0x0040) puts_unfiltered (" STACK"); + } +} + +void +print_387_status_word (status) + unsigned int status; +{ + printf_filtered ("status %s:", local_hex_string (status & 0xffff)); + print_387_status_bits (status); + puts_unfiltered ("\n"); +} + +void +i387_print_register (raw_regs, regnum) + char *raw_regs; + int regnum; +{ + unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; + unsigned long val; + int j, sign, special; + unsigned swd, tags, expon, top, norm, ls, ms; + char string[12]; + +#if (FPREG_RAW_SIZE != 10) +#error "Bad FPREG_RAW_SIZE" +#endif + + printf_filtered ("%8.8s: ", REGISTER_NAME (regnum)); + if (regnum < FPDATA_REGNUM) + { + val = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum), 4); + if ( (regnum < FPSTART_REGNUM + 3) || + (regnum == FPSTART_REGNUM + 6) ) + /* Don't print the un-modifiable bytes. */ + sprintf(string, "0x%04x", val & 0xffff); + else + sprintf(string, "0x%08x", val); + + printf_unfiltered ("%10.10s", string); - printf_unfiltered ("top %d\n", (status >> 11) & 7); + if (regnum == FPCONTROL_REGNUM) + print_387_control_bits (val); + else if (regnum == FPSTATUS_REGNUM) + print_387_status_bits (val); + } + else + { + /* An FPU stack register. */ + if ( REGISTER_RAW_SIZE (regnum) != FPREG_RAW_SIZE ) + error ("GDB bug: i387-tdep.c (i387_print_register): wrong size for FPU stack register"); + + /* Put the data in the buffer. No conversions are ever necessary. */ + memcpy (virtual_buffer, raw_regs + REGISTER_BYTE (regnum), + FPREG_RAW_SIZE); + + swd = extract_signed_integer (raw_regs + REGISTER_BYTE (FPSTATUS_REGNUM), + 4); + top = (swd >> 11) & 7; + tags = extract_signed_integer (raw_regs + REGISTER_BYTE (FPTAG_REGNUM), + 4); + + puts_unfiltered ("0x"); + for (j = 0; j < FPREG_RAW_SIZE; j++) + printf_unfiltered ("%02x", + (unsigned char)raw_regs[REGISTER_BYTE (regnum) + + FPREG_RAW_SIZE - 1 - j]); + + puts_unfiltered (" "); + special = 0; + switch ((tags >> (((regnum - FPDATA_REGNUM + top) & 7) * 2)) & 3) + { + case 0: puts_unfiltered ("Valid "); break; + case 1: puts_unfiltered ("Zero "); break; + case 2: puts_unfiltered ("Spec "); + special = 1; + break; + case 3: puts_unfiltered ("Empty "); break; + } + + expon = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) + + FPREG_RAW_SIZE - 2, 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 "); + } + + val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0, + gdb_stdout, 0, + 1, 0, Val_pretty_default); + } + puts_filtered ("\n"); +} + +void i387_float_info(void) +{ + char raw_regs [REGISTER_BYTES]; + int i; + + for (i = FPSTART_REGNUM; i <= FPEND_REGNUM; i++) + read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i)); + + for (i = FPSTART_REGNUM; i <= FPEND_REGNUM; i++) + i387_print_register (raw_regs, i); +} + +#ifdef LD_I387 +int +i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr) +{ + if (len == TARGET_LONG_DOUBLE_BIT / 8) + { + if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT) + { + DOUBLEST retval; + + memcpy (dretptr, addr, sizeof (retval)); + } + else + floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr); + + return 1; + } + else + return 0; +} + +int +i387_store_floating (PTR addr, int len, DOUBLEST val) +{ + 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); + + return 1; + } + else + return 0; } +#endif /* LD_I387 */ |