~ubuntu-branches/ubuntu/lucid/gauche-c-wrapper/lucid

« back to all changes in this revision

Viewing changes to libffi/src/mips/ffi.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2008-04-07 09:15:03 UTC
  • Revision ID: james.westby@ubuntu.com-20080407091503-wu0h414koe95kj4i
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -----------------------------------------------------------------------
 
2
   ffi.c - Copyright (c) 1996 Red Hat, Inc.
 
3
   
 
4
   MIPS 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
 
 
26
#include <ffi.h>
 
27
#include <ffi_common.h>
 
28
 
 
29
#include <stdlib.h>
 
30
#include <sys/cachectl.h>
 
31
 
 
32
#if _MIPS_SIM == _ABIN32
 
33
#define FIX_ARGP \
 
34
FFI_ASSERT(argp <= &stack[bytes]); \
 
35
if (argp == &stack[bytes]) \
 
36
{ \
 
37
  argp = stack; \
 
38
  ffi_stop_here(); \
 
39
}
 
40
#else
 
41
#define FIX_ARGP 
 
42
#endif
 
43
 
 
44
 
 
45
/* ffi_prep_args is called by the assembly routine once stack space
 
46
   has been allocated for the function's arguments */
 
47
 
 
48
static void ffi_prep_args(char *stack, 
 
49
                          extended_cif *ecif,
 
50
                          int bytes,
 
51
                          int flags)
 
52
{
 
53
  int i;
 
54
  void **p_argv;
 
55
  char *argp;
 
56
  ffi_type **p_arg;
 
57
 
 
58
#if _MIPS_SIM == _ABIN32
 
59
  /* If more than 8 double words are used, the remainder go
 
60
     on the stack. We reorder stuff on the stack here to 
 
61
     support this easily. */
 
62
  if (bytes > 8 * sizeof(ffi_arg))
 
63
    argp = &stack[bytes - (8 * sizeof(ffi_arg))];
 
64
  else
 
65
    argp = stack;
 
66
#else
 
67
  argp = stack;
 
68
#endif
 
69
 
 
70
  memset(stack, 0, bytes);
 
71
 
 
72
#if _MIPS_SIM == _ABIN32
 
73
  if ( ecif->cif->rstruct_flag != 0 )
 
74
#else
 
75
  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
 
76
#endif  
 
77
    {
 
78
      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
 
79
      argp += sizeof(ffi_arg);
 
80
      FIX_ARGP;
 
81
    }
 
82
 
 
83
  p_argv = ecif->avalue;
 
84
 
 
85
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
 
86
    {
 
87
      size_t z;
 
88
      unsigned int a;
 
89
 
 
90
      /* Align if necessary.  */
 
91
      a = (*p_arg)->alignment;
 
92
      if (a < sizeof(ffi_arg))
 
93
        a = sizeof(ffi_arg);
 
94
      
 
95
      if ((a - 1) & (unsigned int) argp)
 
96
        {
 
97
          argp = (char *) ALIGN(argp, a);
 
98
          FIX_ARGP;
 
99
        }
 
100
 
 
101
      z = (*p_arg)->size;
 
102
      if (z <= sizeof(ffi_arg))
 
103
        {
 
104
          z = sizeof(ffi_arg);
 
105
 
 
106
          switch ((*p_arg)->type)
 
107
            {
 
108
              case FFI_TYPE_SINT8:
 
109
                *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
 
110
                break;
 
111
 
 
112
              case FFI_TYPE_UINT8:
 
113
                *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
 
114
                break;
 
115
                  
 
116
              case FFI_TYPE_SINT16:
 
117
                *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
 
118
                break;
 
119
                  
 
120
              case FFI_TYPE_UINT16:
 
121
                *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
 
122
                break;
 
123
                  
 
124
              case FFI_TYPE_SINT32:
 
125
                *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
 
126
                break;
 
127
                  
 
128
              case FFI_TYPE_UINT32:
 
129
              case FFI_TYPE_POINTER:
 
130
                *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
 
131
                break;
 
132
 
 
133
              /* This can only happen with 64bit slots.  */
 
134
              case FFI_TYPE_FLOAT:
 
135
                *(float *) argp = *(float *)(* p_argv);
 
136
                break;
 
137
 
 
138
              /* Handle small structures.  */
 
139
              case FFI_TYPE_STRUCT:
 
140
              default:
 
141
                memcpy(argp, *p_argv, (*p_arg)->size);
 
142
                break;
 
143
            }
 
144
        }
 
145
      else
 
146
        {
 
147
#if _MIPS_SIM == _ABIO32
 
148
          memcpy(argp, *p_argv, z);
 
149
#else
 
150
          {
 
151
            unsigned end = (unsigned) argp+z;
 
152
            unsigned cap = (unsigned) stack+bytes;
 
153
 
 
154
            /* Check if the data will fit within the register space.
 
155
               Handle it if it doesn't.  */
 
156
 
 
157
            if (end <= cap)
 
158
              memcpy(argp, *p_argv, z);
 
159
            else
 
160
              {
 
161
                unsigned portion = end - cap;
 
162
 
 
163
                memcpy(argp, *p_argv, portion);
 
164
                argp = stack;
 
165
                memcpy(argp,
 
166
                       (void*)((unsigned)(*p_argv)+portion), z - portion);
 
167
              }
 
168
          }
 
169
#endif
 
170
      }
 
171
      p_argv++;
 
172
      argp += z;
 
173
      FIX_ARGP;
 
174
    }
 
175
}
 
