1dnl  AMD64 calling conventions checking.
2
3dnl  Copyright 2000, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
4dnl
5dnl  This file is part of the GNU MP Library.
6dnl
7dnl  The GNU MP Library is free software; you can redistribute it and/or
8dnl  modify it under the terms of the GNU Lesser General Public License as
9dnl  published by the Free Software Foundation; either version 3 of the
10dnl  License, or (at your option) any later version.
11dnl
12dnl  The GNU MP Library is distributed in the hope that it will be useful,
13dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
14dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15dnl  Lesser General Public License for more details.
16dnl
17dnl  You should have received a copy of the GNU Lesser General Public License
18dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
19
20
21include(`../config.m4')
22
23
24C void x86_fldcw (unsigned short cw);
25C
26C Execute an fldcw, setting the x87 control word to cw.
27
28PROLOGUE(x86_fldcw)
29	movq	%rdi, -8(%rsp)
30	fldcw	-8(%rsp)
31	ret
32EPILOGUE()
33
34
35C unsigned short x86_fstcw (void);
36C
37C Execute an fstcw, returning the current x87 control word.
38
39PROLOGUE(x86_fstcw)
40        movq	$0, -8(%rsp)
41        fstcw	-8(%rsp)
42        movq	-8(%rsp), %rax
43	ret
44EPILOGUE()
45
46
47dnl  Instrumented profiling won't come out quite right below, since we don't
48dnl  do an actual "ret".  There's only a few instructions here, so there's
49dnl  no great need to get them separately accounted, just let them get
50dnl  attributed to the caller.
51
52ifelse(WANT_PROFILING,instrument,
53`define(`WANT_PROFILING',no)')
54
55
56C int calling_conventions (...);
57C
58C The global variable "calling_conventions_function" is the function to
59C call, with the arguments as passed here.
60C
61C Perhaps the finit should be done only if the tags word isn't clear, but
62C nothing uses the rounding mode or anything at the moment.
63
64define(`WANT_RBX', eval(8*0)($1))
65define(`WANT_RBP', eval(8*1)($1))
66define(`WANT_R12', eval(8*2)($1))
67define(`WANT_R13', eval(8*3)($1))
68define(`WANT_R14', eval(8*4)($1))
69define(`WANT_R15', eval(8*5)($1))
70
71define(`JUNK_RAX', eval(8*6)($1))
72define(`JUNK_R10', eval(8*7)($1))
73define(`JUNK_R11', eval(8*8)($1))
74
75define(`SAVE_RBX', eval(8*9)($1))
76define(`SAVE_RBP', eval(8*10)($1))
77define(`SAVE_R12', eval(8*11)($1))
78define(`SAVE_R13', eval(8*12)($1))
79define(`SAVE_R14', eval(8*13)($1))
80define(`SAVE_R15', eval(8*14)($1))
81
82define(`RETADDR',  eval(8*15)($1))
83
84define(`RBX',	   eval(8*16)($1))
85define(`RBP',	   eval(8*17)($1))
86define(`R12',	   eval(8*18)($1))
87define(`R13',	   eval(8*19)($1))
88define(`R14',	   eval(8*20)($1))
89define(`R15',	   eval(8*21)($1))
90define(`RFLAGS',   eval(8*22)($1))
91
92
93define(G,
94m4_assert_numargs(1)
95`GSYM_PREFIX`'$1')
96
97	TEXT
98	ALIGN(32)
99PROLOGUE(calling_conventions)
100	push	%rdi
101	movq	G(calling_conventions_values)@GOTPCREL(%rip), %rdi
102
103	movq	8(%rsp), %rax
104	movq	%rax, RETADDR(%rdi)
105
106	leaq	L(return)(%rip), %rax
107	movq	%rax, 8(%rsp)
108
109	movq	%rbx, SAVE_RBX(%rdi)
110	movq	%rbp, SAVE_RBP(%rdi)
111	movq	%r12, SAVE_R12(%rdi)
112	movq	%r13, SAVE_R13(%rdi)
113	movq	%r14, SAVE_R14(%rdi)
114	movq	%r15, SAVE_R15(%rdi)
115
116	C values we expect to see unchanged, as per amd64check.c
117	movq	WANT_RBX(%rdi), %rbx
118	movq	WANT_RBP(%rdi), %rbp
119	movq	WANT_R12(%rdi), %r12
120	movq	WANT_R13(%rdi), %r13
121	movq	WANT_R14(%rdi), %r14
122	movq	WANT_R15(%rdi), %r15
123
124	C Try to provoke a problem by starting with junk in the registers,
125	C especially %rax which will be the return value.
126	C
127	C ENHANCE-ME: If we knew how many of the parameter registers were
128	C actually being used we could put junk in the rest.  Maybe we could
129	C get try.c to communicate this to us.
130C	movq	JUNK_RAX(%rdi), %rax		C overwritten below anyway
131	movq	JUNK_R10(%rdi), %r10
132	movq	JUNK_R11(%rdi), %r11
133
134	movq	G(calling_conventions_function)@GOTPCREL(%rip), %rax
135	pop	%rdi
136	jmp	*(%rax)
137
138L(return):
139	movq	G(calling_conventions_values)@GOTPCREL(%rip), %rdi
140
141	movq	%rbx, RBX(%rdi)
142	movq	%rbp, RBP(%rdi)
143	movq	%r12, R12(%rdi)
144	movq	%r13, R13(%rdi)
145	movq	%r14, R14(%rdi)
146	movq	%r15, R15(%rdi)
147
148	pushfq
149	popq	%rbx
150	movq	%rbx, RFLAGS(%rdi)
151
152	movq	G(calling_conventions_fenv)@GOTPCREL(%rip), %rbx
153	fstenv	(%rbx)
154	finit
155
156	movq	SAVE_RBX(%rdi), %rbx
157	movq	SAVE_RBP(%rdi), %rbp
158	movq	SAVE_R12(%rdi), %r12
159	movq	SAVE_R13(%rdi), %r13
160	movq	SAVE_R14(%rdi), %r14
161	movq	SAVE_R15(%rdi), %r15
162
163	jmp	*RETADDR(%rdi)
164
165EPILOGUE()
166