public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
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: Thu, 23 Feb 2023 12:49:25 +0000	[thread overview]
Message-ID: <CH2PR15MB3544A7B221FE70CDE58ADE27D6AB9@CH2PR15MB3544.namprd15.prod.outlook.com> (raw)
In-Reply-To: <02d8d62d9980ea5ae8e30b3ee1e7ac46a1b9f412.camel@de.ibm.com>


[-- Attachment #1.1: Type: text/plain, Size: 17789 bytes --]

Hi Ulrich and community,

Please find attached the patch. {See: 0001-Enable-vector-instruction-debugging-for-AIX.patch}.

Please see my comments in blue.

Kindly suggest for changes if needed and review this patch.

Have a nice day ahead.

Thanks and regards,
Aditya.

>So you're now using ptrace here as well.  From what I
>understand, this wrong - ptrace can only be used with
>kernel threads.  For user threads, registers need to
>be retrieved from the context managed by the thread
>library and retrieved via pthdb_pthread_context.

>Shouldn't the vector registers then also come from there?

>Do you have a way to test with using user threads?

Yes. So I did not get this back then. As my learning increased via the threads bug we had just solved I understood what you are trying to tell me here. Kindly see pdc_read_regs () and pdc_write_regs ().
We now do it via pthdb_pthread_context ().

Kindly see code 1 which uses user threads and it sample output 1. It works alright. Even our alti-vec-regs.exp testcase in test suite passes.

>>(gdb) info reg vr0
>>vr0            {uint128 = <unavailable>, v4_float = {<unavailable>, <unavailable>, <unavailable>, >><unavailable>}, v4_int32 = {<unavailable>, <unavailable>, <unavailable>, <unavailable>}, v8_int16 = >>{<unavailable>, <unavailable>, <unavailable>, <unavailable>, <unavailable>, <unavailable>, >><unavailable>, <unavailable>}, v16_int8 = {<unavailable> <repeats 16 times>}}

>I still don't quite understand the intended behavior.  As far
>as I can see, there are three possible states:

>- The machine doesn't have any vector registers
>  (i.e. __power_vmx() returns 0)
If it doesn’t have we do not do any thing. We do not even say machine does not have any vector registers. Hence no else part to this if condition.

>- The machine does have vector registers, but the inferior
>  process does not use them
 > (i.e. __power_vmx() returns 1 but ptrace returns an error)

In this we intend to show it unavailable. Because till the user uses vector registers it has to be unavailable.

- The inferior process uses vector registers
  (i.e. no error from ptrace)
Here we show the value.

>What is the intended behavior in those cases?  In particular,
>should GDB behave differently between the first and the
>second case?  Should GDB not show any vector registers at all,
>should it show vector registers as <unavailable>, or should
>it show vector registers containing zero?

In Linux I have seen they show a 0, in the second case. So do we also do the same?
When I tried doing so, I can tell you ptrace () did not allow me to write 0 as well in store_vsx_register_aix(), since till user or debugee code actually uses it, it is unavailable. So we cannot write 0 in the ptrace call via PT_WRITE_VEC.

But yeah, we can use this regcache->raw_collect (), set to 0 in GDB data structures and return. We won’t be able to write 0 though through ptrace call in the kernel. This way we can show users it is zero like in the linux world. So shall we do it?


>>>+      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);
>
>>>Just noticed this here.  Everywhere else in this file, a *pid* is
>>>passed to rs6000_ptrace64/32.  Only in this new routine, you're
>>>apparently passing a thread ID.   Why should this be different just
>>>for these registers?  Shouldn't per-thread registers be handled in
>>>aix-thread.c anyway?
>>Well, this is because in the documentation I read, I did not find something
>>like a PT_READ_VSX that I can use. All I have is PTT_READ_VSX and in AIX
>>PTT _* options are usually thread IDs.. I am restricted.. If it existed,
>>I would have loved to use it. Like for writing general purpose registers
>>we have PTT_WRITE_GPRS and PT_WRITE_GPRS and can use it as per convenience
>>of thread or process..

>Huh.  This is really strange, and doesn't quite map on the current GDB
>implementation.  Everything related to thread IDs is currently done in
>the aix-threads.c file.  It seems not really clean to mix this up.

>How is this intended to be used?

