2005-09-26 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Mon, 26 Sep 2005 02:17:34 +0000 (02:17 +0000)
committerPaul Brook <paul@codesourcery.com>
Mon, 26 Sep 2005 02:17:34 +0000 (02:17 +0000)
* arm-tdep.c (arm_type_align): New function.
(arm_push_dummy_call): Use it.  Ensure proper argument alignment.
(arm_extract_struct_value_address): Remove.
(arm_use_struct_convention): Rename...
(arm_return_in_memory): ... To this.  Return nonzero for all small
aggregates under the EABI.
(arm_return_value): New function.
(arm_gdbarch_init): Default for VFP float model for EABI binaries.
Use set_gdbarch_return_value instead of obsolete functions.
* testsuite/long_long.exp: Exclude eabi targets from arm FPA float
format test.

gdb/ChangeLog
gdb/arm-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/long_long.exp

index e84e094d64bdbcf66f1fbae161dfb6cc252e97d0..1ddfe1eb16693abb5a75d53c6517ecc45e9604fc 100644 (file)
@@ -1,3 +1,17 @@
+2005-09-26  Paul Brook  <paul@codesourcery.com>
+
+       * arm-tdep.c (arm_type_align): New function.
+       (arm_push_dummy_call): Use it.  Ensure proper argument alignment.
+       (arm_extract_struct_value_address): Remove.
+       (arm_use_struct_convention): Rename...
+       (arm_return_in_memory): ... To this.  Return nonzero for all small
+       aggregates under the EABI.
+       (arm_return_value): New function.
+       (arm_gdbarch_init): Default for VFP float model for EABI binaries.
+       Use set_gdbarch_return_value instead of obsolete functions.
+       * testsuite/long_long.exp: Exclude eabi targets from arm FPA float
+       format test.
+
 2005-09-21  Mark Kettenis  <kettenis@gnu.org>
 
        * mips-tdep.c (n32n64_floatformat_always_valid): Use 'const void
index 69547898514adb4bc36bb3fb34f7af526a4db0b3..ba713f21419cd5e4f2611fb111e701e6a120acad 100644 (file)
@@ -1204,6 +1204,54 @@ pop_stack_item (struct stack_item *si)
   return si;
 }
 
+
+/* Return the alignment (in bytes) of the given type.  */
+
+static int
+arm_type_align (struct type *t)
+{
+  int n;
+  int align;
+  int falign;
+
+  t = check_typedef (t);
+  switch (TYPE_CODE (t))
+    {
+    default:
+      /* Should never happen.  */
+      internal_error (__FILE__, __LINE__, _("unknown type alignment"));
+      return 4;
+
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_SET:
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_BITSTRING:
+    case TYPE_CODE_REF:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_BOOL:
+      return TYPE_LENGTH (t);
+
+    case TYPE_CODE_ARRAY:
+    case TYPE_CODE_COMPLEX:
+      /* TODO: What about vector types?  */
+      return arm_type_align (TYPE_TARGET_TYPE (t));
+
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      align = 1;
+      for (n = 0; n < TYPE_NFIELDS (t); n++)
+       {
+         falign = arm_type_align (TYPE_FIELD_TYPE (t, n));
+         if (falign > align)
+           align = falign;
+       }
+      return align;
+    }
+}
+
 /* We currently only support passing parameters in integer registers.  This
    conforms with GCC's default model.  Several other variants exist and
    we should probably support some of them based on the selected ABI.  */
@@ -1255,6 +1303,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       struct type *target_type;
       enum type_code typecode;
       bfd_byte *val;
+      int align;
 
       arg_type = check_typedef (value_type (args[argnum]));
       len = TYPE_LENGTH (arg_type);
@@ -1262,6 +1311,35 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       typecode = TYPE_CODE (arg_type);
       val = value_contents_writeable (args[argnum]);
 
+      align = arm_type_align (arg_type);
+      /* Round alignment up to a whole number of words.  */
+      align = (align + INT_REGISTER_SIZE - 1) & ~(INT_REGISTER_SIZE - 1);
+      /* Different ABIs have different maximum alignments.  */
+      if (gdbarch_tdep (gdbarch)->arm_abi == ARM_ABI_APCS)
+       {
+         /* The APCS ABI only requires word alignment.  */
+         align = INT_REGISTER_SIZE;
+       }
+      else
+       {
+         /* The AAPCS requires at most doubleword alignment.  */
+         if (align > INT_REGISTER_SIZE * 2)
+           align = INT_REGISTER_SIZE * 2;
+       }
+
+      /* Push stack padding for dowubleword alignment.  */
+      if (nstack & (align - 1))
+       {
+         si = push_stack_item (si, val, INT_REGISTER_SIZE);
+         nstack += INT_REGISTER_SIZE;
+       }
+      
+      /* Doubleword aligned quantities must go in even register pairs.  */
+      if (argreg <= ARM_LAST_ARG_REGNUM
+         && align > INT_REGISTER_SIZE
+         && argreg & 1)
+       argreg++;
+
       /* If the argument is a pointer to a function, and it is a
         Thumb function, create a LOCAL copy of the value and set
         the THUMB bit in it.  */
