]>
Commit | Line | Data |
---|---|---|
14957cd0 A |
1 | /* |
2 | * Copyright (C) 2011 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #ifndef DFGFPRInfo_h | |
27 | #define DFGFPRInfo_h | |
28 | ||
29 | #if ENABLE(DFG_JIT) | |
30 | ||
93a37866 A |
31 | #include "DFGRegisterBank.h" |
32 | #include "MacroAssembler.h" | |
14957cd0 A |
33 | |
34 | namespace JSC { namespace DFG { | |
35 | ||
36 | typedef MacroAssembler::FPRegisterID FPRReg; | |
37 | #define InvalidFPRReg ((FPRReg)-1) | |
38 | ||
6fe7ccc8 A |
39 | #if CPU(X86) || CPU(X86_64) |
40 | ||
14957cd0 A |
41 | class FPRInfo { |
42 | public: | |
43 | typedef FPRReg RegisterType; | |
44 | static const unsigned numberOfRegisters = 6; | |
45 | ||
46 | // Temporary registers. | |
47 | static const FPRReg fpRegT0 = X86Registers::xmm0; | |
48 | static const FPRReg fpRegT1 = X86Registers::xmm1; | |
49 | static const FPRReg fpRegT2 = X86Registers::xmm2; | |
50 | static const FPRReg fpRegT3 = X86Registers::xmm3; | |
51 | static const FPRReg fpRegT4 = X86Registers::xmm4; | |
52 | static const FPRReg fpRegT5 = X86Registers::xmm5; | |
6fe7ccc8 A |
53 | #if CPU(X86_64) |
54 | // Only X86_64 passes aguments in xmm registers | |
14957cd0 A |
55 | static const FPRReg argumentFPR0 = X86Registers::xmm0; // fpRegT0 |
56 | static const FPRReg argumentFPR1 = X86Registers::xmm1; // fpRegT1 | |
57 | static const FPRReg argumentFPR2 = X86Registers::xmm2; // fpRegT2 | |
58 | static const FPRReg argumentFPR3 = X86Registers::xmm3; // fpRegT3 | |
6fe7ccc8 A |
59 | #endif |
60 | // On X86 the return will actually be on the x87 stack, | |
61 | // so we'll copy to xmm0 for sanity! | |
14957cd0 A |
62 | static const FPRReg returnValueFPR = X86Registers::xmm0; // fpRegT0 |
63 | ||
64 | // FPRReg mapping is direct, the machine regsiter numbers can | |
65 | // be used directly as indices into the FPR RegisterBank. | |
66 | COMPILE_ASSERT(X86Registers::xmm0 == 0, xmm0_is_0); | |
67 | COMPILE_ASSERT(X86Registers::xmm1 == 1, xmm1_is_1); | |
68 | COMPILE_ASSERT(X86Registers::xmm2 == 2, xmm2_is_2); | |
69 | COMPILE_ASSERT(X86Registers::xmm3 == 3, xmm3_is_3); | |
70 | COMPILE_ASSERT(X86Registers::xmm4 == 4, xmm4_is_4); | |
71 | COMPILE_ASSERT(X86Registers::xmm5 == 5, xmm5_is_5); | |
72 | static FPRReg toRegister(unsigned index) | |
73 | { | |
74 | return (FPRReg)index; | |
75 | } | |
76 | static unsigned toIndex(FPRReg reg) | |
77 | { | |
78 | return (unsigned)reg; | |
79 | } | |
80 | ||
14957cd0 A |
81 | static const char* debugName(FPRReg reg) |
82 | { | |
83 | ASSERT(reg != InvalidFPRReg); | |
6fe7ccc8 | 84 | #if CPU(X86_64) |
93a37866 | 85 | ASSERT(static_cast<int>(reg) < 16); |
14957cd0 A |
86 | static const char* nameForRegister[16] = { |
87 | "xmm0", "xmm1", "xmm2", "xmm3", | |
88 | "xmm4", "xmm5", "xmm6", "xmm7", | |
89 | "xmm8", "xmm9", "xmm10", "xmm11", | |
90 | "xmm12", "xmm13", "xmm14", "xmm15" | |
91 | }; | |
6fe7ccc8 | 92 | #elif CPU(X86) |
93a37866 | 93 | ASSERT(static_cast<int>(reg) < 8); |
6fe7ccc8 A |
94 | static const char* nameForRegister[8] = { |
95 | "xmm0", "xmm1", "xmm2", "xmm3", | |
96 | "xmm4", "xmm5", "xmm6", "xmm7" | |
97 | }; | |
98 | #endif | |
14957cd0 A |
99 | return nameForRegister[reg]; |
100 | } | |
6fe7ccc8 A |
101 | }; |
102 | ||
14957cd0 | 103 | #endif |
6fe7ccc8 | 104 | |
93a37866 | 105 | #if CPU(ARM) |
6fe7ccc8 A |
106 | |
107 | class FPRInfo { | |
108 | public: | |
109 | typedef FPRReg RegisterType; | |
110 | static const unsigned numberOfRegisters = 6; | |
111 | ||
112 | // Temporary registers. | |
113 | // d7 is use by the MacroAssembler as fpTempRegister. | |
114 | static const FPRReg fpRegT0 = ARMRegisters::d0; | |
115 | static const FPRReg fpRegT1 = ARMRegisters::d1; | |
116 | static const FPRReg fpRegT2 = ARMRegisters::d2; | |
117 | static const FPRReg fpRegT3 = ARMRegisters::d3; | |
118 | static const FPRReg fpRegT4 = ARMRegisters::d4; | |
119 | static const FPRReg fpRegT5 = ARMRegisters::d5; | |
120 | // ARMv7 doesn't pass arguments in fp registers. The return | |
121 | // value is also actually in integer registers, for now | |
122 | // we'll return in d0 for simplicity. | |
123 | static const FPRReg returnValueFPR = ARMRegisters::d0; // fpRegT0 | |
124 | ||
93a37866 A |
125 | #if CPU(ARM_HARDFP) |
126 | static const FPRReg argumentFPR0 = ARMRegisters::d0; // fpRegT0 | |
127 | static const FPRReg argumentFPR1 = ARMRegisters::d1; // fpRegT1 | |
128 | #endif | |
129 | ||
6fe7ccc8 A |
130 | // FPRReg mapping is direct, the machine regsiter numbers can |
131 | // be used directly as indices into the FPR RegisterBank. | |
132 | COMPILE_ASSERT(ARMRegisters::d0 == 0, d0_is_0); | |
133 | COMPILE_ASSERT(ARMRegisters::d1 == 1, d1_is_1); | |
134 | COMPILE_ASSERT(ARMRegisters::d2 == 2, d2_is_2); | |
135 | COMPILE_ASSERT(ARMRegisters::d3 == 3, d3_is_3); | |
136 | COMPILE_ASSERT(ARMRegisters::d4 == 4, d4_is_4); | |
137 | COMPILE_ASSERT(ARMRegisters::d5 == 5, d5_is_5); | |
138 | static FPRReg toRegister(unsigned index) | |
139 | { | |
140 | return (FPRReg)index; | |
141 | } | |
142 | static unsigned toIndex(FPRReg reg) | |
143 | { | |
144 | return (unsigned)reg; | |
145 | } | |
146 | ||
147 | static const char* debugName(FPRReg reg) | |
148 | { | |
149 | ASSERT(reg != InvalidFPRReg); | |
93a37866 | 150 | ASSERT(static_cast<int>(reg) < 32); |
6fe7ccc8 A |
151 | static const char* nameForRegister[32] = { |
152 | "d0", "d1", "d2", "d3", | |
153 | "d4", "d5", "d6", "d7", | |
154 | "d8", "d9", "d10", "d11", | |
93a37866 A |
155 | "d12", "d13", "d14", "d15", |
156 | "d16", "d17", "d18", "d19", | |
157 | "d20", "d21", "d22", "d23", | |
158 | "d24", "d25", "d26", "d27", | |
6fe7ccc8 A |
159 | "d28", "d29", "d30", "d31" |
160 | }; | |
161 | return nameForRegister[reg]; | |
162 | } | |
14957cd0 A |
163 | }; |
164 | ||
6fe7ccc8 A |
165 | #endif |
166 | ||
93a37866 A |
167 | #if CPU(ARM64) |
168 | ||
169 | class FPRInfo { | |
170 | public: | |
171 | typedef FPRReg RegisterType; | |
172 | static const unsigned numberOfRegisters = 23; | |
173 | ||
174 | // Temporary registers. | |
175 | // q8-q15 are callee saved, q31 is use by the MacroAssembler as fpTempRegister. | |
176 | static const FPRReg fpRegT0 = ARM64Registers::q0; | |
177 | static const FPRReg fpRegT1 = ARM64Registers::q1; | |
178 | static const FPRReg fpRegT2 = ARM64Registers::q2; | |
179 | static const FPRReg fpRegT3 = ARM64Registers::q3; | |
180 | static const FPRReg fpRegT4 = ARM64Registers::q4; | |
181 | static const FPRReg fpRegT5 = ARM64Registers::q5; | |
182 | static const FPRReg fpRegT6 = ARM64Registers::q6; | |
183 | static const FPRReg fpRegT7 = ARM64Registers::q7; | |
184 | static const FPRReg fpRegT8 = ARM64Registers::q16; | |
185 | static const FPRReg fpRegT9 = ARM64Registers::q17; | |
186 | static const FPRReg fpRegT10 = ARM64Registers::q18; | |
187 | static const FPRReg fpRegT11 = ARM64Registers::q19; | |
188 | static const FPRReg fpRegT12 = ARM64Registers::q20; | |
189 | static const FPRReg fpRegT13 = ARM64Registers::q21; | |
190 | static const FPRReg fpRegT14 = ARM64Registers::q22; | |
191 | static const FPRReg fpRegT15 = ARM64Registers::q23; | |
192 | static const FPRReg fpRegT16 = ARM64Registers::q24; | |
193 | static const FPRReg fpRegT17 = ARM64Registers::q25; | |
194 | static const FPRReg fpRegT18 = ARM64Registers::q26; | |
195 | static const FPRReg fpRegT19 = ARM64Registers::q27; | |
196 | static const FPRReg fpRegT20 = ARM64Registers::q28; | |
197 | static const FPRReg fpRegT21 = ARM64Registers::q29; | |
198 | static const FPRReg fpRegT22 = ARM64Registers::q30; | |
199 | ||
200 | static const FPRReg argumentFPR0 = ARM64Registers::q0; // fpRegT0 | |
201 | static const FPRReg argumentFPR1 = ARM64Registers::q1; // fpRegT1 | |
202 | static const FPRReg argumentFPR2 = ARM64Registers::q2; // fpRegT2 | |
203 | static const FPRReg argumentFPR3 = ARM64Registers::q3; // fpRegT3 | |
204 | static const FPRReg argumentFPR4 = ARM64Registers::q4; // fpRegT4 | |
205 | static const FPRReg argumentFPR5 = ARM64Registers::q5; // fpRegT5 | |
206 | static const FPRReg argumentFPR6 = ARM64Registers::q6; // fpRegT6 | |
207 | static const FPRReg argumentFPR7 = ARM64Registers::q7; // fpRegT7 | |
208 | ||
209 | static const FPRReg returnValueFPR = ARM64Registers::q0; // fpRegT0 | |
210 | ||
211 | static FPRReg toRegister(unsigned index) | |
212 | { | |
213 | ASSERT(index < numberOfRegisters); | |
214 | static const FPRReg registerForIndex[numberOfRegisters] = { | |
215 | fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5, fpRegT6, fpRegT7, | |
216 | fpRegT8, fpRegT9, fpRegT10, fpRegT11, fpRegT12, fpRegT13, fpRegT14, fpRegT15, | |
217 | fpRegT16, fpRegT17, fpRegT18, fpRegT19, fpRegT20, fpRegT21, fpRegT22 | |
218 | }; | |
219 | return registerForIndex[index]; | |
220 | } | |
221 | ||
222 | static unsigned toIndex(FPRReg reg) | |
223 | { | |
224 | ASSERT(reg != InvalidFPRReg); | |
225 | ASSERT(static_cast<int>(reg) < 32); | |
226 | static const unsigned indexForRegister[32] = { | |
227 | 0, 1, 2, 3, 4, 5, 6, 7, | |
228 | InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, | |
229 | 8, 9, 10, 11, 12, 13, 14, 15, | |
230 | 16, 17, 18, 19, 20, 21, 22, InvalidIndex | |
231 | }; | |
232 | unsigned result = indexForRegister[reg]; | |
233 | ASSERT(result != InvalidIndex); | |
234 | return result; | |
235 | } | |
236 | ||
237 | static const char* debugName(FPRReg reg) | |
238 | { | |
239 | ASSERT(reg != InvalidFPRReg); | |
240 | ASSERT(static_cast<int>(reg) < 32); | |
241 | static const char* nameForRegister[32] = { | |
242 | "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", | |
243 | "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", | |
244 | "q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23", | |
245 | "q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31" | |
246 | }; | |
247 | return nameForRegister[reg]; | |
248 | } | |
249 | ||
250 | private: | |
251 | static const unsigned InvalidIndex = 0xffffffff; | |
252 | }; | |
253 | ||
254 | #endif | |
255 | ||
256 | #if CPU(MIPS) | |
257 | ||
258 | class FPRInfo { | |
259 | public: | |
260 | typedef FPRReg RegisterType; | |
261 | static const unsigned numberOfRegisters = 6; | |
262 | ||
263 | // Temporary registers. | |
264 | static const FPRReg fpRegT0 = MIPSRegisters::f0; | |
265 | static const FPRReg fpRegT1 = MIPSRegisters::f4; | |
266 | static const FPRReg fpRegT2 = MIPSRegisters::f6; | |
267 | static const FPRReg fpRegT3 = MIPSRegisters::f8; | |
268 | static const FPRReg fpRegT4 = MIPSRegisters::f10; | |
269 | static const FPRReg fpRegT5 = MIPSRegisters::f18; | |
270 | ||
271 | static const FPRReg returnValueFPR = MIPSRegisters::f0; | |
272 | ||
273 | static const FPRReg argumentFPR0 = MIPSRegisters::f12; | |
274 | static const FPRReg argumentFPR1 = MIPSRegisters::f14; | |
275 | ||
276 | static FPRReg toRegister(unsigned index) | |
277 | { | |
278 | static const FPRReg registerForIndex[numberOfRegisters] = { | |
279 | fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5 }; | |
280 | ||
281 | ASSERT(index < numberOfRegisters); | |
282 | return registerForIndex[index]; | |
283 | } | |
284 | ||
285 | static unsigned toIndex(FPRReg reg) | |
286 | { | |
287 | ASSERT(reg != InvalidFPRReg); | |
288 | ASSERT(reg < 20); | |
289 | static const unsigned indexForRegister[20] = { | |
290 | 0, InvalidIndex, InvalidIndex, InvalidIndex, | |
291 | 1, InvalidIndex, 2, InvalidIndex, | |
292 | 3, InvalidIndex, 4, InvalidIndex, | |
293 | InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, | |
294 | InvalidIndex, InvalidIndex, 5, InvalidIndex, | |
295 | }; | |
296 | unsigned result = indexForRegister[reg]; | |
297 | ASSERT(result != InvalidIndex); | |
298 | return result; | |
299 | } | |
300 | ||
301 | static const char* debugName(FPRReg reg) | |
302 | { | |
303 | ASSERT(reg != InvalidFPRReg); | |
304 | ASSERT(reg < 32); | |
305 | static const char* nameForRegister[32] = { | |
306 | "f0", "f1", "f2", "f3", | |
307 | "f4", "f5", "f6", "f7", | |
308 | "f8", "f9", "f10", "f11", | |
309 | "f12", "f13", "f14", "f15" | |
310 | "f16", "f17", "f18", "f19" | |
311 | "f20", "f21", "f22", "f23" | |
312 | "f24", "f25", "f26", "f27" | |
313 | "f28", "f29", "f30", "f31" | |
314 | }; | |
315 | return nameForRegister[reg]; | |
316 | } | |
317 | private: | |
318 | ||
319 | static const unsigned InvalidIndex = 0xffffffff; | |
320 | }; | |
321 | ||
322 | #endif | |
323 | ||
14957cd0 A |
324 | typedef RegisterBank<FPRInfo>::iterator fpr_iterator; |
325 | ||
326 | } } // namespace JSC::DFG | |
327 | ||
328 | #endif | |
329 | #endif |