* arm-tdep.c (arm_gdbarch_init): Use gdbarch_num_pseudo_regs
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index a60f4978f048b1f2bfb7145928f5e2896140abd2..3474d1fc0788c4ad4c163d7cf531a666d7c811e0 100644 (file)
@@ -1263,6 +1263,25 @@ static LONGEST arm_call_dummy_words[] =
   0xe1a0e00f, 0xe1a0f004, 0xe7ffdefe
 };
 
+/* Adjust the call_dummy_breakpoint_offset for the bp_call_dummy
+   breakpoint to the proper address in the call dummy, so that
+   `finish' after a stop in a call dummy works.
+
+   FIXME rearnsha 2002-02018: Tweeking current_gdbarch is not an
+   optimal solution, but the call to arm_fix_call_dummy is immediately
+   followed by a call to run_stack_dummy, which is the only function
+   where call_dummy_breakpoint_offset is actually used.  */
+
+
+static void
+arm_set_call_dummy_breakpoint_offset (void)
+{
+  if (caller_is_thumb)
+    set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 4);
+  else
+    set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 8);
+}
+
 /* Fix up the call dummy, based on whether the processor is currently
    in Thumb or ARM mode, and whether the target function is Thumb or
    ARM.  There are three different situations requiring three
@@ -1292,6 +1311,7 @@ arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
 
   /* Set flag indicating whether the current PC is in a Thumb function. */
   caller_is_thumb = arm_pc_is_thumb (read_pc ());
+  arm_set_call_dummy_breakpoint_offset ();
 
   /* If the target function is Thumb, set the low bit of the function
      address.  And if the CPU is currently in ARM mode, patch the
@@ -1326,22 +1346,6 @@ arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
   write_register (4, fun);
 }
 
-/* Return the offset in the call dummy of the instruction that needs
-   to have a breakpoint placed on it.  This is the offset of the 'swi
-   24' instruction, which is no longer actually used, but simply acts
-   as a place-holder now.
-
-   This implements the CALL_DUMMY_BREAK_OFFSET macro.  */
-
-int
-arm_call_dummy_breakpoint_offset (void)
-{
-  if (caller_is_thumb)
-    return 4;
-  else
-    return 8;
-}
-
 /* Note: ScottB
 
    This function does not support passing parameters using the FPA
@@ -2074,8 +2078,8 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
    abi-specific code during establishment of the gdbarch vector.  */
 
 
-/* XXX for now we allow a non-multi-arch gdb to override these
-   definitions.  */
+/* NOTE rearnsha 2002-02-18: for now we allow a non-multi-arch gdb to
+   override these definitions.  */
 #ifndef ARM_LE_BREAKPOINT
 #define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7}
 #endif
@@ -2135,7 +2139,29 @@ arm_extract_return_value (struct type *type,
                          char *valbuf)
 {
   if (TYPE_CODE_FLT == TYPE_CODE (type))
-    convert_from_extended (&regbuf[REGISTER_BYTE (ARM_F0_REGNUM)], valbuf);
+    {
+      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+      switch (tdep->fp_model)
+       {
+       case ARM_FLOAT_FPA:
+         convert_from_extended (&regbuf[REGISTER_BYTE (ARM_F0_REGNUM)],
+                                valbuf);
+         break;
+
+       case ARM_FLOAT_SOFT:
+       case ARM_FLOAT_SOFT_VFP:
+         memcpy (valbuf, &regbuf[REGISTER_BYTE (ARM_A1_REGNUM)],
+                 TYPE_LENGTH (type));
+         break;
+
+       default:
+         internal_error
+           (__FILE__, __LINE__,
+            "arm_extract_return_value: Floating point model not supported");
+         break;
+       }
+    }
   else
     memcpy (valbuf, &regbuf[REGISTER_BYTE (ARM_A1_REGNUM)],
            TYPE_LENGTH (type));
@@ -2252,15 +2278,32 @@ arm_store_return_value (struct type *type, char *valbuf)
 {
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
+      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
       char buf[MAX_REGISTER_RAW_SIZE];
 
-      convert_to_extended (valbuf, buf);
-      /* XXX Is this correct for soft-float?  */
-      write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
-                           MAX_REGISTER_RAW_SIZE);
+      switch (tdep->fp_model)
+       {
+       case ARM_FLOAT_FPA:
+
+         convert_to_extended (valbuf, buf);
+         write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
+                               MAX_REGISTER_RAW_SIZE);
+         break;
+
+       case ARM_FLOAT_SOFT:
+       case ARM_FLOAT_SOFT_VFP:
+         write_register_bytes (ARM_A1_REGNUM, valbuf, TYPE_LENGTH (type));
+         break;
+
+       default:
+         internal_error
+           (__FILE__, __LINE__,
+            "arm_store_return_value: Floating point model not supported");
+         break;
+       }
     }
   else
