mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 01:28:46 +00:00
Support i386 AVX.
2010-04-07 H.J. Lu <hongjiu.lu@intel.com> * i386-linux-nat.c: Include "regset.h", "elf/common.h", <sys/uio.h> and "i386-xstate.h". (PTRACE_GETREGSET): New. (PTRACE_SETREGSET): Likewise. (fetch_xstateregs): Likewise. (store_xstateregs): Likewise. (GETXSTATEREGS_SUPPLIES): Likewise. (regmap): Include 8 upper YMM registers. (i386_linux_fetch_inferior_registers): Support XSAVE extended state. (i386_linux_store_inferior_registers): Likewise. (i386_linux_read_description): Check and enable AVX target descriptions. * i386-linux-tdep.c: Include "regset.h", "i387-tdep.h", "i386-xstate.h" and "features/i386/i386-avx-linux.c". (i386_linux_regset_sections): Add ".reg-xstate". (i386_linux_gregset_reg_offset): Include 8 upper YMM registers. (i386_linux_core_read_xcr0): New. (i386_linux_core_read_description): Check and enable AVX target description. (i386_linux_init_abi): Set xsave_xcr0_offset. (_initialize_i386_linux_tdep): Call initialize_tdesc_i386_avx_linux. * i386-linux-tdep.h (I386_LINUX_ORIG_EAX_REGNUM): Replace I386_SSE_NUM_REGS with I386_AVX_NUM_REGS. (i386_linux_core_read_xcr0): New. (tdesc_i386_avx_linux): Likewise. (I386_LINUX_XSAVE_XCR0_OFFSET): Likewise. * i386-tdep.c: Include "i386-xstate.h" and "features/i386/i386-avx.c". (i386_ymm_names): New. (i386_ymmh_names): Likewise. (i386_ymmh_regnum_p): Likewise. (i386_ymm_regnum_p): Likewise. (i386_xmm_regnum_p): Likewise. (i386_register_name): Likewise. (i386_ymm_type): Likewise. (i386_supply_xstateregset): Likewise. (i386_collect_xstateregset): Likewise. (i386_sse_regnum_p): Removed. (i386_pseudo_register_name): Support pseudo YMM registers. (i386_pseudo_register_type): Likewise. (i386_pseudo_register_read): Likewise. (i386_pseudo_register_write): Likewise. (i386_dbx_reg_to_regnum): Return %ymmN register number for %xmmN if AVX is available. (i386_regset_from_core_section): Support .reg-xstate section. (i386_register_reggroup_p): Supper upper YMM and YMM registers. (i386_process_record): Replace i386_sse_regnum_p with i386_xmm_regnum_p. (i386_validate_tdesc_p): Support org.gnu.gdb.i386.avx feature. Set ymmh_register_names, num_ymm_regs, ymm0h_regnum and xcr0. (i386_gdbarch_init): Set xstateregset. Set xsave_xcr0_offset. Call set_gdbarch_register_name. Replace I386_SSE_NUM_REGS with I386_AVX_NUM_REGS. Set ymmh_register_names, ymm0h_regnum and num_ymm_regs. Add num_ymm_regs to set_gdbarch_num_pseudo_regs. Set ymm0_regnum. (_initialize_i386_tdep): Call initialize_tdesc_i386_avx. * i386-tdep.h (gdbarch_tdep): Add xstateregset, ymm0_regnum, xcr0, xsave_xcr0_offset, ymm0h_regnum, ymmh_register_names and i386_ymm_type. (i386_regnum): Add I386_YMM0H_REGNUM, and I386_YMM7H_REGNUM. (I386_AVX_NUM_REGS): New. (i386_xmm_regnum_p): Likewise. (i386_ymm_regnum_p): Likewise. (i386_ymmh_regnum_p): Likewise. * common/i386-xstate.h: New.
This commit is contained in:
@@ -23,11 +23,14 @@
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
#include "regset.h"
|
||||
#include "target.h"
|
||||
#include "linux-nat.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include "gdb_string.h"
|
||||
#include "elf/common.h"
|
||||
#include <sys/uio.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/procfs.h>
|
||||
@@ -69,6 +72,19 @@
|
||||
|
||||
/* Defines ps_err_e, struct ps_prochandle. */
|
||||
#include "gdb_proc_service.h"
|
||||
|
||||
#include "i386-xstate.h"
|
||||
|
||||
#ifndef PTRACE_GETREGSET
|
||||
#define PTRACE_GETREGSET 0x4204
|
||||
#endif
|
||||
|
||||
#ifndef PTRACE_SETREGSET
|
||||
#define PTRACE_SETREGSET 0x4205
|
||||
#endif
|
||||
|
||||
/* Does the current host support PTRACE_GETREGSET? */
|
||||
static int have_ptrace_getregset = -1;
|
||||
|
||||
|
||||
/* The register sets used in GNU/Linux ELF core-dumps are identical to
|
||||
@@ -98,6 +114,8 @@ static int regmap[] =
|
||||
-1, -1, -1, -1, /* xmm0, xmm1, xmm2, xmm3 */
|
||||
-1, -1, -1, -1, /* xmm4, xmm5, xmm6, xmm6 */
|
||||
-1, /* mxcsr */
|
||||
-1, -1, -1, -1, /* ymm0h, ymm1h, ymm2h, ymm3h */
|
||||
-1, -1, -1, -1, /* ymm4h, ymm5h, ymm6h, ymm6h */
|
||||
ORIG_EAX
|
||||
};
|
||||
|
||||
@@ -110,6 +128,9 @@ static int regmap[] =
|
||||
#define GETFPXREGS_SUPPLIES(regno) \
|
||||
(I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS)
|
||||
|
||||
#define GETXSTATEREGS_SUPPLIES(regno) \
|
||||
(I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX_NUM_REGS)
|
||||
|
||||
/* Does the current host support the GETREGS request? */
|
||||
int have_ptrace_getregs =
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
@@ -355,6 +376,57 @@ static void store_fpregs (const struct regcache *regcache, int tid, int regno) {
|
||||
|
||||
/* Transfering floating-point and SSE registers to and from GDB. */
|
||||
|
||||
/* Fetch all registers covered by the PTRACE_GETREGSET request from
|
||||
process/thread TID and store their values in GDB's register array.
|
||||
Return non-zero if successful, zero otherwise. */
|
||||
|
||||
static int
|
||||
fetch_xstateregs (struct regcache *regcache, int tid)
|
||||
{
|
||||
char xstateregs[I386_XSTATE_MAX_SIZE];
|
||||
struct iovec iov;
|
||||
|
||||
if (!have_ptrace_getregset)
|
||||
return 0;
|
||||
|
||||
iov.iov_base = xstateregs;
|
||||
iov.iov_len = sizeof(xstateregs);
|
||||
if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
|
||||
&iov) < 0)
|
||||
perror_with_name (_("Couldn't read extended state status"));
|
||||
|
||||
i387_supply_xsave (regcache, -1, xstateregs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Store all valid registers in GDB's register array covered by the
|
||||
PTRACE_SETREGSET request into the process/thread specified by TID.
|
||||
Return non-zero if successful, zero otherwise. */
|
||||
|
||||
static int
|
||||
store_xstateregs (const struct regcache *regcache, int tid, int regno)
|
||||
{
|
||||
char xstateregs[I386_XSTATE_MAX_SIZE];
|
||||
struct iovec iov;
|
||||
|
||||
if (!have_ptrace_getregset)
|
||||
return 0;
|
||||
|
||||
iov.iov_base = xstateregs;
|
||||
iov.iov_len = sizeof(xstateregs);
|
||||
if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
|
||||
&iov) < 0)
|
||||
perror_with_name (_("Couldn't read extended state status"));
|
||||
|
||||
i387_collect_xsave (regcache, regno, xstateregs, 0);
|
||||
|
||||
if (ptrace (PTRACE_SETREGSET, tid, (unsigned int) NT_X86_XSTATE,
|
||||
(int) &iov) < 0)
|
||||
perror_with_name (_("Couldn't write extended state status"));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTRACE_GETFPXREGS
|
||||
|
||||
/* Fill GDB's register array with the floating-point and SSE register
|
||||
@@ -489,6 +561,8 @@ i386_linux_fetch_inferior_registers (struct target_ops *ops,
|
||||
return;
|
||||
}
|
||||
|
||||
if (fetch_xstateregs (regcache, tid))
|
||||
return;
|
||||
if (fetch_fpxregs (regcache, tid))
|
||||
return;
|
||||
fetch_fpregs (regcache, tid);
|
||||
@@ -501,6 +575,12 @@ i386_linux_fetch_inferior_registers (struct target_ops *ops,
|
||||
return;
|
||||
}
|
||||
|
||||
if (GETXSTATEREGS_SUPPLIES (regno))
|
||||
{
|
||||
if (fetch_xstateregs (regcache, tid))
|
||||
return;
|
||||
}
|
||||
|
||||
if (GETFPXREGS_SUPPLIES (regno))
|
||||
{
|
||||
if (fetch_fpxregs (regcache, tid))
|
||||
@@ -553,6 +633,8 @@ i386_linux_store_inferior_registers (struct target_ops *ops,
|
||||
if (regno == -1)
|
||||
{
|
||||
store_regs (regcache, tid, regno);
|
||||
if (store_xstateregs (regcache, tid, regno))
|
||||
return;
|
||||
if (store_fpxregs (regcache, tid, regno))
|
||||
return;
|
||||
store_fpregs (regcache, tid, regno);
|
||||
@@ -565,6 +647,12 @@ i386_linux_store_inferior_registers (struct target_ops *ops,
|
||||
return;
|
||||
}
|
||||
|
||||
if (GETXSTATEREGS_SUPPLIES (regno))
|
||||
{
|
||||
if (store_xstateregs (regcache, tid, regno))
|
||||
return;
|
||||
}
|
||||
|
||||
if (GETFPXREGS_SUPPLIES (regno))
|
||||
{
|
||||
if (store_fpxregs (regcache, tid, regno))
|
||||
@@ -858,7 +946,42 @@ i386_linux_child_post_startup_inferior (ptid_t ptid)
|
||||
static const struct target_desc *
|
||||
i386_linux_read_description (struct target_ops *ops)
|
||||
{
|
||||
return tdesc_i386_linux;
|
||||
static uint64_t xcr0;
|
||||
|
||||
if (have_ptrace_getregset == -1)
|
||||
{
|
||||
int tid;
|
||||
uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))];
|
||||
struct iovec iov;
|
||||
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
tid = TIDGET (inferior_ptid);
|
||||
if (tid == 0)
|
||||
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
||||
|
||||
iov.iov_base = xstateregs;
|
||||
iov.iov_len = sizeof (xstateregs);
|
||||
|
||||
/* Check if PTRACE_GETREGSET works. */
|
||||
if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
|
||||
&iov) < 0)
|
||||
have_ptrace_getregset = 0;
|
||||
else
|
||||
{
|
||||
have_ptrace_getregset = 1;
|
||||
|
||||
/* Get XCR0 from XSAVE extended state. */
|
||||
xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
|
||||
/ sizeof (long long))];
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the native XCR0 only if PTRACE_GETREGSET is available. */
|
||||
if (have_ptrace_getregset
|
||||
&& (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
|
||||
return tdesc_i386_avx_linux;
|
||||
else
|
||||
return tdesc_i386_linux;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user