Index: ELF/Arch/ARM.cpp =================================================================== --- ELF/Arch/ARM.cpp +++ ELF/Arch/ARM.cpp @@ -342,7 +342,7 @@ break; case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: - Range = 0x1000000; + Range = Config->ARMJ1J2BranchEncoding ? 0x1000000 : 0x400000; InstrSize = 2; break; default: @@ -447,11 +447,23 @@ } // Bit 12 is 0 for BLX, 1 for BL write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12); + if (!Config->ARMJ1J2BranchEncoding) { + // Older Arm architectures do not support R_ARM_THM_JUMP24 and have + // different encoding rules and range due to J1 and J2 always being 1. + checkInt(Loc, Val, 23, Type); + write16le(Loc, + 0xf000 | // opcode + ((Val >> 12) & 0x07ff)); // imm11 + write16le(Loc + 2, + (read16le(Loc + 2) & 0xd000) | // opcode + 0x2800 | // J1 == J2 == 1 + ((Val >> 1) & 0x07ff)); // imm11 + break; + } // Fall through as rest of encoding is the same as B.W LLVM_FALLTHROUGH; case R_ARM_THM_JUMP24: // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 - // FIXME: Use of I1 and I2 require v6T2ops checkInt(Loc, Val, 25, Type); write16le(Loc, 0xf000 | // opcode @@ -542,10 +554,19 @@ ((Lo & 0x07ff) << 1)); // imm11:0 } case R_ARM_THM_CALL: + if (!Config->ARMJ1J2BranchEncoding) { + // Older Arm architectures do not support R_ARM_THM_JUMP24 and have + // different encoding rules and range due to J1 and J2 always being 1. + uint16_t Hi = read16le(Buf); + uint16_t Lo = read16le(Buf + 2); + return SignExtend64<22>(((Hi & 0x7ff) << 12) | // imm11 + ((Lo & 0x7ff) << 1)); // imm11:0 + break; + } + LLVM_FALLTHROUGH; case R_ARM_THM_JUMP24: { // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S) - // FIXME: I1 and I2 require v6T2ops uint16_t Hi = read16le(Buf); uint16_t Lo = read16le(Buf + 2); return SignExtend64<24>(((Hi & 0x0400) << 14) | // S Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1504,9 +1504,6 @@ if (Config->ARMHasBlx == false) warn("lld uses blx instruction, no object with architecture supporting " "feature detected."); - if (Config->ARMJ1J2BranchEncoding == false) - warn("lld uses extended branch encoding, no object with architecture " - "supporting feature detected."); if (Config->ARMHasMovtMovw == false) warn("lld may use movt/movw, no object with architecture supporting " "feature detected."); Index: test/ELF/arm-bl-v6-inrange.s =================================================================== --- test/ELF/arm-bl-v6-inrange.s +++ test/ELF/arm-bl-v6-inrange.s @@ -0,0 +1,47 @@ +// REQUIRES: arm +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: .callee1 0x100004 : { *(.callee_low) } \ +// RUN: .caller 0x500000 : { *(.text) } \ +// RUN: .callee2 0x900004 : { *(.callee_high) } } " > %t.script +// RUN: ld.lld %t --script %t.script -o %t2 2>&1 +// RUN: llvm-objdump -d -triple=thumbv6-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-THUMB %s +// RUN: llvm-objdump -d -triple=armv6-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-ARM %s + +// On older Arm Architectures such as v5 and v6 the Thumb BL and BLX relocation +// uses a slightly different encoding that has a lower range. These relocations +// are at the extreme range of what is permitted. + .thumb + .text + .syntax unified + .cpu arm1176jzf-s + .globl _start + .type _start,%function +_start: + bl thumbfunc + bl armfunc + bx lr + + .section .callee_low, "ax", %progbits + .globl thumbfunc + .type thumbfunc, %function +thumbfunc: + bx lr +// CHECK-THUMB: Disassembly of section .callee1: +// CHECK-THUMB-NEXT: thumbfunc: +// CHECK-THUMB-NEXT: 100004: 70 47 bx lr +// CHECK-THUMB-NEXT: Disassembly of section .caller: +// CHECK-THUMB-NEXT: _start: +// CHECK-THUMB-NEXT: 500000: 00 f4 00 f8 bl #-4194304 +// CHECK-THUMB-NEXT: 500004: ff f3 fe ef blx #4194300 +// CHECK-THUMB-NEXT: 500008: 70 47 bx lr + + .arm + .section .callee_high, "ax", %progbits + .globl armfunc + .type armfunc, %function +armfunc: + bx lr +// CHECK-ARM: Disassembly of section .callee2: +// CHECK-ARM-NEXT: armfunc: +// CHECK-ARM-NEXT: 900004: 1e ff 2f e1 bx lr Index: test/ELF/arm-bl-v6.s =================================================================== --- test/ELF/arm-bl-v6.s +++ test/ELF/arm-bl-v6.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s // On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the @@ -9,14 +9,12 @@ // use these instructions either. At present we don't support v6 so we give a // warning for unsupported features. -// CHECK: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. -// CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected. +// CHECK: warning: lld may use movt/movw, no object with architecture supporting feature detected. // ARM v6 supports blx so we shouldn't see the blx not supported warning. // CHECK-NOT: warning: lld uses blx instruction, no object with architecture supporting feature detected. .text .syntax unified .cpu arm1176jzf-s - .eabi_attribute 6, 6 @ Tag_CPU_arch .globl _start .type _start,%function .balign 0x1000 Index: test/ELF/arm-blx-v4t.s =================================================================== --- test/ELF/arm-blx-v4t.s +++ test/ELF/arm-blx-v4t.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s // On Arm v4t there is no blx instruction so all interworking must go via @@ -7,13 +7,11 @@ // features. // CHECK: warning: lld uses blx instruction, no object with architecture supporting feature detected. -// CHECK-NEXT: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. // CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected. .text .syntax unified .cpu arm7tdmi - .eabi_attribute 6, 2 @ Tag_CPU_arch .arm .globl _start .type _start,%function Index: test/ELF/arm-thumb-branch.s =================================================================== --- test/ELF/arm-thumb-branch.s +++ test/ELF/arm-thumb-branch.s @@ -1,6 +1,6 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar // RUN: echo "SECTIONS { \ // RUN: . = 0xb4; \ // RUN: .callee1 : { *(.callee_low) } \ Index: test/ELF/arm-thumb-condbranch-thunk.s =================================================================== --- test/ELF/arm-thumb-condbranch-thunk.s +++ test/ELF/arm-thumb-condbranch-thunk.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // The output file is large, most of it zeroes. We dissassemble only the // parts we need to speed up the test and avoid a large output file Index: test/ELF/arm-thumb-mix-range-thunk-os.s =================================================================== --- test/ELF/arm-thumb-mix-range-thunk-os.s +++ test/ELF/arm-thumb-mix-range-thunk-os.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // The output file is large, most of it zeroes. We dissassemble only the // parts we need to speed up the test and avoid a large output file Index: test/ELF/arm-thumb-plt-range-thunk-os.s =================================================================== --- test/ELF/arm-thumb-plt-range-thunk-os.s +++ test/ELF/arm-thumb-plt-range-thunk-os.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t --shared --icf=all -o %t.so // The output file is large, most of it zeroes. We dissassemble only the // parts we need to speed up the test and avoid a large output file Index: test/ELF/arm-thumb-range-thunk-os.s =================================================================== --- test/ELF/arm-thumb-range-thunk-os.s +++ test/ELF/arm-thumb-range-thunk-os.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // The output file is large, most of it zeroes. We dissassemble only the // parts we need to speed up the test and avoid a large output file Index: test/ELF/arm-thumb-thunk-empty-pass.s =================================================================== --- test/ELF/arm-thumb-thunk-empty-pass.s +++ test/ELF/arm-thumb-thunk-empty-pass.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // RUN: llvm-objdump -d %t2 -start-address=69632 -stop-address=69646 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s // RUN: llvm-objdump -d %t2 -start-address=16846856 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s Index: test/ELF/arm-thunk-largesection.s =================================================================== --- test/ELF/arm-thunk-largesection.s +++ test/ELF/arm-thunk-largesection.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=69632 -stop-address=69636 %t2 | FileCheck -check-prefix=CHECK1 %s // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=73732 -stop-address=73742 %t2 | FileCheck -check-prefix=CHECK2 %s Index: test/ELF/arm-thunk-linkerscript-large.s =================================================================== --- test/ELF/arm-thunk-linkerscript-large.s +++ test/ELF/arm-thunk-linkerscript-large.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: echo "SECTIONS { \ // RUN: .text 0x100000 : { *(.text) } \ // RUN: .textl : { *(.text_l0*) *(.text_l1*) *(.text_l2*) *(.text_l3*) } \ @@ -21,7 +21,8 @@ // per OutputSection basis .syntax unified -// Define a function that we can match with .text_l* aligned on a megabyte // boundary +// Define a function that we can match with .text_l* aligned on a megabyte +// boundary .macro FUNCTIONL suff .section .text_l\suff\(), "ax", %progbits .thumb Index: test/ELF/arm-thunk-linkerscript-sort.s =================================================================== --- test/ELF/arm-thunk-linkerscript-sort.s +++ test/ELF/arm-thunk-linkerscript-sort.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: echo "SECTIONS { \ // RUN: .text 0x100000 : { *(SORT_BY_NAME(.text.*)) } \ // RUN: }" > %t.script Index: test/ELF/arm-thunk-multipass.s =================================================================== --- test/ELF/arm-thunk-multipass.s +++ test/ELF/arm-thunk-multipass.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 2>&1 // The output file is large, most of it zeroes. We dissassemble only the // parts we need to speed up the test and avoid a large output file