diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index 2e1ba268170c1..c23ccbafa3123 100644 --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -100,6 +100,10 @@ RelExpr ARM::getRelExpr(RelType type, const Symbol &s, case R_ARM_MOVT_ABS: case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_ALU_ABS_G0_NC: + case R_ARM_THM_ALU_ABS_G1_NC: + case R_ARM_THM_ALU_ABS_G2_NC: + case R_ARM_THM_ALU_ABS_G3: return R_ABS; case R_ARM_THM_JUMP8: case R_ARM_THM_JUMP11: @@ -681,6 +685,18 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { ((val << 4) & 0x7000) | // imm3 (val & 0x00ff)); // imm8 break; + case R_ARM_THM_ALU_ABS_G3: + write16(loc, (read16(loc) &~ 0x00ff) | ((val >> 24) & 0x00ff)); + break; + case R_ARM_THM_ALU_ABS_G2_NC: + write16(loc, (read16(loc) &~ 0x00ff) | ((val >> 16) & 0x00ff)); + break; + case R_ARM_THM_ALU_ABS_G1_NC: + write16(loc, (read16(loc) &~ 0x00ff) | ((val >> 8) & 0x00ff)); + break; + case R_ARM_THM_ALU_ABS_G0_NC: + write16(loc, (read16(loc) &~ 0x00ff) | (val & 0x00ff)); + break; case R_ARM_ALU_PC_G0: encodeAluGroup(loc, rel, val, 0, true); break; @@ -858,6 +874,11 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const { ((lo & 0x7000) >> 4) | // imm3 (lo & 0x00ff)); // imm8 } + case R_ARM_THM_ALU_ABS_G0_NC: + case R_ARM_THM_ALU_ABS_G1_NC: + case R_ARM_THM_ALU_ABS_G2_NC: + case R_ARM_THM_ALU_ABS_G3: + return read16(buf) & 0xff; case R_ARM_ALU_PC_G0: case R_ARM_ALU_PC_G0_NC: case R_ARM_ALU_PC_G1: diff --git a/lld/test/ELF/arm-thumb-alu.s b/lld/test/ELF/arm-thumb-alu.s new file mode 100644 index 0000000000000..d68900edc5c02 --- /dev/null +++ b/lld/test/ELF/arm-thumb-alu.s @@ -0,0 +1,114 @@ +// REQUIRES: arm + +// RUN: split-file %s %t +// RUN: llvm-mc -filetype=obj -triple=thumbv6m-unknown-linux-gnueabi %t/asm -o %t.o +// RUN: ld.lld --script %t/lds %t.o -o %t2 +// RUN: llvm-objdump -d %t2 --triple=thumbv6m-unknown-linux-gnueabi --no-show-raw-insn | FileCheck %s + +//--- lds +SECTIONS { + .tests 0x00001000 : AT(0x00001000) { *(.tests) } + .sym1 0x11223344 : AT(0x11223344) { *(.sym1) } + .sym2 0x00ffffff : AT(0x00ffffff) { *(.sym2) } + .fn 0x55667788 : AT(0x55667788) { *(.fn) } +} + +//--- asm + .section .tests, "ax", %progbits + +// CHECK-LABEL: : +// CHECK: adds r0, #0x44 +// CHECK-NEXT: movs r0, #0x44 +// CHECK-NEXT: movs r0, #0x45 +// CHECK-NEXT: movs r0, #0x43 +// CHECK-NEXT: movs r0, #0xff +// CHECK-NEXT: movs r0, #0x0 +// CHECK-NEXT: movs r0, #0xfe +// CHECK-NEXT: movs r0, #0x89 +// CHECK-NEXT: movs r0, #0x8b +R_ARM_THM_ALU_ABS_G0_NC: + adds r0, :lower0_7:sym1 + movs r0, :lower0_7:sym1 + movs r0, :lower0_7:sym1+1 + movs r0, :lower0_7:sym1+0xff + movs r0, :lower0_7:sym2 + movs r0, :lower0_7:sym2+1 + movs r0, :lower0_7:sym2+0xff + movs r0, :lower0_7:fn + movs r0, :lower0_7:fn+2 + +// CHECK-LABEL: : +// CHECK: adds r0, #0x33 +// CHECK-NEXT: movs r0, #0x33 +// CHECK-NEXT: movs r0, #0x33 +// CHECK-NEXT: movs r0, #0x34 +// CHECK-NEXT: movs r0, #0xff +// CHECK-NEXT: movs r0, #0x0 +// CHECK-NEXT: movs r0, #0x0 +// CHECK-NEXT: movs r0, #0x77 +// CHECK-NEXT: movs r0, #0x77 +R_ARM_THM_ALU_ABS_G1_NC: + adds r0, :lower8_15:sym1 + movs r0, :lower8_15:sym1 + movs r0, :lower8_15:sym1+1 + movs r0, :lower8_15:sym1+0xff + movs r0, :lower8_15:sym2 + movs r0, :lower8_15:sym2+1 + movs r0, :lower8_15:sym2+0xff + movs r0, :lower8_15:fn + movs r0, :lower8_15:fn+2 + +// CHECK-LABEL: : +// CHECK: adds r0, #0x22 +// CHECK-NEXT: movs r0, #0x22 +// CHECK-NEXT: movs r0, #0x22 +// CHECK-NEXT: movs r0, #0x22 +// CHECK-NEXT: movs r0, #0xff +// CHECK-NEXT: movs r0, #0x0 +// CHECK-NEXT: movs r0, #0x0 +// CHECK-NEXT: movs r0, #0x66 +// CHECK-NEXT: movs r0, #0x66 +R_ARM_THM_ALU_ABS_G2_NC: + adds r0, :upper0_7:sym1 + movs r0, :upper0_7:sym1 + movs r0, :upper0_7:sym1+1 + movs r0, :upper0_7:sym1+0xff + movs r0, :upper0_7:sym2 + movs r0, :upper0_7:sym2+1 + movs r0, :upper0_7:sym2+0xff + movs r0, :upper0_7:fn + movs r0, :upper0_7:fn+2 + +// CHECK-LABEL: : +// CHECK: adds r0, #0x11 +// CHECK-NEXT: movs r0, #0x11 +// CHECK-NEXT: movs r0, #0x11 +// CHECK-NEXT: movs r0, #0x11 +// CHECK-NEXT: movs r0, #0x0 +// CHECK-NEXT: movs r0, #0x1 +// CHECK-NEXT: movs r0, #0x1 +// CHECK-NEXT: movs r0, #0x55 +// CHECK-NEXT: movs r0, #0x55 +R_ARM_THM_ALU_ABS_G3: + adds r0, :upper8_15:sym1 + movs r0, :upper8_15:sym1 + movs r0, :upper8_15:sym1+1 + movs r0, :upper8_15:sym1+0xff + movs r0, :upper8_15:sym2 + movs r0, :upper8_15:sym2+1 + movs r0, :upper8_15:sym2+0xff + movs r0, :upper8_15:fn + movs r0, :upper8_15:fn+2 + + .section .sym1, "aw", %progbits +sym1: + .byte 0 + + .section .sym2, "aw", %progbits +sym2: + .byte 0 + + .section .fn, "ax", %progbits + .thumb_func +fn: + bx lr