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

« back to all changes in this revision

Viewing changes to libffi/src/sh/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) 2002, 2003, 2004, 2005 Kaz Kojima
 
3
   
 
4
   SuperH 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
 
 
31
#define NGREGARG 4
 
32
#if defined(__SH4__)
 
33
#define NFREGARG 8
 
34
#endif
 
35
 
 
36
#if defined(__HITACHI__)
 
37
#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
 
38
#else
 
39
#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
 
40
#endif
 
41
 
 
42
/* If the structure has essentialy an unique element, return its type.  */
 
43
static int
 
44
simple_type (ffi_type *arg)
 
45
{
 
46
  if (arg->type != FFI_TYPE_STRUCT)
 
47
    return arg->type;
 
48
  else if (arg->elements[1])
 
49
    return FFI_TYPE_STRUCT;
 
50
 
 
51
  return simple_type (arg->elements[0]);
 
52
}
 
53
 
 
54
static int
 
55
return_type (ffi_type *arg)
 
56
{
 
57
  unsigned short type;
 
58
 
 
59
  if (arg->type != FFI_TYPE_STRUCT)
 
60
    return arg->type;
 
61
 
 
62
  type = simple_type (arg->elements[0]);
 
63
  if (! arg->elements[1])
 
64
    {
 
65
      switch (type)
 
66
        {
 
67
        case FFI_TYPE_SINT8:
 
68
        case FFI_TYPE_UINT8:
 
69
        case FFI_TYPE_SINT16:
 
70
        case FFI_TYPE_UINT16:
 
71
        case FFI_TYPE_SINT32:
 
72
        case FFI_TYPE_UINT32:
 
73
          return FFI_TYPE_INT;
 
74
 
 
75
        default:
 
76
          return type;
 
77
        }
 
78
    }
 
79
 
 
80
  /* gcc uses r0/r1 pair for some kind of structures.  */
 
81
  if (arg->size <= 2 * sizeof (int))
 
82
    {
 
83
      int i = 0;
 
84
      ffi_type *e;
 
85
 
 
86
      while ((e = arg->elements[i++]))
 
87
        {
 
88
          type = simple_type (e);
 
89
          switch (type)
 
90
            {
 
91
            case FFI_TYPE_SINT32:
 
92
            case FFI_TYPE_UINT32:
 
93
            case FFI_TYPE_INT:
 
94
            case FFI_TYPE_FLOAT:
 
95
              return FFI_TYPE_UINT64;
 
96
 
 
97
            default:
 
98
              break;
 
99
            }
 
100
        }
 
101
    }
 
102
 
 
103
  return FFI_TYPE_STRUCT;
 
104
}
 
105
 
 
106
/* ffi_prep_args is called by the assembly routine once stack space
 
107
   has been allocated for the function's arguments */
 
108
 
 
109
/*@-exportheader@*/
 
110
void ffi_prep_args(char *stack, extended_cif *ecif)
 
111
/*@=exportheader@*/
 
