* alpha-tdep.c (alpha_register_name): New function.
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index 434b26fce0d8cdb064a9bdb588802f0f82053197..74a61afa19f5e22ac2f9facdba5a6c91ab0c3b98 100644 (file)
@@ -727,6 +727,7 @@ static void
 arm_scan_prologue (struct frame_info *fi)
 {
   int regno, sp_offset, fp_offset;
+  LONGEST return_value;
   CORE_ADDR prologue_start, prologue_end, current_pc;
 
   /* Check if this function is already in the cache of frame information. */
@@ -791,9 +792,13 @@ arm_scan_prologue (struct frame_info *fi)
     {
       /* Get address of the stmfd in the prologue of the callee; the saved
          PC is the address of the stmfd + 8.  */
-      prologue_start = ADDR_BITS_REMOVE (read_memory_integer (fi->frame, 4))
-       - 8;
-      prologue_end = prologue_start + 64;      /* See above. */
+      if (!safe_read_memory_integer (fi->frame, 4,  &return_value))
+        return;
+      else
+        {
+          prologue_start = ADDR_BITS_REMOVE (return_value) - 8;
+          prologue_end = prologue_start + 64;   /* See above. */
+        }
     }
 
   /* Now search the prologue looking for instructions that set up the
@@ -807,98 +812,104 @@ arm_scan_prologue (struct frame_info *fi)
      traceback.
 
      In the APCS, the prologue should start with  "mov ip, sp" so
-     if we don't see this as the first insn, we will stop.  */
+     if we don't see this as the first insn, we will stop.  [Note:
+     This doesn't seem to be true any longer, so it's now an optional
+     part of the prologue.  - Kevin Buettner, 2001-11-20]  */
 
   sp_offset = fp_offset = 0;
 
   if (read_memory_unsigned_integer (prologue_start, 4)
       == 0xe1a0c00d)           /* mov ip, sp */
