1 | /*␊ |
2 | * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * This file contains Original Code and/or Modifications of Original Code␊ |
7 | * as defined in and that are subject to the Apple Public Source License␊ |
8 | * Version 2.0 (the 'License'). You may not use this file except in␊ |
9 | * compliance with the License. Please obtain a copy of the License at␊ |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this␊ |
11 | * file.␊ |
12 | * ␊ |
13 | * The Original Code and all software distributed under the License are␊ |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.␊ |
18 | * Please see the License for the specific language governing rights and␊ |
19 | * limitations under the License.␊ |
20 | * ␊ |
21 | * @APPLE_LICENSE_HEADER_END@␊ |
22 | */␊ |
23 | ␊ |
24 | #ifndef _PPC_MODE_INDEPENDENT_ASM_H_␊ |
25 | #define _PPC_MODE_INDEPENDENT_ASM_H_␊ |
26 | ␊ |
27 | ␊ |
28 | /* This file facilitates writing mode-independent PPC assembler source, ie␊ |
29 | * source which can be built both for 32-bit mode (__ppc__) and 64-bit ␊ |
30 | * mode (__ppc64__.)␊ |
31 | *␊ |
32 | * It defines constants such as the number of bytes in a GPR (GPR_BYTES),␊ |
33 | * macros to address and call externals (MI_GET_ADDRESS), and a set of mode␊ |
34 | * independent PPC assembler pseudo-mnemonics.␊ |
35 | *␊ |
36 | * The assembler mnemonics map to word operations when building for __ppc__,␊ |
37 | * and to doubleword operations when building for __ppc64__. They use "g" to␊ |
38 | * stand for either word or doubleword, depending on the target mode. ␊ |
39 | *␊ |
40 | * Although there are certainly other things to be aware of when writing code␊ |
41 | * targeted at both 32 and 64-bit mode, using these macros and psuedo-mnemonics␊ |
42 | * is surprisingly helpful.␊ |
43 | */␊ |
44 | ␊ |
45 | #if defined(__ppc64__)␊ |
46 | #define MODE_CHOICE(x, y) y␊ |
47 | #elif defined(__ppc__)␊ |
48 | #define MODE_CHOICE(x, y) x␊ |
49 | #else␊ |
50 | #error undefined architecture␊ |
51 | #endif␊ |
52 | ␊ |
53 | ␊ |
54 | /* The mode-independent "g" mnemonics. */␊ |
55 | ␊ |
56 | #define cmpg MODE_CHOICE(cmpw, cmpd)␊ |
57 | #define cmplg MODE_CHOICE(cmplw, cmpld)␊ |
58 | #define cmpgi MODE_CHOICE(cmpwi, cmpdi)␊ |
59 | #define cmplgi MODE_CHOICE(cmplwi, cmpldi)␊ |
60 | #define srgi MODE_CHOICE(srwi, srdi)␊ |
61 | #define srg MODE_CHOICE(srw, srd)␊ |
62 | #define sragi MODE_CHOICE(srawi, sradi)␊ |
63 | #define slgi MODE_CHOICE(slwi, sldi)␊ |
64 | #define rotlgi MODE_CHOICE(rotlwi, rotldi)␊ |
65 | #define clrrgi MODE_CHOICE(clrrwi, clrrdi)␊ |
66 | #define cntlzg MODE_CHOICE(cntlzw, cntlzd)␊ |
67 | #define lg MODE_CHOICE(lwz, ld)␊ |
68 | #define stg MODE_CHOICE(stw, std)␊ |
69 | #define lgx MODE_CHOICE(lwzx, ldx)␊ |
70 | #define stgx MODE_CHOICE(stwx, stdx)␊ |
71 | #define lgu MODE_CHOICE(lwzu, ldu)␊ |
72 | #define stgu MODE_CHOICE(stwu, stdu)␊ |
73 | #define lgux MODE_CHOICE(lwzux, ldux)␊ |
74 | #define stgux MODE_CHOICE(stwux, stdux)␊ |
75 | #define lgwa MODE_CHOICE(lwz, lwa)␊ |
76 | ␊ |
77 | #define g_long MODE_CHOICE(long, quad) // usage is ".g_long"␊ |
78 | ␊ |
79 | ␊ |
80 | /* Architectural constants. */␊ |
81 | ␊ |
82 | #define GPR_BYTES MODE_CHOICE(4,8) // size of a GPR in bytes␊ |
83 | #define LOG2_GPR_BYTES MODE_CHOICE(2,3) // log2(GPR_BYTES)␊ |
84 | ␊ |
85 | ␊ |
86 | /* Stack frame definitions. To keep things simple, we are limited␊ |
87 | * to eight arguments and two locals.␊ |
88 | */␊ |
89 | #define SF_CRSAVE MODE_CHOICE(4,8)␊ |
90 | #define SF_RETURN MODE_CHOICE(8,16)␊ |
91 | #define SF_ARG1 MODE_CHOICE(24,48)␊ |
92 | #define SF_ARG2 MODE_CHOICE(28,56)␊ |
93 | #define SF_ARG3 MODE_CHOICE(32,64)␊ |
94 | #define SF_ARG4 MODE_CHOICE(36,72)␊ |
95 | #define SF_ARG5 MODE_CHOICE(40,80)␊ |
96 | #define SF_ARG6 MODE_CHOICE(44,88)␊ |
97 | #define SF_ARG7 MODE_CHOICE(48,96)␊ |
98 | #define SF_ARG8 MODE_CHOICE(52,104)␊ |
99 | #define SF_LOCAL1 MODE_CHOICE(56,112)␊ |
100 | #define SF_LOCAL2 MODE_CHOICE(60,120)␊ |
101 | #define SF_SIZE MODE_CHOICE(64,128)␊ |
102 | ␊ |
103 | #define SF_ALIGNMENT MODE_CHOICE(16,32)␊ |
104 | #define SF_REDZONE MODE_CHOICE(224,320)␊ |
105 | ␊ |
106 | #define SF_ROUND(x) (((x)+SF_ALIGNMENT-1)&(-SF_ALIGNMENT))␊ |
107 | ␊ |
108 | #define SF_MINSIZE MODE_CHOICE(64,128)␊ |
109 | ␊ |
110 | ␊ |
111 | /* WARNING: some clients fall through this macro, so do not attempt␊ |
112 | * to optimize by doing an ".align 5" in the macro. Do the 32-byte␊ |
113 | * alignment in the .s file, before invoking the macro.␊ |
114 | */␊ |
115 | #define MI_ENTRY_POINT(name) \␊ |
116 | .globl name @\␊ |
117 | .text @\␊ |
118 | .align 2 @\␊ |
119 | name:␊ |
120 | ␊ |
121 | #define MI_PUSH_STACK_FRAME \␊ |
122 | mflr r0 @\␊ |
123 | stg r0,SF_RETURN(r1) @\␊ |
124 | stgu r1,-SF_SIZE(r1)␊ |
125 | ␊ |
126 | #define MI_POP_STACK_FRAME_AND_RETURN \␊ |
127 | lg r0,SF_RETURN+SF_SIZE(r1) @\␊ |
128 | addi r1,r1,SF_SIZE @\␊ |
129 | mtlr r0 @\␊ |
130 | blr␊ |
131 | ␊ |
132 | ␊ |
133 | /* MI_GET_ADDRESS(reg,var) is the basic primitive to address data or code.␊ |
134 | * It works both in 32 and 64-bit mode, and with static and dynamic␊ |
135 | * code generation. Note however that it can be invoked at most once per␊ |
136 | * symbol, since it always creates a non_lazy_ptr in dynamic mode.␊ |
137 | * Save the address for re-use, rather than invoking the macro again.␊ |
138 | */␊ |
139 | #if defined(__DYNAMIC__)␊ |
140 | #define MI_GET_ADDRESS(reg,var) \␊ |
141 | mflr r0 @\␊ |
142 | bcl 20,31,1f @\␊ |
143 | 1: mflr reg @\␊ |
144 | mtlr r0 @\␊ |
145 | addis reg,reg,ha16(L ## var ## __non_lazy_ptr - 1b) @\␊ |
146 | lg reg,lo16(L ## var ## __non_lazy_ptr - 1b)(reg) @\␊ |
147 | .non_lazy_symbol_pointer @\␊ |
148 | .align LOG2_GPR_BYTES @\␊ |
149 | .indirect_symbol var @\␊ |
150 | L ## var ## __non_lazy_ptr: @\␊ |
151 | .g_long 0 @\␊ |
152 | .text @\␊ |
153 | .align 2␊ |
154 | #else /* ! __DYNAMIC__ */␊ |
155 | #define MI_GET_ADDRESS(reg,var) \␊ |
156 | lis reg,hi16(var) @\␊ |
157 | ori reg,reg,lo16(var)␊ |
158 | #endif␊ |
159 | ␊ |
160 | ␊ |
161 | /* MI_CALL_EXTERNAL(var) */␊ |
162 | ␊ |
163 | #if defined(__DYNAMIC__)␊ |
164 | #define MI_CALL_EXTERNAL(var) \␊ |
165 | MI_GET_ADDRESS(r12,var) @\␊ |
166 | mtctr r12 @\␊ |
167 | bctrl␊ |
168 | #else /* ! __DYNAMIC__ */␊ |
169 | #define MI_CALL_EXTERNAL(var) \␊ |
170 | bl var␊ |
171 | #endif␊ |
172 | ␊ |
173 | ␊ |
174 | /* MI_BRANCH_EXTERNAL(var) */␊ |
175 | ␊ |
176 | #if defined(__DYNAMIC__)␊ |
177 | #define MI_BRANCH_EXTERNAL(var) \␊ |
178 | MI_GET_ADDRESS(r12,var) @\␊ |
179 | mtctr r12 @\␊ |
180 | bctr␊ |
181 | #else /* ! __DYNAMIC__ */␊ |
182 | #define MI_BRANCH_EXTERNAL(var) \␊ |
183 | b var␊ |
184 | #endif␊ |
185 | ␊ |
186 | ␊ |
187 | #endif /* _PPC_MODE_INDEPENDENT_ASM_H_ */␊ |
188 | |