* alphafbsd-tdep.c: Update for unwinder changes.
[deliverable/binutils-gdb.git] / gdb / avr-tdep.c
index 1d50991dd14fd249ffa2b5d1107d062e27f86f8c..85f3c0a580942c01cbd56e4749d9f017331135fd 100644 (file)
@@ -1,13 +1,13 @@
 /* Target-dependent code for Atmel AVR, for GDB.
 
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 /* Target-dependent code for Atmel AVR, for GDB.
 
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   2006, 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,9 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Contributed by Theodore A. Roth, troth@openavr.org */
 
 
 /* Contributed by Theodore A. Roth, troth@openavr.org */
 
@@ -32,6 +30,7 @@
 #include "trad-frame.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "trad-frame.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
+#include "gdbtypes.h"
 #include "inferior.h"
 #include "symfile.h"
 #include "arch-utils.h"
 #include "inferior.h"
 #include "symfile.h"
 #include "arch-utils.h"
@@ -189,7 +188,7 @@ struct gdbarch_tdep
 /* Lookup the name of a register given it's number. */
 
 static const char *
 /* Lookup the name of a register given it's number. */
 
 static const char *
-avr_register_name (int regnum)
+avr_register_name (struct gdbarch *gdbarch, int regnum)
 {
   static char *register_names[] = {
     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
 {
   static char *register_names[] = {
     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -311,38 +310,18 @@ avr_pointer_to_address (struct type *type, const gdb_byte *buf)
 }
 
 static CORE_ADDR
 }
 
 static CORE_ADDR
-avr_read_pc (ptid_t ptid)
+avr_read_pc (struct regcache *regcache)
 {
 {
-  ptid_t save_ptid;
   ULONGEST pc;
   ULONGEST pc;
-  CORE_ADDR retval;
-
-  save_ptid = inferior_ptid;
-  inferior_ptid = ptid;
-  regcache_cooked_read_unsigned (current_regcache, AVR_PC_REGNUM, &pc);
-  inferior_ptid = save_ptid;
-  retval = avr_make_iaddr (pc);
-  return retval;
+  regcache_cooked_read_unsigned (regcache, AVR_PC_REGNUM, &pc);
+  return avr_make_iaddr (pc);
 }
 
 static void
 }
 
 static void
-avr_write_pc (CORE_ADDR val, ptid_t ptid)
-{
-  ptid_t save_ptid;
-
-  save_ptid = inferior_ptid;
-  inferior_ptid = ptid;
-  write_register (AVR_PC_REGNUM, avr_convert_iaddr_to_raw (val));
-  inferior_ptid = save_ptid;
-}
-
-static CORE_ADDR
-avr_read_sp (void)
+avr_write_pc (struct regcache *regcache, CORE_ADDR val)
 {
 {
-  ULONGEST sp;
-
-  regcache_cooked_read_unsigned (current_regcache, AVR_SP_REGNUM, &sp);
-  return (avr_make_saddr (sp));
+  regcache_cooked_write_unsigned (regcache, AVR_PC_REGNUM,
+                                 avr_convert_iaddr_to_raw (val));
 }
 
 static int
 }
 
 static int
@@ -765,7 +744,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
 }
 
 static CORE_ADDR
 }
 
 static CORE_ADDR
