Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callvm_arm32_thumb.c @ 27:523c45dfa8fb
- refactored arm calling conventions' callvm code, so that the code that keeps
the caller from overwriting the return value on some platforms also works on
OpenBSD (before we casted the function pointer to have long long as return
type, to hint the caller that there is one, but that triggers an intentional
SIGABRT on OpenBSD for security reasons; now the decl reflects this, directly)
author | cslag |
---|---|
date | Tue, 15 Sep 2015 12:48:52 +0200 |
parents | 1c539fb1d2dd |
children | 67961454902b |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_arm32_thumb.c | |
6 Description: ARM 32-bit "thumb" ABI callvm implementation | |
7 License: | |
8 | |
9 Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>, | |
10 Tassilo Philipp <tphilipp@potion-studios.com> | |
11 | |
12 Permission to use, copy, modify, and distribute this software for any | |
13 purpose with or without fee is hereby granted, provided that the above | |
14 copyright notice and this permission notice appear in all copies. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
23 | |
24 */ | |
25 | |
26 | |
27 | |
28 /* | |
29 | |
30 dyncall callvm for 32bit ARM32 family of processors | |
31 | |
32 SUPPORTED CALLING CONVENTIONS | |
33 armthumbcall | |
34 | |
35 REVISION | |
36 2007/12/11 initial | |
37 | |
38 */ | |
39 | |
40 | |
41 #include "dyncall_callvm_arm32_thumb.h" | |
42 #include "dyncall_alloc.h" | |
43 | |
44 static void dc_callvm_mode_arm32_thumb(DCCallVM* in_self,DCint mode); | |
45 | |
46 static DCCallVM* dc_callvm_new_arm32_thumb(DCCallVM_vt* vt, DCsize size) | |
47 { | |
48 /* Store at least 16 bytes (4 words) for internal spill area. Assembly code depends on it. */ | |
49 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)dcAllocMem(sizeof(DCCallVM_arm32_thumb)+size+16); | |
50 dc_callvm_base_init(&self->mInterface, vt); | |
51 dcVecInit(&self->mVecHead, size); | |
52 return (DCCallVM*)self; | |
53 } | |
54 | |
55 | |
56 static void dc_callvm_free_arm32_thumb(DCCallVM* in_self) | |
57 { | |
58 dcFreeMem(in_self); | |
59 } | |
60 | |
61 | |
62 static void dc_callvm_reset_arm32_thumb(DCCallVM* in_self) | |
63 { | |
64 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
65 dcVecReset(&self->mVecHead); | |
66 } | |
67 | |
68 | |
69 static void dc_callvm_argInt_arm32_thumb(DCCallVM* in_self, DCint x) | |
70 { | |
71 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
72 dcVecAppend(&self->mVecHead, &x, sizeof(DCint)); | |
73 } | |
74 | |
75 | |
76 static void dc_callvm_argBool_arm32_thumb(DCCallVM* in_self, DCbool x) | |
77 { | |
78 dc_callvm_argInt_arm32_thumb(in_self, (DCint)x); | |
79 } | |
80 | |
81 | |
82 static void dc_callvm_argChar_arm32_thumb(DCCallVM* in_self, DCchar x) | |
83 { | |
84 dc_callvm_argInt_arm32_thumb(in_self, x); | |
85 } | |
86 | |
87 | |
88 static void dc_callvm_argShort_arm32_thumb(DCCallVM* in_self, DCshort x) | |
89 { | |
90 dc_callvm_argInt_arm32_thumb(in_self, x); | |
91 } | |
92 | |
93 | |
94 static void dc_callvm_argLong_arm32_thumb(DCCallVM* in_self, DClong x) | |
95 { | |
96 dc_callvm_argInt_arm32_thumb(in_self, x); | |
97 } | |
98 | |
99 | |
100 static void dc_callvm_argLongLong_arm32_thumb(DCCallVM* in_self, DClonglong x) | |
101 { | |
102 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
103 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
104 } | |
105 | |
106 | |
107 static void dc_callvm_argLongLong_arm32_thumb_eabi(DCCallVM* in_self, DClonglong x) | |
108 { | |
109 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
110 | |
111 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
112 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
113 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
114 } | |
115 | |
116 | |
117 static void dc_callvm_argFloat_arm32_thumb(DCCallVM* in_self, DCfloat x) | |
118 { | |
119 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
120 dcVecAppend(&self->mVecHead, &x, sizeof(DCfloat)); | |
121 } | |
122 | |
123 | |
124 static void dc_callvm_argDouble_arm32_thumb(DCCallVM* in_self, DCdouble x) | |
125 { | |
126 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
127 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
128 } | |
129 | |
130 | |
131 static void dc_callvm_argDouble_arm32_thumb_eabi(DCCallVM* in_self, DCdouble x) | |
132 { | |
133 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
134 | |
135 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
136 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
137 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
138 } | |
139 | |
140 | |
141 static void dc_callvm_argPointer_arm32_thumb(DCCallVM* in_self, DCpointer x) | |
142 { | |
143 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
144 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer)); | |
145 } | |
146 | |
147 | |
148 /* Call. */ | |
149 void dc_callvm_call_arm32_thumb(DCCallVM* in_self, DCpointer target) | |
150 { | |
151 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
27
523c45dfa8fb
- refactored arm calling conventions' callvm code, so that the code that keeps
cslag
parents:
20
diff
changeset
|
152 dcCall_arm32_thumb(target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead)); |
0 | 153 } |
154 | |
155 | |
156 DCCallVM_vt gVT_arm32_thumb = | |
157 { | |
158 &dc_callvm_free_arm32_thumb | |
159 , &dc_callvm_reset_arm32_thumb | |
160 , &dc_callvm_mode_arm32_thumb | |
161 , &dc_callvm_argBool_arm32_thumb | |
162 , &dc_callvm_argChar_arm32_thumb | |
163 , &dc_callvm_argShort_arm32_thumb | |
164 , &dc_callvm_argInt_arm32_thumb | |
165 , &dc_callvm_argLong_arm32_thumb | |
166 , &dc_callvm_argLongLong_arm32_thumb | |
167 , &dc_callvm_argFloat_arm32_thumb | |
168 , &dc_callvm_argDouble_arm32_thumb | |
169 , &dc_callvm_argPointer_arm32_thumb | |
170 , NULL /* argStruct */ | |
171 , (DCvoidvmfunc*) &dc_callvm_call_arm32_thumb | |
172 , (DCboolvmfunc*) &dc_callvm_call_arm32_thumb | |
173 , (DCcharvmfunc*) &dc_callvm_call_arm32_thumb | |
174 , (DCshortvmfunc*) &dc_callvm_call_arm32_thumb | |
175 , (DCintvmfunc*) &dc_callvm_call_arm32_thumb | |
176 , (DClongvmfunc*) &dc_callvm_call_arm32_thumb | |
177 , (DClonglongvmfunc*) &dc_callvm_call_arm32_thumb | |
178 , (DCfloatvmfunc*) &dc_callvm_call_arm32_thumb | |
179 , (DCdoublevmfunc*) &dc_callvm_call_arm32_thumb | |
180 , (DCpointervmfunc*) &dc_callvm_call_arm32_thumb | |
181 , NULL /* callStruct */ | |
182 }; | |
183 | |
184 | |
185 DCCallVM_vt gVT_arm32_thumb_eabi = | |
186 { | |
187 &dc_callvm_free_arm32_thumb | |
188 , &dc_callvm_reset_arm32_thumb | |
189 , &dc_callvm_mode_arm32_thumb | |
190 , &dc_callvm_argBool_arm32_thumb | |
191 , &dc_callvm_argChar_arm32_thumb | |
192 , &dc_callvm_argShort_arm32_thumb | |
193 , &dc_callvm_argInt_arm32_thumb | |
194 , &dc_callvm_argLong_arm32_thumb | |
195 , &dc_callvm_argLongLong_arm32_thumb_eabi | |
196 , &dc_callvm_argFloat_arm32_thumb | |
197 , &dc_callvm_argDouble_arm32_thumb_eabi | |
198 , &dc_callvm_argPointer_arm32_thumb | |
199 , NULL /* argStruct */ | |
200 , (DCvoidvmfunc*) &dc_callvm_call_arm32_thumb | |
201 , (DCboolvmfunc*) &dc_callvm_call_arm32_thumb | |
202 , (DCcharvmfunc*) &dc_callvm_call_arm32_thumb | |
203 , (DCshortvmfunc*) &dc_callvm_call_arm32_thumb | |
204 , (DCintvmfunc*) &dc_callvm_call_arm32_thumb | |
205 , (DClongvmfunc*) &dc_callvm_call_arm32_thumb | |
206 , (DClonglongvmfunc*) &dc_callvm_call_arm32_thumb | |
207 , (DCfloatvmfunc*) &dc_callvm_call_arm32_thumb | |
208 , (DCdoublevmfunc*) &dc_callvm_call_arm32_thumb | |
209 , (DCpointervmfunc*) &dc_callvm_call_arm32_thumb | |
210 , NULL /* callStruct */ | |
211 }; | |
212 | |
213 | |
214 DCCallVM* dcNewCallVM_arm32_thumb(DCsize size) | |
215 { | |
216 /* Check OS if we need EABI as default. */ | |
217 #if defined(DC__ABI_ARM_EABI) | |
218 return dc_callvm_new_arm32_thumb(&gVT_arm32_thumb_eabi, size); | |
219 #else | |
220 return dc_callvm_new_arm32_thumb(&gVT_arm32_thumb, size); | |
221 #endif | |
222 } | |
223 | |
224 | |
225 DCCallVM* dcNewCallVM(DCsize size) | |
226 { | |
227 return dcNewCallVM_arm32_thumb(size); | |
228 } | |
229 | |
230 | |
231 static void dc_callvm_mode_arm32_thumb(DCCallVM* in_self,DCint mode) | |
232 { | |
233 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*) in_self; | |
234 DCCallVM_vt* vt; | |
235 switch(mode) { | |
236 /* Check OS if we need EABI as default. */ | |
237 case DC_CALL_C_ELLIPSIS: | |
238 #if defined(DC__ABI_ARM_EABI) | |
239 case DC_CALL_C_DEFAULT: vt = &gVT_arm32_thumb_eabi; break; | |
240 #else | |
241 case DC_CALL_C_DEFAULT: vt = &gVT_arm32_thumb; break; | |
242 #endif | |
243 case DC_CALL_C_ARM_THUMB: vt = &gVT_arm32_thumb; break; | |
244 case DC_CALL_C_ARM_THUMB_EABI: vt = &gVT_arm32_thumb_eabi; break; | |
245 default: self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; return; | |
246 } | |
247 self->mInterface.mVTpointer = vt; | |
248 } | |
249 |