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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libffi/] [src/] [sh64/] [ffi.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* -----------------------------------------------------------------------
2
   ffi.c - Copyright (c) 2003, 2004 Kaz Kojima
3
 
4
   SuperH SHmedia 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 8
32
#define NFREGARG 12
33
 
34
static int
35
return_type (ffi_type *arg)
36
{
37
 
38
  if (arg->type != FFI_TYPE_STRUCT)
39
    return arg->type;
40
 
41
  /* gcc uses r2 if the result can be packed in on register.  */
42
  if (arg->size <= sizeof (UINT8))
43
    return FFI_TYPE_UINT8;
44
  else if (arg->size <= sizeof (UINT16))
45
    return FFI_TYPE_UINT16;
46
  else if (arg->size <= sizeof (UINT32))
47
    return FFI_TYPE_UINT32;
48
  else if (arg->size <= sizeof (UINT64))
49
    return FFI_TYPE_UINT64;
50
 
51
  return FFI_TYPE_STRUCT;
52
}
53
 
54
/* ffi_prep_args is called by the assembly routine once stack space
55
   has been allocated for the function's arguments */
56
 
57
/*@-exportheader@*/
58
void ffi_prep_args(char *stack, extended_cif *ecif)
59
/*@=exportheader@*/
60
{
61
  register unsigned int i;
62
  register unsigned int avn;
63
  register void **p_argv;
64
  register char *argp;
65
  register ffi_type **p_arg;
66
 
67
  argp = stack;
68
 
69
  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
70
    {
71
      *(void **) argp = ecif->rvalue;
72
      argp += sizeof (UINT64);
73
    }
74
 
75
  avn = ecif->cif->nargs;
76
  p_argv = ecif->avalue;
77
 
78
  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
79
    {
80
      size_t z;
81
      int align;
82
 
83
      z = (*p_arg)->size;
84
      align = (*p_arg)->alignment;
85
      if (z < sizeof (UINT32))
86
        {
87
          switch ((*p_arg)->type)
88
            {
89
            case FFI_TYPE_SINT8:
90
              *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
91
              break;
92
 
93
            case FFI_TYPE_UINT8:
94
              *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
95
              break;
96
 
97
            case FFI_TYPE_SINT16:
98
              *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
99
              break;
100
 
101
            case FFI_TYPE_UINT16:
102
              *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
103
              break;
104
 
105
            case FFI_TYPE_STRUCT:
106
              memcpy (argp, *p_argv, z);
107
              break;
108
 
109
            default:
110
              FFI_ASSERT(0);
111
            }
112
          argp += sizeof (UINT64);
113
        }
114
      else if (z == sizeof (UINT32) && align == sizeof (UINT32))
115
        {
116
          switch ((*p_arg)->type)
117
            {
118
            case FFI_TYPE_INT:
119
            case FFI_TYPE_SINT32:
120
              *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
121
              break;
122
 
123
            case FFI_TYPE_FLOAT:
124
            case FFI_TYPE_POINTER:
125
            case FFI_TYPE_UINT32:
126
            case FFI_TYPE_STRUCT:
127
              *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
128
              break;
129
 
130
            default:
131
              FFI_ASSERT(0);
132
              break;
133
            }
134
          argp += sizeof (UINT64);
135
        }
136
      else if (z == sizeof (UINT64)
137
               && align == sizeof (UINT64)
138
               && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
139
        {
140
          *(UINT64 *) argp = *(UINT64 *) (*p_argv);
141
          argp += sizeof (UINT64);
142
        }
143
      else
144
        {
145
          int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
146
 
147
          memcpy (argp, *p_argv, z);
148
          argp += n * sizeof (UINT64);
149
        }
150
    }
151
 
152
  return;
153
}
154
 
155
/* Perform machine dependent cif processing */
156
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
157
{
158
  int i, j;
159
  int size, type;
160
  int n, m;
161
  int greg;
162
  int freg;
163
 
164
  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
165
  freg = 0;
166
  cif->flags2 = 0;
167
 
168
  for (i = j = 0; i < cif->nargs; i++)
169
    {
170
      type = (cif->arg_types)[i]->type;
171
      switch (type)
172
        {
173
        case FFI_TYPE_FLOAT:
174
          greg++;
175
          cif->bytes += sizeof (UINT64) - sizeof (float);
176
          if (freg >= NFREGARG - 1)
177
            continue;
178
          freg++;
179
          cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
180
          break;
181
 
182
        case FFI_TYPE_DOUBLE:
183
          if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
184
            continue;
185
          if ((freg + 1) < NFREGARG)
186
            {
187
              freg = (freg + 1) & ~1;
188
              freg += 2;
189
              cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
190
            }
191
          else
192
            cif->flags2 += FFI_TYPE_INT << (2 * j++);
193
          break;
194
 
195
        default:
196
          size = (cif->arg_types)[i]->size;
197
          if (size < sizeof (UINT64))
198
            cif->bytes += sizeof (UINT64) - size;
199
          n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
200
          if (greg >= NGREGARG)
201
            continue;
202
          else if (greg + n - 1 >= NGREGARG)
203
            greg = NGREGARG;
204
          else
205
            greg += n;
206
          for (m = 0; m < n; m++)
207
            cif->flags2 += FFI_TYPE_INT << (2 * j++);
208
          break;
209
        }
210
    }
211
 
212
  /* Set the return type flag */
213
  switch (cif->rtype->type)
214
    {
215
    case FFI_TYPE_STRUCT:
216
      cif->flags = return_type (cif->rtype);
217
      break;
218
 
219
    case FFI_TYPE_VOID:
220
    case FFI_TYPE_FLOAT:
221
    case FFI_TYPE_DOUBLE:
222
    case FFI_TYPE_SINT64:
223
    case FFI_TYPE_UINT64:
224
      cif->flags = cif->rtype->type;
225
      break;
226
 
227
    default:
228
      cif->flags = FFI_TYPE_INT;
229
      break;
230
    }
231
 
232
  return FFI_OK;
233
}
234
 
235
/*@-declundef@*/
236
/*@-exportheader@*/
237
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
238
                          /*@out@*/ extended_cif *,
239
                          unsigned, unsigned, long long,
240
                          /*@out@*/ unsigned *,
241
                          void (*fn)());
242
/*@=declundef@*/
243
/*@=exportheader@*/
244
 
245
void ffi_call(/*@dependent@*/ ffi_cif *cif,
246
              void (*fn)(),
247
              /*@out@*/ void *rvalue,
248
              /*@dependent@*/ void **avalue)
249
{
250
  extended_cif ecif;
251
  UINT64 trvalue;
252
 
253
  ecif.cif = cif;
254
  ecif.avalue = avalue;
255
 
256
  /* If the return value is a struct and we don't have a return */
257
  /* value address then we need to make one                     */
258
 
259
  if (cif->rtype->type == FFI_TYPE_STRUCT
260
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
261
    ecif.rvalue = &trvalue;
262
  else if ((rvalue == NULL) &&
263
      (cif->rtype->type == FFI_TYPE_STRUCT))
264
    {
265
      /*@-sysunrecog@*/
266
      ecif.rvalue = alloca(cif->rtype->size);
267
      /*@=sysunrecog@*/
268
    }
269
  else
270
    ecif.rvalue = rvalue;
271
 
272
  switch (cif->abi)
273
    {
274
    case FFI_SYSV:
275
      /*@-usedef@*/
276
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
277
                    cif->flags, cif->flags2, ecif.rvalue, fn);
278
      /*@=usedef@*/
279
      break;
280
    default:
281
      FFI_ASSERT(0);
282
      break;
283
    }
284
 
285
  if (rvalue
286
      && cif->rtype->type == FFI_TYPE_STRUCT
287
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
288
    memcpy (rvalue, &trvalue, cif->rtype->size);
289
}
290
 
291
extern void ffi_closure_SYSV (void);
292
extern void __ic_invalidate (void *line);
293
 
294
ffi_status
295
ffi_prep_closure (ffi_closure *closure,
296
                  ffi_cif *cif,
297
                  void (*fun)(ffi_cif*, void*, void**, void*),
298
                  void *user_data)
299
{
300
  unsigned int *tramp;
301
 
302
  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
303
 
304
  tramp = (unsigned int *) &closure->tramp[0];
305
  /* Since ffi_closure is an aligned object, the ffi trampoline is
306
     called as an SHcompact code.  Sigh.
307
     SHcompact part:
308
     mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
309
     SHmedia part:
310
     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
311
     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */
312
#ifdef __LITTLE_ENDIAN__
313
  tramp[0] = 0x7001c701;
314
  tramp[1] = 0x0009402b;
315
#else
316
  tramp[0] = 0xc7017001;
317
  tramp[1] = 0x402b0009;
318
#endif
319
  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
320
  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
321
  tramp[4] = 0x6bf10600;
322
  tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
323
  tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
324
  tramp[7] = 0x4401fff0;
325
 
326
  closure->cif = cif;
327
  closure->fun = fun;
328
  closure->user_data = user_data;
329
 
330
  /* Flush the icache.  */
331
  asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
332
 
333
  return FFI_OK;
334
}
335
 
336
/* Basically the trampoline invokes ffi_closure_SYSV, and on
337
 * entry, r3 holds the address of the closure.
338
 * After storing the registers that could possibly contain
339
 * parameters to be passed into the stack frame and setting
340
 * up space for a return value, ffi_closure_SYSV invokes the
341
 * following helper function to do most of the work.
342
 */
343
 
344
int
345
ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
346
                         UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
347
{
348
  void **avalue;
349
  ffi_type **p_arg;
350
  int i, avn;
351
  int greg, freg;
352
  ffi_cif *cif;
353
 
354
  cif = closure->cif;
355
  avalue = alloca (cif->nargs * sizeof (void *));
356
 
357
  /* Copy the caller's structure return value address so that the closure
358
     returns the data directly to the caller.  */
359
  if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
360
    {
361
      rvalue = *pgr;
362
      greg = 1;
363
    }
364
  else
365
    greg = 0;
366
 
367
  freg = 0;
368
  cif = closure->cif;
369
  avn = cif->nargs;
370
 
371
  /* Grab the addresses of the arguments from the stack frame.  */
372
  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
373
    {
374
      size_t z;
375
      void *p;
376
 
377
      z = (*p_arg)->size;
378
      if (z < sizeof (UINT32))
379
        {
380
          p = pgr + greg++;
381
 
382
          switch ((*p_arg)->type)
383
            {
384
            case FFI_TYPE_SINT8:
385
            case FFI_TYPE_UINT8:
386
            case FFI_TYPE_SINT16:
387
            case FFI_TYPE_UINT16:
388
            case FFI_TYPE_STRUCT:
389
#ifdef __LITTLE_ENDIAN__
390
              avalue[i] = p;
391
#else
392
              avalue[i] = ((char *) p) + sizeof (UINT32) - z;
393
#endif
394
              break;
395
 
396
            default:
397
              FFI_ASSERT(0);
398
            }
399
        }
400
      else if (z == sizeof (UINT32))
401
        {
402
          if ((*p_arg)->type == FFI_TYPE_FLOAT)
403
            {
404
              if (freg < NFREGARG - 1)
405
#ifdef __LITTLE_ENDIAN__
406
                avalue[i] = (UINT32 *) pfr + (1 ^ freg++);
407
#else
408
                avalue[i] = (UINT32 *) pfr + freg++;
409
#endif
410
              else
411
#ifdef __LITTLE_ENDIAN__
412
                avalue[i] = pgr + greg;
413
#else
414
                avalue[i] = (UINT32 *) (pgr + greg) + 1;
415
#endif
416
            }
417
          else
418
#ifdef __LITTLE_ENDIAN__
419
            avalue[i] = pgr + greg;
420
#else
421
            avalue[i] = (UINT32 *) (pgr + greg) + 1;
422
#endif
423
          greg++;
424
        }
425
      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
426
        {
427
          if (freg + 1 >= NFREGARG)
428
            avalue[i] = pgr + greg;
429
          else
430
            {
431
              freg = (freg + 1) & ~1;
432
              avalue[i] = pfr + (freg >> 1);
433
              freg += 2;
434
            }
435
          greg++;
436
        }
437
      else
438
        {
439
          int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
440
 
441
          avalue[i] = pgr + greg;
442
          greg += n;
443
        }
444
    }
445
 
446
  (closure->fun) (cif, rvalue, avalue, closure->user_data);
447
 
448
  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
449
  return return_type (cif->rtype);
450
}
451
 

powered by: WebSVN 2.1.0

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