~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Modules/_ctypes/libffi/src/arm/ffi.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -----------------------------------------------------------------------
 
2
   ffi.c - Copyright (c) 1998, 2008  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,
 
18
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
19
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
20
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 
21
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
22
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
23
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
24
   DEALINGS IN THE SOFTWARE.
 
25
   ----------------------------------------------------------------------- */
 
26
 
 
27
#include <ffi.h>
 
28
#include <ffi_common.h>
 
29
 
 
30
#include <stdlib.h>
 
31
 
 
32
/* ffi_prep_args is called by the assembly routine once stack space
 
33
   has been allocated for the function's arguments */
 
34
 
 
35
void ffi_prep_args(char *stack, extended_cif *ecif)
 
36
{
 
37
  register unsigned int i;
 
38
  register void **p_argv;
 
39
  register char *argp;
 
40
  register ffi_type **p_arg;
 
41
 
 
42
  argp = stack;
 
43
 
 
44
  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
 
45
    *(void **) argp = ecif->rvalue;
 
46
    argp += 4;
 
47
  }
 
48
 
 
49
  p_argv = ecif->avalue;
 
50
 
 
51
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
 
52
       (i != 0);
 
53
       i--, p_arg++)
 
54
    {
 
55
      size_t z;
 
56
 
 
57
      /* Align if necessary */
 
58
      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
 
59
        argp = (char *) ALIGN(argp, (*p_arg)->alignment);
 
60
      }
 
61
 
 
62
      if ((*p_arg)->type == FFI_TYPE_STRUCT)
 
63
        argp = (char *) ALIGN(argp, 4);
 
64
 
 
65
          z = (*p_arg)->size;
 
66
          if (z < sizeof(int))
 
67
            {
 
68
              z = sizeof(int);
 
69
              switch ((*p_arg)->type)
 
70
                {
 
71
                case FFI_TYPE_SINT8:
 
72
                  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
 
73
                  break;
 
74
                  
 
75
                case FFI_TYPE_UINT8:
 
76
                  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
 
77
                  break;
 
78
                  
 
79
                case FFI_TYPE_SINT16:
 
80
                  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
 
81
                  break;
 
82
                  
 
83
                case FFI_TYPE_UINT16:
 
84
                  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
 
85
                  break;
 
86
                  
 
87
                case FFI_TYPE_STRUCT:
 
88
                  memcpy(argp, *p_argv, (*p_arg)->size);
 
89
                  break;
 
90
 
 
91
                default:
 
92
                  FFI_ASSERT(0);
 
93
                }
 
94
            }
 
95
          else if (z == sizeof(int))
 
96
            {
 
97
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
98
            }
 
99
          else
 
100
            {
 
101
              memcpy(argp, *p_argv, z);
 
102
            }
 
103
          p_argv++;
 
104
          argp += z;
 
105
    }
 
106
  
 
107
  return;
 
108
}
 
109
 
 
110
/* Perform machine dependent cif processing */
 
111
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 
112
{
 
113
  /* Round the stack up to a multiple of 8 bytes.  This isn't needed 
 
114
     everywhere, but it is on some platforms, and it doesn't harm anything
 
115
     when it isn't needed.  */
 
116
  cif->bytes = (cif->bytes + 7) & ~7;
 
117
 
 
118
  /* Set the return type flag */
 
119
  switch (cif->rtype->type)
 
120
    {
 
121
    case FFI_TYPE_VOID:
 
122
    case FFI_TYPE_FLOAT:
 
123
    case FFI_TYPE_DOUBLE:
 
124
      cif->flags = (unsigned) cif->rtype->type;
 
125
      break;
 
126
 
 
127
    case FFI_TYPE_SINT64:
 
128
    case FFI_TYPE_UINT64:
 
129
      cif->flags = (unsigned) FFI_TYPE_SINT64;
 
130
      break;
 
131
 
 
132
    case FFI_TYPE_STRUCT:
 
133
      if (cif->rtype->size <= 4)
 
134
        /* A Composite Type not larger than 4 bytes is returned in r0.  */
 
135
        cif->flags = (unsigned)FFI_TYPE_INT;
 
136
      else
 
137
        /* A Composite Type larger than 4 bytes, or whose size cannot
 
138
           be determined statically ... is stored in memory at an
 
139
           address passed [in r0].  */
 
140
        cif->flags = (unsigned)FFI_TYPE_STRUCT;
 
141
      break;
 
142
 
 
143
    default:
 
144
      cif->flags = FFI_TYPE_INT;
 
145
      break;
 
146
    }
 
147
 
 
148
  return FFI_OK;
 
149
}
 
150
 
 
151
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
 
152
                          unsigned, unsigned, unsigned *, void (*fn)(void));
 
