]> Git Repo - binutils.git/blobdiff - gdb/mips-tdep.c
* gdb.disasm/hppa.s (addib_tests): Fix typo.
[binutils.git] / gdb / mips-tdep.c
index b86fea90cd6371e9ab2552dd6ea0f7f76bbfc414..2bc9a038f97c5403590736888a68ae36770beeca 100644 (file)
@@ -1,5 +1,6 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
-   Copyright 1988, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994
+   Free Software Foundation, Inc.
    Contributed by Alessandro Forin([email protected]) at CMU
    and by Per Bothner([email protected]) at U.Wisconsin.
 
    Contributed by Alessandro Forin([email protected]) at CMU
    and by Per Bothner([email protected]) at U.Wisconsin.
 
@@ -30,8 +31,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "symfile.h"
 #include "objfiles.h"
 
 #include "symfile.h"
 #include "objfiles.h"
 
+#include "opcode/mips.h"
+
 #define VM_MIN_ADDRESS (unsigned)0x400000
 \f
 #define VM_MIN_ADDRESS (unsigned)0x400000
 \f
+#if 0
+static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#endif
+
 /* Some MIPS boards don't support floating point, so we permit the
    user to turn it off.  */
 int mips_fpu = 1;
 /* Some MIPS boards don't support floating point, so we permit the
    user to turn it off.  */
 int mips_fpu = 1;
@@ -70,19 +77,25 @@ read_next_frame_reg(fi, regno)
      int regno;
 {
   /* If it is the frame for sigtramp we have a complete sigcontext
      int regno;
 {
   /* If it is the frame for sigtramp we have a complete sigcontext
-     immediately below the frame and we get the saved registers from there.
+     somewhere above the frame and we get the saved registers from there.
      If the stack layout for sigtramp changes we might have to change these
      If the stack layout for sigtramp changes we might have to change these
-     constants and the companion fixup_sigtramp in mipsread.c  */
+     constants and the companion fixup_sigtramp in mdebugread.c  */
 #ifndef SIGFRAME_BASE
 #ifndef SIGFRAME_BASE
-#define SIGFRAME_BASE          0x12c   /* sizeof(sigcontext) */
-#define SIGFRAME_PC_OFF                (-SIGFRAME_BASE + 2 * 4)
-#define SIGFRAME_REGSAVE_OFF   (-SIGFRAME_BASE + 3 * 4)
+/* To satisfy alignment restrictions the sigcontext is located 4 bytes
+   above the sigtramp frame.  */
+#define SIGFRAME_BASE          4
+#define SIGFRAME_PC_OFF                (SIGFRAME_BASE + 2 * 4)
+#define SIGFRAME_REGSAVE_OFF   (SIGFRAME_BASE + 3 * 4)
+#endif
+#ifndef SIGFRAME_REG_SIZE
+#define SIGFRAME_REG_SIZE      4
 #endif
   for (; fi; fi = fi->next)
 #endif
   for (; fi; fi = fi->next)
-      if (in_sigtramp(fi->pc, 0)) {
+      if (fi->signal_handler_caller) {
          int offset;
          if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF;
          int offset;
          if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF;
-         else if (regno < 32) offset = SIGFRAME_REGSAVE_OFF + regno * 4;
+         else if (regno < 32) offset = (SIGFRAME_REGSAVE_OFF
+                                        + regno * SIGFRAME_REG_SIZE);
          else return 0;
          return read_memory_integer(fi->frame + offset, 4);
       }
          else return 0;
          return read_memory_integer(fi->frame + offset, 4);
       }
@@ -97,7 +110,10 @@ mips_frame_saved_pc(frame)
      FRAME frame;
 {
   mips_extra_func_info_t proc_desc = frame->proc_desc;
      FRAME frame;
 {
   mips_extra_func_info_t proc_desc = frame->proc_desc;
-  int pcreg = proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM;
+  /* We have to get the saved pc from the sigcontext
+     if it is a signal handler frame.  */
+  int pcreg = frame->signal_handler_caller ? PC_REGNUM
+             : (proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM);
 
   if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
       return read_memory_integer(frame->frame - 4, 4);
 
   if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
       return read_memory_integer(frame->frame - 4, 4);
@@ -135,12 +151,25 @@ heuristic_proc_start(pc)
               decstation).  22apr93 [email protected].  */
            if (!stop_soon_quietly)
              {
               decstation).  22apr93 [email protected].  */
            if (!stop_soon_quietly)
              {
+               static int blurb_printed = 0;
+
                if (fence == VM_MIN_ADDRESS)
                  warning("Hit beginning of text section without finding");
                else
                  warning("Hit heuristic-fence-post without finding");
                
                if (fence == VM_MIN_ADDRESS)
                  warning("Hit beginning of text section without finding");
                else
                  warning("Hit heuristic-fence-post without finding");
                
-               warning("enclosing function for pc 0x%x", pc);
+               warning("enclosing function for address 0x%x", pc);
+               if (!blurb_printed)
+                 {
+                   printf_filtered ("\
+This warning occurs if you are debugging a function without any symbols\n\
+(for example, in a stripped executable).  In that case, you may wish to\n\
+increase the size of the search with the `set heuristic-fence-post' command.\n\
+\n\
+Otherwise, you told GDB there was a function where there isn't one, or\n\
+(more likely) you have encountered a bug in GDB.\n");
+                   blurb_printed = 1;
+                 }
              }
 
            return 0; 
              }
 
            return 0; 
@@ -166,24 +195,26 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
     CORE_ADDR cur_pc;
     int frame_size;
     int has_frame_reg = 0;
     CORE_ADDR cur_pc;
     int frame_size;
     int has_frame_reg = 0;
-    int reg30; /* Value of $r30. Used by gcc for frame-pointer */
+    int reg30 = 0; /* Value of $r30. Used by gcc for frame-pointer */
     unsigned long reg_mask = 0;
 
     if (start_pc == 0) return NULL;
     unsigned long reg_mask = 0;
 
     if (start_pc == 0) return NULL;
-    bzero(&temp_proc_desc, sizeof(temp_proc_desc));
-    bzero(&temp_saved_regs, sizeof(struct frame_saved_regs));
+    memset(&temp_proc_desc, '\0', sizeof(temp_proc_desc));
+    memset(&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
     PROC_LOW_ADDR(&temp_proc_desc) = start_pc;
 
     if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;
   restart:
     frame_size = 0;
     for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
     PROC_LOW_ADDR(&temp_proc_desc) = start_pc;
 
     if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;
   restart:
     frame_size = 0;
     for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
+        char buf[4];
        unsigned long word;
        int status;
 
        unsigned long word;
        int status;
 
-       status = read_memory_nobpt (cur_pc, (char *)&word, 4); 
-       if (status) memory_error (status, cur_pc); 
-       SWAP_TARGET_AND_HOST (&word, sizeof (word));
+       status = read_memory_nobpt (cur_pc, buf, 4); 
+       if (status) memory_error (status, cur_pc);
+       word = extract_unsigned_integer (buf, 4);
+
        if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */
            frame_size += (-word) & 0xFFFF;
        else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */
        if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */
            frame_size += (-word) & 0xFFFF;
        else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */
@@ -191,19 +222,19 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
        else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */
            int reg = (word & 0x001F0000) >> 16;
            reg_mask |= 1 << reg;
        else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */
            int reg = (word & 0x001F0000) >> 16;
            reg_mask |= 1 << reg;
-           temp_saved_regs.regs[reg] = sp + (short)word;
+           temp_saved_regs.regs[reg] = sp + (word & 0xffff);
        }
        else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size */
        }
        else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size */
