*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index b9d65d6300f5769823cc5b68479ea11c5a73dff5..976bcf7f0e651eaef821bc1eed94bdb9be06f48f 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 
    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
@@ -887,19 +887,19 @@ mips_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
           (next_frame, gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM);
 }
 
-/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+/* 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
-mips_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+mips_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   return frame_id_build
-          (frame_unwind_register_signed (next_frame,
-                                         gdbarch_num_regs (gdbarch)
-                                         + MIPS_SP_REGNUM),
-                                         frame_pc_unwind (next_frame));
+          (get_frame_register_signed (this_frame,
+                                      gdbarch_num_regs (gdbarch)
+                                      + MIPS_SP_REGNUM),
+           get_frame_pc (this_frame));
 }
 
 static void
@@ -926,7 +926,7 @@ mips_fetch_instruction (CORE_ADDR addr)
     }
   else
     instlen = MIPS_INSN32_SIZE;
-  status = read_memory_nobpt (addr, buf, instlen);
+  status = target_read_memory (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
   return extract_unsigned_integer (buf, instlen);
@@ -1151,7 +1151,7 @@ struct upk_mips16
 
 
 /* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format
-   for the bits which make up the immediatate extension.  */
+   for the bits which make up the immediate extension.  */
 
 static CORE_ADDR
 extended_offset (unsigned int extension)
@@ -1488,7 +1488,7 @@ mips16_get_imm (unsigned short prev_inst, /* previous instruction */
 
 static CORE_ADDR
 mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                      struct frame_info *next_frame,
+                      struct frame_info *this_frame,
                       struct mips_frame_cache *this_cache)
 {
   CORE_ADDR cur_pc;
@@ -1500,19 +1500,20 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   unsigned short prev_inst = 0;        /* saved copy of previous instruction */
   unsigned inst = 0;           /* current instruction */
   unsigned entry_inst = 0;     /* the entry instruction */
+  unsigned save_inst = 0;      /* the save instruction */
   int reg, offset;
 
   int extend_bytes = 0;
   int prev_extend_bytes;
   CORE_ADDR end_prologue_addr = 0;
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
   /* Can be called when there's no process, and hence when there's no
-     NEXT_FRAME.  */
-  if (next_frame != NULL)
-    sp = frame_unwind_register_signed (next_frame,
-                                      gdbarch_num_regs (gdbarch)
-                                      + MIPS_SP_REGNUM);
+     THIS_FRAME.  */
+  if (this_frame != NULL)
+    sp = get_frame_register_signed (this_frame,
+                                   gdbarch_num_regs (gdbarch)
+                                   + MIPS_SP_REGNUM);
   else
     sp = 0;
 
@@ -1603,6 +1604,12 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
       else if ((inst & 0xf81f) == 0xe809
                && (inst & 0x700) != 0x700)     /* entry */
        entry_inst = inst;      /* save for later processing */
+      else if ((inst & 0xff80) == 0x6480)      /* save */
+       {
+         save_inst = inst;     /* save for later processing */
+         if (prev_extend_bytes)                /* extend */
+           save_inst |= prev_inst << 16;
+       }
       else if ((inst & 0xf800) == 0x1800)      /* jal(x) */
        cur_pc += MIPS_INSN16_SIZE;     /* 32-bit instruction */
       else if ((inst & 0xff1c) == 0x6704)      /* move reg,$a0-$a3 */
@@ -1661,11 +1668,106 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
        }
     }
 
