From: Aditya Kamath1 <Aditya.Kamath1@ibm.com>
To: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>,
"simark@simark.ca" <simark@simark.ca>
Cc: Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
Subject: Re: [PATCH] Enable vector instruction debugging for AIX
Date: Tue, 7 Mar 2023 12:13:59 +0000 [thread overview]
Message-ID: <CH2PR15MB3544EF0FEAEF71B1CC83B1A3D6B79@CH2PR15MB3544.namprd15.prod.outlook.com> (raw)
In-Reply-To: <300eb480053b4c27b868d23196058273758320b1.camel@de.ibm.com>
[-- Attachment #1.1: Type: text/plain, Size: 5723 bytes --]
Hi Ulrich and community,
Please find attached the patch with the newly suggested changes with indentations as per GNU style/guidelines.
Thank you for guiding about the same. Kindly see my reply to 2 of your queries in blue.
Kindly push this patch if there are no changes.
Have a nice day ahead.
Thanks and regards,
Aditya.
>You've added this under the GDB 11 news section, which is wrong.
>You should instead add a new section
> * Removed targets and native configurations
>in the topmost
> *** Changes since GDB 13
>section.
This is done. Kindly let me know if this is okay.
>+ memset(&vmx, 0, sizeof(__vmx_context_t));
>+ if (data->arch64)
>Why is this check necessary, and what happens on 32-bit targets?
Thank you for reminding me. So I was experimenting with the altivec-regs.exp and site.exp in 32 bit mode attempting to see what happens if I have that condition. I forgot to remove it.
From: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date: Tuesday, 7 March 2023 at 3:55 PM
To: gdb-patches@sourceware.org <gdb-patches@sourceware.org>, Aditya Kamath1 <Aditya.Kamath1@ibm.com>, simark@simark.ca <simark@simark.ca>
Cc: Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
Subject: Re: [PATCH] Enable vector instruction debugging for AIX
Aditya Kamath1 <Aditya.Kamath1@ibm.com> wrote:
>So I connected with my seniors on this. So AIX folks are using 7.1 now.
>So I have changed this to minimum 7.x.. Kindly see it in this patch.
>For those who are below 7.1, we are not supporting.
OK, this makes sense to me. But it looks like you've added this
to the wrong section now, see below.
>>Fix coding style ({ should be indented).
>This is done. I have eliminated all RHS space and aligned the flower brackets wherever I saw it was not aligned.
Unfortunately it seems you changed many of these
in the wrong direction now. GNU coding style is
to indent the { by two spaces, and then indent the
block inside by *another* two spaces:
if (condition)
{
/* code */
}
Also, the patch still introduces various instances of
8 spaces (that should be tabs), and whitespace at the
end of the line (which should be removed).
>@@ -938,6 +938,9 @@ info sources
>
> ARM Symbian arm*-*-symbianelf*
>
>+GDB no longer supports AIX 4.x, AIX 5.x and AIX 6.x. The minimum supported
>+AIX version is now AIX 7.1.
>+
You've added this under the GDB 11 news section, which is wrong.
You should instead add a new section
* Removed targets and native configurations
in the topmost
*** Changes since GDB 13
section.
>+ __vmx_context_t vmx;
>+ if (__power_vmx() && (flags & PTHDB_FLAG_REGS))
>+ {
Wrong indentation.
>+ /* vsx registers. */
>+ __vsx_context_t vsx;
>+ if (__power_vsx() && (flags & PTHDB_FLAG_REGS))
>+ {
Likewise.
>+ /* vector registers. */
>+ if (__power_vmx() && (flags & PTHDB_FLAG_REGS))
>+ {
Likewise.
>+ /* vsx registers. */
>+ if (__power_vsx() && (flags & PTHDB_FLAG_REGS))
>+ {
Likewise.
>+ /* Fill altivec-registers. */
>+
>+ if (__power_vmx())
>+ {
Likewise throughout the block
>+ memset(&vmx, 0, sizeof(__vmx_context_t));
>+ if (data->arch64)
Why is this check necessary, and what happens on 32-bit targets?
>+ /* Fill vsx registers. */
>+
>+ if (__power_vsx())
>+ {
>+ memset(&vsx, 0, sizeof(__vsx_context_t));
>+ if (data->arch64)
Same question, also same indentation issues.
>+ /* 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)))
>+ {
Also indentation issues throughout the block.
>+ /* VSX registers. */
>+ if (tdep->ppc_vsr0_upper_regnum != -1 && (regno == -1
>+ || (regno >=tdep->ppc_vsr0_upper_regnum)))
You've now removed the upper limit completely. I think this needs an
&& regno < tdep->ppc_vsr0_upper_regnum + ppc_num_vshrs
>+ memset(&vsx, 0, sizeof(__vsx_context_t));
>+ if (__power_vsx() && thrd_i > 0)
>+ {
Indentation.
>+ memset(&vmx, 0, sizeof(__vmx_context_t));
>+ if (__power_vmx() && thrd_i > 0)
>+ {
Likewise.
>+ memset(&vmx, 0, sizeof(__vmx_context_t));
>+ if (__power_vmx() && thrd_i > 0)
>+ {
Likewise.
>+ memset(&vsx, 0, sizeof(__vsx_context_t));
>+ if (__power_vsx() && thrd_i > 0)
>+ {
Likewise.
>+ /* 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;
>+ }
Likewise.
>+ 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;
>+ }
Likewise.
>+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;
>+}
Likewise.
>+ if (regnum == -1)
>+ {
Likewise.
>+ if (regnum == -1)
>+ {
Likewise.
>+ if (regnum == -1)
>+ {
Likewise.
>+ if (regnum == -1)
>+ {
Likewise.
Bye,
Ulrich
[-- Attachment #2: 0001-Enable-vector-instruction-debugging-for-AIX.patch --]
[-- Type: application/octet-stream, Size: 26138 bytes --]
From 5fcb5e2f50416ef63e51bcc022e8db00ec59bf5e Mon Sep 17 00:00:00 2001
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
Date: Tue, 7 Mar 2023 05:57:56 -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 | 252 +++++++++++++++++++++++++++++++++++++++++-
gdb/rs6000-aix-nat.c | 221 ++++++++++++++++++++++++++++++++++++
gdb/rs6000-aix-tdep.c | 182 ++++++++++++++++++++++++++++++
4 files changed, 659 insertions(+), 1 deletion(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 75cd11b204e..f456f52523b 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..650cfcb639b 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<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,55 @@ 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)))
+ {
+ __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 <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 @@ class rs6000_nat_target final : public inf_ptrace_target
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). */
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<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);
+
}
--
2.38.3
next prev parent reply other threads:[~2023-03-07 12:14 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-13 10:52 Aditya Kamath1
2022-10-13 10:52 ` Aditya Kamath1
2022-10-14 12:41 ` Ulrich Weigand
2022-10-28 10:35 ` Aditya Kamath1
2022-10-28 12:39 ` Ulrich Weigand
2022-11-14 16:26 ` Aditya Kamath1
2022-11-15 19:03 ` Ulrich Weigand
2023-02-23 12:49 ` Aditya Kamath1
2023-02-24 15:26 ` Ulrich Weigand
2023-03-01 12:34 ` Aditya Kamath1
2023-03-03 14:59 ` Ulrich Weigand
2023-03-06 13:45 ` Aditya Kamath1
2023-03-07 10:25 ` Ulrich Weigand
2023-03-07 12:13 ` Aditya Kamath1 [this message]
2023-03-07 12:55 ` Ulrich Weigand
2023-03-07 13:24 ` Aditya Kamath1
2023-03-07 15:53 ` Ulrich Weigand
2023-03-09 2:21 ` Aditya Kamath1
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CH2PR15MB3544EF0FEAEF71B1CC83B1A3D6B79@CH2PR15MB3544.namprd15.prod.outlook.com \
--to=aditya.kamath1@ibm.com \
--cc=Ulrich.Weigand@de.ibm.com \
--cc=gdb-patches@sourceware.org \
--cc=sangamesh.swamy@in.ibm.com \
--cc=simark@simark.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).