111
|
1 /* -----------------------------------------------------------------------
|
|
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 }
|