112
{
 
113
  register unsigned int i;
 
114
  register int tmp;
 
115
  register unsigned int avn;
 
116
  register void **p_argv;
 
117
  register char *argp;
 
118
  register ffi_type **p_arg;
 
119
  int greg, ireg;
 
120
#if defined(__SH4__)
 
121
  int freg = 0;
 
122
#endif
 
123
 
 
124
  tmp = 0;
 
125
  argp = stack;
 
126
 
 
127
  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
 
128
    {
 
129
      *(void **) argp = ecif->rvalue;
 
130
      argp += 4;
 
131
      ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
 
132
    }
 
133
  else
 
134
    ireg = 0;
 
135
 
 
136
  /* Set arguments for registers.  */
 
137
  greg = ireg;
 
138
  avn = ecif->cif->nargs;
 
139
  p_argv = ecif->avalue;
 
140
 
 
141
  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
 
142
    {
 
143
      size_t z;
 
144
 
 
145
      z = (*p_arg)->size;
 
146
      if (z < sizeof(int))
 
147
        {
 
148
          if (greg++ >= NGREGARG)
 
149
            continue;
 
150
 
 
151
          z = sizeof(int);
 
152
          switch ((*p_arg)->type)
 
153
            {
 
154
            case FFI_TYPE_SINT8:
 
155
              *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
 
156
              break;
 
157
  
 
158
            case FFI_TYPE_UINT8:
 
159
              *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
 
160
              break;
 
161
  
 
162
            case FFI_TYPE_SINT16:
 
163
              *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
 
164
              break;
 
165
  
 
166
            case FFI_TYPE_UINT16:
 
167
              *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
 
168
              break;
 
169
  
 
170
            case FFI_TYPE_STRUCT:
 
171
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
172
              break;
 
173
 
 
174
            default:
 
175
              FFI_ASSERT(0);
 
176
            }
 
177
          argp += z;
 
178
        }
 
179
      else if (z == sizeof(int))
 
180
        {
 
181
#if defined(__SH4__)
 
182
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
 
183
            {
 
184
              if (freg++ >= NFREGARG)
 
185
                continue;
 
186
            }
 
187
          else
 
188
#endif
 
189
            {
 
190
              if (greg++ >= NGREGARG)
 
191
                continue;
 
192
            }
 
193
          *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
194
          argp += z;
 
195
        }
 
196
#if defined(__SH4__)
 
197
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
 
198
        {
 
199
          if (freg + 1 >= NFREGARG)
 
200
            continue;
 
201
          freg = (freg + 1) & ~1;
 
202
          freg += 2;
 
203
          memcpy (argp, *p_argv, z);
 
204
          argp += z;
 
205
        }
 
206
#endif
 
207
      else
 
208
        {
 
209
          int n = (z + sizeof (int) - 1) / sizeof (int);
 
210
#if defined(__SH4__)
 
211
          if (greg + n - 1 >= NGREGARG)
 
212
            continue;
 
213
#else
 
214
          if (greg >= NGREGARG)
 
215
            continue;
 
216
#endif
 
217
          greg += n;
 
218
          memcpy (argp, *p_argv, z);
 
219
          argp += n * sizeof (int);
 
220
        }
 
221
    }
 
222
 
 
223
  /* Set arguments on stack.  */
 
224
  greg = ireg;
 
225
#if defined(__SH4__)
 
226
  freg = 0;
 
227
#endif
 
228
  p_argv = ecif->avalue;
 
229
 
 
230
  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
 
231
    {
 
232
      size_t z;
 
233
 
 
234
      z = (*p_arg)->size;
 
235
      if (z < sizeof(int))
 
236
        {
 
237
          if (greg++ < NGREGARG)
 
238
            continue;
 
239
 
 
240
          z = sizeof(int);
 
241
          switch ((*p_arg)->type)
 
242
            {
 
243
            case FFI_TYPE_SINT8:
 
244
              *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
 
245
              break;
 
246
  
 
247
            case FFI_TYPE_UINT8:
 
248
              *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
 
249
              break;
 
250
  
 
251
            case FFI_TYPE_SINT16:
 
252
              *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
 
253
              break;
 
254
  
 
255
            case FFI_TYPE_UINT16:
 
256
              *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
 
257
              break;
 
258
  
 
259
            case FFI_TYPE_STRUCT:
 
260
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
261
              break;
 
262
 
 
263
            default:
 
264
              FFI_ASSERT(0);
 
265
            }
 
266
          argp += z;
 
267
        }
 
268
      else if (z == sizeof(int))
 
269
        {
 
270
#if defined(__SH4__)
 
271
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
 
272
            {
 
273
              if (freg++ < NFREGARG)
 
274
                continue;
 
275
            }
 
276
          else
 
277
#endif
 
278
            {
 
279
              if (greg++ < NGREGARG)
 
280
                continue;
 
281
            }
 
282
          *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
283
          argp += z;
 
284
        }
 
285
#if defined(__SH4__)
 
286
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
 
287
        {
 
288
          if (freg + 1 < NFREGARG)
 
289
            {
 
290
              freg = (freg + 1) & ~1;
 
291
              freg += 2;
 
292
              continue;
 
293
            }
 
294
          memcpy (argp, *p_argv, z);
 
295
          argp += z;
 
296
        }
 
297
#endif
 
298
      else
 
299
        {
 
300
          int n = (z + sizeof (int) - 1) / sizeof (int);
 
301
          if (greg + n - 1 < NGREGARG)
 
302
            {
 
303
              greg += n;
 
304
              continue;
 
305
            }
 
306
#if (! defined(__SH4__))
 
307
          else if (greg < NGREGARG)
 
308
            {
 
309
              greg = NGREGARG;
 
310
              continue;
 
311
            }
 
312
#endif
 
313
          memcpy (argp, *p_argv, z);
 
314
          argp += n * sizeof (int);
 
315
        }
 
316
    }
 
317
 
 
318
  return;
 
319
}
 
320
 
 
321
/* Perform machine dependent cif processing */
 
