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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libffi/] [src/] [frv/] [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) 2004  Anthony Green
3
   Copyright (C) 2007  Free Software Foundation, Inc.
4
           Copyright (C) 2008  Red Hat, Inc.
5
 
6
   FR-V Foreign Function Interface
7
 
8
   Permission is hereby granted, free of charge, to any person obtaining
9
   a copy of this software and associated documentation files (the
10
   ``Software''), to deal in the Software without restriction, including
11
   without limitation the rights to use, copy, modify, merge, publish,
12
   distribute, sublicense, and/or sell copies of the Software, and to
13
   permit persons to whom the Software is furnished to do so, subject to
14
   the following conditions:
15
 
16
   The above copyright notice and this permission notice shall be included
17
   in all copies or substantial portions of the Software.
18
 
19
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
   DEALINGS IN THE SOFTWARE.
27
   ----------------------------------------------------------------------- */
28
 
29
#include <ffi.h>
30
#include <ffi_common.h>
31
 
32
#include <stdlib.h>
33
 
34
/* ffi_prep_args is called by the assembly routine once stack space
35
   has been allocated for the function's arguments */
36
 
37
void *ffi_prep_args(char *stack, extended_cif *ecif)
38
{
39
  register unsigned int i;
40
  register void **p_argv;
41
  register char *argp;
42
  register ffi_type **p_arg;
43
  register int count = 0;
44
 
45
  p_argv = ecif->avalue;
46
  argp = stack;
47
 
48
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
49
       (i != 0);
50
       i--, p_arg++)
51
    {
52
      size_t z;
53
 
54
      z = (*p_arg)->size;
55
 
56
      if ((*p_arg)->type == FFI_TYPE_STRUCT)
57
        {
58
          z = sizeof(void*);
59
          *(void **) argp = *p_argv;
60
        }
61
      /*      if ((*p_arg)->type == FFI_TYPE_FLOAT)
62
        {
63
          if (count > 24)
64
            {
65
              // This is going on the stack.  Turn it into a double.
66
              *(double *) argp = (double) *(float*)(* p_argv);
67
              z = sizeof(double);
68
            }
69
          else
70
            *(void **) argp = *(void **)(* p_argv);
71
        }  */
72
      else if (z < sizeof(int))
73
        {
74
          z = sizeof(int);
75
          switch ((*p_arg)->type)
76
            {
77
            case FFI_TYPE_SINT8:
78
              *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
79
              break;
80
 
81
            case FFI_TYPE_UINT8:
82
              *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
83
              break;
84
 
85
            case FFI_TYPE_SINT16:
86
              *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
87
              break;
88
 
89
            case FFI_TYPE_UINT16:
90
              *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
91
              break;
92
 
93
            default:
94
              FFI_ASSERT(0);
95
            }
96
        }
97
      else if (z == sizeof(int))
98
        {
99
          *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
100
        }
101
      else
102
        {
103
          memcpy(argp, *p_argv, z);
104
        }
105
      p_argv++;
106
      argp += z;
107
      count += z;
108
    }
109
 
110
  return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
111
}
112
 
113
/* Perform machine dependent cif processing */
114
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
115
{
116
  if (cif->rtype->type == FFI_TYPE_STRUCT)
117
    cif->flags = -1;
118
  else
119
    cif->flags = cif->rtype->size;
120
 
121
  cif->bytes = ALIGN (cif->bytes, 8);
122
 
123
  return FFI_OK;
124
}
125
 
126
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
127
                          extended_cif *,
128
                          unsigned, unsigned,
129
                          unsigned *,
130
                          void (*fn)(void));
131
 
132
void ffi_call(ffi_cif *cif,
133
              void (*fn)(void),
134
              void *rvalue,
135
              void **avalue)
136
{
137
  extended_cif ecif;
138
 
139
  ecif.cif = cif;
140
  ecif.avalue = avalue;
141
 
142
  /* If the return value is a struct and we don't have a return */
143
  /* value address then we need to make one                     */
144
 
145
  if ((rvalue == NULL) &&
146
      (cif->rtype->type == FFI_TYPE_STRUCT))
147
    {
148
      ecif.rvalue = alloca(cif->rtype->size);
149
    }
150
  else
151
    ecif.rvalue = rvalue;
152
 
153
 
154
  switch (cif->abi)
155
    {
156
    case FFI_EABI:
157
      ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
158
                    cif->flags, ecif.rvalue, fn);
159
      break;
160
    default:
161
      FFI_ASSERT(0);
162
      break;
163
    }
164
}
165
 
166
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
167
                       unsigned arg4, unsigned arg5, unsigned arg6)
