diff options
Diffstat (limited to 'gdb/i386v4-nat.c')
-rw-r--r-- | gdb/i386v4-nat.c | 88 |
1 files changed, 84 insertions, 4 deletions
diff --git a/gdb/i386v4-nat.c b/gdb/i386v4-nat.c index 10802cb..056ea7f 100644 --- a/gdb/i386v4-nat.c +++ b/gdb/i386v4-nat.c @@ -142,17 +142,65 @@ fill_gregset (gregsetp, regno) #endif /* HAVE_GREGSET_T */ -#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) +#if defined (HAVE_FPREGSET_T) /* Given a pointer to a floating point register set in /proc format (fpregset_t *), unpack the register contents and supply them as gdb's idea of the current floating point register values. */ +/* FIXME: Assumes that fpregsetp contains an i387 FSAVE area. */ +static const int freg_offset_map[] = +{ +#if !defined(FPREGSET_FSAVE_OFFSET) +#define FPREGSET_FSAVE_OFFSET 0 +#endif + FPREGSET_FSAVE_OFFSET + 28 + 0 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 1 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 2 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 3 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 4 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 5 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 6 * 10, + FPREGSET_FSAVE_OFFSET + 28 + 7 * 10, + FPREGSET_FSAVE_OFFSET + 0, + FPREGSET_FSAVE_OFFSET + 4, + FPREGSET_FSAVE_OFFSET + 8, + FPREGSET_FSAVE_OFFSET + 16, + FPREGSET_FSAVE_OFFSET + 12, + FPREGSET_FSAVE_OFFSET + 24, + FPREGSET_FSAVE_OFFSET + 20, + FPREGSET_FSAVE_OFFSET + 16 +}; + void supply_fpregset (fpregsetp) fpregset_t *fpregsetp; { - /* FIXME: see m68k-tdep.c for an example, for the m68k. */ + int regi; + + if (NUM_FREGS == 0) + return; + for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++) + { + char tbuf[4]; + ULONGEST tval; + char *from = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM]; + + if (regi == FCS_REGNUM) + { + tval = extract_unsigned_integer (from, 4) & 0xffff; + store_unsigned_integer (tbuf, 4, tval); + supply_register (regi, tbuf); + } + else if (regi == FOP_REGNUM) + { + tval = (extract_unsigned_integer (from, 4) >> 16) & ((1 << 11) - 1); + store_unsigned_integer (tbuf, 4, tval); + supply_register (regi, tbuf); + } + else + supply_register (regi, from); + } } /* Given a pointer to a floating point register set in /proc format @@ -165,9 +213,41 @@ fill_fpregset (fpregsetp, regno) fpregset_t *fpregsetp; int regno; { - /* FIXME: see m68k-tdep.c for an example, for the m68k. */ + int regi; + + if (NUM_FREGS == 0) + return; + for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++) + { + if ((regno == -1) || (regno == regi)) + { + char *to = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM]; + char *from = (char *) ®isters[REGISTER_BYTE (regi)]; + ULONGEST valto; + ULONGEST valfrom; + + if (regi == FCS_REGNUM) + { + valto = extract_unsigned_integer (to, 4); + valfrom = extract_unsigned_integer (from, 4); + valto = (valto & ~0xffff) | (valfrom & 0xffff); + store_unsigned_integer (to, 4, valto); + } + else if (regi == FOP_REGNUM) + { + valto = extract_unsigned_integer (to, 4); + valfrom = extract_unsigned_integer (from, 4); + valto = (valto & 0xffff) | ((valfrom & ((1 << 11) - 1)) << 16); + store_unsigned_integer (to, 4, valto); + } + else + { + memcpy (to, from, REGISTER_RAW_SIZE (regi)); + } + } + } } -#endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */ +#endif /* defined (HAVE_FPREGSET_T) */ #endif /* HAVE_SYS_PROCFS_H */ |