-           if ((unsigned short)word != frame_size)
-               reg30 = sp + (unsigned short)word;
+           if ((word & 0xffff) != frame_size)
+               reg30 = sp + (word & 0xffff);
            else if (!has_frame_reg) {
                int alloca_adjust;
                has_frame_reg = 1;
                reg30 = read_next_frame_reg(next_frame, 30);
            else if (!has_frame_reg) {
                int alloca_adjust;
                has_frame_reg = 1;
                reg30 = read_next_frame_reg(next_frame, 30);
-               alloca_adjust = reg30 - (sp + (unsigned short)word);
+               alloca_adjust = reg30 - (sp + (word & 0xffff));
                if (alloca_adjust > 0) {
                    /* FP > SP + frame_size. This may be because
                if (alloca_adjust > 0) {
                    /* FP > SP + frame_size. This may be because
-                   /* of an alloca or somethings similar.
+                    * of an alloca or somethings similar.
                     * Fix sp to "pre-alloca" value, and try again.
                     */
                    sp += alloca_adjust;
                     * Fix sp to "pre-alloca" value, and try again.
                     */
                    sp += alloca_adjust;
@@ -214,7 +245,7 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
        else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30) */
            int reg = (word & 0x001F0000) >> 16;
            reg_mask |= 1 << reg;
        else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30) */
            int reg = (word & 0x001F0000) >> 16;
            reg_mask |= 1 << reg;
-           temp_saved_regs.regs[reg] = reg30 + (short)word;
+           temp_saved_regs.regs[reg] = reg30 + (word & 0xffff);
        }
     }
     if (has_frame_reg) {
        }
     }
     if (has_frame_reg) {
@@ -237,8 +268,23 @@ find_proc_desc(pc, next_frame)
 {
   mips_extra_func_info_t proc_desc;
   struct block *b = block_for_pc(pc);
 {
   mips_extra_func_info_t proc_desc;
   struct block *b = block_for_pc(pc);
-  struct symbol *sym =
-      b ? lookup_symbol(MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL) : NULL;
+  struct symbol *sym;
+  CORE_ADDR startaddr;
+
+  find_pc_partial_function (pc, NULL, &startaddr, NULL);
+  if (b == NULL)
+    sym = NULL;
+  else
+    {
+      if (startaddr > BLOCK_START (b))
+       /* This is the "pathological" case referred to in a comment in
+          print_frame_info.  It might be better to move this check into
+          symbol reading.  */
+       sym = NULL;
+      else
+       sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE,
+                            0, NULL);
+    }
 
   if (sym)
     {
 
   if (sym)
     {
@@ -280,8 +326,12 @@ find_proc_desc(pc, next_frame)
          if (PROC_LOW_ADDR(&link->info) <= pc
              && PROC_HIGH_ADDR(&link->info) > pc)
              return &link->info;
          if (PROC_LOW_ADDR(&link->info) <= pc
              && PROC_HIGH_ADDR(&link->info) > pc)
              return &link->info;
+
+      if (startaddr == 0)
+       startaddr = heuristic_proc_start (pc);
+
       proc_desc =
       proc_desc =
-         heuristic_proc_desc(heuristic_proc_start(pc), pc, next_frame);
+       heuristic_proc_desc (startaddr, pc, next_frame);
     }
   return proc_desc;
 }
     }
   return proc_desc;
 }
