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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
#include "../includes/ghcconfig.h"
/* ******************************** PowerPC ******************************** */
#if defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
#if !(defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS))
/* The following code applies, with some differences,
to all powerpc platforms except for powerpc32-linux,
whose calling convention is annoyingly complex.
*/
/* The code is "almost" the same for
32-bit and for 64-bit
*/
#if defined(powerpc64_HOST_ARCH)
#define WS 8
#define LOAD ld
#define STORE std
#else
#define WS 4
#define LOAD lwz
#define STORE stw
#endif
/* Some info about stack frame layout */
#define LINK_SLOT (2*WS)
#define LINKAGE_AREA_SIZE (6*WS)
/* The following defines mirror struct AdjustorStub
from Adjustor.c. Make sure to keep these in sync.
*/
#define HEADER_WORDS 3
#define HPTR_OFF ((HEADER_WORDS )*WS)
#define WPTR_OFF ((HEADER_WORDS + 1)*WS)
#define FRAMESIZE_OFF ((HEADER_WORDS + 2)*WS)
#define EXTRA_WORDS_OFF ((HEADER_WORDS + 3)*WS)
#if defined(aix_HOST_OS)
/* IBM's assembler needs a different pseudo-op to declare a .text section */
.csect .text[PR]
#else
.text
#endif
#if LEADING_UNDERSCORE
.globl _adjustorCode
_adjustorCode:
#else
.globl adjustorCode
/* Note that we don't build a function descriptor
for AIX-derived ABIs here. This will happen at runtime
in createAdjustor().
*/
adjustorCode:
#endif
/* On entry, r2 will point to the AdjustorStub data structure. */
/* save the link */
mflr 0
STORE 0, LINK_SLOT(1)
/* set up stack frame */
LOAD 12, FRAMESIZE_OFF(2)
#if defined(powerpc64_HOST_ARCH)
stdux 1, 1, 12
#else
stwux 1, 1, 12
#endif
/* Save some regs so that we can use them.
Note that we use the "Red Zone" below the stack pointer.
*/
STORE 31, -WS(1)
STORE 30, -2*WS(1)
mr 31, 1
subf 30, 12, 31
LOAD 12, EXTRA_WORDS_OFF(2)
mtctr 12
b L2
L1:
LOAD 0, LINKAGE_AREA_SIZE + 8*WS(30)
STORE 0, LINKAGE_AREA_SIZE + 10*WS(31)
addi 30, 30, WS
addi 31, 31, WS
L2:
bdnz L1
/* Restore r30 and r31 now.
*/
LOAD 31, -WS(1)
LOAD 30, -2*WS(1)
STORE 10, LINKAGE_AREA_SIZE + 9*WS(1)
STORE 9, LINKAGE_AREA_SIZE + 8*WS(1)
mr 10, 8
mr 9, 7
mr 8, 6
mr 7, 5
mr 6, 4
mr 5, 3
LOAD 3, HPTR_OFF(2)
LOAD 12, WPTR_OFF(2)
LOAD 0, 0(12)
/* The function we're calling will never be a nested function,
so we don't load r11.
*/
mtctr 0
LOAD 2, WS(12)
bctrl
LOAD 1, 0(1)
LOAD 0, LINK_SLOT(1)
mtlr 0
blr
#endif
/* ********************************* i386 ********************************** */
#elif defined(i386_HOST_ARCH)
#define WS 4
#define RETVAL_OFF 5
#define HEADER_BYTES 8
#define HPTR_OFF HEADER_BYTES
#define WPTR_OFF (HEADER_BYTES + 1*WS)
#define FRAMESIZE_OFF (HEADER_BYTES + 2*WS)
#define ARGWORDS_OFF (HEADER_BYTES + 3*WS)
#if defined(LEADING_UNDERSCORE)
.globl _adjustorCode
_adjustorCode:
#else
.globl adjustorCode
adjustorCode:
#endif
popl %eax
subl $RETVAL_OFF, %eax
pushl %ebp
movl %esp, %ebp
subl FRAMESIZE_OFF(%eax), %esp
pushl %esi
pushl %edi
leal 8(%ebp), %esi
leal 12(%esp), %edi
movl ARGWORDS_OFF(%eax), %ecx
rep
movsl
popl %edi
popl %esi
pushl HPTR_OFF(%eax)
call *WPTR_OFF(%eax)
leave
ret
#endif
/* mark stack as nonexecutable */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",@progbits
#endif
|