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

Subversion Repositories openrisc

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

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  Renesas Technology
3
           Copyright (c) 2008  Red Hat, Inc.
4
 
5
   M32R 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, EXPRESS
19
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
22
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
   OTHER DEALINGS IN THE SOFTWARE.
25
   ----------------------------------------------------------------------- */
26
 
27
#include <ffi.h>
28
#include <ffi_common.h>
29
 
30
#include <stdlib.h>
31
 
32
/* ffi_prep_args is called by the assembly routine once stack
33
   space has been allocated for the function's arguments.  */
34
 
35
void ffi_prep_args(char *stack, extended_cif *ecif)
36
{
37
  unsigned int i;
38
  int tmp;
39
  unsigned int avn;
40
  void **p_argv;
41
  char *argp;
42
  ffi_type **p_arg;
43
 
44
  tmp = 0;
45
  argp = stack;
46
 
47
  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
48
    {
49
      *(void **) argp = ecif->rvalue;
50
      argp += 4;
51
    }
52
 
53
  avn = ecif->cif->nargs;
54
  p_argv = ecif->avalue;
55
 
56
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
57
       (i != 0) && (avn != 0);
58
       i--, p_arg++)
59
    {
60
      size_t z;
61
 
62
      /* Align if necessary.  */
63
      if (((*p_arg)->alignment - 1) & (unsigned) argp)
64
        argp = (char *) ALIGN (argp, (*p_arg)->alignment);
65
 
66
      if (avn != 0)
67
        {
68
          avn--;
69
          z = (*p_arg)->size;
70
          if (z < sizeof (int))
71
            {
72
              z = sizeof (int);
73
 
74
              switch ((*p_arg)->type)
75
                {
76
                case FFI_TYPE_SINT8:
77
                  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
78
                  break;
79
 
80
                case FFI_TYPE_UINT8:
81
                  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
82
                  break;
83
 
84
                case FFI_TYPE_SINT16:
85
                  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
86
                  break;
87
 
88
                case FFI_TYPE_UINT16:
89
                  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
90
                  break;
91
 
92
                case FFI_TYPE_STRUCT:
93
                  z = (*p_arg)->size;
94
                  if ((*p_arg)->alignment != 1)
95
                    memcpy (argp, *p_argv, z);
96
                  else
97
                    memcpy (argp + 4 - z, *p_argv, z);
98
                  z = sizeof (int);
99
                  break;
100
 
101
                default:
102
                  FFI_ASSERT(0);
103
                }
104
            }
105
          else if (z == sizeof (int))
106
            {
107
               *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
108
            }
109
          else
110
            {
111
              if ((*p_arg)->type == FFI_TYPE_STRUCT)
112
                {
113
                  if (z > 8)
114
                    {
115
                      *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
116
                      z = sizeof(void *);
117
                    }
118
                  else
119
                    {
120
                      memcpy(argp, *p_argv, z);
121
                      z = 8;
122
                    }
123
                }
124
              else
125
                {
126
                  /* Double or long long 64bit.  */
127
                  memcpy (argp, *p_argv, z);
128
                }
129
            }
130
          p_argv++;
131
          argp += z;
132
        }
133
    }
134
 
135
  return;
136
}
137
 
138
/* Perform machine dependent cif processing.  */
139
ffi_status
140
ffi_prep_cif_machdep(ffi_cif *cif)
141
{
142
  /* Set the return type flag.  */
143
  switch (cif->rtype->type)
144
    {
145
    case FFI_TYPE_VOID:
146
      cif->flags = (unsigned) cif->rtype->type;
147
      break;
148
 
149
    case FFI_TYPE_STRUCT:
150
      if (cif->rtype->size <= 4)
151
        cif->flags = FFI_TYPE_INT;
152
 
153
      else if (cif->rtype->size <= 8)
154
        cif->flags = FFI_TYPE_DOUBLE;
155
 
156
      else
157
        cif->flags = (unsigned) cif->rtype->type;
158
      break;
159
 
160
    case FFI_TYPE_SINT64:
161
    case FFI_TYPE_UINT64:
162
    case FFI_TYPE_DOUBLE:
163
      cif->flags = FFI_TYPE_DOUBLE;
164
      break;
165
 
166
    case FFI_TYPE_FLOAT:
167
    default:
168
      cif->flags = FFI_TYPE_INT;
169
      break;
170
    }
171
 
172
  return FFI_OK;
173
}
174
 
175
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
176
                          unsigned, unsigned, unsigned *, void (*fn)(void));
177
 
178
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
179
{
180
  extended_cif ecif;
181
 
182
  ecif.cif = cif;
183
  ecif.avalue = avalue;
184
 
185
  /* If the return value is a struct and we don't have
186
     a return value address then we need to make one.  */
187
  if ((rvalue == NULL) &&
188
      (cif->rtype->type == FFI_TYPE_STRUCT))
189
    {
190
      ecif.rvalue = alloca (cif->rtype->size);
191
    }
192
  else
193
    ecif.rvalue = rvalue;
194
 
195
  switch (cif->abi)
196
    {
197
    case FFI_SYSV:
198
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
199
                    cif->flags, ecif.rvalue, fn);
200
      if (cif->rtype->type == FFI_TYPE_STRUCT)
201
        {
202
          int size = cif->rtype->size;
203
          int align = cif->rtype->alignment;
204
 
205
          if (size < 4)
206
            {
207
              if (align == 1)
208
                *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
209
            }
210
          else if (4 < size && size < 8)
211
            {
212
              if (align == 1)
213
                {
214
                  memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
215
                }
216
              else if (align == 2)
217
                {
218
                  if (size & 1)
219
                    size += 1;
220
 
221
                  if (size != 8)
222
                    memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
223
                }
224
            }
225
        }
226
      break;
227
 
228
    default:
229
      FFI_ASSERT(0);
230
      break;
231
    }
232
}

powered by: WebSVN 2.1.0

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