* i387-nat.h (i387_supply_fsave, i387_fill_fsave): Make extern.

(i387_supply_fxsave, i387_fill_fxsave): New prototypes.
* i387-nat.c (i387_supply_fsave): Declare `val' as `unsigned int'.
(fxsave_offset): New variable.
(FXSAVE_ADDR): New macro.
(i387_supply_fxsave, i387_fill_fxsave, i387_tag): New functions.
This commit is contained in:
Mark Kettenis 2000-08-10 14:54:51 +00:00
parent 2e685b93df
commit e2890f0804
3 changed files with 234 additions and 5 deletions

View file

@ -1,3 +1,12 @@
2000-08-10 Mark Kettenis <kettenis@gnu.org>
* i387-nat.h (i387_supply_fsave, i387_fill_fsave): Make extern.
(i387_supply_fxsave, i387_fill_fxsave): New prototypes.
* i387-nat.c (i387_supply_fsave): Declare `val' as `unsigned int'.
(fxsave_offset): New variable.
(FXSAVE_ADDR): New macro.
(i387_supply_fxsave, i387_fill_fxsave, i387_tag): New functions.
2000-08-08 Tom Tromey <tromey@cygnus.com>
* jv-valprint.c (java_value_print): Only print non-null Strings.

View file

@ -1,5 +1,5 @@
/* Native-dependent code for the i387.
Copyright (C) 2000 Free Software Foundation, Inc.
Copyright 2000 Free Software Foundation, Inc.
This file is part of GDB.
@ -71,7 +71,7 @@ i387_supply_fsave (char *fsave)
if (i >= FIRST_FPU_CTRL_REGNUM
&& i != FCOFF_REGNUM && i != FDOFF_REGNUM)
{
unsigned val = *(unsigned short *) (FSAVE_ADDR (fsave, i));
unsigned int val = *(unsigned short *) (FSAVE_ADDR (fsave, i));
if (i == FOP_REGNUM)
{
@ -123,3 +123,210 @@ i387_fill_fsave (char *fsave, int regno)
REGISTER_RAW_SIZE (i));
}
}
/* At fxsave_offset[REGNO] you'll find the offset to the location in
the data structure used by the "fxsave" instruction where GDB
register REGNO is stored. */
static int fxsave_offset[] =
{
32, /* FP0_REGNUM through ... */
48,
64,
80,
96,
112,
128,
144, /* ... FP7_REGNUM (80 bits each). */
0, /* FCTRL_REGNUM (16 bits). */
2, /* FSTAT_REGNUM (16 bits). */
4, /* FTAG_REGNUM (16 bits). */
12, /* FCS_REGNUM (16 bits). */
8, /* FCOFF_REGNUM. */
20, /* FDS_REGNUM (16 bits). */
16, /* FDOFF_REGNUM. */
6, /* FOP_REGNUM (bottom 11 bits). */
160, /* XMM0_REGNUM through ... */
176,
192,
208,
224,
240,
256,
272, /* ... XMM7_REGNUM (128 bits each). */
24, /* MXCSR_REGNUM. */
};
#define FXSAVE_ADDR(fxsave, regnum) \
(fxsave + fxsave_offset[regnum - FP0_REGNUM])
static int i387_tag (unsigned char *raw);
/* Fill GDB's register array with the floating-point and SSE register
values in *FXSAVE. This function masks off any of the reserved
bits in *FXSAVE. */
void
i387_supply_fxsave (char *fxsave)
{
int i;
for (i = FP0_REGNUM; i <= MXCSR_REGNUM; i++)
{
/* Most of the FPU control registers occupy only 16 bits in
the fxsave area. Give those a special treatment. */
if (i >= FIRST_FPU_CTRL_REGNUM && i < XMM0_REGNUM
&& i != FCOFF_REGNUM && i != FDOFF_REGNUM)
{
unsigned long val = *(unsigned short *) (FXSAVE_ADDR (fxsave, i));
if (i == FOP_REGNUM)
{
val &= ((1 << 11) - 1);
supply_register (i, (char *) &val);
}
else if (i== FTAG_REGNUM)
{
/* The fxsave area contains a simplified version of the
tag word. We have to look at the actual 80-bit FP
data to recreate the traditional i387 tag word. */
unsigned long ftag = 0;
unsigned long fstat;
int fpreg;
int top;
fstat = *(unsigned short *) (FXSAVE_ADDR (fxsave, FSTAT_REGNUM));
top = ((fstat >> 11) & 0x111);
for (fpreg = 7; fpreg >= 0; fpreg--)
{
int tag = 0x11;
if (val & (1 << fpreg))
{
int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
}
ftag |= tag << (2 * fpreg);
}
supply_register (i, (char *) &ftag);
}
else
supply_register (i, (char *) &val);
}
else
supply_register (i, FXSAVE_ADDR (fxsave, i));
}
}
/* Fill register REGNO (if it is a floating-point or SSE register) in
*FXSAVE with the value in GDB's register array. If REGNO is -1, do
this for all registers. This function doesn't touch any of the
reserved bits in *FXSAVE. */
void
i387_fill_fxsave (char *fxsave, int regno)
{
int i;
for (i = FP0_REGNUM; i <= MXCSR_REGNUM; i++)
if (regno == -1 || regno == i)
{
/* Most of the FPU control registers occupy only 16 bits in
the fxsave area. Give those a special treatment. */
if (i >= FIRST_FPU_CTRL_REGNUM && i < XMM0_REGNUM
&& i != FCOFF_REGNUM && i != FDOFF_REGNUM)
{
if (i == FOP_REGNUM)
{
unsigned short oldval, newval;
/* The opcode occupies only 11 bits. */
oldval = (*(unsigned short *) (FXSAVE_ADDR (fxsave, i)));
newval = *(unsigned short *) &registers[REGISTER_BYTE (i)];
newval &= ((1 << 11) - 1);
newval |= oldval & ~((1 << 11) - 1);
memcpy (FXSAVE_ADDR (fxsave, i), &newval, 2);
}
else if (i == FTAG_REGNUM)
{
/* Converting back is much easier. */
unsigned char val = 0;
unsigned short ftag;
int fpreg;
ftag = *(unsigned short *) &registers[REGISTER_BYTE (i)];
for (fpreg = 7; fpreg >= 0; fpreg--)
{
int tag = (ftag >> (fpreg * 2)) & 0x11;
if (tag != 0x11)
val |= (1 << fpreg);
}
memcpy (FXSAVE_ADDR (fxsave, i), &val, 2);
}
else
memcpy (FXSAVE_ADDR (fxsave, i),
&registers[REGISTER_BYTE (i)], 2);
}
else
memcpy (FXSAVE_ADDR (fxsave, i), &registers[REGISTER_BYTE (i)],
REGISTER_RAW_SIZE (i));
}
}
/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
*RAW. */
static int
i387_tag (unsigned char *raw)
{
int integer;
unsigned int exponent;
unsigned long fraction[2];
integer = raw[7] & 0x80;
exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
| (raw[5] << 8) | raw[4]);
if (exponent == 0x7fff)
{
/* Special. */
return (0x10);
}
else if (exponent == 0x0000)
{
if (integer)
{
/* Valid. */
return (0x00);
}
else
{
/* Special. */
return (0x10);
}
}
else
{
if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
{
/* Zero. */
return (0x01);
}
else
{
/* Special. */
return (0x10);
}
}
}

