diff options
author | Daniel Jacobowitz <drow@false.org> | 2002-02-27 07:07:49 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2002-02-27 07:07:49 +0000 |
commit | 58caa3dcdb43a5d66932182338f41df0bfd6cc98 (patch) | |
tree | 8932e0b600933a36f94b2668449ca3626bc0b5ac /gdb/gdbserver/i387-fp.c | |
parent | 936521746ce912bf28fbeb3be2a006f6ffe23929 (diff) | |
download | gdb-58caa3dcdb43a5d66932182338f41df0bfd6cc98.zip gdb-58caa3dcdb43a5d66932182338f41df0bfd6cc98.tar.gz gdb-58caa3dcdb43a5d66932182338f41df0bfd6cc98.tar.bz2 |
2002-02-27 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/acconfig.h: New file.
* gdbserver/i387-fp.c: New file.
* gdbserver/i387-fp.h: New file.
* gdbserver/linux-x86-64.c: New file.
* regformats/reg-x86-64.dat: New file.
* configure.tgt: Add x86_64-*-linux* gdbserver support.
& gdbserver/configure.srv: Add x86_64-*-linux* and regset support.
* gdbserver/configure.in: Add support for regsets.
* gdbserver/config.in: Regenerate.
* gdbserver/configure: Regenerate.
* gdbserver/Makefile.in: Likewise. Add $(linux_low_h).
* gdbserver/linux-low.h: New file.
* gdbserver/linux-low.c: Include "linux-low.h". Add support
for regsets.
* gdbserver/linux-arm-low.c: Include "linux-low.h".
* gdbserver/linux-ia64-low.c: Include "linux-low.h".
* gdbserver/linux-m68k-low.c: Include "linux-low.h".
* gdbserver/linux-mips-low.c: Include "linux-low.h".
* gdbserver/linux-ppc-low.c: Include "linux-low.h".
* gdbserver/linux-sh-low.c: Include "linux-low.h".
* gdbserver/linux-i386-low.c: Include "linux-low.h". Include
"i387-fp.h". Add PTRACE_GETREGS and friends.
* gdbserver/regcache.c (supply_register): New function.
(supply_register_by_name): New function.
(collect_register): New function.
(collect_register_by_name): New function.
Diffstat (limited to 'gdb/gdbserver/i387-fp.c')
-rw-r--r-- | gdb/gdbserver/i387-fp.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/gdb/gdbserver/i387-fp.c b/gdb/gdbserver/i387-fp.c new file mode 100644 index 0000000..3d1d6a6 --- /dev/null +++ b/gdb/gdbserver/i387-fp.c @@ -0,0 +1,290 @@ +/* i387-specific utility functions, for the remote server for GDB. + Copyright 2000, 2001, 2002 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "server.h" + +int num_xmm_registers = 8; + +/* Note: These functions preserve the reserved bits in control registers. + However, gdbserver promptly throws away that information. */ + +/* These structs should have the proper sizes and alignment on both + i386 and x86-64 machines. */ + +struct i387_fsave { + /* All these are only sixteen bits, plus padding, except for fop (which + is only eleven bits), and fooff / fioff (which are 32 bits each). */ + unsigned int fctrl; + unsigned int fstat; + unsigned int ftag; + unsigned int fioff; + unsigned short fiseg; + unsigned short fop; + unsigned int fooff; + unsigned int foseg; + + /* Space for eight 80-bit FP values. */ + char st_space[80]; +}; + +struct i387_fxsave { + /* All these are only sixteen bits, plus padding, except for fop (which + is only eleven bits), and fooff / fioff (which are 32 bits each). */ + unsigned short fctrl; + unsigned short fstat; + unsigned short ftag; + unsigned short fop; + unsigned int fioff; + unsigned int fiseg; + unsigned int fooff; + unsigned int foseg; + + unsigned int mxcsr; + + unsigned int _pad1; + + /* Space for eight 80-bit FP values in 128-bit spaces. */ + char st_space[128]; + + /* Space for eight 128-bit XMM values, or 16 on x86-64. */ + char xmm_space[256]; +}; + +void +i387_cache_to_fsave (void *buf) +{ + struct i387_fsave *fp = (struct i387_fsave *) buf; + int i; + int st0_regnum = find_regno ("st0"); + unsigned long val, val2; + + for (i = 0; i < 8; i++) + collect_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 10); + + collect_register_by_name ("fioff", &fp->fioff); + collect_register_by_name ("fooff", &fp->fooff); + + /* This one's 11 bits... */ + collect_register_by_name ("fop", &val2); + fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800); + + /* Some registers are 16-bit. */ + collect_register_by_name ("fctrl", &val); + *(unsigned short *) &fp->fctrl = val; + + collect_register_by_name ("fstat", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->fstat = val; + + collect_register_by_name ("ftag", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->ftag = val; + + collect_register_by_name ("fiseg", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->fiseg = val; + + collect_register_by_name ("foseg", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->foseg = val; +} + +void +i387_fsave_to_cache (void *buf) +{ + struct i387_fsave *fp = (struct i387_fsave *) buf; + int i; + int st0_regnum = find_regno ("st0"); + unsigned long val; + + for (i = 0; i < 8; i++) + supply_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 10); + + supply_register_by_name ("fioff", &fp->fioff); + supply_register_by_name ("fooff", &fp->fooff); + + /* Some registers are 16-bit. */ + val = fp->fctrl & 0xFFFF; + supply_register_by_name ("fctrl", &val); + + val = fp->fstat & 0xFFFF; + supply_register_by_name ("fstat", &val); + + val = fp->ftag & 0xFFFF; + supply_register_by_name ("ftag", &val); + + val = fp->fiseg & 0xFFFF; + supply_register_by_name ("fiseg", &val); + + val = fp->foseg & 0xFFFF; + supply_register_by_name ("foseg", &val); + + val = (fp->fop) & 0x7FF; + supply_register_by_name ("fop", &val); +} + +void +i387_cache_to_fxsave (void *buf) +{ + struct i387_fxsave *fp = (struct i387_fxsave *) buf; + int i; + int st0_regnum = find_regno ("st0"); + int xmm0_regnum = find_regno ("xmm0"); + unsigned long val, val2; + + for (i = 0; i < 8; i++) + collect_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 16); + for (i = 0; i < num_xmm_registers; i++) + collect_register (i + xmm0_regnum, ((char *) &fp->xmm_space[0]) + i * 16); + + collect_register_by_name ("fioff", &fp->fioff); + collect_register_by_name ("fooff", &fp->fooff); + collect_register_by_name ("mxcsr", &fp->mxcsr); + + /* This one's 11 bits... */ + collect_register_by_name ("fop", &val2); + fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800); + + /* Some registers are 16-bit. */ + collect_register_by_name ("fctrl", &val); + *(unsigned short *) &fp->fctrl = val; + + collect_register_by_name ("fstat", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->fstat = val; + + /* Convert to the simplifed tag form stored in fxsave data. */ + collect_register_by_name ("ftag", &val); + val &= 0xFFFF; + for (i = 7; i >= 0; i--) + { + int tag = (val >> (i * 2)) & 3; + + if (tag != 3) + val2 |= (1 << i); + } + *(unsigned short *) &fp->ftag = val2; + + collect_register_by_name ("fiseg", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->fiseg = val; + + collect_register_by_name ("foseg", &val); + val &= 0xFFFF; + *(unsigned short *) &fp->foseg = val; +} + +static int +i387_ftag (struct i387_fxsave *fp, int regno) +{ + unsigned char *raw = &fp->st_space[regno * 16]; + unsigned int exponent; + unsigned long fraction[2]; + int integer; + + 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 (2); + } + else if (exponent == 0x0000) + { + if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer) + { + /* Zero. */ + return (1); + } + else + { + /* Special. */ + return (2); + } + } + else + { + if (integer) + { + /* Valid. */ + return (0); + } + else + { + /* Special. */ + return (2); + } + } +} + +void +i387_fxsave_to_cache (void *buf) +{ + struct i387_fxsave *fp = (struct i387_fxsave *) buf; + int i, top; + int st0_regnum = find_regno ("st0"); + int xmm0_regnum = find_regno ("xmm0"); + unsigned long val; + + for (i = 0; i < 8; i++) + supply_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 16); + for (i = 0; i < num_xmm_registers; i++) + supply_register (i + xmm0_regnum, ((char *) &fp->xmm_space[0]) + i * 16); + + supply_register_by_name ("fioff", &fp->fioff); + supply_register_by_name ("fooff", &fp->fooff); + supply_register_by_name ("mxcsr", &fp->mxcsr); + + /* Some registers are 16-bit. */ + val = fp->fctrl & 0xFFFF; + supply_register_by_name ("fctrl", &val); + + val = fp->fstat & 0xFFFF; + supply_register_by_name ("fstat", &val); + + /* Generate the form of ftag data that GDB expects. */ + top = (fp->fstat >> 11) & 0x7; + val = 0; + for (i = 7; i >= 0; i--) + { + int tag; + if (val & (1 << i)) + tag = i387_ftag (fp, (i + 8 - top) % 8); + else + tag = 3; + val |= tag << (2 * i); + } + supply_register_by_name ("ftag", &val); + + val = fp->fiseg & 0xFFFF; + supply_register_by_name ("fiseg", &val); + + val = fp->foseg & 0xFFFF; + supply_register_by_name ("foseg", &val); + + val = (fp->fop) & 0x7FF; + supply_register_by_name ("fop", &val); +} + |