From 9f872cfdb5867f4ea75fd529d6a69685e1154611 Mon Sep 17 00:00:00 2001 From: mgretton Date: Fri, 16 Mar 2012 15:15:13 +0000 Subject: * bfd/elf32-arm.c (elf32_arm_attributes_accept_div): New function. (elf32_arm_attributes_forbid_div): Likewise. (elf32_arm_merge_eabi_attributes): Correct handling of Tag_DIV_use. --- bfd/elf32-arm.c | 79 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 23 deletions(-) (limited to 'bfd/elf32-arm.c') diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 92315522cd..8721f949b0 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -11268,6 +11268,46 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out, #undef T } +/* Query attributes object to see if integer divide instructions may be + present in an object. */ +static bfd_boolean +elf32_arm_attributes_accept_div (const obj_attribute *attr) +{ + int arch = attr[Tag_CPU_arch].i; + int profile = attr[Tag_CPU_arch_profile].i; + + switch (attr[Tag_DIV_use].i) + { + case 0: + /* Integer divide allowed if instruction contained in archetecture. */ + if (arch == TAG_CPU_ARCH_V7 && (profile == 'R' || profile == 'M')) + return TRUE; + else if (arch >= TAG_CPU_ARCH_V7E_M) + return TRUE; + else + return FALSE; + + case 1: + /* Integer divide explicitly prohibited. */ + return FALSE; + + default: + /* Unrecognised case - treat as allowing divide everywhere. */ + case 2: + /* Integer divide allowed in ARM state. */ + return TRUE; + } +} + +/* Query attributes object to see if integer divide instructions are + forbidden to be in the object. This is not the inverse of + elf32_arm_attributes_accept_div. */ +static bfd_boolean +elf32_arm_attributes_forbid_div (const obj_attribute *attr) +{ + return attr[Tag_DIV_use].i == 1; +} + /* Merge EABI object attributes from IBFD into OBFD. Raise an error if there are conflicting attributes. */ @@ -11709,29 +11749,22 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) break; case Tag_DIV_use: - /* This tag is set to zero if we can use UDIV and SDIV in Thumb - mode on a v7-M or v7-R CPU; to one if we can not use UDIV or - SDIV at all; and to two if we can use UDIV or SDIV on a v7-A - CPU. We will merge as follows: If the input attribute's value - is one then the output attribute's value remains unchanged. If - the input attribute's value is zero or two then if the output - attribute's value is one the output value is set to the input - value, otherwise the output value must be the same as the - inputs. */ - if (in_attr[i].i != 1 && out_attr[i].i != 1) - { - if (in_attr[i].i != out_attr[i].i) - { - _bfd_error_handler - (_("DIV usage mismatch between %B and %B"), - ibfd, obfd); - result = FALSE; - } - } - - if (in_attr[i].i != 1) - out_attr[i].i = in_attr[i].i; - + /* A value of zero on input means that the divide instruction may + be used if available in the base architecture as specified via + Tag_CPU_arch and Tag_CPU_arch_profile. A value of 1 means that + the user did not want divide instructions. A value of 2 + explicitly means that divide instructions were allowed in ARM + and Thumb state. */ + if (in_attr[i].i == out_attr[i].i) + /* Do nothing. */ ; + else if (elf32_arm_attributes_forbid_div (in_attr) + && !elf32_arm_attributes_accept_div (out_attr)) + out_attr[i].i = 1; + else if (elf32_arm_attributes_forbid_div (out_attr) + && elf32_arm_attributes_accept_div (in_attr)) + out_attr[i].i = in_attr[i].i; + else if (in_attr[i].i == 2) + out_attr[i].i = in_attr[i].i; break; case Tag_MPextension_use_legacy: -- cgit v1.2.1