/Modules/_ctypes/libffi_arm_wince/sysv.asm

http://unladen-swallow.googlecode.com/ · Assembly · 228 lines · 99 code · 46 blank · 83 comment · 0 complexity · f2349a7d1d803cfb746229de0437ccdb MD5 · raw file

  1. ; -----------------------------------------------------------------------
  2. ; sysv.S - Copyright (c) 1998 Red Hat, Inc.
  3. ;
  4. ; ARM Foreign Function Interface
  5. ;
  6. ; Permission is hereby granted, free of charge, to any person obtaining
  7. ; a copy of this software and associated documentation files (the
  8. ; ``Software''), to deal in the Software without restriction, including
  9. ; without limitation the rights to use, copy, modify, merge, publish,
  10. ; distribute, sublicense, and/or sell copies of the Software, and to
  11. ; permit persons to whom the Software is furnished to do so, subject to
  12. ; the following conditions:
  13. ;
  14. ; The above copyright notice and this permission notice shall be included
  15. ; in all copies or substantial portions of the Software.
  16. ;
  17. ; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. ; OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. ; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. ; IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21. ; OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22. ; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. ; OTHER DEALINGS IN THE SOFTWARE.
  24. ; ----------------------------------------------------------------------- */
  25. ;#define LIBFFI_ASM
  26. ;#include <fficonfig.h>
  27. ;#include <ffi.h>
  28. ;#ifdef HAVE_MACHINE_ASM_H
  29. ;#include <machine/asm.h>
  30. ;#else
  31. ;#ifdef __USER_LABEL_PREFIX__
  32. ;#define CONCAT1(a, b) CONCAT2(a, b)
  33. ;#define CONCAT2(a, b) a ## b
  34. ;/* Use the right prefix for global labels. */
  35. ;#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
  36. ;#else
  37. ;#define CNAME(x) x
  38. ;#endif
  39. ;#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
  40. ;#endif
  41. FFI_TYPE_VOID EQU 0
  42. FFI_TYPE_INT EQU 1
  43. FFI_TYPE_FLOAT EQU 2
  44. FFI_TYPE_DOUBLE EQU 3
  45. ;FFI_TYPE_LONGDOUBLE EQU 4
  46. FFI_TYPE_UINT8 EQU 5
  47. FFI_TYPE_SINT8 EQU 6
  48. FFI_TYPE_UINT16 EQU 7
  49. FFI_TYPE_SINT16 EQU 8
  50. FFI_TYPE_UINT32 EQU 9
  51. FFI_TYPE_SINT32 EQU 10
  52. FFI_TYPE_UINT64 EQU 11
  53. FFI_TYPE_SINT64 EQU 12
  54. FFI_TYPE_STRUCT EQU 13
  55. FFI_TYPE_POINTER EQU 14
  56. ; WinCE always uses software floating point (I think)
  57. __SOFTFP__ EQU {TRUE}
  58. AREA |.text|, CODE, ARM ; .text
  59. ; a1: ffi_prep_args
  60. ; a2: &ecif
  61. ; a3: cif->bytes
  62. ; a4: fig->flags
  63. ; sp+0: ecif.rvalue
  64. ; sp+4: fn
  65. ; This assumes we are using gas.
  66. ;ENTRY(ffi_call_SYSV)
  67. EXPORT |ffi_call_SYSV|
  68. |ffi_call_SYSV| PROC
  69. ; Save registers
  70. stmfd sp!, {a1-a4, fp, lr}
  71. mov fp, sp
  72. ; Make room for all of the new args.
  73. sub sp, fp, a3
  74. ; Place all of the ffi_prep_args in position
  75. mov ip, a1
  76. mov a1, sp
  77. ; a2 already set
  78. ; And call
  79. mov lr, pc
  80. mov pc, ip
  81. ; move first 4 parameters in registers
  82. ldr a1, [sp, #0]
  83. ldr a2, [sp, #4]
  84. ldr a3, [sp, #8]
  85. ldr a4, [sp, #12]
  86. ; and adjust stack
  87. ldr ip, [fp, #8]
  88. cmp ip, #16
  89. movge ip, #16
  90. add sp, sp, ip
  91. ; call function
  92. mov lr, pc
  93. ldr pc, [fp, #28]
  94. ; Remove the space we pushed for the args
  95. mov sp, fp
  96. ; Load a3 with the pointer to storage for the return value
  97. ldr a3, [sp, #24]
  98. ; Load a4 with the return type code
  99. ldr a4, [sp, #12]
  100. ; If the return value pointer is NULL, assume no return value.
  101. cmp a3, #0
  102. beq call_epilogue
  103. ; return INT
  104. cmp a4, #FFI_TYPE_INT
  105. streq a1, [a3]
  106. beq call_epilogue
  107. ; return FLOAT
  108. cmp a4, #FFI_TYPE_FLOAT
  109. [ __SOFTFP__ ;ifdef __SOFTFP__
  110. streq a1, [a3]
  111. | ;else
  112. stfeqs f0, [a3]
  113. ] ;endif
  114. beq call_epilogue
  115. ; return DOUBLE or LONGDOUBLE
  116. cmp a4, #FFI_TYPE_DOUBLE
  117. [ __SOFTFP__ ;ifdef __SOFTFP__
  118. stmeqia a3, {a1, a2}
  119. | ;else
  120. stfeqd f0, [a3]
  121. ] ;endif
  122. beq call_epilogue
  123. ; return SINT64 or UINT64
  124. cmp a4, #FFI_TYPE_SINT64
  125. stmeqia a3, {a1, a2}
  126. call_epilogue
  127. ldmfd sp!, {a1-a4, fp, pc}
  128. ;.ffi_call_SYSV_end:
  129. ;.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
  130. ENDP
  131. RESERVE_RETURN EQU 16
  132. ; This function is called by the trampoline
  133. ; It is NOT callable from C
  134. ; ip = pointer to struct ffi_closure
  135. IMPORT |ffi_closure_SYSV_inner|
  136. EXPORT |ffi_closure_SYSV|
  137. |ffi_closure_SYSV| PROC
  138. ; Store the argument registers on the stack
  139. stmfd sp!, {a1-a4}
  140. ; Push the return address onto the stack
  141. stmfd sp!, {lr}
  142. mov a1, ip ; first arg = address of ffi_closure
  143. add a2, sp, #4 ; second arg = sp+4 (points to saved a1)
  144. ; Allocate space for a non-struct return value
  145. sub sp, sp, #RESERVE_RETURN
  146. mov a3, sp ; third arg = return value address
  147. ; static unsigned int
  148. ; ffi_closure_SYSV_inner (ffi_closure *closure, char *in_args, void *rvalue)
  149. bl ffi_closure_SYSV_inner
  150. ; a1 now contains the return type code
  151. ; At this point the return value is on the stack
  152. ; Transfer it to the correct registers if necessary
  153. ; return INT
  154. cmp a1, #FFI_TYPE_INT
  155. ldreq a1, [sp]
  156. beq closure_epilogue
  157. ; return FLOAT
  158. cmp a1, #FFI_TYPE_FLOAT
  159. [ __SOFTFP__ ;ifdef __SOFTFP__
  160. ldreq a1, [sp]
  161. | ;else
  162. stfeqs f0, [sp]
  163. ] ;endif
  164. beq closure_epilogue
  165. ; return DOUBLE or LONGDOUBLE
  166. cmp a1, #FFI_TYPE_DOUBLE
  167. [ __SOFTFP__ ;ifdef __SOFTFP__
  168. ldmeqia sp, {a1, a2}
  169. | ;else
  170. stfeqd f0, [sp]
  171. ] ;endif
  172. beq closure_epilogue
  173. ; return SINT64 or UINT64
  174. cmp a1, #FFI_TYPE_SINT64
  175. ldmeqia sp, {a1, a2}
  176. closure_epilogue
  177. add sp, sp, #RESERVE_RETURN ; remove return value buffer
  178. ldmfd sp!, {ip} ; ip = pop return address
  179. add sp, sp, #16 ; remove saved argument registers {a1-a4} from the stack
  180. mov pc, ip ; return
  181. ENDP ; ffi_closure_SYSV
  182. END