Enable vector instruction debugging for AIX
authorAditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
Tue, 7 Mar 2023 13:22:19 +0000 (07:22 -0600)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 7 Mar 2023 15:52:18 +0000 (16:52 +0100)
AIX now supports vector register contents debugging for both VMX
VSX registers.

gdb/NEWS
gdb/aix-thread.c
gdb/rs6000-aix-nat.c
gdb/rs6000-aix-tdep.c

index 8827efaefb62ef8d514bc361a806c5d9f42bf576..cc262f1f8a616396f26777a2d26f5221559ec958 100644 (file)
--- 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
index 4184c87a92b7b634db4dd549ded5ecff5889d7d6..e8f57fe185a22fa623ddc2941ca44ba3ae1a7867 100644 (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
index 8c9dc1a6e68cdc028fbd9cc7e57493e107fe3297..728b23bc86e9f62bbb5eee3b2e11944699bb06ac 100644 (file)
 #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).  */
index 15602c80b005c78429491b15831eeda2b41f352f..9a3a5396508178a2895c4656522bac90108f17ce 100644 (file)
 /* 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);
+
 }