+  /* The SAVE instruction is similar to ENTRY, except that defined by the
+     MIPS16e ASE of the MIPS Architecture.  Unlike with ENTRY though, the
+     size of the frame is specified as an immediate field of instruction
+     and an extended variation exists which lets additional registers and
+     frame space to be specified.  The instruction always treats registers
+     as 32-bit so its usefulness for 64-bit ABIs is questionable.  */
+  if (save_inst != 0 && mips_abi_regsize (gdbarch) == 4)
+    {
+      static int args_table[16] = {
+       0, 0, 0, 0, 1, 1, 1, 1,
+       2, 2, 2, 0, 3, 3, 4, -1,
+      };
+      static int astatic_table[16] = {
+       0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 4, 0, 1, 0, -1,
+      };
+      int aregs = (save_inst >> 16) & 0xf;
+      int xsregs = (save_inst >> 24) & 0x7;
+      int args = args_table[aregs];
+      int astatic = astatic_table[aregs];
+      long frame_size;
+
+      if (args < 0)
+       {
+         warning (_("Invalid number of argument registers encoded in SAVE."));
+         args = 0;
+       }
+      if (astatic < 0)
+       {
+         warning (_("Invalid number of static registers encoded in SAVE."));
+         astatic = 0;
+       }
+
+      /* For standard SAVE the frame size of 0 means 128.  */
+      frame_size = ((save_inst >> 16) & 0xf0) | (save_inst & 0xf);
+      if (frame_size == 0 && (save_inst >> 16) == 0)
+       frame_size = 16;
+      frame_size *= 8;
+      frame_offset += frame_size;
+
+      /* Now we can calculate what the SP must have been at the
+         start of the function prologue.  */
+      sp += frame_offset;
+
+      /* Check if A0-A3 were saved in the caller's argument save area.  */
+      for (reg = MIPS_A0_REGNUM, offset = 0; reg < args + 4; reg++)
+       {
+         set_reg_offset (this_cache, reg, sp + offset);
+         offset += mips_abi_regsize (gdbarch);
+       }
+
+      offset = -4;
+
+      /* Check if the RA register was pushed on the stack.  */
+      if (save_inst & 0x40)
+       {
+         set_reg_offset (this_cache, MIPS_RA_REGNUM, sp + offset);
+         offset -= mips_abi_regsize (gdbarch);
+       }
+
+      /* Check if the S8 register was pushed on the stack.  */
+      if (xsregs > 6)
+       {
+         set_reg_offset (this_cache, 30, sp + offset);
+         offset -= mips_abi_regsize (gdbarch);
+         xsregs--;
+       }
+      /* Check if S2-S7 were pushed on the stack.  */
+      for (reg = 18 + xsregs - 1; reg > 18 - 1; reg--)
+       {
+         set_reg_offset (this_cache, reg, sp + offset);
+         offset -= mips_abi_regsize (gdbarch);
+       }
+
+      /* Check if the S1 register was pushed on the stack.  */
+      if (save_inst & 0x10)
+       {
+         set_reg_offset (this_cache, 17, sp + offset);
+         offset -= mips_abi_regsize (gdbarch);
+       }
+      /* Check if the S0 register was pushed on the stack.  */
+      if (save_inst & 0x20)
+       {
+         set_reg_offset (this_cache, 16, sp + offset);
+         offset -= mips_abi_regsize (gdbarch);
+       }
+
+      /* Check if A0-A3 were pushed on the stack.  */
+      for (reg = MIPS_A0_REGNUM + 3; reg > MIPS_A0_REGNUM + 3 - astatic; reg--)
+       {
+         set_reg_offset (this_cache, reg, sp + offset);
+         offset -= mips_abi_regsize (gdbarch);
+       }
+    }
+
   if (this_cache != NULL)
     {
       this_cache->base =
-        (frame_unwind_register_signed (next_frame,
-                                      gdbarch_num_regs (gdbarch) + frame_reg)
+        (get_frame_register_signed (this_frame,
+                                   gdbarch_num_regs (gdbarch) + frame_reg)
          + frame_offset - frame_adjust);
       /* FIXME: brobecker/2004-10-10: Just as in the mips32 case, we should
          be able to get rid of the assignment below, evetually. But it's
@@ -1689,7 +1791,7 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
    mips_insn32 unwinder.  */
 
 static struct mips_frame_cache *
-mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_insn16_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct mips_frame_cache *cache;
 
@@ -1697,12 +1799,11 @@ mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
     return (*this_cache);
   cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
   (*this_cache) = cache;
-  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
   /* Analyze the function prologue.  */
   {
-    const CORE_ADDR pc =
-      frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+    const CORE_ADDR pc = get_frame_address_in_block (this_frame);
     CORE_ADDR start_addr;
 
     find_pc_partial_function (pc, NULL, &start_addr, NULL);
@@ -1713,62 +1814,60 @@ mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
     if (start_addr == 0)
       return cache;
 
-    mips16_scan_prologue (start_addr, pc, next_frame, *this_cache);
+    mips16_scan_prologue (start_addr, pc, this_frame, *this_cache);
   }
   
   /* gdbarch_sp_regnum contains the value and not the address.  */
   trad_frame_set_value (cache->saved_regs,
-                       gdbarch_num_regs (get_frame_arch (next_frame))
-                         + MIPS_SP_REGNUM,
+                       gdbarch_num_regs (get_frame_arch (this_frame))
+                       + MIPS_SP_REGNUM,
                        cache->base);
 
   return (*this_cache);
 }
 
 static void
-mips_insn16_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_insn16_frame_this_id (struct frame_info *this_frame, void **this_cache,
                           struct frame_id *this_id)
 {
-  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
                                                           this_cache);
-  (*this_id) = frame_id_build (info->base,
-                              frame_func_unwind (next_frame, NORMAL_FRAME));
+  (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
 }
 
-static void
-mips_insn16_frame_prev_register (struct frame_info *next_frame,
-                                void **this_cache,
-                                int regnum, int *optimizedp,
-                                enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, gdb_byte *valuep)
+static struct value *
+mips_insn16_frame_prev_register (struct frame_info *this_frame,
+                                void **this_cache, int regnum)
 {
-  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
                                                           this_cache);
-  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, valuep);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static int
+mips_insn16_frame_sniffer (const struct frame_unwind *self,
+                          struct frame_info *this_frame, void **this_cache)
+{
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  if (mips_pc_is_mips16 (pc))
+    return 1;
+  return 0;
 }
 
 static const struct frame_unwind mips_insn16_frame_unwind =
 {
   NORMAL_FRAME,
   mips_insn16_frame_this_id,
-  mips_insn16_frame_prev_register
+  mips_insn16_frame_prev_register,
+  NULL,
+  mips_insn16_frame_sniffer
 };
 