@@ -303,8 +353,19 @@ mips_frame_chain(frame)
       return 0;
 
     cached_proc_desc = proc_desc;
       return 0;
 
     cached_proc_desc = proc_desc;
-    return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
-      + PROC_FRAME_OFFSET(proc_desc);
+
+    /* If no frame pointer and frame size is zero, we must be at end
+       of stack (or otherwise hosed).  If we don't check frame size,
+       we loop forever if we see a zero size frame.  */
+    if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+       && PROC_FRAME_OFFSET (proc_desc) == 0
+       /* The previous frame from a sigtramp frame might be frameless
+          and have frame size zero.  */
+       && !frame->signal_handler_caller)
+      return 0;
+    else
+      return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
+       + PROC_FRAME_OFFSET(proc_desc);
 }
 
 void
 }
 
 void
@@ -313,56 +374,128 @@ init_extra_frame_info(fci)
 {
   extern struct obstack frame_cache_obstack;
   /* Use proc_desc calculated in frame_chain */
 {
   extern struct obstack frame_cache_obstack;
   /* Use proc_desc calculated in frame_chain */
-  mips_extra_func_info_t proc_desc = fci->next ? cached_proc_desc :
-      find_proc_desc(fci->pc, fci->next);
+  mips_extra_func_info_t proc_desc =
+    fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
 
   fci->saved_regs = (struct frame_saved_regs*)
     obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
 
   fci->saved_regs = (struct frame_saved_regs*)
     obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
-  bzero(fci->saved_regs, sizeof(struct frame_saved_regs));
+  memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
   fci->proc_desc =
   fci->proc_desc =
-      proc_desc == &temp_proc_desc ? 0 : proc_desc;
+    proc_desc == &temp_proc_desc ? 0 : proc_desc;
   if (proc_desc)
     {
       int ireg;
       CORE_ADDR reg_position;
   if (proc_desc)
     {
       int ireg;
       CORE_ADDR reg_position;
-      unsigned long mask;
       /* r0 bit means kernel trap */
       int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
 
       /* Fixup frame-pointer - only needed for top frame */
       /* r0 bit means kernel trap */
       int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
 
       /* Fixup frame-pointer - only needed for top frame */
-      /* This may not be quite right, if proc has a real frame register */
-      if (fci->pc == PROC_LOW_ADDR(proc_desc))
-       fci->frame = read_register (SP_REGNUM);
+      /* This may not be quite right, if proc has a real frame register.
+        Get the value of the frame relative sp, procedure might have been
+        interrupted by a signal at it's very start.  */
+      if (fci->pc == PROC_LOW_ADDR(proc_desc) && !PROC_DESC_IS_DUMMY(proc_desc))
+       fci->frame = READ_FRAME_REG(fci, SP_REGNUM);
       else
        fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
                      + PROC_FRAME_OFFSET(proc_desc);
 
       if (proc_desc == &temp_proc_desc)
       else
        fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
                      + PROC_FRAME_OFFSET(proc_desc);
 
       if (proc_desc == &temp_proc_desc)
-         *fci->saved_regs = temp_saved_regs;
+       *fci->saved_regs = temp_saved_regs;
       else
       else
-      {
-         /* find which general-purpose registers were saved */
-         reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);
-         mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
-         for (ireg= 31; mask; --ireg, mask <<= 1)
-             if (mask & 0x80000000)
+       {
+         /* What registers have been saved?  Bitmasks.  */
+         unsigned long gen_mask, float_mask;
+
+         gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
+         float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
+
+         if (/* In any frame other than the innermost, we assume that all
+                registers have been saved.  This assumes that all register
+                saves in a function happen before the first function
+                call.  */
+             fci->next == NULL
+
+             /* In a dummy frame we know exactly where things are saved.  */
+             && !PROC_DESC_IS_DUMMY (proc_desc)
+
+             /* Not sure exactly what kernel_trap means, but if it means
+                the kernel saves the registers without a prologue doing it,
+                we better not examine the prologue to see whether registers
+                have been saved yet.  */
+             && !kernel_trap)
+           {
+             /* We need to figure out whether the registers that the proc_desc
+                claims are saved have been saved yet.  */
+
+             CORE_ADDR addr;
+             int status;
+             char buf[4];
+             unsigned long inst;
+
+             /* Bitmasks; set if we have found a save for the register.  */
+             unsigned long gen_save_found = 0;
+             unsigned long float_save_found = 0;
+
+             for (addr = PROC_LOW_ADDR (proc_desc);
+                  addr < fci->pc && (gen_mask != gen_save_found
+                                     || float_mask != float_save_found);
+                  addr += 4)
+               {
+                 status = read_memory_nobpt (addr, buf, 4);
+                 if (status)
+                   memory_error (status, addr);
+                 inst = extract_unsigned_integer (buf, 4);
+                 if (/* sw reg,n($sp) */
+                     (inst & 0xffe00000) == 0xafa00000
+
+                     /* sw reg,n($r30) */
+                     || (inst & 0xffe00000) == 0xafc00000)
+                   {
+                     /* It might be possible to use the instruction to
+                        find the offset, rather than the code below which
+                        is based on things being in a certain order in the
+                        frame, but figuring out what the instruction's offset
+                        is relative to might be a little tricky.  */
+                     int reg = (inst & 0x001f0000) >> 16;
+                     gen_save_found |= (1 << reg);
+                   }
+                 else if (/* swc1 freg,n($sp) */
+                          (inst & 0xffe00000) == 0xe7a00000
+
+                          /* swc1 freg,n($r30) */
+                          || (inst & 0xffe00000) == 0xe7c00000)
+                   {
+                     int reg = ((inst & 0x001f0000) >> 16);
+                     float_save_found |= (1 << reg);
+                   }
+               }
+             gen_mask = gen_save_found;
+             float_mask = float_save_found;
+           }
+
+         /* Fill in the offsets for the registers which gen_mask says
+            were saved.  */
+         reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
+         for (ireg= 31; gen_mask; --ireg, gen_mask <<= 1)
+           if (gen_mask & 0x80000000)
              {
              {
-                 fci->saved_regs->regs[ireg] = reg_position;
-                 reg_position -= 4;
+               fci->saved_regs->regs[ireg] = reg_position;
+               reg_position -= 4;
              }
              }
-         /* find which floating-point registers were saved */
-         reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);
-         /* The freg_offset points to where the first *double* register is saved.
-          * So skip to the high-order word. */
+         /* Fill in the offsets for the registers which float_mask says
+            were saved.  */
+         reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc);
+
+         /* The freg_offset points to where the first *double* register
+            is saved.  So skip to the high-order word. */
          reg_position += 4;
          reg_position += 4;
-         mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
-         for (ireg = 31; mask; --ireg, mask <<= 1)
-             if (mask & 0x80000000)
+         for (ireg = 31; float_mask; --ireg, float_mask <<= 1)
+           if (float_mask & 0x80000000)
              {
              {
-                 fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
-                 reg_position -= 4;
+               fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
+               reg_position -= 4;
              }
              }
-      }
+       }
 
       /* hack: if argument regs are saved, guess these contain args */
       if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
 
       /* hack: if argument regs are saved, guess these contain args */
       if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
@@ -410,7 +543,6 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
   int struct_return;
   CORE_ADDR struct_addr;
 {
   int struct_return;
   CORE_ADDR struct_addr;
 {
-  CORE_ADDR buf;
   register i;
   int accumulate_size = struct_return ? 4 : 0;
   struct mips_arg { char *contents; int len; int offset; };
   register i;
   int accumulate_size = struct_return ? 4 : 0;
   struct mips_arg { char *contents; int len; int offset; };
@@ -438,26 +570,29 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
   sp -= accumulate_size;
   for (i = nargs; m_arg--, --i >= 0; )
     write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
   sp -= accumulate_size;
   for (i = nargs; m_arg--, --i >= 0; )
     write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
-  if (struct_return) {
-    buf = struct_addr;
-    write_memory(sp, (char *)&buf, sizeof(CORE_ADDR));
-  }
+  if (struct_return)
+    {
+      char buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+
+      store_address (buf, sizeof buf, struct_addr);
+      write_memory (sp, buf, sizeof buf);
+    }
   return sp;
 }
 
 /* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
   return sp;
 }
 
 /* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
-#define MASK(i,j) ((1 << (j)+1)-1 ^ (1 << (i))-1)
+#define MASK(i,j) (((1 << ((j)+1))-1) ^ ((1 << (i))-1))
 
 void
 mips_push_dummy_frame()
 {
 
 void
 mips_push_dummy_frame()
 {
+  char buffer[MAX_REGISTER_RAW_SIZE];
   int ireg;
   struct linked_proc_info *link = (struct linked_proc_info*)
       xmalloc(sizeof(struct linked_proc_info));
   mips_extra_func_info_t proc_desc = &link->info;
   CORE_ADDR sp = read_register (SP_REGNUM);
   CORE_ADDR save_address;
   int ireg;
   struct linked_proc_info *link = (struct linked_proc_info*)
       xmalloc(sizeof(struct linked_proc_info));
   mips_extra_func_info_t proc_desc = &link->info;
   CORE_ADDR sp = read_register (SP_REGNUM);
   CORE_ADDR save_address;
-  REGISTER_TYPE buffer;
   link->next = linked_proc_desc_table;
   linked_proc_desc_table = link;
 #define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */
   link->next = linked_proc_desc_table;
   linked_proc_desc_table = link;
 #define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */
@@ -498,8 +633,9 @@ mips_push_dummy_frame()
   for (ireg = 32; --ireg >= 0; )
     if (PROC_REG_MASK(proc_desc) & (1 << ireg))
       {
   for (ireg = 32; --ireg >= 0; )
     if (PROC_REG_MASK(proc_desc) & (1 << ireg))
       {
-       buffer = read_register (ireg);
-       write_memory (save_address, (char *)&buffer, sizeof(REGISTER_TYPE));
+       store_unsigned_integer (buffer, REGISTER_RAW_SIZE (ireg),
+                               read_register (ireg));
+       write_memory (save_address, buffer, REGISTER_RAW_SIZE (ireg));
        save_address -= 4;
       }
   /* save floating-points registers starting with high order word */
        save_address -= 4;
       }
   /* save floating-points registers starting with high order word */
@@ -507,21 +643,27 @@ mips_push_dummy_frame()
   for (ireg = 32; --ireg >= 0; )
     if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
       {
   for (ireg = 32; --ireg >= 0; )
     if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
       {
-       buffer = read_register (ireg + FP0_REGNUM);
-       write_memory (save_address, (char *)&buffer, 4);
+       store_unsigned_integer (buffer, 4, read_register (ireg + FP0_REGNUM));
+       write_memory (save_address, buffer, 4);
        save_address -= 4;
       }
   write_register (PUSH_FP_REGNUM, sp);
   PROC_FRAME_REG(proc_desc) = PUSH_FP_REGNUM;
   PROC_FRAME_OFFSET(proc_desc) = 0;
        save_address -= 4;
       }
   write_register (PUSH_FP_REGNUM, sp);
   PROC_FRAME_REG(proc_desc) = PUSH_FP_REGNUM;
   PROC_FRAME_OFFSET(proc_desc) = 0;
-  buffer = read_register (PC_REGNUM);
-  write_memory (sp - 4, (char *)&buffer, sizeof(REGISTER_TYPE));
-  buffer = read_register (HI_REGNUM);
-  write_memory (sp - 8, (char *)&buffer, sizeof(REGISTER_TYPE));
-  buffer = read_register (LO_REGNUM);
-  write_memory (sp - 12, (char *)&buffer, sizeof(REGISTER_TYPE));
-  buffer = read_register (mips_fpu ? FCRCS_REGNUM : ZERO_REGNUM);
-  write_memory (sp - 16, (char *)&buffer, sizeof(REGISTER_TYPE));
+  store_unsigned_integer (buffer, REGISTER_RAW_SIZE (PC_REGNUM),
+                         read_register (PC_REGNUM));
+  write_memory (sp - 4, buffer, REGISTER_RAW_SIZE (PC_REGNUM));
+  store_unsigned_integer (buffer, REGISTER_RAW_SIZE (HI_REGNUM),
+                         read_register (HI_REGNUM));
+  write_memory (sp - 8, buffer, REGISTER_RAW_SIZE (HI_REGNUM));
+  store_unsigned_integer (buffer, REGISTER_RAW_SIZE (LO_REGNUM),
+                         read_register (LO_REGNUM));
+  write_memory (sp - 12, buffer, REGISTER_RAW_SIZE (LO_REGNUM));
+  store_unsigned_integer
+    (buffer,
+     REGISTER_RAW_SIZE (FCRCS_REGNUM),
+     mips_fpu ? read_register (FCRCS_REGNUM) : 0);
+  write_memory (sp - 16, buffer, REGISTER_RAW_SIZE (FCRCS_REGNUM));
   sp -= 4 * (GEN_REG_SAVE_COUNT
             + (mips_fpu ? FLOAT_REG_SAVE_COUNT : 0)
             + SPECIAL_REG_SAVE_COUNT);
   sp -= 4 * (GEN_REG_SAVE_COUNT
             + (mips_fpu ? FLOAT_REG_SAVE_COUNT : 0)
             + SPECIAL_REG_SAVE_COUNT);
@@ -559,7 +701,7 @@ mips_pop_frame()
   /* We let mips_init_extra_frame_info figure out the frame pointer */
   set_current_frame (create_new_frame (0, read_pc ()));
 
   /* We let mips_init_extra_frame_info figure out the frame pointer */
   set_current_frame (create_new_frame (0, read_pc ()));
 
-  if (PROC_DESC_IS_DUMMY(proc_desc))
+  if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
     {
       struct linked_proc_info *pi_ptr, *prev_ptr;
 
     {
       struct linked_proc_info *pi_ptr, *prev_ptr;
 
@@ -592,59 +734,64 @@ static void
 mips_print_register (regnum, all)
      int regnum, all;
 {
 mips_print_register (regnum, all)
      int regnum, all;
 {
-      unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
-      REGISTER_TYPE val;
+  unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
 
 
-      /* Get the data in raw format.  */
-      if (read_relative_register_raw_bytes (regnum, raw_buffer))
-       {
-         printf_filtered ("%s: [Invalid]", reg_names[regnum]);
-         return;
-       }
-      
-      /* If an even floating pointer register, also print as double. */
-      if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+32
-         && !((regnum-FP0_REGNUM) & 1)) {
-         char dbuffer[MAX_REGISTER_RAW_SIZE]; 
-
-         read_relative_register_raw_bytes (regnum, dbuffer);
-         read_relative_register_raw_bytes (regnum+1, dbuffer+4);
+  /* Get the data in raw format.  */
+  if (read_relative_register_raw_bytes (regnum, raw_buffer))
+    {
+      printf_filtered ("%s: [Invalid]", reg_names[regnum]);
+      return;
+    }
+
+  /* If an even floating pointer register, also print as double. */
+  if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+32
+      && !((regnum-FP0_REGNUM) & 1)) {
+    char dbuffer[MAX_REGISTER_RAW_SIZE]; 
+
+    read_relative_register_raw_bytes (regnum, dbuffer);
+    read_relative_register_raw_bytes (regnum+1, dbuffer+4);
 #ifdef REGISTER_CONVERT_TO_TYPE
 #ifdef REGISTER_CONVERT_TO_TYPE
-          REGISTER_CONVERT_TO_TYPE(regnum, builtin_type_double, dbuffer);
-#endif
-         printf_filtered ("(d%d: ", regnum-FP0_REGNUM);
-         val_print (builtin_type_double, dbuffer, 0,
-                    stdout, 0, 1, 0, Val_pretty_default);
-         printf_filtered ("); ");
-      }
-      fputs_filtered (reg_names[regnum], stdout);
-#ifndef NUMERIC_REG_NAMES
-      if (regnum < 32)
-         printf_filtered ("(r%d): ", regnum);
-      else
+    REGISTER_CONVERT_TO_TYPE(regnum, builtin_type_double, dbuffer);
 #endif
 #endif
-         printf_filtered (": ");
+    printf_filtered ("(d%d: ", regnum-FP0_REGNUM);
+    val_print (builtin_type_double, dbuffer, 0,
+              gdb_stdout, 0, 1, 0, Val_pretty_default);
+    printf_filtered ("); ");
+  }
+  fputs_filtered (reg_names[regnum], gdb_stdout);
+
+  /* The problem with printing numeric register names (r26, etc.) is that
+     the user can't use them on input.  Probably the best solution is to
+     fix it so that either the numeric or the funky (a2, etc.) names
+     are accepted on input.  */
+  if (regnum < 32)
+    printf_filtered ("(r%d): ", regnum);
+  else
+    printf_filtered (": ");
 
 
-      /* If virtual format is floating, print it that way.  */
-      if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
-         && ! INVALID_FLOAT (raw_buffer, REGISTER_VIRTUAL_SIZE(regnum))) {
-         val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0,
-                    stdout, 0, 1, 0, Val_pretty_default);
-      }
-      /* Else print as integer in hex.  */
+  /* If virtual format is floating, print it that way.  */
+  if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
+      && ! INVALID_FLOAT (raw_buffer, REGISTER_VIRTUAL_SIZE(regnum))) {
+    val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0,
+              gdb_stdout, 0, 1, 0, Val_pretty_default);
+  }
+  /* Else print as integer in hex.  */
+  else
+    {
+      long val;
+
+      val = extract_signed_integer (raw_buffer,
+                                   REGISTER_RAW_SIZE (regnum));
+
+      if (val == 0)
+       printf_filtered ("0");
+      else if (all)
+       /* FIXME: We should be printing this in a fixed field width, so that
+          registers line up.  */
+       printf_filtered (local_hex_format(), val);
       else
       else
-       {
-         long val;
-
-         bcopy (raw_buffer, &val, sizeof (long));
-         SWAP_TARGET_AND_HOST ((char *)&val, sizeof (long));
-         if (val == 0)
-           printf_filtered ("0");
-         else if (all)
-           printf_filtered (local_hex_format(), val);
-         else
-           printf_filtered ("%s=%d", local_hex_string(val), val);
-       }
+       printf_filtered ("%s=%ld", local_hex_string(val), val);
+    }
 }
 
 /* Replacement for generic do_registers_info.  */
 }
 
 /* Replacement for generic do_registers_info.  */
