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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libffi/] [src/] [alpha/] [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) 1998, 2001 Red Hat, Inc.
3
 
4
   Alpha 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
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)());
32
extern void ffi_closure_osf(void);
33
 
34
 
35
ffi_status
36
ffi_prep_cif_machdep(ffi_cif *cif)
37
{
38
  /* Adjust cif->bytes to represent a minimum 6 words for the temporary
39
     register argument loading area.  */
40
  if (cif->bytes < 6*FFI_SIZEOF_ARG)
41
    cif->bytes = 6*FFI_SIZEOF_ARG;
42
 
43
  /* Set the return type flag */
44
  switch (cif->rtype->type)
45
    {
46
    case FFI_TYPE_STRUCT:
47
    case FFI_TYPE_FLOAT:
48
    case FFI_TYPE_DOUBLE:
49
      cif->flags = cif->rtype->type;
50
      break;
51
 
52
    default:
53
      cif->flags = FFI_TYPE_INT;
54
      break;
55
    }
56
 
57
  return FFI_OK;
58
}
59
 
60
void
61
ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
62
{
63
  unsigned long *stack, *argp;
64
  long i, avn;
65
  ffi_type **arg_types;
66
 
67
  FFI_ASSERT (cif->abi == FFI_OSF);
68
 
69
  /* If the return value is a struct and we don't have a return
70
     value address then we need to make one.  */
71
  if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
72
    rvalue = alloca(cif->rtype->size);
73
 
74
  /* Allocate the space for the arguments, plus 4 words of temp
75
     space for ffi_call_osf.  */
76
  argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
77
 
78
  if (cif->flags == FFI_TYPE_STRUCT)
79
    *(void **) argp++ = rvalue;
80
 
81
  i = 0;
82
  avn = cif->nargs;
83
  arg_types = cif->arg_types;
84
 
85
  while (i < avn)
86
    {
87
      switch ((*arg_types)->type)
88
        {
89
        case FFI_TYPE_SINT8:
90
          *(SINT64 *) argp = *(SINT8 *)(* avalue);
91
          break;
92
 
93
        case FFI_TYPE_UINT8:
94
          *(SINT64 *) argp = *(UINT8 *)(* avalue);
95
          break;
96
 
97
        case FFI_TYPE_SINT16:
98
          *(SINT64 *) argp = *(SINT16 *)(* avalue);
99
          break;
100
 
101
        case FFI_TYPE_UINT16:
102
          *(SINT64 *) argp = *(UINT16 *)(* avalue);
103
          break;
104
 
105
        case FFI_TYPE_SINT32:
106
        case FFI_TYPE_UINT32:
107
          /* Note that unsigned 32-bit quantities are sign extended.  */
108
          *(SINT64 *) argp = *(SINT32 *)(* avalue);
109
          break;
110
 
111
        case FFI_TYPE_SINT64:
112
        case FFI_TYPE_UINT64:
113
        case FFI_TYPE_POINTER:
114
          *(UINT64 *) argp = *(UINT64 *)(* avalue);
115
          break;
116
 
117
        case FFI_TYPE_FLOAT:
118
          if (argp - stack < 6)
119
            {
120
              /* Note the conversion -- all the fp regs are loaded as
121
                 doubles.  The in-register format is the same.  */
122
              *(double *) argp = *(float *)(* avalue);
123
            }
124
          else
125
            *(float *) argp = *(float *)(* avalue);
126
          break;
127
 
128
        case FFI_TYPE_DOUBLE:
129
          *(double *) argp = *(double *)(* avalue);
130
          break;
131
 
132
        case FFI_TYPE_STRUCT:
133
          memcpy(argp, *avalue, (*arg_types)->size);
134
          break;
135
 
136
        default:
137
          FFI_ASSERT(0);
138
        }
139
 
140
      argp += ALIGN((*arg_types)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
141
      i++, arg_types++, avalue++;
142
    }
143
 
144
  ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
145
}
146
 
147
 
148
ffi_status
149
ffi_prep_closure (ffi_closure* closure,
150
                  ffi_cif* cif,
151
                  void (*fun)(ffi_cif*, void*, void**, void*),
152
                  void *user_data)
153
{
154
  unsigned int *tramp;
155
 
156
  FFI_ASSERT (cif->abi == FFI_OSF);
157
 
158
  tramp = (unsigned int *) &closure->tramp[0];
159
  tramp[0] = 0x47fb0401; /* mov $27,$1           */
160
  tramp[1] = 0xa77b0010;        /* ldq $27,16($27)      */
161
  tramp[2] = 0x6bfb0000;        /* jmp $31,($27),0      */
162
  tramp[3] = 0x47ff041f;        /* nop                  */
163
  *(void **) &tramp[4] = ffi_closure_osf;
164
 
165
  closure->cif = cif;
166
  closure->fun = fun;
167
  closure->user_data = user_data;
168
 
169
  /* Flush the Icache.
170
 
171
     Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
172
     instead, since both Compaq as and gas can handle it.
173
 
174
     0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>.  */
175
  asm volatile ("call_pal 0x86" : : : "memory");
176
 
177
  return FFI_OK;
178
}
179
 
180
int
181
ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
182
{
183
  ffi_cif *cif;
184
  void **avalue;
185
  ffi_type **arg_types;
186
  long i, avn, argn;
187
 
188
  cif = closure->cif;
189
  avalue = alloca(cif->nargs * sizeof(void *));
190
 
191
  argn = 0;
192
 
193
  /* Copy the caller's structure return address to that the closure
194
     returns the data directly to the caller.  */
195
  if (cif->flags == FFI_TYPE_STRUCT)
196
    {
197
      rvalue = (void *) argp[0];
198
      argn = 1;
199
    }
200
 
201
  i = 0;
202
  avn = cif->nargs;
203
  arg_types = cif->arg_types;
204
 
205
  /* Grab the addresses of the arguments from the stack frame.  */
206
  while (i < avn)
207
    {
208
      switch (arg_types[i]->type)
209
        {
210
        case FFI_TYPE_SINT8:
211
        case FFI_TYPE_UINT8:
212
        case FFI_TYPE_SINT16:
213
        case FFI_TYPE_UINT16:
214
        case FFI_TYPE_SINT32:
215
        case FFI_TYPE_UINT32:
216
        case FFI_TYPE_SINT64:
217
        case FFI_TYPE_UINT64:
218
        case FFI_TYPE_POINTER:
219
        case FFI_TYPE_STRUCT:
220
          avalue[i] = &argp[argn];
221
          break;
222
 
223
        case FFI_TYPE_FLOAT:
224
          if (argn < 6)
225
            {
226
              /* Floats coming from registers need conversion from double
227
                 back to float format.  */
228
              *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
229
              avalue[i] = &argp[argn - 6];
230
            }
231
          else
232
            avalue[i] = &argp[argn];
233
          break;
234
 
235
        case FFI_TYPE_DOUBLE:
236
          avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
237
          break;
238
 
239
        default:
240
          FFI_ASSERT(0);
241
        }
242
 
243
      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
244
      i++;
245
    }
246
 
247
  /* Invoke the closure.  */
248
  (closure->fun) (cif, rvalue, avalue, closure->user_data);
249
 
250
  /* Tell ffi_closure_osf how to perform return type promotions.  */
251
  return cif->rtype->type;
252
}

powered by: WebSVN 2.1.0

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