* arm-tdep.h (enum arm_abi): New enum.
[binutils-gdb.git] / gdb / arm-linux-tdep.c
index 6faf85be9ba41cb198ce1b29f0ebffd57eb8427b..ac2f8e0542b25c9a38cbf51fc1078714b0b06f9b 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU/Linux on ARM target support.
-   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "regcache.h"
 #include "doublest.h"
 
+#include "arm-tdep.h"
+
 /* For arm_linux_skip_solib_resolver.  */
 #include "symtab.h"
 #include "symfile.h"
 #include "objfiles.h"
 
+/* CALL_DUMMY_WORDS:
+   This sequence of words is the instructions
+
+   mov  lr, pc
+   mov  pc, r4
+   swi bkpt_swi
+
+   Note this is 12 bytes.  */
+
+LONGEST arm_linux_call_dummy_words[] =
+{
+  0xe1a0e00f, 0xe1a0f004, 0xef9f001
+};
+
 #ifdef GET_LONGJMP_TARGET
 
 /* Figure out where the longjmp will land.  We expect that we have
    just entered longjmp and haven't yet altered r0, r1, so the
-   arguments are still in the registers.  (A1_REGNUM) points at the
-   jmp_buf structure from which we extract the pc (JB_PC) that we will
-   land at.  The pc is copied into ADDR.  This routine returns true on
-   success. */
+   arguments are still in the registers.  (ARM_A1_REGNUM) points at
+   the jmp_buf structure from which we extract the pc (JB_PC) that we
+   will land at.  The pc is copied into ADDR.  This routine returns
+   true on success. */
 
 #define LONGJMP_TARGET_SIZE    sizeof(int)
 #define JB_ELEMENT_SIZE                sizeof(int)
@@ -55,7 +71,7 @@ arm_get_longjmp_target (CORE_ADDR * pc)
   CORE_ADDR jb_addr;
   char buf[LONGJMP_TARGET_SIZE];
 
-  jb_addr = read_register (A1_REGNUM);
+  jb_addr = read_register (ARM_A1_REGNUM);
 
   if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
                          LONGJMP_TARGET_SIZE))
@@ -82,7 +98,8 @@ arm_linux_extract_return_value (struct type *type,
      GDB.  I suspect this won't handle NWFPE registers correctly, nor
      will the default ARM version (arm_extract_return_value()).  */
 
-  int regnum = (TYPE_CODE_FLT == TYPE_CODE (type)) ? F0_REGNUM : A1_REGNUM;
+  int regnum = ((TYPE_CODE_FLT == TYPE_CODE (type))
+               ? ARM_F0_REGNUM : ARM_A1_REGNUM);
   memcpy (valbuf, &regbuf[REGISTER_BYTE (regnum)], TYPE_LENGTH (type));
 }
 
@@ -146,7 +163,7 @@ arm_linux_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
     }
 
   /* Initialize the integer argument register pointer.  */
-  argreg = A1_REGNUM;
+  argreg = ARM_A1_REGNUM;
 
   /* The struct_return pointer occupies the first parameter passing
      register.  */
@@ -160,7 +177,6 @@ arm_linux_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
     {
       int len;
       char *val;
-      double dbl_arg;
       CORE_ADDR regval;
       enum type_code typecode;
       struct type *arg_type, *target_type;
@@ -180,14 +196,11 @@ arm_linux_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
          calling the function.  */
       if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
        {
-         /* Float argument in buffer is in host format.  Read it and 
-            convert to DOUBLEST, and store it in target double.  */
          DOUBLEST dblval;
-         
+         dblval = extract_floating (val, len);
          len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
-         floatformat_to_doublest (HOST_FLOAT_FORMAT, val, &dblval);
-         store_floating (&dbl_arg, len, dblval);
-         val = (char *) &dbl_arg;
+         val = alloca (len);
+         store_floating (val, len, dblval);
        }
 
       /* If the argument is a pointer to a function, and it is a Thumb
@@ -406,7 +419,7 @@ skip_hurd_resolver (CORE_ADDR pc)
   if (resolver)
     {
       struct minimal_symbol *fixup
-       = lookup_minimal_symbol ("fixup", 0, objfile);
+       = lookup_minimal_symbol ("fixup", NULL, objfile);
 
       if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
        return (SAVED_PC_AFTER_CALL (get_current_frame ()));
@@ -508,16 +521,26 @@ arm_linux_sigcontext_register_address (CORE_ADDR sp, CORE_ADDR pc, int regno)
         PSR value follows the sixteen registers which accounts for
         the constant 19 below. */
 
-      if (0 <= regno && regno <= PC_REGNUM)
+      if (0 <= regno && regno <= ARM_PC_REGNUM)
        reg_addr = sigcontext_addr + 12 + (4 * regno);
-      else if (regno == PS_REGNUM)
+      else if (regno == ARM_PS_REGNUM)
        reg_addr = sigcontext_addr + 19 * 4;
     }
 
   return reg_addr;
 }
 
+static void
+arm_linux_init_abi (struct gdbarch_info info,
+                   struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->lowest_pc = 0x8000;
+}
+
 void
 _initialize_arm_linux_tdep (void)
 {
+  arm_gdbarch_register_os_abi (ARM_ABI_LINUX, arm_linux_init_abi);
 }