322
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 
323
{
 
324
  int i, j;
 
325
  int size, type;
 
326
  int n, m;
 
327
  int greg;
 
328
#if defined(__SH4__)
 
329
  int freg = 0;
 
330
#endif
 
331
 
 
332
  cif->flags = 0;
 
333
 
 
334
  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
 
335
          STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
 
336
 
 
337
#if defined(__SH4__)
 
338
  for (i = j = 0; i < cif->nargs && j < 12; i++)
 
339
    {
 
340
      type = (cif->arg_types)[i]->type;
 
341
      switch (type)
 
342
        {
 
343
        case FFI_TYPE_FLOAT:
 
344
          if (freg >= NFREGARG)
 
345
            continue;
 
346
          freg++;
 
347
          cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
 
348
          j++;
 
349
          break;
 
350
 
 
351
        case FFI_TYPE_DOUBLE:
 
352
          if ((freg + 1) >= NFREGARG)
 
353
            continue;
 
354
          freg = (freg + 1) & ~1;
 
355
          freg += 2;
 
356
          cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
 
357
          j++;
 
358
          break;
 
359
              
 
360
        default:
 
361
          size = (cif->arg_types)[i]->size;
 
362
          n = (size + sizeof (int) - 1) / sizeof (int);
 
363
          if (greg + n - 1 >= NGREGARG)
 
364
                continue;
 
365
          greg += n;
 
366
          for (m = 0; m < n; m++)
 
367
            cif->flags += FFI_TYPE_INT << (2 * j++);
 
368
          break;
 
369
        }
 
370
    }
 
371
#else
 
372
  for (i = j = 0; i < cif->nargs && j < 4; i++)
 
373
    {
 
374
      size = (cif->arg_types)[i]->size;
 
375
      n = (size + sizeof (int) - 1) / sizeof (int);
 
376
      if (greg >= NGREGARG)
 
377
        continue;
 
378
      else if (greg + n - 1 >= NGREGARG)
 
379
        n = NGREGARG - greg;
 
380
      greg += n;
 
381
      for (m = 0; m < n; m++)
 
382
        cif->flags += FFI_TYPE_INT << (2 * j++);
 
383
    }
 
384
#endif
 
385
 
 
386
  /* Set the return type flag */
 
387
  switch (cif->rtype->type)
 
388
    {
 
389
    case FFI_TYPE_STRUCT:
 
390
      cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
 
391
      break;
 
392
 
 
393
    case FFI_TYPE_VOID:
 
394
    case FFI_TYPE_FLOAT:
 
395
    case FFI_TYPE_DOUBLE:
 
396
    case FFI_TYPE_SINT64:
 
397
    case FFI_TYPE_UINT64:
 
398
      cif->flags += (unsigned) cif->rtype->type << 24;
 
399
      break;
 
400
 
 
401
    default:
 
402
      cif->flags += FFI_TYPE_INT << 24;
 
403
      break;
 
404
    }
 
405
 
 
406
  return FFI_OK;
 
407
}
 
408
 
 
409
/*@-declundef@*/
 
410
/*@-exportheader@*/
 
411
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
 
412
                          /*@out@*/ extended_cif *, 
 
413
                          unsigned, unsigned, 
 
414
                          /*@out@*/ unsigned *, 
 
415
                          void (*fn)());
 
416
/*@=declundef@*/
 
417
/*@=exportheader@*/
 
418
 
 
419
void ffi_call(/*@dependent@*/ ffi_cif *cif, 
 
420
              void (*fn)(), 
 
421
              /*@out@*/ void *rvalue, 
 
422
              /*@dependent@*/ void **avalue)
 
