From 2eb2613519ae444493c301be1c37901c8a528c40 Mon Sep 17 00:00:00 2001 From: Aditya Vidyadhar Kamath Date: Tue, 7 Mar 2023 07:22:19 -0600 Subject: [PATCH] Enable vector instruction debugging for AIX AIX now supports vector register contents debugging for both VMX VSX registers. --- gdb/NEWS | 5 + gdb/aix-thread.c | 253 +++++++++++++++++++++++++++++++++++++++++- gdb/rs6000-aix-nat.c | 221 ++++++++++++++++++++++++++++++++++++ gdb/rs6000-aix-tdep.c | 182 ++++++++++++++++++++++++++++++ 4 files changed, 660 insertions(+), 1 deletion(-) diff --git a/gdb/NEWS b/gdb/NEWS index 8827efaefb6..cc262f1f8a6 100644 --- a/gdb/NEWS +++ b/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 diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c index 4184c87a92b..e8f57fe185a 100644 --- a/gdb/aix-thread.c +++ b/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 (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 (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 (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 (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 diff --git a/gdb/rs6000-aix-nat.c b/gdb/rs6000-aix-nat.c index 8c9dc1a6e68..728b23bc86e 100644 --- a/gdb/rs6000-aix-nat.c +++ b/gdb/rs6000-aix-nat.c @@ -58,6 +58,14 @@ #include #include +/* Header files for alti-vec reg. */ +#include + +#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 (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 (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 (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 (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). */ diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index 15602c80b00..9a3a5396508 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -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 (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 (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 (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 (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 (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); + } -- 2.30.2