-
Notifications
You must be signed in to change notification settings - Fork 71
/
sqCogStackAlignment.h
144 lines (138 loc) · 5.73 KB
/
sqCogStackAlignment.h
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/****************************************************************************
* FILE: sqCogUnixStackAlignment.h
* CONTENT: Answer & check stack alignment for current plaform
*
* AUTHOR: Eliot Miranda
* DATE: February 2009
*
* Changes: eem Tue 28 Apr 2015 Add ARM32 support.
* eem Wed Jul 14 2010 make 16 bytes the default alignment for all x86.
*/
#if __i386__ || _M_IX86
# if __SSE2__ || (__APPLE__ && __MACH__) || __linux__ || _M_IX86_FP==2
/* 16-byte stack alignment on x86 is required for SSE instructions which
* require 16-byte aligned addresses to access 64 or 128 bit values in memory.
*/
# define STACK_ALIGN_BYTES 16
# define STACK_FP_ALIGNMENT 8 /* aligned sp - retpc - saved fp */
# else
# define STACK_ALIGN_BYTES 4
# define STACK_FP_ALIGNMENT 0
# endif
#endif
#if defined(__arm64__) || defined(__aarch64__) || defined(ARM64)
/* Quad-byte stack alignment on ARM64 is required.
(SP mod 16) == 0
*/
# define STACK_ALIGN_BYTES 16
# define STACK_FP_ALIGNMENT 8
#elif defined(__arm__) || defined(__arm32__) || defined(ARM32)
/* 8-byte stack alignment on ARM32 is required for instructions which
* require 8-byte aligned addresses to access doubles in memory.
*/
# define STACK_ALIGN_BYTES 8
# define STACK_FP_ALIGNMENT 4
#endif
#if defined(x86_64) || defined(__amd64) || defined(__x86_64) || defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_IA64)
/* From the System V ABI:
* 3.2.2 The Stack Frame
* ... The end of the input argument area shall be aligned on a 16 (32, if
* __m256 is passed on stack) byte boundary. In other words, the value
* (%rsp + 8) is always a multiple of 16 (32) when control is transferred to
* the function entry point.
* However,
* https://developer.apple.com/library/mac/documentation/DeveloperTools/
* Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html
* claims
* "The OS X x86-64 function calling conventions are the same as the function
* calling conventions described in System V Application Binary Interface AMD64
* Architecture Processor Supplement, found at
* http://people.freebsd.org/~obrien/amd64-elf-abi.pdf. See that document for
* details."
* and that document states:
* "The end of the input argument area shall be aligned on a 16 byte boundary.
* In other words, the value (%rsp ? 8) is always a multiple of 16 when control
* is transferred to the function entry point. The stack pointer, %rsp, always
* points to the end of the latest allocated stack frame."
*/
# if __APPLE__ && __MACH__ && 0/* i.e. the __m256 regime */
# define STACK_ALIGN_BYTES 32
# define STACK_FP_ALIGNMENT 16 /* aligned sp - retpc - saved fp */
# else
# define STACK_ALIGN_BYTES 16
# define STACK_FP_ALIGNMENT 0 /* aligned sp - retpc - saved fp */
# endif
#endif
#if defined(STACK_ALIGN_BYTES)
# if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)
# if __GNUC__ || __clang__
# define getfp() ({ register usqIntptr_t fp; \
asm volatile ("movl %%ebp,%0" : "=r"(fp) : ); \
fp; })
# define getsp() ({ register usqIntptr_t sp; \
asm volatile ("movl %%esp,%0" : "=r"(sp) : ); \
sp; })
# endif
# elif defined(__arm64__) || defined(__aarch64__) || defined(ARM64)
/* https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/index.html
*/
# if __GNUC__
# define getfp() ({ usqIntptr_t fp; \
asm volatile ("mov x0, x29" : "=r"(fp) : ); \
fp; })
# define getsp() ({ usqIntptr_t sp; \
asm volatile ("mov x0, sp" : "=r"(sp) : ); \
sp; })
# define setsp(sp) asm volatile ("ldr x16, %0 \n\t" "mov sp, x16" : : "m"(sp) )
# endif
# elif defined(__arm__) || defined(__arm32__) || defined(ARM32)
/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0041c/Cegbidie.html
* ARM DUI 0041C Page 9-7
*/
# if __GNUC__
# define getfp() ({ usqIntptr_t fp; \
asm volatile ("mov %0, %%fp" : "=r"(fp) : ); \
fp; })
# define getsp() ({ usqIntptr_t sp; \
asm volatile ("mov %0, %%sp" : "=r"(sp) : ); \
sp; })
# endif
# elif defined(x86_64) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(x64) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_IA64)
# if __GNUC__ || __clang__
# define getfp() ({ register usqIntptr_t fp; \
asm volatile ("movq %%rbp,%0" : "=r"(fp) : ); \
fp; })
# define getsp() ({ register usqIntptr_t sp; \
asm volatile ("movq %%rsp,%0" : "=r"(sp) : ); \
sp; })
# else /* MSVC for example: use ceGetFP ceGetSP */
# endif
# else /* !(__i386__ || __arm__ || __x86_64__) */
# error define code for your processor here
# endif
# if !defined(getfp)
# define getfp() ceGetFP() /* provided by Cogit */
# endif
# if !defined(getsp)
# define getsp() ceGetSP() /* provided by Cogit */
# endif
# define STACK_ALIGN_MASK (STACK_ALIGN_BYTES-1)
# define assertCStackWellAligned() do { \
extern sqInt cFramePointerInUse; \
if (cFramePointerInUse) \
assert((getfp() & STACK_ALIGN_MASK) == STACK_FP_ALIGNMENT); \
assert((getsp() & STACK_ALIGN_MASK) == 0); \
} while (0)
#else /* defined(STACK_ALIGN_BYTES) */
# if defined(powerpc) || defined(__powerpc__) || defined(_POWER) || defined(__POWERPC__) || defined(__PPC__)
# define STACK_ALIGN_BYTES 16
# elif defined(__sparc64__) || defined(__sparcv9__) || defined(__sparc_v9__) /* must precede 32-bit sparc defs */
# define STACK_ALIGN_BYTES 16
# elif defined(sparc) || defined(__sparc__) || defined(__sparclite__)
# define STACK_ALIGN_BYTES 8
# else
# define STACK_ALIGN_BYTES sizeof(void *)
# endif
# define assertCStackWellAligned() 0
#endif /* defined(STACK_ALIGN_BYTES) */