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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 732 jeremybenn
/* -----------------------------------------------------------------------
2
   ffi.c - Copyright (c) 1996, 2007, 2008  Red Hat, Inc.
3
           Copyright (c) 2008       David Daney
4
 
5
   MIPS 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
#ifdef __GNUC__
34
#  if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
35
#    define USE__BUILTIN___CLEAR_CACHE 1
36
#  endif
37
#endif
38
 
39
#ifndef USE__BUILTIN___CLEAR_CACHE
40
#include <sys/cachectl.h>
41
#endif
42
 
43
#ifdef FFI_DEBUG
44
# define FFI_MIPS_STOP_HERE() ffi_stop_here()
45
#else
46
# define FFI_MIPS_STOP_HERE() do {} while(0)
47
#endif
48
 
49
#ifdef FFI_MIPS_N32
50
#define FIX_ARGP \
51
FFI_ASSERT(argp <= &stack[bytes]); \
52
if (argp == &stack[bytes]) \
53
{ \
54
  argp = stack; \
55
  FFI_MIPS_STOP_HERE(); \
56
}
57
#else
58
#define FIX_ARGP 
59
#endif
60
 
61
 
62
/* ffi_prep_args is called by the assembly routine once stack space
63
   has been allocated for the function's arguments */
64
 
65
static void ffi_prep_args(char *stack,
66
                          extended_cif *ecif,
67
                          int bytes,
68
                          int flags)
69
{
70
  int i;
71
  void **p_argv;
72
  char *argp;
73
  ffi_type **p_arg;
74
 
75
#ifdef FFI_MIPS_N32
76
  /* If more than 8 double words are used, the remainder go
77
     on the stack. We reorder stuff on the stack here to
78
     support this easily. */
79
  if (bytes > 8 * sizeof(ffi_arg))
80
    argp = &stack[bytes - (8 * sizeof(ffi_arg))];
81
  else
82
    argp = stack;
83
#else
84
  argp = stack;
85
#endif
86
 
87
  memset(stack, 0, bytes);
88
 
89
#ifdef FFI_MIPS_N32
90
  if ( ecif->cif->rstruct_flag != 0 )
91
#else
92
  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
93
#endif  
94
    {
95
      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
96
      argp += sizeof(ffi_arg);
97
      FIX_ARGP;
98
    }
99
 
100
  p_argv = ecif->avalue;
101
 
102
  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
103
    {
104
      size_t z;
105
      unsigned int a;
106
 
107
      /* Align if necessary.  */
108
      a = (*p_arg)->alignment;
109
      if (a < sizeof(ffi_arg))
110
        a = sizeof(ffi_arg);
111
 
112
      if ((a - 1) & (unsigned long) argp)
113
        {
114
          argp = (char *) ALIGN(argp, a);
115
          FIX_ARGP;
116
        }
117
 
118
      z = (*p_arg)->size;
119
      if (z <= sizeof(ffi_arg))
120
        {
121
          int type = (*p_arg)->type;
122
          z = sizeof(ffi_arg);
123
 
124
          /* The size of a pointer depends on the ABI */
125
          if (type == FFI_TYPE_POINTER)
126
            type = (ecif->cif->abi == FFI_N64
127
                    || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
128
              ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
129
 
130
        if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
131
                      || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
132
          {
133
            switch (type)
134
              {
135
              case FFI_TYPE_FLOAT:
136
                type = FFI_TYPE_UINT32;
137
                break;
138
              case FFI_TYPE_DOUBLE:
139
                type = FFI_TYPE_UINT64;
140
                break;
141
              default:
142
                break;
143
              }
144
          }
145
          switch (type)
146
            {
147
              case FFI_TYPE_SINT8:
148
                *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
149
                break;
150
 
151
              case FFI_TYPE_UINT8:
152
                *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
153
                break;
154
 
155
              case FFI_TYPE_SINT16:
156
                *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
157
                break;
158
 
159
              case FFI_TYPE_UINT16:
160
                *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
161
                break;
162
 
163
              case FFI_TYPE_SINT32:
164
                *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
165
                break;
166
 
167
              case FFI_TYPE_UINT32:
168
                *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
169
                break;
170
 
171
              /* This can only happen with 64bit slots.  */
172
              case FFI_TYPE_FLOAT:
173
                *(float *) argp = *(float *)(* p_argv);
174
                break;
175
 
176
              /* Handle structures.  */
177
              default:
178
                memcpy(argp, *p_argv, (*p_arg)->size);
179
                break;
180
            }
181
        }
182
      else
183
        {
184
#ifdef FFI_MIPS_O32
185
          memcpy(argp, *p_argv, z);
186
#else
187
          {
188
            unsigned long end = (unsigned long) argp + z;
189
            unsigned long cap = (unsigned long) stack + bytes;
190
 
191
            /* Check if the data will fit within the register space.
192
               Handle it if it doesn't.  */
193
 
194
            if (end <= cap)
195
              memcpy(argp, *p_argv, z);
196
            else
197
              {
198
                unsigned long portion = cap - (unsigned long)argp;
199
 
200
                memcpy(argp, *p_argv, portion);
201
                argp = stack;
202
                z -= portion;
203
                memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
204
                       z);
205
              }
206
          }
207
#endif
208
      }
209
      p_argv++;
210
      argp += z;
211
      FIX_ARGP;
212
    }
213
}
214
 
