aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-06-18 10:23:16 +0100
committerNick Clifton <nickc@redhat.com>2015-06-18 10:23:16 +0100
commitc12d2c9d48cf18d818f79b89bffda934c354fdac (patch)
treeff33a5f7012f0b0999a2710342a4d96d224d8457 /gas/config
parent75c11999673ba32027eb17f6df9c37904622ed24 (diff)
downloadbinutils-c12d2c9d48cf18d818f79b89bffda934c354fdac.zip
binutils-c12d2c9d48cf18d818f79b89bffda934c354fdac.tar.gz
binutils-c12d2c9d48cf18d818f79b89bffda934c354fdac.tar.bz2
Add support for using the ADR alias in Thumb mode against nearby symbols.
PR gas/18541 gas * config/tc-arm.c (md_apply_fix): Add support for ADR in thumb mode against a nearby symbol. tests * gas/arm/thumb.s: Add test of ADR against a nearby symbol. * gas/arm/thumb.d: Update expected output. * gas/arm/thumb-eabi.d: Likewise.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-arm.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 9ccee40..1793965 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -23158,6 +23158,45 @@ md_apply_fix (fixS * fixP,
}
else if (rs == REG_PC || rs == REG_SP)
{
+ /* PR gas/18541. If the addition is for a defined symbol
+ within range of an ADR instruction then accept it. */
+ if (subtract
+ && value == 4
+ && fixP->fx_addsy != NULL)
+ {
+ subtract = 0;
+
+ if (! S_IS_DEFINED (fixP->fx_addsy)
+ || S_GET_SEGMENT (fixP->fx_addsy) != seg
+ || S_IS_WEAK (fixP->fx_addsy))
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("address calculation needs a strongly defined nearby symbol"));
+ }
+ else
+ {
+ offsetT v = fixP->fx_where + fixP->fx_frag->fr_address;
+
+ /* Round up to the next 4-byte boundary. */
+ if (v & 3)
+ v = (v + 3) & ~ 3;
+ else
+ v += 4;
+ v = S_GET_VALUE (fixP->fx_addsy) - v;
+
+ if (v & ~0x3fc)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("symbol too far away"));
+ }
+ else
+ {
+ fixP->fx_done = 1;
+ value = v;
+ }
+ }
+ }
+
if (subtract || value & ~0x3fc)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("invalid immediate for address calculation (value = 0x%08lX)"),