* arm-tdep.c (arm_frame_chain_valid): Remove unnecessary test.
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index 386ab9163bf39027e076cb1eb2731c3e87adfa26..e988db41fc54e73a86d42350958bc0b11f3d2244 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
    Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
-   2001, 2002 Free Software Foundation, Inc.
+   2001, 2002, 2003 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -34,6 +34,7 @@
 #include "value.h"
 #include "arch-utils.h"
 #include "solib-svr4.h"
+#include "osabi.h"
 
 #include "arm-tdep.h"
 #include "gdb/sim-arm.h"
@@ -131,7 +132,10 @@ static void set_disassembly_flavor_sfunc(char *, int,
                                         struct cmd_list_element *);
 static void set_disassembly_flavor (void);
 
-static void convert_from_extended (void *ptr, void *dbl);
+static void convert_from_extended (const struct floatformat *, const void *,
+                                  void *);
+static void convert_to_extended (const struct floatformat *, void *,
+                                const void *);
 
 /* Define other aspects of the stack frame.  We keep the offsets of
    all saved registers, 'cause we need 'em a lot!  We also keep the
@@ -155,7 +159,7 @@ struct frame_extra_info
 static int
 arm_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
 {
-  return (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC));
+  return (FRAME_SAVED_PC (thisframe) >= LOWEST_PC);
 }
 
 /* Set to true if the 32-bit mode is in use.  */
@@ -272,7 +276,7 @@ arm_frameless_function_invocation (struct frame_info *fi)
        stmdb sp!, {}
        sub sp, ip, #4.  */
 