>If we need thread IDs anyway (and apparently we can always get a thread
>ID even for a non-threaded process?), should we just use the aix-thread.c
>methods for all processes?

The online documentation I read { https://www.ibm.com/docs/en/aix/7.2?topic=p-ptrace-ptracex-ptrace64-subroutine } said The PTT_READ_VEC request reads the vector register state of the specified thread. There is no PT_READ_VEC or any call that takes <pid> to get vector registers in any online or internal documents I searched. So we need a thread ID to fetch vector registers.

Coming to just using aix-thread.c for all process, I did try it today. What is happening is fetch_registers () in aix-thread.c is not getting called after the thread target is set for any debugee that does not use pthreads or is multi threaded once the pthdebug session is established. {Like the program with name “code 2” pasted below this email}. Only while the process is getting born it does call fetch_registers () in the rs6000-aix-nat.c . If we can make the thread target to call fetch_registers () once the thread target is set it will work. But is that correct?

>As an aside, I don't see any documentation of PTT_READ_VSX either.
>Do you know since when this is supported?
From the documentation  I read it is 2009.

+  if (altivec_register_p (gdbarch, regno))
+    fetch_altivec_registers_aix (regcache);
+  if (vsx_register_p (gdbarch, regno))
+    fetch_vsx_registers_aix (regcache);

>I meant that you should skip everything else in those cases:

 > if (altivec_register_p (gdbarch, regno))
 >   {
 >     fetch_altivec_registers_aix (regcache);
>      return;

>just like in store_register.

This is also done.

>>Since for the stxvd2x instruction, the last bit is part of the
>>register number, these two lines should be merged into:
> > >            || (op & 0xfc1ffffe) == 0x7c012f98 /* stxvd2x Vs, r1, r5 */
>>
>>>As above, the comment needs to be updated to match.

>>You should still do this (the 0x...e mask, and the comment).

I did not get this.. Kindly give me more information.

>Well, at the very least this needs to be announced in the NEWS file.

>This still mentions AIX 4 being supported.

So what is the process and when do we do it. Do we do it after the commit of this patch??

There's still this one in there:
>-   bfd_mach_rs6k, &tdesc_rs6000},
>+   bfd_mach_rs6k, &tdesc_powerpc_vsx32},

>I don't think this should be needed either.
This I have removed.

----------------------------------------------------------
Code 1:-
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>

pthread_barrier_t barrier;

#define NUM_THREADS 3

void *
thread_function (void *arg)
{
  /* This ensures that the breakpoint is only hit after both threads
     are created, so the test can always switch to the non-event
     thread when the breakpoint triggers.  */
  pthread_barrier_wait (&barrier);

  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[0] + Arr2[0];
        printf("Arr3[1] = { %d, %d, %d, %d }\n", Arr3[1][0], Arr3[1][1], Arr3[1][2], Arr3[1][3]);



  while (1); /* break here */
}

int
main (void)
{
  int i;

  alarm (300);

  pthread_barrier_init (&barrier, NULL, NUM_THREADS);

  for (i = 0; i < NUM_THREADS; i++)
    {
      pthread_t thread;
      int res;

      res = pthread_create (&thread, NULL,
                            thread_function, NULL);
      assert (res == 0);
    }

  while (1)
    sleep (1);

  return 0;
}
-----------------------------------------------------
Output with patch:-
Reading symbols from /home/aditya/gdb_tests/vector_thread_test...
(gdb) r
Starting program: /home/aditya/gdb_tests/vector_thread_test
Adding Arrays
Arr3[1] = { 2, 4, 6, 8 }
Adding Arrays
Arr3[1] = { 2, 4, 6, 8 }
Adding Arrays
Arr3[1] = { 2, 4, 6, 8 }
[New Thread 258]
[New Thread 515]
[New Thread 772]