215
#ifdef FFI_MIPS_N32
216
 
217
/* The n32 spec says that if "a chunk consists solely of a double
218
   float field (but not a double, which is part of a union), it
219
   is passed in a floating point register. Any other chunk is
220
   passed in an integer register". This code traverses structure
221
   definitions and generates the appropriate flags. */
222
 
223
static unsigned
224
calc_n32_struct_flags(int soft_float, ffi_type *arg,
225
                      unsigned *loc, unsigned *arg_reg)
226
{
227
  unsigned flags = 0;
228
  unsigned index = 0;
229
 
230
  ffi_type *e;
231
 
232
  if (soft_float)
233
    return 0;
234
 
235
  while ((e = arg->elements[index]))
236
    {
237
      /* Align this object.  */
238
      *loc = ALIGN(*loc, e->alignment);
239
      if (e->type == FFI_TYPE_DOUBLE)
240
        {
241
          /* Already aligned to FFI_SIZEOF_ARG.  */
242
          *arg_reg = *loc / FFI_SIZEOF_ARG;
243
          if (*arg_reg > 7)
244
            break;
245
          flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
246
          *loc += e->size;
247
        }
248
      else
249
        *loc += e->size;
250
      index++;
251
    }
252
  /* Next Argument register at alignment of FFI_SIZEOF_ARG.  */
253
  *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
254
 
255
  return flags;
256
}
257
 
258
static unsigned
259
calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
260
{
261
  unsigned flags = 0;
262
  unsigned small = FFI_TYPE_SMALLSTRUCT;
263
  ffi_type *e;
264
 
265
  /* Returning structures under n32 is a tricky thing.
266
     A struct with only one or two floating point fields
267
     is returned in $f0 (and $f2 if necessary). Any other
268
     struct results at most 128 bits are returned in $2
269
     (the first 64 bits) and $3 (remainder, if necessary).
270
     Larger structs are handled normally. */
271
 
272
  if (arg->size > 16)
273
    return 0;
274
 
275
  if (arg->size > 8)
276
    small = FFI_TYPE_SMALLSTRUCT2;
277
 
278
  e = arg->elements[0];
279
 
280
  if (e->type == FFI_TYPE_DOUBLE)
281
    flags = FFI_TYPE_DOUBLE;
282
  else if (e->type == FFI_TYPE_FLOAT)
283
    flags = FFI_TYPE_FLOAT;
284
 
285
  if (flags && (e = arg->elements[1]))
286
    {
287
      if (e->type == FFI_TYPE_DOUBLE)
288
        flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
289
      else if (e->type == FFI_TYPE_FLOAT)
290
        flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
291
      else
292
        return small;
293
 
294
      if (flags && (arg->elements[2]))
295
        {
296
          /* There are three arguments and the first two are
297
             floats! This must be passed the old way. */
298
          return small;
299
        }
300
      if (soft_float)
301
        flags += FFI_TYPE_STRUCT_SOFT;
302
    }
303
  else
304
    if (!flags)
305
      return small;
306
 
307
  return flags;
308
}
309
 
310
#endif
311
 
