Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callvm_x86.c @ 533:71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
* integration of aggregate-by-value (struct, union) support patch for x64 (win and sysv)
* windows/x64 asm additions to specify how stack unwinds (help for debuggers, exception handling, etc.)
* see Changelog for details
- new calling convention modes for thiscalls (platform agnostic, was specific before)
* new signature character for platform agnostic thiscalls ('*' / DC_SIGCHAR_CC_THISCALL)
- dcCallF(), dcVCallF(), dcArgF() and dcVArgF():
* added support for aggregates-by-value (wasn't part of patch)
* change that those functions don't implicitly call dcReset() anymore, which was unflexible (breaking change)
- added macros to feature test implementation for aggregate-by-value and syscall support
- changed libdyncall_s.lib and libdyncallback_s.lib order in callback test makefiles, as some toolchains are picky about order
- doc:
* man page updates to describe aggregate interface
* manual overview changes to highlight platforms with aggregate-by-value support
- test/plain: replaced tests w/ old/stale sctruct interface with new aggregate one
author | Tassilo Philipp |
---|---|
date | Thu, 21 Apr 2022 13:35:47 +0200 |
parents | ddfb9577a00e |
children | 5d999f5c13d1 |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_x86.c | |
6 Description: Call VM for x86 architecture implementation | |
7 License: | |
8 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
9 Copyright (c) 2007-2020 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 #include "dyncall_callvm_x86.h" | |
29 #include "dyncall_alloc.h" | |
30 | |
31 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
32 /* |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
33 ** x86 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:
365
diff
changeset
|
34 ** |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
35 ** - 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:
365
diff
changeset
|
36 ** |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
37 */ |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
38 |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
39 #if defined(DC__OS_Plan9) /* No support for other cconvs on Plan9 and vice-versa. */ |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
40 void dcCall_x86_plan9 (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:
365
diff
changeset
|
41 #else |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
42 void dcCall_x86_cdecl (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:
365
diff
changeset
|
43 void dcCall_x86_win32_std (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:
365
diff
changeset
|
44 void dcCall_x86_win32_fast (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:
365
diff
changeset
|
45 void dcCall_x86_win32_msthis (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:
365
diff
changeset
|
46 void dcCall_x86_syscall_int80h_linux(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:
365
diff
changeset
|
47 void dcCall_x86_syscall_int80h_bsd (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:
365
diff
changeset
|
48 #endif |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
49 |
ad5f9803f52f
- removal of some unnecessary headers that only contained internally used forward declarations, so no need to have them
Tassilo Philipp
parents:
365
diff
changeset
|
50 |
0 | 51 void dc_callvm_mode_x86(DCCallVM* in_self, DCint mode); |
52 | |
53 /* call vm destructor */ | |
54 | |
55 static void dc_callvm_free_x86(DCCallVM* in_self) | |
56 { | |
57 dcFreeMem(in_self); | |
58 } | |
59 | |
60 /* reset */ | |
61 | |
62 static void dc_callvm_reset_x86(DCCallVM* in_self) | |
63 { | |
64 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
65 dcVecReset(&self->mVecHead); | |
66 self->mIntRegs = 0; | |
67 } | |
68 | |
69 /* arg (bool,char,short,long auto-promoted) to int */ | |
70 | |
71 static void dc_callvm_argInt_x86(DCCallVM* in_self, DCint x) | |
72 { | |
73 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
74 dcVecAppend(&self->mVecHead, &x, sizeof(DCint) ); | |
75 } | |
76 | |
77 /* arg bool - promoted to int */ | |
78 | |
79 static void dc_callvm_argBool_x86(DCCallVM* in_self, DCbool x) | |
80 { | |
81 | |
82 DCint v = (DCint) x; | |
83 dc_callvm_argInt_x86(in_self, v); | |
84 } | |
85 | |
86 /* arg char - promoted to int */ | |
87 | |
88 static void dc_callvm_argChar_x86(DCCallVM* in_self, DCchar x) | |
89 { | |
90 DCint v = (DCint) x; | |
91 dc_callvm_argInt_x86(in_self, v); | |
92 } | |
93 | |
94 /* arg short - promoted to int */ | |
95 | |
96 static void dc_callvm_argShort_x86(DCCallVM* in_self, DCshort x) | |
97 { | |
98 DCint v = (DCint) x; | |
99 dc_callvm_argInt_x86(in_self, v); | |
100 } | |
101 | |
102 /* arg long - promoted to int */ | |
103 | |
104 static void dc_callvm_argLong_x86(DCCallVM* in_self, DClong x) | |
105 { | |
106 DCint v = (DCint) x; | |
107 dc_callvm_argInt_x86(in_self, v); | |
108 } | |
109 | |
110 /* arg long long */ | |
111 | |
112 static void dc_callvm_argLongLong_x86(DCCallVM* in_self, DClonglong x) | |
113 { | |
114 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
115 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong) ); | |
116 } | |
117 | |
118 /* arg float */ | |
119 | |
120 static void dc_callvm_argFloat_x86(DCCallVM* in_self, DCfloat x) | |
121 { | |
122 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
123 dcVecAppend(&self->mVecHead, &x, sizeof(DCfloat) ); | |
124 } | |
125 | |
126 /* arg double */ | |
127 | |
128 static void dc_callvm_argDouble_x86(DCCallVM* in_self, DCdouble x) | |
129 { | |
130 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
131 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble) ); | |
132 } | |
133 | |
134 /* arg pointer */ | |
135 | |
136 static void dc_callvm_argPointer_x86(DCCallVM* in_self, DCpointer x) | |
137 { | |
138 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
139 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer) ); | |
140 } | |
141 | |
142 | |
143 /* Plan9 specific calling convention. */ | |
144 #if defined(DC__OS_Plan9) | |
145 | |
146 /* call 'plan9' */ | |
147 | |
148 void dc_callvm_call_x86_plan9(DCCallVM* in_self, DCpointer target) | |
149 { | |
150 /* Calls with 32-bit return values have it returned via EAX, so we don't */ | |
151 /* need to do anything special here. */ | |
152 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
153 dcCall_x86_plan9(target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead)); | |
154 } | |
155 | |
156 DClonglong dc_callvm_call_x86_plan9_ll(DCCallVM* in_self, DCpointer target) | |
157 { | |
158 /* Call for 64 bit integer return values is a bit different, call a */ | |
159 /* different assembler stub that stores the return value in a variable */ | |
160 /* for us, and return the latter. */ | |
161 DClonglong ret; | |
162 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
163 dcCall_x86_plan9_ll(target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead), &ret ); | |
164 return ret; | |
165 } | |
166 | |
167 DCCallVM_vt gVT_x86_plan9 = | |
168 { | |
169 &dc_callvm_free_x86 | |
170 , &dc_callvm_reset_x86 | |
171 , &dc_callvm_mode_x86 | |
172 , &dc_callvm_argBool_x86 | |
173 , &dc_callvm_argChar_x86 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
174 , &dc_callvm_argShort_x86 |
0 | 175 , &dc_callvm_argInt_x86 |
176 , &dc_callvm_argLong_x86 | |
177 , &dc_callvm_argLongLong_x86 | |
178 , &dc_callvm_argFloat_x86 | |
179 , &dc_callvm_argDouble_x86 | |
180 , &dc_callvm_argPointer_x86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
181 , NULL /* argAggr */ |
0 | 182 , (DCvoidvmfunc*) &dc_callvm_call_x86_plan9 |
183 , (DCboolvmfunc*) &dc_callvm_call_x86_plan9 | |
184 , (DCcharvmfunc*) &dc_callvm_call_x86_plan9 | |
185 , (DCshortvmfunc*) &dc_callvm_call_x86_plan9 | |
186 , (DCintvmfunc*) &dc_callvm_call_x86_plan9 | |
187 , (DClongvmfunc*) &dc_callvm_call_x86_plan9 | |
188 , (DClonglongvmfunc*) &dc_callvm_call_x86_plan9_ll | |
189 , (DCfloatvmfunc*) &dc_callvm_call_x86_plan9 | |
190 , (DCdoublevmfunc*) &dc_callvm_call_x86_plan9 | |
191 , (DCpointervmfunc*) &dc_callvm_call_x86_plan9 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
192 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
193 , NULL /* beginAggr */ |
0 | 194 }; |
195 | |
196 | |
197 #else | |
198 | |
199 | |
200 /* call 'cdecl' */ | |
201 | |
202 void dc_callvm_call_x86_cdecl(DCCallVM* in_self, DCpointer target) | |
203 { | |
204 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
205 dcCall_x86_cdecl( target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead) ); | |
206 } | |
207 | |
208 DCCallVM_vt gVT_x86_cdecl = | |
209 { | |
210 &dc_callvm_free_x86 | |
211 , &dc_callvm_reset_x86 | |
212 , &dc_callvm_mode_x86 | |
213 , &dc_callvm_argBool_x86 | |
214 , &dc_callvm_argChar_x86 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
215 , &dc_callvm_argShort_x86 |
0 | 216 , &dc_callvm_argInt_x86 |
217 , &dc_callvm_argLong_x86 | |
218 , &dc_callvm_argLongLong_x86 | |
219 , &dc_callvm_argFloat_x86 | |
220 , &dc_callvm_argDouble_x86 | |
221 , &dc_callvm_argPointer_x86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
222 , NULL /* argAggr */ |
0 | 223 , (DCvoidvmfunc*) &dc_callvm_call_x86_cdecl |
224 , (DCboolvmfunc*) &dc_callvm_call_x86_cdecl | |
225 , (DCcharvmfunc*) &dc_callvm_call_x86_cdecl | |
226 , (DCshortvmfunc*) &dc_callvm_call_x86_cdecl | |
227 , (DCintvmfunc*) &dc_callvm_call_x86_cdecl | |
228 , (DClongvmfunc*) &dc_callvm_call_x86_cdecl | |
229 , (DClonglongvmfunc*) &dc_callvm_call_x86_cdecl | |
230 , (DCfloatvmfunc*) &dc_callvm_call_x86_cdecl | |
231 , (DCdoublevmfunc*) &dc_callvm_call_x86_cdecl | |
232 , (DCpointervmfunc*) &dc_callvm_call_x86_cdecl | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
233 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
234 , NULL /* beginAggr */ |
0 | 235 }; |
236 | |
237 | |
238 | |
239 /* --- stdcall -------------------------------------------------------------- */ | |
240 | |
241 /* call win32/std */ | |
242 | |
243 void dc_callvm_call_x86_win32_std(DCCallVM* in_self, DCpointer target) | |
244 { | |
245 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
246 dcCall_x86_win32_std( target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead) ); | |
247 } | |
248 | |
249 /* win32/std vtable */ | |
250 | |
251 DCCallVM_vt gVT_x86_win32_std = | |
252 { | |
253 &dc_callvm_free_x86 | |
254 , &dc_callvm_reset_x86 | |
255 , &dc_callvm_mode_x86 | |
256 , &dc_callvm_argBool_x86 | |
257 , &dc_callvm_argChar_x86 | |
258 , &dc_callvm_argShort_x86 | |
259 , &dc_callvm_argInt_x86 | |
260 , &dc_callvm_argLong_x86 | |
261 , &dc_callvm_argLongLong_x86 | |
262 , &dc_callvm_argFloat_x86 | |
263 , &dc_callvm_argDouble_x86 | |
264 , &dc_callvm_argPointer_x86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
265 , NULL /* argAggr */ |
0 | 266 , (DCvoidvmfunc*) &dc_callvm_call_x86_win32_std |
267 , (DCboolvmfunc*) &dc_callvm_call_x86_win32_std | |
268 , (DCcharvmfunc*) &dc_callvm_call_x86_win32_std | |
269 , (DCshortvmfunc*) &dc_callvm_call_x86_win32_std | |
270 , (DCintvmfunc*) &dc_callvm_call_x86_win32_std | |
271 , (DClongvmfunc*) &dc_callvm_call_x86_win32_std | |
272 , (DClonglongvmfunc*) &dc_callvm_call_x86_win32_std | |
273 , (DCfloatvmfunc*) &dc_callvm_call_x86_win32_std | |
274 , (DCdoublevmfunc*) &dc_callvm_call_x86_win32_std | |
275 , (DCpointervmfunc*) &dc_callvm_call_x86_win32_std | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
276 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
277 , NULL /* beginAggr */ |
0 | 278 }; |
279 | |
280 | |
281 /* --- fastcall common (ms/gnu) -------------------------------------------- */ | |
282 | |
283 /* call win32 ms fast */ | |
284 | |
285 static void dc_callvm_call_x86_win32_fast(DCCallVM* in_self, DCpointer target) | |
286 { | |
287 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
288 dcCall_x86_win32_fast( target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead) ); | |
289 } | |
290 | |
291 /* reset - always resize to 8 bytes (stores ECX and EDX) */ | |
292 | |
293 static void dc_callvm_reset_x86_win32_fast(DCCallVM* in_self) | |
294 { | |
295 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
296 dcVecResize(&self->mVecHead, sizeof(DCint) * 2 ); | |
297 self->mIntRegs = 0; | |
298 } | |
299 | |
300 | |
301 /* --- fastcall ms --------------------------------------------------------- */ | |
302 | |
303 /* arg int - probably hold in ECX and EDX */ | |
304 | |
305 static void dc_callvm_argInt_x86_win32_fast_ms(DCCallVM* in_self, DCint x) | |
306 { | |
307 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
308 if (self->mIntRegs < 2) { | |
309 *( (int*) dcVecAt(&self->mVecHead, sizeof(DCint) * self->mIntRegs ) ) = x; | |
310 ++( self->mIntRegs ); | |
311 } else | |
312 dcVecAppend(&self->mVecHead, &x, sizeof(DCint) ); | |
313 } | |
314 | |
315 /* arg bool - promote to int */ | |
316 | |
317 static void dc_callvm_argBool_x86_win32_fast_ms(DCCallVM* in_self, DCbool x) | |
318 { | |
319 DCint v = (DCint) x; | |
320 dc_callvm_argInt_x86_win32_fast_ms(in_self,v); | |
321 } | |
322 | |
323 /* arg char - promote to int */ | |
324 | |
325 static void dc_callvm_argChar_x86_win32_fast_ms(DCCallVM* in_self, DCchar x) | |
326 { | |
327 DCint v = (DCint) x; | |
328 dc_callvm_argInt_x86_win32_fast_ms(in_self,v); | |
329 } | |
330 | |
331 /* arg short - promote to int */ | |
332 | |
333 static void dc_callvm_argShort_x86_win32_fast_ms(DCCallVM* in_self, DCshort x) | |
334 { | |
335 DCint v = (DCint) x; | |
336 dc_callvm_argInt_x86_win32_fast_ms(in_self,v); | |
337 } | |
338 | |
339 /* arg long - promote to int */ | |
340 | |
341 static void dc_callvm_argLong_x86_win32_fast_ms(DCCallVM* in_self, DClong x) | |
342 { | |
343 DCint v = (DCint) x; | |
344 dc_callvm_argInt_x86_win32_fast_ms(in_self,v); | |
345 } | |
346 | |
347 /* arg pointer - promote to int */ | |
348 | |
349 static void dc_callvm_argPointer_x86_win32_fast_ms(DCCallVM* in_self, DCpointer x) | |
350 { | |
351 DCint v = (DCint) x; | |
352 dc_callvm_argInt_x86_win32_fast_ms(in_self,v); | |
353 } | |
354 | |
355 /* win32/fast vt */ | |
356 | |
357 DCCallVM_vt gVT_x86_win32_fast_ms = | |
358 { | |
359 &dc_callvm_free_x86 | |
360 , &dc_callvm_reset_x86_win32_fast | |
361 , &dc_callvm_mode_x86 | |
362 , &dc_callvm_argBool_x86_win32_fast_ms | |
363 , &dc_callvm_argChar_x86_win32_fast_ms | |
364 , &dc_callvm_argShort_x86_win32_fast_ms | |
365 , &dc_callvm_argInt_x86_win32_fast_ms | |
366 , &dc_callvm_argLong_x86_win32_fast_ms | |
367 , &dc_callvm_argLongLong_x86 | |
368 , &dc_callvm_argFloat_x86 | |
369 , &dc_callvm_argDouble_x86 | |
370 , &dc_callvm_argPointer_x86_win32_fast_ms | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
371 , NULL /* argAggr */ |
0 | 372 , (DCvoidvmfunc*) &dc_callvm_call_x86_win32_fast |
373 , (DCboolvmfunc*) &dc_callvm_call_x86_win32_fast | |
374 , (DCcharvmfunc*) &dc_callvm_call_x86_win32_fast | |
375 , (DCshortvmfunc*) &dc_callvm_call_x86_win32_fast | |
376 , (DCintvmfunc*) &dc_callvm_call_x86_win32_fast | |
377 , (DClongvmfunc*) &dc_callvm_call_x86_win32_fast | |
378 , (DClonglongvmfunc*) &dc_callvm_call_x86_win32_fast | |
379 , (DCfloatvmfunc*) &dc_callvm_call_x86_win32_fast | |
380 , (DCdoublevmfunc*) &dc_callvm_call_x86_win32_fast | |
381 , (DCpointervmfunc*) &dc_callvm_call_x86_win32_fast | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
382 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
383 , NULL /* beginAggr */ |
0 | 384 }; |
385 | |
386 | |
387 /* --- gnu fastcall -------------------------------------------------------- */ | |
388 | |
389 /* arg int - probably hold in ECX and EDX */ | |
390 | |
391 static void dc_callvm_argInt_x86_win32_fast_gnu(DCCallVM* in_self, DCint x) | |
392 { | |
393 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
394 if (self->mIntRegs < 2) { | |
395 *( (int*) dcVecAt(&self->mVecHead, sizeof(DCint) * self->mIntRegs ) ) = x; | |
396 ++( self->mIntRegs ); | |
397 } else | |
398 dcVecAppend(&self->mVecHead, &x, sizeof(DCint) ); | |
399 } | |
400 | |
401 /* arg bool - promote to int */ | |
402 | |
403 static void dc_callvm_argBool_x86_win32_fast_gnu(DCCallVM* in_self, DCbool x) | |
404 { | |
405 DCint v = (DCint) x; | |
406 dc_callvm_argInt_x86_win32_fast_gnu(in_self,v); | |
407 } | |
408 | |
409 /* arg char - promote to int */ | |
410 | |
411 static void dc_callvm_argChar_x86_win32_fast_gnu(DCCallVM* in_self, DCchar x) | |
412 { | |
413 DCint v = (DCint) x; | |
414 dc_callvm_argInt_x86_win32_fast_gnu(in_self,v); | |
415 } | |
416 | |
417 /* arg short - promote to int */ | |
418 | |
419 static void dc_callvm_argShort_x86_win32_fast_gnu(DCCallVM* in_self, DCshort x) | |
420 { | |
421 DCint v = (DCint) x; | |
422 dc_callvm_argInt_x86_win32_fast_gnu(in_self,v); | |
423 } | |
424 | |
425 /* arg long - promote to int */ | |
426 | |
427 static void dc_callvm_argLong_x86_win32_fast_gnu(DCCallVM* in_self, DClong x) | |
428 { | |
429 DCint v = (DCint) x; | |
430 dc_callvm_argInt_x86_win32_fast_gnu(in_self,v); | |
431 } | |
432 | |
433 /* arg pointer - promote to int */ | |
434 | |
435 static void dc_callvm_argPointer_x86_win32_fast_gnu(DCCallVM* in_self, DCpointer x) | |
436 { | |
437 DCint v = (DCint) x; | |
438 dc_callvm_argInt_x86_win32_fast_gnu(in_self,v); | |
439 } | |
440 | |
441 /* arg long long - skip registers and push on stack */ | |
442 | |
443 static void dc_callvm_argLongLong_x86_win32_fast_gnu(DCCallVM* in_self, DClonglong x) | |
444 { | |
445 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
446 self->mIntRegs = 2; | |
447 dc_callvm_argLongLong_x86(in_self,x); | |
448 } | |
449 | |
450 /* win32/fast/gnu vt */ | |
451 | |
452 DCCallVM_vt gVT_x86_win32_fast_gnu = | |
453 { | |
454 &dc_callvm_free_x86 | |
455 , &dc_callvm_reset_x86_win32_fast | |
456 , &dc_callvm_mode_x86 | |
457 , &dc_callvm_argBool_x86_win32_fast_gnu | |
458 , &dc_callvm_argChar_x86_win32_fast_gnu | |
459 , &dc_callvm_argShort_x86_win32_fast_gnu | |
460 , &dc_callvm_argInt_x86_win32_fast_gnu | |
461 , &dc_callvm_argLong_x86_win32_fast_gnu | |
462 , &dc_callvm_argLongLong_x86_win32_fast_gnu | |
463 , &dc_callvm_argFloat_x86 | |
464 , &dc_callvm_argDouble_x86 | |
465 , &dc_callvm_argPointer_x86_win32_fast_gnu | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
466 , NULL /* argAggr */ |
0 | 467 , (DCvoidvmfunc*) &dc_callvm_call_x86_win32_fast |
468 , (DCboolvmfunc*) &dc_callvm_call_x86_win32_fast | |
469 , (DCcharvmfunc*) &dc_callvm_call_x86_win32_fast | |
470 , (DCshortvmfunc*) &dc_callvm_call_x86_win32_fast | |
471 , (DCintvmfunc*) &dc_callvm_call_x86_win32_fast | |
472 , (DClongvmfunc*) &dc_callvm_call_x86_win32_fast | |
473 , (DClonglongvmfunc*) &dc_callvm_call_x86_win32_fast | |
474 , (DCfloatvmfunc*) &dc_callvm_call_x86_win32_fast | |
475 , (DCdoublevmfunc*) &dc_callvm_call_x86_win32_fast | |
476 , (DCpointervmfunc*) &dc_callvm_call_x86_win32_fast | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
477 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
478 , NULL /* beginAggr */ |
0 | 479 }; |
480 | |
481 | |
482 /* --- this ms ------------------------------------------------------------- */ | |
483 | |
484 /* call win32/this/ms */ | |
485 | |
486 void dc_callvm_call_x86_win32_this_ms(DCCallVM* in_self, DCpointer target) | |
487 { | |
488 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
489 dcCall_x86_win32_msthis( target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead) ); | |
490 } | |
491 | |
492 /* win32/this/ms vt */ | |
493 | |
494 DCCallVM_vt gVT_x86_win32_this_ms = | |
495 { | |
496 &dc_callvm_free_x86 | |
497 , &dc_callvm_reset_x86 | |
498 , &dc_callvm_mode_x86 | |
499 , &dc_callvm_argBool_x86 | |
500 , &dc_callvm_argChar_x86 | |
501 , &dc_callvm_argShort_x86 | |
502 , &dc_callvm_argInt_x86 | |
503 , &dc_callvm_argLong_x86 | |
504 , &dc_callvm_argLongLong_x86 | |
505 , &dc_callvm_argFloat_x86 | |
506 , &dc_callvm_argDouble_x86 | |
507 , &dc_callvm_argPointer_x86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
508 , NULL /* argAggr */ |
0 | 509 , (DCvoidvmfunc*) &dc_callvm_call_x86_win32_this_ms |
510 , (DCboolvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
511 , (DCcharvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
512 , (DCshortvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
513 , (DCintvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
514 , (DClongvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
515 , (DClonglongvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
516 , (DCfloatvmfunc*) &dc_callvm_call_x86_win32_this_ms | |
517 , (DCdoublevmfunc*) &dc_callvm_call_x86_win32_this_ms | |
518 , (DCpointervmfunc*) &dc_callvm_call_x86_win32_this_ms | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
519 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
520 , NULL /* beginAggr */ |
0 | 521 }; |
522 | |
523 /* --- syscall ------------------------------------------------------------- */ | |
524 | |
525 /* call syscall */ | |
526 | |
341 | 527 void dc_callvm_call_x86_syscall_int80h_linux(DCCallVM* in_self, DCpointer target) |
0 | 528 { |
529 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
341 | 530 dcCall_x86_syscall_int80h_linux( target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead) ); |
0 | 531 } |
532 | |
341 | 533 void dc_callvm_call_x86_syscall_int80h_bsd(DCCallVM* in_self, DCpointer target) |
0 | 534 { |
535 DCCallVM_x86* self = (DCCallVM_x86*) in_self; | |
341 | 536 dcCall_x86_syscall_int80h_bsd( target, dcVecData(&self->mVecHead), dcVecSize(&self->mVecHead) ); |
0 | 537 } |
538 | |
341 | 539 DCCallVM_vt gVT_x86_syscall_int80h_linux = |
0 | 540 { |
541 &dc_callvm_free_x86 | |
542 , &dc_callvm_reset_x86 | |
543 , &dc_callvm_mode_x86 | |
544 , &dc_callvm_argBool_x86 | |
545 , &dc_callvm_argChar_x86 | |
546 , &dc_callvm_argShort_x86 | |
547 , &dc_callvm_argInt_x86 | |
548 , &dc_callvm_argLong_x86 | |
549 , &dc_callvm_argLongLong_x86 | |
550 , &dc_callvm_argFloat_x86 | |
551 , &dc_callvm_argDouble_x86 | |
552 , &dc_callvm_argPointer_x86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
553 , NULL /* argAggr */ |
341 | 554 , (DCvoidvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux |
555 , (DCboolvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
556 , (DCcharvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
557 , (DCshortvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
558 , (DCintvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
559 , (DClongvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
560 , (DClonglongvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
561 , (DCfloatvmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
562 , (DCdoublevmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
563 , (DCpointervmfunc*) &dc_callvm_call_x86_syscall_int80h_linux | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
564 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
565 , NULL /* beginAggr */ |
0 | 566 }; |
567 | |
341 | 568 DCCallVM_vt gVT_x86_syscall_int80h_bsd = |
0 | 569 { |
570 &dc_callvm_free_x86 | |
571 , &dc_callvm_reset_x86 | |
572 , &dc_callvm_mode_x86 | |
573 , &dc_callvm_argBool_x86 | |
574 , &dc_callvm_argChar_x86 | |
575 , &dc_callvm_argShort_x86 | |
576 , &dc_callvm_argInt_x86 | |
577 , &dc_callvm_argLong_x86 | |
578 , &dc_callvm_argLongLong_x86 | |
579 , &dc_callvm_argFloat_x86 | |
580 , &dc_callvm_argDouble_x86 | |
581 , &dc_callvm_argPointer_x86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
582 , NULL /* argAggr */ |
341 | 583 , (DCvoidvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd |
584 , (DCboolvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
585 , (DCcharvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
586 , (DCshortvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
587 , (DCintvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
588 , (DClongvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
589 , (DClonglongvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
590 , (DCfloatvmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
591 , (DCdoublevmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
592 , (DCpointervmfunc*) &dc_callvm_call_x86_syscall_int80h_bsd | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
593 , NULL /* callAggr */ |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
594 , NULL /* beginAggr */ |
0 | 595 }; |
596 | |
597 | |
598 #endif | |
599 | |
600 | |
601 /* mode */ | |
602 | |
603 void dc_callvm_mode_x86(DCCallVM* in_self, DCint mode) | |
604 { | |
84 | 605 DCCallVM_x86* self = (DCCallVM_x86*)in_self; |
606 DCCallVM_vt* vt; | |
607 | |
0 | 608 switch(mode) { |
84 | 609 case DC_CALL_C_DEFAULT: |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
610 #if !defined(DC__C_MSVC) |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
611 case DC_CALL_C_DEFAULT_THIS: |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
612 #endif |
0 | 613 case DC_CALL_C_ELLIPSIS: |
614 case DC_CALL_C_ELLIPSIS_VARARGS: | |
84 | 615 /* Plan9 (and forks) have their own calling convention (and no support for foreign ones). */ |
616 #if defined(DC_PLAN9) | |
0 | 617 case DC_CALL_C_X86_PLAN9: vt = &gVT_x86_plan9; break; |
618 #else | |
465
e2899b4ff713
- // -> /* */, mainly for consistency (but also for a few obscure compilers)
Tassilo Philipp
parents:
366
diff
changeset
|
619 case DC_CALL_C_X86_CDECL: vt = &gVT_x86_cdecl; break; /* also handles DC_CALL_C_X86_WIN32_THIS_GNU */ |
0 | 620 case DC_CALL_C_X86_WIN32_STD: vt = &gVT_x86_win32_std; break; |
621 case DC_CALL_C_X86_WIN32_FAST_MS: vt = &gVT_x86_win32_fast_ms; break; | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
622 #if defined(DC__C_MSVC) |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
623 case DC_CALL_C_DEFAULT_THIS: |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
624 #endif |
0 | 625 case DC_CALL_C_X86_WIN32_THIS_MS: vt = &gVT_x86_win32_this_ms; break; |
626 case DC_CALL_C_X86_WIN32_FAST_GNU: vt = &gVT_x86_win32_fast_gnu; break; | |
339 | 627 case DC_CALL_SYS_DEFAULT: |
0 | 628 # if defined DC_UNIX |
629 # if defined DC__OS_Linux | |
341 | 630 vt = &gVT_x86_syscall_int80h_linux; break; |
0 | 631 # else |
341 | 632 vt = &gVT_x86_syscall_int80h_bsd; break; |
0 | 633 # endif |
634 # else | |
635 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; return; | |
636 # endif | |
341 | 637 case DC_CALL_SYS_X86_INT80H_LINUX: vt = &gVT_x86_syscall_int80h_linux; break; |
638 case DC_CALL_SYS_X86_INT80H_BSD: vt = &gVT_x86_syscall_int80h_bsd; break; | |
0 | 639 #endif |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
465
diff
changeset
|
640 default: |
84 | 641 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; |
642 return; | |
0 | 643 } |
84 | 644 dc_callvm_base_init(&self->mInterface, vt); |
0 | 645 } |
646 | |
84 | 647 /* Public API. */ |
0 | 648 DCCallVM* dcNewCallVM(DCsize size) |
649 { | |
84 | 650 DCCallVM_x86* p = (DCCallVM_x86*)dcAllocMem(sizeof(DCCallVM_x86)+size); |
651 | |
652 dc_callvm_mode_x86((DCCallVM*)p, DC_CALL_C_DEFAULT); | |
653 | |
654 dcVecInit(&p->mVecHead, size); | |
655 dc_callvm_reset_x86((DCCallVM*)p); | |
656 | |
657 return (DCCallVM*)p; | |
0 | 658 } |
659 |