Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callvm_arm32_thumb.c @ 542:a73a5cd50c19
- fix passing aggregate-by-val on x64/sysv: subaggr classification for
aggr *arrays* was wrong (was problematic when there ware exactly 2 8bytes to
be classified, potentially be passed via registers)
author | Tassilo Philipp |
---|---|
date | Mon, 02 May 2022 15:32:41 +0200 |
parents | 71c884e610f0 |
children |
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 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
9 Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>, |
0 | 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 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
44 /* |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
45 ** arm32 thumb mode calling convention calls |
366
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
46 ** |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
47 ** - hybrid return-type call (bool ... pointer) |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
48 ** |
409
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
49 ** Note: return types of this decl and func below are of double-word size, intentionally |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
50 ** to keep some platforms' compilers from generating code in the callers that reuse, and |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
51 ** thus overwrite, r0 and r1 directly after the call. |
366
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
52 ** With this "hint", we preserve those registers by letting the compiler assume both |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
53 ** registers are used for the return type. |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
54 */ |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
55 DClonglong dcCall_arm32_thumb(DCpointer target, DCpointer stackdata, DCsize size); |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
56 |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
281
diff
changeset
|
57 |
409
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
58 /* Call. */ |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
59 DClonglong dc_callvm_call_arm32_thumb(DCCallVM* in_self, DCpointer target) |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
60 { |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
61 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
62 return dcCall_arm32_thumb(target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead)); |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
63 } |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
64 |
15698dc0cba3
- regression fix: return values were broken on some arm32-thumb targets
Tassilo Philipp
parents:
366
diff
changeset
|
65 |
0 | 66 static void dc_callvm_mode_arm32_thumb(DCCallVM* in_self,DCint mode); |
67 | |
68 static void dc_callvm_free_arm32_thumb(DCCallVM* in_self) | |
69 { | |
70 dcFreeMem(in_self); | |
71 } | |
72 | |
73 | |
74 static void dc_callvm_reset_arm32_thumb(DCCallVM* in_self) | |
75 { | |
76 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
77 dcVecReset(&self->mVecHead); | |
78 } | |
79 | |
80 | |
81 static void dc_callvm_argInt_arm32_thumb(DCCallVM* in_self, DCint x) | |
82 { | |
83 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
84 dcVecAppend(&self->mVecHead, &x, sizeof(DCint)); | |
85 } | |
86 | |
87 | |
88 static void dc_callvm_argBool_arm32_thumb(DCCallVM* in_self, DCbool x) | |
89 { | |
90 dc_callvm_argInt_arm32_thumb(in_self, (DCint)x); | |
91 } | |
92 | |
93 | |
94 static void dc_callvm_argChar_arm32_thumb(DCCallVM* in_self, DCchar x) | |
95 { | |
96 dc_callvm_argInt_arm32_thumb(in_self, x); | |
97 } | |
98 | |
99 | |
100 static void dc_callvm_argShort_arm32_thumb(DCCallVM* in_self, DCshort x) | |
101 { | |
102 dc_callvm_argInt_arm32_thumb(in_self, x); | |
103 } | |
104 | |
105 | |
106 static void dc_callvm_argLong_arm32_thumb(DCCallVM* in_self, DClong x) | |
107 { | |
108 dc_callvm_argInt_arm32_thumb(in_self, x); | |
109 } | |
110 | |
111 | |
112 static void dc_callvm_argLongLong_arm32_thumb(DCCallVM* in_self, DClonglong x) | |
113 { | |
114 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
115 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
116 } | |
117 | |
118 | |
119 static void dc_callvm_argLongLong_arm32_thumb_eabi(DCCallVM* in_self, DClonglong x) | |
120 { | |
121 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
122 | |
123 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
124 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
125 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); | |
126 } | |
127 | |
128 | |
129 static void dc_callvm_argFloat_arm32_thumb(DCCallVM* in_self, DCfloat x) | |
130 { | |
131 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
132 dcVecAppend(&self->mVecHead, &x, sizeof(DCfloat)); | |
133 } | |
134 | |
135 | |
136 static void dc_callvm_argDouble_arm32_thumb(DCCallVM* in_self, DCdouble x) | |
137 { | |
138 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
139 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
140 } | |
141 | |
142 | |
143 static void dc_callvm_argDouble_arm32_thumb_eabi(DCCallVM* in_self, DCdouble x) | |
144 { | |
145 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
146 | |
147 /* 64 bit values need to be aligned on 8 byte boundaries */ | |
148 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4); | |
149 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble)); | |
150 } | |
151 | |
152 | |
153 static void dc_callvm_argPointer_arm32_thumb(DCCallVM* in_self, DCpointer x) | |
154 { | |
155 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
156 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer)); | |
157 } | |
158 | |
159 | |
160 DCCallVM_vt gVT_arm32_thumb = | |
161 { | |
162 &dc_callvm_free_arm32_thumb | |
163 , &dc_callvm_reset_arm32_thumb | |
164 , &dc_callvm_mode_arm32_thumb | |
165 , &dc_callvm_argBool_arm32_thumb | |
166 , &dc_callvm_argChar_arm32_thumb | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
167 , &dc_callvm_argShort_arm32_thumb |
0 | 168 , &dc_callvm_argInt_arm32_thumb |
169 , &dc_callvm_argLong_arm32_thumb | |
170 , &dc_callvm_argLongLong_arm32_thumb | |
171 , &dc_callvm_argFloat_arm32_thumb | |
172 , &dc_callvm_argDouble_arm32_thumb | |
173 , &dc_callvm_argPointer_arm32_thumb | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
174 , NULL /* argAggr */ |
0 | 175 , (DCvoidvmfunc*) &dc_callvm_call_arm32_thumb |
176 , (DCboolvmfunc*) &dc_callvm_call_arm32_thumb | |
177 , (DCcharvmfunc*) &dc_callvm_call_arm32_thumb | |
178 , (DCshortvmfunc*) &dc_callvm_call_arm32_thumb | |
179 , (DCintvmfunc*) &dc_callvm_call_arm32_thumb | |
180 , (DClongvmfunc*) &dc_callvm_call_arm32_thumb | |
181 , (DClonglongvmfunc*) &dc_callvm_call_arm32_thumb | |
182 , (DCfloatvmfunc*) &dc_callvm_call_arm32_thumb | |
183 , (DCdoublevmfunc*) &dc_callvm_call_arm32_thumb | |
184 , (DCpointervmfunc*) &dc_callvm_call_arm32_thumb | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
185 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
186 , NULL /* beginAggr */ |
0 | 187 }; |
188 | |
189 DCCallVM_vt gVT_arm32_thumb_eabi = | |
190 { | |
191 &dc_callvm_free_arm32_thumb | |
192 , &dc_callvm_reset_arm32_thumb | |
193 , &dc_callvm_mode_arm32_thumb | |
194 , &dc_callvm_argBool_arm32_thumb | |
195 , &dc_callvm_argChar_arm32_thumb | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
196 , &dc_callvm_argShort_arm32_thumb |
0 | 197 , &dc_callvm_argInt_arm32_thumb |
198 , &dc_callvm_argLong_arm32_thumb | |
199 , &dc_callvm_argLongLong_arm32_thumb_eabi | |
200 , &dc_callvm_argFloat_arm32_thumb | |
201 , &dc_callvm_argDouble_arm32_thumb_eabi | |
202 , &dc_callvm_argPointer_arm32_thumb | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
203 , NULL /* argAggr */ |
0 | 204 , (DCvoidvmfunc*) &dc_callvm_call_arm32_thumb |
205 , (DCboolvmfunc*) &dc_callvm_call_arm32_thumb | |
206 , (DCcharvmfunc*) &dc_callvm_call_arm32_thumb | |
207 , (DCshortvmfunc*) &dc_callvm_call_arm32_thumb | |
208 , (DCintvmfunc*) &dc_callvm_call_arm32_thumb | |
209 , (DClongvmfunc*) &dc_callvm_call_arm32_thumb | |
210 , (DClonglongvmfunc*) &dc_callvm_call_arm32_thumb | |
211 , (DCfloatvmfunc*) &dc_callvm_call_arm32_thumb | |
212 , (DCdoublevmfunc*) &dc_callvm_call_arm32_thumb | |
213 , (DCpointervmfunc*) &dc_callvm_call_arm32_thumb | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
214 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
215 , NULL /* beginAggr */ |
0 | 216 }; |
217 | |
84 | 218 static void dc_callvm_mode_arm32_thumb(DCCallVM* in_self, DCint mode) |
219 { | |
220 DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*)in_self; | |
221 DCCallVM_vt* vt; | |
0 | 222 |
84 | 223 switch(mode) { |
224 case DC_CALL_C_ELLIPSIS: | |
225 case DC_CALL_C_ELLIPSIS_VARARGS: | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
226 case DC_CALL_C_DEFAULT_THIS: |
0 | 227 /* Check OS if we need EABI as default. */ |
228 #if defined(DC__ABI_ARM_EABI) | |
84 | 229 case DC_CALL_C_DEFAULT: vt = &gVT_arm32_thumb_eabi; break; |
0 | 230 #else |
84 | 231 case DC_CALL_C_DEFAULT: vt = &gVT_arm32_thumb; break; |
0 | 232 #endif |
84 | 233 case DC_CALL_C_ARM_THUMB: vt = &gVT_arm32_thumb; break; |
234 case DC_CALL_C_ARM_THUMB_EABI: vt = &gVT_arm32_thumb_eabi; break; | |
235 default: | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
409
diff
changeset
|
236 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; |
84 | 237 return; |
238 } | |
239 dc_callvm_base_init(&self->mInterface, vt); | |
0 | 240 } |
241 | |
84 | 242 /* Public API. */ |
243 DCCallVM* dcNewCallVM(DCsize size) | |
0 | 244 { |
84 | 245 /* Store at least 16 bytes (4 words) for internal spill area. Assembly code depends on it. */ |
246 DCCallVM_arm32_thumb* p = (DCCallVM_arm32_thumb*)dcAllocMem(sizeof(DCCallVM_arm32_thumb)+size+16); | |
247 | |
248 dc_callvm_mode_arm32_thumb((DCCallVM*)p, DC_CALL_C_DEFAULT); | |
249 | |
250 dcVecInit(&p->mVecHead, size); | |
251 | |
252 return (DCCallVM*)p; | |
0 | 253 } |
254 |