aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-arm.c57
1 files changed, 17 insertions, 40 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 538d83f..1721097 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -4716,39 +4716,29 @@ s_arm_unwind_save_mmxwcg (void)
ignore_rest_of_line ();
}
+/* Convert range and mask_range into a sequence of s_arm_unwind_core
+ and s_arm_unwind_pseudo operations. We assume that mask_range will
+ not have consecutive bits set, or that one operation per bit is
+ acceptable. */
+
static void
s_arm_unwind_save_mixed (long range, long mask_range)
{
- const long roof = ((sizeof (long) * CHAR_BIT) - 1)
- - __builtin_clzl (mask_range);
-
- long subrange = 0;
- unsigned lim_lo = 0;
- unsigned lim_hi = 0;
-
- /* Iterate over pseudoregister to establish subrange bounds. */
- for (; lim_hi <= roof; lim_hi++)
+ while (mask_range)
{
- if (mask_range & (1 << lim_hi))
- {
- /* Once we know where to split our range, construct subrange. */
- for (unsigned n = lim_lo; n < lim_hi; n++)
- {
- if (range & (1 << n))
- subrange |= (1 << n);
- }
+ long mask_bit = mask_range & -mask_range;
+ long subrange = range & (mask_bit - 1);
- s_arm_unwind_save_core (subrange);
- s_arm_unwind_save_pseudo (1 << lim_hi);
+ if (subrange)
+ s_arm_unwind_save_core (subrange);
- subrange = 0;
- lim_lo = lim_hi + 1;
- }
+ s_arm_unwind_save_pseudo (mask_bit);
+ range &= ~subrange;
+ mask_range &= ~mask_bit;
}
- lim_lo = 0xffff << roof;
- subrange = range & lim_lo;
- s_arm_unwind_save_core (subrange);
+ if (range)
+ s_arm_unwind_save_core (range);
}
/* Parse an unwind_save directive.
@@ -4810,21 +4800,8 @@ s_arm_unwind_save (int arch_v6)
demand_empty_rest_of_line ();
- if (!mask_range)
- {
- s_arm_unwind_save_core (range);
- return;
- }
- else if (!range)
- {
- s_arm_unwind_save_pseudo (mask_range);
- return;
- }
- else
- {
- s_arm_unwind_save_mixed (range, mask_range);
- return;
- }
+ s_arm_unwind_save_mixed (range, mask_range);
+ return;
case REG_TYPE_VFD:
if (arch_v6)