public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Enable vector instruction debugging for AIX
@ 2022-10-13 10:52 Aditya Kamath1
  2022-10-13 10:52 ` Aditya Kamath1
  2022-10-14 12:41 ` Ulrich Weigand
  0 siblings, 2 replies; 18+ messages in thread
From: Aditya Kamath1 @ 2022-10-13 10:52 UTC (permalink / raw)
  To: Aditya Kamath1 via Gdb-patches, Ulrich Weigand, simark
  Cc: Sangamesh Mallayya, Aditya Kamath1

[-- Attachment #1: Type: text/plain, Size: 3247 bytes --]

Hi all,

Brief Introduction:- Vector registers are an extension to the POWERPC processor architecture in order to support vector and matrix mathematical functions. This is to improve graphics and multimedia. For example, the vector ALU SIMD- style arithmetic unit where a single instruction performs the same operation on all the data elements of each vector.


The problem:- While a user finds bugs in applications which uses vector instructions, they would like to debug vector registers or set vector registers to a particular value to figure it out. Currently in AIX, we have not enabled vector instruction debugging. This patch is used to enable vector instruction debugging.

Please find attached the patch. [See 0001-PATCH-Enable-Vector-support-for-AIX.patch]

A sample program is as shown below:-


#include <stdio.h>

int main () {

vector int Arr1[5] = {

  { 1, 2, 3, 4 },

  { 11, 22, 33, 44 },

  { 111, 222, 333, 444 },

  { 1111, 2222, 3333, 4444 },

  { 11111, 22222, 33333, 44444 }

};

vector int Arr2[5] = {

  { 1, 2, 3, 4 },

  { 11, 22, 33, 44 },

  { 111, 222, 333, 444 },

  { 1111, 2222, 3333, 4444 },

  { 11111, 22222, 33333, 44444 }

};

vector int Arr3[5] = {

  { 0, 0, 0, 0 },

  { 0, 0, 0, 0 },

  { 0, 0, 0, 0 },

  { 0, 0, 0, 0 },

  { 0, 0, 0, 0 }

};

        printf("Adding Arrays\n");

        Arr3[1] = Arr1[2] + Arr2[3];

        printf("Arr3[1] = { %d, %d, %d, %d }\n", Arr3[1][0], Arr3[1][1], Arr3[1][2], Arr3[1][3]);

        return 0;

}


The output expected is as follows:-


(gdb) b main

Breakpoint 1 at 0x1000052c: file /home/XYZ/gdb_tests/vector_lab_test.c, line 3.

(gdb) r

Starting program: /home/XYZ/gdb_tests/vector_lab_test


Breakpoint 1, main () at /home/XYZ/gdb_tests/vector_lab_test.c:3

3       vector int Arr1[5] = {

(gdb) n

10      vector int Arr2[5] = {

(gdb) n

17      vector int Arr3[5] = {

(gdb) n

24              printf("Adding Arrays\n");

(gdb) n

Adding Arrays

25              Arr3[1] = Arr1[2] + Arr2[3];

(gdb) n

26              printf("Arr3[1] = { %d, %d, %d, %d }\n", Arr3[1][0], Arr3[1][1], Arr3[1][2], Arr3[1][3]);

(gdb) info reg vr0

vr0            {uint128 = 0x4c60000098c00000e5200001318, v4_float = {0x4c6, 0x98c, 0xe52, 0x1318}, v4_int32 = {0x4c6, 0x98c, 0xe52, 0x1318}, v8_int16 = {0x0, 0x4c6, 0x0, 0x98c, 0x0, 0xe52, 0x0, 0x1318}, v16_int8 = {0x0, 0x0, 0x4, 0xc6, 0x0, 0x0, 0x9, 0x8c, 0x0, 0x0, 0xe, 0x52, 0x0, 0x0, 0x13, 0x18}}

(gdb) set $vr0.v4_int32[3] = 1

(gdb) info reg vr0

vr0            {uint128 = 0x4c60000098c00000e5200000001, v4_float = {0x4c6, 0x98c, 0xe52, 0x1}, v4_int32 = {0x4c6, 0x98c, 0xe52, 0x1}, v8_int16 = {0x0, 0x4c6, 0x0, 0x98c, 0x0, 0xe52, 0x0, 0x1}, v16_int8 = {0x0, 0x0, 0x4, 0xc6, 0x0, 0x0, 0x9, 0x8c, 0x0, 0x0, 0xe, 0x52, 0x0, 0x0, 0x0, 0x1}}

(gdb)

-------------------------------------------------------------------------


Kindly note in AIX unless and until a debugee uses vector registers the debugger cannot set or get the same.

Kindly let me know if this patch works. If yes, kindly push it else kindly give me feedback for changes.

Have a nice day ahead.

Thanks and regards,
Aditya.

[-- Attachment #2: 0001-PATCH-Enable-Vector-support-for-AIX.patch --]
[-- Type: application/octet-stream, Size: 26055 bytes --]

From e1db88b16f7e78cd8312eeb729859298cc8d0eab Mon Sep 17 00:00:00 2001
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
Date: Thu, 13 Oct 2022 05:21:36 -0500
Subject: [PATCH] Enable vector instruction debugging for AIX

---
 gdb/aix-thread.c      | 114 +++++++++++++++++++++-
 gdb/rs6000-aix-nat.c  | 220 +++++++++++++++++++++++++++++++++++++++++-
 gdb/rs6000-aix-tdep.c | 213 +++++++++++++++++++++++++++++++++++++++-
 gdb/rs6000-tdep.c     |  67 ++++++-------
 4 files changed, 568 insertions(+), 46 deletions(-)

diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index 57e5756e144..15400f5b90d 100644
--- a/gdb/aix-thread.c
+++ b/gdb/aix-thread.c
@@ -1347,11 +1347,75 @@ fetch_regs_kernel_thread (struct regcache *regcache, int regno,
 	  supply_sprs32 (regcache, sprs32.pt_iar, sprs32.pt_msr, sprs32.pt_cr,
 			 sprs32.pt_lr, sprs32.pt_ctr, sprs32.pt_xer,
 			 sprs32.pt_fpscr);
-
-	  if (tdep->ppc_mq_regnum >= 0)
-	    regcache->raw_supply (tdep->ppc_mq_regnum, (char *) &sprs32.pt_mq);
 	}
+     }
+  /* vector registers */
+  if (tdep->ppc_vr0_regnum != -1 && regno >= tdep->ppc_vr0_regnum)
+  {
+    int ret = 0;
+    int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
+    __vmx_context_t vmx;
+    memset(&vmx, 0, sizeof(__vmx_context_t));
+    if (__power_vmx())
+    {
+       ret = ptrace64 (PTT_READ_VEC, tid, (long long) &vmx, 0, 0);
+       if (ret < 0)
+       {
+         if (errno == ENXIO)
+           return;
+         perror_with_name (_("Unable to fetch AltiVec registers"));
+       }
+       for (i = 0; i < num_of_vrregs; i++)
+         regcache->raw_supply (tdep->ppc_vr0_regnum + i, &(vmx.__vr[i]));
+    }
+  }
+
+  /* vsx registers */
+  if (tdep->ppc_vsr0_upper_regnum != -1 && regno >= tdep->ppc_vsr0_upper_regnum)
+  {
+    __vsx_context_t vsx;
+    memset(&vsx, 0, sizeof(__vsx_context_t));
+    if (__power_vsx())
+    {
+      int ret = 0;
+      ret = ptrace64 (PTT_READ_VSX, tid, (long long) &vsx, 0, 0);
+      if (ret < 0)
+      {
+        if (errno == ENXIO)
+          return;
+        perror_with_name (_("Unable to fetch VSX registers"));
+      }
+    for (i = 0; i < ppc_num_vshrs; i++)
+      regcache->raw_supply (tdep->ppc_vsr0_upper_regnum + i, &(vsx.__vsr_dw1[i]));
     }
+  } 
+}
+
+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 num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
+  int regno;
+
+  for (regno = 0; regno < num_of_vrregs; regno++)
+    if (REG_VALID == regcache->get_register_status (tdep->ppc_vr0_regnum + regno))
+      regcache->raw_collect (tdep->ppc_vr0_regnum + regno,
+                                 &(vmx->__vr[0]) + regno);
+}
+
+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);
 }
 
 /* Fetch register REGNO if != -1 or all registers otherwise from the
@@ -1692,6 +1756,50 @@ store_regs_kernel_thread (const struct regcache *regcache, int regno,
 	  ptrace32 (PTT_WRITE_SPRS, tid, (uintptr_t) &sprs32, 0, NULL);
 	}
     }
+    if (tdep->ppc_vr0_regnum != -1 && regno >= tdep->ppc_vr0_regnum)
+    {
+      int ret = 0;
+      __vmx_context_t vmx;
+      memset(&vmx, 0, sizeof(__vmx_context_t));
+      if (__power_vmx())
+      {
+         ret = ptrace64 (PTT_READ_VEC, tid, (long long) &vmx, 0, 0);
+         if (ret < 0)
+         {
+           if (errno == ENXIO)
+           {
+             warning (_("Unable to fetch AltiVec registers."));
+             return;
+           }
+           fill_altivec(regcache, &vmx);
+           ret = ptrace64 (PTT_WRITE_VEC, tid, (long long) &vmx, 0, 0);
+           if (ret < 0)
+             perror_with_name (_("Unable to store AltiVec register."));
+       }
+     }
+   }
+   /* vmx registers */
+   if (tdep->ppc_vsr0_upper_regnum != -1 && regno >= tdep->ppc_vsr0_upper_regnum)
+   {
+     __vsx_context_t vsx;
+     memset(&vsx, 0, sizeof(__vsx_context_t));
+     if (__power_vsx())
+     {
+        int ret =  ptrace64 (PTT_READ_VSX, tid, (long long) &vsx, 0, 0);
+        if (ret < 0)
+        {
+          if (errno == ENXIO)
+          {
+            warning (_("Unable to fetch VSX registers."));
+            return;
+          }
+        }
+        fill_vsx (regcache, &vsx);
+        ret = ptrace64 (PTT_WRITE_VSX, tid, (long long) &vsx, 0, 0);
+        if (ret < 0)
+          perror_with_name (_("Unable to store VSX register."));
+    }
+  }
 }
 
 /* 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 cb141427696..e989a9a6739 100644
--- a/gdb/rs6000-aix-nat.c
+++ b/gdb/rs6000-aix-nat.c
@@ -54,6 +54,19 @@
 #include <sys/ldr.h>
 #include <sys/systemcfg.h>
 
+#include "gdbthread.h"
+#include <sys/context.h>
+#include <sys/pthdebug.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"
+
+int have_ptrace_getvrregs = 1;
+
+int have_ptrace_getsetvsxregs = 1;
+
 /* 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.  */