-static const struct frame_unwind *
-mips_insn16_frame_sniffer (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  if (mips_pc_is_mips16 (pc))
-    return &mips_insn16_frame_unwind;
-  return NULL;
-}
-
 static CORE_ADDR
-mips_insn16_frame_base_address (struct frame_info *next_frame,
+mips_insn16_frame_base_address (struct frame_info *this_frame,
                                void **this_cache)
 {
-  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
                                                           this_cache);
   return info->base;
 }
@@ -1782,9 +1881,10 @@ static const struct frame_base mips_insn16_frame_base =
 };
 
 static const struct frame_base *
-mips_insn16_frame_base_sniffer (struct frame_info *next_frame)
+mips_insn16_frame_base_sniffer (struct frame_info *this_frame)
 {
-  if (mips_insn16_frame_sniffer (next_frame) != NULL)
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  if (mips_pc_is_mips16 (pc))
     return &mips_insn16_frame_base;
   else
     return NULL;
@@ -1816,7 +1916,7 @@ reset_saved_regs (struct mips_frame_cache *this_cache)
 
 static CORE_ADDR
 mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                      struct frame_info *next_frame,
+                      struct frame_info *this_frame,
                       struct mips_frame_cache *this_cache)
 {
   CORE_ADDR cur_pc;
@@ -1828,14 +1928,15 @@ mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   CORE_ADDR end_prologue_addr = 0;
   int seen_sp_adjust = 0;
   int load_immediate_bytes = 0;
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
 
   /* Can be called when there's no process, and hence when there's no
-     NEXT_FRAME.  */
-  if (next_frame != NULL)
-    sp = frame_unwind_register_signed (next_frame,
-                                      gdbarch_num_regs (gdbarch)
-                                      + MIPS_SP_REGNUM);
+     THIS_FRAME.  */
+  if (this_frame != NULL)
+    sp = get_frame_register_signed (this_frame,
+                                   gdbarch_num_regs (gdbarch)
+                                   + MIPS_SP_REGNUM);
   else
     sp = 0;
 
@@ -1871,11 +1972,13 @@ restart:
            break;
           seen_sp_adjust = 1;
        }
-      else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+      else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+               && !regsize_is_64_bits)
        {
          set_reg_offset (this_cache, reg, sp + low_word);
        }
