This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] mn10300: Rewrite prologue analyzer


On Fri, 13 Mar 2009 16:24:50 -0700
Kevin Buettner <kevinb@redhat.com> wrote:

> + /* The typical call instruction will have saved the return address on the
> +    stack.  It's possible, such as when using -mrelax with gcc that
> +    other registers were saved on the stack as well.  If this happens,
> +    we really have no chance of deciphering the frame.  DWARF info
> +    can save the day when this happens.  */
> +  regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4);
> +  pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);

Further testing revealed that there was a problem with this part of
the patch.  I've changed it as follows:

+ /* The typical call instruction will have saved the return address on the
+    stack.  Space for the return address has already been preallocated in
+    the caller's frame.  It's possible, such as when using -mrelax with gcc
+    that other registers were saved as well.  If this happens, we really
+    have no chance of deciphering the frame.  DWARF info can save the day
+    when this happens.  */
+  pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);

Note that I've updated the comment to indicate why the stack pointer
update is not necessary.  (It's not only unnecessary, but wrong...)

For completeness, the full patch that I've committed is below:

2009-03-25  Kevin Buettner  <kevinb@redhat.com>

	* mn10300-tdep.c (trad-frame.h): Don't include.
	(prologue-value.h): Include.
	(mn10300_frame_unwind_cache, set_reg_offsets): Delete.
	(struct mn10300_prologue): Define.
	(push_reg, translate_rreg, check_for_saved): New functions.
	(mn10300_analyze_prologue): Rewrite, using prologue-value
	machinery.  Handle more instructions than before.  Permit
	instructions to occur in any order.
	(mn10300_skip_prologue): Find the extents of the function
	in question; mn10300_analyze_prologue no longer does this.
	(mn10300_analyze_frame_prologue): New function.
	(mn10300_frame_base): New function.
	(mn10300_frame_this_id): Rewrite, no longer using trad-frame
	implementation.
	(mn10300_frame_prev_register): Likewise.
	(mn10300_frame_base_address, mn10300_frame_base struct): Delete.
	(mn10300_unwind_pc, mn10300_unwind_sp): Rename `next_frame' to
	`this_frame'.
	(mn10300_frame_unwind_init): Don't call frame_base_set_default().

Index: mn10300-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mn10300-tdep.c,v
retrieving revision 1.162
diff -u -p -r1.162 mn10300-tdep.c
--- mn10300-tdep.c	22 Feb 2009 01:02:19 -0000	1.162
+++ mn10300-tdep.c	25 Mar 2009 13:30:58 -0000
@@ -31,18 +31,53 @@
 #include "frame.h"
 #include "frame-unwind.h"
 #include "frame-base.h"
-#include "trad-frame.h"
 #include "symtab.h"
 #include "dwarf2-frame.h"
 #include "osabi.h"
 #include "infcall.h"
+#include "prologue-value.h"
 #include "target.h"
 
 #include "mn10300-tdep.h"
 
-/* Forward decl.  */
-extern struct trad_frame_cache *mn10300_frame_unwind_cache (struct frame_info*,
-							    void **);
+
+/* The am33-2 has 64 registers.  */
+#define MN10300_MAX_NUM_REGS 64
+
+/* This structure holds the results of a prologue analysis.  */
+struct mn10300_prologue
+{
+  /* The offset from the frame base to the stack pointer --- always
+     zero or negative.
+
+     Calling this a "size" is a bit misleading, but given that the
+     stack grows downwards, using offsets for everything keeps one
+     from going completely sign-crazy: you never change anything's
+     sign for an ADD instruction; always change the second operand's
+     sign for a SUB instruction; and everything takes care of
+     itself.  */
+  int frame_size;
+
+  /* Non-zero if this function has initialized the frame pointer from
+     the stack pointer, zero otherwise.  */
+  int has_frame_ptr;
+
+  /* If has_frame_ptr is non-zero, this is the offset from the frame
+     base to where the frame pointer points.  This is always zero or
+     negative.  */
+  int frame_ptr_offset;
+
+  /* The address of the first instruction at which the frame has been
+     set up and the arguments are where the debug info says they are
+     --- as best as we can tell.  */
+  CORE_ADDR prologue_end;
+
+  /* reg_offset[R] is the offset from the CFA at which register R is
+     saved, or 1 if register R has not been saved.  (Real values are
+     always zero or negative.)  */
+  int reg_offset[MN10300_MAX_NUM_REGS];
+};
+
 
 /* Compute the alignment required by a type.  */
 
@@ -298,538 +333,722 @@ mn10300_breakpoint_from_pc (struct gdbar
   return breakpoint;
 }
 
-/* Set offsets of saved registers.
-   This is a helper function for mn10300_analyze_prologue.  */
-
+/* Model the semantics of pushing a register onto the stack.  This
+   is a helper function for mn10300_analyze_prologue, below.  */
 static void
-set_reg_offsets (struct frame_info *fi, 
-		  void **this_cache, 
-		  int movm_args,
-		  int fpregmask,
-		  int stack_extra_size,
-		  int frame_in_fp)
+push_reg (pv_t *regs, struct pv_area *stack, int regnum)
 {
-  struct gdbarch *gdbarch;
-  struct trad_frame_cache *cache;
-  int offset = 0;
-  CORE_ADDR base;
-
-  if (fi == NULL || this_cache == NULL)
-    return;
-
-  cache = mn10300_frame_unwind_cache (fi, this_cache);
-  if (cache == NULL)
-    return;
-  gdbarch = get_frame_arch (fi);
+  regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4);
+  pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[regnum]);
+}
 
-  if (frame_in_fp)
-    {
-      base = get_frame_register_unsigned (fi, E_A3_REGNUM);
-    }
+/* Translate an "r" register number extracted from an instruction encoding
+   into a GDB register number.  Adapted from a simulator function
+   of the same name; see am33.igen.  */
+static int
+translate_rreg (int rreg)
+{
+ /* The higher register numbers actually correspond to the
+     basic machine's address and data registers.  */
+  if (rreg > 7 && rreg < 12)
+    return E_A0_REGNUM + rreg - 8;
+  else if (rreg > 11 && rreg < 16)
+    return E_D0_REGNUM + rreg - 12;
   else
-    {
-      base = get_frame_register_unsigned (fi, E_SP_REGNUM)
-	       + stack_extra_size;
-    }
+    return E_E0_REGNUM + rreg;
+}
 