-avr_skip_prologue (CORE_ADDR pc)
+avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR func_addr, func_end;
   CORE_ADDR prologue_end = pc;
 {
   CORE_ADDR func_addr, func_end;
   CORE_ADDR prologue_end = pc;
@@ -809,7 +788,7 @@ avr_skip_prologue (CORE_ADDR pc)
    only target, this shouldn't be a problem (I hope). TRoth/2003-05-14  */
 
 static const unsigned char *
    only target, this shouldn't be a problem (I hope). TRoth/2003-05-14  */
 
 static const unsigned char *
-avr_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+avr_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr)
 {
     static unsigned char avr_break_insn [] = { 0x98, 0x95 };
     *lenptr = sizeof (avr_break_insn);
 {
     static unsigned char avr_break_insn [] = { 0x98, 0x95 };
     *lenptr = sizeof (avr_break_insn);
@@ -848,6 +827,44 @@ avr_extract_return_value (struct type *type, struct regcache *regcache,
     }
 }
 
     }
 }
 
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+   should be returned.  If it is supposed to be returned in registers,
+   and READBUF is non-zero, read the appropriate value from REGCACHE,
+   and copy it into READBUF.  If WRITEBUF is non-zero, write the value
+   from WRITEBUF into REGCACHE.  */
+
+enum return_value_convention
+avr_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                 struct type *valtype, struct regcache *regcache,
+                 gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  int struct_return = ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+                       || TYPE_CODE (valtype) == TYPE_CODE_UNION
+                       || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+                      && !(TYPE_LENGTH (valtype) == 1
+                           || TYPE_LENGTH (valtype) == 2
+                           || TYPE_LENGTH (valtype) == 4
+                           || TYPE_LENGTH (valtype) == 8));
+
+  if (writebuf != NULL)
+    {
+      gdb_assert (!struct_return);
+      error (_("Cannot store return value."));
+    }
+
+  if (readbuf != NULL)
+    {
+      gdb_assert (!struct_return);
+      avr_extract_return_value (valtype, regcache, readbuf);
+    }
+
+  if (struct_return)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+  else
+    return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+
 /* Put here the code to store, into fi->saved_regs, the addresses of
    the saved registers of frame described by FRAME_INFO.  This
    includes special registers such as pc and fp saved in special ways
 /* Put here the code to store, into fi->saved_regs, the addresses of
    the saved registers of frame described by FRAME_INFO.  This
    includes special registers such as pc and fp saved in special ways
@@ -855,7 +872,7 @@ avr_extract_return_value (struct type *type, struct regcache *regcache,
    for it IS the sp for the next frame. */
 
 struct avr_unwind_cache *
    for it IS the sp for the next frame. */
 
 struct avr_unwind_cache *
-avr_frame_unwind_cache (struct frame_info *next_frame,
+avr_frame_unwind_cache (struct frame_info *this_frame,
                         void **this_prologue_cache)
 {
   CORE_ADDR pc;
                         void **this_prologue_cache)
 {
   CORE_ADDR pc;
@@ -869,14 +886,14 @@ avr_frame_unwind_cache (struct frame_info *next_frame,
 
   info = FRAME_OBSTACK_ZALLOC (struct avr_unwind_cache);
   (*this_prologue_cache) = info;
 
   info = FRAME_OBSTACK_ZALLOC (struct avr_unwind_cache);
   (*this_prologue_cache) = info;
-  info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+  info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
   info->size = 0;
   info->prologue_type = AVR_PROLOGUE_NONE;
 
 
   info->size = 0;
   info->prologue_type = AVR_PROLOGUE_NONE;
 
-  pc = frame_func_unwind (next_frame);
+  pc = get_frame_func (this_frame);
 
 
-  if ((pc > 0) && (pc < frame_pc_unwind (next_frame)))
+  if ((pc > 0) && (pc < get_frame_pc (this_frame)))
     avr_scan_prologue (pc, info);
 
   if ((info->prologue_type != AVR_PROLOGUE_NONE)
     avr_scan_prologue (pc, info);
 
   if ((info->prologue_type != AVR_PROLOGUE_NONE)
@@ -887,8 +904,8 @@ avr_frame_unwind_cache (struct frame_info *next_frame,
       /* The SP was moved to the FP.  This indicates that a new frame
          was created.  Get THIS frame's FP value by unwinding it from
          the next frame.  */
       /* The SP was moved to the FP.  This indicates that a new frame
          was created.  Get THIS frame's FP value by unwinding it from
          the next frame.  */
-      frame_unwind_unsigned_register (next_frame, AVR_FP_REGNUM, &this_base);
-      frame_unwind_unsigned_register (next_frame, AVR_FP_REGNUM+1, &high_base);
+      this_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM);
+      high_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM+1);
       this_base += (high_base << 8);
       
       /* The FP points at the last saved register.  Adjust the FP back
       this_base += (high_base << 8);
       
       /* The FP points at the last saved register.  Adjust the FP back
@@ -899,7 +916,7 @@ avr_frame_unwind_cache (struct frame_info *next_frame,
     {
       /* Assume that the FP is this frame's SP but with that pushed
          stack space added back.  */
     {
       /* Assume that the FP is this frame's SP but with that pushed
          stack space added back.  */
-      frame_unwind_unsigned_register (next_frame, AVR_SP_REGNUM, &this_base);
+      this_base = get_frame_register_unsigned (this_frame, AVR_SP_REGNUM);
       prev_sp = this_base + info->size;
     }
 
       prev_sp = this_base + info->size;
     }
 
@@ -911,7 +928,7 @@ avr_frame_unwind_cache (struct frame_info *next_frame,
 
   /* Adjust all the saved registers so that they contain addresses and not
      offsets.  */
 
   /* Adjust all the saved registers so that they contain addresses and not
      offsets.  */
-  for (i = 0; i < NUM_REGS - 1; i++)
+  for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++)
     if (info->saved_regs[i].addr)
       {
         info->saved_regs[i].addr = (info->prev_sp - info->saved_regs[i].addr);
     if (info->saved_regs[i].addr)
       {
         info->saved_regs[i].addr = (info->prev_sp - info->saved_regs[i].addr);
@@ -937,27 +954,37 @@ avr_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
   ULONGEST pc;
 
 {
   ULONGEST pc;
 
-  frame_unwind_unsigned_register (next_frame, AVR_PC_REGNUM, &pc);
+  pc = frame_unwind_register_unsigned (next_frame, AVR_PC_REGNUM);
 
   return avr_make_iaddr (pc);
 }
 
 
   return avr_make_iaddr (pc);
 }
 
+static CORE_ADDR
+avr_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  ULONGEST sp;
+
+  sp = frame_unwind_register_unsigned (next_frame, AVR_SP_REGNUM);
+
+  return avr_make_saddr (sp);
+}
+
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct.  */
 
 static void
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct.  */
 
 static void
-avr_frame_this_id (struct frame_info *next_frame,
+avr_frame_this_id (struct frame_info *this_frame,
                    void **this_prologue_cache,
                    struct frame_id *this_id)
 {
   struct avr_unwind_cache *info
                    void **this_prologue_cache,
                    struct frame_id *this_id)
 {
   struct avr_unwind_cache *info
-    = avr_frame_unwind_cache (next_frame, this_prologue_cache);
+    = avr_frame_unwind_cache (this_frame, this_prologue_cache);
   CORE_ADDR base;
   CORE_ADDR func;
   struct frame_id id;
 
   /* The FUNC is easy.  */
   CORE_ADDR base;
   CORE_ADDR func;
   struct frame_id id;
 
   /* The FUNC is easy.  */
-  func = frame_func_unwind (next_frame);
+  func = get_frame_func (this_frame);
 
   /* Hopefully the prologue analysis either correctly determined the
      frame's base (which is the SP from the previous frame), or set
 
   /* Hopefully the prologue analysis either correctly determined the
      frame's base (which is the SP from the previous frame), or set
@@ -970,83 +997,69 @@ avr_frame_this_id (struct frame_info *next_frame,
   (*this_id) = id;
 }
 
   (*this_id) = id;
 }
 
-static void
-avr_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 *
+avr_frame_prev_register (struct frame_info *this_frame,
+                         void **this_prologue_cache, int regnum)
 {
   struct avr_unwind_cache *info
 {
   struct avr_unwind_cache *info
-    = avr_frame_unwind_cache (next_frame, this_prologue_cache);
+    = avr_frame_unwind_cache (this_frame, this_prologue_cache);
 
   if (regnum == AVR_PC_REGNUM)
     {
       if (trad_frame_addr_p (info->saved_regs, regnum))
         {
 
   if (regnum == AVR_PC_REGNUM)
     {
       if (trad_frame_addr_p (info->saved_regs, regnum))
         {
-          *optimizedp = 0;
-          *lvalp = lval_memory;
-          *addrp = info->saved_regs[regnum].addr;
-          *realnump = -1;
-          if (bufferp != NULL)
-            {
-              /* Reading the return PC from the PC register is slightly
-                 abnormal.  register_size(AVR_PC_REGNUM) says it is 4 bytes,
-                 but in reality, only two bytes (3 in upcoming mega256) are
-                 stored on the stack.
-
-                 Also, note that the value on the stack is an addr to a word
-                 not a byte, so we will need to multiply it by two at some
-                 point. 
-
-                 And to confuse matters even more, the return address stored
-                 on the stack is in big endian byte order, even though most
-                 everything else about the avr is little endian. Ick!  */
-
-              /* FIXME: number of bytes read here will need updated for the
-                 mega256 when it is available.  */
-
-              ULONGEST pc;
-              unsigned char tmp;
-              unsigned char buf[2];
-
-              read_memory (info->saved_regs[regnum].addr, buf, 2);
-
-              /* Convert the PC read from memory as a big-endian to
-                 little-endian order. */
-              tmp = buf[0];
-              buf[0] = buf[1];
-              buf[1] = tmp;
-
-              pc = (extract_unsigned_integer (buf, 2) * 2);
-              store_unsigned_integer (bufferp,
-                                      register_size (current_gdbarch, regnum),
-                                      pc);
-            }
+         /* Reading the return PC from the PC register is slightly
+            abnormal.  register_size(AVR_PC_REGNUM) says it is 4 bytes,
+            but in reality, only two bytes (3 in upcoming mega256) are
+            stored on the stack.
+
+            Also, note that the value on the stack is an addr to a word
+            not a byte, so we will need to multiply it by two at some
+            point. 
+
+            And to confuse matters even more, the return address stored
+            on the stack is in big endian byte order, even though most
+            everything else about the avr is little endian. Ick!  */
+
+         /* FIXME: number of bytes read here will need updated for the
+            mega256 when it is available.  */
+
+         ULONGEST pc;
+         unsigned char tmp;
+         unsigned char buf[2];
+
+         read_memory (info->saved_regs[regnum].addr, buf, 2);
+
+         /* Convert the PC read from memory as a big-endian to
+            little-endian order. */
+         tmp = buf[0];
+         buf[0] = buf[1];
+         buf[1] = tmp;
+
+         pc = (extract_unsigned_integer (buf, 2) * 2);
+
+         return frame_unwind_got_constant (this_frame, regnum, pc);
         }
         }
+
+      return frame_unwind_got_optimized (this_frame, regnum);
     }
     }
