2002-03-27 Elena Zannoni <ezannoni@redhat.com>
authorElena Zannoni <ezannoni@kwikemart.cygnus.com>
Thu, 28 Mar 2002 00:48:41 +0000 (00:48 +0000)
committerElena Zannoni <ezannoni@kwikemart.cygnus.com>
Thu, 28 Mar 2002 00:48:41 +0000 (00:48 +0000)
* rs6000-tdep.c (struct rs6000_framedata): Add fields for AltiVec
vector registers handling.
(skip_prologue): Handle new AltiVec instructions.  Fill in new
fields of frame data.
(frame_get_saved_regs): Fill in information for AltiVec registers.

gdb/ChangeLog
gdb/rs6000-tdep.c

index af8bb5e071f13521db16ca575ca93dea919bcb95..40fdcc7d6bf08f55467ab3a577d29b17275f9de8 100644 (file)
@@ -1,3 +1,11 @@
+2002-03-27  Elena Zannoni  <ezannoni@redhat.com>
+
+       * rs6000-tdep.c (struct rs6000_framedata): Add fields for AltiVec
+       vector registers handling.
+       (skip_prologue): Handle new AltiVec instructions.  Fill in new
+       fields of frame data.
+       (frame_get_saved_regs): Fill in information for AltiVec registers.
+
 2002-03-27  Jim Blandy  <jimb@redhat.com>
 
        * symtab.h (SYMBOL_INIT_MANGLED_NAME): Turn this macro's body into
index 9e4d668ca4c26eeff509d28e01e5f139e004c9fe..e21fdad51279bc2e87ef444ed17fbb31e090b6f3 100644 (file)
@@ -64,13 +64,16 @@ struct rs6000_framedata
                                   the frame */
     int saved_gpr;             /* smallest # of saved gpr */
     int saved_fpr;             /* smallest # of saved fpr */
+    int saved_vr;               /* smallest # of saved vr */
     int alloca_reg;            /* alloca register number (frame ptr) */
     char frameless;            /* true if frameless functions. */
     char nosavedpc;            /* true if pc not saved. */
     int gpr_offset;            /* offset of saved gprs from prev sp */
     int fpr_offset;            /* offset of saved fprs from prev sp */
+    int vr_offset;              /* offset of saved vrs from prev sp */
     int lr_offset;             /* offset of saved lr */
     int cr_offset;             /* offset of saved cr */
+    int vrsave_offset;          /* offset of saved vrsave register */
   };
 
 /* Description of a single register. */
