Recent

Author Topic: AArch64, load a constant to register  (Read 733 times)

LemonParty

  • Hero Member
  • *****
  • Posts: 519
AArch64, load a constant to register
« on: July 02, 2025, 07:32:49 pm »
Hello.
I have a constant:
Code: Pascal  [Select][+][-]
  1. const
  2.   CArray: array [0..15] of Byte = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
How do I load this constant into q0?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

Thaddy

  • Hero Member
  • *****
  • Posts: 19241
  • Glad to be alive.
Re: AArch64, load a constant to register
« Reply #1 on: July 03, 2025, 08:41:18 am »
Usually what I do is write it in pascal and compile with -a, the examine the  xx.s file to give me some idea on how the compiler handles this. Specifically for AARCH64 in which I am kind of a beginner.
This leads often to two options:
- compiler is fine. leave it alone and keep the pascal code
- (mainly double loads) I see room for improvement and optimize and test it.

Untested example from DeepSeek:
Code: Pascal  [Select][+][-]
  1. program LoadQ0Example;
  2. {$mode objfpc}
  3. {$asmmode advanced}
  4.  
  5. // Align to 16 bytes for optimal performance
  6. {$ALIGN 16}
  7. const
  8.   CArray: array [0..15] of Byte = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
  9.  
  10. // Another aligned array for verification
  11. {$ALIGN 16}
  12. var
  13.   VerifyArray: array [0..15] of Byte;
  14.  
  15. procedure LoadToQ0; assembler;
  16. asm
  17.   // Load array address into x0
  18.   ldr x0, =CArray                      //<---------
  19.  
  20.   // Load 16 bytes into q0
  21.   ldr q0, [x0]                          //<----------
  22.  
  23.   // Optional: Store back to VerifyArray for testing
  24.   ldr x1, =VerifyArray
  25.   str q0, [x1]
  26. end;
  27.  
  28. var
  29.   i: Integer;
  30. begin
  31.   LoadToQ0;
  32.  
  33.   // Verify the transfer
  34.   WriteLn('Contents of q0:');
  35.   for i := 0 to 15 do
  36.     Write(VerifyArray[i], ' ');
  37. end.
Looks OK. Let me know if it works. Will test later on a Raspberry Pi.
I added arrows to the 2 instructions you need and I know that part is correct.
« Last Edit: July 03, 2025, 09:16:13 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Khrys

  • Sr. Member
  • ****
  • Posts: 456
Re: AArch64, load a constant to register
« Reply #2 on: July 03, 2025, 09:37:38 am »
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.

Code: Pascal  [Select][+][-]
  1. {$codealign constmin=16}
  2.  
  3. const
  4.   CArray: array [0..15] of Byte = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
  5.  
  6. asm
  7.   adrp  x0, CArray@PAGE
  8.   ldr   q0, [x0, CArray@PAGEOFF]
  9.   // ...
  10. 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.

Thaddy

  • Hero Member
  • *****
  • Posts: 19241
  • Glad to be alive.
Re: AArch64, load a constant to register
« Reply #3 on: July 03, 2025, 10:21:01 am »
Luckily OP is using trunk/main according to his signature.
objects are fine constructs. You can even initialize them with constructors.

LemonParty

  • Hero Member
  • *****
  • Posts: 519
Re: AArch64, load a constant to register
« Reply #4 on: July 03, 2025, 02:34:25 pm »
@Thaddy, your code gives this error:
Quote
Fatal: Illegal character "'='"

@Khrys
Your code work. Thank you. What @PAGE and @PAGEOFF in your code mean?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

Thaddy

  • Hero Member
  • *****
  • Posts: 19241
  • Glad to be alive.
Re: AArch64, load a constant to register
« Reply #5 on: July 03, 2025, 03:59:35 pm »
Yes, that failed on the pseudo instruction =. Corrected:
Code: Pascal  [Select][+][-]
  1. program LoadQ0Example;
  2. {$mode objfpc}
  3. {$asmmode advanced}
  4.  
  5. // Align to 16 bytes for optimal performance
  6. {$ALIGN 16}
  7. const
  8.   CArray: array [0..15] of Byte = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
  9.  
  10. // Another aligned array for verification
  11. {$ALIGN 16}
  12. var
  13.   VerifyArray: array [0..15] of Byte;
  14.  
  15. procedure LoadToQ0; assembler; nostackframe;
  16. asm
  17.   // Load array address using adrp+add (position-independent)
  18.   adrp x0, CArray
  19.   add x0, x0, :lo12:CArray
  20.  
  21.   // Load 16 bytes into q0
  22.   ldr q0, [x0]
  23.  
  24.   // Optional: Store back to VerifyArray for testing
  25.   adrp x1, VerifyArray
  26.   add x1, x1, :lo12:VerifyArray
  27.   str q0, [x1]
  28. end;
  29.  
  30. var
  31.   i: Integer;
  32. begin
  33.   LoadToQ0;
  34.  
  35.   // Verify the transfer
  36.   WriteLn('Contents of q0:');
  37.   for i := 0 to 15 do
  38.     Write(VerifyArray[i], ' ');
  39.   WriteLn;
  40. end.
@Khrys is right.
« Last Edit: July 03, 2025, 04:03:54 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018