2026-05-04 16:33:16 +01:00
|
|
|
.global _callvm_invoke_i
|
|
|
|
|
.align 4
|
|
|
|
|
|
|
|
|
|
# x0 = (function ptr) impl
|
|
|
|
|
# x1 = (struct callvm) context
|
|
|
|
|
_callvm_invoke_i:
|
|
|
|
|
# save the stack frame and link pointer
|
|
|
|
|
stp x29, x30, [sp, #-16]!
|
|
|
|
|
mov x29, sp
|
|
|
|
|
|
2026-05-04 20:18:19 +01:00
|
|
|
# preserve callee-saved registers
|
|
|
|
|
stp x19, x20, [sp, #-16]!
|
2026-05-04 16:33:16 +01:00
|
|
|
|
2026-05-04 20:18:19 +01:00
|
|
|
# store function pointer and callvm context for later
|
|
|
|
|
mov x19, x0
|
|
|
|
|
mov x20, x1
|
2026-05-04 16:33:16 +01:00
|
|
|
|
2026-05-04 20:18:19 +01:00
|
|
|
# First, set up the variable arguments
|
2026-05-04 16:33:16 +01:00
|
|
|
|
2026-05-04 20:18:19 +01:00
|
|
|
### calculate the amount of stack space needed for the varargs
|
|
|
|
|
# store the original stack pointer, so it can be restored later
|
|
|
|
|
mov x0, sp
|
|
|
|
|
str x0, [sp, #-16]!
|
|
|
|
|
# x8 = excess arg count
|
|
|
|
|
ldr x8, [x20, #32]
|
|
|
|
|
# x8 = excess arg buffer size (8 bytes per value)
|
|
|
|
|
lsl x8, x8, #3
|
2026-05-04 16:33:16 +01:00
|
|
|
# allocate the stack space
|
2026-05-04 20:18:19 +01:00
|
|
|
sub sp, sp, x8
|
|
|
|
|
|
|
|
|
|
# re-align the stack, and take a pointer to the newly-allocated buffer
|
|
|
|
|
mov x0, sp
|
|
|
|
|
and x0, x0, #0xFFFFFFFFFFFFFFF0
|
|
|
|
|
mov sp, x0
|
|
|
|
|
|
|
|
|
|
ldr x1, [x20, #176]
|
|
|
|
|
mov x2, x8
|
|
|
|
|
|
|
|
|
|
# memcpy(stack vararg buffer, callvm excess buffer, arg size)
|
|
|
|
|
bl _memcpy
|
|
|
|
|
|
|
|
|
|
# Next, set up the fixed integer arguments
|
|
|
|
|
ldr x0, [x20, #48]
|
|
|
|
|
ldr x1, [x20, #56]
|
|
|
|
|
ldr x2, [x20, #64]
|
|
|
|
|
ldr x3, [x20, #72]
|
|
|
|
|
ldr x4, [x20, #80]
|
|
|
|
|
ldr x5, [x20, #88]
|
|
|
|
|
ldr x6, [x20, #96]
|
|
|
|
|
ldr x7, [x20, #104]
|
|
|
|
|
|
|
|
|
|
# Finally, set up the fixed double arguments
|
|
|
|
|
ldr d0, [x20, #112]
|
|
|
|
|
ldr d1, [x20, #120]
|
|
|
|
|
ldr d2, [x20, #128]
|
|
|
|
|
ldr d3, [x20, #136]
|
|
|
|
|
ldr d4, [x20, #144]
|
|
|
|
|
ldr d5, [x20, #152]
|
|
|
|
|
ldr d6, [x20, #160]
|
|
|
|
|
ldr d7, [x20, #168]
|
2026-05-04 16:33:16 +01:00
|
|
|
|
|
|
|
|
# call the function implementation
|
2026-05-04 20:18:19 +01:00
|
|
|
blr x19
|
2026-05-04 16:33:16 +01:00
|
|
|
|
2026-05-04 20:18:19 +01:00
|
|
|
# restore the saved stack pointer, and de-allocate the stack varargs buffer
|
|
|
|
|
ldr x9, [x29, #-32]
|
|
|
|
|
mov sp, x9
|
2026-05-04 16:33:16 +01:00
|
|
|
|
2026-05-04 20:18:19 +01:00
|
|
|
# restore callee-saved registers
|
|
|
|
|
ldp x19, x20, [sp], #16
|
2026-05-04 16:33:16 +01:00
|
|
|
|
|
|
|
|
# restore the saved stack frame and link pointer
|
2026-05-04 20:18:19 +01:00
|
|
|
ldp x29, x30, [sp], #16
|
2026-05-04 16:33:16 +01:00
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.global _callvm_invoke_d
|
|
|
|
|
.align 4
|
|
|
|
|
|
|
|
|
|
# x0 = (function ptr) impl
|
|
|
|
|
# x1 = (struct callvm) context
|
|
|
|
|
_callvm_invoke_d:
|
|
|
|
|
b _callvm_invoke_i
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.global _callvm_invoke_v
|
|
|
|
|
.align 4
|
|
|
|
|
|
|
|
|
|
# x0 = (function ptr) impl
|
|
|
|
|
# x1 = (struct callvm) context
|
|
|
|
|
_callvm_invoke_v:
|
|
|
|
|
b _callvm_invoke_i
|