-  func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
+  func_start = (get_pc_function_start (get_frame_pc (fi)) + FUNCTION_START_OFFSET);
   after_prologue = SKIP_PROLOGUE (func_start);
 
   /* There are some frameless functions whose first two instructions
@@ -536,15 +540,15 @@ thumb_scan_prologue (struct frame_info *fi)
 
   /* Don't try to scan dummy frames.  */
   if (fi != NULL
-      && DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
+      && DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
     return;
 
-  if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+  if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
     {
       struct symtab_and_line sal = find_pc_line (prologue_start, 0);
 
       if (sal.line == 0)               /* no line info, use current PC  */
-       prologue_end = fi->pc;
+       prologue_end = get_frame_pc (fi);
       else if (sal.end < prologue_end) /* next line begins after fn end */
        prologue_end = sal.end;         /* (probably means no prologue)  */
     }
@@ -553,7 +557,7 @@ thumb_scan_prologue (struct frame_info *fi)
        16 pushes, an add, and "mv fp,sp".  */
     prologue_end = prologue_start + 40;
 
-  prologue_end = min (prologue_end, fi->pc);
+  prologue_end = min (prologue_end, get_frame_pc (fi));
 
   /* Initialize the saved register map.  When register H is copied to
      register L, we will put H in saved_reg[L].  */
@@ -588,7 +592,7 @@ thumb_scan_prologue (struct frame_info *fi)
            if (mask & (1 << regno))
              {
                fi->extra_info->framesize += 4;
-               fi->saved_regs[saved_reg[regno]] =
+               get_frame_saved_regs (fi)[saved_reg[regno]] =
                  -(fi->extra_info->framesize);
                /* Reset saved register map.  */
                saved_reg[regno] = regno;
@@ -661,13 +665,13 @@ check_prologue_cache (struct frame_info *fi)
 {
   int i;
 
-  if (fi->pc == prologue_cache.pc)
+  if (get_frame_pc (fi) == get_frame_pc (&prologue_cache))
     {
       fi->extra_info->framereg = prologue_cache.extra_info->framereg;
       fi->extra_info->framesize = prologue_cache.extra_info->framesize;
       fi->extra_info->frameoffset = prologue_cache.extra_info->frameoffset;
       for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
-       fi->saved_regs[i] = prologue_cache.saved_regs[i];
+       get_frame_saved_regs (fi)[i] = get_frame_saved_regs (&prologue_cache)[i];
       return 1;
     }
   else
@@ -682,13 +686,13 @@ save_prologue_cache (struct frame_info *fi)
 {
   int i;
 
-  prologue_cache.pc = fi->pc;
+  deprecated_update_frame_pc_hack (&prologue_cache, get_frame_pc (fi));
   prologue_cache.extra_info->framereg = fi->extra_info->framereg;
   prologue_cache.extra_info->framesize = fi->extra_info->framesize;
   prologue_cache.extra_info->frameoffset = fi->extra_info->frameoffset;
 
   for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
-    prologue_cache.saved_regs[i] = fi->saved_regs[i];
+    get_frame_saved_regs (&prologue_cache)[i] = get_frame_saved_regs (fi)[i];
 }
 
 
@@ -776,7 +780,7 @@ arm_scan_prologue (struct frame_info *fi)
   fi->extra_info->frameoffset = 0;
 
   /* Check for Thumb prologue.  */
-  if (arm_pc_is_thumb (fi->pc))
+  if (arm_pc_is_thumb (get_frame_pc (fi)))
     {
       thumb_scan_prologue (fi);
       save_prologue_cache (fi);
@@ -785,7 +789,7 @@ arm_scan_prologue (struct frame_info *fi)
 
   /* Find the function prologue.  If we can't find the function in
      the symbol table, peek in the stack frame to find the PC.  */
-  if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+  if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
     {
       /* One way to find the end of the prologue (which works well
          for unoptimized code) is to do the following:
@@ -793,7 +797,7 @@ arm_scan_prologue (struct frame_info *fi)
            struct symtab_and_line sal = find_pc_line (prologue_start, 0);
 
            if (sal.line == 0)
-             prologue_end = fi->pc;
+             prologue_end = get_frame_pc (fi);
            else if (sal.end < prologue_end)
              prologue_end = sal.end;
 
@@ -887,7 +891,7 @@ arm_scan_prologue (struct frame_info *fi)
            if (mask & (1 << regno))
              {
                sp_offset -= 4;
-               fi->saved_regs[regno] = sp_offset;
+               get_frame_saved_regs (fi)[regno] = sp_offset;
              }
        }
       else if ((insn & 0xffffc000) == 0xe54b0000 ||    /* strb rx,[r11,#-n] */
@@ -923,7 +927,7 @@ arm_scan_prologue (struct frame_info *fi)
        {
          sp_offset -= 12;
          regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-         fi->saved_regs[regno] = sp_offset;
+         get_frame_saved_regs (fi)[regno] = sp_offset;
        }
       else if ((insn & 0xffbf0fff) == 0xec2d0200)      /* sfmfd f0, 4, [sp!] */
        {
@@ -950,7 +954,7 @@ arm_scan_prologue (struct frame_info *fi)
          for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
            {
              sp_offset -= 12;
-             fi->saved_regs[fp_start_reg++] = sp_offset;
+             get_frame_saved_regs (fi)[fp_start_reg++] = sp_offset;
            }
        }
       else if ((insn & 0xf0000000) != 0xe0000000)
@@ -990,18 +994,18 @@ arm_find_callers_reg (struct frame_info *fi, int regnum)
      function could be called directly.  */
   for (; fi; fi = fi->next)
     {
-      if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
+      if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
        {
-         return deprecated_read_register_dummy (fi->pc, fi->frame, regnum);
+         return deprecated_read_register_dummy (get_frame_pc (fi), fi->frame, regnum);
        }
-      else if (fi->saved_regs[regnum] != 0)
+      else if (get_frame_saved_regs (fi)[regnum] != 0)
        {
          /* NOTE: cagney/2002-05-03: This would normally need to
              handle ARM_SP_REGNUM as a special case as, according to
              the frame.h comments, saved_regs[SP_REGNUM] contains the
              SP value not its address.  It appears that the ARM isn't
              doing this though.  */
-         return read_memory_integer (fi->saved_regs[regnum],
+         return read_memory_integer (get_frame_saved_regs (fi)[regnum],
                                      REGISTER_RAW_SIZE (regnum));
        }
     }
@@ -1009,9 +1013,9 @@ arm_find_callers_reg (struct frame_info *fi, int regnum)
 }
 /* Function: frame_chain Given a GDB frame, determine the address of
    the calling function's frame.  This will be used to create a new
-   GDB frame struct, and then INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC
-   will be called for the new frame.  For ARM, we save the frame size
-   when we initialize the frame_info.  */
+   GDB frame struct, and then INIT_EXTRA_FRAME_INFO and
+   DEPRECATED_INIT_FRAME_PC will be called for the new frame.  For
+   ARM, we save the frame size when we initialize the frame_info.  */
 
 static CORE_ADDR
 arm_frame_chain (struct frame_info *fi)
@@ -1019,11 +1023,11 @@ arm_frame_chain (struct frame_info *fi)
   CORE_ADDR caller_pc;
   int framereg = fi->extra_info->framereg;
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
     /* A generic call dummy's frame is the same as caller's.  */
     return fi->frame;
 
-  if (fi->pc < LOWEST_PC)
+  if (get_frame_pc (fi) < LOWEST_PC)
     return 0;
 
   /* If the caller is the startup code, we're at the end of the chain.  */
@@ -1035,7 +1039,7 @@ arm_frame_chain (struct frame_info *fi)
      frame register number.  */
   /* XXX Fixme, we should try to do this without creating a temporary
      caller_fi.  */
-  if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (fi->pc))
+  if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (fi)))
     {
       struct frame_info caller_fi;
       struct cleanup *old_chain;
@@ -1051,7 +1055,7 @@ arm_frame_chain (struct frame_info *fi)
       make_cleanup (xfree, caller_fi.saved_regs);
 
       /* Now, scan the prologue and obtain the frame register.  */
-      caller_fi.pc = caller_pc;
+      deprecated_update_frame_pc_hack (&caller_fi, caller_pc);
       arm_scan_prologue (&caller_fi);
       framereg = caller_fi.extra_info->framereg;
 
@@ -1083,7 +1087,7 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
   int reg;
   CORE_ADDR sp;
 
-  if (fi->saved_regs == NULL)
+  if (get_frame_saved_regs (fi) == NULL)
     frame_saved_regs_zalloc (fi);
 
   fi->extra_info = (struct frame_extra_info *)
@@ -1094,18 +1098,18 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
   fi->extra_info->framereg = 0;
 
   if (fi->next)
-    fi->pc = FRAME_SAVED_PC (fi->next);
+    deprecated_update_frame_pc_hack (fi, FRAME_SAVED_PC (fi->next));
 
-  memset (fi->saved_regs, '\000', sizeof fi->saved_regs);
+  memset (get_frame_saved_regs (fi), '\000', sizeof get_frame_saved_regs (fi));
 
   /* 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 if (DEPRECATED_PC_IN_CALL_DUMMY (fi->next->pc, 0, 0))
+  else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi->next), 0, 0))
     /* For generic dummy frames, pull the value direct from the frame.
        Having an unwind function to do this would be nice.  */
-    sp = deprecated_read_register_dummy (fi->next->pc, fi->next->frame,
+    sp = deprecated_read_register_dummy (get_frame_pc (fi->next), fi->next->frame,
                                         ARM_SP_REGNUM);
   else
     sp = (fi->next->frame - fi->next->extra_info->frameoffset
@@ -1129,15 +1133,15 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
      before calling functions like this.  */
 
   if (SIGCONTEXT_REGISTER_ADDRESS_P () 
-      && ((get_frame_type (fi) == SIGTRAMP_FRAME) || PC_IN_SIGTRAMP (fi->pc, (char *)0)))
+      && ((get_frame_type (fi) == SIGTRAMP_FRAME) || PC_IN_SIGTRAMP (get_frame_pc (fi), (char *)0)))
     {
       for (reg = 0; reg < NUM_REGS; reg++)
-       fi->saved_regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, fi->pc, reg);
+       get_frame_saved_regs (fi)[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, get_frame_pc (fi), reg);
 
       /* FIXME: What about thumb mode?  */
       fi->extra_info->framereg = ARM_SP_REGNUM;
       fi->frame =
-       read_memory_integer (fi->saved_regs[fi->extra_info->framereg],
+       read_memory_integer (get_frame_saved_regs (fi)[fi->extra_info->framereg],
                             REGISTER_RAW_SIZE (fi->extra_info->framereg));
       fi->extra_info->framesize = 0;
       fi->extra_info->frameoffset = 0;
@@ -1150,7 +1154,7 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
       if (!fi->next)
        /* This is the innermost frame?  */
        fi->frame = read_register (fi->extra_info->framereg);
-      else if (DEPRECATED_PC_IN_CALL_DUMMY (fi->next->pc, 0, 0))
+      else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi->next), 0, 0))
        /* Next inner most frame is a dummy, just grab its frame.
            Dummy frames always have the same FP as their caller.  */
        fi->frame = fi->next->frame;
@@ -1159,10 +1163,9 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
        {
          /* not the innermost frame */
          /* If we have an FP, the callee saved it.  */
-         if (fi->next->saved_regs[fi->extra_info->framereg] != 0)
+         if (get_frame_saved_regs (get_next_frame (fi))[fi->extra_info->framereg] != 0)
            fi->frame =
-             read_memory_integer (fi->next
-                                  ->saved_regs[fi->extra_info->framereg], 4);
+             read_memory_integer (get_frame_saved_regs (get_next_frame (fi))[fi->extra_info->framereg], 4);
          else if (fromleaf)
            /* If we were called by a frameless fn.  then our frame is
               still in the frame pointer register on the board...  */
@@ -1172,9 +1175,9 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
       /* Calculate actual addresses of saved registers using offsets
          determined by arm_scan_prologue.  */
       for (reg = 0; reg < NUM_REGS; reg++)
-       if (fi->saved_regs[reg] != 0)
-         fi->saved_regs[reg] += (fi->frame + fi->extra_info->framesize
-                                 - fi->extra_info->frameoffset);
+       if (get_frame_saved_regs (fi)[reg] != 0)
+         get_frame_saved_regs (fi)[reg] += (fi->frame + fi->extra_info->framesize
+                                            - fi->extra_info->frameoffset);
     }
 }
 
@@ -1191,13 +1194,13 @@ static CORE_ADDR
 arm_frame_saved_pc (struct frame_info *fi)
 {
   /* If a dummy frame, pull the PC out of the frame's register buffer.  */
-  if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
-    return deprecated_read_register_dummy (fi->pc, fi->frame, ARM_PC_REGNUM);
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
+    return deprecated_read_register_dummy (get_frame_pc (fi), fi->frame, ARM_PC_REGNUM);
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->extra_info->frameoffset,
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), fi->frame - fi->extra_info->frameoffset,
                        fi->frame))
     {
-      return read_memory_integer (fi->saved_regs[ARM_PC_REGNUM],
+      return read_memory_integer (get_frame_saved_regs (fi)[ARM_PC_REGNUM],
                                  REGISTER_RAW_SIZE (ARM_PC_REGNUM));
     }
   else
@@ -1229,7 +1232,7 @@ static void
 arm_frame_init_saved_regs (struct frame_info *fip)
 {
 
-  if (fip->saved_regs)
+  if (get_frame_saved_regs (fip))
     return;
 
   arm_init_extra_frame_info (0, fip);
@@ -1520,7 +1523,7 @@ arm_pop_frame (void)
   CORE_ADDR old_SP = (frame->frame - frame->extra_info->frameoffset
                      + frame->extra_info->framesize);
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), frame->frame, frame->frame))
     {
       generic_pop_dummy_frame ();
       flush_cached_frames ();
@@ -1528,9 +1531,9 @@ arm_pop_frame (void)
     }
 
   for (regnum = 0; regnum < NUM_REGS; regnum++)
