* arm-tdep.h (arm_float_model): Add AUTO and LAST values.
authorRichard Earnshaw <richard.earnshaw@arm.com>
Sat, 22 Mar 2003 20:39:21 +0000 (20:39 +0000)
committerRichard Earnshaw <richard.earnshaw@arm.com>
Sat, 22 Mar 2003 20:39:21 +0000 (20:39 +0000)
(arm_get_fp_model): Declare.
* arm-tdep.c (fp_model_strings): New string array.
(arm_fp_model, current_fp_model): New variables.
(arm_get_fp_model): New function.
(arm_set_fp): New function.
(set_fp_model_sfunc): New function.
(show_fp_model): New function.
(_initialize_arm_tdep): Add new command to set/show the FPU.
(arm_extract_return_value): Use arm_get_fp_model.
(arm_store_return_value): Likewise.
(arm_gdbarch_init): Default fpa model is softfpa.  Call arm_set_fp
to initialize the floating-point data types.
* arm-linux-tdep.c (arm_linux_init_abi): The default floating point
model is FPA.

gdb/ChangeLog
gdb/arm-linux-tdep.c
gdb/arm-tdep.c
gdb/arm-tdep.h

index 18904e1f66e7c786f23a5fde6a71275fcc804f38..58963592853398bd3c968023657dff3af380ed63 100644 (file)
@@ -1,3 +1,21 @@
+2003-03-22  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm-tdep.h (arm_float_model): Add AUTO and LAST values.
+       (arm_get_fp_model): Declare.
+       * arm-tdep.c (fp_model_strings): New string array.
+       (arm_fp_model, current_fp_model): New variables.
+       (arm_get_fp_model): New function.
+       (arm_set_fp): New function.
+       (set_fp_model_sfunc): New function.
+       (show_fp_model): New function.
+       (_initialize_arm_tdep): Add new command to set/show the FPU.
+       (arm_extract_return_value): Use arm_get_fp_model.
+       (arm_store_return_value): Likewise.
+       (arm_gdbarch_init): Default fpa model is softfpa.  Call arm_set_fp
+       to initialize the floating-point data types.
+       * arm-linux-tdep.c (arm_linux_init_abi): The default floating point
+       model is FPA.
+
 2003-03-22  Richard Earnshaw  <rearnsha@arm.com>
 
        * arm-tdep.c (show_arm_command): Don't print out help.  Instead, show
index 1ebe600191f1ff802fad110b36841867a71c1e3f..01b45f13f8968e06ff6205b4da170f11ff968c89 100644 (file)
@@ -525,6 +525,8 @@ arm_linux_init_abi (struct gdbarch_info info,
   tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
   tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint);
 
+  tdep->fp_model = ARM_FLOAT_FPA;
+
   tdep->jb_pc = ARM_LINUX_JB_PC;
   tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
 
index 53a36929147a3a6ee15355dc465313c029537ded..da60ade72ffb8f94553928fd711676e637d6411a 100644 (file)
@@ -103,6 +103,21 @@ static int arm_debug;
 static struct cmd_list_element *setarmcmdlist = NULL;
 static struct cmd_list_element *showarmcmdlist = NULL;
 
+/* The type of floating-point to use.  Keep this in sync with enum
+   arm_float_model, and the help string in _initialize_arm_tdep.  */
+static const char *fp_model_strings[] =
+{
+  "auto",
+  "softfpa",
+  "fpa",
+  "softvfp",
+  "vfp"
+};
+
+/* A variable that can be configured by the user.  */
+static enum arm_float_model arm_fp_model = ARM_FLOAT_AUTO;
+static const char *current_fp_model = "auto";
+
 /* Number of different reg name sets (options).  */
 static int num_disassembly_options;
 