-      else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
+      else if (((high_word & 0xFFE0) == 0xffa0)        /* sd reg,offset($sp) */
+               && regsize_is_64_bits)
        {
          /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra.  */
          set_reg_offset (this_cache, reg, sp + low_word);
@@ -1885,13 +1988,13 @@ restart:
          /* Old gcc frame, r30 is virtual frame pointer.  */
          if ((long) low_word != frame_offset)
            frame_addr = sp + low_word;
-         else if (next_frame && frame_reg == MIPS_SP_REGNUM)
+         else if (this_frame && frame_reg == MIPS_SP_REGNUM)
            {
              unsigned alloca_adjust;
 
              frame_reg = 30;
-             frame_addr = frame_unwind_register_signed
-                            (next_frame, gdbarch_num_regs (gdbarch) + 30);
+             frame_addr = get_frame_register_signed
+               (this_frame, gdbarch_num_regs (gdbarch) + 30);
 
              alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
              if (alloca_adjust > 0)
@@ -1915,13 +2018,13 @@ restart:
       else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
        {
          /* New gcc frame, virtual frame pointer is at r30 + frame_size.  */
-         if (next_frame && frame_reg == MIPS_SP_REGNUM)
+         if (this_frame && frame_reg == MIPS_SP_REGNUM)
            {
              unsigned alloca_adjust;
 
              frame_reg = 30;
-             frame_addr = frame_unwind_register_signed
-                            (next_frame, gdbarch_num_regs (gdbarch) + 30);
+             frame_addr = get_frame_register_signed
+               (this_frame, gdbarch_num_regs (gdbarch) + 30);
 
              alloca_adjust = (unsigned) (frame_addr - sp);
              if (alloca_adjust > 0)
@@ -1939,7 +2042,8 @@ restart:
                }
            }
        }
-      else if ((high_word & 0xFFE0) == 0xafc0) /* sw reg,offset($30) */
+      else if ((high_word & 0xFFE0) == 0xafc0  /* sw reg,offset($30) */
+               && !regsize_is_64_bits)
        {
          set_reg_offset (this_cache, reg, frame_addr + low_word);
        }
@@ -1987,8 +2091,8 @@ restart:
   if (this_cache != NULL)
     {
       this_cache->base = 
-        (frame_unwind_register_signed (next_frame,
-                                      gdbarch_num_regs (gdbarch) + frame_reg)
+        (get_frame_register_signed (this_frame,
+                                   gdbarch_num_regs (gdbarch) + frame_reg)
          + frame_offset);
       /* FIXME: brobecker/2004-09-15: We should be able to get rid of
          this assignment below, eventually.  But it's still needed
@@ -2023,7 +2127,7 @@ restart:
    unwinder.  */
 
 static struct mips_frame_cache *
-mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_insn32_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct mips_frame_cache *cache;
 
@@ -2032,12 +2136,11 @@ mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
 
   cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
   (*this_cache) = cache;
-  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
   /* Analyze the function prologue.  */
   {
-    const CORE_ADDR pc =
-      frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+    const CORE_ADDR pc = get_frame_address_in_block (this_frame);
     CORE_ADDR start_addr;
 
     find_pc_partial_function (pc, NULL, &start_addr, NULL);
@@ -2048,62 +2151,60 @@ mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
     if (start_addr == 0)
       return cache;
 
-    mips32_scan_prologue (start_addr, pc, next_frame, *this_cache);
+    mips32_scan_prologue (start_addr, pc, this_frame, *this_cache);
   }
   
   /* gdbarch_sp_regnum contains the value and not the address.  */
   trad_frame_set_value (cache->saved_regs,
-                       gdbarch_num_regs (get_frame_arch (next_frame))
-                         + MIPS_SP_REGNUM,
+                       gdbarch_num_regs (get_frame_arch (this_frame))
+                       + MIPS_SP_REGNUM,
                        cache->base);
 
   return (*this_cache);
 }
 
 static void
-mips_insn32_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_insn32_frame_this_id (struct frame_info *this_frame, void **this_cache,
                           struct frame_id *this_id)
 {
-  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
                                                           this_cache);
-  (*this_id) = frame_id_build (info->base,
-                              frame_func_unwind (next_frame, NORMAL_FRAME));
+  (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
 }
 
-static void
-mips_insn32_frame_prev_register (struct frame_info *next_frame,
-                                void **this_cache,
-                                int regnum, int *optimizedp,
-                                enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, gdb_byte *valuep)
+static struct value *
+mips_insn32_frame_prev_register (struct frame_info *this_frame,
+                                void **this_cache, int regnum)
 {
-  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
                                                           this_cache);
-  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, valuep);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static int
+mips_insn32_frame_sniffer (const struct frame_unwind *self,
+                          struct frame_info *this_frame, void **this_cache)
+{
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  if (! mips_pc_is_mips16 (pc))
+    return 1;
+  return 0;
 }
 
 static const struct frame_unwind mips_insn32_frame_unwind =
 {
   NORMAL_FRAME,
   mips_insn32_frame_this_id,
-  mips_insn32_frame_prev_register
+  mips_insn32_frame_prev_register,
+  NULL,
+  mips_insn32_frame_sniffer
 };
 
-static const struct frame_unwind *
-mips_insn32_frame_sniffer (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  if (! mips_pc_is_mips16 (pc))
-    return &mips_insn32_frame_unwind;
-  return NULL;
-}
-
 static CORE_ADDR
-mips_insn32_frame_base_address (struct frame_info *next_frame,
+mips_insn32_frame_base_address (struct frame_info *this_frame,
                                void **this_cache)
 {
-  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
                                                           this_cache);
   return info->base;
 }
@@ -2117,38 +2218,41 @@ static const struct frame_base mips_insn32_frame_base =
 };
 
 static const struct frame_base *