-    if (frame->saved_regs[regnum] != 0)
+    if (get_frame_saved_regs (frame)[regnum] != 0)
       write_register (regnum,
-                 read_memory_integer (frame->saved_regs[regnum],
+                 read_memory_integer (get_frame_saved_regs (frame)[regnum],
                                       REGISTER_RAW_SIZE (regnum)));
 
   write_register (ARM_PC_REGNUM, FRAME_SAVED_PC (frame));
@@ -1664,7 +1667,8 @@ arm_register_sim_regno (int regnum)
    little-endian systems.  */
 
 static void
-convert_from_extended (void *ptr, void *dbl)
+convert_from_extended (const struct floatformat *fmt, const void *ptr,
+                      void *dbl)
 {
   DOUBLEST d;
   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
@@ -1672,14 +1676,14 @@ convert_from_extended (void *ptr, void *dbl)
   else
     floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
                             ptr, &d);
-  floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
+  floatformat_from_doublest (fmt, &d, dbl);
 }
 
 static void
-convert_to_extended (void *dbl, void *ptr)
+convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr)
 {
   DOUBLEST d;
-  floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
+  floatformat_to_doublest (fmt, ptr, &d);
   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
   else
@@ -2217,9 +2221,11 @@ arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 
 static void
 arm_extract_return_value (struct type *type,
-                         char regbuf[REGISTER_BYTES],
-                         char *valbuf)
+                         struct regcache *regs,
+                         void *dst)
 {
+  bfd_byte *valbuf = dst;
+
   if (TYPE_CODE_FLT == TYPE_CODE (type))
     {
       struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
@@ -2227,14 +2233,24 @@ arm_extract_return_value (struct type *type,
       switch (tdep->fp_model)
        {
        case ARM_FLOAT_FPA:
-         convert_from_extended (&regbuf[REGISTER_BYTE (ARM_F0_REGNUM)],
-                                valbuf);
+         {
+           /* The value is in register F0 in internal format.  We need to
+              extract the raw value and then convert it to the desired
+              internal type.  */
+           bfd_byte tmpbuf[FP_REGISTER_RAW_SIZE];
+
+           regcache_cooked_read (regs, ARM_F0_REGNUM, tmpbuf);
+           convert_from_extended (floatformat_from_type (type), tmpbuf,
+                                  valbuf);
+         }
          break;
 
        case ARM_FLOAT_SOFT:
        case ARM_FLOAT_SOFT_VFP:
-         memcpy (valbuf, &regbuf[REGISTER_BYTE (ARM_A1_REGNUM)],
-                 TYPE_LENGTH (type));
+         regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
+         if (TYPE_LENGTH (type) > 4)
+           regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
+                                 valbuf + INT_REGISTER_RAW_SIZE);
          break;
 
        default:
@@ -2244,9 +2260,50 @@ arm_extract_return_value (struct type *type,
          break;
        }
     }
+  else if (TYPE_CODE (type) == TYPE_CODE_INT
+          || TYPE_CODE (type) == TYPE_CODE_CHAR
+          || TYPE_CODE (type) == TYPE_CODE_BOOL
+          || TYPE_CODE (type) == TYPE_CODE_PTR
+          || TYPE_CODE (type) == TYPE_CODE_REF
+          || TYPE_CODE (type) == TYPE_CODE_ENUM)
+    {
+      /* If the the type is a plain integer, then the access is
+        straight-forward.  Otherwise we have to play around a bit more.  */
+      int len = TYPE_LENGTH (type);
+      int regno = ARM_A1_REGNUM;
+      ULONGEST tmp;
+
+      while (len > 0)
+       {
+         /* By using store_unsigned_integer we avoid having to do
+            anything special for small big-endian values.  */
+         regcache_cooked_read_unsigned (regs, regno++, &tmp);
+         store_unsigned_integer (valbuf, 
+                                 (len > INT_REGISTER_RAW_SIZE
+                                  ? INT_REGISTER_RAW_SIZE : len),
+                                 tmp);
+         len -= INT_REGISTER_RAW_SIZE;
+         valbuf += INT_REGISTER_RAW_SIZE;
+       }
+    }
   else
-    memcpy (valbuf, &regbuf[REGISTER_BYTE (ARM_A1_REGNUM)],
-           TYPE_LENGTH (type));
+    {
+      /* For a structure or union the behaviour is as if the value had
+         been stored to word-aligned memory and then loaded into 
+         registers with 32-bit load instruction(s).  */
+      int len = TYPE_LENGTH (type);
+      int regno = ARM_A1_REGNUM;
+      bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+
+      while (len > 0)
+       {
+         regcache_cooked_read (regs, regno++, tmpbuf);
+         memcpy (valbuf, tmpbuf,
+                 len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
+         len -= INT_REGISTER_RAW_SIZE;
+         valbuf += INT_REGISTER_RAW_SIZE;
+       }
+    }
 }
 
 /* Extract from an array REGBUF containing the (raw) register state
@@ -2359,8 +2416,11 @@ arm_use_struct_convention (int gcc_p, struct type *type)
    TYPE, given in virtual format.  */
 
 static void
-arm_store_return_value (struct type *type, char *valbuf)
+arm_store_return_value (struct type *type, struct regcache *regs,
+                       const void *src)
 {
+  const bfd_byte *valbuf = src;
+
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
       struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
@@ -2370,15 +2430,16 @@ arm_store_return_value (struct type *type, char *valbuf)
        {
        case ARM_FLOAT_FPA:
 
-         convert_to_extended (valbuf, buf);
-         deprecated_write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
-                                          FP_REGISTER_RAW_SIZE);
+         convert_to_extended (floatformat_from_type (type), buf, valbuf);
+         regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
          break;
 
        case ARM_FLOAT_SOFT:
        case ARM_FLOAT_SOFT_VFP:
-         deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
-                                          TYPE_LENGTH (type));
+         regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
+         if (TYPE_LENGTH (type) > 4)
+           regcache_cooked_write (regs, ARM_A1_REGNUM + 1, 
+                                  valbuf + INT_REGISTER_RAW_SIZE);
          break;
 
        default:
@@ -2388,9 +2449,57 @@ arm_store_return_value (struct type *type, char *valbuf)
          break;
        }
     }
