* gdb.texinfo (Help): Fix formatting of examples.
[deliverable/binutils-gdb.git] / gdb / arch-utils.c
index 78768a61a91bb806b35adfb8f0476b0c496c75ac..1ec3c37ff454c926154242f9809d0a943c3e8498 100644 (file)
 
 #include "floatformat.h"
 
-/* Implementation of extract return value that grubs around in the
-   register cache.  */
-void
-legacy_extract_return_value (struct type *type, struct regcache *regcache,
-                            gdb_byte *valbuf)
-{
-  gdb_byte *registers = deprecated_grub_regcache_for_registers (regcache);
-  gdb_byte *buf = valbuf;
-  DEPRECATED_EXTRACT_RETURN_VALUE (type, registers, buf); /* OK */
-}
-
-/* Implementation of store return value that grubs the register cache.
-   Takes a local copy of the buffer to avoid const problems.  */
-void
-legacy_store_return_value (struct type *type, struct regcache *regcache,
-                          const gdb_byte *buf)
-{
-  gdb_byte *b = alloca (TYPE_LENGTH (type));
-  gdb_assert (regcache == current_regcache);
-  memcpy (b, buf, TYPE_LENGTH (type));
-  DEPRECATED_STORE_RETURN_VALUE (type, b);
-}
-
 int
 always_use_struct_convention (int gcc_p, struct type *value_type)
 {
@@ -166,42 +143,6 @@ core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs)
   return (lhs > rhs);
 }
 
-
-/* Helper functions for TARGET_{FLOAT,DOUBLE}_FORMAT */
-
-const struct floatformat *
-default_float_format (struct gdbarch *gdbarch)
-{
-  int byte_order = gdbarch_byte_order (gdbarch);
-  switch (byte_order)
-    {
-    case BFD_ENDIAN_BIG:
-      return &floatformat_ieee_single_big;
-    case BFD_ENDIAN_LITTLE:
-      return &floatformat_ieee_single_little;
-    default:
-      internal_error (__FILE__, __LINE__,
-                     _("default_float_format: bad byte order"));
-    }
-}
-
-
-const struct floatformat *
-default_double_format (struct gdbarch *gdbarch)
-{
-  int byte_order = gdbarch_byte_order (gdbarch);
-  switch (byte_order)
-    {
-    case BFD_ENDIAN_BIG:
-      return &floatformat_ieee_double_big;
-    case BFD_ENDIAN_LITTLE:
-      return &floatformat_ieee_double_little;
-    default:
-      internal_error (__FILE__, __LINE__,
-                     _("default_double_format: bad byte order"));
-    }
-}
-
 /* Misc helper functions for targets. */
 
 CORE_ADDR
@@ -273,7 +214,7 @@ int
 generic_register_size (int regnum)
 {
   gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
-  return TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum));
+  return TYPE_LENGTH (register_type (current_gdbarch, regnum));
 }
 
 /* Assume all registers are adjacent.  */
@@ -312,17 +253,6 @@ generic_convert_register_p (int regnum, struct type *type)
 int
 default_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
 {
-  if (DEPRECATED_REG_STRUCT_HAS_ADDR_P ()
-      && DEPRECATED_REG_STRUCT_HAS_ADDR (processing_gcc_compilation, type))
-    {
-      CHECK_TYPEDEF (type);
-
-      return (TYPE_CODE (type) == TYPE_CODE_STRUCT
-             || TYPE_CODE (type) == TYPE_CODE_UNION
-             || TYPE_CODE (type) == TYPE_CODE_SET
-             || TYPE_CODE (type) == TYPE_CODE_BITSTRING);
-    }
-
   return 0;
 }
 
@@ -333,6 +263,13 @@ generic_instruction_nullified (struct gdbarch *gdbarch,
   return 0;
 }
 
+int
+default_remote_register_number (struct gdbarch *gdbarch,
+                               int regno)
+{
+  return regno;
+}
+
 \f
 /* Functions to manipulate the endianness of the target.  */
 
@@ -350,13 +287,22 @@ static const char *endian_enum[] =
 };
 static const char *set_endian_string;
 
