// vim:ft=arm64asm
// Startup code for QEMU virt machine (Cortex-A53)
.section .text.start, "ax", %progbits
.global start
.type start, %function
start:
// Disable all interrupts (DAIF = Debug, Async, IRQ, FIQ).
msr daifset, 0b1111
// Set up the kernel stack (SP_EL1).
// We start with SPSel=1 (using SP_EL1).
adrp x0, __kernel_stack_end__
add x0, x0, :lo12:__kernel_stack_end__
mov sp, x0
adrp x0, vector
add x0, x0, :lo12:vector
msr vbar_el1, x0
isb
bl init
// Copy .data section from ROM to RAM.
// Use callee-saved registers (x19/x20) for loop pointers since the
// init_array loop calls functions that may clobber volatile registers.
adrp x19, __copy_table__
add x19, x19, :lo12:__copy_table__
adrp x20, __copy_table_end__
add x20, x20, :lo12:__copy_table_end__
b 2f
0: ldp x0, x1, [x19], 16 // x0 = dest, x1 = src
ldr x2, [x19], 8 // x2 = size
cbz x2, 2f // skip if size is 0
1: ldr x3, [x1], 8
str x3, [x0], 8
subs x2, x2, 8
b.ne 1b
2: cmp x19, x20
b.ne 0b
// Zero .bss section.
adrp x19, __zero_table__
add x19, x19, :lo12:__zero_table__
adrp x20, __zero_table_end__
add x20, x20, :lo12:__zero_table_end__
b 2f
0: ldp x0, x1, [x19], 16 // x0 = start, x1 = size
cbz x1, 2f // skip if size is 0
1: str xzr, [x0], 8
subs x1, x1, 8
b.ne 1b
2: cmp x19, x20
b.ne 0b
// Call C++ constructors / init_array.
adrp x19, __init_array__
add x19, x19, :lo12:__init_array__
adrp x20, __init_array_end__
add x20, x20, :lo12:__init_array_end__
b 1f
0: ldr x0, [x19], 8
blr x0
1: cmp x19, x20
b.ne 0b
b rt_start
.size start, .-start