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