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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 732 jeremybenn
/* -----------------------------------------------------------------------
2
   ffi.c
3
 
4
   m68k Foreign Function Interface
5
   ----------------------------------------------------------------------- */
6
 
7
#include <ffi.h>
8
#include <ffi_common.h>
9
 
10
#include <stdlib.h>
11
#include <unistd.h>
12
#ifdef __rtems__
13
void rtems_cache_flush_multiple_data_lines( const void *, size_t );
14
#else
15
#include <sys/syscall.h>
16
#include <asm/cachectl.h>
17
#endif
18
 
19
void ffi_call_SYSV (extended_cif *,
20
                    unsigned, unsigned,
21
                    void *, void (*fn) ());
22
void *ffi_prep_args (void *stack, extended_cif *ecif);
23
void ffi_closure_SYSV (ffi_closure *);
24
void ffi_closure_struct_SYSV (ffi_closure *);
25
unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
26
                                     void *resp, void *args);
27
 
28
/* ffi_prep_args is called by the assembly routine once stack space has
29
   been allocated for the function's arguments.  */
30
 
31
void *
32
ffi_prep_args (void *stack, extended_cif *ecif)
33
{
34
  unsigned int i;
35
  void **p_argv;
36
  char *argp;
37
  ffi_type **p_arg;
38
  void *struct_value_ptr;
39
 
40
  argp = stack;
41
 
42
  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
43
      && !ecif->cif->flags)
44
    struct_value_ptr = ecif->rvalue;
45
  else
46
    struct_value_ptr = NULL;
47
 
48
  p_argv = ecif->avalue;
49
 
50
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
51
       i != 0;
52
       i--, p_arg++)
53
    {
54
      size_t z;
55
 
56
      z = (*p_arg)->size;
57
      if (z < sizeof (int))
58
        {
59
          switch ((*p_arg)->type)
60
            {
61
            case FFI_TYPE_SINT8:
62
              *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
63
              break;
64
 
65
            case FFI_TYPE_UINT8:
66
              *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
67
              break;
68
 
69
            case FFI_TYPE_SINT16:
70
              *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
71
              break;
72
 
73
            case FFI_TYPE_UINT16:
74
              *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
75
              break;
76
 
77
            case FFI_TYPE_STRUCT:
78
              memcpy (argp + sizeof (int) - z, *p_argv, z);
79
              break;
80
 
81
            default:
82
              FFI_ASSERT (0);
83
            }
84
          z = sizeof (int);
85
        }
86
      else
87
        {
88
          memcpy (argp, *p_argv, z);
89
 
90
          /* Align if necessary.  */
91
          if ((sizeof(int) - 1) & z)
92
            z = ALIGN(z, sizeof(int));
93
        }
94
 
95
      p_argv++;
96
      argp += z;
97
    }
98
 
99
  return struct_value_ptr;
100
}
101
 
102
#define CIF_FLAGS_INT           1
103
#define CIF_FLAGS_DINT          2
104
#define CIF_FLAGS_FLOAT         4
105
#define CIF_FLAGS_DOUBLE        8
106
#define CIF_FLAGS_LDOUBLE       16
107
#define CIF_FLAGS_POINTER       32
108
#define CIF_FLAGS_STRUCT1       64
109
#define CIF_FLAGS_STRUCT2       128
110
 
