diff options
-rw-r--r-- | gas/ChangeLog | 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/gas/ChangeLog b/gas/ChangeLog index 691ba01..d0a8209 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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> diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index e4de83f..1bfe5b3 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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 }, diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi index 0b113f9..b5b9374 100644 --- a/gas/doc/c-arm.texi +++ b/gas/doc/c-arm.texi @@ -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. |