* gdbthread.h (struct thread_info): Add comments around
[deliverable/binutils-gdb.git] / gdb / mn10300-tdep.c
index e0fc6a7893433cb8e6abd31899924a0ab75f7697..88cb150b73519e490e74fe7959964b6bcc60794f 100644 (file)
@@ -35,6 +35,8 @@
 #include "symtab.h"
 #include "dwarf2-frame.h"
 #include "osabi.h"
+#include "infcall.h"
+#include "target.h"
 
 #include "mn10300-tdep.h"
 
@@ -194,9 +196,9 @@ mn10300_extract_return_value (struct gdbarch *gdbarch, struct type *type,
    from WRITEBUF into REGCACHE.  */
 
 static enum return_value_convention
-mn10300_return_value (struct gdbarch *gdbarch, struct type *type,
-                     struct regcache *regcache, gdb_byte *readbuf,
-                     const gdb_byte *writebuf)
+mn10300_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                     struct type *type, struct regcache *regcache,
+                     gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   if (mn10300_use_struct_convention (type))
     return RETURN_VALUE_STRUCT_CONVENTION;
@@ -322,11 +324,11 @@ set_reg_offsets (struct frame_info *fi,
 
   if (frame_in_fp)
     {
-      base = frame_unwind_register_unsigned (fi, E_A3_REGNUM);
+      base = get_frame_register_unsigned (fi, E_A3_REGNUM);
     }
   else
     {
-      base = frame_unwind_register_unsigned (fi, E_SP_REGNUM)
+      base = get_frame_register_unsigned (fi, E_SP_REGNUM)
               + stack_extra_size;
     }
 
@@ -608,6 +610,22 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch, struct frame_info *fi,
        goto finish_prologue;
     }
 
+  /* 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;
+
+      /* 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.  */
+      status = target_read_memory (addr, buf, 2);
+      if (status != 0)
+       goto finish_prologue;
+    }
+
   if (AM33_MODE (gdbarch) == 2)
     {
       /* Determine if any floating point registers are to be saved.
@@ -635,6 +653,7 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch, struct frame_info *fi,
         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)
@@ -715,12 +734,9 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch, struct frame_info *fi,
                        break;
 
                      /* An fmov instruction has just been seen.  We can
-                        now really commit to the pattern match.  Set the
-                        address to restore at the end of this speculative
-                        bit of code to the actually address that we've
-                        been incrementing (or not) throughout the
-                        speculation.  */
-                     restore_addr = addr;
+                        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:
@@ -739,29 +755,18 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch, struct frame_info *fi,
                      imm_size = (buf[0] == 0xf9) ? 3 : 4;
                    }
                }
-             else
-               {
-                 /* No "fmov" was found. Reread the two bytes at the original
-                    "addr" to reset the state. */
-                 addr = restore_addr;
-                 if (!safe_frame_unwind_memory (fi, addr, buf, 2))
-                   goto finish_prologue;
-               }
            }
-         /* else the prologue consists entirely of an "add -SIZE,sp"
-            instruction. Handle this below. */
        }
-      /* else no "add -SIZE,sp" was found indicating no floating point
-        registers are saved in this prologue.  */
-
-      /* In the pattern match code contained within this block, `restore_addr'
-        is set to the starting address at the very beginning and then
-        iteratively to the next address to start scanning at once the
-        pattern match has succeeded.  Thus `restore_addr' will contain
-        the address to rewind to if the pattern match failed.  If the
-        match succeeded, `restore_addr' and `addr' will already have the
-        same value.  */
-      addr = restore_addr;
+      /* 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)
+       {
+         addr = restore_addr;
+         status = target_read_memory (addr, buf, 2);
+         if (status != 0)
+           goto finish_prologue;
+         stack_extra_size = 0;
+       }
     }
 
   /* Now see if we set up a frame pointer via "mov sp,a3" */
@@ -839,7 +844,7 @@ mn10300_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 /* Simple frame_unwind_cache.  
    This finds the "extra info" for the frame.  */
 struct trad_frame_cache *