111
/* Perform machine dependent cif processing */
112
ffi_status
113
ffi_prep_cif_machdep (ffi_cif *cif)
114
{
115
  /* Set the return type flag */
116
  switch (cif->rtype->type)
117
    {
118
    case FFI_TYPE_VOID:
119
      cif->flags = 0;
120
      break;
121
 
122
    case FFI_TYPE_STRUCT:
123
      switch (cif->rtype->size)
124
        {
125
        case 1:
126
          cif->flags = CIF_FLAGS_STRUCT1;
127
          break;
128
        case 2:
129
          cif->flags = CIF_FLAGS_STRUCT2;
130
          break;
131
        case 4:
132
          cif->flags = CIF_FLAGS_INT;
133
          break;
134
        case 8:
135
          cif->flags = CIF_FLAGS_DINT;
136
          break;
137
        default:
138
          cif->flags = 0;
139
          break;
140
        }
141
      break;
142
 
143
    case FFI_TYPE_FLOAT:
144
      cif->flags = CIF_FLAGS_FLOAT;
145
      break;
146
 
147
    case FFI_TYPE_DOUBLE:
148
      cif->flags = CIF_FLAGS_DOUBLE;
149
      break;
150
 
151
#if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
152
    case FFI_TYPE_LONGDOUBLE:
153
      cif->flags = CIF_FLAGS_LDOUBLE;
154
      break;
155
#endif
156
 
157
    case FFI_TYPE_POINTER:
158
      cif->flags = CIF_FLAGS_POINTER;
159
      break;
160
 
161
    case FFI_TYPE_SINT64:
162
    case FFI_TYPE_UINT64:
163
      cif->flags = CIF_FLAGS_DINT;
164
      break;
165
 
166
    default:
167
      cif->flags = CIF_FLAGS_INT;
168
      break;
169
    }
170
 
171
  return FFI_OK;
172
}
173
 
174
void
175
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
176
{
177
  extended_cif ecif;
178
 
179
  ecif.cif = cif;
180
  ecif.avalue = avalue;
181
 
182
  /* If the return value is a struct and we don't have a return value
183
     address then we need to make one.  */
184
 
185
  if (rvalue == NULL
186
      && cif->rtype->type == FFI_TYPE_STRUCT
187
      && cif->rtype->size > 8)
188
    ecif.rvalue = alloca (cif->rtype->size);
189
  else
190
    ecif.rvalue = rvalue;
191
 
192
  switch (cif->abi)
193
    {
194
    case FFI_SYSV:
195
      ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
196
                     ecif.rvalue, fn);
197
      break;
198
 
199
    default:
200
      FFI_ASSERT (0);
201
      break;
202
    }
203
}
204
 
205
static void
206
ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
207
{
208
  unsigned int i;
209
  void **p_argv;
210
  char *argp;
211
  ffi_type **p_arg;
212
 
213
  argp = stack;
214
  p_argv = avalue;
215
 
216
  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
217
    {
218
      size_t z;
219
 
220
      z = (*p_arg)->size;
221
      if (z <= 4)
222
        {
223
          *p_argv = (void *) (argp + 4 - z);
224
 
225
          z = 4;
226
        }
227
      else
228
        {
229
          *p_argv = (void *) argp;
230
 
231
          /* Align if necessary */
232
          if ((sizeof(int) - 1) & z)
233
            z = ALIGN(z, sizeof(int));
234
        }
235
 
236
      p_argv++;
237
      argp += z;
238
    }
239
}
240
 
241
unsigned int
242
ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
243
{
244
  ffi_cif *cif;
245
  void **arg_area;
246
 
247
  cif = closure->cif;
248
  arg_area = (void**) alloca (cif->nargs * sizeof (void *));
249
 
250
  ffi_prep_incoming_args_SYSV(args, arg_area, cif);
251
 
252
  (closure->fun) (cif, resp, arg_area, closure->user_data);
253
 
254
  return cif->flags;
255
}
256
 
257
ffi_status
258
ffi_prep_closure_loc (ffi_closure* closure,
259
                      ffi_cif* cif,
260
                      void (*fun)(ffi_cif*,void*,void**,void*),
261
                      void *user_data,
262
                      void *codeloc)
263
{
264
  FFI_ASSERT (cif->abi == FFI_SYSV);
265
 
266
  *(unsigned short *)closure->tramp = 0x207c;
267
  *(void **)(closure->tramp + 2) = codeloc;
268
  *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
269
  if (cif->rtype->type == FFI_TYPE_STRUCT
270
      && !cif->flags)
271
    *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
272
  else
273
    *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
274
 
275
#ifdef __rtems__
276
  rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
277
#else
278
  syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
279
          FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
280
#endif
281
 
282
  closure->cif  = cif;
283
  closure->user_data = user_data;
284
  closure->fun  = fun;
285
 
286
  return FFI_OK;
287
}
288
 

powered by: WebSVN 2.1.0

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