81
* Registers %rdi and %rsi must be preserved on Windows, but not on Linux.
95
* Allocate stack frame for Linux arguments.
97
* First 6 arguments are passed through registers, so we need space for
98
* argument 7 and above. The arguments should be copied onto stack after
99
* the space has been reserved.
102
.macro reserve_stack argtotal
103
sub $(\argtotal - 6) * 8, %rsp
106
.macro free_stack argtotal
107
add $(\argtotal - 6) * 8, %rsp
111
* Call Linux function. win2lin macro puts its address to %r10.
115
xor %rax, %rax /* number of arguments in SSE registers */
120
* win2lin_win_arg(N, ARGTOTAL) gives the address of the Windows argument
121
* N out of ARGTOTAL after the stack has been prepared for the Linux function
124
* When calling the Linux function, two registers (%rdi and %rsi) are pushed
125
* to the stack in win2lin_prolog. When passing more than 6 arguments,
126
* arguments starting with argument 7 are pushed to the stack as well.
128
* When called from Windows, the Nth argument is at (N * 8)(%rsp). We add two
129
* 8-byte positions for the saved registers (%rdi and %rsi) and (ARGTOTAL - 6)
130
* for the arguments to be passed on stack to the Linux function.
132
* If there are 6 and less arguments, ARGTOTAL must be 6. N must be at least
133
* 5, as arguments 1 to 4 are passed in registers.
135
#define win2lin_win_arg(arg, argtotal) ((arg + 2 + (argtotal - 6)) * 8)(%rsp)
138
* win2lin_lin_arg(N) gives the address of the Nth linux argument of the extra
139
* linux stack frame. When more than 6 arguments are used, %rsp points to the
80
#define LINUX_REG_ARGS 6
81
#define LOOP_THRESHOLD 9
85
* %rsi and %rdi must be saved because they are not saved by Linux calls, but
86
* Windows callers expect them to be saved. %rbp is saved to create a stack
87
* frame, which can help with debugging. We need to reserve space for an odd
88
* number of registers anyway to keep 16-bit alignment of the stack (one more
89
* position is used by the return address).
94
* When calling the Linux function, several registers are saved on the stack.
95
* When passing more than 6 arguments, arguments starting with argument 7 are
96
* pushed to the stack as well.
98
* We also need to allocate an additional word on the stack to keep it aligned
99
* to the 16-bit boundary if the number of saved arguments plus one (for the
100
* return address) is odd.
104
* Number of arguments we pass on stack to the Linux function.
105
* The value of true is -1 in assembler, so we multiply it by another true
108
#define stack_args(argc) \
109
((0 < 1) * (argc > LINUX_REG_ARGS) * (argc - LINUX_REG_ARGS))
111
/* Full required change of stack pointer, in words */
112
#define stack_words_raw(argc) (stack_args(argc) + SAVED_REGS + 1)
114
/* Full actual change of stack pointer, in words (must be even) */
115
#define stack_words_aligned(argc) ((stack_words_raw(argc) + 1) & ~1)
117
/* Space allocated for Linux arguments on stack */
118
#define stack_space(argc) \
119
((stack_words_aligned(argc) - SAVED_REGS - 1) * WORD_BYTES)
122
* win2lin_win_arg(N, ARGC) gives the address of the Windows argument N out of
123
* total ARGC after the stack has been prepared for the Linux function call.
125
* When called from Windows, the Nth argument is at (N * 8)(%rsp). We add the
126
* stack space allocated by the Linux function to compensate for %rsp change.
128
* Don't call with N less than 5!
130
#define win2lin_win_arg(n, argc) \
131
((n + SAVED_REGS) * WORD_BYTES + stack_space(argc))(%rsp)
134
* win2lin_lin_arg(N) gives the address of the Nth Linux argument on the extra
135
* Linux stack frame. When more than 6 arguments are used, %rsp points to the
140
136
* 7th argument. The Nth argument is therefore at ((N - 7) * 8)(%rsp).
142
#define win2lin_lin_arg(n) ((n - 7) * 8)(%rsp)
144
/* Copy arguments 1 - 4 */
145
#define win2lin_arg1 mov %rcx, %rdi
146
#define win2lin_arg2 mov %rdx, %rsi
147
#define win2lin_arg3 mov %r8, %rdx
148
#define win2lin_arg4 mov %r9, %rcx
151
* Copy arguments 5 - 6.
153
* Arguments 5 and 6 must be copied after arguments 3 and 4 to prevent
154
* clobbering %r8 and %r9. win2lin_arg5 and win2lin_arg6 must be used
155
* only between win2lin_prolog and reserving the extra stack space for the
158
#define win2lin_arg5 mov win2lin_win_arg(5, 6), %r8
159
#define win2lin_arg6 mov win2lin_win_arg(6, 6), %r9
161
.type win2lin0, @function
167
.size win2lin0, .-win2lin0
169
.type win2lin1, @function
176
.size win2lin1, .-win2lin1
178
.type win2lin2, @function
186
.size win2lin2, .-win2lin2
188
.type win2lin3, @function
197
.size win2lin3, .-win2lin3
199
.type win2lin4, @function
209
.size win2lin4, .-win2lin4
211
.type win2lin5, @function
222
.size win2lin5, .-win2lin5
224
.type win2lin6, @function
236
.size win2lin6, .-win2lin6
238
.type win2lin7, @function
251
/* Copy Windows argument 7 onto stack for the Linux function */
252
mov win2lin_win_arg(7, 7), %r11
253
mov %r11, win2lin_lin_arg(7)
261
.size win2lin7, .-win2lin7
263
.type win2lin8, @function
276
/* Copy Windows arguments 7 and 8 onto stack for the Linux function */
277
mov win2lin_win_arg(7,8), %r11
278
mov %r11, win2lin_lin_arg(7)
279
mov win2lin_win_arg(8,8), %r11
280
mov %r11, win2lin_lin_arg(8)
288
.size win2lin8, .-win2lin8
291
* We assume here that we never need to handle more than 12 arguments.
292
* Copy 12 arguments even if we need less.
294
.type win2lin9, @function
303
/* Copy Windows arguments 7 through 12 onto stack */
304
mov %rcx, %r11 /* save %rcx */
305
lea win2lin_win_arg(7, 12), %rsi /* source */
306
lea win2lin_lin_arg(7), %rdi /* destination */
307
mov $6, %rcx /* 6 arguments */
310
mov %r11, %rcx /* restore %rcx */
312
/* Copy arguments 1 - 4 */
319
* Copy arguments 5 and 6. Cannot use win2lin_arg5 and win2lin_arg6
320
* after reserve_stack.
322
mov win2lin_win_arg(5, 12), %r8
323
mov win2lin_win_arg(6, 12), %r9
331
.size win2lin9, .-win2lin9
333
#define win2lin(name, argc) \
334
ENTRY(win2lin_ ## name ## _ ## argc) \
335
lea name(%rip), %r10 ; \
138
* Don't call with N less than 7!
140
#define win2lin_lin_arg(n) ((n - 1 - LINUX_REG_ARGS) * WORD_BYTES)(%rsp)
142
/* Declare function LONGNAME, call function SHORTNAME with ARGC arguments */
143
.macro win2linm longname, shortname, argc
144
.type \longname, @function
147
/* Create a call frame - it's optional, but good for debugging */
150
.cfi_def_cfa %rsp, 2 * WORD_BYTES
151
.cfi_offset %rbp, -2 * WORD_BYTES
153
.cfi_def_cfa %rbp, 2 * WORD_BYTES
156
* Registers %rdi and %rsi are volatile on Linux, but not on Windows,
157
* so save them on the stack.
162
/* Allocate extra stack space for arguments 7 and up */
163
sub $stack_space(\argc), %rsp
166
* Copy arguments 7 and up. We do it early, before %rdi and %rsi
167
* are used for arguments 1 and 2, so we don't have to save them.
168
* We still need to save %rcx if using a string copy.
170
.if (\argc < LOOP_THRESHOLD)
171
/* If a few arguments, copy them individually through %r11 */
173
mov win2lin_win_arg(7, \argc), %r11
174
mov %r11, win2lin_lin_arg(7)
177
mov win2lin_win_arg(8, \argc), %r11
178
mov %r11, win2lin_lin_arg(8)
181
/* If there are many arguments, copy them in a loop */
182
/* Save arg1 to %r11 */
184
/* Source and destination */
185
lea win2lin_win_arg(LINUX_REG_ARGS + 1, \argc), %rsi
186
lea win2lin_lin_arg(LINUX_REG_ARGS + 1), %rdi
187
/* Number of arguments to copy (%ecx zero-extends to %rcx) */
188
mov $(\argc - LINUX_REG_ARGS), %ecx
190
/* Restore arg1 directly to %rdi */
195
* Argument 1 - %rcx on Windows, %rdi on Linux
196
* Micro-optimization - if we used loop, arg1 is already in %rdi
198
.if (\argc >= 1) && (\argc < LOOP_THRESHOLD)
202
/* Argument 2 - %rdx on Windows, %rsi on Linux */
207
/* Argument 3 - %r8 on Windows, %rdx on Linux */
212
/* Argument 4 - %r9 on Windows, %rcx on Linux */
217
/* Argument 5 - first argument on stack on Windows, %r8 Linux */
219
mov win2lin_win_arg(5, \argc), %r8
222
/* Argument 6 - second argument on stack on Windows, %r9 Linux */
224
mov win2lin_win_arg(6, \argc), %r9
227
/* %rax on Linux is the number of arguments in SSE registers (zero) */
230
/* Call the function */
233
/* Free stack space for arguments 7 and up */
234
add $stack_space(\argc), %rsp
236
/* Restore saved registers */
240
/* Return to Windows code */
242
.cfi_def_cfa %rsp, WORD_BYTES
246
.size \longname, (. - \longname)
249
#define win2lin(name, argc) win2linm win2lin_ ## name ## _ ## argc, name, argc
338
251
#include "win2lin_stubs.h"