-  else
-    trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
-                                 optimizedp, lvalp, addrp, realnump, bufferp);
+
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
 }
 
 static const struct frame_unwind avr_frame_unwind = {
   NORMAL_FRAME,
   avr_frame_this_id,
 }
 
 static const struct frame_unwind avr_frame_unwind = {
   NORMAL_FRAME,
   avr_frame_this_id,
-  avr_frame_prev_register
+  avr_frame_prev_register,
+  NULL,
+  default_frame_sniffer
 };
 
 };
 
-const struct frame_unwind *
-avr_frame_sniffer (struct frame_info *next_frame)
-{
-  return &avr_frame_unwind;
-}
-
 static CORE_ADDR
 static CORE_ADDR
-avr_frame_base_address (struct frame_info *next_frame, void **this_cache)
+avr_frame_base_address (struct frame_info *this_frame, void **this_cache)
 {
   struct avr_unwind_cache *info
 {
   struct avr_unwind_cache *info
-    = avr_frame_unwind_cache (next_frame, this_cache);
+    = avr_frame_unwind_cache (this_frame, this_cache);
 
   return info->base;
 }
 
   return info->base;
 }
@@ -1058,18 +1071,17 @@ static const struct frame_base avr_frame_base = {
   avr_frame_base_address
 };
 
   avr_frame_base_address
 };
 