+    current_pc = prologue_start + 4;
+  else
+    current_pc = prologue_start;
+
+  for (; current_pc < prologue_end; current_pc += 4)
     {
-      for (current_pc = prologue_start + 4; current_pc < prologue_end;
-          current_pc += 4)
+      unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+
+      if ((insn & 0xffff0000) == 0xe92d0000)
+       /* stmfd sp!, {..., fp, ip, lr, pc}
+          or
+          stmfd sp!, {a1, a2, a3, a4}  */
        {
-         unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+         int mask = insn & 0xffff;
 
-         if ((insn & 0xffff0000) == 0xe92d0000)
-           /* stmfd sp!, {..., fp, ip, lr, pc}
-              or
-              stmfd sp!, {a1, a2, a3, a4}  */
-           {
-             int mask = insn & 0xffff;
+         /* Calculate offsets of saved registers. */
+         for (regno = PC_REGNUM; regno >= 0; regno--)
+           if (mask & (1 << regno))
+             {
+               sp_offset -= 4;
+               fi->fsr.regs[regno] = sp_offset;
+             }
+       }
+      else if ((insn & 0xfffff000) == 0xe24cb000)      /* sub fp, ip #n */
+       {
+         unsigned imm = insn & 0xff;   /* immediate value */
+         unsigned rot = (insn & 0xf00) >> 7;   /* rotate amount */
+         imm = (imm >> rot) | (imm << (32 - rot));
+         fp_offset = -imm;
+         fi->framereg = FP_REGNUM;
+       }
+      else if ((insn & 0xfffff000) == 0xe24dd000)      /* sub sp, sp #n */
+       {
+         unsigned imm = insn & 0xff;   /* immediate value */
+         unsigned rot = (insn & 0xf00) >> 7;   /* rotate amount */
+         imm = (imm >> rot) | (imm << (32 - rot));
+         sp_offset -= imm;
+       }
+      else if ((insn & 0xffff7fff) == 0xed6d0103)      /* stfe f?, [sp, -#c]! */
+       {
+         sp_offset -= 12;
+         regno = F0_REGNUM + ((insn >> 12) & 0x07);
+         fi->fsr.regs[regno] = sp_offset;
+       }
+      else if ((insn & 0xffbf0fff) == 0xec2d0200)      /* sfmfd f0, 4, [sp!] */
+       {
+         int n_saved_fp_regs;
+         unsigned int fp_start_reg, fp_bound_reg;
 
-             /* Calculate offsets of saved registers. */
-             for (regno = PC_REGNUM; regno >= 0; regno--)
-               if (mask & (1 << regno))
-                 {
-                   sp_offset -= 4;
-                   fi->fsr.regs[regno] = sp_offset;
-                 }
-           }
-         else if ((insn & 0xfffff000) == 0xe24cb000)   /* sub fp, ip #n */
+         if ((insn & 0x800) == 0x800)  /* N0 is set */
            {
-             unsigned imm = insn & 0xff;       /* immediate value */
-             unsigned rot = (insn & 0xf00) >> 7;       /* rotate amount */
-             imm = (imm >> rot) | (imm << (32 - rot));
-             fp_offset = -imm;
-             fi->framereg = FP_REGNUM;
+             if ((insn & 0x40000) == 0x40000)  /* N1 is set */
+               n_saved_fp_regs = 3;
+             else
+               n_saved_fp_regs = 1;
            }
-         else if ((insn & 0xfffff000) == 0xe24dd000)   /* sub sp, sp #n */
+         else
            {
-             unsigned imm = insn & 0xff;       /* immediate value */
-             unsigned rot = (insn & 0xf00) >> 7;       /* rotate amount */
-             imm = (imm >> rot) | (imm << (32 - rot));
-             sp_offset -= imm;
+             if ((insn & 0x40000) == 0x40000)  /* N1 is set */
+               n_saved_fp_regs = 2;
+             else
+               n_saved_fp_regs = 4;
            }
-         else if ((insn & 0xffff7fff) == 0xed6d0103)   /* stfe f?, [sp, -#c]! */
+
+         fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
+         fp_bound_reg = fp_start_reg + n_saved_fp_regs;
+         for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
            {
              sp_offset -= 12;
-             regno = F0_REGNUM + ((insn >> 12) & 0x07);
-             fi->fsr.regs[regno] = sp_offset;
-           }
-         else if ((insn & 0xffbf0fff) == 0xec2d0200)   /* sfmfd f0, 4, [sp!] */
-           {
-             int n_saved_fp_regs;
-             unsigned int fp_start_reg, fp_bound_reg;
-
-             if ((insn & 0x800) == 0x800)      /* N0 is set */
-               {
-                 if ((insn & 0x40000) == 0x40000)      /* N1 is set */
-                   n_saved_fp_regs = 3;
-                 else
-                   n_saved_fp_regs = 1;
-               }
-             else
-               {
-                 if ((insn & 0x40000) == 0x40000)      /* N1 is set */
-                   n_saved_fp_regs = 2;
-                 else
-                   n_saved_fp_regs = 4;
-               }
-
-             fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
-             fp_bound_reg = fp_start_reg + n_saved_fp_regs;
-             for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
-               {
-                 sp_offset -= 12;
-                 fi->fsr.regs[fp_start_reg++] = sp_offset;
-               }
+             fi->fsr.regs[fp_start_reg++] = sp_offset;
            }
-         else if ((insn & 0xf0000000) != 0xe0000000)
-           break;      /* Condition not true, exit early */
-         else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
-           break;      /* Don't scan past a block load */
-         else
-           /* The optimizer might shove anything into the prologue,
-              so we just skip what we don't recognize. */
-           continue;
        }
+      else if ((insn & 0xf0000000) != 0xe0000000)
+       break;  /* Condition not true, exit early */
+      else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
+       break;  /* Don't scan past a block load */
+      else
+       /* The optimizer might shove anything into the prologue,
+          so we just skip what we don't recognize. */
+       continue;
     }
 
   /* The frame size is just the negative of the offset (from the original SP)
      of the last thing thing we pushed on the stack.  The frame offset is
      [new FP] - [new SP].  */
   fi->framesize = -sp_offset;
-  fi->frameoffset = fp_offset - sp_offset;
+  if (fi->framereg == FP_REGNUM)
+    fi->frameoffset = fp_offset - sp_offset;
+  else
+    fi->frameoffset = 0;
 
   save_prologue_cache (fi);
 }
