arm-thumb2-adr.s 4.88 KB
// REQUIRES: arm
// RUN: llvm-mc --triple=thumbv7m-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %s
// RUN: echo "SECTIONS { \
// RUN:                 .rodata.low 0x8012  : { *(.rodata.low) } \
// RUN:                 .text.low   0x8f00  : { *(.text.low) } \
// RUN:                 .text.neg   0x9000  : { *(.text.neg) } \
// RUN:                 .text.pos   0x10000 : { *(.text.pos) } \
// RUN:                 .text.high  0x10100 : { *(.text.high) } \
// RUN:                 .data_high  0x1100f : { *(.data.high) } \
// RUN:               } " > %t.script
// RUN: ld.lld --script %t.script %t.o -o %t
// RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=SYMS
// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7m-none-eabi %t | FileCheck %s

/// Test the various legal cases for the R_ARM_THM_ALU_PREL_11_0 relocation
/// Interesting things to note
/// Range is +- 4095 bytes
/// The expression is S + A - Pa where Pa is AlignDown(PC, 4) so we will use
/// 2-byte nops to make some of the adr psuedo instructions 2-byte aligned.
 .section .rodata.low, "a", %progbits
dat1:
 .byte 0
dat2:
 .byte 1
dat3:
 .byte 2
dat4:
 .byte 3

 .section .text.low, "ax", %progbits
 .balign 4
 .global target1
 .type target1, %function
target1:
 bx lr
 .type target2, %function
target2:
 bx lr

 .section .text.neg, "ax", %progbits
 .balign 4
 .global _start
 .thumb_func
_start:
 nop
///  adr.w r0, dat1
 .inst.w 0xf2af0004
 .reloc 2, R_ARM_THM_ALU_PREL_11_0, dat1
/// adr.w r1, dat2
 .inst.w 0xf2af0104
 .reloc 6, R_ARM_THM_ALU_PREL_11_0, dat2
 nop
/// adr.w r2, dat3
 .inst.w 0xf2af0204
 .reloc 0xc, R_ARM_THM_ALU_PREL_11_0, dat3
/// adr.w r3, dat4
 .inst.w 0xf2af0304
 .reloc 0x10, R_ARM_THM_ALU_PREL_11_0, dat4
/// adr.w r0, target1
 .inst.w 0xf2af0004
 .reloc 0x14, R_ARM_THM_ALU_PREL_11_0, target1
 nop
/// adr.w r1, target2
 .inst.w 0xf2af0104
 .reloc 0x1a, R_ARM_THM_ALU_PREL_11_0, target2
 .section .text.pos, "ax", %progbits
 .balign 4
 .global pos
 .thumb_func
pos:
/// adr.w r2, target3
 .inst.w 0xf2af0204
 .reloc 0, R_ARM_THM_ALU_PREL_11_0, target3
 nop
/// adr.w r3, target4
 .inst.w 0xf2af0304
 .reloc 6, R_ARM_THM_ALU_PREL_11_0, target4
 nop
/// adr.w r0, dat5
 .inst.w 0xf2af0004
 .reloc 0xc, R_ARM_THM_ALU_PREL_11_0, dat5
/// adr.w r1, dat6
 .inst.w 0xf2af0104
 .reloc 0x10, R_ARM_THM_ALU_PREL_11_0, dat6

 nop
/// adr.w r2, dat7
 .inst.w 0xf2af0204
 .reloc 0x16, R_ARM_THM_ALU_PREL_11_0, dat7

/// adr.w r3, dat8
 .inst.w 0xf2af0304
 .reloc 0x1a, R_ARM_THM_ALU_PREL_11_0, dat8
/// positive addend in instruction, all others are -4 (PC bias)
/// adr.w r4, dat5 + 8
 .inst.w 0xf20f0404
 .reloc 0x1e, R_ARM_THM_ALU_PREL_11_0, dat5 + 8

 .section .text.high, "ax", %progbits
 .balign 4
 .thumb_func
 .global target3
target3:
 bx lr
 .thumb_func
target4:
 bx lr

 .section .data.high, "aw", %progbits
dat5:
 .byte 0
dat6:
 .byte 1
dat7:
 .byte 2
dat8:
 .byte 3

// SYMS:     Name: dat1
// SYMS-NEXT:     Value: 0x8012
// SYMS:     Name: dat2
// SYMS-NEXT:     Value: 0x8013
// SYMS:     Name: dat3
// SYMS-NEXT:     Value: 0x8014
// SYMS:     Name: dat4
// SYMS-NEXT:     Value: 0x8015

// CHECK: 00008f00 <target1>:
// CHECK-NEXT:     8f00: bx      lr
// CHECK: 00008f02 <target2>:
// CHECK-NEXT:     8f02: bx      lr

// CHECK: 00009000 <_start>:
// CHECK-NEXT:     9000: nop
/// AlignDown(0x9002+4, 4) - 0xff2 = 0x8012
// CHECK-NEXT:     9002: adr.w   r0, #-4082
/// AlignDown(0x9006+4, 4) - 0xff5 = 0x8013
// CHECK-NEXT:     9006: adr.w   r1, #-4085
// CHECK-NEXT:     900a: nop
/// AlignDown(0x900c+4, 4) - 0xffc = 0x8014
// CHECK-NEXT:     900c: adr.w   r2, #-4092
/// AlignDown(0x9010+4, 4) - 0xfff = 0x8015
// CHECK-NEXT:     9010: adr.w   r3, #-4095
/// AlignDown(0x9014+4, 4) - 0x117 = 0x8f01
// CHECK-NEXT:     9014: adr.w   r0, #-279
// CHECK-NEXT:     9018: nop
/// AlignDown(0x901a+4, 4) - 0x119 = 0x8f03
// CHECK-NEXT:     901a: adr.w   r1, #-281

// CHECK: 00010000 <pos>:
/// AlignDown(0x10000+4, 4) + 0xfd = 0x10101
// CHECK-NEXT:    10000: adr.w   r2, #253
// CHECK-NEXT:    10004: nop
/// AlignDown(0x10006+4, 4) + 0xfb = 0x10103
// CHECK-NEXT:    10006: adr.w   r3, #251
// CHECK-NEXT:    1000a: nop
/// AlignDown(0x1000c+4, 4) + 0xfff = 0x1100f
// CHECK-NEXT:    1000c: adr.w   r0, #4095
/// AlignDown(0x10010+4, 4) + 0xffc = 0x11010
// CHECK-NEXT:    10010: adr.w   r1, #4092
// CHECK-NEXT:    10014: nop
/// AlignDown(0x10016+4, 4) + 0xff9 = 0x11011
// CHECK-NEXT:    10016: adr.w   r2, #4089
/// AlignDown(0x1001a+4, 4) + 0xff6 = 0x11012
// CHECK-NEXT:    1001a: adr.w   r3, #4086
/// AlignDown(0x1001e+4, 4) + 0xff7 = 0x11017 = dat5 + 8
// CHECK-NEXT:   1001e:  adr.w  r4, #4087

// CHECK: 00010100 <target3>:
// CHECK-NEXT:    10100: bx      lr

// CHECK: 00010102 <target4>:
// CHECK-NEXT:    10102: bx      lr

// SYMS:     Name: dat5
// SYMS-NEXT:     Value: 0x1100F
// SYMS:     Name: dat6
// SYMS-NEXT:     Value: 0x11010
// SYMS:     Name: dat7
// SYMS-NEXT:     Value: 0x11011
// SYMS:     Name: dat8
// SYMS-NEXT:     Value: 0x11012