-/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
-   dummy frame.  The frame ID's base needs to match the TOS value
-   saved by save_dummy_frame_tos(), and the PC match the dummy frame's
-   breakpoint.  */
+/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy
+   frame.  The frame ID's base needs to match the TOS value saved by
+   save_dummy_frame_tos(), and the PC match the dummy frame's breakpoint.  */
 
 static struct frame_id
 
 static struct frame_id
-avr_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+avr_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   ULONGEST base;
 
 {
   ULONGEST base;
 
-  frame_unwind_unsigned_register (next_frame, AVR_SP_REGNUM, &base);
-  return frame_id_build (avr_make_saddr (base), frame_pc_unwind (next_frame));
+  base = get_frame_register_unsigned (this_frame, AVR_SP_REGNUM);
+  return frame_id_build (avr_make_saddr (base), get_frame_pc (this_frame));
 }
 
 /* When arguments must be pushed onto the stack, they go on in reverse
 }
 
 /* When arguments must be pushed onto the stack, they go on in reverse
@@ -1161,8 +1173,8 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   if (struct_return)
     {
       fprintf_unfiltered (gdb_stderr, "struct_return: 0x%lx\n", struct_addr);
   if (struct_return)
     {
       fprintf_unfiltered (gdb_stderr, "struct_return: 0x%lx\n", struct_addr);
-      write_register (argreg--, struct_addr & 0xff);
-      write_register (argreg--, (struct_addr >>8) & 0xff);
+      regcache_cooked_write_unsigned (regcache, argreg--, struct_addr & 0xff);
+      regcache_cooked_write_unsigned (regcache, argreg--, (struct_addr >>8) & 0xff);
     }
 #endif
 
     }
 #endif
 
@@ -1267,13 +1279,12 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
   set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
 
   set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
   set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
 
-  set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
-  set_gdbarch_double_format (gdbarch, &floatformat_ieee_single_little);
-  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_single_little);
+  set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
+  set_gdbarch_double_format (gdbarch, floatformats_ieee_single);
+  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_single);
 
   set_gdbarch_read_pc (gdbarch, avr_read_pc);
   set_gdbarch_write_pc (gdbarch, avr_write_pc);
 
   set_gdbarch_read_pc (gdbarch, avr_read_pc);
   set_gdbarch_write_pc (gdbarch, avr_write_pc);
-  set_gdbarch_read_sp (gdbarch, avr_read_sp);
 
   set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS);
 
 
   set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS);
 
@@ -1283,7 +1294,7 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_name (gdbarch, avr_register_name);
   set_gdbarch_register_type (gdbarch, avr_register_type);
 
   set_gdbarch_register_name (gdbarch, avr_register_name);
   set_gdbarch_register_type (gdbarch, avr_register_type);
 
-  set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value);
+  set_gdbarch_return_value (gdbarch, avr_return_value);
   set_gdbarch_print_insn (gdbarch, print_insn_avr);
 
   set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call);
   set_gdbarch_print_insn (gdbarch, print_insn_avr);
 
   set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call);
@@ -1296,12 +1307,13 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc);
 
 
   set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc);
 
-  frame_unwind_append_sniffer (gdbarch, avr_frame_sniffer);
+  frame_unwind_append_unwinder (gdbarch, &avr_frame_unwind);
   frame_base_set_default (gdbarch, &avr_frame_base);
 
   frame_base_set_default (gdbarch, &avr_frame_base);
 
-  set_gdbarch_unwind_dummy_id (gdbarch, avr_unwind_dummy_id);
+  set_gdbarch_dummy_id (gdbarch, avr_dummy_id);
 
   set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc);
 
   set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc);
+  set_gdbarch_unwind_sp (gdbarch, avr_unwind_sp);
 
   return gdbarch;
 }
 
   return gdbarch;
 }
This page took 0.029409 seconds and 4 git commands to generate.