comparison dyncall/dyncall_call_x86.S @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children 572aff021627
comparison
equal deleted inserted replaced
-1:000000000000 0:3e629dc19168
1 /*
2
3 Package: dyncall
4 Library: dyncall
5 File: dyncall/dyncall_call_x86.S
6 Description: All - except Plan9 - x86 abi call kernel 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 #include "../portasm/portasm-x86.S"
29 BEGIN_ASM
30 /* ============================================================================
31 DynCall Call Kernels for X86 Architecture
32 ----------------------------------------------------------------------------
33 C Interface:
34 dcCall_x86_XXX(void* target, void* args, size_t size);
35 ddCall_x86_sys_XXX(int_ptr target, void* args, size_t size);
36
37 Where XXX is one of calling-conventions,
38 cdecl, win32_msthis, win32_std, win32_fastcall.
39
40 Parameter Stack layout:
41 size := EBP + 16
42 args := EBP + 12
43 target := EBP + 8
44
45 NOTES:
46 - epilog restore ESP serves callee cleanup
47 - 16 byte alignment (to be compatible with darwin).
48 */
49
50
51 /*--- default / cdecl --------------------------------------------------------
52
53 Details:
54 - caller clean-up
55
56 */
57
58 GLOBAL(dcCall_x86_cdecl)
59 BEGIN_PROC(dcCall_x86_cdecl)
60 PUSH(EBP) /* prolog. */
61 MOVL(ESP,EBP)
62 PUSH(ESI) /* save preserved registers. */
63 PUSH(EDI)
64 MOVL(DWORD(EBP,12),ESI) /* ESI = arg buffer ptr */
65 MOVL(DWORD(EBP,16),ECX) /* ECX = arg buffer size */
66 ADDL(LIT(15),ECX) /* ECX = align(ECX,16) */
67 ANDL(LIT(-16),ECX)
68 MOVL(ECX,DWORD(EBP,16)) /* save ECX. */
69 SUBL(ECX,ESP) /* allocate stack size */
70 MOVL(ESP,EDI) /* EDI = stack ptr */
71
72 /*
73 work around for rep movsd (not supported by SunPro)
74
75 SHRL(LIT(2),ECX)
76 REP(MOVSD)
77
78 */
79
80 REP(MOVSB)
81 CALL_DWORD(EBP,8)
82 ADDL(DWORD(EBP,16),ESP)
83 POP(EDI)
84 POP(ESI)
85 MOVL(EBP,ESP)
86 POP(EBP)
87 RET()
88 END_PROC(dcCall_x86_cdecl)
89 /* ---- C++ this calls (microsoft) ------------------------------------------
90
91 Details:
92 - this pointer is in ECX
93
94 */
95
96 GLOBAL(dcCall_x86_win32_msthis)
97 BEGIN_PROC(dcCall_x86_win32_msthis)
98 PUSH(EBP) /* prolog. */
99 MOVL(ESP,EBP)
100 PUSH(ESI) /* save preserved. */
101 PUSH(EDI)
102 MOVL(DWORD(EBP,12),ESI) /* ESI = pointer on args. */
103 MOVL(DWORD(EBP,16),ECX) /* ECX = size. */
104 MOVL(DWORD(ESI,0),EAX) /* EAX = this pointer. */
105 ADDL(LIT(4),ESI) /* increment args pointer by thisptr. */
106 SUBL(LIT(4),ECX) /* decrement size by sizeof(thisptr). */
107 SUBL(ECX,ESP) /* allocate argument-block on stack. */
108 MOVL(ESP,EDI) /* EDI = stack args. */
109 REP(MOVSB) /* copy arguments. */
110 MOVL(EAX,ECX) /* ECX = this pointer. */
111 CALL_DWORD(EBP,8) /* call function. */
112 POP(EDI) /* restore preserved. */
113 POP(ESI)
114 MOVL(EBP,ESP) /* epilog. */
115 POP(EBP)
116 RET()
117 END_PROC(dcCall_x86_win32_msthis)
118
119 /*---- win32 stdcall ---------------------------------------------------------
120
121 Details:
122 - callee cleans up stack
123
124 */
125
126 GLOBAL(dcCall_x86_win32_std)
127 BEGIN_PROC(dcCall_x86_win32_std)
128 PUSH(EBP) /* prolog. */
129 MOVL(ESP,EBP)
130 PUSH(ESI) /* save ESI, EDI. */
131 PUSH(EDI)
132 MOVL(DWORD(EBP,12),ESI) /* ESI = args. */
133 MOVL(DWORD(EBP,16),ECX) /* ECX = size. */
134 SUBL(ECX,ESP) /* allocate size bytes on stack. */
135 MOVL(ESP,EDI) /* EDI = copy destination stack. */
136 REP(MOVSB) /* copy BYTEs. */
137 CALL_DWORD(EBP,8) /* call target. */
138 POP(EDI) /* restore EDI, ESI. */
139 POP(ESI)
140 MOVL(EBP,ESP) /* epilog. */
141 POP(EBP)
142 RET()
143 END_PROC(dcCall_x86_win32_std)
144
145 /*---- win32 fastcall (GNU/Microsoft) ----------------------------------------
146
147 Details:
148 - callee cleans up stack
149 - first two integer (up to 32bits) are passed in ECX and EDX
150
151 */
152
153 GLOBAL(dcCall_x86_win32_fast)
154 BEGIN_PROC(dcCall_x86_win32_fast)
155 PUSH(EBP) /* prolog. */
156 MOVL(ESP,EBP)
157 PUSH(ESI) /* save preserved. */
158 PUSH(EDI)
159 MOVL(DWORD(EBP,12),ESI) /* ESI = copy source args. */
160 MOVL(DWORD(EBP,16),ECX) /* ECX = size. */
161 MOVL(DWORD(ESI,0),EAX) /* EAX = first argument. */
162 MOVL(DWORD(ESI,4),EDX) /* EDX = second argument. */
163 ADDL(LIT(8),ESI) /* skip registers. */
164 SUBL(LIT(8),ECX)
165 MOVL(ECX,DWORD(EBP,16)) /* save stack alloc size. */
166 SUBL(ECX,ESP) /* allocate stack. */
167 MOVL(ESP,EDI) /* EDI = stack args. */
168 REP(MOVSB) /* copy BYTEs. */
169 MOVL(EAX,ECX) /* ECX = first argument. */
170 CALL_DWORD(EBP,8) /* call target. */
171 POP(EDI) /* restore preserved. */
172 POP(ESI)
173 MOVL(EBP,ESP) /* epilog. */
174 POP(EBP)
175 RET()
176 END_PROC(dcCall_x86_win32_fast)
177
178 /*--- syscall int80 linux ---------------------------------------------------
179
180 Details:
181 - all arguments are passed via registers
182
183 */
184
185 GLOBAL(dcCall_x86_sys_int80h_linux)
186 BEGIN_PROC(dcCall_x86_sys_int80h_linux)
187 PUSH(EBP) /* prolog. */
188 MOVL(ESP,EBP)
189 PUSH(EBX) /* save preserved. */
190 PUSH(ESI)
191 PUSH(EDI)
192 MOVL(DWORD(EBP,12),EAX) /* EAX = argument buffer. */
193 MOVL(DWORD(EAX,0),EBX) /* move first five arguments. */
194 MOVL(DWORD(EAX,4),ECX)
195 MOVL(DWORD(EAX,8),EDX)
196 MOVL(DWORD(EAX,12),ESI)
197 MOVL(DWORD(EAX,16),EDI)
198 MOVL(DWORD(EBP,8),EAX) /* EAX = syscall id. */
199 INT(LIT(HEX(80)))
200 POP(EDI) /* restore preserved. */
201 POP(ESI)
202 POP(EBX)
203 MOVL(EBP,ESP) /* epilog. */
204 POP(EBP)
205 RET()
206 END_PROC(dcCall_x86_sys_int80h_linux)
207
208 /*--- syscall int80 bsd -----------------------------------------------------
209
210 Details:
211 - all arguments are passed via stack
212
213 */
214
215 GLOBAL(dcCall_x86_sys_int80h_bsd)
216 BEGIN_PROC(dcCall_x86_sys_int80h_bsd)
217 PUSH(EBP) /* prolog. */
218 MOVL(ESP,EBP)
219 PUSH(ESI) /* save preserved. */
220 PUSH(EDI)
221 MOVL(DWORD(EBP,12),ESI) /* ESI = pointer on args. */
222 MOVL(DWORD(EBP,16),ECX) /* ECX = size. */
223 SUBL(ECX,ESP) /* allocate stack space. */
224 MOVL(ESP,EDI) /* EDI = stack args. */
225 REP(MOVSB)
226 MOVL(DWORD(EBP,8),EAX) /* load system call id. */
227 CALL(_do_int)
228 POP(EDI) /* restore preserved. */
229 POP(ESI)
230 MOVL(EBP,ESP) /* epilog. */
231 POP(EBP)
232 RET()
233 _do_int:
234 INT(LIT(HEX(80)))
235 RET()
236 END_PROC(dcCall_x86_sys_int80h_bsd)
237
238 END_ASM
239