176
 
 
177
#if _MIPS_SIM == _ABIN32
 
178
 
 
179
/* The n32 spec says that if "a chunk consists solely of a double 
 
180
   float field (but not a double, which is part of a union), it
 
181
   is passed in a floating point register. Any other chunk is
 
182
   passed in an integer register". This code traverses structure
 
183
   definitions and generates the appropriate flags. */
 
184
 
 
185
unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
 
186
{
 
187
  unsigned flags = 0;
 
188
  unsigned index = 0;
 
189
 
 
190
  ffi_type *e;
 
191
 
 
192
  while (e = arg->elements[index])
 
193
    {
 
194
      if (e->type == FFI_TYPE_DOUBLE)
 
195
        {
 
196
          flags += (FFI_TYPE_DOUBLE << *shift);
 
197
          *shift += FFI_FLAG_BITS;
 
198
        }
 
199
      else if (e->type == FFI_TYPE_STRUCT)
 
200
          flags += calc_n32_struct_flags(e, shift);
 
201
      else
 
202
        *shift += FFI_FLAG_BITS;
 
203
 
 
204
      index++;
 
205
    }
 
206
 
 
207
  return flags;
 
208
}
 
209
 
 
210
unsigned calc_n32_return_struct_flags(ffi_type *arg)
 
211
{
 
212
  unsigned flags = 0;
 
213
  unsigned index = 0;
 
214
  unsigned small = FFI_TYPE_SMALLSTRUCT;
 
215
  ffi_type *e;
 
216
 
 
217
  /* Returning structures under n32 is a tricky thing.
 
218
     A struct with only one or two floating point fields 
 
219
     is returned in $f0 (and $f2 if necessary). Any other
 
220
     struct results at most 128 bits are returned in $2
 
221
     (the first 64 bits) and $3 (remainder, if necessary).
 
222
     Larger structs are handled normally. */
 
223
  
 
224
  if (arg->size > 16)
 
225
    return 0;
 
226
 
 
227
  if (arg->size > 8)
 
228
    small = FFI_TYPE_SMALLSTRUCT2;
 
229
 
 
230
  e = arg->elements[0];
 
231
  if (e->type == FFI_TYPE_DOUBLE)
 
232
    flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
 
233
  else if (e->type == FFI_TYPE_FLOAT)
 
234
    flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
 
235
 
 
236
  if (flags && (e = arg->elements[1]))
 
237
    {
 
238
      if (e->type == FFI_TYPE_DOUBLE)
 
239
        flags += FFI_TYPE_DOUBLE;
 
240
      else if (e->type == FFI_TYPE_FLOAT)
 
241
        flags += FFI_TYPE_FLOAT;
 
242
      else 
 
243
        return small;
 
244
 
 
245
      if (flags && (arg->elements[2]))
 
246
        {
 
247
          /* There are three arguments and the first two are 
 
248
             floats! This must be passed the old way. */
 
249
          return small;
 
250
        }
 
251
    }
 
252
  else
 
253
    if (!flags)
 
254
      return small;
 
255
 
 
256
  return flags;
 
257
}
 
258
 
 
259
#endif
 
260
 
 
261
/* Perform machine dependent cif processing */
 