+enum bfd_endian
+selected_byte_order (void)
+{
+  if (target_byte_order_user != BFD_ENDIAN_UNKNOWN)
+    return TARGET_BYTE_ORDER;
+  else
+    return BFD_ENDIAN_UNKNOWN;
+}
+
 /* Called by ``show endian''.  */
 
 static void
 show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c,
             const char *value)
 {
-  if (target_byte_order_user != BFD_ENDIAN_UNKNOWN)
+  if (target_byte_order_user == BFD_ENDIAN_UNKNOWN)
     if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
       fprintf_unfiltered (file, _("The target endianness is set automatically "
                                  "(currently big endian)\n"));
@@ -409,6 +355,75 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
   show_endian (gdb_stdout, from_tty, NULL, NULL);
 }
 
+/* Given SELECTED, a currently selected BFD architecture, and
+   FROM_TARGET, a BFD architecture reported by the target description,
+   return what architecture to use.  Either may be NULL; if both are
+   specified, we use the more specific.  If the two are obviously
+   incompatible, warn the user.  */
+
+static const struct bfd_arch_info *
+choose_architecture_for_target (const struct bfd_arch_info *selected,
+                               const struct bfd_arch_info *from_target)
+{
+  const struct bfd_arch_info *compat1, *compat2;
+
+  if (selected == NULL)
+    return from_target;
+
+  if (from_target == NULL)
+    return selected;
+
+  /* struct bfd_arch_info objects are singletons: that is, there's
+     supposed to be exactly one instance for a given machine.  So you
+     can tell whether two are equivalent by comparing pointers.  */
+  if (from_target == selected)
+    return selected;
+
+  /* BFD's 'A->compatible (A, B)' functions return zero if A and B are
+     incompatible.  But if they are compatible, it returns the 'more
+     featureful' of the two arches.  That is, if A can run code
+     written for B, but B can't run code written for A, then it'll
+     return A.
+
+     Some targets (e.g. MIPS as of 2006-12-04) don't fully
+     implement this, instead always returning NULL or the first
+     argument.  We detect that case by checking both directions.  */
+
+  compat1 = selected->compatible (selected, from_target);
+  compat2 = from_target->compatible (from_target, selected);
+
+  if (compat1 == NULL && compat2 == NULL)
+    {
+      warning (_("Selected architecture %s is not compatible "
+                "with reported target architecture %s"),
+              selected->printable_name, from_target->printable_name);
+      return selected;
+    }
+
+  if (compat1 == NULL)
+    return compat2;
+  if (compat2 == NULL)
+    return compat1;
+  if (compat1 == compat2)
+    return compat1;
+
+  /* If the two didn't match, but one of them was a default architecture,
+     assume the more specific one is correct.  This handles the case
+     where an executable or target description just says "mips", but
+     the other knows which MIPS variant.  */
+  if (compat1->the_default)
+    return compat2;
+  if (compat2->the_default)
+    return compat1;
+
+  /* We have no idea which one is better.  This is a bug, but not
+     a critical problem; warn the user.  */
+  warning (_("Selected architecture %s is ambiguous with "
+            "reported target architecture %s"),
+          selected->printable_name, from_target->printable_name);
+  return selected;
+}
+
 /* Functions to manipulate the architecture of the target */
 
 enum set_arch { set_arch_auto, set_arch_manual };
@@ -703,6 +718,10 @@ gdbarch_info_fill (struct gdbarch_info *info)
       && bfd_get_arch (info->abfd) != bfd_arch_unknown
       && bfd_get_arch (info->abfd) != bfd_arch_obscure)
     info->bfd_arch_info = bfd_get_arch_info (info->abfd);
+  /* From the target.  */
+  if (info->target_desc != NULL)
+    info->bfd_arch_info = choose_architecture_for_target
+      (info->bfd_arch_info, tdesc_architecture (info->target_desc));
   /* From the default.  */
   if (info->bfd_arch_info == NULL)
     info->bfd_arch_info = default_bfd_arch;
This page took 0.026451 seconds and 4 git commands to generate.