Mercurial > hg > CbC > CbC_gcc
comparison libffi/src/arc/ffi.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* ----------------------------------------------------------------------- | |
2 ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com) | |
3 | |
4 ARC 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 RENESAS TECHNOLOGY 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 #include <stdint.h> | |
31 | |
32 #include <sys/cachectl.h> | |
33 | |
34 /* for little endian ARC, the code is in fact stored as mixed endian for | |
35 performance reasons */ | |
36 #if __BIG_ENDIAN__ | |
37 #define CODE_ENDIAN(x) (x) | |
38 #else | |
39 #define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16)) | |
40 #endif | |
41 | |
42 /* ffi_prep_args is called by the assembly routine once stack | |
43 space has been allocated for the function's arguments. */ | |
44 | |
45 void | |
46 ffi_prep_args (char *stack, extended_cif * ecif) | |
47 { | |
48 unsigned int i; | |
49 int tmp; | |
50 void **p_argv; | |
51 char *argp; | |
52 ffi_type **p_arg; | |
53 | |
54 tmp = 0; | |
55 argp = stack; | |
56 | |
57 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) | |
58 { | |
59 *(void **) argp = ecif->rvalue; | |
60 argp += 4; | |
61 } | |
62 | |
63 p_argv = ecif->avalue; | |
64 | |
65 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; | |
66 (i != 0); i--, p_arg++) | |
67 { | |
68 size_t z; | |
69 int alignment; | |
70 | |
71 /* align alignment to 4 */ | |
72 alignment = (((*p_arg)->alignment - 1) | 3) + 1; | |
73 | |
74 /* Align if necessary. */ | |
75 if ((alignment - 1) & (unsigned) argp) | |
76 argp = (char *) ALIGN (argp, alignment); | |
77 | |
78 z = (*p_arg)->size; | |
79 if (z < sizeof (int)) | |
80 { | |
81 z = sizeof (int); | |
82 | |
83 switch ((*p_arg)->type) | |
84 { | |
85 case FFI_TYPE_SINT8: | |
86 *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv); | |
87 break; | |
88 | |
89 case FFI_TYPE_UINT8: | |
90 *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv); | |
91 break; | |
92 | |
93 case FFI_TYPE_SINT16: | |
94 *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv); | |
95 break; | |
96 | |
97 case FFI_TYPE_UINT16: | |
98 *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv); | |
99 break; | |
100 | |
101 case FFI_TYPE_STRUCT: | |
102 memcpy (argp, *p_argv, (*p_arg)->size); | |
103 break; | |
104 | |
105 default: | |
106 FFI_ASSERT (0); | |
107 } | |
108 } | |
109 else if (z == sizeof (int)) | |
110 { | |
111 *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv); | |
112 } | |
113 else | |
114 { | |
115 if ((*p_arg)->type == FFI_TYPE_STRUCT) | |
116 { | |
117 memcpy (argp, *p_argv, z); | |
118 } | |
119 else | |
120 { | |
121 /* Double or long long 64bit. */ | |
122 memcpy (argp, *p_argv, z); | |
123 } | |
124 } | |
125 p_argv++; | |
126 argp += z; | |
127 } | |
128 | |
129 return; | |
130 } | |
131 | |
132 /* Perform machine dependent cif processing. */ | |
133 ffi_status | |
134 ffi_prep_cif_machdep (ffi_cif * cif) | |
135 { | |
136 /* Set the return type flag. */ | |
137 switch (cif->rtype->type) | |
138 { | |
139 case FFI_TYPE_VOID: | |
140 cif->flags = (unsigned) cif->rtype->type; | |
141 break; | |
142 | |
143 case FFI_TYPE_STRUCT: | |
144 cif->flags = (unsigned) cif->rtype->type; | |
145 break; | |
146 | |
147 case FFI_TYPE_SINT64: | |
148 case FFI_TYPE_UINT64: | |
149 case FFI_TYPE_DOUBLE: | |
150 cif->flags = FFI_TYPE_DOUBLE; | |
151 break; | |
152 | |
153 case FFI_TYPE_FLOAT: | |
154 default: | |
155 cif->flags = FFI_TYPE_INT; | |
156 break; | |
157 } | |
158 | |
159 return FFI_OK; | |
160 } | |
161 | |
162 extern void ffi_call_ARCompact (void (*)(char *, extended_cif *), | |
163 extended_cif *, unsigned, unsigned, | |
164 unsigned *, void (*fn) (void)); | |
165 | |
166 void | |
167 ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue) | |
168 { | |
169 extended_cif ecif; | |
170 | |
171 ecif.cif = cif; | |
172 ecif.avalue = avalue; | |
173 | |
174 /* If the return value is a struct and we don't have | |
175 a return value address then we need to make one. */ | |
176 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) | |
177 { | |
178 ecif.rvalue = alloca (cif->rtype->size); | |
179 } | |
180 else | |
181 ecif.rvalue = rvalue; | |
182 | |
183 switch (cif->abi) | |
184 { | |
185 case FFI_ARCOMPACT: | |
186 ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes, | |
187 cif->flags, ecif.rvalue, fn); | |
188 break; | |
189 | |
190 default: | |
191 FFI_ASSERT (0); | |
192 break; | |
193 } | |
194 } | |
195 | |
196 int | |
197 ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue, | |
198 ffi_arg * args) | |
199 { | |
200 void **arg_area, **p_argv; | |
201 ffi_cif *cif = closure->cif; | |
202 char *argp = (char *) args; | |
203 ffi_type **p_argt; | |
204 int i; | |
205 | |
206 arg_area = (void **) alloca (cif->nargs * sizeof (void *)); | |
207 | |
208 /* handle hidden argument */ | |
209 if (cif->flags == FFI_TYPE_STRUCT) | |
210 { | |
211 rvalue = *(void **) argp; | |
212 argp += 4; | |
213 } | |
214 | |
215 p_argv = arg_area; | |
216 | |
217 for (i = 0, p_argt = cif->arg_types; i < cif->nargs; | |
218 i++, p_argt++, p_argv++) | |
219 { | |
220 size_t z; | |
221 int alignment; | |
222 | |
223 /* align alignment to 4 */ | |
224 alignment = (((*p_argt)->alignment - 1) | 3) + 1; | |
225 | |
226 /* Align if necessary. */ | |
227 if ((alignment - 1) & (unsigned) argp) | |
228 argp = (char *) ALIGN (argp, alignment); | |
229 | |
230 z = (*p_argt)->size; | |
231 *p_argv = (void *) argp; | |
232 argp += z; | |
233 } | |
234 | |
235 (closure->fun) (cif, rvalue, arg_area, closure->user_data); | |
236 | |
237 return cif->flags; | |
238 } | |
239 | |
240 extern void ffi_closure_ARCompact (void); | |
241 | |
242 ffi_status | |
243 ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif, | |
244 void (*fun) (ffi_cif *, void *, void **, void *), | |
245 void *user_data, void *codeloc) | |
246 { | |
247 uint32_t *tramp = (uint32_t *) & (closure->tramp[0]); | |
248 | |
249 switch (cif->abi) | |
250 { | |
251 case FFI_ARCOMPACT: | |
252 FFI_ASSERT (tramp == codeloc); | |
253 tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */ | |
254 tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */ | |
255 tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact); | |
256 break; | |
257 | |
258 default: | |
259 return FFI_BAD_ABI; | |
260 } | |
261 | |
262 closure->cif = cif; | |
263 closure->fun = fun; | |
264 closure->user_data = user_data; | |
265 cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE); | |
266 | |
267 return FFI_OK; | |
268 } |