+  else if (TYPE_CODE (type) == TYPE_CODE_INT
+          || TYPE_CODE (type) == TYPE_CODE_CHAR
+          || TYPE_CODE (type) == TYPE_CODE_BOOL
+          || TYPE_CODE (type) == TYPE_CODE_PTR
+          || TYPE_CODE (type) == TYPE_CODE_REF
+          || TYPE_CODE (type) == TYPE_CODE_ENUM)
+    {
+      if (TYPE_LENGTH (type) <= 4)
+       {
+         /* Values of one word or less are zero/sign-extended and
+            returned in r0.  */
+         bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+         LONGEST val = unpack_long (type, valbuf);
+
+         store_signed_integer (tmpbuf, INT_REGISTER_RAW_SIZE, val);
+         regcache_cooked_write (regs, ARM_A1_REGNUM, tmpbuf);
+       }
+      else
+       {
+         /* Integral values greater than one word are stored in consecutive
+            registers starting with r0.  This will always be a multiple of
+            the regiser size.  */
+         int len = TYPE_LENGTH (type);
+         int regno = ARM_A1_REGNUM;
+
+         while (len > 0)
+           {
+             regcache_cooked_write (regs, regno++, valbuf);
+             len -= INT_REGISTER_RAW_SIZE;
+             valbuf += INT_REGISTER_RAW_SIZE;
+           }
+       }
+    }
   else