-  trad_frame_set_this_base (cache, base);
+/* Find saved registers in a 'struct pv_area'; we pass this to pv_area_scan.
 
-  if (AM33_MODE (gdbarch) == 2)
-    {
-      /* If bit N is set in fpregmask, fsN is saved on the stack.
-	 The floating point registers are saved in ascending order.
-	 For example:  fs16 <- Frame Pointer
-	               fs17    Frame Pointer + 4 */
-      if (fpregmask != 0)
+   If VALUE is a saved register, ADDR says it was saved at a constant
+   offset from the frame base, and SIZE indicates that the whole
+   register was saved, record its offset in RESULT_UNTYPED.  */
+static void
+check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+{
+  struct mn10300_prologue *result = (struct mn10300_prologue *) result_untyped;
+
+  if (value.kind == pvk_register
+      && value.k == 0
+      && pv_is_register (addr, E_SP_REGNUM)
+      && size == register_size (current_gdbarch, value.reg))
+    result->reg_offset[value.reg] = addr.k;
+}
+
+/* Analyze the prologue to determine where registers are saved,
+   the end of the prologue, etc.  The result of this analysis is
+   returned in RESULT.  See struct mn10300_prologue above for more
+   information.  */
+static void
+mn10300_analyze_prologue (struct gdbarch *gdbarch,
+                          CORE_ADDR start_pc, CORE_ADDR limit_pc,
+                          struct mn10300_prologue *result)
+{
+  CORE_ADDR pc, next_pc;
+  int rn;
+  pv_t regs[MN10300_MAX_NUM_REGS];
+  struct pv_area *stack;
+  struct cleanup *back_to;
+  CORE_ADDR after_last_frame_setup_insn = start_pc;
+  int am33_mode = AM33_MODE (gdbarch);
+
+  memset (result, 0, sizeof (*result));
+
+  for (rn = 0; rn < MN10300_MAX_NUM_REGS; rn++)
+    {
+      regs[rn] = pv_register (rn, 0);
+      result->reg_offset[rn] = 1;
+    }
+  stack = make_pv_area (E_SP_REGNUM);
+  back_to = make_cleanup_free_pv_area (stack);
+
+ /* The typical call instruction will have saved the return address on the
+    stack.  Space for the return address has already been preallocated in
+    the caller's frame.  It's possible, such as when using -mrelax with gcc
+    that other registers were saved as well.  If this happens, we really
+    have no chance of deciphering the frame.  DWARF info can save the day
+    when this happens.  */
+  pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);
+
+  pc = start_pc;
+  while (pc < limit_pc)
+    {
+      int status;
+      gdb_byte instr[2];
+
+      /* Instructions can be as small as one byte; however, we usually
+         need at least two bytes to do the decoding, so fetch that many
+	 to begin with.  */
+      status = target_read_memory (pc, instr, 2);
+      if (status != 0)
+	break;
+
+      /* movm [regs], sp  */
+      if (instr[0] == 0xcf)
 	{
-	  int i;
-	  for (i = 0; i < 32; i++)
+	  gdb_byte save_mask;
+
+	  save_mask = instr[1];
+
+	  if ((save_mask & movm_exreg0_bit) && am33_mode)
+	    {
+	      push_reg (regs, stack, E_E2_REGNUM);
+	      push_reg (regs, stack, E_E3_REGNUM);
+	    }
+	  if ((save_mask & movm_exreg1_bit) && am33_mode)
+	    {
+	      push_reg (regs, stack, E_E4_REGNUM);
+	      push_reg (regs, stack, E_E5_REGNUM);
+	      push_reg (regs, stack, E_E6_REGNUM);
+	      push_reg (regs, stack, E_E7_REGNUM);
+	    }
+	  if ((save_mask & movm_exother_bit) && am33_mode)
+	    {
+	      push_reg (regs, stack, E_E0_REGNUM);
+	      push_reg (regs, stack, E_E1_REGNUM);
+	      push_reg (regs, stack, E_MDRQ_REGNUM);
+	      push_reg (regs, stack, E_MCRH_REGNUM);
+	      push_reg (regs, stack, E_MCRL_REGNUM);
+	      push_reg (regs, stack, E_MCVF_REGNUM);
+	    }
+	  if (save_mask & movm_d2_bit)
+	    push_reg (regs, stack, E_D2_REGNUM);
+	  if (save_mask & movm_d3_bit)
+	    push_reg (regs, stack, E_D3_REGNUM);
+	  if (save_mask & movm_a2_bit)
+	    push_reg (regs, stack, E_A2_REGNUM);
+	  if (save_mask & movm_a3_bit)
+	    push_reg (regs, stack, E_A3_REGNUM);
+	  if (save_mask & movm_other_bit)
 	    {
-	      if (fpregmask & (1 << i))
-		{
-		  trad_frame_set_reg_addr (cache, E_FS0_REGNUM + i,
-					   base + offset);
-		  offset += 4;
-		}
+	      push_reg (regs, stack, E_D0_REGNUM);
+	      push_reg (regs, stack, E_D1_REGNUM);
+	      push_reg (regs, stack, E_A0_REGNUM);
+	      push_reg (regs, stack, E_A1_REGNUM);
+	      push_reg (regs, stack, E_MDR_REGNUM);
+	      push_reg (regs, stack, E_LIR_REGNUM);
+	      push_reg (regs, stack, E_LAR_REGNUM);
+	      /* The `other' bit leaves a blank area of four bytes at
+		 the beginning of its block of saved registers, making
+		 it 32 bytes long in total.  */
+	      regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4);
 	    }
+
+	  pc += 2;
+	  after_last_frame_setup_insn = pc;
 	}