262
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 
263
{
 
264
  cif->flags = 0;
 
265
 
 
266
#if _MIPS_SIM == _ABIO32
 
267
  /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
 
268
   * does not have special handling for floating point args.
 
269
   */
 
270
 
 
271
  if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
 
272
    {
 
273
      if (cif->nargs > 0)
 
274
        {
 
275
          switch ((cif->arg_types)[0]->type)
 
276
            {
 
277
            case FFI_TYPE_FLOAT:
 
278
            case FFI_TYPE_DOUBLE:
 
279
              cif->flags += (cif->arg_types)[0]->type;
 
280
              break;
 
281
              
 
282
            default:
 
283
              break;
 
284
            }
 
285
 
 
286
          if (cif->nargs > 1)
 
287
            {
 
288
              /* Only handle the second argument if the first
 
289
                 is a float or double. */
 
290
              if (cif->flags)
 
291
                {
 
292
                  switch ((cif->arg_types)[1]->type)
 
293
                    {
 
294
                    case FFI_TYPE_FLOAT:
 
295
                    case FFI_TYPE_DOUBLE:
 
296
                      cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
 
297
                      break;
 
298
                      
 
299
                    default:
 
300
                      break;
 
301
                    }
 
302
                }
 
303
            }
 
304
        }
 
305
    }
 
306
      
 
307
  /* Set the return type flag */
 
308
 
 
309
  if (cif->abi == FFI_O32_SOFT_FLOAT)
 
310
    {
 
311
      switch (cif->rtype->type)
 
312
        {
 
313
        case FFI_TYPE_VOID:
 
314
        case FFI_TYPE_STRUCT:
 
315
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
 
316
          break;
 
317
 
 
318
        case FFI_TYPE_SINT64:
 
319
        case FFI_TYPE_UINT64:
 
320
        case FFI_TYPE_DOUBLE:
 
321
          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
 
322
          break;
 
323
      
 
324
        case FFI_TYPE_FLOAT:
 
325
        default:
 
326
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
 
327
          break;
 
328
        }
 
329
    }
 
330
  else
 
331
    {
 
332
      /* FFI_O32 */      
 
333
      switch (cif->rtype->type)
 
334
        {
 
335
        case FFI_TYPE_VOID:
 
336
        case FFI_TYPE_STRUCT:
 
337
        case FFI_TYPE_FLOAT:
 
338
        case FFI_TYPE_DOUBLE:
 
339
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
 
340
          break;
 
341
 
 
342
        case FFI_TYPE_SINT64:
 
343
        case FFI_TYPE_UINT64:
 
344
          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
 
345
          break;
 
346
      
 
347
        default:
 
348
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
 
349
          break;
 
350
        }
 
351
    }
 
352
#endif
 
353
 
 
354
#if _MIPS_SIM == _ABIN32
 
355
  /* Set the flags necessary for N32 processing */
 
356
  {
 
357
    unsigned shift = 0;
 
358
    unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
 
359
    unsigned index = 0;
 
360
 
 
361
    unsigned struct_flags = 0;
 
362
 
 
363
    if (cif->rtype->type == FFI_TYPE_STRUCT)
 
364
      {
 
365
        struct_flags = calc_n32_return_struct_flags(cif->rtype);
 
366
 
 
367
        if (struct_flags == 0)
 
368
          {
 
369
            /* This means that the structure is being passed as
 
370
               a hidden argument */
 
371
 
 
372
            shift = FFI_FLAG_BITS;
 
373
            count = (cif->nargs < 7) ? cif->nargs : 7;
 
374
 
 
375
            cif->rstruct_flag = !0;
 
376
          }
 
377
        else
 
378
            cif->rstruct_flag = 0;
 
379
      }
 
380
    else
 
381
      cif->rstruct_flag = 0;
 
382
 
 
383
    while (count-- > 0)
 
384
      {
 
385
        switch ((cif->arg_types)[index]->type)
 
386
          {
 
387
          case FFI_TYPE_FLOAT:
 
388
          case FFI_TYPE_DOUBLE:
 
389
            cif->flags += ((cif->arg_types)[index]->type << shift);
 
390
            shift += FFI_FLAG_BITS;
 
391
            break;
 
392
 
 
393
          case FFI_TYPE_STRUCT:
 
394
            cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
 
395
                                                &shift);
 
396
            break;
 
397
 
 
398
          default:
 
399
            shift += FFI_FLAG_BITS;
 
400
          }
 
401
 
 
402
        index++;
 
403
      }
 
404
 
 
405
  /* Set the return type flag */
 
406
    switch (cif->rtype->type)
 
407
      {
 
408
      case FFI_TYPE_STRUCT:
 
409
        {
 
410
          if (struct_flags == 0)
 
411
            {
 
412
              /* The structure is returned through a hidden
 
413
                 first argument. Do nothing, 'cause FFI_TYPE_VOID 
 
414
                 is 0 */
 
415
            }
 
416
          else
 
417
            {
 
418
              /* The structure is returned via some tricky
 
419
                 mechanism */
 
420
              cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
 
421
              cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
 
422
            }
 
423
          break;
 
424
        }
 
425
      
 
426
      case FFI_TYPE_VOID:
 
427
        /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
 
428
        break;
 
429
        
 
430
      case FFI_TYPE_FLOAT:
 
431
      case FFI_TYPE_DOUBLE:
 
432
        cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
 
433
        break;
 
434
        
 
435
      default:
 
436
        cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
 
437
        break;
 
438
      }
 
439
  }
 