@@ -1009,6 +1020,7 @@ void
 arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
 {
   int reg;
+  CORE_ADDR sp;
 
   if (fi->next)
     fi->pc = FRAME_SAVED_PC (fi->next);
@@ -1028,6 +1040,13 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
   else
 #endif
 
+  /* Compute stack pointer for this frame.  We use this value for both the
+     sigtramp and call dummy cases.  */
+  if (!fi->next)
+    sp = read_sp();
+  else
+    sp = fi->next->frame - fi->next->frameoffset + fi->next->framesize;
+
   /* Determine whether or not we're in a sigtramp frame. 
      Unfortunately, it isn't sufficient to test
      fi->signal_handler_caller because this value is sometimes set
@@ -1038,28 +1057,45 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
      Note: If an ARM IN_SIGTRAMP method ever needs to compare against
      the name of the function, the code below will have to be changed
      to first fetch the name of the function and then pass this name
-     to IN_SIGTRAMP. */
+     to IN_SIGTRAMP.  */
 
   if (SIGCONTEXT_REGISTER_ADDRESS_P () 
-      && (fi->signal_handler_caller || IN_SIGTRAMP (fi->pc, 0)))
+      && (fi->signal_handler_caller || IN_SIGTRAMP (fi->pc, (char *)0)))
     {
-      CORE_ADDR sp;
-
-      if (!fi->next)
-       sp = read_sp();
-      else
-       sp = fi->next->frame - fi->next->frameoffset + fi->next->framesize;
-
       for (reg = 0; reg < NUM_REGS; reg++)
        fi->fsr.regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, fi->pc, reg);
 
       /* FIXME: What about thumb mode? */
       fi->framereg = SP_REGNUM;
-      fi->frame = read_memory_integer (fi->fsr.regs[fi->framereg], 4);
+      fi->frame = read_memory_integer (fi->fsr.regs[fi->framereg],
+                                       REGISTER_RAW_SIZE (fi->framereg));
       fi->framesize = 0;
       fi->frameoffset = 0;
 
     }
+  else if (PC_IN_CALL_DUMMY (fi->pc, sp, fi->frame))
+    {
+      CORE_ADDR rp;
+      CORE_ADDR callers_sp;
+
+      /* Set rp point at the high end of the saved registers.  */
+      rp = fi->frame - REGISTER_SIZE;
+
+      /* Fill in addresses of saved registers.  */
+      fi->fsr.regs[PS_REGNUM] = rp;
+      rp -= REGISTER_RAW_SIZE (PS_REGNUM);
+      for (reg = PC_REGNUM; reg >= 0; reg--)
+       {
+         fi->fsr.regs[reg] = rp;
+         rp -= REGISTER_RAW_SIZE (reg);
+       }
+
+      callers_sp = read_memory_integer (fi->fsr.regs[SP_REGNUM],
+                                        REGISTER_RAW_SIZE (SP_REGNUM));
+      fi->framereg = FP_REGNUM;
+      fi->framesize = callers_sp - sp;
+      fi->frameoffset = fi->frame - sp;
+    }
   else
     {
       arm_scan_prologue (fi);
@@ -1105,6 +1141,11 @@ arm_frame_saved_pc (struct frame_info *fi)
     return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
   else
 #endif
+  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->frameoffset, fi->frame))
+    {
+      return read_memory_integer (fi->fsr.regs[PC_REGNUM], REGISTER_RAW_SIZE (PC_REGNUM));
+    }
+  else
     {
       CORE_ADDR pc = arm_find_callers_reg (fi, LR_REGNUM);
       return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
@@ -1151,13 +1192,15 @@ arm_push_dummy_frame (void)
      instruction stores the PC, it stores the address of the stm
      instruction itself plus 12.  */
   fp = sp = push_word (sp, prologue_start + 12);
-  sp = push_word (sp, read_register (PC_REGNUM));      /* FIXME: was PS_REGNUM */
-  sp = push_word (sp, old_sp);
-  sp = push_word (sp, read_register (FP_REGNUM));
 
-  for (regnum = 10; regnum >= 0; regnum--)
+  /* Push the processor status.  */
+  sp = push_word (sp, read_register (PS_REGNUM));
+
+  /* Push all 16 registers starting with r15.  */
+  for (regnum = PC_REGNUM; regnum >= 0; regnum--)
     sp = push_word (sp, read_register (regnum));
 
+  /* Update fp (for both Thumb and ARM) and sp.  */
   write_register (FP_REGNUM, fp);
   write_register (THUMB_FP_REGNUM, fp);
   write_register (SP_REGNUM, sp);
@@ -1372,45 +1415,25 @@ arm_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
   return sp;
 }
 
