diff options
author | Mark Shinwell <shinwell@codesourcery.com> | 2006-08-15 10:50:40 +0000 |
---|---|---|
committer | Mark Shinwell <shinwell@codesourcery.com> | 2006-08-15 10:50:40 +0000 |
commit | 7c4f72819a43e979428e80ce212c81428ef74db3 (patch) | |
tree | 867776dfde7b31e16e879409eedd269ce4083d4b | |
parent | c3df17c49e4bbfd9b77f5af33e62ff9e7e2b3256 (diff) | |
download | binutils-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.csl | 11 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 65 | ||||
-rw-r--r-- | gas/doc/c-arm.texi | 22 |
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. |