@@ -91,6 +104,8 @@ class rs6000_nat_target final : public inf_ptrace_target
 
   ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
 
+  const struct target_desc *read_description ()  override;
+
 protected:
 
   void post_startup_inferior (ptid_t ptid) override
@@ -107,6 +122,82 @@ class rs6000_nat_target final : public inf_ptrace_target
 
 static rs6000_nat_target the_rs6000_nat_target;
 
+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()) 
+  {
+    ret = ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
+    if (ret < 0)
+    {
+       if (errno == ENXIO)
+       {
+         /* have_ptrace_getsetvsxregs = 0; */
+         warning (_("Unable to fetch VSX registers."));
+         return;
+       }
+    }
+  }
+  regcache->raw_collect (regno, &(vsx.__vsr_dw1[0])+
+                       regno - tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace64 (PTT_WRITE_VSX, thrd_i, (long long) &vsx, 0, 0);
+
+  if (ret < 0)
+    perror_with_name (_("Unable to store VSX register."));
+}
+
+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);
+  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  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())  
+  {
+    ret = ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
+    if (ret < 0)
+    {
+       if (errno == ENXIO)
+       {
+         /* have_ptrace_getvrregs = 0; */
+         warning (_("Unable to fetch AltiVec registers."));
+         return;
+       }
+    }
+  }   
+
+  regcache->raw_collect (regno, &(vmx.__vr[0]) + regno
+                                - tdep->ppc_vr0_regnum);
+
+  ret = ptrace64 (PTT_WRITE_VEC, thrd_i, (long long) &vmx, 0, 0);
+  if (ret < 0)
+     perror_with_name (_("Unable to store AltiVec register."));
+
+}
+
 /* Given REGNO, a gdb register number, return the corresponding
    number suitable for use as a ptrace() parameter.  Return -1 if
    there's no suitable mapping.  Also, set the int pointed to by
@@ -264,6 +355,17 @@ store_register (struct regcache *regcache, int regno)
 
   nr = regmap (gdbarch, regno, &isfloat);
 
+  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;
+  }
+
   /* Floating-point registers.  */
   if (isfloat)
     rs6000_ptrace32 (PT_WRITE_FPR, pid, addr, nr, 0);