View file

@ -1,5 +1,5 @@
/* Native-dependent code for the i387.
Copyright (C) 2000 Free Software Foundation, Inc.
Copyright 2000 Free Software Foundation, Inc.
This file is part of GDB.
@ -25,13 +25,26 @@
in *FSAVE. This function masks off any of the reserved
bits in *FSAVE. */
void i387_supply_fsave (char *fsave);
extern void i387_supply_fsave (char *fsave);
/* Fill register REGNO (if it is a floating-point register) in *FSAVE
with the value in GDB's register array. If REGNO is -1, do this
for all registers. This function doesn't touch any of the reserved
bits in *FSAVE. */
void i387_fill_fsave (char *fsave, int regno);
extern void i387_fill_fsave (char *fsave, int regno);
/* Fill GDB's register array with the floating-point and SSE register
values in *FXSAVE. This function masks off any of the reserved
bits in *FXSAVE. */
extern void i387_supply_fxsave (char *fxsave);
/* Fill register REGNO (if it is a floating-point or SSE register) in
*FXSAVE with the value in GDB's register array. If REGNO is -1, do
this for all registers. This function doesn't touch any of the
reserved bits in *FXSAVE. */
extern void i387_fill_fxsave (char *fxsave, int regno);
#endif /* i387-nat.h */