1713acb315e089caeebd618841a119b0fc165ad4
[ghc.git] / rts / AdjustorAsm.S
1 #include "../includes/ghcconfig.h"
2
3 /* ******************************** PowerPC ******************************** */
4
5 #if defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
6 #if !(defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS))
7     /* The following code applies, with some differences,
8        to all powerpc platforms except for powerpc32-linux,
9        whose calling convention is annoyingly complex.
10     */
11
12
13     /* The code is "almost" the same for
14        32-bit and for 64-bit
15     */
16 #if defined(powerpc64_HOST_ARCH)
17 #define WS          8
18 #define LOAD        ld
19 #define STORE       std
20 #else
21 #define WS          4
22 #define LOAD        lwz
23 #define STORE       stw
24 #endif
25
26     /* Some info about stack frame layout */
27 #define LINK_SLOT           (2*WS)
28 #define LINKAGE_AREA_SIZE   (6*WS)
29
30     /* The following defines mirror struct AdjustorStub
31        from Adjustor.c. Make sure to keep these in sync.
32     */
33 #if defined(powerpc_HOST_ARCH) && defined(darwin_HOST_OS)
34 #define HEADER_WORDS   6
35 #elif defined(powerpc64_HOST_ARCH) && defined(darwin_HOST_OS)
36 #else
37 #define HEADER_WORDS   3
38 #endif
39
40 #define HPTR_OFF        ((HEADER_WORDS    )*WS)
41 #define WPTR_OFF        ((HEADER_WORDS + 1)*WS)
42 #define FRAMESIZE_OFF   ((HEADER_WORDS + 2)*WS)
43 #define EXTRA_WORDS_OFF ((HEADER_WORDS + 3)*WS)
44
45     /* Darwin insists on register names, everyone else prefers
46        to use numbers. */
47 #if !defined(darwin_HOST_OS)
48 #define r0 0
49 #define r1 1
50 #define r2 2
51 #define r3 3
52 #define r4 4
53 #define r5 5
54 #define r6 6
55 #define r7 7
56 #define r8 8
57 #define r9 9
58 #define r10 10
59 #define r11 11
60 #define r12 12
61
62 #define r30 30
63 #define r31 31
64 #endif
65
66 #if defined(aix_HOST_OS)
67 /* IBM's assembler needs a different pseudo-op to declare a .text section */
68 .csect .text[PR]
69 #else
70 .text
71 #endif
72 #if LEADING_UNDERSCORE
73     .globl _adjustorCode
74 _adjustorCode:
75 #else
76     .globl adjustorCode
77         /* Note that we don't build a function descriptor
78            for AIX-derived ABIs here. This will happen at runtime
79            in createAdjustor().
80         */
81 adjustorCode:
82 #endif
83     /* On entry, r2 will point to the AdjustorStub data structure. */
84
85         /* save the link */
86     mflr    r0
87     STORE   r0, LINK_SLOT(r1)
88     
89         /* set up stack frame */
90     LOAD    r12, FRAMESIZE_OFF(r2)
91 #ifdef powerpc64_HOST_ARCH
92     stdux   r1, r1, r12
93 #else   
94     stwux   r1, r1, r12
95 #endif
96
97         /* Save some regs so that we can use them.
98            Note that we use the "Red Zone" below the stack pointer.
99         */
100     STORE   r31, -WS(r1)
101     STORE   r30, -2*WS(r1)
102
103     mr      r31, r1
104     subf    r30, r12, r31
105
106     LOAD    r12, EXTRA_WORDS_OFF(r2)
107     mtctr   r12
108     b       L2
109 L1:
110     LOAD    r0, LINKAGE_AREA_SIZE +  8*WS(r30)
111     STORE   r0, LINKAGE_AREA_SIZE + 10*WS(r31)
112     addi    r30, r30, WS
113     addi    r31, r31, WS
114 L2:
115     bdnz    L1
116
117         /* Restore r30 and r31 now.
118         */
119     LOAD    r31, -WS(r1)
120     LOAD    r30, -2*WS(r1)
121
122     STORE   r10, LINKAGE_AREA_SIZE + 9*WS(r1)
123     STORE   r9,  LINKAGE_AREA_SIZE + 8*WS(r1)
124     mr      r10, r8
125     mr      r9, r7
126     mr      r8, r6
127     mr      r7, r5
128     mr      r6, r4
129     mr      r5, r3
130
131     LOAD    r3, HPTR_OFF(r2)
132
133     LOAD    r12, WPTR_OFF(r2)
134 #if defined(darwin_HOST_OS)
135     mtctr   r12
136 #else
137     LOAD    r0, 0(r12)
138         /* The function we're calling will never be a nested function,
139            so we don't load r11. 
140         */
141     mtctr   r0
142     LOAD    r2, WS(r12)
143 #endif
144     bctrl
145
146     LOAD    r1, 0(r1)
147     LOAD    r0, LINK_SLOT(r1)
148     mtlr    r0
149     blr
150 #endif
151
152 /* ********************************* i386 ********************************** */
153
154 #elif defined(i386_HOST_ARCH)
155
156 #define WS              4
157 #define RETVAL_OFF      5
158 #define HEADER_BYTES    8
159
160 #define HPTR_OFF        HEADER_BYTES
161 #define WPTR_OFF        (HEADER_BYTES + 1*WS)
162 #define FRAMESIZE_OFF   (HEADER_BYTES + 2*WS)
163 #define ARGWORDS_OFF    (HEADER_BYTES + 3*WS)
164
165 #ifdef LEADING_UNDERSCORE
166     .globl _adjustorCode
167 _adjustorCode:
168 #else
169     .globl adjustorCode
170 adjustorCode:
171 #endif
172     popl    %eax
173     subl    $RETVAL_OFF, %eax
174     
175     pushl   %ebp
176     movl    %esp, %ebp
177     
178     subl    FRAMESIZE_OFF(%eax), %esp
179
180     pushl   %esi
181     pushl   %edi
182         
183     leal    8(%ebp), %esi
184     leal    12(%esp), %edi
185     movl    ARGWORDS_OFF(%eax), %ecx
186     rep
187     movsl
188     
189     popl    %edi
190     popl    %esi
191     
192     pushl   HPTR_OFF(%eax)
193     call    *WPTR_OFF(%eax)
194     
195     leave
196     ret
197 #endif
198
199 /* mark stack as nonexecutable */
200 #if defined(__linux__) && defined(__ELF__)
201 .section .note.GNU-stack,"",@progbits
202 #endif