[project @ 2005-01-28 12:55:17 by simonmar]
[ghc-hetmet.git] / ghc / rts / AdjustorAsm.S
1 #include "../includes/ghcconfig.h"
2
3 #if defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
4 #if !(defined(powerpc_HOST_ARCH) && defined(linux_HOST_OS))
5     /* The following code applies, with some differences,
6        to all powerpc platforms except for powerpc32-linux,
7        whose calling convention is annoyingly complex.
8     */
9
10
11     /* The code is "almost" the same for
12        32-bit and for 64-bit
13     */
14 #if defined(powerpc64_HOST_ARCH)
15 #define WS          8
16 #define LOAD        ld
17 #define STORE       std
18 #else
19 #define WS          4
20 #define LOAD        lwz
21 #define STORE       stw
22 #endif
23
24     /* Some info about stack frame layout */
25 #define LINK_SLOT           (2*WS)
26 #define LINKAGE_AREA_SIZE   (6*WS)
27
28     /* The following defines mirror struct AdjustorStub
29        from Adjustor.c. Make sure to keep these in sync.
30     */
31 #if defined(powerpc_HOST_ARCH) && defined(darwin_HOST_OS)
32 #define HEADER_WORDS   6
33 #elif defined(powerpc64_HOST_ARCH) && defined(darwin_HOST_OS)
34 #else
35 #define HEADER_WORDS   3
36 #endif
37
38 #define HPTR_OFF        ((HEADER_WORDS    )*WS)
39 #define WPTR_OFF        ((HEADER_WORDS + 1)*WS)
40 #define FRAMESIZE_OFF   ((HEADER_WORDS + 2)*WS)
41 #define EXTRA_WORDS_OFF ((HEADER_WORDS + 3)*WS)
42
43     /* Darwin insists on register names, everyone else prefers
44        to use numbers. */
45 #if !defined(darwin_HOST_OS)
46 #define r0 0
47 #define r1 1
48 #define r2 2
49 #define r3 3
50 #define r4 4
51 #define r5 5
52 #define r6 6
53 #define r7 7
54 #define r8 8
55 #define r9 9
56 #define r10 10
57 #define r11 11
58 #define r12 12
59
60 #define r30 30
61 #define r31 31
62 #endif
63
64
65 .text
66 #if LEADING_UNDERSCORE
67     .globl _adjustorCode
68 _adjustorCode:
69 #else
70     .globl adjustorCode
71         /* Note that we don't build a function descriptor
72            for AIX-derived ABIs here. This will happen at runtime
73            in createAdjustor().
74         */
75 adjustorCode:
76 #endif
77     /* On entry, r2 will point to the AdjustorStub data structure. */
78
79         /* save the link */
80     mflr    r0
81     STORE   r0, LINK_SLOT(r1)
82     
83         /* set up stack frame */
84     LOAD    r12, FRAMESIZE_OFF(r2)
85 #ifdef powerpc64_HOST_ARCH
86     stdux   r1, r1, r12
87 #else   
88     stwux   r1, r1, r12
89 #endif
90
91         /* Save some regs so that we can use them.
92            Note that we use the "Red Zone" below the stack pointer.
93         */
94     STORE   r31, -WS(r1)
95     STORE   r30, -2*WS(r1)
96
97     mr      r31, r1
98     subf    r30, r12, r31
99
100     LOAD    r12, EXTRA_WORDS_OFF(r2)
101     mtctr   r12
102     b       2f
103 1:
104     LOAD    r0, LINKAGE_AREA_SIZE +  8*WS(r30)
105     STORE   r0, LINKAGE_AREA_SIZE + 10*WS(r31)
106     addi    r30, r30, WS
107     addi    r31, r31, WS
108 2:
109     bdnz    1b
110
111         /* Restore r30 and r31 now.
112         */
113     LOAD    r31, -WS(r1)
114     LOAD    r30, -2*WS(r1)
115
116     STORE   r10, LINKAGE_AREA_SIZE + 9*WS(r1)
117     STORE   r9,  LINKAGE_AREA_SIZE + 8*WS(r1)
118     mr      r10, r8
119     mr      r9, r7
120     mr      r8, r6
121     mr      r7, r5
122     mr      r6, r4
123     mr      r5, r3
124
125     LOAD    r3, HPTR_OFF(r2)
126
127     LOAD    r12, WPTR_OFF(r2)
128 #if defined(darwin_HOST_OS)
129     mtctr   r12
130 #else
131     LOAD    r0, 0(r12)
132         /* The function we're calling will never be a nested function,
133            so we don't load r11. 
134         */
135     mtctr   r0
136     LOAD    r2, WS(r12)
137 #endif
138     bctrl
139
140     LOAD    r1, 0(r1)
141     LOAD    r0, LINK_SLOT(r1)
142     mtlr    r0
143     blr
144 #endif
145 #endif
146