312
/* Perform machine dependent cif processing */
313
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
314
{
315
  cif->flags = 0;
316
 
317
#ifdef FFI_MIPS_O32
318
  /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
319
   * does not have special handling for floating point args.
320
   */
321
 
322
  if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
323
    {
324
      if (cif->nargs > 0)
325
        {
326
          switch ((cif->arg_types)[0]->type)
327
            {
328
            case FFI_TYPE_FLOAT:
329
            case FFI_TYPE_DOUBLE:
330
              cif->flags += (cif->arg_types)[0]->type;
331
              break;
332
 
333
            default:
334
              break;
335
            }
336
 
337
          if (cif->nargs > 1)
338
            {
339
              /* Only handle the second argument if the first
340
                 is a float or double. */
341
              if (cif->flags)
342
                {
343
                  switch ((cif->arg_types)[1]->type)
344
                    {
345
                    case FFI_TYPE_FLOAT:
346
                    case FFI_TYPE_DOUBLE:
347
                      cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
348
                      break;
349
 
350
                    default:
351
                      break;
352
                    }
353
                }
354
            }
355
        }
356
    }
357
 
358
  /* Set the return type flag */
359
 
360
  if (cif->abi == FFI_O32_SOFT_FLOAT)
361
    {
362
      switch (cif->rtype->type)
363
        {
364
        case FFI_TYPE_VOID:
365
        case FFI_TYPE_STRUCT:
366
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
367
          break;
368
 
369
        case FFI_TYPE_SINT64:
370
        case FFI_TYPE_UINT64:
371
        case FFI_TYPE_DOUBLE:
372
          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
373
          break;
374
 
375
        case FFI_TYPE_FLOAT:
376
        default:
377
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
378
          break;
379
        }
380
    }
381
  else
382
    {
383
      /* FFI_O32 */
384
      switch (cif->rtype->type)
385
        {
386
        case FFI_TYPE_VOID:
387
        case FFI_TYPE_STRUCT:
388
        case FFI_TYPE_FLOAT:
389
        case FFI_TYPE_DOUBLE:
390
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
391
          break;
392
 
393
        case FFI_TYPE_SINT64:
394
        case FFI_TYPE_UINT64:
395
          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
396
          break;
397
 
398
        default:
399
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
400
          break;
401
        }
402
    }
403
#endif
404
 
405
#ifdef FFI_MIPS_N32
406
  /* Set the flags necessary for N32 processing */
407
  {
408
    int type;
409
    unsigned arg_reg = 0;
410
    unsigned loc = 0;
411
    unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
412
    unsigned index = 0;
413
 
414
    unsigned struct_flags = 0;
415
    int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
416
                      || cif->abi == FFI_N64_SOFT_FLOAT);
417
 
418
    if (cif->rtype->type == FFI_TYPE_STRUCT)
419
      {
420
        struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
421
 
422
        if (struct_flags == 0)
423
          {
424
            /* This means that the structure is being passed as
425
               a hidden argument */
426
 
427
            arg_reg = 1;
428
            count = (cif->nargs < 7) ? cif->nargs : 7;
429
 
430
            cif->rstruct_flag = !0;
431
          }
432
        else
433
            cif->rstruct_flag = 0;
434
      }
435
    else
436
      cif->rstruct_flag = 0;
437
 
438
    while (count-- > 0 && arg_reg < 8)
439
      {
440
        type = (cif->arg_types)[index]->type;
441
        if (soft_float)
442
          {
443
            switch (type)
444
              {
445
              case FFI_TYPE_FLOAT:
446
                type = FFI_TYPE_UINT32;
447
                break;
448
              case FFI_TYPE_DOUBLE:
449
                type = FFI_TYPE_UINT64;
450
                break;
451
              default:
452
                break;
453
              }
454
          }
455
        switch (type)
456
          {
457
          case FFI_TYPE_FLOAT:
458
          case FFI_TYPE_DOUBLE:
459
            cif->flags +=
460
              ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
461
            arg_reg++;
462
            break;
463
          case FFI_TYPE_LONGDOUBLE:
464
            /* Align it.  */
465
            arg_reg = ALIGN(arg_reg, 2);
466
            /* Treat it as two adjacent doubles.  */
467
            if (soft_float)
468
              {
469
                arg_reg += 2;
470
              }
471
            else
472
              {
473
                cif->flags +=
474
                  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
475
                arg_reg++;
476
                cif->flags +=
477
                  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
478
                arg_reg++;
479
              }
480
            break;
481
 
482
          case FFI_TYPE_STRUCT:
483
            loc = arg_reg * FFI_SIZEOF_ARG;
484
            cif->flags += calc_n32_struct_flags(soft_float,
485
                                                (cif->arg_types)[index],
486
                                                &loc, &arg_reg);
487
            break;
488
 
489
          default:
490
            arg_reg++;
491
            break;
492
          }
493
 
494
        index++;
495
      }
496
 
497
  /* Set the return type flag */
498
    switch (cif->rtype->type)
499
      {
500
      case FFI_TYPE_STRUCT:
501
        {
502
          if (struct_flags == 0)
503
            {
504
              /* The structure is returned through a hidden
505
                 first argument. Do nothing, 'cause FFI_TYPE_VOID
506
                 is 0 */
507
            }
508
          else
509
            {
510
              /* The structure is returned via some tricky
511
                 mechanism */
512
              cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
513
              cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
514
            }
515
          break;
516
        }
517
 
518
      case FFI_TYPE_VOID:
519
        /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
520
        break;
521
 
522
      case FFI_TYPE_POINTER:
523
        if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
524
          cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
525
        else
526
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
527
        break;
528
 
529
      case FFI_TYPE_FLOAT:
530
        if (soft_float)
531
          {
532
            cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
533
            break;
534
          }
535
        /* else fall through */
536
      case FFI_TYPE_DOUBLE:
537
        if (soft_float)
538
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
539
        else
540
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
541
        break;
542
 
543
      case FFI_TYPE_LONGDOUBLE:
544
        /* Long double is returned as if it were a struct containing
545
           two doubles.  */
546
        if (soft_float)
547
          {
548
            cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
549
            cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
550
          }
551
        else
552
          {
553
            cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
554
            cif->flags += (FFI_TYPE_DOUBLE
555
                           + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
556
                                              << (4 + (FFI_FLAG_BITS * 8));
557
          }
558
        break;
559
      default:
560
        cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
561
        break;
562
      }
563
  }
564
#endif
565
 
566
  return FFI_OK;
567
}
568
 