-mips_insn32_frame_base_sniffer (struct frame_info *next_frame)
+mips_insn32_frame_base_sniffer (struct frame_info *this_frame)
 {
-  if (mips_insn32_frame_sniffer (next_frame) != NULL)
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  if (! mips_pc_is_mips16 (pc))
     return &mips_insn32_frame_base;
   else
     return NULL;
 }
 
 static struct trad_frame_cache *
-mips_stub_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_stub_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   CORE_ADDR pc;
   CORE_ADDR start_addr;
   CORE_ADDR stack_addr;
   struct trad_frame_cache *this_trad_cache;
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  int num_regs = gdbarch_num_regs (gdbarch);
 
   if ((*this_cache) != NULL)
     return (*this_cache);
-  this_trad_cache = trad_frame_cache_zalloc (next_frame);
+  this_trad_cache = trad_frame_cache_zalloc (this_frame);
   (*this_cache) = this_trad_cache;
 
   /* The return address is in the link register.  */
   trad_frame_set_reg_realreg (this_trad_cache,
                              gdbarch_pc_regnum (gdbarch),
-                             (gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM));
+                             num_regs + MIPS_RA_REGNUM);
 
   /* Frame ID, since it's a frameless / stackless function, no stack
      space is allocated and SP on entry is the current SP.  */
-  pc = frame_pc_unwind (next_frame);
+  pc = get_frame_pc (this_frame);
   find_pc_partial_function (pc, NULL, &start_addr, NULL);
-  stack_addr = frame_unwind_register_signed (next_frame, MIPS_SP_REGNUM);
+  stack_addr = get_frame_register_signed (this_frame,
+                                         num_regs + MIPS_SP_REGNUM);
   trad_frame_set_id (this_trad_cache, frame_id_build (stack_addr, start_addr));
 
   /* Assume that the frame's base is the same as the
@@ -2159,47 +2263,37 @@ mips_stub_frame_cache (struct frame_info *next_frame, void **this_cache)
 }
 
 static void
-mips_stub_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_stub_frame_this_id (struct frame_info *this_frame, void **this_cache,
                         struct frame_id *this_id)
 {
   struct trad_frame_cache *this_trad_cache
-    = mips_stub_frame_cache (next_frame, this_cache);
+    = mips_stub_frame_cache (this_frame, this_cache);
   trad_frame_get_id (this_trad_cache, this_id);
 }
 
-static void
-mips_stub_frame_prev_register (struct frame_info *next_frame,
-                                void **this_cache,
-                                int regnum, int *optimizedp,
-                                enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, gdb_byte *valuep)
+static struct value *
+mips_stub_frame_prev_register (struct frame_info *this_frame,
+                              void **this_cache, int regnum)
 {
   struct trad_frame_cache *this_trad_cache
-    = mips_stub_frame_cache (next_frame, this_cache);
-  trad_frame_get_register (this_trad_cache, next_frame, regnum, optimizedp,
-                          lvalp, addrp, realnump, valuep);
+    = mips_stub_frame_cache (this_frame, this_cache);
+  return trad_frame_get_register (this_trad_cache, this_frame, regnum);
 }
 
-static const struct frame_unwind mips_stub_frame_unwind =
-{
-  NORMAL_FRAME,
-  mips_stub_frame_this_id,
-  mips_stub_frame_prev_register
-};
-
-static const struct frame_unwind *
-mips_stub_frame_sniffer (struct frame_info *next_frame)
+static int
+mips_stub_frame_sniffer (const struct frame_unwind *self,
+                        struct frame_info *this_frame, void **this_cache)
 {
   gdb_byte dummy[4];
   struct obj_section *s;
-  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+  CORE_ADDR pc = get_frame_address_in_block (this_frame);
 
   /* Use the stub unwinder for unreadable code.  */