153
 
 
154
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 
155
{
 
156
  extended_cif ecif;
 
157
 
 
158
  int small_struct = (cif->flags == FFI_TYPE_INT 
 
159
                      && cif->rtype->type == FFI_TYPE_STRUCT);
 
160
 
 
161
  ecif.cif = cif;
 
162
  ecif.avalue = avalue;
 
163
 
 
164
  unsigned int temp;
 
165
  
 
166
  /* If the return value is a struct and we don't have a return */
 
167
  /* value address then we need to make one                     */
 
168
 
 
169
  if ((rvalue == NULL) && 
 
170
      (cif->flags == FFI_TYPE_STRUCT))
 
171
    {
 
172
      ecif.rvalue = alloca(cif->rtype->size);
 
173
    }
 
174
  else if (small_struct)
 
175
    ecif.rvalue = &temp;
 
176
  else
 
177
    ecif.rvalue = rvalue;
 
178
 
 
179
  switch (cif->abi) 
 
180
    {
 
181
    case FFI_SYSV:
 
182
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
 
183
                    fn);
 
184
 
 
185
      break;
 
186
    default:
 
187
      FFI_ASSERT(0);
 
188
      break;
 
189
    }
 
190
  if (small_struct)
 
191
    memcpy (rvalue, &temp, cif->rtype->size);
 
192
}
 
193
 
 
194
/** private members **/
 
195
 
 
196
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
 
197
                                         void** args, ffi_cif* cif);
 
198
 
 
199
void ffi_closure_SYSV (ffi_closure *);
 
200
 
 
201
/* This function is jumped to by the trampoline */
 
202
 
 
203
unsigned int
 
204
ffi_closure_SYSV_inner (closure, respp, args)
 
205
     ffi_closure *closure;
 
206
     void **respp;
 
207
     void *args;
 
208
{
 
209
  // our various things...
 
210
  ffi_cif       *cif;
 
211
  void         **arg_area;
 
212
 
 
213
  cif         = closure->cif;
 
214
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
 
215
 
 
216
  /* this call will initialize ARG_AREA, such that each
 
217
   * element in that array points to the corresponding 
 
218
   * value on the stack; and if the function returns
 
219
   * a structure, it will re-set RESP to point to the
 
220
   * structure return address.  */
 
221
 
 
222
  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
 
223
 
 
224
  (closure->fun) (cif, *respp, arg_area, closure->user_data);
 
225
 
 
226
  return cif->flags;
 
227
}
 
228
 
 
229
/*@-exportheader@*/
 
230
static void 
 
231
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
 
232
                            void **avalue, ffi_cif *cif)
 
233
/*@=exportheader@*/
 
234
{
 
235
  register unsigned int i;
 
236
  register void **p_argv;
 
237
  register char *argp;
 
238
  register ffi_type **p_arg;
 
239
 
 
240
  argp = stack;
 
241
 
 
242
  if ( cif->flags == FFI_TYPE_STRUCT ) {
 
243
    *rvalue = *(void **) argp;
 
244
    argp += 4;
 
245
  }
 
246
 
 
247
  p_argv = avalue;
 
248
 
 
249
  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
 
250
    {
 
251
      size_t z;
 
252
 
 
253
      size_t alignment = (*p_arg)->alignment;
 
254
      if (alignment < 4)
 
255
        alignment = 4;
 
256
      /* Align if necessary */
 
257
      if ((alignment - 1) & (unsigned) argp) {
 
258
        argp = (char *) ALIGN(argp, alignment);
 
259
      }
 
260
 
 
261
      z = (*p_arg)->size;
 
262
 
 
263
      /* because we're little endian, this is what it turns into.   */
 
264
 
 
265
      *p_argv = (void*) argp;
 
266
 
 
267
      p_argv++;
 
268
      argp += z;
 
269
    }
 
270
  
 
271
  return;
 
272
}
 
273
 
 
274
/* How to make a trampoline.  */
 
275
 
 
276
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)                              \
 
277
({ unsigned char *__tramp = (unsigned char*)(TRAMP);                    \
 
278
   unsigned int  __fun = (unsigned int)(FUN);                           \
 
279
   unsigned int  __ctx = (unsigned int)(CTX);                           \
 
280
   *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */  \
 
281
   *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */        \
 
282
   *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */        \
 
283
   *(unsigned int*) &__tramp[12] = __ctx;                               \
 
284
   *(unsigned int*) &__tramp[16] = __fun;                               \
 
285
   __clear_cache((&__tramp[0]), (&__tramp[19]));                        \
 
286
 })
 
287
 
 
288
 
 
289
/* the cif must already be prep'ed */
 
290
 
 
291
ffi_status
 
292
ffi_prep_closure_loc (ffi_closure* closure,
 
293
                      ffi_cif* cif,
 
294
                      void (*fun)(ffi_cif*,void*,void**,void*),
 
295
                      void *user_data,
 
296
                      void *codeloc)
 
297
{
 
298
  FFI_ASSERT (cif->abi == FFI_SYSV);
 
299
 
 
300
  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
 
301
                       &ffi_closure_SYSV,  \
 
302
                       codeloc);
 
303
    
 
304
  closure->cif  = cif;
 
305
  closure->user_data = user_data;
 
306
  closure->fun  = fun;
 
307
 
 
308
  return FFI_OK;
 
309
}