569
/* Low level routine for calling O32 functions */
570
extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
571
                        extended_cif *, unsigned,
572
                        unsigned, unsigned *, void (*)(void));
573
 
574
/* Low level routine for calling N32 functions */
575
extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
576
                        extended_cif *, unsigned,
577
                        unsigned, void *, void (*)(void));
578
 
579
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
580
{
581
  extended_cif ecif;
582
 
583
  ecif.cif = cif;
584
  ecif.avalue = avalue;
585
 
586
  /* If the return value is a struct and we don't have a return */
587
  /* value address then we need to make one                     */
588
 
589
  if ((rvalue == NULL) &&
590
      (cif->rtype->type == FFI_TYPE_STRUCT))
591
    ecif.rvalue = alloca(cif->rtype->size);
592
  else
593
    ecif.rvalue = rvalue;
594
 
595
  switch (cif->abi)
596
    {
597
#ifdef FFI_MIPS_O32
598
    case FFI_O32:
599
    case FFI_O32_SOFT_FLOAT:
600
      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
601
                   cif->flags, ecif.rvalue, fn);
602
      break;
603
#endif
604
 
605
#ifdef FFI_MIPS_N32
606
    case FFI_N32:
607
    case FFI_N32_SOFT_FLOAT:
608
    case FFI_N64:
609
    case FFI_N64_SOFT_FLOAT:
610
      {
611
        int copy_rvalue = 0;
612
        int copy_offset = 0;
613
        char *rvalue_copy = ecif.rvalue;
614
        if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
615
          {
616
            /* For structures smaller than 16 bytes we clobber memory
617
               in 8 byte increments.  Make a copy so we don't clobber
618
               the callers memory outside of the struct bounds.  */
619
            rvalue_copy = alloca(16);
620
            copy_rvalue = 1;
621
          }
622
        else if (cif->rtype->type == FFI_TYPE_FLOAT
623
                 && (cif->abi == FFI_N64_SOFT_FLOAT
624
                     || cif->abi == FFI_N32_SOFT_FLOAT))
625
          {
626
            rvalue_copy = alloca (8);
627
            copy_rvalue = 1;
628
#if defined(__MIPSEB__) || defined(_MIPSEB)
629
            copy_offset = 4;
630
#endif
631
          }
632
        ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
633
                     cif->flags, rvalue_copy, fn);
634
        if (copy_rvalue)
635
          memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
636
      }
637
      break;
638
#endif
639
 
640
    default:
641
      FFI_ASSERT(0);
642
      break;
643
    }
644
}
645
 
646
#if FFI_CLOSURES
647
#if defined(FFI_MIPS_O32)
648
extern void ffi_closure_O32(void);
649
#else
650
extern void ffi_closure_N32(void);
651
#endif /* FFI_MIPS_O32 */
652
 
653
ffi_status
654
ffi_prep_closure_loc (ffi_closure *closure,
655
                      ffi_cif *cif,
656
                      void (*fun)(ffi_cif*,void*,void**,void*),
657
                      void *user_data,
658
                      void *codeloc)
659
{
660
  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
661
  void * fn;
662
  char *clear_location = (char *) codeloc;
663
 
664
#if defined(FFI_MIPS_O32)
665
  FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
666
  fn = ffi_closure_O32;
667
#else /* FFI_MIPS_N32 */
668
  FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
669
  fn = ffi_closure_N32;
670
#endif /* FFI_MIPS_O32 */
671
 
672
#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
673
  /* lui  $25,high(fn) */
674
  tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
675
  /* ori  $25,low(fn)  */
676
  tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
677
  /* lui  $12,high(codeloc) */
678
  tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
679
  /* jr   $25          */
680
  tramp[3] = 0x03200008;
681
  /* ori  $12,low(codeloc)  */
682
  tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
683
#else
684
  /* N64 has a somewhat larger trampoline.  */
685
  /* lui  $25,high(fn) */
686
  tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
687
  /* lui  $12,high(codeloc) */
688
  tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
689
  /* ori  $25,mid-high(fn)  */
690
  tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
691
  /* ori  $12,mid-high(codeloc)  */
692
  tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
693
  /* dsll $25,$25,16 */
694
  tramp[4] = 0x0019cc38;
695
  /* dsll $12,$12,16 */
696
  tramp[5] = 0x000c6438;
697
  /* ori  $25,mid-low(fn)  */
698
  tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
699
  /* ori  $12,mid-low(codeloc)  */
700
  tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
701
  /* dsll $25,$25,16 */
702
  tramp[8] = 0x0019cc38;
703
  /* dsll $12,$12,16 */
704
  tramp[9] = 0x000c6438;
705
  /* ori  $25,low(fn)  */
706
  tramp[10] = 0x37390000 | ((unsigned long)fn  & 0xffff);
707
  /* jr   $25          */
708
  tramp[11] = 0x03200008;
709
  /* ori  $12,low(codeloc)  */
710
  tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
711
 
712
#endif
713
 
714
  closure->cif = cif;
715
  closure->fun = fun;
716
  closure->user_data = user_data;
717
 
718
#ifdef USE__BUILTIN___CLEAR_CACHE
719
  __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
720
#else
721
  cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
722
#endif
723
  return FFI_OK;
724
}
725
 
726
/*
727
 * Decodes the arguments to a function, which will be stored on the
728
 * stack. AR is the pointer to the beginning of the integer arguments
729
 * (and, depending upon the arguments, some floating-point arguments
730
 * as well). FPR is a pointer to the area where floating point
731
 * registers have been saved, if any.
732
 *
733
 * RVALUE is the location where the function return value will be
734
 * stored. CLOSURE is the prepared closure to invoke.
735
 *
736
 * This function should only be called from assembly, which is in
737
 * turn called from a trampoline.
738
 *
739
 * Returns the function return type.
740
 *
741
 * Based on the similar routine for sparc.
742
 */
743
int
744
ffi_closure_mips_inner_O32 (ffi_closure *closure,
745
                            void *rvalue, ffi_arg *ar,
746
                            double *fpr)
747
{
748
  ffi_cif *cif;
749
  void **avaluep;
750
  ffi_arg *avalue;
751
  ffi_type **arg_types;
752
  int i, avn, argn, seen_int;
753
 
754
  cif = closure->cif;
755
  avalue = alloca (cif->nargs * sizeof (ffi_arg));
756
  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
757
 
758
  seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
759
  argn = 0;
760
 
761
  if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
762
    {
763
      rvalue = (void *)(UINT32)ar[0];
764
      argn = 1;
765
    }
766
 
767
  i = 0;
768
  avn = cif->nargs;
769
  arg_types = cif->arg_types;
770
 
771
  while (i < avn)
772
    {
773
      if (i < 2 && !seen_int &&
774
          (arg_types[i]->type == FFI_TYPE_FLOAT ||
775
           arg_types[i]->type == FFI_TYPE_DOUBLE ||
776
           arg_types[i]->type == FFI_TYPE_LONGDOUBLE))
777
        {
778
#if defined(__MIPSEB__) || defined(_MIPSEB)
779
          if (arg_types[i]->type == FFI_TYPE_FLOAT)
780
            avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
781
          else
782
#endif
783
            avaluep[i] = (char *) &fpr[i];
784
        }
785
      else
786
        {
787
          if (arg_types[i]->alignment == 8 && (argn & 0x1))
788
            argn++;
789
          switch (arg_types[i]->type)
790
            {
791
              case FFI_TYPE_SINT8:
792
                avaluep[i] = &avalue[i];
793
                *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
794
                break;
795
 
796
              case FFI_TYPE_UINT8:
797
                avaluep[i] = &avalue[i];
798
                *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
799
                break;
800
 
801
              case FFI_TYPE_SINT16:
802
                avaluep[i] = &avalue[i];
803
                *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
804
                break;
805
 
806
              case FFI_TYPE_UINT16:
807
                avaluep[i] = &avalue[i];
808
                *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
809
                break;
810
 
811
              default:
812
                avaluep[i] = (char *) &ar[argn];
813
                break;
814
            }
815
          seen_int = 1;
816
        }
817
      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
818
      i++;
819
    }
820
 
821
  /* Invoke the closure. */
822
  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
823
 
824
  if (cif->abi == FFI_O32_SOFT_FLOAT)
825
    {
826
      switch (cif->rtype->type)
827
        {
828
        case FFI_TYPE_FLOAT:
829
          return FFI_TYPE_INT;
830
        case FFI_TYPE_DOUBLE:
831
          return FFI_TYPE_UINT64;
832
        default:
833
          return cif->rtype->type;
834
        }
835
    }
836
  else
837
    {
838
      return cif->rtype->type;
839
    }
840
}
841
 
842
#if defined(FFI_MIPS_N32)
843
 
844
static void
845
copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
846
                int argn, unsigned arg_offset, ffi_arg *ar,
847
                ffi_arg *fpr, int soft_float)
848
{
849
  ffi_type **elt_typep = type->elements;
850
  while(*elt_typep)
851
    {
852
      ffi_type *elt_type = *elt_typep;
853
      unsigned o;
854
      char *tp;
855
      char *argp;
856
      char *fpp;
857
 
858
      o = ALIGN(offset, elt_type->alignment);
859
      arg_offset += o - offset;
860
      offset = o;
861
      argn += arg_offset / sizeof(ffi_arg);
862
      arg_offset = arg_offset % sizeof(ffi_arg);
863
 
864
      argp = (char *)(ar + argn);
865
      fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
866
 
867
      tp = target + offset;
868
 
869
      if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
870
        *(double *)tp = *(double *)fpp;
871
      else
872
        memcpy(tp, argp + arg_offset, elt_type->size);
873
 
874
      offset += elt_type->size;
875
      arg_offset += elt_type->size;
876
      elt_typep++;
877
      argn += arg_offset / sizeof(ffi_arg);
878
      arg_offset = arg_offset % sizeof(ffi_arg);
879
    }
880
}
881
 
882
/*
883
 * Decodes the arguments to a function, which will be stored on the
884
 * stack. AR is the pointer to the beginning of the integer
885
 * arguments. FPR is a pointer to the area where floating point
886
 * registers have been saved.
887
 *
888
 * RVALUE is the location where the function return value will be
889
 * stored. CLOSURE is the prepared closure to invoke.
890
 *
891
 * This function should only be called from assembly, which is in
892
 * turn called from a trampoline.
893
 *
894
 * Returns the function return flags.
895
 *
896
 */
897
int
898
ffi_closure_mips_inner_N32 (ffi_closure *closure,
899
                            void *rvalue, ffi_arg *ar,
900
                            ffi_arg *fpr)
901
{
902
  ffi_cif *cif;
903
  void **avaluep;
904
  ffi_arg *avalue;
905
  ffi_type **arg_types;
906
  int i, avn, argn;
907
  int soft_float;
908
  ffi_arg *argp;
909
 
910
  cif = closure->cif;
911
  soft_float = cif->abi == FFI_N64_SOFT_FLOAT
912
    || cif->abi == FFI_N32_SOFT_FLOAT;
913
  avalue = alloca (cif->nargs * sizeof (ffi_arg));
914
  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
915
 
916
  argn = 0;
917
 
918
  if (cif->rstruct_flag)
919
    {
920
#if _MIPS_SIM==_ABIN32
921
      rvalue = (void *)(UINT32)ar[0];
922
#else /* N64 */
923
      rvalue = (void *)ar[0];
924
#endif
925
      argn = 1;
926
    }
927
 
928
  i = 0;
929
  avn = cif->nargs;
930
  arg_types = cif->arg_types;
931
 
932
  while (i < avn)
933
    {
934
      if (arg_types[i]->type == FFI_TYPE_FLOAT
935
          || arg_types[i]->type == FFI_TYPE_DOUBLE
936
          || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
937
        {
938
          argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
939
          if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1)))
940
            {
941
              argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
942
              argn++;
943
            }
944
#if defined(__MIPSEB__) || defined(_MIPSEB)
945
          if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
946
            avaluep[i] = ((char *) argp) + sizeof (float);
947
          else
948
#endif
949
            avaluep[i] = (char *) argp;
950
        }
951
      else
952
        {
953
          unsigned type = arg_types[i]->type;
954
 
955
          if (arg_types[i]->alignment > sizeof(ffi_arg))
956
            argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
957
 
958
          argp = ar + argn;
959
 
960
          /* The size of a pointer depends on the ABI */
961
          if (type == FFI_TYPE_POINTER)
962
            type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
963
              ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
964
 
965
          if (soft_float && type ==  FFI_TYPE_FLOAT)
966
            type = FFI_TYPE_UINT32;
967
 
968
          switch (type)
969
            {
970
            case FFI_TYPE_SINT8:
971
              avaluep[i] = &avalue[i];
972
              *(SINT8 *) &avalue[i] = (SINT8) *argp;
973
              break;
974
 
975
            case FFI_TYPE_UINT8:
976
              avaluep[i] = &avalue[i];
977
              *(UINT8 *) &avalue[i] = (UINT8) *argp;
978
              break;
979
 
980
            case FFI_TYPE_SINT16:
981
              avaluep[i] = &avalue[i];
982
              *(SINT16 *) &avalue[i] = (SINT16) *argp;
983
              break;
984
 
985
            case FFI_TYPE_UINT16:
986
              avaluep[i] = &avalue[i];
987
              *(UINT16 *) &avalue[i] = (UINT16) *argp;
988
              break;
989
 
990
            case FFI_TYPE_SINT32:
991
              avaluep[i] = &avalue[i];
992
              *(SINT32 *) &avalue[i] = (SINT32) *argp;
993
              break;
994
 
995
            case FFI_TYPE_UINT32:
996
              avaluep[i] = &avalue[i];
997
              *(UINT32 *) &avalue[i] = (UINT32) *argp;
998
              break;
999
 
1000
            case FFI_TYPE_STRUCT:
1001
              if (argn < 8)
1002
                {
1003
                  /* Allocate space for the struct as at least part of
1004
                     it was passed in registers.  */
1005
                  avaluep[i] = alloca(arg_types[i]->size);
1006
                  copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
1007
                                  argn, 0, ar, fpr, soft_float);
1008
 
1009
                  break;
1010
                }
1011
              /* Else fall through.  */
1012
            default:
1013
              avaluep[i] = (char *) argp;
1014
              break;
1015
            }
1016
        }
1017
      argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
1018
      i++;
1019
    }
1020
 
1021
  /* Invoke the closure. */
1022
  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
1023
 
1024
  return cif->flags >> (FFI_FLAG_BITS * 8);
1025
}
1026
 
1027
#endif /* FFI_MIPS_N32 */
1028
 
1029
#endif /* FFI_CLOSURES */

powered by: WebSVN 2.1.0

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