This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] .savev6 directive for ARM


The FLDMX/FSTMX VFP multiple load/store instructions are deprecated as
of ARMv6 in favour of FLDMD and FSTMD.  The unwind opcodes corresponding
to FSTMD are different from those corresponding to FSTMX.

This patch provides a new gas directive .savev6 that can be used to
generate unwind information corresponding to the saving of VFP registers
with FSTMD.  It also works with VFPv3 registers saved with VSTM.
Assembly source using .save will still use the FSTMX-style unwind
opcodes; thus, backwards compatibility is maintained.

I've also corrected a typo in the example of .save in the manual, see
below.

Up my sleeve I have a gcc patch to go along with this that causes the
compiler to emit .savev6 directives and to no longer emit FLDMX and
FSTMX instructions -- along with the necessary unwinder support and a few
bugfixes in that area.  At the moment that requires this patch, so I'm
posting here first.

Tested for arm-none-linux-gnueabi.

OK?

Mark

--

gas/ChangeLog:

2006-06-20 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 "savev6" directive.
	* doc/c-arm.texi: Correct error in example for "save"
	directive (fstmdf -> fstmdx).  Also document "savev6" directive.

Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.250.2.16
diff -U3 -p -r1.250.2.16 tc-arm.c
--- gas/config/tc-arm.c	15 May 2006 20:46:24 -0000	1.250.2.16
+++ gas/config/tc-arm.c	20 Jun 2006 15:48:00 -0000
@@ -3271,7 +3271,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)
@@ -3509,10 +3559,11 @@ error:
 }
 
 
-/* Parse an unwind_save directive.  */
+/* Parse an unwind_save directive.
+   If the argument is non-zero, this is a .savev6 directive.  */
 
 static void
-s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
+s_arm_unwind_save (int arch_v6)
 {
   char *peek;
   struct reg_entry *reg;
@@ -3549,7 +3600,12 @@ s_arm_unwind_save (int ignored ATTRIBUTE
       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;
 
@@ -3856,6 +3912,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 },
+  { "savev6",		s_arm_unwind_save,	1 },
   { "movsp",		s_arm_unwind_movsp,	0 },
   { "pad",		s_arm_unwind_pad,	0 },
   { "setfp",		s_arm_unwind_setfp,	0 },
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.37.2.2
diff -U3 -p -r1.37.2.2 c-arm.texi
--- gas/doc/c-arm.texi	3 May 2006 16:13:43 -0000	1.37.2.2
+++ gas/doc/c-arm.texi	20 Jun 2006 15:48:01 -0000
@@ -535,7 +535,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]!
@@ -547,6 +547,26 @@ or
   wstrd wr10, [sp, #-8]!
 @end smallexample
 
+@cindex @code{.savev6} directive, ARM
+@item .savev6 @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}
+  .savev6 @{d8, d9, d10@}
+  fstmdd sp!, @{d8, d9, d10@}
+@exdent @emph{VFPv3 registers}
+  .savev6 @{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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]