OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libffi/] [src/] [sh/] [ffi.c] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 732 jeremybenn
/* -----------------------------------------------------------------------
2
   ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Kaz Kojima
3
           Copyright (c) 2008 Red Hat, Inc.
4
 
5
   SuperH Foreign Function Interface
6
 
7
   Permission is hereby granted, free of charge, to any person obtaining
8
   a copy of this software and associated documentation files (the
9
   ``Software''), to deal in the Software without restriction, including
10
   without limitation the rights to use, copy, modify, merge, publish,
11
   distribute, sublicense, and/or sell copies of the Software, and to
12
   permit persons to whom the Software is furnished to do so, subject to
13
   the following conditions:
14
 
15
   The above copyright notice and this permission notice shall be included
16
   in all copies or substantial portions of the Software.
17
 
18
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
   DEALINGS IN THE SOFTWARE.
26
   ----------------------------------------------------------------------- */
27
 
28
#include <ffi.h>
29
#include <ffi_common.h>
30
 
31
#include <stdlib.h>
32
 
33
#define NGREGARG 4
34
#if defined(__SH4__)
35
#define NFREGARG 8
36
#endif
37
 
38
#if defined(__HITACHI__)
39
#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40
#else
41
#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
42
#endif
43
 
44
/* If the structure has essentialy an unique element, return its type.  */
45
static int
46
simple_type (ffi_type *arg)
47
{
48
  if (arg->type != FFI_TYPE_STRUCT)
49
    return arg->type;
50
  else if (arg->elements[1])
51
    return FFI_TYPE_STRUCT;
52
 
53
  return simple_type (arg->elements[0]);
54
}
55
 
56
static int
57
return_type (ffi_type *arg)
58
{
59
  unsigned short type;
60
 
61
  if (arg->type != FFI_TYPE_STRUCT)
62
    return arg->type;
63
 
64
  type = simple_type (arg->elements[0]);
65
  if (! arg->elements[1])
66
    {
67
      switch (type)
68
        {
69
        case FFI_TYPE_SINT8:
70
        case FFI_TYPE_UINT8:
71
        case FFI_TYPE_SINT16:
72
        case FFI_TYPE_UINT16:
73
        case FFI_TYPE_SINT32:
74
        case FFI_TYPE_UINT32:
75
          return FFI_TYPE_INT;
76
 
77
        default:
78
          return type;
79
        }
80
    }
81
 
82
  /* gcc uses r0/r1 pair for some kind of structures.  */
83
  if (arg->size <= 2 * sizeof (int))
84
    {
85
      int i = 0;
86
      ffi_type *e;
87
 
88
      while ((e = arg->elements[i++]))
89
        {
90
          type = simple_type (e);
91
          switch (type)
92
            {
93
            case FFI_TYPE_SINT32:
94
            case FFI_TYPE_UINT32:
95
            case FFI_TYPE_INT:
96
            case FFI_TYPE_FLOAT:
97
              return FFI_TYPE_UINT64;
98
 
99
            default:
100
              break;
101
            }
102
        }
103
    }
104
 
105
  return FFI_TYPE_STRUCT;
106
}
107
 
108
/* ffi_prep_args is called by the assembly routine once stack space
109
   has been allocated for the function's arguments */
110
 
111
void ffi_prep_args(char *stack, extended_cif *ecif)
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
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
410
                          unsigned, unsigned, unsigned *, void (*fn)(void));
411
 
