2010-03-09 Sriraman Tallam <tmsriram@google.com>
[deliverable/binutils-gdb.git] / gdb / avr-tdep.c
index 6d6d4886a473051ff6fbafa2be31ee01afd9f298..ef7d2a71068f6a2dbf32f8057b59c63791714b37 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for Atmel AVR, for GDB.
 
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -89,6 +89,10 @@ enum
   AVR_NUM_REGS = 32 + 1 /*SREG*/ + 1 /*SP*/ + 1 /*PC*/,
   AVR_NUM_REG_BYTES = 32 + 1 /*SREG*/ + 2 /*SP*/ + 4 /*PC*/,
 
+  /* Pseudo registers.  */
+  AVR_PSEUDO_PC_REGNUM = 35,
+  AVR_NUM_PSEUDO_REGS = 1,
+
   AVR_PC_REG_INDEX = 35,       /* index into array of registers */
 
   AVR_MAX_PROLOGUE_SIZE = 64,  /* bytes */
@@ -181,6 +185,13 @@ struct gdbarch_tdep
   /* Number of bytes stored to the stack by call instructions.
      2 bytes for avr1-5, 3 bytes for avr6.  */
   int call_length;
+
+  /* Type for void.  */
+  struct type *void_type;
+  /* Type for a function returning void.  */
+  struct type *func_void_type;
+  /* Type for a pointer to a function.  Used for the type of PC.  */
+  struct type *pc_type;
 };
 
 /* Lookup the name of a register given it's number. */
@@ -193,7 +204,8 @@ avr_register_name (struct gdbarch *gdbarch, int regnum)
     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
-    "SREG", "SP", "PC"
+    "SREG", "SP", "PC2",
+    "pc"
   };
   if (regnum < 0)
     return NULL;
@@ -210,10 +222,11 @@ avr_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
   if (reg_nr == AVR_PC_REGNUM)
     return builtin_type (gdbarch)->builtin_uint32;
+  if (reg_nr == AVR_PSEUDO_PC_REGNUM)
+    return gdbarch_tdep (gdbarch)->pc_type;
   if (reg_nr == AVR_SP_REGNUM)
     return builtin_type (gdbarch)->builtin_data_ptr;
-  else
-    return builtin_type (gdbarch)->builtin_uint8;
+  return builtin_type (gdbarch)->builtin_uint8;
 }
 
 /* Instruction address checks and convertions. */
@@ -338,7 +351,43 @@ static void
 avr_write_pc (struct regcache *regcache, CORE_ADDR val)
 {
   regcache_cooked_write_unsigned (regcache, AVR_PC_REGNUM,
-                                 avr_convert_iaddr_to_raw (val));
+                                  avr_convert_iaddr_to_raw (val));
+}
+
+static void
+avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                          int regnum, gdb_byte *buf)
+{
+  ULONGEST val;
+
+  switch (regnum)
+    {
+    case AVR_PSEUDO_PC_REGNUM:
+      regcache_raw_read_unsigned (regcache, AVR_PC_REGNUM, &val);
+      val >>= 1;
+      store_unsigned_integer (buf, 4, gdbarch_byte_order (gdbarch), val);
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    }
+}
+
+static void
+avr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+                           int regnum, const gdb_byte *buf)
+{
+  ULONGEST val;
+
+  switch (regnum)
+    {
+    case AVR_PSEUDO_PC_REGNUM:
+      val = extract_unsigned_integer (buf, 4, gdbarch_byte_order (gdbarch));
+      val <<= 1;
+      regcache_raw_write_unsigned (regcache, AVR_PC_REGNUM, val);
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    }
 }
 
 /* Function: avr_scan_prologue
@@ -637,7 +686,7 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end,
           info->saved_regs[AVR_SREG_REGNUM].addr = 3;
           info->saved_regs[0].addr = 2;
           info->saved_regs[1].addr = 1;
-          info->size += 3;
+          info->size += 2;
        }
     }
 
@@ -659,9 +708,7 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end,
        break;
     }
 
-  if (vpc >= AVR_MAX_PROLOGUE_SIZE)
-     fprintf_unfiltered (gdb_stderr,
-                         _("Hit end of prologue while scanning pushes\n"));
+  gdb_assert (vpc < AVR_MAX_PROLOGUE_SIZE);
 
   /* Handle static small stack allocation using rcall or push.  */
 
