diff options
author | mgretton <mgretton> | 2012-03-16 15:15:13 +0000 |
---|---|---|
committer | mgretton <mgretton> | 2012-03-16 15:15:13 +0000 |
commit | 9f872cfdb5867f4ea75fd529d6a69685e1154611 (patch) | |
tree | 78f52a53d0d70613ba60af28d495d8c06259a105 /bfd | |
parent | b114a782d4cbac9b6e9c84a071031e1402ffb5d7 (diff) | |
download | binutils-redhat-9f872cfdb5867f4ea75fd529d6a69685e1154611.tar.gz |
* 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.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf32-arm.c | 79 |
2 files changed, 63 insertions, 23 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f967d452d5..15819e6351 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2012-03-16 Matthew Gretton-Dann <matthew.gretton-dann@arm.com> + + * 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. + 2012-03-15 Roland McGrath <mcgrathr@google.com> * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Use 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: |