@@ -305,6 +407,98 @@ store_register (struct regcache *regcache, int regno)
     }
 }
 
+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]));
+}
+
+static void
+fetch_vsx_registers_aix (struct regcache *regcache)
+{
+  int ret;
+  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())  
+  {
+    ret = ptrace64 (PTT_READ_VSX, thrd_i, (long long) &vsx, 0, 0);
+    if (ret < 0)
+    {
+       /* Just fill with 0 zero instead of error return */
+       #if 0
+         if (errno == ENXIO)
+         {
+           have_ptrace_getsetvsxregs = 0;
+           return;
+           perror_with_name (_("Unable to fetch VSX registers"));
+         }
+       #endif
+    }
+  }
+  supply_vsxregset_aix (regcache, &vsx);
+}
+
+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]));
+}
+
+static void
+fetch_altivec_registers_aix (struct regcache *regcache)
+{
+  int ret;
+  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())
+  {  
+    ret = ptrace64 (PTT_READ_VEC, thrd_i, (long long) &vmx, 0, 0);
+    if (ret < 0)
+    {
+       /* Just fill with 0 zero instead of error return */
+       #if 0
+        if (errno == ENXIO)
+         {
+           have_ptrace_getvrregs = 0;
+           return;
+           perror_with_name (_("Unable to fetch AltiVec registers"));
+         }
+       #endif
+    }
+  }   
+  supply_vrregset_aix (regcache, &vmx);
+}
+
+
 /* Read from the inferior all registers if REGNO == -1 and just register
    REGNO otherwise.  */
 