@@ -1036,9 +1083,9 @@ avr_frame_prev_register (struct frame_info *this_frame,
   struct avr_unwind_cache *info
     = avr_frame_unwind_cache (this_frame, this_prologue_cache);
 
-  if (regnum == AVR_PC_REGNUM)
+  if (regnum == AVR_PC_REGNUM || regnum == AVR_PSEUDO_PC_REGNUM)
     {
-      if (trad_frame_addr_p (info->saved_regs, regnum))
+      if (trad_frame_addr_p (info->saved_regs, AVR_PC_REGNUM))
         {
          /* Reading the return PC from the PC register is slightly
             abnormal.  register_size(AVR_PC_REGNUM) says it is 4 bytes,
@@ -1058,14 +1105,18 @@ avr_frame_prev_register (struct frame_info *this_frame,
          struct gdbarch *gdbarch = get_frame_arch (this_frame);
          struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-         read_memory (info->saved_regs[regnum].addr, buf, tdep->call_length);
+         read_memory (info->saved_regs[AVR_PC_REGNUM].addr,
+                       buf, tdep->call_length);
 
          /* Extract the PC read from memory as a big-endian.  */
          pc = 0;
          for (i = 0; i < tdep->call_length; i++)
            pc = (pc << 8) | buf[i];
 
-         return frame_unwind_got_constant (this_frame, regnum, pc << 1);
+          if (regnum == AVR_PC_REGNUM)
+            pc <<= 1;
+
+         return frame_unwind_got_constant (this_frame, regnum, pc);
         }
 
       return frame_unwind_got_optimized (this_frame, regnum);
@@ -1199,10 +1250,14 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   if (struct_return)
     {
-      regcache_cooked_write_unsigned (regcache, regnum--,
-                                      struct_addr & 0xff);
-      regcache_cooked_write_unsigned (regcache, regnum--,
-                                      (struct_addr >> 8) & 0xff);
+      regcache_cooked_write_unsigned
+        (regcache, regnum--, (struct_addr >> 8) & 0xff);
+      regcache_cooked_write_unsigned
+        (regcache, regnum--, struct_addr & 0xff);
+      /* SP being post decremented, we need to reserve one byte so that the
+         return address won't overwrite the result (or vice-versa).  */
+      if (sp == struct_addr)
+        sp--;
     }
 
   for (i = 0; i < nargs; i++)
@@ -1327,6 +1382,14 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   
   tdep->call_length = call_length;
 
+  /* Create a type for PC.  We can't use builtin types here, as they may not
+     be defined.  */
+  tdep->void_type = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+  tdep->func_void_type = make_function_type (tdep->void_type, NULL);
+  tdep->pc_type = arch_type (gdbarch, TYPE_CODE_PTR, 4, NULL);
+  TYPE_TARGET_TYPE (tdep->pc_type) = tdep->func_void_type;
+  TYPE_UNSIGNED (tdep->pc_type) = 1;
+
   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
   set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
   set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
@@ -1353,6 +1416,10 @@ 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_num_pseudo_regs (gdbarch, AVR_NUM_PSEUDO_REGS);
+  set_gdbarch_pseudo_register_read (gdbarch, avr_pseudo_register_read);
+  set_gdbarch_pseudo_register_write (gdbarch, avr_pseudo_register_write);
+
   set_gdbarch_return_value (gdbarch, avr_return_value);
   set_gdbarch_print_insn (gdbarch, print_insn_avr);
 
This page took 0.026159 seconds and 4 git commands to generate.