diff options
Diffstat (limited to 'src/arch/arm64.md')
-rw-r--r-- | src/arch/arm64.md | 137 |
1 files changed, 135 insertions, 2 deletions
diff --git a/src/arch/arm64.md b/src/arch/arm64.md index 2286bd8..605697f 100644 --- a/src/arch/arm64.md +++ b/src/arch/arm64.md @@ -5,6 +5,139 @@ keywords: arm64, aarch64, abi - ISA type: `RISC` - Endianness: `little`, `big` +## Registers +### General purpose registers +```markdown +bytes +[7:0] [3:0] desc +--------------------------------------------- +x0-x28 w0-w28 general purpose registers +x29 w29 frame pointer (FP) +x30 w30 link register (LR) +sp wsp stack pointer (SP) +pc program counter (PC) +xzr wzr zero register +``` +> Write to `wN` register clears upper 32bit. + +### Special registers per EL +```markdown +bytes +[7:0] desc +--------------------------------------------- +sp_el0 stack pointer EL0 + +sp_el1 stack pointer EL1 +elr_el1 exception link register EL1 +spsr_el1 saved process status register EL1 + +sp_el2 stack pointer EL2 +elr_el2 exception link register EL2 +spsr_el2 saved process status register EL2 + +sp_el3 stack pointer EL3 +elr_el3 exception link register EL3 +spsr_el3 saved process status register EL3 +``` + +## Addressing +### Offset +```armasm +ldr x0, [x1] // x0 = [x1] +ldr x0, [x1, 8] // x0 = [x1 + 8] +ldr x0, [x1, x2, lsl #3] // x0 = [x1 + (x2<<3)] +ldr x0, [x1, w2, stxw] // x0 = [x1 + sign_ext(w2)] +ldr x0, [x1, w2, stxw #3] // x0 = [x1 + (sign_ext(w2)<<3)] +``` +> Shift amount can either be `0` or `log2(access_size_bytes)`. Eg for 8byte +> access it can either be `{0, 3}`. + +### Index +```armasm +ldr x0, [x1, 8]! // pre-inc : x1+=8; x0 = [x1] +ldr x0, [x1], 8 // post-inc: x0 = [x1]; x1+=8 +``` + +### Pair access +```armasm +ldp x1, x2, [x0] // x1 = [x0]; x2 = [x0 + 8] +stp x1, x2, [x0] // [x0] = x1; [x0 + 8] = x2 +``` + +## Procedure Call Standard ARM64 ([`aapcs64`][aapcs64]) + +### Passing arguments to functions +- Integer/Pointer arguments + ```markdown + reg arg + ----------- + x0 1 + .. .. + x7 8 + ``` +- Additional arguments are passed on the stack. Arguments are pushed + `right-to-left (RTL)`, meaning next arguments are closer to current `sp`. + ```markdown + void take(..., int a9, int a10); + | | | ... | Hi + | +-->| a10 | | + +---------->| a9 | <-SP | + +-----+ v + | ... | Lo + ``` + +### Return values from functions +- Integer/Pointer return values + ```markdown + reg size + ----------------- + x0 64 bit + ``` + +### Callee saved registers +- `x19` - `x28` +- `SP` + +### Stack +- grows downwards +- `sp` must be 16byte aligned when used to access memory for r/w +- `sp` must be 16byte aligned on public interface interfaces + +### Frame chain +- linked list of stack-frames +- each frame links to the frame of its caller by a `frame record` + - a frame record is described as a `(FP,LR)` pair +- `x29 (FP)` must point to the frame record of the current stack-frame + ```markdown + +------+ Hi + | 0 | frame0 | + +->| 0 | | + | | ... | | + | +------+ | + | | LR | frame1 | + +--| FP |<-+ | + | ... | | | + +------+ | | + | LR | | current | + x29 ->| FP |--+ frame v + | ... | Lo + ``` +- end of the frame chain is indicated by following frame record `(0,-)` +- location of the frame record in the stack frame is not specified + +### Function prologue & epilogue +- prologue + ```armasm + sub sp, sp, 16 + stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30 + mov x29, sp // FP points to frame record + ``` +- epilogue + ```armasm + ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8] + add sp, sp, 16 + ret + ``` ## ASM skeleton Small assembler skeleton, ready to use with following properties: @@ -19,7 +152,7 @@ Small assembler skeleton, ready to use with following properties: .arch armv8-a .section .text, "ax", @progbits - .align 2 + .balign 4 // align code on 4byte boundary .global _start _start: mov x0, 2 // fd @@ -33,7 +166,7 @@ _start: mov w8, __NR_exit // exit(2) syscall svc 0 - .align 3 + .balign 8 // align data on 8byte boundary .section .rodata, "a", @progbits greeting: .asciz "Hi ASM-World!\n" |