Enable vector instruction debugging for AIX

AIX now supports vector register contents debugging for both VMX
VSX registers.
This commit is contained in:
Aditya Vidyadhar Kamath
2023-03-07 07:22:19 -06:00
committed by Ulrich Weigand
parent 711b1f02f3
commit 2eb2613519
4 changed files with 660 additions and 1 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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). */

View File

@@ -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);
}