/* https://cirosantilli.com/linux-kernel-module-cheat#arm-ldr-pseudo-instruction */ #include LKMC_PROLOGUE /* Mnemonic for a PC relative load: * * .... * ldr r0, [pc, offset] * r0 = myvar * .... */ ldr r0, myvar LKMC_ASSERT_EQ(r0, =0x12345678) /* Mnemonic PC relative load with an offset. * Load myvar2 instead of myvar. */ ldr r0, myvar + 4 LKMC_ASSERT_EQ(r0, =0x9ABCDEF0) /* First store the address in r0 using a magic =myvar, which creates * a new variable containing the address and PC-relative addresses it * https://stackoverflow.com/questions/17214962/what-is-the-difference-between-label-equals-sign-and-label-brackets-in-ar * * Use the adr instruction would likely be better for this application however. * * .... * r0 = &myvar * r1 = *r0 * .... */ ldr r0, =myvar ldr r1, [r0] LKMC_ASSERT_EQ(r1, =0x12345678) /* More efficiently, use r0 as the address to read, and write to r0 itself. */ ldr r0, =myvar ldr r0, [r0] LKMC_ASSERT_EQ(r0, =0x12345678) /* Same as =myvar but store a constant to a register. * Can also be done with movw and movt. */ ldr r0, =0x11112222 LKMC_ASSERT_EQ(r0, =0x11112222) /* We can also use GAS tolower16 and topper16 and movw and movt * to load the address of myvar into r0 with two immediates. * * This results in one extra 4 byte instruction read from memory, * and one less data read, so it is likely more cache efficient. * * https://sourceware.org/binutils/docs-2.19/as/ARM_002dRelocations.html */ movw r0, #:lower16:myvar movt r0, #:upper16:myvar ldr r1, [r0] LKMC_ASSERT_EQ(r1, =0x12345678) LKMC_EPILOGUE myvar: .word 0x12345678 myvar2: .word 0x9ABCDEF0