-    }
+      /* mov sp, aN */
+      else if ((instr[0] & 0xfc) == 0x3c)
+	{
+	  int aN = instr[0] & 0x03;
 
+	  regs[E_A0_REGNUM + aN] = regs[E_SP_REGNUM];
 
-  if (movm_args & movm_other_bit)
-    {
-      /* The `other' bit leaves a blank area of four bytes at the
-         beginning of its block of saved registers, making it 32 bytes
-         long in total.  */
-      trad_frame_set_reg_addr (cache, E_LAR_REGNUM,    base + offset + 4);
-      trad_frame_set_reg_addr (cache, E_LIR_REGNUM,    base + offset + 8);
-      trad_frame_set_reg_addr (cache, E_MDR_REGNUM,    base + offset + 12);
-      trad_frame_set_reg_addr (cache, E_A0_REGNUM + 1, base + offset + 16);
-      trad_frame_set_reg_addr (cache, E_A0_REGNUM,     base + offset + 20);
-      trad_frame_set_reg_addr (cache, E_D0_REGNUM + 1, base + offset + 24);
-      trad_frame_set_reg_addr (cache, E_D0_REGNUM,     base + offset + 28);
-      offset += 32;
-    }
+	  pc += 1;
+	  if (aN == 3)
+	    after_last_frame_setup_insn = pc;
+	}
+      /* mov aM, aN */
+      else if ((instr[0] & 0xf0) == 0x90
+               && (instr[0] & 0x03) != ((instr[0] & 0x0c) >> 2))
+	{
+	  int aN = instr[0] & 0x03;
+	  int aM = (instr[0] & 0x0c) >> 2;
 
-  if (movm_args & movm_a3_bit)
-    {
-      trad_frame_set_reg_addr (cache, E_A3_REGNUM, base + offset);
-      offset += 4;
-    }
-  if (movm_args & movm_a2_bit)
-    {
-      trad_frame_set_reg_addr (cache, E_A2_REGNUM, base + offset);
-      offset += 4;
-    }
-  if (movm_args & movm_d3_bit)
-    {
-      trad_frame_set_reg_addr (cache, E_D3_REGNUM, base + offset);
-      offset += 4;
-    }
-  if (movm_args & movm_d2_bit)
-    {
-      trad_frame_set_reg_addr (cache, E_D2_REGNUM, base + offset);
-      offset += 4;
-    }
-  if (AM33_MODE (gdbarch))
-    {
-      if (movm_args & movm_exother_bit)
-        {
-	  trad_frame_set_reg_addr (cache, E_MCVF_REGNUM, base + offset);
-	  trad_frame_set_reg_addr (cache, E_MCRL_REGNUM, base + offset + 4);
-	  trad_frame_set_reg_addr (cache, E_MCRH_REGNUM, base + offset + 8);
-	  trad_frame_set_reg_addr (cache, E_MDRQ_REGNUM, base + offset + 12);
-	  trad_frame_set_reg_addr (cache, E_E1_REGNUM,   base + offset + 16);
-	  trad_frame_set_reg_addr (cache, E_E0_REGNUM,   base + offset + 20);
-          offset += 24;
-        }
-      if (movm_args & movm_exreg1_bit)
-        {
-	  trad_frame_set_reg_addr (cache, E_E7_REGNUM, base + offset);
-	  trad_frame_set_reg_addr (cache, E_E6_REGNUM, base + offset + 4);
-	  trad_frame_set_reg_addr (cache, E_E5_REGNUM, base + offset + 8);
-	  trad_frame_set_reg_addr (cache, E_E4_REGNUM, base + offset + 12);
-          offset += 16;
-        }
-      if (movm_args & movm_exreg0_bit)
-        {
-	  trad_frame_set_reg_addr (cache, E_E3_REGNUM, base + offset);
-	  trad_frame_set_reg_addr (cache, E_E2_REGNUM, base + offset + 4);
-          offset += 8;
-        }
-    }
-  /* The last (or first) thing on the stack will be the PC.  */
-  trad_frame_set_reg_addr (cache, E_PC_REGNUM, base + offset);
-  /* Save the SP in the 'traditional' way.  
-     This will be the same location where the PC is saved.  */
-  trad_frame_set_reg_value (cache, E_SP_REGNUM, base + offset);
-}
-
-/* The main purpose of this file is dealing with prologues to extract
-   information about stack frames and saved registers.
-
-   In gcc/config/mn13000/mn10300.c, the expand_prologue prologue
-   function is pretty readable, and has a nice explanation of how the
-   prologue is generated.  The prologues generated by that code will
-   have the following form (NOTE: the current code doesn't handle all
-   this!):
+	  regs[E_A0_REGNUM + aN] = regs[E_A0_REGNUM + aM];
 
-   + If this is an old-style varargs function, then its arguments
-     need to be flushed back to the stack:
-     
-        mov d0,(4,sp)
-        mov d1,(4,sp)
+	  pc += 1;
+	}
+      /* mov dM, dN */
+      else if ((instr[0] & 0xf0) == 0x80
+               && (instr[0] & 0x03) != ((instr[0] & 0x0c) >> 2))
+	{
+	  int dN = instr[0] & 0x03;
+	  int dM = (instr[0] & 0x0c) >> 2;
 
-   + If we use any of the callee-saved registers, save them now.
-     
-        movm [some callee-saved registers],(sp)
+	  regs[E_D0_REGNUM + dN] = regs[E_D0_REGNUM + dM];
+
+	  pc += 1;
+	}
+      /* mov aM, dN */
+      else if (instr[0] == 0xf1 && (instr[1] & 0xf0) == 0xd0)
+	{
+	  int dN = instr[1] & 0x03;
+	  int aM = (instr[1] & 0x0c) >> 2;
+
+	  regs[E_D0_REGNUM + dN] = regs[E_A0_REGNUM + aM];
 
-   + If we have any floating-point registers to save:
+	  pc += 2;
+	}
+      /* mov dM, aN */
+      else if (instr[0] == 0xf1 && (instr[1] & 0xf0) == 0xe0)
+	{
+	  int aN = instr[1] & 0x03;
+	  int dM = (instr[1] & 0x0c) >> 2;
 
-     - Decrement the stack pointer to reserve space for the registers.
-       If the function doesn't need a frame pointer, we may combine
-       this with the adjustment that reserves space for the frame.
+	  regs[E_A0_REGNUM + aN] = regs[E_D0_REGNUM + dM];
 
-        add -SIZE, sp
+	  pc += 2;
+	}
+      /* add imm8, SP */
+      else if (instr[0] == 0xf8 && instr[1] == 0xfe)
+	{
+	  gdb_byte buf[1];
+	  LONGEST imm8;
 
-     - Save the floating-point registers.  We have two possible
-       strategies:
 
-       . Save them at fixed offset from the SP:
+	  status = target_read_memory (pc + 2, buf, 1);
+	  if (status != 0)
+	    break;
 
-        fmov fsN,(OFFSETN,sp)
-        fmov fsM,(OFFSETM,sp)
-        ...
+	  imm8 = extract_signed_integer (buf, 1);
+	  regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], imm8);
 
-       Note that, if OFFSETN happens to be zero, you'll get the
-       different opcode: fmov fsN,(sp)
+	  pc += 3;
+	  /* Stack pointer adjustments are frame related.  */
+	  after_last_frame_setup_insn = pc;
+	}
+      /* add imm16, SP */
+      else if (instr[0] == 0xfa && instr[1] == 0xfe)
+	{
+	  gdb_byte buf[2];
+	  LONGEST imm16;
 
-       . Or, set a0 to the start of the save area, and then use
-       post-increment addressing to save the FP registers.
+	  status = target_read_memory (pc + 2, buf, 2);
+	  if (status != 0)
+	    break;
 
-        mov sp, a0
-        add SIZE, a0
-        fmov fsN,(a0+)
-        fmov fsM,(a0+)
-        ...
+	  imm16 = extract_signed_integer (buf, 2);
+	  regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], imm16);
 