440
#endif
 
441
  
 
442
  return FFI_OK;
 
443
}
 
444
 
 
445
/* Low level routine for calling O32 functions */
 
446
extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
 
447
                        extended_cif *, unsigned, 
 
448
                        unsigned, unsigned *, void (*)());
 
449
 
 
450
/* Low level routine for calling N32 functions */
 
451
extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
 
452
                        extended_cif *, unsigned, 
 
453
                        unsigned, unsigned *, void (*)());
 
454
 
 
455
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
 
456
{
 
457
  extended_cif ecif;
 
458
 
 
459
  ecif.cif = cif;
 
460
  ecif.avalue = avalue;
 
461
  
 
462
  /* If the return value is a struct and we don't have a return */
 
463
  /* value address then we need to make one                     */
 
464
  
 
465
  if ((rvalue == NULL) && 
 
466
      (cif->rtype->type == FFI_TYPE_STRUCT))
 
467
    ecif.rvalue = alloca(cif->rtype->size);
 
468
  else
 
469
    ecif.rvalue = rvalue;
 
470
    
 
471
  switch (cif->abi) 
 
472
    {
 
473
#if _MIPS_SIM == _ABIO32
 
474
    case FFI_O32:
 
475
    case FFI_O32_SOFT_FLOAT:
 
476
      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
 
477
                   cif->flags, ecif.rvalue, fn);
 
478
      break;
 
479
#endif
 
480
 
 
481
#if _MIPS_SIM == _ABIN32
 
482
    case FFI_N32:
 
483
      ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 
 
484
                   cif->flags, ecif.rvalue, fn);
 
485
      break;
 
486
#endif
 
487
 
 
488
    default:
 
489
      FFI_ASSERT(0);
 
490
      break;
 
491
    }
 
492
}
 
493
 
 
494
#if FFI_CLOSURES  /* N32 not implemented yet, FFI_CLOSURES not defined */
 
495
#if defined(FFI_MIPS_O32)
 
496
extern void ffi_closure_O32(void);
 
497
#endif /* FFI_MIPS_O32 */
 
498
 
 
499
ffi_status
 
500
ffi_prep_closure (ffi_closure *closure,
 
501
                  ffi_cif *cif,
 
502
                  void (*fun)(ffi_cif*,void*,void**,void*),
 
503
                  void *user_data)
 
504
{
 
505
  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
 
506
  unsigned int fn;
 
507
  unsigned int ctx = (unsigned int) closure;
 
508
 
 
509
#if defined(FFI_MIPS_O32)
 
510
  FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
 
511
  fn = (unsigned int) ffi_closure_O32;
 
512
#else /* FFI_MIPS_N32 */
 
513
  FFI_ASSERT(cif->abi == FFI_N32);
 
514
  FFI_ASSERT(!"not implemented");
 
515
#endif /* FFI_MIPS_O32 */
 
516
 
 
517
  tramp[0] = 0x3c190000 | (fn >> 16);     /* lui  $25,high(fn) */
 
518
  tramp[1] = 0x37390000 | (fn & 0xffff);  /* ori  $25,low(fn)  */
 
519
  tramp[2] = 0x3c080000 | (ctx >> 16);    /* lui  $8,high(ctx) */
 
520
  tramp[3] = 0x03200008;                  /* jr   $25          */
 
521
  tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori  $8,low(ctx)  */
 
522
 
 
523
  closure->cif = cif;
 
524
  closure->fun = fun;
 
525
  closure->user_data = user_data;
 
526
 
 
527
  /* XXX this is available on Linux, but anything else? */
 
528
  cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
 
529
 
 
530
  return FFI_OK;
 
531
}
 
