From: Nick Clifton Date: Thu, 18 Jun 2015 09:23:16 +0000 (+0100) Subject: Add support for using the ADR alias in Thumb mode against nearby symbols. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c12d2c9d48cf18d818f79b89bffda934c354fdac;p=binutils-gdb.git 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 00305e96f7e..0a1326e4241 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2015-06-18 Nick Clifton + + PR gas/18541 + * config/tc-arm.c (md_apply_fix): Add support for ADR in thumb + mode against a nearby symbol. + 2015-06-18 Nick Clifton PR gas/18481 diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 9ccee400e8b..1793965785c 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)"), diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index d929e689bec..64e8cd7b18d 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-06-18 Nick Clifton + + PR gas/18541 + * 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. + 2015-06-18 Nick Clifton PR gas/18481 diff --git a/gas/testsuite/gas/arm/thumb-eabi.d b/gas/testsuite/gas/arm/thumb-eabi.d index 19fc7972ba0..afe076ba236 100644 --- a/gas/testsuite/gas/arm/thumb-eabi.d +++ b/gas/testsuite/gas/arm/thumb-eabi.d @@ -163,3 +163,8 @@ Disassembly of section \.text: 0+942 <[^>]+> 4801 ldr r0, \[pc, #4\] ; \(0+948 <[^>]+>\) 0+944 <[^>]+> 1c08 adds r0, r1, #0 0+946 <[^>]+> 46c0 nop ; \(mov r8, r8\) +0+948 <[^>]+> a001 add r0, pc, #4 ; \(adr r0, 00000950 <[^>]+>\) +0+94a <[^>]+> a001 add r0, pc, #4 ; \(adr r0, 00000950 <[^>]+>\) +0+94c <[^>]+> a000 add r0, pc, #0 ; \(adr r0, 00000950 <[^>]+>\) +0+94e <[^>]+> 46c0 nop ; \(mov r8, r8\) +#pass diff --git a/gas/testsuite/gas/arm/thumb.d b/gas/testsuite/gas/arm/thumb.d index c928aaff436..65d007adf69 100644 --- a/gas/testsuite/gas/arm/thumb.d +++ b/gas/testsuite/gas/arm/thumb.d @@ -163,3 +163,8 @@ Disassembly of section \.text: 0+942 <[^>]+> 4801 ldr r0, \[pc, #4\] ; \(0+948 <[^>]+>\) 0+944 <[^>]+> 1c08 adds r0, r1, #0 0+946 <[^>]+> 46c0 nop ; \(mov r8, r8\) +0+948 <[^>]+> a001 add r0, pc, #4 ; \(adr r0, 00000950 <[^>]+>\) +0+94a <[^>]+> a001 add r0, pc, #4 ; \(adr r0, 00000950 <[^>]+>\) +0+94c <[^>]+> a000 add r0, pc, #0 ; \(adr r0, 00000950 <[^>]+>\) +0+94e <[^>]+> 46c0 nop ; \(mov r8, r8\) +#pass diff --git a/gas/testsuite/gas/arm/thumb.s b/gas/testsuite/gas/arm/thumb.s index a044bdfca58..3c759b35fde 100644 --- a/gas/testsuite/gas/arm/thumb.s +++ b/gas/testsuite/gas/arm/thumb.s @@ -201,3 +201,13 @@ forwardonly: baz: mov r0, r1 nop + + adr r0, pr18541 + adr r0, pr18541 + adr r0, pr18541 + nop + .align + .global pr18541 +pr18541: + .long 0 +