-    deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
-                                    TYPE_LENGTH (type));
+    {
+      /* For a structure or union the behaviour is as if the value had
+         been stored to word-aligned memory and then loaded into 
+         registers with 32-bit load instruction(s).  */
+      int len = TYPE_LENGTH (type);
+      int regno = ARM_A1_REGNUM;
+      bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+
+      while (len > 0)
+       {
+         memcpy (tmpbuf, valbuf,
+                 len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
+         regcache_cooked_write (regs, regno++, tmpbuf);
+         len -= INT_REGISTER_RAW_SIZE;
+         valbuf += INT_REGISTER_RAW_SIZE;
+       }
+    }
 }
 
 /* Store the address of the place in which to copy the structure the
@@ -2706,49 +2815,40 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
-  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
   /* Try to deterimine the ABI of the object we are loading.  */
 
-  if (info.abfd != NULL)
+  if (info.abfd != NULL && info.osabi == GDB_OSABI_UNKNOWN)
     {
-      osabi = gdbarch_lookup_osabi (info.abfd);
-      if (osabi == GDB_OSABI_UNKNOWN)
+      switch (bfd_get_flavour (info.abfd))
        {
-         switch (bfd_get_flavour (info.abfd))
-           {
-           case bfd_target_aout_flavour:
-             /* Assume it's an old APCS-style ABI.  */
-             osabi = GDB_OSABI_ARM_APCS;
-             break;
+       case bfd_target_aout_flavour:
+         /* Assume it's an old APCS-style ABI.  */
+         info.osabi = GDB_OSABI_ARM_APCS;
+         break;
 
-           case bfd_target_coff_flavour:
-             /* Assume it's an old APCS-style ABI.  */
-             /* XXX WinCE?  */
-             osabi = GDB_OSABI_ARM_APCS;
-             break;
+       case bfd_target_coff_flavour:
+         /* Assume it's an old APCS-style ABI.  */
+         /* XXX WinCE?  */
+         info.osabi = GDB_OSABI_ARM_APCS;
+         break;
 
-           default:
-             /* Leave it as "unknown".  */
-           }
+       default:
+         /* Leave it as "unknown".  */
        }
     }
 
-  /* Find a candidate among extant architectures.  */
-  for (arches = gdbarch_list_lookup_by_info (arches, &info);
-       arches != NULL;
-       arches = gdbarch_list_lookup_by_info (arches->next, &info))
-    {
-      /* Make sure the ABI selection matches.  */
-      tdep = gdbarch_tdep (arches->gdbarch);
-      if (tdep && tdep->osabi == osabi)
-       return arches->gdbarch;
-    }
+  /* If there is already a candidate, use it.  */
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return arches->gdbarch;
 
   tdep = xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  tdep->osabi = osabi;
+  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
+     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
+  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
 
   /* This is the way it has always defaulted.  */
   tdep->fp_model = ARM_FLOAT_FPA;
@@ -2801,8 +2901,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_push_return_address (gdbarch, arm_push_return_address);
 
   set_gdbarch_push_arguments (gdbarch, arm_push_arguments);
-  set_gdbarch_coerce_float_to_double (gdbarch,
-                                     standard_coerce_float_to_double);
 
   /* Frame handling.  */
   set_gdbarch_frame_chain_valid (gdbarch, arm_frame_chain_valid);
@@ -2865,8 +2963,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_name (gdbarch, arm_register_name);
 
   /* Returning results.  */
-  set_gdbarch_deprecated_extract_return_value (gdbarch, arm_extract_return_value);
-  set_gdbarch_deprecated_store_return_value (gdbarch, arm_store_return_value);
+  set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
+  set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
   set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
   set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
   set_gdbarch_extract_struct_value_address (gdbarch,
@@ -2882,7 +2980,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                         arm_coff_make_msymbol_special);
 
   /* Hook in the ABI-specific overrides, if they have been registered.  */
