[RFA]rs6000-tdep.c: Altivec Prologue analysis

Elena Zannoni ezannoni@redhat.com
Mon Mar 25 14:54:00 GMT 2002


This patch adds support for skipping AltiVec style prologues.

Elena


2002-03-25  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.
 
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v
retrieving revision 1.40
diff -u -p -r1.40 rs6000-tdep.c
--- rs6000-tdep.c	2002/03/22 21:58:15	1.40
+++ rs6000-tdep.c	2002/03/25 22:52:57
@@ -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
    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 l
 {
   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 l
   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 l
 	  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 l
 	  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 l
 				   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 l
 
 	  /* 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 l
 	  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 
 {
   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 
   /* 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 
 	}
     }
 
+  /* 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



More information about the Gdb-patches mailing list