@@ -688,48 +835,39 @@ mips_frame_num_args(fip)
 #endif
        return -1;
 }
 #endif
        return -1;
 }
-
 \f
 \f
-/* Bad floats: Returns 0 if P points to a valid IEEE floating point number,
-   1 if P points to a denormalized number or a NaN. LEN says whether this is
-   a single-precision or double-precision float */
-#define SINGLE_EXP_BITS  8
-#define DOUBLE_EXP_BITS 11
-int
-isa_NAN(p, len)
-     int *p, len;
+#if 0
+/* Is this a branch with a delay slot?  */
+static int
+is_delayed (insn)
+     unsigned long insn;
 {
 {
-  int exponent;
-  if (len == 4)
-    {
-      exponent = *p;
-      exponent = exponent << 1 >> (32 - SINGLE_EXP_BITS - 1);
-      return ((exponent == -1) || (exponent == 0 && ((*p << 1) != 0)));
-    }
-  else if (len == 8)
-    {
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-      exponent = *p;
-#else
-      exponent = *(p+1);
-#endif
-      exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1);
-      return ((exponent == -1) || (! exponent && *p * *(p+1)));
-    }
-  else return 1;
+  int i;
+  for (i = 0; i < NUMOPCODES; ++i)
+    if (mips_opcodes[i].pinfo != INSN_MACRO
+       && (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
+      break;
+  return (i < NUMOPCODES
+         && (mips_opcodes[i].pinfo & (INSN_UNCOND_BRANCH_DELAY
+                                      | INSN_COND_BRANCH_DELAY
+                                      | INSN_COND_BRANCH_LIKELY)));
 }
 }
-\f
-/* To skip prologues, I use this predicate.  Returns either PC
-   itself if the code at PC does not look like a function prologue;
-   otherwise returns an address that (if we're lucky) follows
-   the prologue. */
+#endif
+
+/* To skip prologues, I use this predicate.  Returns either PC itself
+   if the code at PC does not look like a function prologue; otherwise
+   returns an address that (if we're lucky) follows the prologue.  If
+   LENIENT, then we must skip everything which is involved in setting
+   up the frame (it's OK to skip more, just so long as we don't skip
+   anything which might clobber the registers which are being saved.
+   We must skip more in the case where part of the prologue is in the
+   delay slot of a non-prologue instruction).  */
 
 CORE_ADDR
 
 CORE_ADDR
-mips_skip_prologue(pc)
+mips_skip_prologue (pc, lenient)
      CORE_ADDR pc;
      CORE_ADDR pc;
+     int lenient;
 {
 {
-    struct symbol *f;
-    struct block *b;
     unsigned long inst;
     int offset;
     int seen_sp_adjust = 0;
     unsigned long inst;
     int offset;
     int seen_sp_adjust = 0;
@@ -737,8 +875,21 @@ mips_skip_prologue(pc)
     /* Skip the typical prologue instructions. These are the stack adjustment
        instruction and the instructions that save registers on the stack
        or in the gcc frame.  */
     /* Skip the typical prologue instructions. These are the stack adjustment
        instruction and the instructions that save registers on the stack
        or in the gcc frame.  */
-    for (offset = 0; offset < 100; offset += 4) {
-       inst = read_memory_integer(pc + offset, 4);
+    for (offset = 0; offset < 100; offset += 4)
+      {
+       char buf[4];
+       int status;
+
+       status = read_memory_nobpt (pc + offset, buf, 4);
+       if (status)
+         memory_error (status, pc + offset);
+       inst = extract_unsigned_integer (buf, 4);
+
+#if 0
+       if (lenient && is_delayed (inst))
+         continue;
+#endif
+
        if ((inst & 0xffff0000) == 0x27bd0000)  /* addiu $sp,$sp,offset */
            seen_sp_adjust = 1;
        else if ((inst & 0xFFE00000) == 0xAFA00000 && (inst & 0x001F0000))
        if ((inst & 0xffff0000) == 0x27bd0000)  /* addiu $sp,$sp,offset */
            seen_sp_adjust = 1;
        else if ((inst & 0xFFE00000) == 0xAFA00000 && (inst & 0x001F0000))
@@ -753,6 +904,13 @@ mips_skip_prologue(pc)
            continue;
        else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */
            continue;
            continue;
        else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */
            continue;
+       else if ((inst & 0xffff0000) == 0x3c1c0000) /* lui $gp,n */
+           continue;
+       else if ((inst & 0xffff0000) == 0x279c0000) /* addiu $gp,$gp,n */
+           continue;
+       else if (inst == 0x0399e021             /* addu $gp,$gp,$t9 */
+                || inst == 0x033ce021)         /* addu $gp,$t9,$gp */
+         continue;
        else
            break;
     }
        else
            break;
     }
@@ -788,6 +946,24 @@ mips_skip_prologue(pc)
 #endif
 }
 
 #endif
 }
 
+#if 0
+/* The lenient prologue stuff should be superceded by the code in
+   init_extra_frame_info which looks to see whether the stores mentioned
+   in the proc_desc have actually taken place.  */
+
+/* Is address PC in the prologue (loosely defined) for function at
+   STARTADDR?  */
+
+static int
+mips_in_lenient_prologue (startaddr, pc)
+     CORE_ADDR startaddr;
+     CORE_ADDR pc;
+{
+  CORE_ADDR end_prologue = mips_skip_prologue (startaddr, 1);
+  return pc >= startaddr && pc < end_prologue;
+}
+#endif
+
 /* Given a return value in `regbuf' with a type `valtype', 
    extract and copy its value into `valbuf'.  */
 void
 /* Given a return value in `regbuf' with a type `valtype', 
    extract and copy its value into `valbuf'.  */
 void
@@ -826,12 +1002,44 @@ mips_store_return_value (valtype, valbuf)
   write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype));
 }
 
   write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype));
 }
 
