summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Shinwell <shinwell@codesourcery.com>2006-08-15 10:50:40 +0000
committerMark Shinwell <shinwell@codesourcery.com>2006-08-15 10:50:40 +0000
commit7c4f72819a43e979428e80ce212c81428ef74db3 (patch)
tree867776dfde7b31e16e879409eedd269ce4083d4b
parentc3df17c49e4bbfd9b77f5af33e62ff9e7e2b3256 (diff)
downloadbinutils-gdb-7c4f72819a43e979428e80ce212c81428ef74db3.tar.gz
* 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.
-rw-r--r--ChangeLog.csl11
-rw-r--r--gas/config/tc-arm.c65
-rw-r--r--gas/doc/c-arm.texi22
3 files changed, 93 insertions, 5 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index f03e3fc70cd..2f23d4d4824 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,14 @@
+2006-08-15 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-08-03 Joseph Myers <joseph@codesourcery.com>
Backport from mainline.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 9f00ffaf0ac..31687ece6b0 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -3280,7 +3280,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)
@@ -3518,10 +3568,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;
@@ -3558,7 +3609,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;
@@ -3865,6 +3921,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 },
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index 941b1ee4c63..e2f1ce4b228 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -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{.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.