423
{
 
424
  extended_cif ecif;
 
425
  UINT64 trvalue;
 
426
 
 
427
  ecif.cif = cif;
 
428
  ecif.avalue = avalue;
 
429
  
 
430
  /* If the return value is a struct and we don't have a return */
 
431
  /* value address then we need to make one                     */
 
432
 
 
433
  if (cif->rtype->type == FFI_TYPE_STRUCT
 
434
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
 
435
    ecif.rvalue = &trvalue;
 
436
  else if ((rvalue == NULL) && 
 
437
      (cif->rtype->type == FFI_TYPE_STRUCT))
 
438
    {
 
439
      /*@-sysunrecog@*/
 
440
      ecif.rvalue = alloca(cif->rtype->size);
 
441
      /*@=sysunrecog@*/
 
442
    }
 
443
  else
 
444
    ecif.rvalue = rvalue;
 
445
 
 
446
  switch (cif->abi) 
 
447
    {
 
448
    case FFI_SYSV:
 
449
      /*@-usedef@*/
 
450
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
 
451
                    cif->flags, ecif.rvalue, fn);
 
452
      /*@=usedef@*/
 
453
      break;
 
454
    default:
 
455
      FFI_ASSERT(0);
 
456
      break;
 
457
    }
 
458
 
 
459
  if (rvalue
 
460
      && cif->rtype->type == FFI_TYPE_STRUCT
 
461
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
 
462
    memcpy (rvalue, &trvalue, cif->rtype->size);
 
463
}
 
464
 
 
465
extern void ffi_closure_SYSV (void);
 
466
#if defined(__SH4__)
 
467
extern void __ic_invalidate (void *line);
 
468
#endif
 
469
 
 
470
ffi_status
 
471
ffi_prep_closure (ffi_closure* closure,
 
472
                  ffi_cif* cif,
 
473
                  void (*fun)(ffi_cif*, void*, void**, void*),
 
474
                  void *user_data)
 
475
{
 
476
  unsigned int *tramp;
 
477
  unsigned short insn;
 
478
 
 
479
  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
 
480
 
 
481
  tramp = (unsigned int *) &closure->tramp[0];
 
482
  /* Set T bit if the function returns a struct pointed with R2.  */
 
483
  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
 
484
          ? 0x0018 /* sett */
 
485
          : 0x0008 /* clrt */);
 
486
 
 
487
#ifdef __LITTLE_ENDIAN__
 
488
  tramp[0] = 0xd301d102;
 
489
  tramp[1] = 0x0000412b | (insn << 16);
 
490
#else
 
491
  tramp[0] = 0xd102d301;
 
492
  tramp[1] = 0x412b0000 | insn;
 
493
#endif
 
494
  *(void **) &tramp[2] = (void *)closure;          /* ctx */
 
495
  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
 
496
 
 
497
  closure->cif = cif;
 
498
  closure->fun = fun;
 
499
  closure->user_data = user_data;
 
500
 
 
501
#if defined(__SH4__)
 
502
  /* Flush the icache.  */
 
503
  __ic_invalidate(&closure->tramp[0]);
 
504
#endif
 
505
 
 
506
  return FFI_OK;
 
507
}
 
508
 
 
509
/* Basically the trampoline invokes ffi_closure_SYSV, and on 
 
510
 * entry, r3 holds the address of the closure.
 
511
 * After storing the registers that could possibly contain
 
512
 * parameters to be passed into the stack frame and setting
 
513
 * up space for a return value, ffi_closure_SYSV invokes the 
 
514
 * following helper function to do most of the work.
 
515
 */
 
516
 
 
517
#ifdef __LITTLE_ENDIAN__
 
518
#define OFS_INT8        0
 
519
#define OFS_INT16       0
 
520
#else
 
521
#define OFS_INT8        3
 
522
#define OFS_INT16       2
 
523
#endif
 
524
 
 
525
int
 
526
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 
 
527
                         unsigned long *pgr, unsigned long *pfr, 
 
528
                         unsigned long *pst)
 
