gas/
* 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.
This commit is contained in:
parent
be2a5f717b
commit
fa073d6911
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue