.global _fx_function_invoke_i .align 4 # x0 = (function ptr) impl # x1 = (fx_value[]) args # x2 = (size_t) nr args _fx_function_invoke_i: # save the stack frame and link pointer stp x29, x30, [sp, #-16]! # store function pointer for later str x0, [sp, #-16]! # move arg array of of x1 and x2, so that they can be initialised for # the function call mov x8, x1 mov x9, x2 # arg[0] cmp x9, #0 ble .i.done ldr x0, [x8, #8] # arg[1] cmp x9, #1 ble .i.done ldr x1, [x8, #24] # arg[2] cmp x9, #2 ble .i.done ldr x2, [x8, #40] # arg[3] cmp x9, #3 ble .i.done ldr x3, [x8, #56] # arg[4] cmp x9, #4 ble .i.done ldr x4, [x8, #72] # arg[5] cmp x9, #5 ble .i.done ldr x5, [x8, #88] # arg[6] cmp x9, #6 ble .i.done ldr x6, [x8, #104] # arg[7] cmp x9, #7 ble .i.done ldr x7, [x8, #120] .i.done: ldr x8, [sp], #16 blr x8 # restore the saved stack frame and link pointer ldp x29,x30, [sp], #16 ret .global _fx_function_invoke_d .align 4 _fx_function_invoke_d: mov x0, 888 ret .global _fx_function_invoke_v .align 4 _fx_function_invoke_v: ret .global _fx_function_invoke_iv .align 4 # x0 = (function ptr) impl # x1 = (fx_value[]) args # x2 = (size_t) nr fixed args # x3 = (size_t) nr var args _fx_function_invoke_iv: # save the stack frame and link pointer stp x29, x30, [sp, #-16]! mov x29, sp # store function pointer for later mov x15, x0 # move arg array of of x1,x2,x3, so that they can be initialised for # the function call mov x9, x1 mov x10, x2 mov x11, x3 # First, set up the fixed arguments # arg[0] cmp x10, #0 ble .iv.done ldr x0, [x9, #8] add x9, x9, #16 # arg[1] cmp x10, #1 ble .iv.done ldr x1, [x9, #8] add x9, x9, #16 # arg[2] cmp x10, #2 ble .iv.done ldr x2, [x9, #8] add x9, x9, #16 # arg[3] cmp x10, #3 ble .iv.done ldr x3, [x9, #8] add x9, x9, #16 # arg[4] cmp x10, #4 ble .iv.done ldr x4, [x9, #8] add x9, x9, #16 # arg[5] cmp x10, #5 ble .iv.done ldr x5, [x9, #8] add x9, x9, #16 # arg[6] cmp x10, #6 ble .iv.done ldr x6, [x9, #8] add x9, x9, #16 # arg[7] cmp x10, #7 ble .iv.done ldr x7, [x9, #8] add x9, x9, #16 .iv.done: # Next, set up the variable arguments # calculate the amount of stack space needed for the varargs mov x10, #0x10 mul x12, x11, x10 #and x12, x12, #0x10 #mov x10, #0x10 #add x12, x12, 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 # x9: arg src buffer (starts at varargs, increments with every iteration) # x11: number of var args (decrements with every iteration) # x13: var arg dest pointer (starts at the end, decrements with every iteration) .iv.loop: cmp x11, #0 beq .iv.loop.end # read the arg value from the src pointer ldr x14, [x9, #8] # 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 x11, x11, #1 add x9, x9, #16 b .iv.loop .iv.loop.end: # call the function implementation blr x15 # 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 _fx_function_invoke_dv .align 4 _fx_function_invoke_dv: ret .global _fx_function_invoke_vv .align 4 _fx_function_invoke_vv: ret