529
{
 
530
  void **avalue;
 
531
  ffi_type **p_arg;
 
532
  int i, avn;
 
533
  int ireg, greg = 0;
 
534
#if defined(__SH4__)
 
535
  int freg = 0;
 
536
#endif
 
537
  ffi_cif *cif; 
 
538
  double temp; 
 
539
 
 
540
  cif = closure->cif;
 
541
  avalue = alloca(cif->nargs * sizeof(void *));
 
542
 
 
543
  /* Copy the caller's structure return value address so that the closure
 
544
     returns the data directly to the caller.  */
 
545
  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
 
546
    {
 
547
      rvalue = *pgr++;
 
548
      ireg = 1;
 
549
    }
 
550
  else
 
551
    ireg = 0;
 
552
 
 
553
  cif = closure->cif;
 
554
  greg = ireg;
 
555
  avn = cif->nargs;
 
556
 
 
557
  /* Grab the addresses of the arguments from the stack frame.  */
 
558
  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
 
559
    {
 
560
      size_t z;
 
561
 
 
562
      z = (*p_arg)->size;
 
563
      if (z < sizeof(int))
 
564
        {
 
565
          if (greg++ >= NGREGARG)
 
566
            continue;
 
567
 
 
568
          z = sizeof(int);
 
569
          switch ((*p_arg)->type)
 
570
            {
 
571
            case FFI_TYPE_SINT8:
 
572
            case FFI_TYPE_UINT8:
 
573
              avalue[i] = (((char *)pgr) + OFS_INT8);
 
574
              break;
 
575
  
 
576
            case FFI_TYPE_SINT16:
 
577
            case FFI_TYPE_UINT16:
 
578
              avalue[i] = (((char *)pgr) + OFS_INT16);
 
579
              break;
 
580
  
 
581
            case FFI_TYPE_STRUCT:
 
582
              avalue[i] = pgr;
 
583
              break;
 
584
 
 
585
            default:
 
586
              FFI_ASSERT(0);
 
587
            }
 
588
          pgr++;
 
589
        }
 
590
      else if (z == sizeof(int))
 
591
        {
 
592
#if defined(__SH4__)
 
593
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
 
594
            {
 
595
              if (freg++ >= NFREGARG)
 
596
                continue;
 
597
              avalue[i] = pfr;
 
598
              pfr++;
 
599
            }
 
600
          else
 
601
#endif
 
602
            {
 
603
              if (greg++ >= NGREGARG)
 
604
                continue;
 
605
              avalue[i] = pgr;
 
606
              pgr++;
 
607
            }
 
608
        }
 
609
#if defined(__SH4__)
 
610
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
 
611
        {
 
612
          if (freg + 1 >= NFREGARG)
 
613
            continue;
 
614
          freg = (freg + 1) & ~1;
 
615
          freg += 2;
 
616
          avalue[i] = pfr;
 
617
          pfr += 2;
 
618
        }
 
619
#endif
 
620
      else
 
621
        {
 
622
          int n = (z + sizeof (int) - 1) / sizeof (int);
 
623
#if defined(__SH4__)
 
624
          if (greg + n - 1 >= NGREGARG)
 
625
            continue;
 
626
#else
 
627
          if (greg >= NGREGARG)
 
628
            continue;
 
629
#endif
 
630
          greg += n;
 
631
          avalue[i] = pgr;
 
632
          pgr += n;
 
633
        }
 
634
    }
 
635
 
 
636
  greg = ireg;
 
637
#if defined(__SH4__)
 
638
  freg = 0;
 
639
#endif
 
640
 
 
641
  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
 
642
    {
 
643
      size_t z;
 
644
 
 
645
      z = (*p_arg)->size;
 
646
      if (z < sizeof(int))
 
647
        {
 
648
          if (greg++ < NGREGARG)
 
649
            continue;
 
650
 
 
651
          z = sizeof(int);
 
652
          switch ((*p_arg)->type)
 
653
            {
 
654
            case FFI_TYPE_SINT8:
 
655
            case FFI_TYPE_UINT8:
 
656
              avalue[i] = (((char *)pst) + OFS_INT8);
 
657
              break;
 
658
  
 
659
            case FFI_TYPE_SINT16:
 
660
            case FFI_TYPE_UINT16:
 
661
              avalue[i] = (((char *)pst) + OFS_INT16);
 
662
              break;
 
663
  
 
664
            case FFI_TYPE_STRUCT:
 
665
              avalue[i] = pst;
 
666
              break;
 
667
 
 
668
            default:
 
669
              FFI_ASSERT(0);
 
670
            }
 
671
          pst++;
 
672
        }
 
673
      else if (z == sizeof(int))
 
674
        {
 
675
#if defined(__SH4__)
 
676
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
 
677
            {
 
678
              if (freg++ < NFREGARG)
 
679
                continue;
 
680
            }
 
681
          else
 
682
#endif
 
683
            {
 
684
              if (greg++ < NGREGARG)
 
685
                continue;
 
686
            }
 
687
          avalue[i] = pst;
 
688
          pst++;
 
689
        }
 
690
#if defined(__SH4__)
 
691
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
 
692
        {
 
693
          if (freg + 1 < NFREGARG)
 
694
            {
 
695
              freg = (freg + 1) & ~1;
 
696
              freg += 2;
 
697
              continue;
 
698
            }
 
699
          avalue[i] = pst;
 
700
          pst += 2;
 
701
        }
 
702
#endif
 
703
      else
 
704
        {
 
705
          int n = (z + sizeof (int) - 1) / sizeof (int);
 
706
          if (greg + n - 1 < NGREGARG)
 
707
            {
 
708
              greg += n;
 
709
              continue;
 
710
            }
 
711
#if (! defined(__SH4__))
 
712
          else if (greg < NGREGARG)
 
713
            {
 
714
              greg += n;
 
715
              pst += greg - NGREGARG;
 
716
              continue;
 
717
            }
 
718
#endif
 
719
          avalue[i] = pst;
 
720
          pst += n;
 
721
        }
 
722
    }
 
723
 
 
724
  (closure->fun) (cif, rvalue, avalue, closure->user_data);
 
725
 
 
726
  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
 
727
  return return_type (cif->rtype);
 
728
}