.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 # store function pointer for later mov x16, x0 mov x15, x1 # First, set up the fixed arguments # x8 = fixed arg count ldr x8, [x15, #0] # arg[0] cmp x8, #0 ble .iv.idone ldr x0, [x15, #48] # arg[1] cmp x8, #1 ble .iv.idone ldr x1, [x15, #56] # arg[2] cmp x8, #2 ble .iv.idone ldr x2, [x15, #64] # arg[3] cmp x8, #3 ble .iv.idone ldr x3, [x15, #72] # arg[4] cmp x8, #4 ble .iv.idone ldr x4, [x15, #80] # arg[5] cmp x8, #5 ble .iv.idone ldr x5, [x15, #88] # arg[6] cmp x8, #6 ble .iv.idone ldr x6, [x15, #96] # arg[7] cmp x8, #7 ble .iv.idone ldr x7, [x15, #104] .iv.idone: # Next, set up the fixed double arguments # x8 = fixed double arg count ldr x8, [x15, #8] # arg[0] cmp x8, #0 ble .iv.vdone ldr d0, [x15, #112] # arg[1] cmp x8, #1 ble .iv.vdone ldr d1, [x15, #120] # arg[2] cmp x8, #2 ble .iv.vdone ldr d2, [x15, #128] # arg[3] cmp x8, #3 ble .iv.vdone ldr d3, [x15, #136] # arg[4] cmp x8, #4 ble .iv.vdone ldr d4, [x15, #144] # arg[5] cmp x8, #5 ble .iv.vdone ldr d5, [x15, #152] # arg[6] cmp x8, #6 ble .iv.vdone ldr d6, [x15, #160] # arg[7] cmp x8, #7 ble .iv.vdone ldr d7, [x15, #168] .iv.vdone: # Finally, set up the variable arguments # x8 = excess arg count ldr x8, [x15, #32] # calculate the amount of stack space needed for the varargs mov x10, #0x10 mul x12, x8, x10 # x19 is caller-saved, and we'll need x12 later str x19, [sp, #-16]! mov x19, x12 # allocate the stack space sub sp, sp, x19 mov x13, sp # get a pointer to the end of the stack vararg buffer #mov x14, #8 #mul x14, x14, x11 #add x13, x13, x14 # x8: number of var args (decrements with every iteration) # x9: arg src buffer (increments with every iteration) # x13: var arg dest pointer (starts at the end, decrements with every iteration) ldr x9, [x15, #176] .iv.loop: cmp x8, #0 beq .iv.loop.end # read the arg value from the src pointer ldr x14, [x9] # write it to the stack, and increment the dest pointer str x14, [x13] add x13, x13, #8 # increment the src pointer, decrement the arg count sub x8, x8, #1 add x9, x9, #8 b .iv.loop .iv.loop.end: # call the function implementation blr x16 # de-allocate the stack varargs buffer (the size is now stored in x19) add sp, sp, x19 # restore the saved value of x19, ldr x19, [sp], #16 # restore the saved stack frame and link pointer ldp x29,x30, [sp], #16 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