@@ -362,12 +365,15 @@ rs6000_software_single_step (enum target_signal signal,
    which we decrement the sp to allocate the frame.
    - saved_gpr is the number of the first saved gpr.
    - saved_fpr is the number of the first saved fpr.
+   - saved_vr is the number of the first saved vr.
    - alloca_reg is the number of the register used for alloca() handling.
    Otherwise -1.
    - gpr_offset is the offset of the first saved gpr from the previous frame.
    - fpr_offset is the offset of the first saved fpr from the previous frame.
+   - vr_offset is the offset of the first saved vr from the previous frame.
    - lr_offset is the offset of the saved lr
    - cr_offset is the offset of the saved cr
+   - vrsave_offset is the offset of the saved vrsave register
  */
 
 #define SIGNED_SHORT(x)                                                \
@@ -434,11 +440,15 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 {
   CORE_ADDR orig_pc = pc;
   CORE_ADDR last_prologue_pc = pc;
+  CORE_ADDR li_found_pc = 0;
   char buf[4];
   unsigned long op;
   long offset = 0;
+  long vr_saved_offset = 0;
   int lr_reg = -1;
   int cr_reg = -1;
+  int vr_reg = -1;
+  int vrsave_reg = -1;
   int reg;
   int framep = 0;
   int minimal_toc_loaded = 0;
@@ -463,6 +473,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
   memset (fdata, 0, sizeof (struct rs6000_framedata));
   fdata->saved_gpr = -1;
   fdata->saved_fpr = -1;
+  fdata->saved_vr = -1;
   fdata->alloca_reg = -1;
   fdata->frameless = 1;
   fdata->nosavedpc = 1;
@@ -581,8 +592,8 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          break;
 
        }
-      else if (((op & 0xffff0000) == 0x801e0000 ||     /* lwz 0,NUM(r30), used
-                                                          in V.4 -mrelocatable */
+      else if (((op & 0xffff0000) == 0x801e0000 ||   /* lwz 0,NUM(r30), used
+                                                       in V.4 -mrelocatable */
                op == 0x7fc0f214) &&    /* add r30,r0,r30, used
                                           in V.4 -mrelocatable */
               lr_reg == 0x901e0000)
@@ -590,8 +601,8 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          continue;
 
        }
-      else if ((op & 0xffff0000) == 0x3fc00000 ||      /* addis 30,0,foo@ha, used
-                                                          in V.4 -mminimal-toc */
+      else if ((op & 0xffff0000) == 0x3fc00000 ||  /* addis 30,0,foo@ha, used
+                                                     in V.4 -mminimal-toc */
               (op & 0xffff0000) == 0x3bde0000)
        {                       /* addi 30,30,foo@l */
          continue;
@@ -602,17 +613,17 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
                                   to save fprs??? */
 
          fdata->frameless = 0;
-         /* Don't skip over the subroutine call if it is not within the first
-            three instructions of the prologue.  */
+         /* Don't skip over the subroutine call if it is not within
+            the first three instructions of the prologue.  */
          if ((pc - orig_pc) > 8)
            break;
 
          op = read_memory_integer (pc + 4, 4);
 
-         /* At this point, make sure this is not a trampoline function
-            (a function that simply calls another functions, and nothing else).
-            If the next is not a nop, this branch was part of the function
-            prologue. */
+         /* At this point, make sure this is not a trampoline
+            function (a function that simply calls another functions,
+            and nothing else).  If the next is not a nop, this branch
+            was part of the function prologue. */
 
          if (op == 0x4def7b82 || op == 0)      /* crorc 15, 15, 15 */
            break;              /* don't skip over 
@@ -658,8 +669,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 
          /* store parameters in stack */
        }
-      else if ((op & 0xfc1f0000) == 0x90010000 ||      /* st rx,NUM(r1) */
-              (op & 0xfc1f0003) == 0xf8010000 ||       /* std rx,NUM(r1) */
+      else if ((op & 0xfc1f0003) == 0xf8010000 ||      /* std rx,NUM(r1) */
               (op & 0xfc1f0000) == 0xd8010000 ||       /* stfd Rx,NUM(r1) */
               (op & 0xfc1f0000) == 0xfc010000)         /* frsp, fp?,NUM(r1) */
        {
@@ -692,8 +702,74 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          framep = 1;
          fdata->alloca_reg = (op & ~0x38010000) >> 21;
          continue;
-
        }
+      /* AltiVec related instructions.  */
+      /* Store the vrsave register (spr 256) in another register for
+        later manipulation, or load a register into the vrsave
+        register.  2 instructions are used: mfvrsave and
+        mtvrsave.  They are shorthand notation for mfspr Rn, SPR256
+        and mtspr SPR256, Rn.  */
+      /* mfspr Rn SPR256 == 011111 nnnnn 0000001000 01010100110
+        mtspr SPR256 Rn == 011111 nnnnn 0000001000 01110100110  */
+      else if ((op & 0xfc1fffff) == 0x7c0042a6)    /* mfvrsave Rn */
+       {
+          vrsave_reg = GET_SRC_REG (op);
+         continue;
+       }
+      else if ((op & 0xfc1fffff) == 0x7c0043a6)     /* mtvrsave Rn */
+        {
+          continue;
+        }
+      /* Store the register where vrsave was saved to onto the stack:
+         rS is the register where vrsave was stored in a previous
+        instruction.  */
+      /* 100100 sssss 00001 dddddddd dddddddd */
+      else if ((op & 0xfc1f0000) == 0x90010000)     /* stw rS, d(r1) */
+        {
+          if (vrsave_reg == GET_SRC_REG (op))
+           {
+             fdata->vrsave_offset = SIGNED_SHORT (op) + offset;
+             vrsave_reg = -1;
+           }
+          continue;
+        }
+      /* Compute the new value of vrsave, by modifying the register
+         where vrsave was saved to.  */
+      else if (((op & 0xfc000000) == 0x64000000)    /* oris Ra, Rs, UIMM */
+              || ((op & 0xfc000000) == 0x60000000))/* ori Ra, Rs, UIMM */
+       {
+         continue;
+       }
+      /* li r0, SIMM (short for addi r0, 0, SIMM).  This is the first
+        in a pair of insns to save the vector registers on the
+        stack.  */
+      /* 001110 00000 00000 iiii iiii iiii iiii  */
+      else if ((op & 0xffff0000) == 0x38000000)    /* li r0, SIMM */
+       {
+         li_found_pc = pc;
+         vr_saved_offset = SIGNED_SHORT (op);
+       }
+      /* 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;
+           }
+       }
+      /* End AltiVec related instructions.  */
       else
        {
          /* Not a recognized prologue instruction.
@@ -1304,7 +1380,8 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
 {
   CORE_ADDR frame_addr;
   struct rs6000_framedata work_fdata;
-  int wordsize = TDEP->wordsize;
+  struct gdbarch_tdep * tdep = gdbarch_tdep (current_gdbarch);
+  int wordsize = tdep->wordsize;
 
   if (fi->saved_regs)
     return;
@@ -1322,8 +1399,12 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
   /* The following is true only if the frame doesn't have a call to
      alloca(), FIXME. */
 
-  if (fdatap->saved_fpr == 0 && fdatap->saved_gpr == 0
-      && fdatap->lr_offset == 0 && fdatap->cr_offset == 0)
+  if (fdatap->saved_fpr == 0
+      && fdatap->saved_gpr == 0
+      && fdatap->saved_vr == 0
+      && fdatap->lr_offset == 0
+      && fdatap->cr_offset == 0
+      && fdatap->vr_offset == 0)
     frame_addr = 0;
   else if (fi->prev && fi->prev->frame)
     frame_addr = fi->prev->frame;
@@ -1358,17 +1439,36 @@ frame_get_saved_regs (struct frame_info *fi, struct rs6000_framedata *fdatap)
        }
     }
 
+  /* if != -1, fdatap->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 (fdatap->saved_vr >= 0)
+       {
+         int i;
+         CORE_ADDR vr_addr = frame_addr + fdatap->vr_offset;
+         for (i = fdatap->saved_vr; i < 32; i++)
+           {
+             fi->saved_regs[tdep->ppc_vr0_regnum + i] = vr_addr;
+             vr_addr += REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum);
+           }
+       }
+    }
+
   /* If != 0, fdatap->cr_offset is the offset from the frame that holds
      the CR.  */
   if (fdatap->cr_offset != 0)
-    fi->saved_regs[gdbarch_tdep (current_gdbarch)->ppc_cr_regnum] =
-      frame_addr + fdatap->cr_offset;
+    fi->saved_regs[tdep->ppc_cr_regnum] = frame_addr + fdatap->cr_offset;
 
   /* If != 0, fdatap->lr_offset is the offset from the frame that holds
      the LR.  */
   if (fdatap->lr_offset != 0)
-    fi->saved_regs[gdbarch_tdep (current_gdbarch)->ppc_lr_regnum] =
-      frame_addr + fdatap->lr_offset;
+    fi->saved_regs[tdep->ppc_lr_regnum] = frame_addr + fdatap->lr_offset;
+
+  /* If != 0, fdatap->vrsave_offset is the offset from the frame that holds
+     the VRSAVE.  */
+  if (fdatap->vrsave_offset != 0)
+    fi->saved_regs[tdep->ppc_vrsave_regnum] = frame_addr + fdatap->vrsave_offset;
 }
 
 /* Return the address of a frame. This is the inital %sp value when the frame