-  if (target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0)
-    return &mips_stub_frame_unwind;
+  if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
+    return 1;
 
   if (in_plt_section (pc, NULL))
-    return &mips_stub_frame_unwind;
+    return 1;
 
   /* Binutils for MIPS puts lazy resolution stubs into .MIPS.stubs.  */
   s = find_pc_section (pc);
@@ -2207,17 +2301,26 @@ mips_stub_frame_sniffer (struct frame_info *next_frame)
   if (s != NULL
       && strcmp (bfd_get_section_name (s->objfile->obfd, s->the_bfd_section),
                 ".MIPS.stubs") == 0)
-    return &mips_stub_frame_unwind;
+    return 1;
 
-  return NULL;
+  return 0;
 }
 
+static const struct frame_unwind mips_stub_frame_unwind =
+{
+  NORMAL_FRAME,
+  mips_stub_frame_this_id,
+  mips_stub_frame_prev_register,
+  NULL,
+  mips_stub_frame_sniffer
+};
+
 static CORE_ADDR
-mips_stub_frame_base_address (struct frame_info *next_frame,
+mips_stub_frame_base_address (struct frame_info *this_frame,
                              void **this_cache)
 {
   struct trad_frame_cache *this_trad_cache
-    = mips_stub_frame_cache (next_frame, this_cache);
+    = mips_stub_frame_cache (this_frame, this_cache);
   return trad_frame_get_this_base (this_trad_cache);
 }
 
@@ -2230,9 +2333,9 @@ static const struct frame_base mips_stub_frame_base =
 };
 
 static const struct frame_base *