-  gdbarch_init_osabi (info, gdbarch, osabi);
+  gdbarch_init_osabi (info, gdbarch);
 
   /* Now we have tuned the configuration, set a few final things,
      based on what the OS ABI has told us.  */
@@ -2926,8 +3024,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* We can't use SIZEOF_FRAME_SAVED_REGS here, since that still
      references the old architecture vector, not the one we are
      building here.  */
-  if (prologue_cache.saved_regs != NULL)
-    xfree (prologue_cache.saved_regs);
+  if (get_frame_saved_regs (&prologue_cache) != NULL)
+    xfree (get_frame_saved_regs (&prologue_cache));
 
   /* We can't use NUM_REGS nor NUM_PSEUDO_REGS here, since that still
      references the old architecture vector, not the one we are
@@ -2948,9 +3046,6 @@ arm_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
   if (tdep == NULL)
     return;
 
-  fprintf_unfiltered (file, "arm_dump_tdep: OS ABI = %s\n",
-                     gdbarch_osabi_name (tdep->osabi));
-
   fprintf_unfiltered (file, "arm_dump_tdep: Lowest pc = 0x%lx",
                      (unsigned long) tdep->lowest_pc);
 }
@@ -2997,11 +3092,11 @@ _initialize_arm_tdep (void)
                                  arm_elf_osabi_sniffer);
 
   /* Register some ABI variants for embedded systems.  */
-  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_EABI_V1,
+  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V1,
                           arm_init_abi_eabi_v1);
-  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_EABI_V2,
+  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V2,
                           arm_init_abi_eabi_v2);
-  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_APCS,
+  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_APCS,
                           arm_init_abi_apcs);
 
   tm_print_insn = gdb_print_insn_arm;
This page took 0.034428 seconds and 4 git commands to generate.