root/lib/armutil/callfunc.S

/* [<][>][^][v][top][bottom][index][help] */
   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

/* [<][>][^][v][top][bottom][index][help] */