diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
index 4dc3e8e45a3..564896fdc94 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -649,11 +649,13 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 		     struct frame_info *next_frame)
 {
   CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+  CORE_ADDR vfp = sp;
   CORE_ADDR cur_pc;
   int frame_size;
   int has_frame_reg = 0;
   unsigned long reg_mask = 0;
   int pcreg = -1;
+  int regno;
 
   if (start_pc == 0)
     return NULL;
@@ -678,7 +680,12 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
       if ((word & 0xffff0000) == 0x23de0000)	/* lda $sp,n($sp) */
 	{
 	  if (word & 0x8000)
-	    frame_size += (-word) & 0xffff;
+          {
+            /* Consider only the first stack allocation instruction
+               to contain the static size of the frame. */
+            if (frame_size == 0)
+	        frame_size += (-word) & 0xffff;
+          }
 	  else
 	    /* Exit loop if a positive stack adjustment is found, which
 	       usually means that the stack cleanup code in the function
@@ -690,7 +697,16 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 	{
 	  int reg = (word & 0x03e00000) >> 21;
 	  reg_mask |= 1 << reg;
-	  temp_saved_regs[reg] = sp + (short) word;
+
+          /* Do not compute the address where the register was saved yet,
+             because we don't know yet if the offset will need to be
+             relative to $sp or $fp (we can not compute the address relative
+             to $sp if $sp is updated during the execution of the current
+             subroutine, for instance when doing some alloca). So just store
+             the offset for the moment, and compute the address later
+             when we know whether this frame has a frame pointer or not.
+           */
+          temp_saved_regs[reg] = (short) word;
 
 	  /* Starting with OSF/1-3.2C, the system libraries are shipped
 	     without local symbols, but they still contain procedure
@@ -719,8 +735,15 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 	}
       else if ((word & 0xffe0ffff) == 0x6be08001)	/* ret zero,reg,1 */
 	pcreg = (word >> 16) & 0x1f;
-      else if (word == 0x47de040f)	/* bis sp,sp fp */
-	has_frame_reg = 1;
+      else if (word == 0x47de040f || word == 0x47fe040f) /* bis sp,sp fp */
+        {
+          /* ??? I am not sure what instruction is 0x47fe040f, and I
+             am suspecting that there was a typo and should have been
+             0x47fe040f. I'm keeping it in the test above until further
+             investigation */
+	    has_frame_reg = 1;
+          vfp = read_next_frame_reg (next_frame, ALPHA_GCC_FP_REGNUM);
+        }
     }
   if (pcreg == -1)
     {
@@ -759,6 +782,18 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
     PROC_FRAME_REG (&temp_proc_desc) = ALPHA_GCC_FP_REGNUM;
   else
     PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
+
+  /* At this point, we know which of the Stack Pointer or the Frame Pointer
+     to use as the reference address to compute the saved registers address.
+     But in both cases, the processing above has set vfp to this reference
+     address, so just need to increment the offset of each saved register
+     by this address. */
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      if (reg_mask & 1 << regno)
+	temp_saved_regs[regno] += vfp;
+    }
+
   PROC_FRAME_OFFSET (&temp_proc_desc) = frame_size;
   PROC_REG_MASK (&temp_proc_desc) = reg_mask;
   PROC_PC_REG (&temp_proc_desc) = (pcreg == -1) ? ALPHA_RA_REGNUM : pcreg;