Thread 2 received signal SIGINT, Interrupt.
[Switching to Thread 258]
thread_function (arg=0x0) at /home/aditya/gdb_tests/vector_thread_test.c:63
63        while (1); /* break here */
(gdb) info reg $vr0
vr0            {uint128 = 0x2000000040000000600000008, v4_float = {0x2, 0x4, 0x6, 0x8}, v4_int32 = {0x2, 0x4, 0x6, 0x8}, v8_int16 = {0x0, 0x2, 0x0, 0x4, 0x0, 0x6, 0x0, 0x8}, v16_int8 = {0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x8}}
(gdb) thread 2
[Switching to thread 2 (Thread 258)]
#0  thread_function (arg=
0x0) at /home/aditya/gdb_tests/vector_thread_test.c:63
63        while (1); /* break here */
(gdb) info reg $vr0
vr0            {uint128 = 0x2000000040000000600000008, v4_float = {0x2, 0x4, 0x6, 0x8}, v4_int32 = {0x2, 0x4, 0x6, 0x8}, v8_int16 = {0x0, 0x2, 0x0, 0x4, 0x0, 0x6, 0x0, 0x8}, v16_int8 = {0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x8}}
(gdb)
----------------------------------------
Code 2:-
#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;
}
------------------------------
Sample output 2:-
Reading symbols from /home/aditya/gdb_tests/vector_lab_test...
(gdb) b main
Breakpoint 1 at 0x1000052c: file /home/aditya/gdb_tests/vector_lab_test.c, line 3.
(gdb) r
Starting program: /home/aditya/gdb_tests/vector_lab_test

Breakpoint 1, main () at /home/aditya/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)
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)

From: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date: Wednesday, 16 November 2022 at 12:33 AM
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:

>>I just noticed that there seem to be two methods, handling
>>user threads and kernel threads, respectively.  You patch
>>only adds support for VMX/VSX registers to kernel threads
>>-- should this also be done for user threads?  (Same applies
>>to store_regs_... of course.)
>
>Yes, this I have added in the new patch..

So you're now using ptrace here as well.  From what I
understand, this wrong - ptrace can only be used with
kernel threads.  For user threads, registers need to
be retrieved from the context managed by the thread
library and retrieved via pthdb_pthread_context.

Shouldn't the vector registers then also come from there?

Do you have a way to test with using user threads?


>>So if access to VMX registers fails because ptrace fails,
>>you now zero out the registers.  But if access fails because
>>__power_vmx() fails, the registers are left undefined.
>
>>Is this intentional?  What the meaning of this difference?
>
>So, if VMX register fails I will get an output like this below.
>Otherwise, I set to 0 like it is in all other places. So I am
>not doing any special handling..
>
>(gdb) info reg vr0
>vr0            {uint128 = <unavailable>, v4_float = {<unavailable>, <unavailable>, <unavailable>, <unavailable>}, v4_int32 = {<unavailable>, <unavailable>, <unavailable>, <unavailable>}, v8_int16 = {<unavailable>, <unavailable>, <unavailable>, <unavailable>, <unavailable>, <unavailable>, <unavailable>, <unavailable>}, v16_int8 = {<unavailable> <repeats 16 times>}}

I still don't quite understand the intended behavior.  As far
as I can see, there are three possible states:

- The machine doesn't have any vector registers
  (i.e. __power_vmx() returns 0)
- The machine does have vector registers, but the inferior
  process does not use them
  (i.e. __power_vmx() returns 1 but ptrace returns an error)
- The inferior process uses vector registers
  (i.e. no error from ptrace)

What is the intended behavior in those cases?  In particular,
should GDB behave differently between the first and the
second case?  Should GDB not show any vector registers at all,
should it show vector registers as <unavailable>, or should
it show vector registers containing zero?


>>>+      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);
>
>>Just noticed this here.  Everywhere else in this file, a *pid* is
>>passed to rs6000_ptrace64/32.  Only in this new routine, you're
>>apparently passing a thread ID.   Why should this be different just
>>for these registers?  Shouldn't per-thread registers be handled in
>>aix-thread.c anyway?
>
>Well, this is because in the documentation I read, I did not find something
>like a PT_READ_VSX that I can use. All I have is PTT_READ_VSX and in AIX
>PTT _* options are usually thread IDs.. I am restricted.. If it existed,
>I would have loved to use it. Like for writing general purpose registers
>we have PTT_WRITE_GPRS and PT_WRITE_GPRS and can use it as per convenience
>of thread or process..

Huh.  This is really strange, and doesn't quite map on the current GDB
implementation.  Everything related to thread IDs is currently done in
the aix-threads.c file.  It seems not really clean to mix this up.

How is this intended to be used?

If we need thread IDs anyway (and apparently we can always get a thread
ID even for a non-threaded process?), should we just use the aix-thread.c
methods for all processes?