-   + If the function needs a frame pointer, we set it here.
+	  pc += 4;
+	  /* Stack pointer adjustments are frame related.  */
+	  after_last_frame_setup_insn = pc;
+	}
+      /* add imm32, SP */
+      else if (instr[0] == 0xfc && instr[1] == 0xfe)
+	{
+	  gdb_byte buf[4];
+	  LONGEST imm32;
 
-        mov sp, a3
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
 
-   + Now we reserve space for the stack frame proper.  This could be
-     merged into the `add -SIZE, sp' instruction for FP saves up
-     above, unless we needed to set the frame pointer in the previous
-     step, or the frame is so large that allocating the whole thing at
-     once would put the FP register save slots out of reach of the
-     addressing mode (128 bytes).
-      
-        add -SIZE, sp        
 
-   One day we might keep the stack pointer constant, that won't
-   change the code for prologues, but it will make the frame
-   pointerless case much more common.  */
+	  imm32 = extract_signed_integer (buf, 4);
+	  regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], imm32);
 
-/* Analyze the prologue to determine where registers are saved,
-   the end of the prologue, etc etc.  Return the end of the prologue
-   scanned.
+	  pc += 6;
+	  /* Stack pointer adjustments are frame related.  */
+	  after_last_frame_setup_insn = pc;
+	}
+      /* add imm8, aN  */
+      else if ((instr[0] & 0xfc) == 0x20)
+	{
+	  int aN;
+	  LONGEST imm8;
 
-   We store into FI (if non-null) several tidbits of information:
+	  aN = instr[0] & 0x03;
+	  imm8 = extract_signed_integer (&instr[1], 1);
 
-   * stack_size -- size of this stack frame.  Note that if we stop in
-   certain parts of the prologue/epilogue we may claim the size of the
-   current frame is zero.  This happens when the current frame has
-   not been allocated yet or has already been deallocated.
-
-   * fsr -- Addresses of registers saved in the stack by this frame.
-
-   * status -- A (relatively) generic status indicator.  It's a bitmask
-   with the following bits: 
-
-   MY_FRAME_IN_SP: The base of the current frame is actually in
-   the stack pointer.  This can happen for frame pointerless
-   functions, or cases where we're stopped in the prologue/epilogue
-   itself.  For these cases mn10300_analyze_prologue will need up
-   update fi->frame before returning or analyzing the register
-   save instructions.
-
-   MY_FRAME_IN_FP: The base of the current frame is in the
-   frame pointer register ($a3).
-
-   NO_MORE_FRAMES: Set this if the current frame is "start" or
-   if the first instruction looks like mov <imm>,sp.  This tells
-   frame chain to not bother trying to unwind past this frame.  */
+	  regs[E_A0_REGNUM + aN] = pv_add_constant (regs[E_A0_REGNUM + aN],
+	                                            imm8);
 
-static CORE_ADDR
-mn10300_analyze_prologue (struct gdbarch *gdbarch, struct frame_info *fi, 
-			  void **this_cache, 
-			  CORE_ADDR pc)
-{
-  CORE_ADDR func_addr, func_end, addr, stop;
-  long stack_extra_size = 0;
-  int imm_size;
-  unsigned char buf[4];
-  int status;
-  int movm_args = 0;
-  int fpregmask = 0;
-  char *name;
-  int frame_in_fp = 0;
+	  pc += 2;
+	}
+      /* add imm16, aN  */
+      else if (instr[0] == 0xfa && (instr[1] & 0xfc) == 0xd0)
+	{
+	  int aN;
+	  LONGEST imm16;
+	  gdb_byte buf[2];
 
-  /* Use the PC in the frame if it's provided to look up the
-     start of this function.
+	  aN = instr[1] & 0x03;
 
-     Note: kevinb/2003-07-16: We used to do the following here:
-	pc = (fi ? get_frame_pc (fi) : pc);
-     But this is (now) badly broken when called from analyze_dummy_frame().
-  */
-  if (fi)
-    {
-      pc = (pc ? pc : get_frame_pc (fi));
-    }
+	  status = target_read_memory (pc + 2, buf, 2);
+	  if (status != 0)
+	    break;
 
-  /* Find the start of this function.  */
-  status = find_pc_partial_function (pc, &name, &func_addr, &func_end);
 
-  /* Do nothing if we couldn't find the start of this function 
+	  imm16 = extract_signed_integer (buf, 2);
 
-     MVS: comment went on to say "or if we're stopped at the first
-     instruction in the prologue" -- but code doesn't reflect that, 
-     and I don't want to do that anyway.  */
-  if (status == 0)
-    {
-      addr = pc;
-      goto finish_prologue;
-    }
+	  regs[E_A0_REGNUM + aN] = pv_add_constant (regs[E_A0_REGNUM + aN],
+	                                            imm16);
 
-  /* If we're in start, then give up.  */
-  if (strcmp (name, "start") == 0)
-    {
-      addr = pc;
-      goto finish_prologue;
-    }
+	  pc += 4;
+	}
+      /* add imm32, aN  */
+      else if (instr[0] == 0xfc && (instr[1] & 0xfc) == 0xd0)
+	{
+	  int aN;
+	  LONGEST imm32;
+	  gdb_byte buf[4];
 
-  /* Figure out where to stop scanning.  */
-  stop = fi ? pc : func_end;
+	  aN = instr[1] & 0x03;
 
-  /* Don't walk off the end of the function.  */
-  stop = stop > func_end ? func_end : stop;
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
 
-  /* Start scanning on the first instruction of this function.  */
-  addr = func_addr;
+	  imm32 = extract_signed_integer (buf, 2);
 
-  /* Suck in two bytes.  */
-  if (addr + 2 > stop || !safe_frame_unwind_memory (fi, addr, buf, 2))
-    goto finish_prologue;
-
-  /* First see if this insn sets the stack pointer from a register; if
-     so, it's probably the initialization of the stack pointer in _start,
-     so mark this as the bottom-most frame.  */
-  if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0)
-    {
-      goto finish_prologue;
-    }
+	  regs[E_A0_REGNUM + aN] = pv_add_constant (regs[E_A0_REGNUM + aN],
+	                                            imm32);
+	  pc += 6;
+	}
+      /* fmov fsM, (rN) */
+      else if (instr[0] == 0xf9 && (instr[1] & 0xfd) == 0x30)
+	{
+	  int fsM, sM, Y, rN;
+	  gdb_byte buf[1];
 
-  /* Now look for movm [regs],sp, which saves the callee saved registers.
+	  Y = (instr[1] & 0x02) >> 1;
 
-     At this time we don't know if fi->frame is valid, so we only note
-     that we encountered a movm instruction.  Later, we'll set the entries
-     in fsr.regs as needed.  */
-  if (buf[0] == 0xcf)
-    {
-      /* Extract the register list for the movm instruction.  */
-      movm_args = buf[1];
+	  status = target_read_memory (pc + 2, buf, 1);
+	  if (status != 0)
+	    break;
 
-      addr += 2;
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
 
-      /* Quit now if we're beyond the stop point.  */
-      if (addr >= stop)
-	goto finish_prologue;
-
-      /* Get the next two bytes so the prologue scan can continue.  */
-      if (!safe_frame_unwind_memory (fi, addr, buf, 2))
-	goto finish_prologue;
-    }
+	  pv_area_store (stack, regs[translate_rreg (rN)], 4,
+	                 regs[E_FS0_REGNUM + fsM]);
 
-  /* Check for "mov pc, a2", an instruction found in optimized, position
-     independent code.  Skip it if found.  */
-  if (buf[0] == 0xf0 && buf[1] == 0x2e)
-    {
-      addr += 2;
+	  pc += 3;
+	}
+      /* fmov fsM, (sp) */
+      else if (instr[0] == 0xf9 && (instr[1] & 0xfd) == 0x34)
+	{
+	  int fsM, sM, Y;
+	  gdb_byte buf[1];
 
-      /* Quit now if we're beyond the stop point.  */
-      if (addr >= stop)
-	goto finish_prologue;
+	  Y = (instr[1] & 0x02) >> 1;
 
-      /* Get the next two bytes so the prologue scan can continue.  */
-      status = target_read_memory (addr, buf, 2);
-      if (status != 0)
-	goto finish_prologue;
-    }
+	  status = target_read_memory (pc + 2, buf, 1);
+	  if (status != 0)
+	    break;
 
-  if (AM33_MODE (gdbarch) == 2)
-    {
-      /* Determine if any floating point registers are to be saved.
-	 Look for one of the following three prologue formats:
+	  sM = (buf[0] & 0xf0) >> 4;
+	  fsM = (Y << 4) | sM;
 
-	[movm [regs],(sp)] [movm [regs],(sp)] [movm [regs],(sp)]
+	  pv_area_store (stack, regs[E_SP_REGNUM], 4,
+	                 regs[E_FS0_REGNUM + fsM]);
 
-	 add -SIZE,sp       add -SIZE,sp       add -SIZE,sp
-	 fmov fs#,(sp)      mov sp,a0/a1       mov sp,a0/a1
-	 fmov fs#,(#,sp)    fmov fs#,(a0/a1+)  add SIZE2,a0/a1
-	 ...                ...                fmov fs#,(a0/a1+)
-	 ...                ...                ...
-	 fmov fs#,(#,sp)    fmov fs#,(a0/a1+)  fmov fs#,(a0/a1+)
-
-	[mov sp,a3]        [mov sp,a3]
-	[add -SIZE2,sp]    [add -SIZE2,sp]                                 */
-
-      /* Remember the address at which we started in the event that we
-	 don't ultimately find an fmov instruction.  Once we're certain
-	 that we matched one of the above patterns, we'll set
-	 ``restore_addr'' to the appropriate value.  Note: At one time
-	 in the past, this code attempted to not adjust ``addr'' until
-	 there was a fair degree of certainty that the pattern would be
-	 matched.  However, that code did not wait until an fmov instruction
-	 was actually encountered.  As a consequence, ``addr'' would
-	 sometimes be advanced even when no fmov instructions were found.  */
-      CORE_ADDR restore_addr = addr;
-      int fmov_found = 0;
-
-      /* First, look for add -SIZE,sp (i.e. add imm8,sp  (0xf8feXX)
-                                         or add imm16,sp (0xfafeXXXX)
-                                         or add imm32,sp (0xfcfeXXXXXXXX)) */
-      imm_size = 0;
-      if (buf[0] == 0xf8 && buf[1] == 0xfe)
-	imm_size = 1;
-      else if (buf[0] == 0xfa && buf[1] == 0xfe)
-	imm_size = 2;
-      else if (buf[0] == 0xfc && buf[1] == 0xfe)
-	imm_size = 4;
-      if (imm_size != 0)
-	{
-	  /* An "add -#,sp" instruction has been found. "addr + 2 + imm_size"
-	     is the address of the next instruction. Don't modify "addr" until
-	     the next "floating point prologue" instruction is found. If this
-	     is not a prologue that saves floating point registers we need to
-	     be able to back out of this bit of code and continue with the
-	     prologue analysis. */
-	  if (addr + 2 + imm_size < stop)
-	    {
-	      if (!safe_frame_unwind_memory (fi, addr + 2 + imm_size, buf, 3))
-		goto finish_prologue;
-	      if ((buf[0] & 0xfc) == 0x3c)
-		{
-		  /* Occasionally, especially with C++ code, the "fmov"
-		     instructions will be preceded by "mov sp,aN"
-		     (aN => a0, a1, a2, or a3).
-
-		     This is a one byte instruction:  mov sp,aN = 0011 11XX
-		     where XX is the register number.
-
-		     Skip this instruction by incrementing addr.  The "fmov"
-		     instructions will have the form "fmov fs#,(aN+)" in this
-		     case, but that will not necessitate a change in the
-		     "fmov" parsing logic below. */
-
-		  addr++;
-
-		  if ((buf[1] & 0xfc) == 0x20)
-		    {
-		      /* Occasionally, especially with C++ code compiled with
-			 the -fomit-frame-pointer or -O3 options, the
-			 "mov sp,aN" instruction will be followed by an
-			 "add #,aN" instruction. This indicates the
-			 "stack_size", the size of the portion of the stack
-			 containing the arguments. This instruction format is:
-			 add #,aN = 0010 00XX YYYY YYYY
-			 where XX        is the register number
-			       YYYY YYYY is the constant.
-			 Note the size of the stack (as a negative number) in
-			 the frame info structure. */
-		      if (fi)
-			stack_extra_size += -buf[2];
-
-		      addr += 2;
-		    }
-		}
-
-	      if ((buf[0] & 0xfc) == 0x3c ||
-		  buf[0] == 0xf9 || buf[0] == 0xfb)
-		{
-		  /* An "fmov" instruction has been found indicating that this
-		     prologue saves floating point registers (or, as described
-		     above, a "mov sp,aN" and possible "add #,aN" have been
-		     found and we will assume an "fmov" follows). Process the
-		     consecutive "fmov" instructions. */
-		  for (addr += 2 + imm_size;;addr += imm_size)
-		    {
-		      int regnum;
-
-		      /* Read the "fmov" instruction. */
-		      if (addr >= stop ||
-			  !safe_frame_unwind_memory (fi, addr, buf, 4))
-			goto finish_prologue;
-
-		      if (buf[0] != 0xf9 && buf[0] != 0xfb)
-			break;
-
-		      /* An fmov instruction has just been seen.  We can
-		         now really commit to the pattern match.  */
-
-		      fmov_found = 1;
-
-		      /* Get the floating point register number from the 
-			 2nd and 3rd bytes of the "fmov" instruction:
-			 Machine Code: 0000 00X0 YYYY 0000 =>
-			 Regnum: 000X YYYY */
-		      regnum = (buf[1] & 0x02) << 3;
-		      regnum |= ((buf[2] & 0xf0) >> 4) & 0x0f;
-
-		      /* Add this register number to the bit mask of floating
-			 point registers that have been saved. */
-		      fpregmask |= 1 << regnum;
-		  
-		      /* Determine the length of this "fmov" instruction.
-			 fmov fs#,(sp)   => 3 byte instruction
-			 fmov fs#,(#,sp) => 4 byte instruction */
-		      imm_size = (buf[0] == 0xf9) ? 3 : 4;
-		    }
-		}
-	    }
+	  pc += 3;
 	}
-      /* If no fmov instructions were found by the above sequence, reset
-         the state and pretend that the above bit of code never happened.  */
-      if (!fmov_found)
+      /* fmov fsM, (rN, rI) */
+      else if (instr[0] == 0xfb && instr[1] == 0x37)
 	{
-	  addr = restore_addr;
-	  status = target_read_memory (addr, buf, 2);
+	  int fsM, sM, Z, rN, rI;
+	  gdb_byte buf[2];
+
+
+	  status = target_read_memory (pc + 2, buf, 2);
 	  if (status != 0)
-	    goto finish_prologue;
-	  stack_extra_size = 0;
+	    break;
+
+	  rI = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  sM = (buf[1] & 0xf0) >> 4;
+	  Z = (buf[1] & 0x02) >> 1;
+	  fsM = (Z << 4) | sM;
+
+	  pv_area_store (stack,
+	                 pv_add (regs[translate_rreg (rN)],
+			         regs[translate_rreg (rI)]),
+			 4, regs[E_FS0_REGNUM + fsM]);
+
+	  pc += 4;
 	}
-    }
+      /* fmov fsM, (d8, rN) */
+      else if (instr[0] == 0xfb && (instr[1] & 0xfd) == 0x30)
+	{
+	  int fsM, sM, Y, rN;
+	  LONGEST d8;
+	  gdb_byte buf[2];
 
-  /* Now see if we set up a frame pointer via "mov sp,a3" */
-  if (buf[0] == 0x3f)
-    {
-      addr += 1;
+	  Y = (instr[1] & 0x02) >> 1;
 
-      /* The frame pointer is now valid.  */
-      if (fi)
+	  status = target_read_memory (pc + 2, buf, 2);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+	  d8 = extract_signed_integer (&buf[1], 1);
+
+	  pv_area_store (stack,
+	                 pv_add_constant (regs[translate_rreg (rN)], d8),
+	                 4, regs[E_FS0_REGNUM + fsM]);
+
+	  pc += 4;
+	}
+      /* fmov fsM, (d24, rN) */
+      else if (instr[0] == 0xfd && (instr[1] & 0xfd) == 0x30)
 	{
-	  frame_in_fp = 1;
+	  int fsM, sM, Y, rN;
+	  LONGEST d24;
+	  gdb_byte buf[4];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+	  d24 = extract_signed_integer (&buf[1], 3);
+
+	  pv_area_store (stack,
+	                 pv_add_constant (regs[translate_rreg (rN)], d24),
+	                 4, regs[E_FS0_REGNUM + fsM]);
+
+	  pc += 6;
 	}
+      /* fmov fsM, (d32, rN) */
+      else if (instr[0] == 0xfe && (instr[1] & 0xfd) == 0x30)
+	{
+	  int fsM, sM, Y, rN;
+	  LONGEST d32;
+	  gdb_byte buf[5];
 
-      /* Quit now if we're beyond the stop point.  */
-      if (addr >= stop)
-	goto finish_prologue;
+	  Y = (instr[1] & 0x02) >> 1;
 
-      /* Get two more bytes so scanning can continue.  */
-      if (!safe_frame_unwind_memory (fi, addr, buf, 2))
-	goto finish_prologue;
-    }
+	  status = target_read_memory (pc + 2, buf, 5);
+	  if (status != 0)
+	    break;
 
-  /* Next we should allocate the local frame.  No more prologue insns
-     are found after allocating the local frame.
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+	  d32 = extract_signed_integer (&buf[1], 4);
+
+	  pv_area_store (stack,
+	                 pv_add_constant (regs[translate_rreg (rN)], d32),
+	                 4, regs[E_FS0_REGNUM + fsM]);
 
-     Search for add imm8,sp (0xf8feXX)
-     or add imm16,sp (0xfafeXXXX)
-     or add imm32,sp (0xfcfeXXXXXXXX).
-
-     If none of the above was found, then this prologue has no 
-     additional stack.  */
-
-  imm_size = 0;
-  if (buf[0] == 0xf8 && buf[1] == 0xfe)
-    imm_size = 1;
-  else if (buf[0] == 0xfa && buf[1] == 0xfe)
-    imm_size = 2;
-  else if (buf[0] == 0xfc && buf[1] == 0xfe)
-    imm_size = 4;
+	  pc += 7;
+	}
+      /* fmov fsM, (d8, SP) */
+      else if (instr[0] == 0xfb && (instr[1] & 0xfd) == 0x34)
+	{
+	  int fsM, sM, Y;
+	  LONGEST d8;
+	  gdb_byte buf[2];
 
-  if (imm_size != 0)
-    {
-      /* Suck in imm_size more bytes, they'll hold the size of the
-         current frame.  */
-      if (!safe_frame_unwind_memory (fi, addr + 2, buf, imm_size))
-	goto finish_prologue;
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 2);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  fsM = (Y << 4) | sM;
+	  d8 = extract_signed_integer (&buf[1], 1);
+
+	  pv_area_store (stack,
+	                 pv_add_constant (regs[E_SP_REGNUM], d8),
+	                 4, regs[E_FS0_REGNUM + fsM]);
+
+	  pc += 4;
+	}
+      /* fmov fsM, (d24, SP) */
+      else if (instr[0] == 0xfd && (instr[1] & 0xfd) == 0x34)
+	{
+	  int fsM, sM, Y;
+	  LONGEST d24;
+	  gdb_byte buf[4];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  fsM = (Y << 4) | sM;
+	  d24 = extract_signed_integer (&buf[1], 3);
+
+	  pv_area_store (stack,
+	                 pv_add_constant (regs[E_SP_REGNUM], d24),
+	                 4, regs[E_FS0_REGNUM + fsM]);
+
+	  pc += 6;
+	}
+      /* fmov fsM, (d32, SP) */
+      else if (instr[0] == 0xfe && (instr[1] & 0xfd) == 0x34)
+	{
+	  int fsM, sM, Y;
+	  LONGEST d32;
+	  gdb_byte buf[5];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 5);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  fsM = (Y << 4) | sM;
+	  d32 = extract_signed_integer (&buf[1], 4);
+
+	  pv_area_store (stack,
+	                 pv_add_constant (regs[E_SP_REGNUM], d32),
+	                 4, regs[E_FS0_REGNUM + fsM]);
+
+	  pc += 7;
+	}
+      /* fmov fsM, (rN+) */
+      else if (instr[0] == 0xf9 && (instr[1] & 0xfd) == 0x31)
+	{
+	  int fsM, sM, Y, rN, rN_regnum;
+	  gdb_byte buf[1];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 1);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+
+	  rN_regnum = translate_rreg (rN);
+
+	  pv_area_store (stack, regs[rN_regnum], 4,
+	                 regs[E_FS0_REGNUM + fsM]);
+	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], 4);
+
+	  pc += 3;
+	}
+      /* fmov fsM, (rN+, imm8) */
+      else if (instr[0] == 0xfb && (instr[1] & 0xfd) == 0x31)
+	{
+	  int fsM, sM, Y, rN, rN_regnum;
+	  LONGEST imm8;
+	  gdb_byte buf[2];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 2);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+	  imm8 = extract_signed_integer (&buf[1], 1);
+
+	  rN_regnum = translate_rreg (rN);
+
+	  pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm8);
+
+	  pc += 4;
+	}
+      /* fmov fsM, (rN+, imm24) */
+      else if (instr[0] == 0xfd && (instr[1] & 0xfd) == 0x31)
+	{
+	  int fsM, sM, Y, rN, rN_regnum;
+	  LONGEST imm24;
+	  gdb_byte buf[4];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+	  imm24 = extract_signed_integer (&buf[1], 3);
+
+	  rN_regnum = translate_rreg (rN);
+
+	  pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm24);
+
+	  pc += 6;
+	}
+      /* fmov fsM, (rN+, imm32) */
+      else if (instr[0] == 0xfe && (instr[1] & 0xfd) == 0x31)
+	{
+	  int fsM, sM, Y, rN, rN_regnum;
+	  LONGEST imm32;
+	  gdb_byte buf[5];
+
+	  Y = (instr[1] & 0x02) >> 1;
+
+	  status = target_read_memory (pc + 2, buf, 5);
+	  if (status != 0)
+	    break;
+
+	  sM = (buf[0] & 0xf0) >> 4;
+	  rN = buf[0] & 0x0f;
+	  fsM = (Y << 4) | sM;
+	  imm32 = extract_signed_integer (&buf[1], 4);
+
+	  rN_regnum = translate_rreg (rN);
+
+	  pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm32);
+
+	  pc += 7;
+	}
+      /* mov imm8, aN */
+      else if ((instr[0] & 0xf0) == 0x90)
+        {
+	  int aN = instr[0] & 0x03;
+	  LONGEST imm8;
+
+	  imm8 = extract_signed_integer (&instr[1], 1);
+
+	  regs[E_A0_REGNUM + aN] = pv_constant (imm8);
+	  pc += 2;
+	}
+      /* mov imm16, aN */
+      else if ((instr[0] & 0xfc) == 0x24)
+        {
+	  int aN = instr[0] & 0x03;
+	  gdb_byte buf[2];
+	  LONGEST imm16;
+
+	  status = target_read_memory (pc + 1, buf, 2);
+	  if (status != 0)
+	    break;
+
+	  imm16 = extract_signed_integer (buf, 2);
+	  regs[E_A0_REGNUM + aN] = pv_constant (imm16);
+	  pc += 3;
+	}
+      /* mov imm32, aN */
+      else if (instr[0] == 0xfc && ((instr[1] & 0xfc) == 0xdc))
+        {
+	  int aN = instr[1] & 0x03;
+	  gdb_byte buf[4];
+	  LONGEST imm32;
+
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
+
+	  imm32 = extract_signed_integer (buf, 4);
+	  regs[E_A0_REGNUM + aN] = pv_constant (imm32);
+	  pc += 6;
+	}
+      /* mov imm8, dN */
+      else if ((instr[0] & 0xf0) == 0x80)
+        {
+	  int dN = instr[0] & 0x03;
+	  LONGEST imm8;
+
+	  imm8 = extract_signed_integer (&instr[1], 1);
 
-      /* Note the size of the stack.  */
-      stack_extra_size -= extract_signed_integer (buf, imm_size);
+	  regs[E_D0_REGNUM + dN] = pv_constant (imm8);
+	  pc += 2;
+	}
+      /* mov imm16, dN */
+      else if ((instr[0] & 0xfc) == 0x2c)
+        {
+	  int dN = instr[0] & 0x03;
+	  gdb_byte buf[2];
+	  LONGEST imm16;
+
+	  status = target_read_memory (pc + 1, buf, 2);
+	  if (status != 0)
+	    break;
+
+	  imm16 = extract_signed_integer (buf, 2);
+	  regs[E_D0_REGNUM + dN] = pv_constant (imm16);
+	  pc += 3;
+	}
+      /* mov imm32, dN */
+      else if (instr[0] == 0xfc && ((instr[1] & 0xfc) == 0xcc))
+        {
+	  int dN = instr[1] & 0x03;
+	  gdb_byte buf[4];
+	  LONGEST imm32;
+
+	  status = target_read_memory (pc + 2, buf, 4);
+	  if (status != 0)
+	    break;
+
+	  imm32 = extract_signed_integer (buf, 4);
+	  regs[E_D0_REGNUM + dN] = pv_constant (imm32);
+	  pc += 6;
+	}
+      else
+	{
+	  /* We've hit some instruction that we don't recognize.  Hopefully,
+	     we have enough to do prologue analysis.  */
+	  break;
+	}
+    }
 
-      /* We just consumed 2 + imm_size bytes.  */
-      addr += 2 + imm_size;
+  /* Is the frame size (offset, really) a known constant?  */
+  if (pv_is_register (regs[E_SP_REGNUM], E_SP_REGNUM))
+    result->frame_size = regs[E_SP_REGNUM].k;
 
-      /* No more prologue insns follow, so begin preparation to return.  */
-      goto finish_prologue;
+  /* Was the frame pointer initialized?  */
+  if (pv_is_register (regs[E_A3_REGNUM], E_SP_REGNUM))
+    {
+      result->has_frame_ptr = 1;
+      result->frame_ptr_offset = regs[E_A3_REGNUM].k;
     }
-  /* Do the essentials and get out of here.  */
- finish_prologue:
-  /* Note if/where callee saved registers were saved.  */
-  if (fi)
-    set_reg_offsets (fi, this_cache, movm_args, fpregmask, stack_extra_size,
-		     frame_in_fp);
-  return addr;
+
+  /* Record where all the registers were saved.  */
+  pv_area_scan (stack, check_for_saved, (void *) result);
+
+  result->prologue_end = after_last_frame_setup_insn;
+
+  do_cleanups (back_to);
 }
 
 /* Function: skip_prologue
@@ -838,43 +1057,70 @@ mn10300_analyze_prologue (struct gdbarch
 static CORE_ADDR
 mn10300_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  return mn10300_analyze_prologue (gdbarch, NULL, NULL, pc);
+  char *name;
+  CORE_ADDR func_addr, func_end;
+  struct mn10300_prologue p;
+
+  /* Try to find the extent of the function that contains PC.  */
+  if (!find_pc_partial_function (pc, &name, &func_addr, &func_end))
+    return pc;
+
+  mn10300_analyze_prologue (gdbarch, pc, func_end, &p);
+  return p.prologue_end;
 }
 
-/* Simple frame_unwind_cache.  
-   This finds the "extra info" for the frame.  */
-struct trad_frame_cache *
-mn10300_frame_unwind_cache (struct frame_info *this_frame,
-			    void **this_prologue_cache)
+/* Wrapper for mn10300_analyze_prologue: find the function start;
+   use the current frame PC as the limit, then
+   invoke mn10300_analyze_prologue and return its result.  */
+static struct mn10300_prologue *
+mn10300_analyze_frame_prologue (struct frame_info *this_frame,
+			   void **this_prologue_cache)
 {
-  struct gdbarch *gdbarch;
-  struct trad_frame_cache *cache;
-  CORE_ADDR pc, start, end;
-  void *cache_p;
-
-  if (*this_prologue_cache)
-    return (*this_prologue_cache);
-
-  gdbarch = get_frame_arch (this_frame);
-  cache_p = trad_frame_cache_zalloc (this_frame);
-  pc = get_frame_register_unsigned (this_frame, E_PC_REGNUM);
-  mn10300_analyze_prologue (gdbarch, this_frame, &cache_p, pc);
-  cache = cache_p;
-
-  if (find_pc_partial_function (pc, NULL, &start, &end))
-    trad_frame_set_id (cache, 
-		       frame_id_build (trad_frame_get_this_base (cache), 
-				       start));
-  else
+  if (!*this_prologue_cache)
     {
-      start = get_frame_func (this_frame);
-      trad_frame_set_id (cache,
-			 frame_id_build (trad_frame_get_this_base (cache),
-					 start));
+      CORE_ADDR func_start, stop_addr;
+
+      *this_prologue_cache = FRAME_OBSTACK_ZALLOC (struct mn10300_prologue);
+
+      func_start = get_frame_func (this_frame);
+      stop_addr = get_frame_pc (this_frame);
+
+      /* If we couldn't find any function containing the PC, then
+         just initialize the prologue cache, but don't do anything.  */
+      if (!func_start)
+        stop_addr = func_start;
+
+      mn10300_analyze_prologue (get_frame_arch (this_frame),
+                                func_start, stop_addr, *this_prologue_cache);
     }
 
-  (*this_prologue_cache) = cache;
-  return cache;
+  return *this_prologue_cache;
+}
+
+/* Given the next frame and a prologue cache, return this frame's
+   base.  */
+static CORE_ADDR
+mn10300_frame_base (struct frame_info *this_frame, void **this_prologue_cache)
+{
+  struct mn10300_prologue *p
+    = mn10300_analyze_frame_prologue (this_frame, this_prologue_cache);
+
+  /* In functions that use alloca, the distance between the stack
+     pointer and the frame base varies dynamically, so we can't use
+     the SP plus static information like prologue analysis to find the
+     frame base.  However, such functions must have a frame pointer,
+     to be able to restore the SP on exit.  So whenever we do have a
+     frame pointer, use that to find the base.  */
+  if (p->has_frame_ptr)
+    {
+      CORE_ADDR fp = get_frame_register_unsigned (this_frame, E_A3_REGNUM);
+      return fp - p->frame_ptr_offset;
+    }
+  else
+    {
+      CORE_ADDR sp = get_frame_register_unsigned (this_frame, E_SP_REGNUM);
+      return sp - p->frame_size;
+    }
 }
 
 /* Here is a dummy implementation.  */
@@ -886,26 +1132,38 @@ mn10300_dummy_id (struct gdbarch *gdbarc
   return frame_id_build (sp, pc);
 }
 
-/* Trad frame implementation.  */
 static void
 mn10300_frame_this_id (struct frame_info *this_frame,
 		       void **this_prologue_cache,
 		       struct frame_id *this_id)
 {
-  struct trad_frame_cache *cache = 
-    mn10300_frame_unwind_cache (this_frame, this_prologue_cache);
+  *this_id = frame_id_build (mn10300_frame_base (this_frame, this_prologue_cache),
+			     get_frame_func (this_frame));
 
-  trad_frame_get_id (cache, this_id);
 }
 
 static struct value *
 mn10300_frame_prev_register (struct frame_info *this_frame,
-			     void **this_prologue_cache, int regnum)
+		             void **this_prologue_cache, int regnum)
 {
-  struct trad_frame_cache *cache =
-    mn10300_frame_unwind_cache (this_frame, this_prologue_cache);
-
-  return trad_frame_get_register (cache, this_frame, regnum);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
+  struct mn10300_prologue *p
+    = mn10300_analyze_frame_prologue (this_frame, this_prologue_cache);
+  CORE_ADDR frame_base = mn10300_frame_base (this_frame, this_prologue_cache);
+  int reg_size = register_size (get_frame_arch (this_frame), regnum);
+
+  if (regnum == E_SP_REGNUM)
+    return frame_unwind_got_constant (this_frame, regnum, frame_base);
+
+  /* If prologue analysis says we saved this register somewhere,
+     return a description of the stack slot holding it.  */
+  if (p->reg_offset[regnum] != 1)
+    return frame_unwind_got_memory (this_frame, regnum,
+                                    frame_base + p->reg_offset[regnum]);
+
+  /* Otherwise, presume we haven't changed the value of this
+     register, and get it from the next frame.  */
+  return frame_unwind_got_register (this_frame, regnum, regnum);
 }
 
 static const struct frame_unwind mn10300_frame_unwind = {
@@ -917,37 +1175,20 @@ static const struct frame_unwind mn10300
 };
 
 static CORE_ADDR
-mn10300_frame_base_address (struct frame_info *this_frame,
-			    void **this_prologue_cache)
-{
-  struct trad_frame_cache *cache = 
-    mn10300_frame_unwind_cache (this_frame, this_prologue_cache);
-
-  return trad_frame_get_this_base (cache);
-}
-
-static const struct frame_base mn10300_frame_base = {
-  &mn10300_frame_unwind, 
-  mn10300_frame_base_address, 
-  mn10300_frame_base_address,
-  mn10300_frame_base_address
-};
-
-static CORE_ADDR
-mn10300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+mn10300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   ULONGEST pc;
 
-  pc = frame_unwind_register_unsigned (next_frame, E_PC_REGNUM);
+  pc = frame_unwind_register_unsigned (this_frame, E_PC_REGNUM);
   return pc;
 }
 
 static CORE_ADDR
-mn10300_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+mn10300_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   ULONGEST sp;
 
-  sp = frame_unwind_register_unsigned (next_frame, E_SP_REGNUM);
+  sp = frame_unwind_register_unsigned (this_frame, E_SP_REGNUM);
   return sp;
 }
 
@@ -956,7 +1197,6 @@ mn10300_frame_unwind_init (struct gdbarc
 {
   dwarf2_append_unwinders (gdbarch);
   frame_unwind_append_unwinder (gdbarch, &mn10300_frame_unwind);
-  frame_base_set_default (gdbarch, &mn10300_frame_base);
   set_gdbarch_dummy_id (gdbarch, mn10300_dummy_id);
   set_gdbarch_unwind_pc (gdbarch, mn10300_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, mn10300_unwind_sp);
@@ -1120,7 +1360,7 @@ mn10300_dwarf2_reg_to_regnum (struct gdb
     40, 41, 42, 43, 44, 45, 46, 47,
     48, 49, 50, 51, 52, 53, 54, 55,
     56, 57, 58, 59, 60, 61, 62, 63,
-    9
+    9, 11
   };
 
   if (dwarf2 < 0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]