+/* Pop the current frame.  So long as the frame info has been initialized
+   properly (see arm_init_extra_frame_info), this code works for dummy frames
+   as well as regular frames.  I.e, there's no need to have a special case
+   for dummy frames.  */
 void
 arm_pop_frame (void)
 {
   int regnum;
   struct frame_info *frame = get_current_frame ();
+  CORE_ADDR old_SP = frame->frame - frame->frameoffset + frame->framesize;
 
-  if (!PC_IN_CALL_DUMMY(frame->pc, frame->frame, read_fp()))
-    {
-      CORE_ADDR old_SP;
-
-      old_SP = read_register (frame->framereg);
-      for (regnum = 0; regnum < NUM_REGS; regnum++)
-        if (frame->fsr.regs[regnum] != 0)
-          write_register (regnum,
-                     read_memory_integer (frame->fsr.regs[regnum], 4));
+  for (regnum = 0; regnum < NUM_REGS; regnum++)
+    if (frame->fsr.regs[regnum] != 0)
+      write_register (regnum,
+                 read_memory_integer (frame->fsr.regs[regnum],
+                                      REGISTER_RAW_SIZE (regnum)));
 
-      write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
-      write_register (SP_REGNUM, old_SP);
-    }
-  else
-    {
-      CORE_ADDR sp;
-
-      sp = read_register (FP_REGNUM);
-      sp -= sizeof(CORE_ADDR); /* we don't care about this first word */
-
-      write_register (PC_REGNUM, read_memory_integer (sp, 4));
-      sp -= sizeof(CORE_ADDR);
-      write_register (SP_REGNUM, read_memory_integer (sp, 4));
-      sp -= sizeof(CORE_ADDR);
-      write_register (FP_REGNUM, read_memory_integer (sp, 4));
-      sp -= sizeof(CORE_ADDR);
-
-      for (regnum = 10; regnum >= 0; regnum--)
-        {
-          write_register (regnum, read_memory_integer (sp, 4));
-          sp -= sizeof(CORE_ADDR);
-        }
-    }
+  write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+  write_register (SP_REGNUM, old_SP);
 
   flush_cached_frames ();
 }
@@ -1452,7 +1475,7 @@ arm_register_type (int regnum)
 {
   if (regnum >= F0_REGNUM && regnum < F0_REGNUM + NUM_FREGS)
     {
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
        return builtin_type_arm_ext_big;
       else
        return builtin_type_arm_ext_littlebyte_bigword;
@@ -1470,7 +1493,7 @@ static void
 convert_from_extended (void *ptr, void *dbl)
 {
   DOUBLEST d;
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     floatformat_to_doublest (&floatformat_arm_ext_big, ptr, &d);
   else
     floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
@@ -1483,7 +1506,7 @@ convert_to_extended (void *dbl, void *ptr)
 {
   DOUBLEST d;
   floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
   else
     floatformat_from_doublest (&floatformat_arm_ext_littlebyte_bigword,
@@ -1928,7 +1951,7 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
   else
     info->symbols = NULL;
 
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     return print_insn_big_arm (memaddr, info);
   else
     return print_insn_little_arm (memaddr, info);
@@ -1947,7 +1970,7 @@ arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
   if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
     {
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
        {
          static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
          *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
@@ -1964,7 +1987,7 @@ arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
     }
   else
     {
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
        {
          static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
          *lenptr = sizeof (arm_breakpoint);
This page took 0.027887 seconds and 4 git commands to generate.