2
* Copyright (C) 2005 Karl Vogel, Giridhar Pemmasani
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
16
#include <linux/linkage.h>
21
# Windows <---> Linux register usage conversion when calling functions
23
# NV = Non Volatile (needs to be saved)
26
# ---------------------------------------
27
# Rax Return V Return V
44
# In addition, Linux uses %rax to indicate number of SSE registers used
45
# when variadic functions are called. Since there is no way to obtain this
46
# from Windows, for now, we just assume this is 0 (hence %rax is cleared).
48
# Windows pushes arguments 5 and higher onto stack in case of integer
49
# variables and 4 and higher in case of floating point variabes (passed
52
In a windows function, the stackframe/registers look like this:
59
# 0x0020 shadow/spill space for arg4
60
# 0x0018 shadow/spill space for arg3
61
# 0x0010 shadow/spill space for arg2
62
# 0x0008 shadow/spill space for arg1
65
# register spill space is same irrespective of number of arguments - even
66
# if Windows function takes less than 4 arguments, 32 bytes above return
67
# address is reserved for the function
69
In Linux it should look like:
79
# setup for Windows to Linux function call
94
# when Windows function calls Linux function, the function address is in %r10
97
xor %rax, %rax # rax indicates number of SSE regs
101
# before prolog, 0(%rsp) is return address, 8(%rsp) would be arg1
102
# (but it is in register) and so on, so n'th arg would be at n*8(%rsp)
103
# for n > 4. But in prolog, we push 2 registers that are non-volaile in
104
# Windows, but volatile in Linux. So after prolog, args are at (n+2)*8(%rsp)
106
#define win2lin_win_arg(n) (n+2)*8(%rsp)
108
#define win2lin_arg1 mov %rcx, %rdi
109
#define win2lin_arg2 mov %rdx, %rsi
110
#define win2lin_arg3 mov %r8, %rdx
111
#define win2lin_arg4 mov %r9, %rcx
112
#define win2lin_arg5 mov win2lin_win_arg(5), %r8
113
#define win2lin_arg6 mov win2lin_win_arg(6), %r9
115
.type win2lin0, @function
121
.size win2lin0, .-win2lin0
123
.type win2lin1, @function
130
.size win2lin1, .-win2lin1
132
.type win2lin2, @function
140
.size win2lin2, .-win2lin2
142
.type win2lin3, @function
151
.size win2lin3, .-win2lin3
153
.type win2lin4, @function
163
.size win2lin4, .-win2lin4
165
.type win2lin5, @function
176
.size win2lin5, .-win2lin5
178
.type win2lin6, @function
190
.size win2lin6, .-win2lin6
192
# Allocate stack frame for Linux arguments before calling function.
193
# First 6 args are passed through registers, so we need space for 7 and above.
194
# The arguments should have been copied onto stack already.
196
.macro call_lin_func_args n
202
# m is index of Linux arg required, n is total number of args to function
203
# After stack frame is allocated, Linux arg 7 should be at 0(%rsp),
204
# arg 8 should be at 1*8(%rsp) and so on. So Linux arg m should be at (m-7)*8
205
# Stack frame starts at -(n-6)*8(%rsp), so before stack frame is allocated
206
# Linux arg m should be at (6-n+m-7)*8(%rsp)
208
#define win2lin_lin_arg(m,n) (m-1-n)*8(%rsp)
210
.type win2lin7, @function
221
# copy windows argument 7 onto stack for Linux function
222
mov win2lin_win_arg(7), %r11
223
mov %r11, win2lin_lin_arg(7,7)
225
call_lin_func_args(7)
228
.size win2lin7, .-win2lin7
230
.type win2lin8, @function
241
# copy windows arguments 7 and 8 onto stack for Linux function
242
mov win2lin_win_arg(7), %r11
243
mov %r11, win2lin_lin_arg(7,8)
244
mov win2lin_win_arg(8), %r11
245
mov %r11, win2lin_lin_arg(8,8)
247
call_lin_func_args(8)
250
.size win2lin8, .-win2lin8
252
.type win2lin9, @function
259
# since we destroy rsi and rdi here, first copy windows
260
# arguments 7 through 12 onto stack for Linux function
261
mov %rcx, %r11 # save rcx
262
lea win2lin_win_arg(7), %rsi # source (windows arg 7 and up)
263
lea win2lin_lin_arg(7,12), %rdi # = destination
264
mov $6, %rcx # 6 arguments
267
mov %r11, %rcx # restore rcx
276
call_lin_func_args(12)
279
.size win2lin9, .-win2lin9
281
#define win2lin(name, argc) \
282
ENTRY(win2lin_ ## name ## _ ## argc) \
283
lea name(%rip), %r10 ; \
286
#include "win2lin_stubs.h"
288
#endif // CONFIG_X86_64