File: libchkstk.S

package info (click to toggle)
pocl 7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 29,768 kB
  • sloc: lisp: 151,669; ansic: 135,425; cpp: 65,801; python: 1,846; sh: 1,084; ruby: 255; pascal: 231; tcl: 180; makefile: 174; asm: 81; java: 72; xml: 49
file content (93 lines) | stat: -rw-r--r-- 2,968 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#if 0
# From:
# https://github.com/skeeto/w64devkit/blob/master/src/libchkstk.S
#
# because Clang on Windows generates calls to chkstk(), it is
# necessary to provide our implementation when not linking to C library.
# For details, see e.g.
# https://stackoverflow.com/questions/8400118/what-is-the-purpose-of-the-chkstk-function
#
# Implementations of ___chkstk_ms (GCC) and __chkstk (MSVC). Unlike
# libgcc, no work happens if the stack is already committed. Execute
# this source with a shell to build libchkstk.a.
# This is free and unencumbered software released into the public domain.
set -ex
${CC:-cc} -c -DCHKSTK_MS -Wa,--no-pad-sections -o chkstk_ms.o $0
${CC:-cc} -c -DCHKSTK    -Wa,--no-pad-sections -o chkstk.o    $0
rm -f "${DESTDIR}libchkstk.a"
${AR:-ar} r "${DESTDIR}libchkstk.a" chkstk_ms.o chkstk.o
rm chkstk_ms.o chkstk.o
exit 0
#endif

#if __amd64
// On x64, ___chkstk_ms and __chkstk have identical semantics. Unlike
// x86 __chkstk, neither adjusts the stack pointer. This implementation
// preserves all registers.
//
// The frame size is passed in rax, and this function ensures that
// enough of the stack is committed for the frame. It commits stack
// pages by writing to the guard page, one page at a time.
#  if CHKSTK_MS
	.globl ___chkstk_ms
___chkstk_ms:
#  elif CHKSTK
	.globl __chkstk
__chkstk:
#  endif
	push %rax
	push %rcx
	mov  %gs:(0x10), %rcx	// rcx = stack low address
	neg  %rax		// rax = frame low address
	add  %rsp, %rax		// "
	jb   1f			// frame low address overflow?
	xor  %eax, %eax		// overflowed: frame low address = null
0:	sub  $0x1000, %rcx	// extend stack into guard page
	test %eax, (%rcx)	// commit page (two instruction bytes)
1:	cmp  %rax, %rcx
	ja   0b
	pop  %rcx
	pop  %rax
	ret
#endif  // __amd64

#if __i386
#  if CHKSTK_MS
// Behaves exactly like x64 ___chkstk_ms.
	.globl ___chkstk_ms
___chkstk_ms:
	push %eax
	push %ecx
	mov  %fs:(0x08), %ecx	// ecx = stack low address
	neg  %eax		// eax = frame low address
	add  %esp, %eax		// "
	jb   1f			// frame low address overflow?
	xor  %eax, %eax		// overflowed: frame low address = null
0:	sub  $0x1000, %ecx	// extend stack into guard page
	test %eax, (%ecx)	// commit page (two instruction bytes)
1:	cmp  %eax, %ecx
	ja   0b
	pop  %ecx
	pop  %eax
	ret
#  elif CHKSTK
// On x86, __chkstk allocates the new stack frame. This implementation
// clobbers eax. MSVC only seems to care about ebp and ecx (this).
	.globl __chkstk
__chkstk:
	push %ecx		// preserve ecx
	mov  %fs:(0x08), %ecx	// ecx = stack low address
	neg  %eax		// eax = frame low address
	lea  8(%esp,%eax), %eax	// "
	cmp  %esp, %eax		// frame low address overflow?
	jb   1f			// "
	xor  %eax, %eax		// overflowed: frame low address = null
0:	sub  $0x1000, %ecx	// extend stack into guard page
	test %eax, (%ecx)	// commit page (two instruction bytes)
1:	cmp  %eax, %ecx
	ja   0b
	pop  %ecx		// restore ecx
	xchg %eax, %esp		// allocate frame
	jmp  *(%eax)		// return
#  endif
#endif  // __i386