* 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.
This commit is contained in:
Matthew Gretton-Dann 2012-03-16 15:15:14 +00:00
parent 692392805b
commit ac56ee8f4c
2 changed files with 63 additions and 23 deletions

View File

@ -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> 2012-03-15 Roland McGrath <mcgrathr@google.com>
* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Use * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Use

View File

@ -11268,6 +11268,46 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
#undef T #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 /* Merge EABI object attributes from IBFD into OBFD. Raise an error if there
are conflicting attributes. */ are conflicting attributes. */
@ -11709,29 +11749,22 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
break; break;
case Tag_DIV_use: case Tag_DIV_use:
/* This tag is set to zero if we can use UDIV and SDIV in Thumb /* A value of zero on input means that the divide instruction may
mode on a v7-M or v7-R CPU; to one if we can not use UDIV or be used if available in the base architecture as specified via
SDIV at all; and to two if we can use UDIV or SDIV on a v7-A Tag_CPU_arch and Tag_CPU_arch_profile. A value of 1 means that
CPU. We will merge as follows: If the input attribute's value the user did not want divide instructions. A value of 2
is one then the output attribute's value remains unchanged. If explicitly means that divide instructions were allowed in ARM
the input attribute's value is zero or two then if the output and Thumb state. */
attribute's value is one the output value is set to the input if (in_attr[i].i == out_attr[i].i)
value, otherwise the output value must be the same as the /* Do nothing. */ ;
inputs. */ else if (elf32_arm_attributes_forbid_div (in_attr)
if (in_attr[i].i != 1 && out_attr[i].i != 1) && !elf32_arm_attributes_accept_div (out_attr))
{ out_attr[i].i = 1;
if (in_attr[i].i != out_attr[i].i) else if (elf32_arm_attributes_forbid_div (out_attr)
{ && elf32_arm_attributes_accept_div (in_attr))
_bfd_error_handler out_attr[i].i = in_attr[i].i;
(_("DIV usage mismatch between %B and %B"), else if (in_attr[i].i == 2)
ibfd, obfd); out_attr[i].i = in_attr[i].i;
result = FALSE;
}
}
if (in_attr[i].i != 1)
out_attr[i].i = in_attr[i].i;
break; break;
case Tag_MPextension_use_legacy: case Tag_MPextension_use_legacy: