AArch64 supports PC-relative addressing (analogously called RIP-relative addressing in x86-64) through the
adr and
adrp instructions. There's a catch, however:
- adr has a range of only +/- 1 MiB
- adrp has a range of +/- 4 GiB, but only operates on page granularity (4 KiB)
This means that loading an arbitrary address generally requires at least two instructions: one for the page's base and one for the offset within that page.
For this purpose FPC's assembler provides two operand suffixes,
@PAGE and
@PAGEOFF, which split the operand's address into the relevant parts.
{$codealign constmin=16}
const
CArray: array [0..15] of Byte = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
asm
adrp x0, CArray@PAGE
ldr q0, [x0, CArray@PAGEOFF]
// ...
end;
Note that
q0 and the other vector registers can only be used in FPC versions that incorporate
this commit from October 15, 2020 since prior to it some register definitions in
compiler/aarch64/ra64num.inc were wrong (e.g.
q0's subtype was declared as
R_SUBQ when it should be
R_SUBMMWHOLE), leading to an internal error.
Unfortunately this commit didn't make it into any official release tag yet, so you'll have to use trunk if you want to use the 128-bit vector registers.