annotate libffi/src/arc/ffi.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* -----------------------------------------------------------------------
kono
parents:
diff changeset
2 ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 ARC Foreign Function Interface
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 Permission is hereby granted, free of charge, to any person obtaining
kono
parents:
diff changeset
7 a copy of this software and associated documentation files (the
kono
parents:
diff changeset
8 ``Software''), to deal in the Software without restriction, including
kono
parents:
diff changeset
9 without limitation the rights to use, copy, modify, merge, publish,
kono
parents:
diff changeset
10 distribute, sublicense, and/or sell copies of the Software, and to
kono
parents:
diff changeset
11 permit persons to whom the Software is furnished to do so, subject to
kono
parents:
diff changeset
12 the following conditions:
kono
parents:
diff changeset
13
kono
parents:
diff changeset
14 The above copyright notice and this permission notice shall be included
kono
parents:
diff changeset
15 in all copies or substantial portions of the Software.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
kono
parents:
diff changeset
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
kono
parents:
diff changeset
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
kono
parents:
diff changeset
20 IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
kono
parents:
diff changeset
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
kono
parents:
diff changeset
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
kono
parents:
diff changeset
23 OTHER DEALINGS IN THE SOFTWARE.
kono
parents:
diff changeset
24 ----------------------------------------------------------------------- */
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 #include <ffi.h>
kono
parents:
diff changeset
27 #include <ffi_common.h>
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 #include <stdlib.h>
kono
parents:
diff changeset
30 #include <stdint.h>
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 #include <sys/cachectl.h>
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 /* for little endian ARC, the code is in fact stored as mixed endian for
kono
parents:
diff changeset
35 performance reasons */
kono
parents:
diff changeset
36 #if __BIG_ENDIAN__
kono
parents:
diff changeset
37 #define CODE_ENDIAN(x) (x)
kono
parents:
diff changeset
38 #else
kono
parents:
diff changeset
39 #define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
kono
parents:
diff changeset
40 #endif
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 /* ffi_prep_args is called by the assembly routine once stack
kono
parents:
diff changeset
43 space has been allocated for the function's arguments. */
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 void
kono
parents:
diff changeset
46 ffi_prep_args (char *stack, extended_cif * ecif)
kono
parents:
diff changeset
47 {
kono
parents:
diff changeset
48 unsigned int i;
kono
parents:
diff changeset
49 int tmp;
kono
parents:
diff changeset
50 void **p_argv;
kono
parents:
diff changeset
51 char *argp;
kono
parents:
diff changeset
52 ffi_type **p_arg;
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 tmp = 0;
kono
parents:
diff changeset
55 argp = stack;
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
kono
parents:
diff changeset
58 {
kono
parents:
diff changeset
59 *(void **) argp = ecif->rvalue;
kono
parents:
diff changeset
60 argp += 4;
kono
parents:
diff changeset
61 }
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 p_argv = ecif->avalue;
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
kono
parents:
diff changeset
66 (i != 0); i--, p_arg++)
kono
parents:
diff changeset
67 {
kono
parents:
diff changeset
68 size_t z;
kono
parents:
diff changeset
69 int alignment;
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 /* align alignment to 4 */
kono
parents:
diff changeset
72 alignment = (((*p_arg)->alignment - 1) | 3) + 1;
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 /* Align if necessary. */
kono
parents:
diff changeset
75 if ((alignment - 1) & (unsigned) argp)
kono
parents:
diff changeset
76 argp = (char *) ALIGN (argp, alignment);
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 z = (*p_arg)->size;
kono
parents:
diff changeset
79 if (z < sizeof (int))
kono
parents:
diff changeset
80 {
kono
parents:
diff changeset
81 z = sizeof (int);
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 switch ((*p_arg)->type)
kono
parents:
diff changeset
84 {
kono
parents:
diff changeset
85 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
86 *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
kono
parents:
diff changeset
87 break;
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 case FFI_TYPE_UINT8:
kono
parents:
diff changeset
90 *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
kono
parents:
diff changeset
91 break;
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
94 *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
kono
parents:
diff changeset
95 break;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 case FFI_TYPE_UINT16:
kono
parents:
diff changeset
98 *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
kono
parents:
diff changeset
99 break;
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
102 memcpy (argp, *p_argv, (*p_arg)->size);
kono
parents:
diff changeset
103 break;
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 default:
kono
parents:
diff changeset
106 FFI_ASSERT (0);
kono
parents:
diff changeset
107 }
kono
parents:
diff changeset
108 }
kono
parents:
diff changeset
109 else if (z == sizeof (int))
kono
parents:
diff changeset
110 {
kono
parents:
diff changeset
111 *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
kono
parents:
diff changeset
112 }
kono
parents:
diff changeset
113 else
kono
parents:
diff changeset
114 {
kono
parents:
diff changeset
115 if ((*p_arg)->type == FFI_TYPE_STRUCT)
kono
parents:
diff changeset
116 {
kono
parents:
diff changeset
117 memcpy (argp, *p_argv, z);
kono
parents:
diff changeset
118 }
kono
parents:
diff changeset
119 else
kono
parents:
diff changeset
120 {
kono
parents:
diff changeset
121 /* Double or long long 64bit. */
kono
parents:
diff changeset
122 memcpy (argp, *p_argv, z);
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124 }
kono
parents:
diff changeset
125 p_argv++;
kono
parents:
diff changeset
126 argp += z;
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 return;
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 /* Perform machine dependent cif processing. */
kono
parents:
diff changeset
133 ffi_status
kono
parents:
diff changeset
134 ffi_prep_cif_machdep (ffi_cif * cif)
kono
parents:
diff changeset
135 {
kono
parents:
diff changeset
136 /* Set the return type flag. */
kono
parents:
diff changeset
137 switch (cif->rtype->type)
kono
parents:
diff changeset
138 {
kono
parents:
diff changeset
139 case FFI_TYPE_VOID:
kono
parents:
diff changeset
140 cif->flags = (unsigned) cif->rtype->type;
kono
parents:
diff changeset
141 break;
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
144 cif->flags = (unsigned) cif->rtype->type;
kono
parents:
diff changeset
145 break;
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 case FFI_TYPE_SINT64:
kono
parents:
diff changeset
148 case FFI_TYPE_UINT64:
kono
parents:
diff changeset
149 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
150 cif->flags = FFI_TYPE_DOUBLE;
kono
parents:
diff changeset
151 break;
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
154 default:
kono
parents:
diff changeset
155 cif->flags = FFI_TYPE_INT;
kono
parents:
diff changeset
156 break;
kono
parents:
diff changeset
157 }
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 return FFI_OK;
kono
parents:
diff changeset
160 }
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 extern void ffi_call_ARCompact (void (*)(char *, extended_cif *),
kono
parents:
diff changeset
163 extended_cif *, unsigned, unsigned,
kono
parents:
diff changeset
164 unsigned *, void (*fn) (void));
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166 void
kono
parents:
diff changeset
167 ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
kono
parents:
diff changeset
168 {
kono
parents:
diff changeset
169 extended_cif ecif;
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 ecif.cif = cif;
kono
parents:
diff changeset
172 ecif.avalue = avalue;
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 /* If the return value is a struct and we don't have
kono
parents:
diff changeset
175 a return value address then we need to make one. */
kono
parents:
diff changeset
176 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
kono
parents:
diff changeset
177 {
kono
parents:
diff changeset
178 ecif.rvalue = alloca (cif->rtype->size);
kono
parents:
diff changeset
179 }
kono
parents:
diff changeset
180 else
kono
parents:
diff changeset
181 ecif.rvalue = rvalue;
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 switch (cif->abi)
kono
parents:
diff changeset
184 {
kono
parents:
diff changeset
185 case FFI_ARCOMPACT:
kono
parents:
diff changeset
186 ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
kono
parents:
diff changeset
187 cif->flags, ecif.rvalue, fn);
kono
parents:
diff changeset
188 break;
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 default:
kono
parents:
diff changeset
191 FFI_ASSERT (0);
kono
parents:
diff changeset
192 break;
kono
parents:
diff changeset
193 }
kono
parents:
diff changeset
194 }
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 int
kono
parents:
diff changeset
197 ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
kono
parents:
diff changeset
198 ffi_arg * args)
kono
parents:
diff changeset
199 {
kono
parents:
diff changeset
200 void **arg_area, **p_argv;
kono
parents:
diff changeset
201 ffi_cif *cif = closure->cif;
kono
parents:
diff changeset
202 char *argp = (char *) args;
kono
parents:
diff changeset
203 ffi_type **p_argt;
kono
parents:
diff changeset
204 int i;
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 arg_area = (void **) alloca (cif->nargs * sizeof (void *));
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 /* handle hidden argument */
kono
parents:
diff changeset
209 if (cif->flags == FFI_TYPE_STRUCT)
kono
parents:
diff changeset
210 {
kono
parents:
diff changeset
211 rvalue = *(void **) argp;
kono
parents:
diff changeset
212 argp += 4;
kono
parents:
diff changeset
213 }
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 p_argv = arg_area;
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
kono
parents:
diff changeset
218 i++, p_argt++, p_argv++)
kono
parents:
diff changeset
219 {
kono
parents:
diff changeset
220 size_t z;
kono
parents:
diff changeset
221 int alignment;
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 /* align alignment to 4 */
kono
parents:
diff changeset
224 alignment = (((*p_argt)->alignment - 1) | 3) + 1;
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* Align if necessary. */
kono
parents:
diff changeset
227 if ((alignment - 1) & (unsigned) argp)
kono
parents:
diff changeset
228 argp = (char *) ALIGN (argp, alignment);
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 z = (*p_argt)->size;
kono
parents:
diff changeset
231 *p_argv = (void *) argp;
kono
parents:
diff changeset
232 argp += z;
kono
parents:
diff changeset
233 }
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 (closure->fun) (cif, rvalue, arg_area, closure->user_data);
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 return cif->flags;
kono
parents:
diff changeset
238 }
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 extern void ffi_closure_ARCompact (void);
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 ffi_status
kono
parents:
diff changeset
243 ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
kono
parents:
diff changeset
244 void (*fun) (ffi_cif *, void *, void **, void *),
kono
parents:
diff changeset
245 void *user_data, void *codeloc)
kono
parents:
diff changeset
246 {
kono
parents:
diff changeset
247 uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 switch (cif->abi)
kono
parents:
diff changeset
250 {
kono
parents:
diff changeset
251 case FFI_ARCOMPACT:
kono
parents:
diff changeset
252 FFI_ASSERT (tramp == codeloc);
kono
parents:
diff changeset
253 tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */
kono
parents:
diff changeset
254 tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */
kono
parents:
diff changeset
255 tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
kono
parents:
diff changeset
256 break;
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 default:
kono
parents:
diff changeset
259 return FFI_BAD_ABI;
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 closure->cif = cif;
kono
parents:
diff changeset
263 closure->fun = fun;
kono
parents:
diff changeset
264 closure->user_data = user_data;
kono
parents:
diff changeset
265 cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 return FFI_OK;
kono
parents:
diff changeset
268 }