@@ -2094,24 +2172,13 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
     }
 }
 
-/* Extract from an array REGBUF containing the (raw) register state
-   the address in which a function should return its structure value.  */
-
-static CORE_ADDR
-arm_extract_struct_value_address (struct regcache *regcache)
-{
-  ULONGEST ret;
-
-  regcache_cooked_read_unsigned (regcache, ARM_A1_REGNUM, &ret);
-  return ret;
-}
 
 /* Will a function return an aggregate type in memory or in a
    register?  Return 0 if an aggregate type can be returned in a
    register, 1 if it must be returned in memory.  */
 
 static int
-arm_use_struct_convention (int gcc_p, struct type *type)
+arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
 {
   int nRc;
   enum type_code code;
@@ -2142,6 +2209,11 @@ arm_use_struct_convention (int gcc_p, struct type *type)
       return 1;
     }
 
+  /* The AAPCS says all aggregates not larger than a word are returned
+     in a register.  */
+  if (gdbarch_tdep (gdbarch)->arm_abi != ARM_ABI_APCS)
+    return 0;
+
   /* The only aggregate types that can be returned in a register are
      structs and unions.  Arrays must be returned in memory.  */
   code = TYPE_CODE (type);
@@ -2289,6 +2361,32 @@ arm_store_return_value (struct type *type, struct regcache *regs,
     }
 }
 
+
+/* Handle function return values.  */
+
+static enum return_value_convention
+arm_return_value (struct gdbarch *gdbarch, struct type *valtype,
+                 struct regcache *regcache, void *readbuf,
+                 const void *writebuf)
+{
+  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+      || TYPE_CODE (valtype) == TYPE_CODE_UNION
+      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+    {
+      if (arm_return_in_memory (gdbarch, valtype))
+       return RETURN_VALUE_STRUCT_CONVENTION;
+    }
+
+  if (writebuf)
+    arm_store_return_value (valtype, regcache, writebuf);
+
+  if (readbuf)
+    arm_extract_return_value (valtype, regcache, readbuf);
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+
 static int
 arm_get_longjmp_target (CORE_ADDR *pc)
 {
@@ -2568,7 +2666,7 @@ arm_write_pc (CORE_ADDR pc, ptid_t ptid)
 static enum gdb_osabi
 arm_elf_osabi_sniffer (bfd *abfd)
 {
-  unsigned int elfosabi, eflags;
+  unsigned int elfosabi;
   enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
   elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
@@ -2646,6 +2744,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
                case EF_ARM_EABI_VER4:
                  arm_abi = ARM_ABI_AAPCS;
+                 /* EABI binaries default to VFP float ordering.  */
+                 if (fp_model == ARM_FLOAT_AUTO)
+                   fp_model = ARM_FLOAT_SOFT_VFP;
                  break;
 
                default:
@@ -2787,10 +2888,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_name (gdbarch, arm_register_name);
 
   /* Returning results.  */
-  set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
-  set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
-  set_gdbarch_deprecated_use_struct_convention (gdbarch, arm_use_struct_convention);
-  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, arm_extract_struct_value_address);
+  set_gdbarch_return_value (gdbarch, arm_return_value);
 
   /* Single stepping.  */
   /* XXX For an RDI target we should ask the target if it can single-step.  */
index be05d414b5fe55b56e7d80af9696fad3449ff83a..f4a78614d8ba6bed405bff204ca5980aa50fe4ed 100644 (file)
@@ -1,3 +1,7 @@
+2005-09-26  Paul Brook  <paul@codesourcery.com>
+
+       * long_long.exp: Exclude eabi targets from arm FPA float format test.
+
 2005-09-20  Wu Zhou  <woodzltc@cn.ibm.com>
 
        * bfp-test.c: New file.
index b36b30b32b246cbb7ef3e77294ffacd5575c0919..fb39d9606e18f010cebf86a6da6be5e89b060b47 100644 (file)
@@ -201,13 +201,16 @@ gdb_test_ptr "p/a val.oct" "" "" "0x77053977" "0xa72ee53977053977"
 gdb_test "p/c val.oct" "'w'"
 
 if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
-    # ARM floating point numbers are not strictly little endian or big endian,
-    # but a hybrid.  They are in little endian format with the two words
-    # swapped in big endian format.
+    # ARM FPA floating point numbers are not strictly little endian or big
+    # endian, but a hybrid.  They are in little endian format with the two
+    # words swapped in big endian format.
+    # EABI targets default to natural-endian VFP format.
 
-    if { [istarget "arm*-*-*"] || \
+    if { ([istarget "arm*-*-*"] || \
            [istarget "xscale*-*-*"] || \
-           [istarget "strongarm*-*-*"] } then {
+           [istarget "strongarm*-*-*"]) \
+         && !([istarget "*-*-*eabi"] || \
+               [istarget "*-*-symbianelf"]) } then {
        # assume the long long represents a floating point double in ARM format
        gdb_test "p/f val.oct" "2.1386676354387559e\\+265"
     } else {