532
 
 
533
/*
 
534
 * Decodes the arguments to a function, which will be stored on the
 
535
 * stack. AR is the pointer to the beginning of the integer arguments
 
536
 * (and, depending upon the arguments, some floating-point arguments
 
537
 * as well). FPR is a pointer to the area where floating point
 
538
 * registers have been saved, if any.
 
539
 *
 
540
 * RVALUE is the location where the function return value will be
 
541
 * stored. CLOSURE is the prepared closure to invoke.
 
542
 *
 
543
 * This function should only be called from assembly, which is in
 
544
 * turn called from a trampoline.
 
545
 *
 
546
 * Returns the function return type.
 
547
 *
 
548
 * Based on the similar routine for sparc.
 
549
 */
 
550
int
 
551
ffi_closure_mips_inner_O32 (ffi_closure *closure,
 
552
                            void *rvalue, ffi_arg *ar,
 
553
                            double *fpr)
 
554
{
 
555
  ffi_cif *cif;
 
556
  void **avaluep;
 
557
  ffi_arg *avalue;
 
558
  ffi_type **arg_types;
 
559
  int i, avn, argn, seen_int;
 
560
 
 
561
  cif = closure->cif;
 
562
  avalue = alloca (cif->nargs * sizeof (ffi_arg));
 
563
  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
 
564
 
 
565
  seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
 
566
  argn = 0;
 
567
 
 
568
  if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
 
569
    {
 
570
      rvalue = (void *) ar[0];
 
571
      argn = 1;
 
572
    }
 
573
 
 
574
  i = 0;
 
575
  avn = cif->nargs;
 
576
  arg_types = cif->arg_types;
 
577
 
 
578
  while (i < avn)
 
579
    {
 
580
      if (i < 2 && !seen_int &&
 
581
          (arg_types[i]->type == FFI_TYPE_FLOAT ||
 
582
           arg_types[i]->type == FFI_TYPE_DOUBLE))
 
583
        {
 
584
#ifdef __MIPSEB__
 
585
          if (arg_types[i]->type == FFI_TYPE_FLOAT)
 
586
            avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
 
587
          else
 
588
#endif
 
589
            avaluep[i] = (char *) &fpr[i];
 
590
        }
 
591
      else
 
592
        {
 
593
          if (arg_types[i]->alignment == 8 && (argn & 0x1))
 
594
            argn++;
 
595
          switch (arg_types[i]->type)
 
596
            {
 
597
              case FFI_TYPE_SINT8:
 
598
                avaluep[i] = &avalue[i];
 
599
                *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
 
600
                break;
 
601
 
 
602
              case FFI_TYPE_UINT8:
 
603
                avaluep[i] = &avalue[i];
 
604
                *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
 
605
                break;
 
606
                  
 
607
              case FFI_TYPE_SINT16:
 
608
                avaluep[i] = &avalue[i];
 
609
                *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
 
610
                break;
 
611
                  
 
612
              case FFI_TYPE_UINT16:
 
613
                avaluep[i] = &avalue[i];
 
614
                *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
 
615
                break;
 
616
 
 
617
              default:
 
618
                avaluep[i] = (char *) &ar[argn];
 
619
                break;
 
620
            }
 
621
          seen_int = 1;
 
622
        }
 
623
      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
 
624
      i++;
 
625
    }
 
626
 
 
627
  /* Invoke the closure. */
 
628
  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
 
629
 
 
630
  if (cif->abi == FFI_O32_SOFT_FLOAT)
 
631
    {
 
632
      switch (cif->rtype->type)
 
633
        {
 
634
        case FFI_TYPE_FLOAT:
 
635
          return FFI_TYPE_INT;
 
636
        case FFI_TYPE_DOUBLE:
 
637
          return FFI_TYPE_UINT64;
 
638
        default:
 
639
          return cif->rtype->type;
 
640
        }
 
641
    }
 
642
  else
 
643
    {
 
644
      return cif->rtype->type;
 
645
    }
 
646
}
 
647
 
 
648
#endif /* FFI_CLOSURES */