forked from Imagelibrary/binutils-gdb
Enable vector instruction debugging for AIX
AIX now supports vector register contents debugging for both VMX VSX registers.
This commit is contained in:
committed by
Ulrich Weigand
parent
711b1f02f3
commit
2eb2613519
5
gdb/NEWS
5
gdb/NEWS
@@ -3,6 +3,11 @@
|
||||
|
||||
*** Changes since GDB 13
|
||||
|
||||
* Removed targets and native configurations
|
||||
|
||||
GDB no longer supports AIX 4.x, AIX 5.x and AIX 6.x. The minimum supported
|
||||
AIX version is now AIX 7.1.
|
||||
|
||||
* Multi-target feature configuration
|
||||
|
||||
GDB now supports the individual configuration of remote targets' feature
|
||||
|
||||
253
gdb/aix-thread.c
253
gdb/aix-thread.c
@@ -301,7 +301,16 @@ ptrace_check (int req, int id, int ret)
|
||||
req, id, ret, errno);
|
||||
return ret == -1 ? 0 : 1;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case PTT_READ_VEC:
|
||||
case PTT_READ_VSX:
|
||||
if (debug_aix_thread)
|
||||
gdb_printf (gdb_stdlog,
|
||||
"ptrace (%d, %d) = %d (errno = %d)\n",
|
||||
req, id, ret, errno);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
error (_("aix-thread: ptrace (%d, %d) returned %d (errno = %d %s)"),
|
||||
req, id, ret, errno, safe_strerror (errno));
|
||||
@@ -475,6 +484,42 @@ pdc_read_regs (pthdb_user_t user_current_pid,
|
||||
memcpy (&context->msr, &sprs32, sizeof(sprs32));
|
||||
}
|
||||
}
|
||||
|
||||
/* vector registers. */
|
||||
__vmx_context_t vmx;
|
||||
if (__power_vmx() && (flags & PTHDB_FLAG_REGS))
|
||||
{
|
||||
if (data->arch64)
|
||||
{
|
||||
if (!ptrace64aix (PTT_READ_VEC, tid, (long long) &vmx, 0, 0))
|
||||
memset (&vmx, 0, sizeof (vmx));
|
||||
memcpy (&context->vmx, &vmx, sizeof(__vmx_context_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ptrace32 (PTT_READ_VEC, tid, (long long) &vmx, 0, 0))
|
||||
memset (&vmx, 0, sizeof (vmx));
|
||||
memcpy (&context->vmx, &vmx, sizeof(__vmx_context_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* vsx registers. */
|
||||
__vsx_context_t vsx;
|
||||
if (__power_vsx() && (flags & PTHDB_FLAG_REGS))
|
||||
{
|
||||
if (data->arch64)
|
||||
{
|
||||
if (!ptrace64aix (PTT_READ_VSX, tid, (long long) &vsx, 0, 0))
|
||||
memset (&vsx, 0, sizeof (vsx));
|
||||
memcpy (&context->vsx, &vsx, sizeof(__vsx_context_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ptrace32 (PTT_READ_VSX, tid, (long long) &vsx, 0, 0))
|
||||
memset (&vsx, 0, sizeof (vsx));
|
||||
memcpy (&context->vsx, &vsx, sizeof(__vsx_context_t));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -531,6 +576,24 @@ pdc_write_regs (pthdb_user_t user_current_pid,
|
||||
ptrace32 (PTT_WRITE_SPRS, tid, (uintptr_t) &context->msr, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* vector registers. */
|
||||
if (__power_vmx() && (flags & PTHDB_FLAG_REGS))
|
||||
{
|
||||
if (data->arch64)
|
||||
ptrace64aix (PTT_WRITE_VEC, tid, (unsigned long) &context->vmx, 0, 0);
|
||||
else
|
||||
ptrace32 (PTT_WRITE_VEC, tid, (uintptr_t) &context->vmx, 0, 0);
|
||||
}
|
||||
|
||||
/* vsx registers. */
|
||||
if (__power_vsx() && (flags & PTHDB_FLAG_REGS))
|
||||
{
|
||||
if (data->arch64)
|
||||
ptrace64aix (PTT_WRITE_VSX, tid, (unsigned long) &context->vsx, 0, 0);
|
||||
else
|
||||
ptrace32 (PTT_WRITE_VSX, tid, (uintptr_t) &context->vsx, 0, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1172,6 +1235,35 @@ aix_thread_target::wait (ptid_t ptid, struct target_waitstatus *status,
|
||||
return pd_update (ptid.pid ());
|
||||
}
|
||||
|
||||
/* Supply AIX altivec registers, both 64 and 32 bit. */
|
||||
|
||||
static void
|
||||
supply_altivec_regs (struct regcache *regcache, __vmx_context_t vmx)
|
||||
{
|
||||
ppc_gdbarch_tdep *tdep
|
||||
= gdbarch_tdep<ppc_gdbarch_tdep> (regcache->arch ());
|
||||
int regno;
|
||||
for (regno = 0; regno < ppc_num_vrs; regno++)
|
||||
regcache->raw_supply (tdep->ppc_vr0_regnum + regno,
|
||||
&(vmx.__vr[regno]));
|
||||
regcache->raw_supply (tdep->ppc_vrsave_regnum, &(vmx.__vrsave));
|
||||
regcache->raw_supply (tdep->ppc_vrsave_regnum - 1, &(vmx.__vscr));
|
||||
}
|
||||
|
||||
/* Supply AIX VSX registers, both 64 and 32 bit. */
|
||||
|
||||
static void
|
||||
supply_vsx_regs (struct regcache *regcache, __vsx_context_t vsx)
|
||||
{
|
||||
ppc_gdbarch_tdep *tdep
|
||||
= gdbarch_tdep<ppc_gdbarch_tdep> (regcache->arch ());
|
||||
int regno;
|
||||
|
||||
for (regno = 0; regno < ppc_num_vshrs; regno++)
|
||||
regcache->raw_supply (tdep->ppc_vsr0_upper_regnum + regno,
|
||||
&(vsx.__vsr_dw1[regno]));
|
||||
}
|
||||
|
||||
/* Record that the 64-bit general-purpose registers contain VALS. */
|
||||
|
||||
static void
|
||||
@@ -1321,6 +1413,12 @@ fetch_regs_user_thread (struct regcache *regcache, pthdb_pthread_t pdtid)
|
||||
else
|
||||
supply_sprs32 (regcache, ctx.iar, ctx.msr, ctx.cr, ctx.lr, ctx.ctr,
|
||||
ctx.xer, ctx.fpscr);
|
||||
|
||||
/* Altivec registers. */
|
||||
supply_altivec_regs (regcache, ctx.vmx);
|
||||
|
||||
/* VSX registers. */
|
||||
supply_vsx_regs (regcache, ctx.vsx);
|
||||
}
|
||||
|
||||
/* Fetch register REGNO if != -1 or all registers otherwise from
|
||||
@@ -1380,6 +1478,38 @@ fetch_regs_kernel_thread (struct regcache *regcache, int regno,
|
||||
}
|
||||
}
|
||||
|
||||
/* vector registers. */
|
||||
if (tdep->ppc_vr0_regnum != -1)
|
||||
{
|
||||
int ret = 0;
|
||||
__vmx_context_t vmx;
|
||||
if (data->arch64)
|
||||
ret = ptrace64aix (PTT_READ_VEC, tid, (long long) &vmx, 0, 0);
|
||||
else
|
||||
ret = ptrace32 (PTT_READ_VEC, tid, (uintptr_t) &vmx, 0, 0);
|
||||
if (ret < 0)
|
||||
memset(&vmx, 0, sizeof(__vmx_context_t));
|
||||
for (i = 0; i < ppc_num_vrs; i++)
|
||||
regcache->raw_supply (tdep->ppc_vr0_regnum + i, &(vmx.__vr[i]));
|
||||
regcache->raw_supply (tdep->ppc_vrsave_regnum, &(vmx.__vrsave));
|
||||
regcache->raw_supply (tdep->ppc_vrsave_regnum - 1, &(vmx.__vscr));
|
||||
}
|
||||
|
||||
/* vsx registers. */
|
||||
if (tdep->ppc_vsr0_upper_regnum != -1)
|
||||
{
|
||||
__vsx_context_t vsx;
|
||||
int ret = 0;
|
||||
if (data->arch64)
|
||||
ret = ptrace64aix (PTT_READ_VSX, tid, (long long) &vsx, 0, 0);
|
||||
else
|
||||
ret = ptrace32 (PTT_READ_VSX, tid, (long long) &vsx, 0, 0);
|
||||
if (ret < 0)
|
||||
memset(&vsx, 0, sizeof(__vsx_context_t));
|
||||
for (i = 0; i < ppc_num_vshrs; i++)
|
||||
regcache->raw_supply (tdep->ppc_vsr0_upper_regnum + i, &(vsx.__vsr_dw1[i]));
|
||||
}
|
||||
|
||||
/* Floating-point registers. */
|
||||
|
||||
if (ppc_floating_point_unit_p (gdbarch)
|
||||
@@ -1447,6 +1577,41 @@ aix_thread_target::fetch_registers (struct regcache *regcache, int regno)
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill altivec registers. */
|
||||
|
||||
static void
|
||||
fill_altivec (const struct regcache *regcache, __vmx_context_t *vmx)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
int regno;
|
||||
|
||||
for (regno = 0; regno < ppc_num_vrs; regno++)
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vr0_regnum + regno))
|
||||
regcache->raw_collect (tdep->ppc_vr0_regnum + regno,
|
||||
&(vmx->__vr[regno]));
|
||||
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vrsave_regnum))
|
||||
regcache->raw_collect (tdep->ppc_vrsave_regnum, &(vmx->__vrsave));
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vrsave_regnum - 1))
|
||||
regcache->raw_collect (tdep->ppc_vrsave_regnum - 1, &(vmx->__vscr));
|
||||
}
|
||||
|
||||
/* Fill vsx registers. */
|
||||
|
||||
static void
|
||||
fill_vsx (const struct regcache *regcache, __vsx_context_t *vsx)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
int regno;
|
||||
|
||||
for (regno = 0; regno < ppc_num_vshrs; regno++)
|
||||
if (REG_VALID == regcache->get_register_status ( tdep->ppc_vsr0_upper_regnum + regno))
|
||||
regcache->raw_collect (tdep->ppc_vsr0_upper_regnum + regno,
|
||||
&(vsx->__vsr_dw1[0]) + regno);
|
||||
}
|
||||
|
||||
/* Store the gp registers into an array of uint32_t or uint64_t. */
|
||||
|
||||
static void
|
||||
@@ -1582,6 +1747,9 @@ store_regs_user_thread (const struct regcache *regcache, pthdb_pthread_t pdtid)
|
||||
uint64_t int64;
|
||||
struct aix_thread_variables *data;
|
||||
data = get_thread_data_helper_for_ptid (inferior_ptid);
|
||||
int ret;
|
||||
__vmx_context_t vmx;
|
||||
__vsx_context_t vsx;
|
||||
|
||||
if (debug_aix_thread)
|
||||
gdb_printf (gdb_stdlog,
|
||||
@@ -1594,6 +1762,38 @@ store_regs_user_thread (const struct regcache *regcache, pthdb_pthread_t pdtid)
|
||||
error (_("aix-thread: store_registers: pthdb_pthread_context returned %s"),
|
||||
pd_status2str (status));
|
||||
|
||||
/* Fill altivec-registers. */
|
||||
|
||||
if (__power_vmx())
|
||||
{
|
||||
memset(&vmx, 0, sizeof(__vmx_context_t));
|
||||
for (i = 0; i < ppc_num_vrs; i++)
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vr0_regnum + i))
|
||||
{
|
||||
regcache->raw_collect (tdep->ppc_vr0_regnum + i,
|
||||
&(vmx.__vr[i]));
|
||||
ctx.vmx.__vr[i] = vmx.__vr[i];
|
||||
}
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vrsave_regnum))
|
||||
ctx.vmx.__vrsave = vmx.__vrsave;
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vrsave_regnum - 1))
|
||||
ctx.vmx.__vscr = vmx.__vscr;
|
||||
}
|
||||
|
||||
/* Fill vsx registers. */
|
||||
|
||||
if (__power_vsx())
|
||||
{
|
||||
memset(&vsx, 0, sizeof(__vsx_context_t));
|
||||
for (i = 0; i < ppc_num_vshrs; i++)
|
||||
if (REG_VALID == regcache->get_register_status (tdep->ppc_vsr0_regnum + i))
|
||||
{
|
||||
regcache->raw_collect (tdep->ppc_vr0_regnum + i,
|
||||
&(vsx.__vsr_dw1[i]));
|
||||
ctx.vsx.__vsr_dw1[i] = vsx.__vsr_dw1[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect general-purpose register values from the regcache. */
|
||||
|
||||
for (i = 0; i < ppc_num_gprs; i++)
|
||||
@@ -1674,6 +1874,7 @@ store_regs_kernel_thread (const struct regcache *regcache, int regno,
|
||||
struct ptxsprs sprs64;
|
||||
struct ptsprs sprs32;
|
||||
struct aix_thread_variables *data;
|
||||
int ret = 0;
|
||||
|
||||
data = get_thread_data_helper_for_ptid (regcache->ptid ());
|
||||
|
||||
@@ -1766,6 +1967,56 @@ store_regs_kernel_thread (const struct regcache *regcache, int regno,
|
||||
ptrace32 (PTT_WRITE_SPRS, tid, (uintptr_t) &sprs32, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Vector registers. */
|
||||
if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1
|
||||
&& (regno == -1 || (regno >= tdep->ppc_vr0_regnum
|
||||
&& regno <= tdep->ppc_vrsave_regnum)))
|
||||
{
|
||||
__vmx_context_t vmx;
|
||||
if (__power_vmx())
|
||||
{
|
||||
if (data->arch64)
|
||||
ret = ptrace64aix (PTT_READ_VEC, tid, (long long) &vmx, 0, 0);
|
||||
else
|
||||
ret = ptrace32 (PTT_READ_VEC, tid, (long long) &vmx, 0, 0);
|
||||
if (ret > 0)
|
||||
{
|
||||
fill_altivec(regcache, &vmx);
|
||||
if (data->arch64)
|
||||
ret = ptrace64aix (PTT_WRITE_VEC, tid, (long long) &vmx, 0, 0);
|
||||
else
|
||||
ret = ptrace32 (PTT_WRITE_VEC, tid, (long long) &vmx, 0, 0);
|
||||
if (ret < 0)
|
||||
perror_with_name (_("Unable to store AltiVec register after read"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* VSX registers. */
|
||||
if (tdep->ppc_vsr0_upper_regnum != -1 && (regno == -1
|
||||
|| (regno >=tdep->ppc_vsr0_upper_regnum
|
||||
&& regno < tdep->ppc_vsr0_upper_regnum + ppc_num_vshrs)))
|
||||
{
|
||||
__vsx_context_t vsx;
|
||||
if (__power_vsx())
|
||||
{
|
||||
if (data->arch64)
|
||||
ret = ptrace64aix (PTT_READ_VSX, tid, (long long) &vsx, 0, 0);
|
||||
else
|
||||
ret = ptrace32 (PTT_READ_VSX, tid, (long long) &vsx, 0, 0);
|
||||
if (ret > 0)
|
||||
{
|
||||
fill_vsx (regcache, &vsx);
|
||||
if (data->arch64)
|
||||
ret = ptrace64aix (PTT_WRITE_VSX, tid, (long long) &vsx, 0, 0);
|
||||
else
|
||||
ret = ptrace32 (PTT_WRITE_VSX, tid, (long long) &vsx, 0, 0);
|
||||
if (ret < 0)
|
||||
perror_with_name (_("Unable to store VSX register after read"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store gdb's current view of the register set into the
|
||||
|
||||
@@ -58,6 +58,14 @@
|
||||
#include <procinfo.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Header files for alti-vec reg. */
|
||||
#include <sys/context.h>
|
||||
|
||||
#include "features/rs6000/powerpc-vsx64.c"
|
||||
#include "features/rs6000/powerpc-vsx32.c"
|
||||
#include "features/rs6000/powerpc-altivec32.c"
|
||||
#include "features/rs6000/powerpc-altivec64.c"
|
||||
|
||||
/* On AIX4.3+, sys/ldr.h provides different versions of struct ld_info for
|
||||
debugging 32-bit and 64-bit processes. Define a typedef and macros for
|
||||
accessing fields in the appropriate structures. */
|
||||
@@ -99,6 +107,8 @@ public:
|
||||
support. */
|
||||
void follow_fork (inferior *, ptid_t, target_waitkind, bool, bool) override;
|
||||
|
||||
const struct target_desc *read_description () override;
|
||||
|
||||
protected:
|
||||
|
||||
void post_startup_inferior (ptid_t ptid) override;
|
||||
@@ -272,6 +282,165 @@ rs6000_ptrace64 (int req, int id, long long addr, int data, void *buf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Store the vsx registers. */
|
||||
|
||||
static void
|
||||
store_vsx_register_aix (struct regcache *regcache, int regno)
|
||||
{
|
||||
int ret;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
struct thrdentry64 thrdentry;
|
||||
__vsx_context_t vsx;
|
||||
pid_t pid = inferior_ptid.pid ();
|
||||
tid64_t thrd_i = 0;
|
||||
|
||||
if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
|
||||
&thrd_i, 1) == 1)
|
||||
thrd_i = thrdentry.ti_tid;
|
||||
|
||||
memset(&vsx, 0, sizeof(__vsx_context_t));
|
||||
if (__power_vsx() && thrd_i > 0)
|
||||
{
|
||||
if (ARCH64 ())
|
||||
ret = rs6000_ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
|
||||
else
|
||||
ret = rs6000_ptrace32 (PTT_READ_VSX, thrd_i, (int *)&vsx, 0, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
regcache->raw_collect (regno, &(vsx.__vsr_dw1[0])+
|
||||
regno - tdep->ppc_vsr0_upper_regnum);
|
||||
|
||||
if (ARCH64 ())
|
||||
ret = rs6000_ptrace64 (PTT_WRITE_VSX, thrd_i, (long long) &vsx, 0, 0);
|
||||
else
|
||||
ret = rs6000_ptrace32 (PTT_WRITE_VSX, thrd_i, (int *) &vsx, 0, 0);
|
||||
|
||||
if (ret < 0)
|
||||
perror_with_name (_("Unable to write VSX registers after reading it"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Store Altivec registers. */
|
||||
|
||||
static void
|
||||
store_altivec_register_aix (struct regcache *regcache, int regno)
|
||||
{
|
||||
int ret;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
struct thrdentry64 thrdentry;
|
||||
__vmx_context_t vmx;
|
||||
pid_t pid = inferior_ptid.pid ();
|
||||
tid64_t thrd_i = 0;
|
||||
|
||||
if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
|
||||
&thrd_i, 1) == 1)
|
||||
thrd_i = thrdentry.ti_tid;
|
||||
|
||||
memset(&vmx, 0, sizeof(__vmx_context_t));
|
||||
if (__power_vmx() && thrd_i > 0)
|
||||
{
|
||||
if (ARCH64 ())
|
||||
ret = rs6000_ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
|
||||
else
|
||||
ret = rs6000_ptrace32 (PTT_READ_VEC, thrd_i, (int *) &vmx, 0, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
regcache->raw_collect (regno, &(vmx.__vr[0]) + regno
|
||||
- tdep->ppc_vr0_regnum);
|
||||
|
||||
if (ARCH64 ())
|
||||
ret = rs6000_ptrace64 (PTT_WRITE_VEC, thrd_i, (long long) &vmx, 0, 0);
|
||||
else
|
||||
ret = rs6000_ptrace32 (PTT_WRITE_VEC, thrd_i, (int *) &vmx, 0, 0);
|
||||
if (ret < 0)
|
||||
perror_with_name (_("Unable to store AltiVec register after reading it"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Supply altivec registers. */
|
||||
|
||||
static void
|
||||
supply_vrregset_aix (struct regcache *regcache, __vmx_context_t *vmx)
|
||||
{
|
||||
int i;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
|
||||
|
||||
for (i = 0; i < num_of_vrregs; i++)
|
||||
regcache->raw_supply (tdep->ppc_vr0_regnum + i,
|
||||
&(vmx->__vr[i]));
|
||||
regcache->raw_supply (tdep->ppc_vrsave_regnum, &(vmx->__vrsave));
|
||||
regcache->raw_supply (tdep->ppc_vrsave_regnum - 1, &(vmx->__vscr));
|
||||
}
|
||||
|
||||
/* Fetch altivec register. */
|
||||
|
||||
static void
|
||||
fetch_altivec_registers_aix (struct regcache *regcache)
|
||||
{
|
||||
struct thrdentry64 thrdentry;
|
||||
__vmx_context_t vmx;
|
||||
pid_t pid = current_inferior ()->pid;
|
||||
tid64_t thrd_i = 0;
|
||||
|
||||
if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
|
||||
&thrd_i, 1) == 1)
|
||||
thrd_i = thrdentry.ti_tid;
|
||||
|
||||
memset(&vmx, 0, sizeof(__vmx_context_t));
|
||||
if (__power_vmx() && thrd_i > 0)
|
||||
{
|
||||
if (ARCH64 ())
|
||||
rs6000_ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
|
||||
else
|
||||
rs6000_ptrace32 (PTT_READ_VEC, thrd_i, (int *) &vmx, 0, 0);
|
||||
supply_vrregset_aix (regcache, &vmx);
|
||||
}
|
||||
}
|
||||
|
||||
/* supply vsx register. */
|
||||
|
||||
static void
|
||||
supply_vsxregset_aix (struct regcache *regcache, __vsx_context_t *vsx)
|
||||
{
|
||||
int i;
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
|
||||
for (i = 0; i < ppc_num_vshrs; i++)
|
||||
regcache->raw_supply (tdep->ppc_vsr0_upper_regnum + i,
|
||||
&(vsx->__vsr_dw1[i]));
|
||||
}
|
||||
|
||||
/* Fetch vsx registers. */
|
||||
static void
|
||||
fetch_vsx_registers_aix (struct regcache *regcache)
|
||||
{
|
||||
struct thrdentry64 thrdentry;
|
||||
__vsx_context_t vsx;
|
||||
pid_t pid = current_inferior ()->pid;
|
||||
tid64_t thrd_i = 0;
|
||||
|
||||
if (getthrds64(pid, &thrdentry, sizeof(struct thrdentry64),
|
||||
&thrd_i, 1) == 1)
|
||||
thrd_i = thrdentry.ti_tid;
|
||||
|
||||
memset(&vsx, 0, sizeof(__vsx_context_t));
|
||||
if (__power_vsx() && thrd_i > 0)
|
||||
{
|
||||
if (ARCH64 ())
|
||||
rs6000_ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
|
||||
else
|
||||
rs6000_ptrace32 (PTT_READ_VSX, thrd_i, (int *) &vsx, 0, 0);
|
||||
supply_vsxregset_aix (regcache, &vsx);
|
||||
}
|
||||
}
|
||||
|
||||
void rs6000_nat_target::post_startup_inferior (ptid_t ptid)
|
||||
{
|
||||
|
||||
@@ -326,6 +495,20 @@ fetch_register (struct regcache *regcache, int regno)
|
||||
/* Retrieved values may be -1, so infer errors from errno. */
|
||||
errno = 0;
|
||||
|
||||
/* Alti-vec register. */
|
||||
if (altivec_register_p (gdbarch, regno))
|
||||
{
|
||||
fetch_altivec_registers_aix (regcache);
|
||||
return;
|
||||
}
|
||||
|
||||
/* VSX register. */
|
||||
if (vsx_register_p (gdbarch, regno))
|
||||
{
|
||||
fetch_vsx_registers_aix (regcache);
|
||||
return;
|
||||
}
|
||||
|
||||
nr = regmap (gdbarch, regno, &isfloat);
|
||||
|
||||
/* Floating-point registers. */
|
||||
@@ -388,6 +571,18 @@ store_register (struct regcache *regcache, int regno)
|
||||
/* -1 can be a successful return value, so infer errors from errno. */
|
||||
errno = 0;
|
||||
|
||||
if (altivec_register_p (gdbarch, regno))
|
||||
{
|
||||
store_altivec_register_aix (regcache, regno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vsx_register_p (gdbarch, regno))
|
||||
{
|
||||
store_vsx_register_aix (regcache, regno);
|
||||
return;
|
||||
}
|
||||
|
||||
nr = regmap (gdbarch, regno, &isfloat);
|
||||
|
||||
/* Floating-point registers. */
|
||||
@@ -458,6 +653,12 @@ rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
|
||||
for (regno = 0; regno < ppc_num_fprs; regno++)
|
||||
fetch_register (regcache, tdep->ppc_fp0_regnum + regno);
|
||||
|
||||
if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
|
||||
fetch_altivec_registers_aix (regcache);
|
||||
|
||||
if (tdep->ppc_vsr0_upper_regnum != -1)
|
||||
fetch_vsx_registers_aix (regcache);
|
||||
|
||||
/* Read special registers. */
|
||||
fetch_register (regcache, gdbarch_pc_regnum (gdbarch));
|
||||
fetch_register (regcache, tdep->ppc_ps_regnum);
|
||||
@@ -472,6 +673,26 @@ rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
|
||||
}
|
||||
}
|
||||
|
||||
const struct target_desc *
|
||||
rs6000_nat_target::read_description ()
|
||||
{
|
||||
if (ARCH64())
|
||||
{
|
||||
if (__power_vsx ())
|
||||
return tdesc_powerpc_vsx64;
|
||||
else if (__power_vmx ())
|
||||
return tdesc_powerpc_altivec64;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (__power_vsx ())
|
||||
return tdesc_powerpc_vsx32;
|
||||
else if (__power_vmx ())
|
||||
return tdesc_powerpc_altivec32;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
@@ -68,6 +68,178 @@
|
||||
/* Minimum possible text address in AIX. */
|
||||
#define AIX_TEXT_SEGMENT_BASE 0x10000000
|
||||
|
||||
struct rs6000_aix_reg_vrreg_offset
|
||||
{
|
||||
int vr0_offset;
|
||||
int vscr_offset;
|
||||
int vrsave_offset;
|
||||
};
|
||||
|
||||
static struct rs6000_aix_reg_vrreg_offset rs6000_aix_vrreg_offset =
|
||||
{
|
||||
/* AltiVec registers. */
|
||||
32, /* vr0_offset */
|
||||
544, /* vscr_offset. */
|
||||
560 /* vrsave_offset */
|
||||
};
|
||||
|
||||
static int
|
||||
rs6000_aix_get_vrreg_offset (ppc_gdbarch_tdep *tdep,
|
||||
const struct rs6000_aix_reg_vrreg_offset *offsets,
|
||||
int regnum)
|
||||
{
|
||||
if (regnum >= tdep->ppc_vr0_regnum &&
|
||||
regnum < tdep->ppc_vr0_regnum + ppc_num_vrs)
|
||||
return offsets->vr0_offset + (regnum - tdep->ppc_vr0_regnum) * 16;
|
||||
|
||||
if (regnum == tdep->ppc_vrsave_regnum - 1)
|
||||
return offsets->vscr_offset;
|
||||
|
||||
if (regnum == tdep->ppc_vrsave_regnum)
|
||||
return offsets->vrsave_offset;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
rs6000_aix_supply_vrregset (const struct regset *regset, struct regcache *regcache,
|
||||
int regnum, const void *vrregs, size_t len)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
const struct rs6000_aix_reg_vrreg_offset *offsets;
|
||||
size_t offset;
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
if (!(tdep->ppc_vr0_regnum >= 0 && tdep->ppc_vrsave_regnum >= 0))
|
||||
return;
|
||||
|
||||
offsets = (const struct rs6000_aix_reg_vrreg_offset *) regset->regmap;
|
||||
if (regnum == -1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
|
||||
i < tdep->ppc_vr0_regnum + ppc_num_vrs;
|
||||
i++, offset += 16)
|
||||
ppc_supply_reg (regcache, i, (const gdb_byte *) vrregs, offset, 16);
|
||||
|
||||
ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
|
||||
(const gdb_byte *) vrregs, offsets->vscr_offset, 4);
|
||||
|
||||
ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
|
||||
(const gdb_byte *) vrregs, offsets->vrsave_offset, 4);
|
||||
|
||||
return;
|
||||
}
|
||||
offset = rs6000_aix_get_vrreg_offset (tdep, offsets, regnum);
|
||||
if (regnum != tdep->ppc_vrsave_regnum &&
|
||||
regnum != tdep->ppc_vrsave_regnum - 1)
|
||||
ppc_supply_reg (regcache, regnum, (const gdb_byte *) vrregs, offset, 16);
|
||||
else
|
||||
ppc_supply_reg (regcache, regnum,
|
||||
(const gdb_byte *) vrregs, offset, 4);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
rs6000_aix_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
|
||||
int regnum, const void *vsxregs, size_t len)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
if (!(tdep->ppc_vsr0_regnum >= 0))
|
||||
return;
|
||||
|
||||
if (regnum == -1)
|
||||
{
|
||||
int i, offset = 0;
|
||||
|
||||
for (i = tdep->ppc_vsr0_upper_regnum; i < tdep->ppc_vsr0_upper_regnum
|
||||
+ 32; i++, offset += 8)
|
||||
ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, offset, 8);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8);
|
||||
}
|
||||
|
||||
static void
|
||||
rs6000_aix_collect_vsxregset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
int regnum, void *vsxregs, size_t len)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
if (!(tdep->ppc_vsr0_regnum >= 0))
|
||||
return;
|
||||
|
||||
if (regnum == -1)
|
||||
{
|
||||
int i;
|
||||
int offset = 0;
|
||||
for (i = tdep->ppc_vsr0_upper_regnum; i < tdep->ppc_vsr0_upper_regnum
|
||||
+ 32; i++, offset += 8)
|
||||
ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, offset, 8);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8);
|
||||
}
|
||||
|
||||
static void
|
||||
rs6000_aix_collect_vrregset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
int regnum, void *vrregs, size_t len)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
const struct rs6000_aix_reg_vrreg_offset *offsets;
|
||||
size_t offset;
|
||||
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
if (!(tdep->ppc_vr0_regnum >= 0 && tdep->ppc_vrsave_regnum >= 0))
|
||||
return;
|
||||
|
||||
offsets = (const struct rs6000_aix_reg_vrreg_offset *) regset->regmap;
|
||||
if (regnum == -1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset; i <
|
||||
tdep->ppc_vr0_regnum + ppc_num_vrs; i++, offset += 16)
|
||||
ppc_collect_reg (regcache, i, (gdb_byte *) vrregs, offset, 16);
|
||||
|
||||
ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
|
||||
(gdb_byte *) vrregs, offsets->vscr_offset, 4);
|
||||
|
||||
ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
|
||||
(gdb_byte *) vrregs, offsets->vrsave_offset, 4);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
offset = rs6000_aix_get_vrreg_offset (tdep, offsets, regnum);
|
||||
if (regnum != tdep->ppc_vrsave_regnum
|
||||
&& regnum != tdep->ppc_vrsave_regnum - 1)
|
||||
ppc_collect_reg (regcache, regnum, (gdb_byte *) vrregs, offset, 16);
|
||||
else
|
||||
ppc_collect_reg (regcache, regnum,
|
||||
(gdb_byte *) vrregs, offset, 4);
|
||||
}
|
||||
|
||||
static const struct regset rs6000_aix_vrregset = {
|
||||
&rs6000_aix_vrreg_offset,
|
||||
rs6000_aix_supply_vrregset,
|
||||
rs6000_aix_collect_vrregset
|
||||
};
|
||||
|
||||
static const struct regset rs6000_aix_vsxregset = {
|
||||
&rs6000_aix_vrreg_offset,
|
||||
rs6000_aix_supply_vsxregset,
|
||||
rs6000_aix_collect_vsxregset
|
||||
};
|
||||
|
||||
static struct trad_frame_cache *
|
||||
aix_sighandle_frame_cache (frame_info_ptr this_frame,
|
||||
void **this_cache)
|
||||
@@ -262,10 +434,20 @@ rs6000_aix_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
||||
const struct regcache *regcache)
|
||||
{
|
||||
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
||||
int have_altivec = tdep->ppc_vr0_regnum != -1;
|
||||
int have_vsx = tdep->ppc_vsr0_upper_regnum != -1;
|
||||
|
||||
if (tdep->wordsize == 4)
|
||||
cb (".reg", 592, 592, &rs6000_aix32_regset, NULL, cb_data);
|
||||
else
|
||||
cb (".reg", 576, 576, &rs6000_aix64_regset, NULL, cb_data);
|
||||
|
||||
if (have_altivec)
|
||||
cb (".aix-vmx", 560, 560, &rs6000_aix_vrregset, "AIX altivec", cb_data);
|
||||
|
||||
if (have_vsx)
|
||||
cb (".aix-vsx", 256, 256, &rs6000_aix_vsxregset, "AIX vsx", cb_data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user