412
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
413
{
414
  extended_cif ecif;
415
  UINT64 trvalue;
416
 
417
  ecif.cif = cif;
418
  ecif.avalue = avalue;
419
 
420
  /* If the return value is a struct and we don't have a return */
421
  /* value address then we need to make one                     */
422
 
423
  if (cif->rtype->type == FFI_TYPE_STRUCT
424
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
425
    ecif.rvalue = &trvalue;
426
  else if ((rvalue == NULL) &&
427
      (cif->rtype->type == FFI_TYPE_STRUCT))
428
    {
429
      ecif.rvalue = alloca(cif->rtype->size);
430
    }
431
  else
432
    ecif.rvalue = rvalue;
433
 
434
  switch (cif->abi)
435
    {
436
    case FFI_SYSV:
437
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
438
                    fn);
439
      break;
440
    default:
441
      FFI_ASSERT(0);
442
      break;
443
    }
444
 
445
  if (rvalue
446
      && cif->rtype->type == FFI_TYPE_STRUCT
447
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
448
    memcpy (rvalue, &trvalue, cif->rtype->size);
449
}
450
 
451
extern void ffi_closure_SYSV (void);
452
#if defined(__SH4__)
453
extern void __ic_invalidate (void *line);
454
#endif
455
 
456
ffi_status
457
ffi_prep_closure_loc (ffi_closure* closure,
458
                      ffi_cif* cif,
459
                      void (*fun)(ffi_cif*, void*, void**, void*),
460
                      void *user_data,
461
                      void *codeloc)
462
{
463
  unsigned int *tramp;
464
  unsigned int insn;
465
 
466
  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
467
 
468
  tramp = (unsigned int *) &closure->tramp[0];
469
  /* Set T bit if the function returns a struct pointed with R2.  */
470
  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
471
          ? 0x0018 /* sett */
472
          : 0x0008 /* clrt */);
473
 
474
#ifdef __LITTLE_ENDIAN__
475
  tramp[0] = 0xd301d102;
476
  tramp[1] = 0x0000412b | (insn << 16);
477
#else
478
  tramp[0] = 0xd102d301;
479
  tramp[1] = 0x412b0000 | insn;
480
#endif
481
  *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
482
  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
483
 
484
  closure->cif = cif;
485
  closure->fun = fun;
486
  closure->user_data = user_data;
487
 
488
#if defined(__SH4__)
489
  /* Flush the icache.  */
490
  __ic_invalidate(codeloc);
491
#endif
492
 
493
  return FFI_OK;
494
}
495
 
496
/* Basically the trampoline invokes ffi_closure_SYSV, and on
497
 * entry, r3 holds the address of the closure.
498
 * After storing the registers that could possibly contain
499
 * parameters to be passed into the stack frame and setting
500
 * up space for a return value, ffi_closure_SYSV invokes the
501
 * following helper function to do most of the work.
502
 */
503
 
504
#ifdef __LITTLE_ENDIAN__
505
#define OFS_INT8        0
506
#define OFS_INT16       0
507
#else
508
#define OFS_INT8        3
509
#define OFS_INT16       2
510
#endif
511
 
512
int
513
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
514
                         unsigned long *pgr, unsigned long *pfr,
515
                         unsigned long *pst)