As an aside, I don't see any documentation of PTT_READ_VSX either.
Do you know since when this is supported?


>>I think you should call this only if the requested regno
>>actually *is* a VMX or VSX register.  Also, if this is the
>>case, you don't need to do anything else in this routine.
>>This should be separate checks at the beginning of the
>>routine, just like you now do in store_register.
>
>I have taken care of it in the new patch..

+  if (altivec_register_p (gdbarch, regno))
+    fetch_altivec_registers_aix (regcache);
+  if (vsx_register_p (gdbarch, regno))
+    fetch_vsx_registers_aix (regcache);

I meant that you should skip everything else in those cases:

  if (altivec_register_p (gdbarch, regno))
    {
      fetch_altivec_registers_aix (regcache);
      return;
    }
  if (vsx_register_p (gdbarch, regno))
    {
      fetch_vsx_registers_aix (regcache);
      return;
    }

just like in store_register.



>>Since for the stxvd2x instruction, the last bit is part of the
>>register number, these two lines should be merged into:
> >             || (op & 0xfc1ffffe) == 0x7c012f98 /* stxvd2x Vs, r1, r5 */
>
>>As above, the comment needs to be updated to match.

You should still do this (the 0x...e mask, and the comment).

>>This means that on older AIX versions, GDB simply won't work anymore,
>>right?  If so, I guess I'll leave if up to you to decide whether this
>>is acceptable.  But the minimum supported version should be documented
>>somewhere (there's still at least mention of AIX 4.x being supported).
>>Also, if we do switch the minimum supported version, I think there's
>>quite a bit of existing code intended to handle old versions that could
>>then just be removed ...
>
>How would you like me to document this. Let me know.. And we can work
>out if possible, via another patch to remove handling the old version codes.

Well, at the very least this needs to be announced in the NEWS file.

This still mentions AIX 4 being supported.


>>Should we change the default for "Motorola PowerPC 620"
>>at this stage?  Can we even test on that machine?
>>>ANS = No. No we cannot test on that machine.
>
>I have removed the same in this patch...

There's still this one in there:

   {"power", "POWER user-level", bfd_arch_rs6000,
-   bfd_mach_rs6k, &tdesc_rs6000},
+   bfd_mach_rs6k, &tdesc_powerpc_vsx32},

I don't think this should be needed either.

Bye,
Ulrich

[-- Attachment #2: 0001-Enable-vector-instruction-debugging-for-AIX.patch --]
[-- Type: application/octet-stream, Size: 26339 bytes --]

From a903782a49917e72ba28982d966c3afe696c3a9f Mon Sep 17 00:00:00 2001
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
Date: Thu, 23 Feb 2023 05:57:30 -0600
Subject: [PATCH] Enable vector instruction debugging for AIX

---
 gdb/aix-thread.c      | 254 +++++++++++++++++++++++++++++++++++++++++-
 gdb/rs6000-aix-nat.c  | 221 ++++++++++++++++++++++++++++++++++++
 gdb/rs6000-aix-tdep.c | 182 ++++++++++++++++++++++++++++++
 gdb/rs6000-tdep.c     |   3 +-
 4 files changed, 658 insertions(+), 2 deletions(-)

diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index 4184c87a92b..4a912c3947a 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,30 @@ pdc_read_regs (pthdb_user_t user_current_pid,
 	  memcpy (&context->msr, &sprs32, sizeof(sprs32));
 	}
     }  
+
+  /* vector registers.  */
+  __vmx_context_t vmx;
+  if (__power_vmx())
+  {
+    if (data->arch64)
+      if (!ptrace64aix (PTT_READ_VEC, tid, (long long) &vmx, 0, 0))
+	memcpy (&context->vmx, &vmx, sizeof(__vmx_context_t));
+    else
+      if (!ptrace32 (PTT_READ_VEC, tid, (long long) &vmx, 0, 0))
+	memcpy (&context->vmx, &vmx, sizeof(__vmx_context_t));
+  }
+
+  /* vsx registers.  */
+  __vsx_context_t vsx;
+  if (__power_vsx())
+  {
+    if (data->arch64)
+      if (!ptrace64aix (PTT_READ_VSX, tid, (long long) &vsx, 0, 0))
+	memcpy (&context->vsx, &vsx, sizeof(__vsx_context_t));
+    else
+      if (!ptrace32 (PTT_READ_VSX, tid, (long long) &vsx, 0, 0))
+	memcpy (&context->vsx, &vsx, sizeof(__vsx_context_t));  
+  }
   return 0;
 }
 
