/Modules/_ctypes/libffi/src/m68k/ffi.c

http://unladen-swallow.googlecode.com/ · C · 278 lines · 213 code · 52 blank · 13 comment · 24 complexity · 8d851db95dfd81e850d6032b8e2b9060 MD5 · raw file

  1. /* -----------------------------------------------------------------------
  2. ffi.c
  3. m68k Foreign Function Interface
  4. ----------------------------------------------------------------------- */
  5. #include <ffi.h>
  6. #include <ffi_common.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <sys/syscall.h>
  10. #include <asm/cachectl.h>
  11. void ffi_call_SYSV (extended_cif *,
  12. unsigned, unsigned,
  13. void *, void (*fn) ());
  14. void *ffi_prep_args (void *stack, extended_cif *ecif);
  15. void ffi_closure_SYSV (ffi_closure *);
  16. void ffi_closure_struct_SYSV (ffi_closure *);
  17. unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
  18. void *resp, void *args);
  19. /* ffi_prep_args is called by the assembly routine once stack space has
  20. been allocated for the function's arguments. */
  21. void *
  22. ffi_prep_args (void *stack, extended_cif *ecif)
  23. {
  24. unsigned int i;
  25. void **p_argv;
  26. char *argp;
  27. ffi_type **p_arg;
  28. void *struct_value_ptr;
  29. argp = stack;
  30. if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
  31. && !ecif->cif->flags)
  32. struct_value_ptr = ecif->rvalue;
  33. else
  34. struct_value_ptr = NULL;
  35. p_argv = ecif->avalue;
  36. for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
  37. i != 0;
  38. i--, p_arg++)
  39. {
  40. size_t z;
  41. z = (*p_arg)->size;
  42. if (z < sizeof (int))
  43. {
  44. switch ((*p_arg)->type)
  45. {
  46. case FFI_TYPE_SINT8:
  47. *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
  48. break;
  49. case FFI_TYPE_UINT8:
  50. *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
  51. break;
  52. case FFI_TYPE_SINT16:
  53. *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
  54. break;
  55. case FFI_TYPE_UINT16:
  56. *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
  57. break;
  58. case FFI_TYPE_STRUCT:
  59. memcpy (argp + sizeof (int) - z, *p_argv, z);
  60. break;
  61. default:
  62. FFI_ASSERT (0);
  63. }
  64. z = sizeof (int);
  65. }
  66. else
  67. {
  68. memcpy (argp, *p_argv, z);
  69. /* Align if necessary. */
  70. if ((sizeof(int) - 1) & z)
  71. z = ALIGN(z, sizeof(int));
  72. }
  73. p_argv++;
  74. argp += z;
  75. }
  76. return struct_value_ptr;
  77. }
  78. #define CIF_FLAGS_INT 1
  79. #define CIF_FLAGS_DINT 2
  80. #define CIF_FLAGS_FLOAT 4
  81. #define CIF_FLAGS_DOUBLE 8
  82. #define CIF_FLAGS_LDOUBLE 16
  83. #define CIF_FLAGS_POINTER 32
  84. #define CIF_FLAGS_STRUCT1 64
  85. #define CIF_FLAGS_STRUCT2 128
  86. /* Perform machine dependent cif processing */
  87. ffi_status
  88. ffi_prep_cif_machdep (ffi_cif *cif)
  89. {
  90. /* Set the return type flag */
  91. switch (cif->rtype->type)
  92. {
  93. case FFI_TYPE_VOID:
  94. cif->flags = 0;
  95. break;
  96. case FFI_TYPE_STRUCT:
  97. switch (cif->rtype->size)
  98. {
  99. case 1:
  100. cif->flags = CIF_FLAGS_STRUCT1;
  101. break;
  102. case 2:
  103. cif->flags = CIF_FLAGS_STRUCT2;
  104. break;
  105. case 4:
  106. cif->flags = CIF_FLAGS_INT;
  107. break;
  108. case 8:
  109. cif->flags = CIF_FLAGS_DINT;
  110. break;
  111. default:
  112. cif->flags = 0;
  113. break;
  114. }
  115. break;
  116. case FFI_TYPE_FLOAT:
  117. cif->flags = CIF_FLAGS_FLOAT;
  118. break;
  119. case FFI_TYPE_DOUBLE:
  120. cif->flags = CIF_FLAGS_DOUBLE;
  121. break;
  122. case FFI_TYPE_LONGDOUBLE:
  123. cif->flags = CIF_FLAGS_LDOUBLE;
  124. break;
  125. case FFI_TYPE_POINTER:
  126. cif->flags = CIF_FLAGS_POINTER;
  127. break;
  128. case FFI_TYPE_SINT64:
  129. case FFI_TYPE_UINT64:
  130. cif->flags = CIF_FLAGS_DINT;
  131. break;
  132. default:
  133. cif->flags = CIF_FLAGS_INT;
  134. break;
  135. }
  136. return FFI_OK;
  137. }
  138. void
  139. ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
  140. {
  141. extended_cif ecif;
  142. ecif.cif = cif;
  143. ecif.avalue = avalue;
  144. /* If the return value is a struct and we don't have a return value
  145. address then we need to make one. */
  146. if (rvalue == NULL
  147. && cif->rtype->type == FFI_TYPE_STRUCT
  148. && cif->rtype->size > 8)
  149. ecif.rvalue = alloca (cif->rtype->size);
  150. else
  151. ecif.rvalue = rvalue;
  152. switch (cif->abi)
  153. {
  154. case FFI_SYSV:
  155. ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
  156. ecif.rvalue, fn);
  157. break;
  158. default:
  159. FFI_ASSERT (0);
  160. break;
  161. }
  162. }
  163. static void
  164. ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
  165. {
  166. unsigned int i;
  167. void **p_argv;
  168. char *argp;
  169. ffi_type **p_arg;
  170. argp = stack;
  171. p_argv = avalue;
  172. for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
  173. {
  174. size_t z;
  175. z = (*p_arg)->size;
  176. if (z <= 4)
  177. {
  178. *p_argv = (void *) (argp + 4 - z);
  179. z = 4;
  180. }
  181. else
  182. {
  183. *p_argv = (void *) argp;
  184. /* Align if necessary */
  185. if ((sizeof(int) - 1) & z)
  186. z = ALIGN(z, sizeof(int));
  187. }
  188. p_argv++;
  189. argp += z;
  190. }
  191. }
  192. unsigned int
  193. ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
  194. {
  195. ffi_cif *cif;
  196. void **arg_area;
  197. cif = closure->cif;
  198. arg_area = (void**) alloca (cif->nargs * sizeof (void *));
  199. ffi_prep_incoming_args_SYSV(args, arg_area, cif);
  200. (closure->fun) (cif, resp, arg_area, closure->user_data);
  201. return cif->flags;
  202. }
  203. ffi_status
  204. ffi_prep_closure_loc (ffi_closure* closure,
  205. ffi_cif* cif,
  206. void (*fun)(ffi_cif*,void*,void**,void*),
  207. void *user_data,
  208. void *codeloc)
  209. {
  210. FFI_ASSERT (cif->abi == FFI_SYSV);
  211. *(unsigned short *)closure->tramp = 0x207c;
  212. *(void **)(closure->tramp + 2) = codeloc;
  213. *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
  214. if (cif->rtype->type == FFI_TYPE_STRUCT
  215. && !cif->flags)
  216. *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
  217. else
  218. *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
  219. syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
  220. FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
  221. closure->cif = cif;
  222. closure->user_data = user_data;
  223. closure->fun = fun;
  224. return FFI_OK;
  225. }