516
{
517
  void **avalue;
518
  ffi_type **p_arg;
519
  int i, avn;
520
  int ireg, greg = 0;
521
#if defined(__SH4__)
522
  int freg = 0;
523
#endif
524
  ffi_cif *cif;
525
 
526
  cif = closure->cif;
527
  avalue = alloca(cif->nargs * sizeof(void *));
528
 
529
  /* Copy the caller's structure return value address so that the closure
530
     returns the data directly to the caller.  */
531
  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
532
    {
533
      rvalue = (void *) *pgr++;
534
      ireg = 1;
535
    }
536
  else
537
    ireg = 0;
538
 
539
  cif = closure->cif;
540
  greg = ireg;
541
  avn = cif->nargs;
542
 
543
  /* Grab the addresses of the arguments from the stack frame.  */
544
  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
545
    {
546
      size_t z;
547
 
548
      z = (*p_arg)->size;
549
      if (z < sizeof(int))
550
        {
551
          if (greg++ >= NGREGARG)
552
            continue;
553
 
554
          z = sizeof(int);
555
          switch ((*p_arg)->type)
556
            {
557
            case FFI_TYPE_SINT8:
558
            case FFI_TYPE_UINT8:
559
              avalue[i] = (((char *)pgr) + OFS_INT8);
560
              break;
561
 
562
            case FFI_TYPE_SINT16:
563
            case FFI_TYPE_UINT16:
564
              avalue[i] = (((char *)pgr) + OFS_INT16);
565
              break;
566
 
567
            case FFI_TYPE_STRUCT:
568
              avalue[i] = pgr;
569
              break;
570
 
571
            default:
572
              FFI_ASSERT(0);
573
            }
574
          pgr++;
575
        }
576
      else if (z == sizeof(int))
577
        {
578
#if defined(__SH4__)
579
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
580
            {
581
              if (freg++ >= NFREGARG)
582
                continue;
583
              avalue[i] = pfr;
584
              pfr++;
585
            }
586
          else
587
#endif
588
            {
589
              if (greg++ >= NGREGARG)
590
                continue;
591
              avalue[i] = pgr;
592
              pgr++;
593
            }
594
        }
595
#if defined(__SH4__)
596
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
597
        {
598
          if (freg + 1 >= NFREGARG)
599
            continue;
600
          if (freg & 1)
601
            pfr++;
602
          freg = (freg + 1) & ~1;
603
          freg += 2;
604
          avalue[i] = pfr;
605
          pfr += 2;
606
        }
607
#endif
608
      else
609
        {
610
          int n = (z + sizeof (int) - 1) / sizeof (int);
611
#if defined(__SH4__)
612
          if (greg + n - 1 >= NGREGARG)
613
            continue;
614
#else
615
          if (greg >= NGREGARG)
616
            continue;
617
#endif
618
          greg += n;
619
          avalue[i] = pgr;
620
          pgr += n;
621
        }
622
    }
623
 
624
  greg = ireg;
625
#if defined(__SH4__)
626
  freg = 0;
627
#endif
628
 
629
  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
630
    {
631
      size_t z;
632
 
633
      z = (*p_arg)->size;
634
      if (z < sizeof(int))
635
        {
636
          if (greg++ < NGREGARG)
637
            continue;
638
 
639
          z = sizeof(int);
640
          switch ((*p_arg)->type)
641
            {
642
            case FFI_TYPE_SINT8:
643
            case FFI_TYPE_UINT8:
644
              avalue[i] = (((char *)pst) + OFS_INT8);
645
              break;
646
 
647
            case FFI_TYPE_SINT16:
648
            case FFI_TYPE_UINT16:
649
              avalue[i] = (((char *)pst) + OFS_INT16);
650
              break;
651
 
652
            case FFI_TYPE_STRUCT:
653
              avalue[i] = pst;
654
              break;
655
 
656
            default:
657
              FFI_ASSERT(0);
658
            }
659
          pst++;
660
        }
661
      else if (z == sizeof(int))
662
        {
663
#if defined(__SH4__)
664
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
665
            {
666
              if (freg++ < NFREGARG)
667
                continue;
668
            }
669
          else
670
#endif
671
            {
672
              if (greg++ < NGREGARG)
673
                continue;
674
            }
675
          avalue[i] = pst;
676
          pst++;
677
        }
678
#if defined(__SH4__)
679
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
680
        {
681
          if (freg + 1 < NFREGARG)
682
            {
683
              freg = (freg + 1) & ~1;
684
              freg += 2;
685
              continue;
686
            }
687
          avalue[i] = pst;
688
          pst += 2;
689
        }
690
#endif
691
      else
692
        {
693
          int n = (z + sizeof (int) - 1) / sizeof (int);
694
          if (greg + n - 1 < NGREGARG)
695
            {
696
              greg += n;
697
              continue;
698
            }
699
#if (! defined(__SH4__))
700
          else if (greg < NGREGARG)
701
            {
702
              greg += n;
703
              pst += greg - NGREGARG;
704
              continue;
705
            }
706
#endif
707
          avalue[i] = pst;
708
          pst += n;
709
        }
710
    }
711
 
712
  (closure->fun) (cif, rvalue, avalue, closure->user_data);
713
 
714
  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
715
  return return_type (cif->rtype);
716
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.