@@ -531,6 +564,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())
+  {
+    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())
+  {
+    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 +1223,34 @@ 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; 
+  int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;            
+  for (regno = 0; regno < num_of_vrregs; regno++)
+     regcache->raw_supply (tdep->ppc_vr0_regnum + regno, 
+			   &(vmx.__vr[regno]));
+}
+
+/* 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_regnum + regno, 
+                           &(vsx.__vsr_dw1[regno]));
+}
+
 /* Record that the 64-bit general-purpose registers contain VALS.  */
 
 static void
@@ -1321,6 +1400,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 +1465,43 @@ fetch_regs_kernel_thread (struct regcache *regcache, int regno,
 	}
     }
 
+  /* vector registers.  */
+  if (tdep->ppc_vr0_regnum != -1)
+    {
+      int ret = 0;
+      int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
+      __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, (uintptr_t) &vmx, 0, 0);
+        if (ret < 0)
+          memset(&vmx, 0, sizeof(__vmx_context_t));
+        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)
+    {
+      __vsx_context_t vsx;
+      if (__power_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 +1569,37 @@ 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 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[regno]));
+}
+
+/* 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 +1735,10 @@ 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;
+  int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
 
   if (debug_aix_thread)
     gdb_printf (gdb_stdlog, 
@@ -1594,6 +1751,40 @@ 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));
+    if (data->arch64)
+    {
+      for (i = 0; i < num_of_vrregs; 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]; 
+	  }
+    }
+  }
+
+  /* Fill vsx registers. */
+
+  if (__power_vsx())
+  {
+    memset(&vsx, 0, sizeof(__vsx_context_t));
+    if (data->arch64)
+    {
+      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 +1865,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 +1958,66 @@ 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)
+        {
+          if (errno == ENXIO)
+          {
+            warning (_("Unable to fetch AltiVec registers."));
+            memset(&vmx, 0, sizeof(__vmx_context_t)); 
+          }
+          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."));
+        }
+      }
+    }
+
+    /* vmx registers.  */
+    if (tdep->ppc_vsr0_upper_regnum != -1  && tdep->ppc_vrsave_regnum != -1
+      && (regno == -1 || (regno >= tdep->ppc_vsr0_upper_regnum
+      && regno <= tdep->ppc_vrsave_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)
+        {
+          if (errno == ENXIO)
+          {
+            warning (_("Unable to fetch VSX registers."));
+            memset(&vsx, 0, sizeof(__vsx_context_t)); 
+          }
+        }
+        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."));
+      }
+   }  
 }
 
 /* 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..1911d8f768e 100644
--- a/gdb/rs6000-aix-nat.c
+++ b/gdb/rs6000-aix-nat.c
@@ -58,6 +58,15 @@
 #include <procinfo.h>
 #include <sys/types.h>
 
+/* Header files for alti-vec reg.  */
+#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"
+
 /* 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 +108,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 +283,175 @@ 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())
+  {
+    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)
+    {
+       if (errno == ENXIO)
+       {
+         warning (_("Unable to fetch VSX registers."));
+         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 store VSX register."));
+}
+
+/* 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())
+  {
+    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)
+    {
+       if (errno == ENXIO)
+       {
+         warning (_("Unable to fetch AltiVec registers."));
+         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."));
+
+}
+
+/* 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]));
+}
+
+/* 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())
+  {
+    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())
+  {
+    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 +506,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 +582,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 +664,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 +684,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 15602c80b00..78d16f2a217 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); 
+
 }
 
 
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 592b447948e..a976cc6a3b3 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1986,7 +1986,8 @@ 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 */
+      else if ((op & 0xfc1fffff) == 0x7c1f01ce   /* stvx Vs, R31, R0 */
+		|| (op & 0xfc1fffff) == 0x7c012f98) /* stxvd2x vs0, r1, r5 */
 	{
 	  if (pc == (li_found_pc + 4))
 	    {
-- 
2.38.3


  reply	other threads:[~2023-02-23 12:49 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 [this message]
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

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=CH2PR15MB3544A7B221FE70CDE58ADE27D6AB9@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).