* alpha-tdep.c (alpha_register_type): Use builtin_type (gdbarch)
[deliverable/binutils-gdb.git] / gdb / mn10300-tdep.c
index 9fcae8a9560b12c14b947d3158a5f8c56bd6b622..50a72074311772da4d02f32cbe70886e21194501 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;
@@ -263,7 +265,7 @@ am33_2_register_name (struct gdbarch *gdbarch, int reg)
 static struct type *
 mn10300_register_type (struct gdbarch *gdbarch, int reg)
 {
-  return builtin_type_int;
+  return builtin_type (gdbarch)->builtin_int;
 }
 
 static CORE_ADDR
@@ -307,6 +309,7 @@ set_reg_offsets (struct frame_info *fi,
                  int stack_extra_size,
                  int frame_in_fp)
 {
+  struct gdbarch *gdbarch;
   struct trad_frame_cache *cache;
   int offset = 0;
   CORE_ADDR base;
@@ -317,19 +320,21 @@ set_reg_offsets (struct frame_info *fi,
   cache = mn10300_frame_unwind_cache (fi, this_cache);
   if (cache == NULL)
     return;
+  gdbarch = get_frame_arch (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) + stack_extra_size;
+      base = get_frame_register_unsigned (fi, E_SP_REGNUM)
+              + stack_extra_size;
     }
 
   trad_frame_set_this_base (cache, base);
 
-  if (AM33_MODE == 2)
+  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.
@@ -342,7 +347,8 @@ set_reg_offsets (struct frame_info *fi,
            {
              if (fpregmask & (1 << i))
                {
-                 trad_frame_set_reg_addr (cache, E_FS0_REGNUM + i, base + offset);
+                 trad_frame_set_reg_addr (cache, E_FS0_REGNUM + i,
+                                          base + offset);
                  offset += 4;
                }
            }
@@ -385,7 +391,7 @@ set_reg_offsets (struct frame_info *fi,
       trad_frame_set_reg_addr (cache, E_D2_REGNUM, base + offset);
       offset += 4;
     }
-  if (AM33_MODE)
+  if (AM33_MODE (gdbarch))
     {
       if (movm_args & movm_exother_bit)
         {
@@ -515,7 +521,7 @@ set_reg_offsets (struct frame_info *fi,
    frame chain to not bother trying to unwind past this frame.  */
 
 static CORE_ADDR
-mn10300_analyze_prologue (struct frame_info *fi, 
+mn10300_analyze_prologue (struct gdbarch *gdbarch, struct frame_info *fi, 
                          void **this_cache, 
                          CORE_ADDR pc)
 {
@@ -604,7 +610,23 @@ mn10300_analyze_prologue (struct frame_info *fi,
        goto finish_prologue;
     }
 
-  if (AM33_MODE == 2)
+  /* 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.
         Look for one of the following three prologue formats:
@@ -631,6 +653,7 @@ mn10300_analyze_prologue (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)
@@ -711,12 +734,9 @@ mn10300_analyze_prologue (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:
@@ -735,29 +755,18 @@ mn10300_analyze_prologue (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" */
@@ -818,7 +827,8 @@ mn10300_analyze_prologue (struct frame_info *fi,
  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);
+    set_reg_offsets (fi, this_cache, movm_args, fpregmask, stack_extra_size,
+                    frame_in_fp);
   return addr;
 }
 
@@ -828,15 +838,16 @@ mn10300_analyze_prologue (struct frame_info *fi,
 static CORE_ADDR
 mn10300_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  return mn10300_analyze_prologue (NULL, NULL, pc);
+  return mn10300_analyze_prologue (gdbarch, NULL, NULL, 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;
   struct trad_frame_cache *cache;
   CORE_ADDR pc, start, end;
   void *cache_p;
@@ -844,9 +855,10 @@ mn10300_frame_unwind_cache (struct frame_info *next_frame,
   if (*this_prologue_cache)
     return (*this_prologue_cache);
 
-  cache_p = trad_frame_cache_zalloc (next_frame);
-  pc = gdbarch_unwind_pc (get_frame_arch (next_frame), next_frame);
-  mn10300_analyze_prologue (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))
@@ -855,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));
@@ -867,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, 
@@ -954,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);
 }
@@ -1069,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;
 }
 
@@ -1080,7 +1107,7 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch,
    to work with the existing GDB, neither of them can change.  So we
    just have to cope.  */
 static int
-mn10300_dwarf2_reg_to_regnum (int dwarf2)
+mn10300_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int dwarf2)
 {
   /* This table is supposed to be shaped like the gdbarch_register_name
      initializer in gcc/config/mn10300/mn10300.h.  Registers which
This page took 0.02952 seconds and 4 git commands to generate.