gas/
authorMark Shinwell <shinwell@codesourcery.com>
Wed, 21 Jun 2006 14:20:25 +0000 (14:20 +0000)
committerMark Shinwell <shinwell@codesourcery.com>
Wed, 21 Jun 2006 14:20:25 +0000 (14:20 +0000)
* config/tc-arm.c (s_arm_unwind_save_vfp_armv6): New.  Parse
a directive saving VFP registers for ARMv6 or later.
(s_arm_unwind_save): Add parameter arch_v6 and call
s_arm_unwind_save_vfp or s_arm_unwind_save_vfp_armv6 as
appropriate.
(md_pseudo_table): Add entry for new "vsave" directive.
* doc/c-arm.texi: Correct error in example for "save"
directive (fstmdf -> fstmdx).  Also document "vsave" directive.

gas/ChangeLog
gas/config/tc-arm.c
gas/doc/c-arm.texi

index 691ba01..d0a8209 100644 (file)
@@ -1,3 +1,14 @@
+2006-06-21  Mark Shinwell  <shinwell@codesourcery.com>
+
+       * config/tc-arm.c (s_arm_unwind_save_vfp_armv6): New.  Parse
+       a directive saving VFP registers for ARMv6 or later.
+       (s_arm_unwind_save): Add parameter arch_v6 and call
+       s_arm_unwind_save_vfp or s_arm_unwind_save_vfp_armv6 as
+       appropriate.
+       (md_pseudo_table): Add entry for new "vsave" directive.
+       * doc/c-arm.texi: Correct error in example for "save"
+       directive (fstmdf -> fstmdx).  Also document "vsave" directive.
+
 2006-18-06  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
            Anatoly Sokolov <aesok@post.ru>
 
index e4de83f..1bfe5b3 100644 (file)
@@ -3274,7 +3274,57 @@ s_arm_unwind_save_fpa (int reg)
 }
 
 
-/* Parse a directive saving VFP registers.  */
+/* Parse a directive saving VFP registers for ARMv6 and above.  */
+
+static void
+s_arm_unwind_save_vfp_armv6 (void)
+{
+  int count;
+  unsigned int start;
+  valueT op;
+  int num_vfpv3_regs = 0;
+  int num_regs_below_16;
+
+  count = parse_vfp_reg_list (&input_line_pointer, &start, REGLIST_VFP_D);
+  if (count == FAIL)
+    {
+      as_bad (_("expected register list"));
+      ignore_rest_of_line ();
+      return;
+    }
+
+  demand_empty_rest_of_line ();
+
+  /* We always generate FSTMD/FLDMD-style unwinding opcodes (rather
+     than FSTMX/FLDMX-style ones).  */
+
+  /* Generate opcode for (VFPv3) registers numbered in the range 16 .. 31.  */
+  if (start >= 16)
+    num_vfpv3_regs = count;
+  else if (start + count > 16)
+    num_vfpv3_regs = start + count - 16;
+
+  if (num_vfpv3_regs > 0)
+    {
+      int start_offset = start > 16 ? start - 16 : 0;
+      op = 0xc800 | (start_offset << 4) | (num_vfpv3_regs - 1);
+      add_unwind_opcode (op, 2);
+    }
+
+  /* Generate opcode for registers numbered in the range 0 .. 15.  */
+  num_regs_below_16 = num_vfpv3_regs > 0 ? 16 - (int) start : count;
+  assert (num_regs_below_16 + num_vfpv3_regs == count);
+  if (num_regs_below_16 > 0)
+    {
+      op = 0xc900 | (start << 4) | (num_regs_below_16 - 1);
+      add_unwind_opcode (op, 2);
+    }
+
+  unwind.frame_size += count * 8;
+}
+
+
+/* Parse a directive saving VFP registers for pre-ARMv6.  */
 
 static void
 s_arm_unwind_save_vfp (void)
@@ -3512,10 +3562,11 @@ error:
 }
 
 
-/* Parse an unwind_save directive.  */
+/* Parse an unwind_save directive.
+   If the argument is non-zero, this is a .vsave directive.  */
 
 static void
-s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
+s_arm_unwind_save (int arch_v6)
 {
   char *peek;
   struct reg_entry *reg;
@@ -3552,7 +3603,12 @@ s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
       return;
 
     case REG_TYPE_RN:    s_arm_unwind_save_core ();   return;
-    case REG_TYPE_VFD:    s_arm_unwind_save_vfp ();    return;
+    case REG_TYPE_VFD:
+      if (arch_v6)
+        s_arm_unwind_save_vfp_armv6 ();
+      else
+        s_arm_unwind_save_vfp ();
+      return;
     case REG_TYPE_MMXWR:  s_arm_unwind_save_mmxwr ();  return;
     case REG_TYPE_MMXWCG: s_arm_unwind_save_mmxwcg (); return;
 
@@ -3862,6 +3918,7 @@ const pseudo_typeS md_pseudo_table[] =
   { "personalityindex",        s_arm_unwind_personalityindex, 0 },
   { "handlerdata",     s_arm_unwind_handlerdata, 0 },
   { "save",            s_arm_unwind_save,      0 },
+  { "vsave",           s_arm_unwind_save,      1 },
   { "movsp",           s_arm_unwind_movsp,     0 },
   { "pad",             s_arm_unwind_pad,       0 },
   { "setfp",           s_arm_unwind_setfp,     0 },
index 0b113f9..b5b9374 100644 (file)
@@ -506,7 +506,7 @@ instruction.
   sfmfd f4, 2, [sp]!
 @exdent @emph{VFP registers}
   .save @{d8, d9, d10@}
-  fstmdf sp!, @{d8, d9, d10@}
+  fstmdx sp!, @{d8, d9, d10@}
 @exdent @emph{iWMMXt registers}
   .save @{wr10, wr11@}
   wstrd wr11, [sp, #-8]!
@@ -518,6 +518,26 @@ or
   wstrd wr10, [sp, #-8]!
 @end smallexample
 
+@cindex @code{.vsave} directive, ARM
+@item .vsave @var{vfp-reglist}
+Generate unwinder annotations to restore the VFP registers in @var{vfp-reglist}
+using FLDMD.  Also works for VFPv3 registers
+that are to be restored using VLDM.
+The format of @var{vfp-reglist} is the same as the corresponding store-multiple
+instruction.
+
+@smallexample
+@exdent @emph{VFP registers}
+  .vsave @{d8, d9, d10@}
+  fstmdd sp!, @{d8, d9, d10@}
+@exdent @emph{VFPv3 registers}
+  .vsave @{d15, d16, d17@}
+  vstm sp!, @{d15, d16, d17@}
+@end smallexample
+
+Since FLDMX and FSTMX are now deprecated, this directive should be
+used in favour of @code{.save} for saving VFP registers for ARMv6 and above.
+
 @cindex @code{.pad} directive, ARM
 @item .pad #@var{count}
 Generate unwinder annotations for a stack adjustment of @var{count} bytes.