-mips_stub_frame_base_sniffer (struct frame_info *next_frame)
+mips_stub_frame_base_sniffer (struct frame_info *this_frame)
 {
-  if (mips_stub_frame_sniffer (next_frame) != NULL)
+  if (mips_stub_frame_sniffer (&mips_stub_frame_unwind, this_frame, NULL))
     return &mips_stub_frame_base;
   else
     return NULL;
@@ -2849,14 +2952,63 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 /* Determine the return value convention being used.  */
 
 static enum return_value_convention
-mips_eabi_return_value (struct gdbarch *gdbarch,
+mips_eabi_return_value (struct gdbarch *gdbarch, struct type *func_type,
                        struct type *type, struct regcache *regcache,
                        gdb_byte *readbuf, const gdb_byte *writebuf)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int fp_return_type = 0;
+  int offset, regnum, xfer;
+
   if (TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
     return RETURN_VALUE_STRUCT_CONVENTION;
-  if (readbuf)
-    memset (readbuf, 0, TYPE_LENGTH (type));
+
+  /* Floating point type?  */
+  if (tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+       fp_return_type = 1;
+      /* Structs with a single field of float type 
+        are returned in a floating point register.  */
+      if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
+          || TYPE_CODE (type) == TYPE_CODE_UNION)
+         && TYPE_NFIELDS (type) == 1)
+       {
+         struct type *fieldtype = TYPE_FIELD_TYPE (type, 0);
+
+         if (TYPE_CODE (check_typedef (fieldtype)) == TYPE_CODE_FLT)
+           fp_return_type = 1;
+       }
+    }
+
+  if (fp_return_type)      
+    {
+      /* A floating-point value belongs in the least significant part
+        of FP0/FP1.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
+      regnum = mips_regnum (gdbarch)->fp0;
+    }
+  else 
+    {
+      /* An integer value goes in V0/V1.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return scalar in $v0\n");
+      regnum = MIPS_V0_REGNUM;
+    }
+  for (offset = 0;
+       offset < TYPE_LENGTH (type);
+       offset += mips_abi_regsize (gdbarch), regnum++)
+    {
+      xfer = mips_abi_regsize (gdbarch);
+      if (offset + xfer > TYPE_LENGTH (type))
+       xfer = TYPE_LENGTH (type) - offset;
+      mips_xfer_register (gdbarch, regcache,
+                         gdbarch_num_regs (gdbarch) + regnum, xfer,
+                         gdbarch_byte_order (gdbarch), readbuf, writebuf,
+                         offset);
+    }
+
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
@@ -3082,8 +3234,21 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 purpose register.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM)
                {
-                 LONGEST regval =
-                   extract_unsigned_integer (val, partial_len);
+                 LONGEST regval;
+
+                 /* Sign extend pointers, 32-bit integers and signed
+                    16-bit and 8-bit integers; everything else is taken
+                    as is.  */
+
+                 if ((partial_len == 4
+                      && (typecode == TYPE_CODE_PTR
+                          || typecode == TYPE_CODE_INT))
+                     || (partial_len < 4
+                         && typecode == TYPE_CODE_INT
+                         && !TYPE_UNSIGNED (arg_type)))
+                   regval = extract_signed_integer (val, partial_len);
+                 else
+                   regval = extract_unsigned_integer (val, partial_len);
 
                  /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
@@ -3146,7 +3311,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 }
 
 static enum return_value_convention
-mips_n32n64_return_value (struct gdbarch *gdbarch,
+mips_n32n64_return_value (struct gdbarch *gdbarch, struct type *func_type,
                          struct type *type, struct regcache *regcache,
                          gdb_byte *readbuf, const gdb_byte *writebuf)
 {
@@ -3604,8 +3769,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 }
 
 static enum return_value_convention
-mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
-                      struct regcache *regcache,
+mips_o32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                      struct type *type, struct regcache *regcache,
                       gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -3993,7 +4158,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 }
 
 static enum return_value_convention
-mips_o64_return_value (struct gdbarch *gdbarch,
+mips_o64_return_value (struct gdbarch *gdbarch, struct type *func_type,
                       struct type *type, struct regcache *regcache,
                       gdb_byte *readbuf, const gdb_byte *writebuf)
 {
@@ -4468,7 +4633,7 @@ mips_single_step_through_delay (struct gdbarch *gdbarch,
    delay slot of a non-prologue instruction).  */
 
 static CORE_ADDR
-mips_skip_prologue (CORE_ADDR pc)
+mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR limit_pc;
   CORE_ADDR func_addr;
@@ -4611,6 +4776,15 @@ static void
 show_mipsfpu_command (char *args, int from_tty)
 {
   char *fpu;
+
+  if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_mips)
+    {
+      printf_unfiltered
+       ("The MIPS floating-point coprocessor is unknown "
+        "because the current architecture is not MIPS.\n");
+      return;
+    }
+
   switch (MIPS_FPU_TYPE)
     {
     case MIPS_FPU_SINGLE:
@@ -4754,7 +4928,7 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
     info->disassembler_options = "gpr-names=32";
 
   /* Call the appropriate disassembler based on the target endian-ness.  */
-  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+  if (info->endian == BFD_ENDIAN_BIG)
     return print_insn_big_mips (memaddr, info);
   else
     return print_insn_little_mips (memaddr, info);
@@ -4929,23 +5103,22 @@ mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
    [1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
 
 static int
-mips_stab_reg_to_regnum (int num)
+mips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
 {
   int regnum;
   if (num >= 0 && num < 32)
     regnum = num;
   else if (num >= 38 && num < 70)
-    regnum = num + mips_regnum (current_gdbarch)->fp0 - 38;
+    regnum = num + mips_regnum (gdbarch)->fp0 - 38;
   else if (num == 70)
-    regnum = mips_regnum (current_gdbarch)->hi;
+    regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
-    regnum = mips_regnum (current_gdbarch)->lo;
+    regnum = mips_regnum (gdbarch)->lo;
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
-    return gdbarch_num_regs (current_gdbarch)
-          + gdbarch_num_pseudo_regs (current_gdbarch);
-  return gdbarch_num_regs (current_gdbarch) + regnum;
+    return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+  return gdbarch_num_regs (gdbarch) + regnum;
 }
 
 
@@ -4953,39 +5126,36 @@ mips_stab_reg_to_regnum (int num)
    gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
 
 static int
-mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num)
+mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num)
 {
   int regnum;
   if (num >= 0 && num < 32)
     regnum = num;
   else if (num >= 32 && num < 64)
-    regnum = num + mips_regnum (current_gdbarch)->fp0 - 32;
+    regnum = num + mips_regnum (gdbarch)->fp0 - 32;
   else if (num == 64)
-    regnum = mips_regnum (current_gdbarch)->hi;
+    regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
-    regnum = mips_regnum (current_gdbarch)->lo;
+    regnum = mips_regnum (gdbarch)->lo;
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
-    return gdbarch_num_regs (current_gdbarch)
-          + gdbarch_num_pseudo_regs (current_gdbarch);
-  return gdbarch_num_regs (current_gdbarch) + regnum;
+    return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+  return gdbarch_num_regs (gdbarch) + regnum;
 }
 
 static int
-mips_register_sim_regno (int regnum)
+mips_register_sim_regno (struct gdbarch *gdbarch, int regnum)
 {
   /* Only makes sense to supply raw registers.  */
-  gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch));
+  gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch));
   /* FIXME: cagney/2002-05-13: Need to look at the pseudo register to
      decide if it is valid.  Should instead define a standard sim/gdb
      register numbering scheme.  */