-mn10300_frame_unwind_cache (struct frame_info *next_frame,
+mn10300_frame_unwind_cache (struct frame_info *this_frame,
                            void **this_prologue_cache)
 {
   struct gdbarch *gdbarch;
@@ -850,10 +855,10 @@ mn10300_frame_unwind_cache (struct frame_info *next_frame,
   if (*this_prologue_cache)
     return (*this_prologue_cache);
 
-  gdbarch = get_frame_arch (next_frame);
-  cache_p = trad_frame_cache_zalloc (next_frame);
-  pc = gdbarch_unwind_pc (gdbarch, next_frame);
-  mn10300_analyze_prologue (gdbarch, next_frame, &cache_p, pc);
+  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))
@@ -862,7 +867,7 @@ mn10300_frame_unwind_cache (struct frame_info *next_frame,
                                       start));
   else
     {
-      start = frame_func_unwind (next_frame, NORMAL_FRAME);
+      start = get_frame_func (this_frame);
       trad_frame_set_id (cache,
                         frame_id_build (trad_frame_get_this_base (cache),
                                         start));
@@ -874,65 +879,53 @@ mn10300_frame_unwind_cache (struct frame_info *next_frame,
 
 /* Here is a dummy implementation.  */
 static struct frame_id
-mn10300_unwind_dummy_id (struct gdbarch *gdbarch,
-                        struct frame_info *next_frame)
+mn10300_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
-  return frame_id_build (frame_sp_unwind (next_frame), 
-                        frame_pc_unwind (next_frame));
+  CORE_ADDR sp = get_frame_register_unsigned (this_frame, E_SP_REGNUM);
+  CORE_ADDR pc = get_frame_register_unsigned (this_frame, E_PC_REGNUM);
+  return frame_id_build (sp, pc);
 }
 
 /* Trad frame implementation.  */
 static void
-mn10300_frame_this_id (struct frame_info *next_frame,
+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 (next_frame, this_prologue_cache);
+    mn10300_frame_unwind_cache (this_frame, this_prologue_cache);
 
   trad_frame_get_id (cache, this_id);
 }
 
-static void
-mn10300_frame_prev_register (struct frame_info *next_frame,
-                            void **this_prologue_cache,
-                            int regnum, int *optimizedp,
-                            enum lval_type *lvalp, CORE_ADDR *addrp,
-                            int *realnump, gdb_byte *bufferp)
+static struct value *
+mn10300_frame_prev_register (struct frame_info *this_frame,
+                            void **this_prologue_cache, int regnum)
 {
   struct trad_frame_cache *cache =
-    mn10300_frame_unwind_cache (next_frame, this_prologue_cache);
+    mn10300_frame_unwind_cache (this_frame, this_prologue_cache);
 
-  trad_frame_get_register (cache, next_frame, regnum, optimizedp, 
-                          lvalp, addrp, realnump, bufferp);
-  /* Or...
-  trad_frame_get_prev_register (next_frame, cache->prev_regs, regnum, 
-                          optimizedp, lvalp, addrp, realnump, bufferp);
-  */
+  return trad_frame_get_register (cache, this_frame, regnum);
 }
 
 static const struct frame_unwind mn10300_frame_unwind = {
   NORMAL_FRAME,
   mn10300_frame_this_id, 
-  mn10300_frame_prev_register
+  mn10300_frame_prev_register,
+  NULL,
+  default_frame_sniffer
 };
 
 static CORE_ADDR
-mn10300_frame_base_address (struct frame_info *next_frame,
+mn10300_frame_base_address (struct frame_info *this_frame,
                            void **this_prologue_cache)
 {
   struct trad_frame_cache *cache = 
-    mn10300_frame_unwind_cache (next_frame, this_prologue_cache);
+    mn10300_frame_unwind_cache (this_frame, this_prologue_cache);
 
   return trad_frame_get_this_base (cache);
 }
 
-static const struct frame_unwind *
-mn10300_frame_sniffer (struct frame_info *next_frame)
-{
-  return &mn10300_frame_unwind;
-}
-
 static const struct frame_base mn10300_frame_base = {
   &mn10300_frame_unwind, 
   mn10300_frame_base_address, 
@@ -961,10 +954,10 @@ mn10300_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 static void
 mn10300_frame_unwind_init (struct gdbarch *gdbarch)
 {
-  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
-  frame_unwind_append_sniffer (gdbarch, mn10300_frame_sniffer);
+  dwarf2_append_unwinders (gdbarch);
+  frame_unwind_append_unwinder (gdbarch, &mn10300_frame_unwind);
   frame_base_set_default (gdbarch, &mn10300_frame_base);
-  set_gdbarch_unwind_dummy_id (gdbarch, mn10300_unwind_dummy_id);
+  set_gdbarch_dummy_id (gdbarch, mn10300_dummy_id);
   set_gdbarch_unwind_pc (gdbarch, mn10300_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, mn10300_unwind_sp);
 }
@@ -1076,6 +1069,33 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch,
 
   /* Update $sp.  */
   regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, sp);
+
+  /* On the mn10300, it's possible to move some of the stack adjustment
+     and saving of the caller-save registers out of the prologue and
+     into the call sites.  (When using gcc, this optimization can
+     occur when using the -mrelax switch.) If this occurs, the dwarf2
+     info will reflect this fact.  We can test to see if this is the
+     case by creating a new frame using the current stack pointer and
+     the address of the function that we're about to call.  We then
+     unwind SP and see if it's different than the SP of our newly
+     created frame.  If the SP values are the same, the caller is not
+     expected to allocate any additional stack.  On the other hand, if
+     the SP values are different, the difference determines the
+     additional stack that must be allocated.
+     
+     Note that we don't update the return value though because that's
+     the value of the stack just after pushing the arguments, but prior
+     to performing the call.  This value is needed in order to
+     construct the frame ID of the dummy call.   */
+  {
+    CORE_ADDR func_addr = find_function_addr (target_func, NULL);
+    CORE_ADDR unwound_sp 
+      = mn10300_unwind_sp (gdbarch, create_new_frame (sp, func_addr));
+    if (sp != unwound_sp)
+      regcache_cooked_write_unsigned (regcache, E_SP_REGNUM,
+                                      sp - (unwound_sp - sp));
+  }
+
   return sp;
 }
 
This page took 0.027353 seconds and 4 git commands to generate.