168
{
169
  /* This function is called by a trampoline.  The trampoline stows a
170
     pointer to the ffi_closure object in gr7.  We must save this
171
     pointer in a place that will persist while we do our work.  */
172
  register ffi_closure *creg __asm__ ("gr7");
173
  ffi_closure *closure = creg;
174
 
175
  /* Arguments that don't fit in registers are found on the stack
176
     at a fixed offset above the current frame pointer.  */
177
  register char *frame_pointer __asm__ ("fp");
178
  char *stack_args = frame_pointer + 16;
179
 
180
  /* Lay the register arguments down in a continuous chunk of memory.  */
181
  unsigned register_args[6] =
182
    { arg1, arg2, arg3, arg4, arg5, arg6 };
183
 
184
  ffi_cif *cif = closure->cif;
185
  ffi_type **arg_types = cif->arg_types;
186
  void **avalue = alloca (cif->nargs * sizeof(void *));
187
  char *ptr = (char *) register_args;
188
  int i;
189
 
190
  /* Find the address of each argument.  */
191
  for (i = 0; i < cif->nargs; i++)
192
    {
193
      switch (arg_types[i]->type)
194
        {
195
        case FFI_TYPE_SINT8:
196
        case FFI_TYPE_UINT8:
197
          avalue[i] = ptr + 3;
198
          break;
199
        case FFI_TYPE_SINT16:
200
        case FFI_TYPE_UINT16:
201
          avalue[i] = ptr + 2;
202
          break;
203
        case FFI_TYPE_SINT32:
204
        case FFI_TYPE_UINT32:
205
        case FFI_TYPE_FLOAT:
206
          avalue[i] = ptr;
207
          break;
208
        case FFI_TYPE_STRUCT:
209
          avalue[i] = *(void**)ptr;
210
          break;
211
        default:
212
          /* This is an 8-byte value.  */
213
          avalue[i] = ptr;
214
          ptr += 4;
215
          break;
216
        }
217
      ptr += 4;
218
 
219
      /* If we've handled more arguments than fit in registers,
220
         start looking at the those passed on the stack.  */
221
      if (ptr == ((char *)register_args + (6*4)))
222
        ptr = stack_args;
223
    }
224
 
225
  /* Invoke the closure.  */
226
  if (cif->rtype->type == FFI_TYPE_STRUCT)
227
    {
228
      /* The caller allocates space for the return structure, and
229
       passes a pointer to this space in gr3.  Use this value directly
230
       as the return value.  */
231
      register void *return_struct_ptr __asm__("gr3");
232
      (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
233
    }
234
  else
235
    {
236
      /* Allocate space for the return value and call the function.  */
237
      long long rvalue;
238
      (closure->fun) (cif, &rvalue, avalue, closure->user_data);
239
 
240
      /* Functions return 4-byte or smaller results in gr8.  8-byte
241
         values also use gr9.  We fill the both, even for small return
242
         values, just to avoid a branch.  */
243
      asm ("ldi  @(%0, #0), gr8" : : "r" (&rvalue));
244
      asm ("ldi  @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
245
    }
246
}
247
 
248
ffi_status
249
ffi_prep_closure_loc (ffi_closure* closure,
250
                      ffi_cif* cif,
251
                      void (*fun)(ffi_cif*, void*, void**, void*),
252
                      void *user_data,
253
                      void *codeloc)
254
{
255
  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
256
  unsigned long fn = (long) ffi_closure_eabi;
257
  unsigned long cls = (long) codeloc;
258
#ifdef __FRV_FDPIC__
259
  register void *got __asm__("gr15");
260
#endif
261
  int i;
262
 
263
  fn = (unsigned long) ffi_closure_eabi;
264
 
265
#ifdef __FRV_FDPIC__
266
  tramp[0] = &((unsigned int *)codeloc)[2];
267
  tramp[1] = got;
268
  tramp[2] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
269
  tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
270
  tramp[4] = 0x8cf80000 + (fn  >> 16);    /* sethi hi(fn), gr6     */
271
  tramp[5] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
272
  tramp[6] = 0x9cc86000;                  /* ldi @(gr6, #0), gr14  */
273
  tramp[7] = 0x8030e000;                  /* jmpl @(gr14, gr0)     */
274
#else
275
  tramp[0] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
276
  tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
277
  tramp[2] = 0x8cf80000 + (fn  >> 16);    /* sethi hi(fn), gr6     */
278
  tramp[3] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
279
  tramp[4] = 0x80300006;                  /* jmpl @(gr0, gr6)      */
280
#endif
281
 
282
  closure->cif = cif;
283
  closure->fun = fun;
284
  closure->user_data = user_data;
285
 
286
  /* Cache flushing.  */
287
  for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
288
    __asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
289
                      "r" (codeloc));
290
 
291
  return FFI_OK;
292
}

powered by: WebSVN 2.1.0

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