@@ -312,10 +506,6 @@ void
 rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  if (regno != -1)
-    fetch_register (regcache, regno);
-
-  else
     {
       ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
 
@@ -331,7 +521,18 @@ rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
       if (tdep->ppc_fp0_regnum >= 0)
 	for (regno = 0; regno < ppc_num_fprs; regno++)
 	  fetch_register (regcache, tdep->ppc_fp0_regnum + regno);
-
+      
+      if (have_ptrace_getvrregs)
+        if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) 
+        {
+           fetch_altivec_registers_aix (regcache);
+        }
+
+     if (have_ptrace_getsetvsxregs)
+         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);
@@ -346,6 +547,15 @@ rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
     }
 }
 
+const struct target_desc *
+rs6000_nat_target::read_description ()
+{
+   if (ARCH64())
+      return tdesc_powerpc_vsx64;
+   else
+      return tdesc_powerpc_vsx32;
+}
+
 /* 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 d47974b51d1..67ae8a6a54a 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -68,6 +68,22 @@
 /* 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 struct trad_frame_cache *
 aix_sighandle_frame_cache (frame_info_ptr this_frame,
 			   void **this_cache)
@@ -145,7 +161,7 @@ aix_sighandle_frame_prev_register (frame_info_ptr this_frame,
 
 static int
 aix_sighandle_frame_sniffer (const struct frame_unwind *self,
-			     frame_info_ptr this_frame,
+			     frame_info_ptr this_frame, 
 			     void **this_prologue_cache)
 {
   CORE_ADDR pc = get_frame_pc (this_frame);
@@ -237,6 +253,190 @@ rs6000_aix_collect_regset (const struct regset *regset,
   ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
 }
 
+/* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+static int
+rs6000_aix_vsx_support_p (struct gdbarch *gdbarch)
+{
+  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+  return tdep->ppc_vsr0_regnum >= 0;
+}
+
+/* Return non-zero if the architecture described by GDBARCH has
+   Altivec registers (vr0 --- vr31, vrsave and vscr).  */
+static int
+rs6000_aix_altivec_support_p (struct gdbarch *gdbarch)
+{
+  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+  return (tdep->ppc_vr0_regnum >= 0
+   && tdep->ppc_vrsave_regnum >= 0);
+}
+
+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;
+
+  if (!rs6000_aix_altivec_support_p (gdbarch))
+    return;
+  
+  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+  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 ();
+
+  if (!rs6000_aix_vsx_support_p (gdbarch))
+    return;
+
+  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+  if (regnum == -1)
+  {
+    int i, offset = 0;
+
+    for (i = tdep->ppc_vsr0_upper_regnum;
+     i < tdep->ppc_vsr0_upper_regnum + 32;
+                           i++, offset++)
+      ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, offset * 8, 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 ();
+
+  if (!rs6000_aix_vsx_support_p (gdbarch))
+    return;
+
+  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+  if (regnum == -1)
+  {
+    int i;
+
+    for (i = tdep->ppc_vsr0_upper_regnum;
+     i < tdep->ppc_vsr0_upper_regnum + 32;
+                                     i++)
+      ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, 0, 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;
+
+  if (!rs6000_aix_altivec_support_p (gdbarch))
+    return;
+
+  ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+  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_aix32_vrregset = {
+  &rs6000_aix_vrreg_offset,
+  rs6000_aix_supply_vrregset,
+  rs6000_aix_collect_vrregset
+};
+
+static const struct regset rs6000_aix32_vsxregset = {
+  &rs6000_aix_vrreg_offset,
+  rs6000_aix_supply_vsxregset,
+  rs6000_aix_collect_vsxregset
+};
 /* AIX register set.  */
 
 static const struct regset rs6000_aix32_regset =
@@ -262,10 +462,19 @@ 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_aix32_vrregset, "AIX altivec", cb_data);
+
+  if (have_vsx)
+   cb (".aix-vsx", 256, 256, &rs6000_aix32_vsxregset, "AIX vsx", cb_data);    
 }
 
 
