1/* stuff needed for libgcc on win32.
2 *
3 *   Copyright (C) 1996-2013 Free Software Foundation, Inc.
4 *   Written By Steve Chamberlain
5 *
6 * This file is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 3, or (at your option) any
9 * later version.
10 *
11 * This file is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * Under Section 7 of GPL version 3, you are granted additional
17 * permissions described in the GCC Runtime Library Exception, version
18 * 3.1, as published by the Free Software Foundation.
19 *
20 * You should have received a copy of the GNU General Public License and
21 * a copy of the GCC Runtime Library Exception along with this program;
22 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 * <http://www.gnu.org/licenses/>.
24 */
25
26#include "auto-host.h"
27
28#ifdef HAVE_GAS_CFI_SECTIONS_DIRECTIVE
29	.cfi_sections	.debug_frame
30# define cfi_startproc()		.cfi_startproc
31# define cfi_endproc()			.cfi_endproc
32# define cfi_adjust_cfa_offset(X) 	.cfi_adjust_cfa_offset X
33# define cfi_def_cfa_register(X)	.cfi_def_cfa_register X
34# define cfi_register(D,S)		.cfi_register D, S
35# ifdef _WIN64
36#  define cfi_push(X)		.cfi_adjust_cfa_offset 8; .cfi_rel_offset X, 0
37#  define cfi_pop(X)		.cfi_adjust_cfa_offset -8; .cfi_restore X
38# else
39#  define cfi_push(X)		.cfi_adjust_cfa_offset 4; .cfi_rel_offset X, 0
40#  define cfi_pop(X)		.cfi_adjust_cfa_offset -4; .cfi_restore X
41# endif
42#else
43# define cfi_startproc()
44# define cfi_endproc()
45# define cfi_adjust_cfa_offset(X)
46# define cfi_def_cfa_register(X)
47# define cfi_register(D,S)
48# define cfi_push(X)
49# define cfi_pop(X)
50#endif /* HAVE_GAS_CFI_SECTIONS_DIRECTIVE */
51
52#ifdef L_chkstk
53/* Function prologue calls __chkstk to probe the stack when allocating more
54   than CHECK_STACK_LIMIT bytes in one go.  Touching the stack at 4K
55   increments is necessary to ensure that the guard pages used
56   by the OS virtual memory manger are allocated in correct sequence.  */
57
58	.global ___chkstk
59	.global	__alloca
60#ifdef _WIN64
61/* __alloca is a normal function call, which uses %rcx as the argument.  */
62	cfi_startproc()
63__alloca:
64	movq	%rcx, %rax
65	/* FALLTHRU */
66
67/* ___chkstk is a *special* function call, which uses %rax as the argument.
68   We avoid clobbering the 4 integer argument registers, %rcx, %rdx,
69   %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use.  */
70	.align	4
71___chkstk:
72	popq	%r11			/* pop return address */
73	cfi_adjust_cfa_offset(-8)	/* indicate return address in r11 */
74	cfi_register(%rip, %r11)
75	movq	%rsp, %r10
76	cmpq	$0x1000, %rax		/* > 4k ?*/
77	jb	2f
78
791:	subq	$0x1000, %r10  		/* yes, move pointer down 4k*/
80	orl	$0x0, (%r10)   		/* probe there */
81	subq	$0x1000, %rax  	 	/* decrement count */
82	cmpq	$0x1000, %rax
83	ja	1b			/* and do it again */
84
852:	subq	%rax, %r10
86	movq	%rsp, %rax		/* hold CFA until return */
87	cfi_def_cfa_register(%rax)
88	orl	$0x0, (%r10)		/* less than 4k, just peek here */
89	movq	%r10, %rsp		/* decrement stack */
90
91	/* Push the return value back.  Doing this instead of just
92	   jumping to %r11 preserves the cached call-return stack
93	   used by most modern processors.  */
94	pushq	%r11
95	ret
96	cfi_endproc()
97#else
98	cfi_startproc()
99___chkstk:
100__alloca:
101	pushl	%ecx			/* save temp */
102	cfi_push(%eax)
103	leal	8(%esp), %ecx		/* point past return addr */
104	cmpl	$0x1000, %eax		/* > 4k ?*/
105	jb	2f
106
1071:	subl	$0x1000, %ecx  		/* yes, move pointer down 4k*/
108	orl	$0x0, (%ecx)   		/* probe there */
109	subl	$0x1000, %eax  	 	/* decrement count */
110	cmpl	$0x1000, %eax
111	ja	1b			/* and do it again */
112
1132:	subl	%eax, %ecx
114	orl	$0x0, (%ecx)		/* less than 4k, just peek here */
115	movl	%esp, %eax		/* save current stack pointer */
116	cfi_def_cfa_register(%eax)
117	movl	%ecx, %esp		/* decrement stack */
118	movl	(%eax), %ecx		/* recover saved temp */
119
120	/* Copy the return register.  Doing this instead of just jumping to
121	   the address preserves the cached call-return stack used by most
122	   modern processors.  */
123	pushl	4(%eax)
124	ret
125	cfi_endproc()
126#endif /* _WIN64 */
127#endif /* L_chkstk */
128
129#ifdef L_chkstk_ms
130/* ___chkstk_ms is a *special* function call, which uses %rax as the argument.
131   We avoid clobbering any registers.  Unlike ___chkstk, it just probes the
132   stack and does no stack allocation.  */
133	.global ___chkstk_ms
134#ifdef _WIN64
135	cfi_startproc()
136___chkstk_ms:
137	pushq	%rcx			/* save temps */
138	cfi_push(%rcx)
139	pushq	%rax
140	cfi_push(%rax)
141	cmpq	$0x1000, %rax		/* > 4k ?*/
142	leaq	24(%rsp), %rcx		/* point past return addr */
143	jb	2f
144
1451:	subq	$0x1000, %rcx  		/* yes, move pointer down 4k */
146	orq	$0x0, (%rcx)   		/* probe there */
147	subq	$0x1000, %rax  	 	/* decrement count */
148	cmpq	$0x1000, %rax
149	ja	1b			/* and do it again */
150
1512:	subq	%rax, %rcx
152	orq	$0x0, (%rcx)		/* less than 4k, just peek here */
153
154	popq	%rax
155	cfi_pop(%rax)
156	popq	%rcx
157	cfi_pop(%rcx)
158	ret
159	cfi_endproc()
160#else
161	cfi_startproc()
162___chkstk_ms:
163	pushl	%ecx			/* save temp */
164	cfi_push(%ecx)
165	pushl	%eax
166	cfi_push(%eax)
167	cmpl	$0x1000, %eax		/* > 4k ?*/
168	leal	12(%esp), %ecx		/* point past return addr */
169	jb	2f
170
1711:	subl	$0x1000, %ecx  		/* yes, move pointer down 4k*/
172	orl	$0x0, (%ecx)   		/* probe there */
173	subl	$0x1000, %eax  	 	/* decrement count */
174	cmpl	$0x1000, %eax
175	ja	1b			/* and do it again */
176
1772:	subl	%eax, %ecx
178	orl	$0x0, (%ecx)		/* less than 4k, just peek here */
179
180	popl	%eax
181	cfi_pop(%eax)
182	popl	%ecx
183	cfi_pop(%ecx)
184	ret
185	cfi_endproc()
186#endif /* _WIN64 */
187#endif /* L_chkstk_ms */
188