2001-12-19 Fernando Nasser <fnasser@redhat.com>
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index 3ca6dbebe21cfcd7e3d6cf2dd990d3c9a6f5167a..434b26fce0d8cdb064a9bdb588802f0f82053197 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
-   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000
-   Free Software Foundation, Inc.
+   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
+   2001 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "coff/internal.h"     /* Internal format of COFF symbols in BFD */
 #include "dis-asm.h"           /* For register flavors. */
 #include <ctype.h>             /* for isupper () */
+#include "regcache.h"
+#include "doublest.h"
+#include "value.h"
+#include "solib-svr4.h"
 
 /* Each OS has a different mechanism for accessing the various
    registers stored in the sigcontext structure.
@@ -116,24 +120,6 @@ struct frame_extra_info
 #define MAKE_THUMB_ADDR(addr)  ((addr) | 1)
 #define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
 
-#define SWAP_TARGET_AND_HOST(buffer,len)                               \
-  do                                                                   \
-    {                                                                  \
-      if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER)                                \
-       {                                                               \
-         char tmp;                                                     \
-         char *p = (char *)(buffer);                                   \
-         char *q = ((char *)(buffer)) + len - 1;                       \
-         for (; p < q; p++, q--)                                       \
-           {                                                           \
-             tmp = *q;                                                 \
-             *q = *p;                                                  \
-             *p = tmp;                                                 \
-           }                                                           \
-       }                                                               \
-    }                                                                  \
-  while (0)
-
 /* 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.  */
@@ -416,15 +402,24 @@ arm_skip_prologue (CORE_ADDR pc)
   unsigned long inst;
   CORE_ADDR skip_pc;
   CORE_ADDR func_addr, func_end;
+  char *func_name;
   struct symtab_and_line sal;
 
   /* See what the symbol table says.  */
 
-  if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+  if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
     {
-      sal = find_pc_line (func_addr, 0);
-      if ((sal.line != 0) && (sal.end < func_end))
-       return sal.end;
+      struct symbol *sym;
+
+      /* Found a function.  */
+      sym = lookup_symbol (func_name, NULL, VAR_NAMESPACE, NULL, NULL);
+      if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
+        {
+         /* Don't use this trick for assembly source files. */
+         sal = find_pc_line (func_addr, 0);
+         if ((sal.line != 0) && (sal.end < func_end))
+           return sal.end;
+        }
     }
 
   /* Check if this is Thumb code.  */
@@ -1185,7 +1180,7 @@ arm_push_dummy_frame (void)
 
 void
 arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
-                   value_ptr *args, struct type *type, int gcc_p)
+                   struct value **args, struct type *type, int gcc_p)
 {
   static short thumb_dummy[4] =
   {
@@ -1254,7 +1249,7 @@ arm_call_dummy_breakpoint_offset (void)
    general registers and/or on the stack.  */
 
 CORE_ADDR
-arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
+arm_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
                    int struct_return, CORE_ADDR struct_addr)
 {
   char *fp;
@@ -1308,7 +1303,6 @@ arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
     {
       int len;
       char *val;
-      double dbl_arg;
       CORE_ADDR regval;
       enum type_code typecode;
       struct type *arg_type, *target_type;
@@ -1328,22 +1322,11 @@ arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
          calling the function.  */
       if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
        {
-         float f;
-         double d;
-         char * bufo = (char *) &d;
-         char * bufd = (char *) &dbl_arg;
-
-         len = sizeof (double);
-         f = *(float *) val;
-         SWAP_TARGET_AND_HOST (&f, sizeof (float));  /* adjust endianess */
-         d = f;
-         /* We must revert the longwords so they get loaded into the
-            the right registers. */
-         memcpy (bufd, bufo + len / 2, len / 2);
-         SWAP_TARGET_AND_HOST (bufd, len / 2);  /* adjust endianess */
-         memcpy (bufd + len / 2, bufo, len / 2);
-         SWAP_TARGET_AND_HOST (bufd + len / 2, len / 2); /* adjust endianess */
-         val = (char *) &dbl_arg;
+         DOUBLEST dblval;
+         dblval = extract_floating (val, len);
+         len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
+         val = alloca (len);
+         store_floating (val, len, dblval);
        }
 #if 1
       /* I don't know why this code was disable. The only logical use
@@ -1464,76 +1447,47 @@ arm_float_info (void)
   print_fpu_flags (status);
 }
 
-#if 0
-/* FIXME:  The generated assembler works but sucks.  Instead of using
-   r0, r1 it pushes them on the stack, then loads them into r3, r4 and
-   uses those registers.  I must be missing something.  ScottB  */
-
-void
-convert_from_extended (void *ptr, void *dbl)
+struct type *
+arm_register_type (int regnum)
 {
-  __asm__ ("
-          ldfe f0,[%0]
-          stfd f0,[%1] "
-:                              /* no output */
-:         "r" (ptr), "r" (dbl));
+  if (regnum >= F0_REGNUM && regnum < F0_REGNUM + NUM_FREGS)
+    {
+      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+       return builtin_type_arm_ext_big;
+      else
+       return builtin_type_arm_ext_littlebyte_bigword;
+    }
+  else
+    return builtin_type_int32;
 }
 
-void
-convert_to_extended (void *dbl, void *ptr)
-{
-  __asm__ ("
-          ldfd f0,[%0]
-          stfe f0,[%1] "
-:                              /* no output */
-:         "r" (dbl), "r" (ptr));
-}
-#else
+/* NOTE: cagney/2001-08-20: Both convert_from_extended() and
+   convert_to_extended() use floatformat_arm_ext_littlebyte_bigword.
+   It is thought that this is is the floating-point register format on
+   little-endian systems.  */
+
 static void
 convert_from_extended (void *ptr, void *dbl)
 {
-  *(double *) dbl = *(double *) ptr;
+  DOUBLEST d;
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+    floatformat_to_doublest (&floatformat_arm_ext_big, ptr, &d);
+  else
+    floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
+                            ptr, &d);
+  floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
 }
 
 void
 convert_to_extended (void *dbl, void *ptr)
 {
-  *(double *) ptr = *(double *) dbl;
-}
-#endif
-
-/* Nonzero if register N requires conversion from raw format to
-   virtual format.  */
-
-int
-arm_register_convertible (unsigned int regnum)
-{
-  return ((regnum - F0_REGNUM) < 8);
-}
-
-/* Convert data from raw format for register REGNUM in buffer FROM to
-   virtual format with type TYPE in buffer TO.  */
-
-void
-arm_register_convert_to_virtual (unsigned int regnum, struct type *type,
-                                void *from, void *to)
-{
-  double val;
-
-  convert_from_extended (from, &val);
-  store_floating (to, TYPE_LENGTH (type), val);
-}
-
-/* Convert data from virtual format with type TYPE in buffer FROM to
-   raw format for register REGNUM in buffer TO.  */
-
-void
-arm_register_convert_to_raw (unsigned int regnum, struct type *type,
-                            void *from, void *to)
-{
-  double val = extract_floating (from, TYPE_LENGTH (type));
-
-  convert_to_extended (&val, to);
+  DOUBLEST d;
+  floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+    floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
+  else
+    floatformat_from_doublest (&floatformat_arm_ext_littlebyte_bigword,
+                              &d, dbl);
 }
 
 static int
@@ -1578,6 +1532,7 @@ condition_true (unsigned long cond, unsigned long status_reg)
   return 1;
 }
 
+/* Support routines for single stepping.  Calculate the next PC value.  */
 #define submask(x) ((1L << ((x) + 1)) - 1)
 #define bit(obj,st) (((obj) >> (st)) & 1)
 #define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
@@ -1912,6 +1867,31 @@ arm_get_next_pc (CORE_ADDR pc)
   return nextpc;
 }
 
+/* single_step() is called just before we want to resume the inferior,
+   if we want to single-step it but there is no hardware or kernel
+   single-step support.  We find the target of the coming instruction
+   and breakpoint it.
+
+   single_step is also called just after the inferior stops.  If we had
+   set up a simulated single-step, we undo our damage.  */
+
+void
+arm_software_single_step (ignore, insert_bpt)
+     int ignore; /* Signal, not needed */
+     int insert_bpt;
+{
+  static int next_pc; /* State between setting and unsetting. */
+  static char break_mem[BREAKPOINT_MAX]; /* Temporary storage for mem@bpt */
+
+  if (insert_bpt)
+    {
+      next_pc = arm_get_next_pc (read_register (PC_REGNUM));
+      target_insert_breakpoint (next_pc, break_mem);
+    }
+  else
+    target_remove_breakpoint (next_pc, break_mem);
+}
+
 #include "bfd-in2.h"
 #include "libcoff.h"
 
@@ -2124,6 +2104,49 @@ arm_othernames (char *names, int n)
   set_disassembly_flavor (); 
 }
 
+/* Fetch, and possibly build, an appropriate link_map_offsets structure
+   for ARM linux targets using the struct offsets defined in <link.h>.
+   Note, however, that link.h is not actually referred to in this file.
+   Instead, the relevant structs offsets were obtained from examining
+   link.h.  (We can't refer to link.h from this file because the host
+   system won't necessarily have it, or if it does, the structs which
+   it defines will refer to the host system, not the target.)  */
+
+struct link_map_offsets *
+arm_linux_svr4_fetch_link_map_offsets (void)
+{
+  static struct link_map_offsets lmo;
+  static struct link_map_offsets *lmp = 0;
+
+  if (lmp == 0)
+    {
+      lmp = &lmo;
+
+      lmo.r_debug_size = 8;    /* Actual size is 20, but this is all we
+                                   need. */
+
+      lmo.r_map_offset = 4;
+      lmo.r_map_size   = 4;
+
+      lmo.link_map_size = 20;  /* Actual size is 552, but this is all we
+                                   need. */
+
+      lmo.l_addr_offset = 0;
+      lmo.l_addr_size   = 4;
+
+      lmo.l_name_offset = 4;
+      lmo.l_name_size   = 4;
+
+      lmo.l_next_offset = 12;
+      lmo.l_next_size   = 4;
+
+      lmo.l_prev_offset = 16;
+      lmo.l_prev_size   = 4;
+    }
+
+    return lmp;
+}
+
 void
 _initialize_arm_tdep (void)
 {
This page took 0.027667 seconds and 4 git commands to generate.