@@ -351,7 +560,7 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       arg = args[argno];
       type = check_typedef (value_type (arg));
-      len = type->length ();
+      len = type->length (); 
 
       if (type->code () == TYPE_CODE_FLT)
 	{
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 8b6d666bbe7..6e8ffc5fb0d 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1972,7 +1972,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       /* 001110 00000 00000 iiii iiii iiii iiii  */
       /* 001110 01110 00000 iiii iiii iiii iiii  */
       else if ((op & 0xffff0000) == 0x38000000         /* li r0, SIMM */
-	       || (op & 0xffff0000) == 0x39c00000)     /* li r14, SIMM */
+	       || (op & 0xffff0000) == 0x39c00000     /* li r14, SIMM */
+               || (op & 0xff0f0000) == 0x38000000)     /* li, r4, SIMM */ 
 	{
 	  if ((op & 0xffff0000) == 0x38000000)
 	    r0_contains_arg = 0;
@@ -1986,24 +1987,21 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 	}
       /* Store vector register S at (r31+r0) aligned to 16 bytes.  */      
       /* 011111 sssss 11111 00000 00111001110 */
-      else if ((op & 0xfc1fffff) == 0x7c1f01ce)   /* stvx Vs, R31, R0 */
-	{
-	  if (pc == (li_found_pc + 4))
-	    {
-	      vr_reg = GET_SRC_REG (op);
-	      /* If this is the first vector reg to be saved, or if
-		 it has a lower number than others previously seen,
-		 reupdate the frame info.  */
-	      if (fdata->saved_vr == -1 || fdata->saved_vr > vr_reg)
-		{
-		  fdata->saved_vr = vr_reg;
-		  fdata->vr_offset = vr_saved_offset + offset;
-		}
-	      vr_saved_offset = -1;
-	      vr_reg = -1;
-	      li_found_pc = 0;
-	    }
-	}
+      else if ((op & 0xfc1fffff) == 0x7c1f01ce   /* stvx Vs, R31, R0 */
+               || (op & 0xfc1fffff) == 0x7c012f99 /* stxvd2x Vs,r1, r5 */
+               || (op & 0xfc1fffff) == 0x7c012f98 /* stxvd2x vs0, r1, r5 */
+               || (op & 0xfc1ff000) == 0x7c012000)   
+      {
+        vr_reg = GET_SRC_REG (op);
+        /* If this is the first vector reg to be saved, or if
+       	   it has a lower number than others previously seen,
+       	   reupdate the frame info.  */
+        fdata->saved_vr = vr_reg;
+        fdata->vr_offset = vr_saved_offset;
+        vr_saved_offset = -1;
+        vr_reg = -1;
+        li_found_pc = 0;
+      }
       /* End AltiVec related instructions.  */
 
       /* Start BookE related instructions.  */