@@ -2170,9 +2185,7 @@ arm_extract_return_value (struct type *type,
 
   if (TYPE_CODE_FLT == TYPE_CODE (type))
     {
-      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
-      switch (tdep->fp_model)
+      switch (arm_get_fp_model (current_gdbarch))
        {
        case ARM_FLOAT_FPA:
          {
@@ -2187,7 +2200,7 @@ arm_extract_return_value (struct type *type,
          }
          break;
 
-       case ARM_FLOAT_SOFT:
+       case ARM_FLOAT_SOFT_FPA:
        case ARM_FLOAT_SOFT_VFP:
          regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
          if (TYPE_LENGTH (type) > 4)
@@ -2365,10 +2378,9 @@ arm_store_return_value (struct type *type, struct regcache *regs,
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
-      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
       char buf[ARM_MAX_REGISTER_RAW_SIZE];
 
-      switch (tdep->fp_model)
+      switch (arm_get_fp_model (current_gdbarch))
        {
        case ARM_FLOAT_FPA:
 
@@ -2376,7 +2388,7 @@ arm_store_return_value (struct type *type, struct regcache *regs,
          regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
          break;
 
-       case ARM_FLOAT_SOFT:
+       case ARM_FLOAT_SOFT_FPA:
        case ARM_FLOAT_SOFT_VFP:
          regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
          if (TYPE_LENGTH (type) > 4)
@@ -2533,6 +2545,69 @@ show_arm_command (char *args, int from_tty)
   cmd_show_list (showarmcmdlist, from_tty, "");
 }
 
+enum arm_float_model
+arm_get_fp_model (struct gdbarch *gdbarch)
+{
+  if (arm_fp_model == ARM_FLOAT_AUTO)
+    return gdbarch_tdep (gdbarch)->fp_model;
+
+  return arm_fp_model;
+}
+
+static void
+arm_set_fp (struct gdbarch *gdbarch)
+{
+  enum arm_float_model fp_model = arm_get_fp_model (gdbarch);
+
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE 
+      && (fp_model == ARM_FLOAT_SOFT_FPA || fp_model == ARM_FLOAT_FPA))
+    {
+      set_gdbarch_double_format        (gdbarch,
+                                &floatformat_ieee_double_littlebyte_bigword);
+      set_gdbarch_long_double_format
+       (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
+    }
+  else
+    {
+      set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
+      set_gdbarch_long_double_format (gdbarch,
+                                     &floatformat_ieee_double_little);
+    }
+}
+
+static void
+set_fp_model_sfunc (char *args, int from_tty,
+                   struct cmd_list_element *c)
+{
+  enum arm_float_model fp_model;
+
+  for (fp_model = ARM_FLOAT_AUTO; fp_model != ARM_FLOAT_LAST; fp_model++)
+    if (strcmp (current_fp_model, fp_model_strings[fp_model]) == 0)
+      {
+       arm_fp_model = fp_model;
+       break;
+      }
+
+  if (fp_model == ARM_FLOAT_LAST)
+    internal_error (__FILE__, __LINE__, "Invalid fp model accepted: %s.",
+                   current_fp_model);
+
+  if (gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm)
+    arm_set_fp (current_gdbarch);
+}
+
+static void
+show_fp_model (char *args, int from_tty,
+              struct cmd_list_element *c)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  if (arm_fp_model == ARM_FLOAT_AUTO 
+      && gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm)
+    printf_filtered ("  - the default for the current ABI is \"%s\".\n",
+                    fp_model_strings[tdep->fp_model]);
+}
+
 /* If the user changes the register disassembly style used for info
    register and other commands, we have to also switch the style used
    in opcodes for disassembly output.  This function is run in the "set
@@ -2804,8 +2879,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      ready to unwind the PC first (see frame.c:get_prev_frame()).  */
   set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
 
-  /* This is the way it has always defaulted.  */
-  tdep->fp_model = ARM_FLOAT_FPA;
+  /* We used to default to FPA for generic ARM, but almost nobody uses that
+     now, and we now provide a way for the user to force the model.  So 
+     default to the most useful variant.  */
+  tdep->fp_model = ARM_FLOAT_SOFT_FPA;
 
   /* Breakpoints.  */
   switch (info.byte_order)
@@ -2953,20 +3030,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
     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);
-       }
+      arm_set_fp (gdbarch);
       break;
 
     default:
@@ -3103,6 +3167,7 @@ _initialize_arm_tdep (void)
                              valid_disassembly_styles, &disassembly_style,
                              helptext, &setarmcmdlist);
 
+  set_cmd_sfunc (new_set, set_disassembly_style_sfunc);
   add_show_from_set (new_set, &showarmcmdlist);
 
   add_setshow_cmd_full ("apcs32", no_class,
@@ -3122,6 +3187,19 @@ _initialize_arm_tdep (void)
                           NULL, NULL,
                           &setarmcmdlist, &showarmcmdlist);
 
+  /* Add a command to allow the user to force the FPU model.  */
+  new_set = add_set_enum_cmd
+    ("fpu", no_class, fp_model_strings, &current_fp_model,
+     "Set the floating point type.\n"
+     "auto - Determine the FP typefrom the OS-ABI.\n"
+     "softfpa - Software FP, mixed-endian doubles on little-endian ARMs.\n"
+     "fpa - FPA co-processor (GCC compiled).\n"
+     "softvfp - Software FP with pure-endian doubles.\n"
+     "vfp - VFP co-processor.",
+     &setarmcmdlist);
+  set_cmd_sfunc (new_set, set_fp_model_sfunc);
+  set_cmd_sfunc (add_show_from_set (new_set, &showarmcmdlist), show_fp_model);
+
   /* Add the deprecated "othernames" command.  */
   deprecate_cmd (add_com ("othernames", class_obscure, arm_othernames,
                          "Switch to the next set of register names."),
index b8c4711838ed477f47f70427c617cf725dd9721d..26f3a83a97379d5fb53f40dab0552cbd075215c7 100644 (file)
@@ -109,16 +109,24 @@ enum gdb_regnum {
    only generate 2 of those.  The third is APCS_FLOAT, where arguments to
    functions are passed in floating-point registers.  
 
-   In addition to the traditional models, VFP adds two more.  */
+   In addition to the traditional models, VFP adds two more. 
+
+   If you update this enum, don't forget to update fp_model_strings in 
+   arm-tdep.c.  */
 
 enum arm_float_model
 {
-  ARM_FLOAT_SOFT,
-  ARM_FLOAT_FPA,
-  ARM_FLOAT_SOFT_VFP,
-  ARM_FLOAT_VFP
+  ARM_FLOAT_AUTO,      /* Automatic detection.  Do not set in tdep.  */
+  ARM_FLOAT_SOFT_FPA,  /* Traditional soft-float (mixed-endian on LE ARM).  */
+  ARM_FLOAT_FPA,       /* FPA co-processor.  GCC calling convention.  */
+  ARM_FLOAT_SOFT_VFP,  /* Soft-float with pure-endian doubles.  */
+  ARM_FLOAT_VFP,       /* Full VFP calling convention.  */
+  ARM_FLOAT_LAST       /* Keep at end.  */
 };
 
+/* A method to the setting based on user's choice and ABI setting.  */
+enum arm_float_model arm_get_fp_model (struct gdbarch *);
+
 /* Target-dependent structure in gdbarch.  */
 struct gdbarch_tdep
 {