PageRenderTime 506ms CodeModel.GetById 221ms app.highlight 18ms RepoModel.GetById 264ms app.codeStats 0ms

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