1 /* 2 unsigned call_func_ptr(void *func, const unsigned *args, unsigned n_args) 3 call a function using arguments specified in a buffer 4 5 See 6 ARM IHI 0042D Procedure Call Standard for the ARM Architecture 7 ARM DUI 0056D ARM Developer Suite Developer Guide 8 for information on calling conventions 9 10 Note that the latter mentions different calling conventions for variadic and 11 standard functions, but gcc appears to use the variadic form for all C functions 12 13 WARNING: 14 NO effort is made to follow the rules for values larger than 32 bits as 15 either arguments or returns. Handling this is up to the caller. 16 17 Uses: 18 call ARM vararg functions from thumb 19 construct the argument list at runtime, i.e. for lua 20 call functions without a stub 21 22 func 23 Address of the function to call. This may be an ARM or Thumb function 24 25 args 26 Array of 32 bit words to be treated as arguments to the function. 27 Per the normal ARM calling convention, bytes or shorts should be promoted to 28 words before calling. 29 Ignored if n_args is 0 30 31 n_args 32 Number of elements in args 33 34 35 */ 36 .text 37 .global call_func_ptr 38 call_func_ptr: 39 PUSH {R4-R5,LR} 40 MOV R12, R0 // function to call 41 MOV R4, SP // save SP 42 43 ADD R5, R1, R2,LSL #2 // end = args + n_nargs*4 44 RSBS R0, R2, #4 // R0 = 4 - R2 45 BLO stack_setup 46 ADD PC, PC, R0,LSL #2 // skip over 4-n_args 47 NOP // reading PC adds +8 48 LDR R3, [R5,#-4]! // fourth arg 49 LDR R2, [R5,#-4]! // third arg 50 LDR R1, [R5,#-4]! // second arg 51 LDR R0, [R5,#-4]! // first arg 52 B do_call // regs done 53 54 stack_setup: 55 SUB R2, R2, #4 // number of stack args 56 SUB R2, R5, R2,LSL #2 // last = src - (n_stack_args)*4 57 58 stack_setup_loop: 59 LDR R0, [R5,#-4]! // t=*(--src) 60 STR R0, [SP,#-4]! // push t 61 CMP R5, R2 62 BNE stack_setup_loop // while (src != last) 63 64 LDMIA R1, {R0-R3} // if we had any stack args, need to load all 4 regs 65 66 do_call: 67 BLX R12 // call the function 68 MOV SP, R4 // clean up stack 69 POP {R4-R5,LR} 70 BX LR