-/* Let the user turn off floating point and set the fence post for
-   heuristic_proc_start.  */
+/* These exist in mdebugread.c.  */
+extern CORE_ADDR sigtramp_address, sigtramp_end;
+extern void fixup_sigtramp PARAMS ((void));
+
+/* Exported procedure: Is PC in the signal trampoline code */
+
+int
+in_sigtramp (pc, ignore)
+     CORE_ADDR pc;
+     char *ignore;             /* function name */
+{
+  if (sigtramp_address == 0)
+    fixup_sigtramp ();
+  return (pc >= sigtramp_address && pc < sigtramp_end);
+}
+
+static void reinit_frame_cache_sfunc PARAMS ((char *, int,
+                                             struct cmd_list_element *));
+
+/* Just like reinit_frame_cache, but with the right arguments to be
+   callable as an sfunc.  */
+static void
+reinit_frame_cache_sfunc (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  reinit_frame_cache ();
+}
 
 void
 _initialize_mips_tdep ()
 {
 
 void
 _initialize_mips_tdep ()
 {
+  struct cmd_list_element *c;
+
+  /* Let the user turn off floating point and set the fence post for
+     heuristic_proc_start.  */
+
   add_show_from_set
     (add_set_cmd ("mipsfpu", class_support, var_boolean,
                  (char *) &mips_fpu,
   add_show_from_set
     (add_set_cmd ("mipsfpu", class_support, var_boolean,
                  (char *) &mips_fpu,
@@ -840,11 +1048,19 @@ Turn off to avoid using floating point instructions when calling functions\n\
 or dealing with return values.", &setlist),
      &showlist);
 
 or dealing with return values.", &setlist),
      &showlist);
 
-  add_show_from_set
-    (add_set_cmd ("heuristic-fence-post", class_support, var_uinteger,
-                 (char *) &heuristic_fence_post,
-                 "Set the distance searched for the start of a function.\n\
-Set number of bytes to be searched backward to find the beginning of a\n\
-function without symbols.", &setlist),
-     &showlist);
+  /* We really would like to have both "0" and "unlimited" work, but
+     command.c doesn't deal with that.  So make it a var_zinteger
+     because the user can always use "999999" or some such for unlimited.  */
+  c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
+                  (char *) &heuristic_fence_post,
+                  "\
+Set the distance searched for the start of a function.\n\
+If you are debugging a stripped executable, GDB needs to search through the\n\
+program for the start of a function.  This command sets the distance of the\n\
+search.  The only need to set it is when debugging a stripped executable.",
+                  &setlist);
+  /* We need to throw away the frame cache when we set this, since it
+     might change our ability to get backtraces.  */
+  c->function.sfunc = reinit_frame_cache_sfunc;
+  add_show_from_set (c, &showlist);
 }
 }
This page took 0.049878 seconds and 4 git commands to generate.