-  if (gdbarch_register_name (current_gdbarch,
-                            gdbarch_num_regs
-                              (current_gdbarch) + regnum) != NULL
-      && gdbarch_register_name (current_gdbarch,
-                               gdbarch_num_regs
-                                 (current_gdbarch) + regnum)[0] != '\0')
+  if (gdbarch_register_name (gdbarch,
+                            gdbarch_num_regs (gdbarch) + regnum) != NULL
+      && gdbarch_register_name (gdbarch,
+                               gdbarch_num_regs (gdbarch) + regnum)[0] != '\0')
     return regnum;
   else
     return LEGACY_SIM_REGNO_IGNORE;
@@ -5654,14 +5824,12 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Unwind the frame.  */
   set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, mips_unwind_sp);
-  set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id);
+  set_gdbarch_dummy_id (gdbarch, mips_dummy_id);
 
   /* Map debug register numbers onto internal register numbers.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
   set_gdbarch_ecoff_reg_to_regnum (gdbarch,
                                   mips_dwarf_dwarf2_ecoff_reg_to_regnum);
-  set_gdbarch_dwarf_reg_to_regnum (gdbarch,
-                                  mips_dwarf_dwarf2_ecoff_reg_to_regnum);
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch,
                                    mips_dwarf_dwarf2_ecoff_reg_to_regnum);
   set_gdbarch_register_sim_regno (gdbarch, mips_register_sim_regno);
@@ -5717,10 +5885,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   gdbarch_init_osabi (info, gdbarch);
 
   /* Unwind the frame.  */
-  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
-  frame_unwind_append_sniffer (gdbarch, mips_stub_frame_sniffer);
-  frame_unwind_append_sniffer (gdbarch, mips_insn16_frame_sniffer);
-  frame_unwind_append_sniffer (gdbarch, mips_insn32_frame_sniffer);
+  dwarf2_append_unwinders (gdbarch);
+  frame_unwind_append_unwinder (gdbarch, &mips_stub_frame_unwind);
+  frame_unwind_append_unwinder (gdbarch, &mips_insn16_frame_unwind);
+  frame_unwind_append_unwinder (gdbarch, &mips_insn32_frame_unwind);
   frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
   frame_base_append_sniffer (gdbarch, mips_stub_frame_base_sniffer);
   frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer);
This page took 0.039197 seconds and 4 git commands to generate.