@@ -2665,8 +2663,8 @@ rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
 	  && regnum >= tdep->ppc_fp0_regnum
 	  && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs
 	  && type->code () == TYPE_CODE_FLT
-	  && (type->length ()
-	      != builtin_type (gdbarch)->builtin_double->length ()));
+          && (type->length ()
+              != builtin_type (gdbarch)->builtin_double->length ()));
 }
 
 static int
@@ -3466,7 +3464,7 @@ struct ppc_variant
     unsigned long mach;
 
     /* Target description for this variant.  */
-    const struct target_desc **tdesc;
+    struct target_desc **tdesc;
   };
 
 static struct ppc_variant variants[] =
@@ -3474,7 +3472,7 @@ static struct ppc_variant variants[] =
   {"powerpc", "PowerPC user-level", bfd_arch_powerpc,
    bfd_mach_ppc, &tdesc_powerpc_altivec32},
   {"power", "POWER user-level", bfd_arch_rs6000,
-   bfd_mach_rs6k, &tdesc_rs6000},
+   bfd_mach_rs6k, &tdesc_powerpc_vsx32},
   {"403", "IBM PowerPC 403", bfd_arch_powerpc,
    bfd_mach_ppc_403, &tdesc_powerpc_403},
   {"405", "IBM PowerPC 405", bfd_arch_powerpc,
@@ -3504,7 +3502,7 @@ static struct ppc_variant variants[] =
   {"powerpc64", "PowerPC 64-bit user-level", bfd_arch_powerpc,
    bfd_mach_ppc64, &tdesc_powerpc_altivec64},
   {"620", "Motorola PowerPC 620", bfd_arch_powerpc,
-   bfd_mach_ppc_620, &tdesc_powerpc_64},
+   bfd_mach_ppc_620, &tdesc_powerpc_vsx64},
   {"630", "Motorola PowerPC 630", bfd_arch_powerpc,
    bfd_mach_ppc_630, &tdesc_powerpc_64},
   {"a35", "PowerPC A35", bfd_arch_powerpc,
@@ -3680,18 +3678,15 @@ rs6000_frame_cache (frame_info_ptr this_frame, void **this_cache)
   /* if != -1, fdata.saved_vr is the smallest number of saved_vr.
      All vr's from saved_vr to vr31 are saved.  */
   if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
-    {
-      if (fdata.saved_vr >= 0)
-	{
-	  int i;
-	  CORE_ADDR vr_addr = cache->base + fdata.vr_offset;
-	  for (i = fdata.saved_vr; i < 32; i++)
-	    {
-	      cache->saved_regs[tdep->ppc_vr0_regnum + i].set_addr (vr_addr);
-	      vr_addr += register_size (gdbarch, tdep->ppc_vr0_regnum);
-	    }
-	}
-    }
+  {
+    int i;
+    CORE_ADDR vr_addr = cache->base + fdata.vr_offset;
+    for (i = 0; i < 66; i++)
+    {
+      cache->saved_regs[tdep->ppc_vsr0_upper_regnum + i].set_addr (vr_addr);
+      vr_addr += register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+    } 
+  } 
 
   /* if != -1, fdata.saved_ev is the smallest number of saved_ev.
      All vr's from saved_ev to ev31 are saved. ?????  */
-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2023-03-09  2:21 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-13 10:52 [PATCH] Enable vector instruction debugging for AIX 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
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

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).