diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 538d83f5462..1721097cfca 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)