-    write_register_bytes (0, valbuf, TYPE_LENGTH (type));
+    write_register_bytes (ARM_A1_REGNUM, valbuf, TYPE_LENGTH (type));
 }
 
 /* Store the address of the place in which to copy the structure the
@@ -2272,6 +2315,23 @@ arm_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
   write_register (ARM_A1_REGNUM, addr);
 }
 
+static int
+arm_get_longjmp_target (CORE_ADDR *pc)
+{
+  CORE_ADDR jb_addr;
+  char buf[INT_REGISTER_RAW_SIZE];
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  
+  jb_addr = read_register (ARM_A1_REGNUM);
+
+  if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf,
+                         INT_REGISTER_RAW_SIZE))
+    return 0;
+
+  *pc = extract_address (buf, INT_REGISTER_RAW_SIZE);
+  return 1;
+}
+
 /* Return non-zero if the PC is inside a thumb call thunk.  */
 
 int
@@ -2504,7 +2564,7 @@ process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
        {
          int os_number = bfd_h_get_32 (abfd, note + 16);
 
-         /* The case numbers are from abi-tags in glibc */
+         /* The case numbers are from abi-tags in glibc */
          switch (os_number)
            {
            case 0 :
@@ -2562,7 +2622,7 @@ process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
 
 /* Return one of the ELFOSABI_ constants for BFDs representing ELF
    executables.  If it's not an ELF executable or if the OS/ABI couldn't
-   be determined, simply return -1. */
+   be determined, simply return -1.  */
 
 static int
 get_elfosabi (bfd *abfd)
@@ -2578,7 +2638,7 @@ get_elfosabi (bfd *abfd)
      have to check the note sections too.
 
      GNU/ARM tools set the EI_OSABI field to ELFOSABI_ARM, so handle that
-     as well.*/
+     as well.  */
   if (elfosabi == 0 || elfosabi == ELFOSABI_ARM)
     {
       bfd_map_over_sections (abfd,
@@ -2677,7 +2737,7 @@ arm_gdbarch_register_os_abi (enum arm_abi abi,
    during this debugging session.
 
    Called e.g. at program startup, when reading a core file, and when reading
-   a binary file. */
+   a binary file.  */
 
 static struct gdbarch *
 arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
@@ -2717,7 +2777,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
-  /* Find a candidate among extant architectures. */
+  /* 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))
@@ -2741,7 +2801,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       tdep->abi_name = "<invalid>";
     }
 
-  /* Breakpoints and floating point sizes and format.  */
+  /* This is the way it has always defaulted.  */
+  tdep->fp_model = ARM_FLOAT_FPA;
+
+  /* Breakpoints.  */
   switch (info.byte_order)
     {
     case BFD_ENDIAN_BIG:
@@ -2750,10 +2813,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       tdep->thumb_breakpoint = arm_default_thumb_be_breakpoint;
       tdep->thumb_breakpoint_size = sizeof (arm_default_thumb_be_breakpoint);
 
-      set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
-      set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
-      set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
-      
       break;
 
     case BFD_ENDIAN_LITTLE:
@@ -2762,12 +2821,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       tdep->thumb_breakpoint = arm_default_thumb_le_breakpoint;
       tdep->thumb_breakpoint_size = sizeof (arm_default_thumb_le_breakpoint);
 
-      set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
-      set_gdbarch_double_format (gdbarch,
-                                &floatformat_ieee_double_littlebyte_bigword);
-      set_gdbarch_long_double_format (gdbarch,
-                                &floatformat_ieee_double_littlebyte_bigword);
-
       break;
 
     default:
@@ -2775,19 +2828,28 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                      "arm_gdbarch_init: bad byte order for float format");
     }
 
+  /* On ARM targets char defaults to unsigned.  */
+  set_gdbarch_char_signed (gdbarch, 0);
+
+  /* This should be low enough for everything.  */
   tdep->lowest_pc = 0x20;
+  tdep->jb_pc = -1; /* Longjump support not enabled by default.  */
 
   set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
 
   /* Call dummy code.  */
   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
   set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+  /* We have to give this a value now, even though we will re-set it 
+     during each call to arm_fix_call_dummy.  */
+  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 8);
   set_gdbarch_call_dummy_p (gdbarch, 1);
   set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
 
   set_gdbarch_call_dummy_words (gdbarch, arm_call_dummy_words);
   set_gdbarch_sizeof_call_dummy_words (gdbarch, sizeof (arm_call_dummy_words));
   set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+  set_gdbarch_call_dummy_length (gdbarch, 0);
 
   set_gdbarch_fix_call_dummy (gdbarch, arm_fix_call_dummy);
 
@@ -2795,6 +2857,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
   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);
@@ -2873,9 +2937,12 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Hook in the ABI-specific overrides, if they have been registered.  */
   if (arm_abi == ARM_ABI_UNKNOWN)
     {
-      fprintf_filtered
-       (gdb_stderr, "GDB doesn't recognize the ABI of the inferior.  "
-        "Attempting to continue with the default ARM settings");
+      /* Don't complain about not knowing the ABI variant if we don't 
+        have an inferior.  */
+      if (info.abfd)
+       fprintf_filtered
+         (gdb_stderr, "GDB doesn't recognize the ABI of the inferior.  "
+          "Attempting to continue with the default ARM settings");
     }
   else
     {
@@ -2904,6 +2971,42 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Now we have tuned the configuration, set a few final things,
      based on what the OS ABI has told us.  */
 
+  if (tdep->jb_pc >= 0)
+    set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
+
+  /* Floating point sizes and format.  */
+  switch (info.byte_order)
+    {
+    case BFD_ENDIAN_BIG:
+      set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
+      set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
+      set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
+      
+      break;
+
+    case BFD_ENDIAN_LITTLE:
+      set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
+      if (tdep->fp_model == ARM_FLOAT_VFP
+         || tdep->fp_model == ARM_FLOAT_SOFT_VFP)
+       {
+         set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
+         set_gdbarch_long_double_format (gdbarch,
+                                         &floatformat_ieee_double_little);
+       }
+      else
+       {
+         set_gdbarch_double_format
+           (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
+         set_gdbarch_long_double_format
+           (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
+       }
+      break;
+
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "arm_gdbarch_init: bad byte order for float format");
+    }
+
   /* We can't use SIZEOF_FRAME_SAVED_REGS here, since that still
      references the old architecture vector, not the one we are
      building here.  */
@@ -2912,7 +3015,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   prologue_cache.saved_regs = (CORE_ADDR *)
     xcalloc (1, (sizeof (CORE_ADDR)
-                * (gdbarch_num_regs (gdbarch) + NUM_PSEUDO_REGS)));
+                * (gdbarch_num_regs (gdbarch)
+                   + gdbarch_num_pseudo_regs (gdbarch))));
 
   return gdbarch;
 }
This page took 0.026903 seconds and 4 git commands to generate.