ยปCore Development>Code coverage>Modules/_ctypes/libffi_msvc/win32.c

Python code coverage for Modules/_ctypes/libffi_msvc/win32.c

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
3n/a Copyright (c) 2001 John Beniton
4n/a Copyright (c) 2002 Ranjit Mathew
5n/a
6n/a
7n/a X86 Foreign Function Interface
8n/a
9n/a Permission is hereby granted, free of charge, to any person obtaining
10n/a a copy of this software and associated documentation files (the
11n/a ``Software''), to deal in the Software without restriction, including
12n/a without limitation the rights to use, copy, modify, merge, publish,
13n/a distribute, sublicense, and/or sell copies of the Software, and to
14n/a permit persons to whom the Software is furnished to do so, subject to
15n/a the following conditions:
16n/a
17n/a The above copyright notice and this permission notice shall be included
18n/a in all copies or substantial portions of the Software.
19n/a
20n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21n/a OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23n/a IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24n/a OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25n/a ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26n/a OTHER DEALINGS IN THE SOFTWARE.
27n/a ----------------------------------------------------------------------- */
28n/a
29n/a/* theller: almost verbatim translation from gas syntax to MSVC inline
30n/a assembler code. */
31n/a
32n/a/* theller: ffi_call_x86 now returns an integer - the difference of the stack
33n/a pointer before and after the function call. If everything is ok, zero is
34n/a returned. If stdcall functions are passed the wrong number of arguments,
35n/a the difference will be nonzero. */
36n/a
37n/a#include <ffi.h>
38n/a#include <ffi_common.h>
39n/a
40n/a__declspec(naked) int
41n/affi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
42n/a extended_cif *ecif, /* 12 */
43n/a unsigned bytes, /* 16 */
44n/a unsigned flags, /* 20 */
45n/a unsigned *rvalue, /* 24 */
46n/a void (*fn)()) /* 28 */
47n/a{
48n/a _asm {
49n/a push ebp
50n/a mov ebp, esp
51n/a
52n/a push esi // NEW: this register must be preserved across function calls
53n/a// XXX SAVE ESP NOW!
54n/a mov esi, esp // save stack pointer before the call
55n/a
56n/a// Make room for all of the new args.
57n/a mov ecx, [ebp+16]
58n/a sub esp, ecx // sub esp, bytes
59n/a
60n/a mov eax, esp
61n/a
62n/a// Place all of the ffi_prep_args in position
63n/a push [ebp + 12] // ecif
64n/a push eax
65n/a call [ebp + 8] // prepfunc
66n/a
67n/a// Return stack to previous state and call the function
68n/a add esp, 8
69n/a// FIXME: Align the stack to a 128-bit boundary to avoid
70n/a// potential performance hits.
71n/a call [ebp + 28]
72n/a
73n/a// Load ecif->cif->abi
74n/a mov ecx, [ebp + 12]
75n/a mov ecx, [ecx]ecif.cif
76n/a mov ecx, [ecx]ecif.cif.abi
77n/a
78n/a cmp ecx, FFI_STDCALL
79n/a je noclean
80n/a// STDCALL: Remove the space we pushed for the args
81n/a mov ecx, [ebp + 16]
82n/a add esp, ecx
83n/a// CDECL: Caller has already cleaned the stack
84n/anoclean:
85n/a// Check that esp has the same value as before!
86n/a sub esi, esp
87n/a
88n/a// Load %ecx with the return type code
89n/a mov ecx, [ebp + 20]
90n/a
91n/a// If the return value pointer is NULL, assume no return value.
92n/a/*
93n/a Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
94n/a otherwise only one BYTE will be compared (instead of a DWORD)!
95n/a */
96n/a cmp DWORD PTR [ebp + 24], 0
97n/a jne sc_retint
98n/a
99n/a// Even if there is no space for the return value, we are
100n/a// obliged to handle floating-point values.
101n/a cmp ecx, FFI_TYPE_FLOAT
102n/a jne sc_noretval
103n/a// fstp %st(0)
104n/a fstp st(0)
105n/a
106n/a jmp sc_epilogue
107n/a
108n/asc_retint:
109n/a cmp ecx, FFI_TYPE_INT
110n/a jne sc_retfloat
111n/a// # Load %ecx with the pointer to storage for the return value
112n/a mov ecx, [ebp + 24]
113n/a mov [ecx + 0], eax
114n/a jmp sc_epilogue
115n/a
116n/asc_retfloat:
117n/a cmp ecx, FFI_TYPE_FLOAT
118n/a jne sc_retdouble
119n/a// Load %ecx with the pointer to storage for the return value
120n/a mov ecx, [ebp+24]
121n/a// fstps (%ecx)
122n/a fstp DWORD PTR [ecx]
123n/a jmp sc_epilogue
124n/a
125n/asc_retdouble:
126n/a cmp ecx, FFI_TYPE_DOUBLE
127n/a jne sc_retlongdouble
128n/a// movl 24(%ebp),%ecx
129n/a mov ecx, [ebp+24]
130n/a fstp QWORD PTR [ecx]
131n/a jmp sc_epilogue
132n/a
133n/a jmp sc_retlongdouble // avoid warning about unused label
134n/asc_retlongdouble:
135n/a cmp ecx, FFI_TYPE_LONGDOUBLE
136n/a jne sc_retint64
137n/a// Load %ecx with the pointer to storage for the return value
138n/a mov ecx, [ebp+24]
139n/a// fstpt (%ecx)
140n/a fstp QWORD PTR [ecx] /* XXX ??? */
141n/a jmp sc_epilogue
142n/a
143n/asc_retint64:
144n/a cmp ecx, FFI_TYPE_SINT64
145n/a jne sc_retstruct
146n/a// Load %ecx with the pointer to storage for the return value
147n/a mov ecx, [ebp+24]
148n/a mov [ecx+0], eax
149n/a mov [ecx+4], edx
150n/a
151n/asc_retstruct:
152n/a// Nothing to do!
153n/a
154n/asc_noretval:
155n/asc_epilogue:
156n/a mov eax, esi
157n/a pop esi // NEW restore: must be preserved across function calls
158n/a mov esp, ebp
159n/a pop ebp
160n/a ret
161n/a }
162n/a}