]>
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 DFGGPRInfo_h | |
27 | #define DFGGPRInfo_h | |
28 | ||
29 | #if ENABLE(DFG_JIT) | |
30 | ||
31 | #include <assembler/MacroAssembler.h> | |
32 | #include <dfg/DFGRegisterBank.h> | |
33 | ||
34 | namespace JSC { namespace DFG { | |
35 | ||
36 | typedef MacroAssembler::RegisterID GPRReg; | |
37 | #define InvalidGPRReg ((GPRReg)-1) | |
38 | ||
6fe7ccc8 A |
39 | #if USE(JSVALUE64) |
40 | class JSValueRegs { | |
41 | public: | |
42 | JSValueRegs() | |
43 | : m_gpr(InvalidGPRReg) | |
44 | { | |
45 | } | |
46 | ||
47 | explicit JSValueRegs(GPRReg gpr) | |
48 | : m_gpr(gpr) | |
49 | { | |
50 | } | |
51 | ||
52 | bool operator!() const { return m_gpr == InvalidGPRReg; } | |
53 | ||
54 | GPRReg gpr() const { return m_gpr; } | |
55 | ||
56 | private: | |
57 | GPRReg m_gpr; | |
58 | }; | |
59 | ||
60 | class JSValueSource { | |
61 | public: | |
62 | JSValueSource() | |
63 | : m_offset(notAddress()) | |
64 | , m_base(InvalidGPRReg) | |
65 | { | |
66 | } | |
67 | ||
68 | JSValueSource(JSValueRegs regs) | |
69 | : m_offset(notAddress()) | |
70 | , m_base(regs.gpr()) | |
71 | { | |
72 | } | |
73 | ||
74 | explicit JSValueSource(GPRReg gpr) | |
75 | : m_offset(notAddress()) | |
76 | , m_base(gpr) | |
77 | { | |
78 | } | |
79 | ||
80 | JSValueSource(MacroAssembler::Address address) | |
81 | : m_offset(address.offset) | |
82 | , m_base(address.base) | |
83 | { | |
84 | ASSERT(m_offset != notAddress()); | |
85 | ASSERT(m_base != InvalidGPRReg); | |
86 | } | |
87 | ||
88 | static JSValueSource unboxedCell(GPRReg payloadGPR) | |
89 | { | |
90 | return JSValueSource(payloadGPR); | |
91 | } | |
92 | ||
93 | bool operator!() const { return m_base == InvalidGPRReg; } | |
94 | ||
95 | bool isAddress() const { return m_offset != notAddress(); } | |
96 | ||
97 | int32_t offset() const | |
98 | { | |
99 | ASSERT(isAddress()); | |
100 | return m_offset; | |
101 | } | |
102 | ||
103 | GPRReg base() const | |
104 | { | |
105 | ASSERT(isAddress()); | |
106 | return m_base; | |
107 | } | |
108 | ||
109 | GPRReg gpr() const | |
110 | { | |
111 | ASSERT(!isAddress()); | |
112 | return m_base; | |
113 | } | |
114 | ||
115 | MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); } | |
116 | ||
117 | private: | |
118 | static inline int32_t notAddress() { return 0x80000000; } | |
119 | ||
120 | int32_t m_offset; | |
121 | GPRReg m_base; | |
122 | }; | |
123 | #endif | |
124 | ||
125 | #if USE(JSVALUE32_64) | |
126 | class JSValueRegs { | |
127 | public: | |
128 | JSValueRegs() | |
129 | : m_tagGPR(static_cast<int8_t>(InvalidGPRReg)) | |
130 | , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg)) | |
131 | { | |
132 | } | |
133 | ||
134 | JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR) | |
135 | : m_tagGPR(tagGPR) | |
136 | , m_payloadGPR(payloadGPR) | |
137 | { | |
138 | ASSERT((static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg) == (static_cast<GPRReg>(payloadGPR) == InvalidGPRReg)); | |
139 | } | |
140 | ||
141 | bool operator!() const { return static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg; } | |
142 | ||
143 | GPRReg tagGPR() const { return static_cast<GPRReg>(m_tagGPR); } | |
144 | GPRReg payloadGPR() const { return static_cast<GPRReg>(m_payloadGPR); } | |
145 | ||
146 | private: | |
147 | int8_t m_tagGPR; | |
148 | int8_t m_payloadGPR; | |
149 | }; | |
150 | ||
151 | class JSValueSource { | |
152 | public: | |
153 | JSValueSource() | |
154 | : m_offset(notAddress()) | |
155 | , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg)) | |
156 | , m_payload(static_cast<int8_t>(InvalidGPRReg)) | |
157 | , m_tagType(0) | |
158 | { | |
159 | } | |
160 | ||
161 | JSValueSource(JSValueRegs regs) | |
162 | : m_offset(notAddress()) | |
163 | , m_baseOrTag(regs.tagGPR()) | |
164 | , m_payload(regs.payloadGPR()) | |
165 | , m_tagType(0) | |
166 | { | |
167 | } | |
168 | ||
169 | JSValueSource(GPRReg tagGPR, GPRReg payloadGPR) | |
170 | : m_offset(notAddress()) | |
171 | , m_baseOrTag(static_cast<int8_t>(tagGPR)) | |
172 | , m_payload(static_cast<int8_t>(payloadGPR)) | |
173 | , m_tagType(0) | |
174 | { | |
175 | } | |
176 | ||
177 | JSValueSource(MacroAssembler::Address address) | |
178 | : m_offset(address.offset) | |
179 | , m_baseOrTag(static_cast<int8_t>(address.base)) | |
180 | , m_payload(static_cast<int8_t>(InvalidGPRReg)) | |
181 | , m_tagType(0) | |
182 | { | |
183 | ASSERT(m_offset != notAddress()); | |
184 | ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg); | |
185 | } | |
186 | ||
187 | static JSValueSource unboxedCell(GPRReg payloadGPR) | |
188 | { | |
189 | JSValueSource result; | |
190 | result.m_offset = notAddress(); | |
191 | result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg); | |
192 | result.m_payload = static_cast<int8_t>(payloadGPR); | |
193 | result.m_tagType = static_cast<int8_t>(JSValue::CellTag); | |
194 | return result; | |
195 | } | |
196 | ||
197 | bool operator!() const { return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg && static_cast<GPRReg>(m_payload) == InvalidGPRReg; } | |
198 | ||
199 | bool isAddress() const | |
200 | { | |
201 | ASSERT(!!*this); | |
202 | return m_offset != notAddress(); | |
203 | } | |
204 | ||
205 | int32_t offset() const | |
206 | { | |
207 | ASSERT(isAddress()); | |
208 | return m_offset; | |
209 | } | |
210 | ||
211 | GPRReg base() const | |
212 | { | |
213 | ASSERT(isAddress()); | |
214 | return static_cast<GPRReg>(m_baseOrTag); | |
215 | } | |
216 | ||
217 | GPRReg tagGPR() const | |
218 | { | |
219 | ASSERT(!isAddress() && m_baseOrTag != InvalidGPRReg); | |
220 | return static_cast<GPRReg>(m_baseOrTag); | |
221 | } | |
222 | ||
223 | GPRReg payloadGPR() const | |
224 | { | |
225 | ASSERT(!isAddress()); | |
226 | return static_cast<GPRReg>(m_payload); | |
227 | } | |
228 | ||
229 | bool hasKnownTag() const | |
230 | { | |
231 | ASSERT(!!*this); | |
232 | ASSERT(!isAddress()); | |
233 | return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg; | |
234 | } | |
235 | ||
236 | uint32_t tag() const | |
237 | { | |
238 | return static_cast<int32_t>(m_tagType); | |
239 | } | |
240 | ||
241 | MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); } | |
242 | ||
243 | private: | |
244 | static inline int32_t notAddress() { return 0x80000000; } | |
245 | ||
246 | int32_t m_offset; | |
247 | int8_t m_baseOrTag; | |
248 | int8_t m_payload; | |
249 | int8_t m_tagType; // Contains the low bits of the tag. | |
250 | }; | |
251 | #endif | |
252 | ||
253 | #if CPU(X86) | |
254 | #define NUMBER_OF_ARGUMENT_REGISTERS 0 | |
255 | ||
256 | class GPRInfo { | |
257 | public: | |
258 | typedef GPRReg RegisterType; | |
259 | static const unsigned numberOfRegisters = 5; | |
260 | ||
261 | // Temporary registers. | |
262 | static const GPRReg regT0 = X86Registers::eax; | |
263 | static const GPRReg regT1 = X86Registers::edx; | |
264 | static const GPRReg regT2 = X86Registers::ecx; | |
265 | static const GPRReg regT3 = X86Registers::ebx; | |
266 | static const GPRReg regT4 = X86Registers::esi; | |
267 | // These registers match the baseline JIT. | |
268 | static const GPRReg cachedResultRegister = regT0; | |
269 | static const GPRReg cachedResultRegister2 = regT1; | |
270 | static const GPRReg callFrameRegister = X86Registers::edi; | |
271 | // These constants provide the names for the general purpose argument & return value registers. | |
272 | static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2 | |
273 | static const GPRReg argumentGPR1 = X86Registers::edx; // regT1 | |
274 | static const GPRReg returnValueGPR = X86Registers::eax; // regT0 | |
275 | static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 | |
276 | static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx; | |
277 | ||
278 | static GPRReg toRegister(unsigned index) | |
279 | { | |
280 | ASSERT(index < numberOfRegisters); | |
281 | static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4 }; | |
282 | return registerForIndex[index]; | |
283 | } | |
284 | ||
285 | static unsigned toIndex(GPRReg reg) | |
286 | { | |
287 | ASSERT(reg != InvalidGPRReg); | |
288 | ASSERT(reg < 8); | |
289 | static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, InvalidIndex }; | |
290 | unsigned result = indexForRegister[reg]; | |
291 | ASSERT(result != InvalidIndex); | |
292 | return result; | |
293 | } | |
294 | ||
295 | static const char* debugName(GPRReg reg) | |
296 | { | |
297 | ASSERT(reg != InvalidGPRReg); | |
298 | ASSERT(reg < 8); | |
299 | static const char* nameForRegister[8] = { | |
300 | "eax", "ecx", "edx", "ebx", | |
301 | "esp", "ebp", "esi", "edi", | |
302 | }; | |
303 | return nameForRegister[reg]; | |
304 | } | |
305 | private: | |
306 | ||
307 | static const unsigned InvalidIndex = 0xffffffff; | |
308 | }; | |
309 | ||
310 | #endif | |
311 | ||
312 | #if CPU(X86_64) | |
313 | #define NUMBER_OF_ARGUMENT_REGISTERS 6 | |
314 | ||
14957cd0 A |
315 | class GPRInfo { |
316 | public: | |
317 | typedef GPRReg RegisterType; | |
318 | static const unsigned numberOfRegisters = 9; | |
319 | ||
6fe7ccc8 A |
320 | // These registers match the baseline JIT. |
321 | static const GPRReg cachedResultRegister = X86Registers::eax; | |
14957cd0 A |
322 | static const GPRReg timeoutCheckRegister = X86Registers::r12; |
323 | static const GPRReg callFrameRegister = X86Registers::r13; | |
324 | static const GPRReg tagTypeNumberRegister = X86Registers::r14; | |
325 | static const GPRReg tagMaskRegister = X86Registers::r15; | |
326 | // Temporary registers. | |
327 | static const GPRReg regT0 = X86Registers::eax; | |
328 | static const GPRReg regT1 = X86Registers::edx; | |
329 | static const GPRReg regT2 = X86Registers::ecx; | |
330 | static const GPRReg regT3 = X86Registers::ebx; | |
331 | static const GPRReg regT4 = X86Registers::edi; | |
332 | static const GPRReg regT5 = X86Registers::esi; | |
333 | static const GPRReg regT6 = X86Registers::r8; | |
334 | static const GPRReg regT7 = X86Registers::r9; | |
335 | static const GPRReg regT8 = X86Registers::r10; | |
336 | // These constants provide the names for the general purpose argument & return value registers. | |
337 | static const GPRReg argumentGPR0 = X86Registers::edi; // regT4 | |
338 | static const GPRReg argumentGPR1 = X86Registers::esi; // regT5 | |
339 | static const GPRReg argumentGPR2 = X86Registers::edx; // regT1 | |
340 | static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2 | |
6fe7ccc8 A |
341 | static const GPRReg argumentGPR4 = X86Registers::r8; // regT6 |
342 | static const GPRReg argumentGPR5 = X86Registers::r9; // regT7 | |
14957cd0 A |
343 | static const GPRReg returnValueGPR = X86Registers::eax; // regT0 |
344 | static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 | |
6fe7ccc8 | 345 | static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi; |
14957cd0 A |
346 | |
347 | static GPRReg toRegister(unsigned index) | |
348 | { | |
349 | ASSERT(index < numberOfRegisters); | |
350 | static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 }; | |
351 | return registerForIndex[index]; | |
352 | } | |
353 | ||
354 | static unsigned toIndex(GPRReg reg) | |
355 | { | |
356 | ASSERT(reg != InvalidGPRReg); | |
357 | ASSERT(reg < 16); | |
358 | static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex }; | |
359 | unsigned result = indexForRegister[reg]; | |
360 | ASSERT(result != InvalidIndex); | |
361 | return result; | |
362 | } | |
363 | ||
14957cd0 A |
364 | static const char* debugName(GPRReg reg) |
365 | { | |
366 | ASSERT(reg != InvalidGPRReg); | |
367 | ASSERT(reg < 16); | |
368 | static const char* nameForRegister[16] = { | |
369 | "rax", "rcx", "rdx", "rbx", | |
370 | "rsp", "rbp", "rsi", "rdi", | |
371 | "r8", "r9", "r10", "r11", | |
372 | "r12", "r13", "r14", "r15" | |
373 | }; | |
374 | return nameForRegister[reg]; | |
375 | } | |
6fe7ccc8 A |
376 | private: |
377 | ||
378 | static const unsigned InvalidIndex = 0xffffffff; | |
379 | }; | |
380 | ||
14957cd0 | 381 | #endif |
6fe7ccc8 A |
382 | |
383 | #if CPU(ARM_THUMB2) | |
384 | #define NUMBER_OF_ARGUMENT_REGISTERS 4 | |
385 | ||
386 | class GPRInfo { | |
387 | public: | |
388 | typedef GPRReg RegisterType; | |
389 | static const unsigned numberOfRegisters = 8; | |
390 | ||
391 | // Temporary registers. | |
392 | static const GPRReg regT0 = ARMRegisters::r0; | |
393 | static const GPRReg regT1 = ARMRegisters::r1; | |
394 | static const GPRReg regT2 = ARMRegisters::r2; | |
395 | static const GPRReg regT3 = ARMRegisters::r4; | |
396 | static const GPRReg regT4 = ARMRegisters::r8; | |
397 | static const GPRReg regT5 = ARMRegisters::r9; | |
398 | static const GPRReg regT6 = ARMRegisters::r10; | |
399 | static const GPRReg regT7 = ARMRegisters::r11; | |
400 | // These registers match the baseline JIT. | |
401 | static const GPRReg cachedResultRegister = regT0; | |
402 | static const GPRReg cachedResultRegister2 = regT1; | |
403 | static const GPRReg callFrameRegister = ARMRegisters::r5; | |
404 | // These constants provide the names for the general purpose argument & return value registers. | |
405 | static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0 | |
406 | static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1 | |
407 | static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2 | |
408 | // FIXME: r3 is currently used be the MacroAssembler as a temporary - it seems | |
409 | // This could threoretically be a problem if theis is used in code generation | |
410 | // between the arguments being set up, and the call being made. That said, | |
411 | // any change introducing a problem here is likely to be immediately apparent! | |
412 | static const GPRReg argumentGPR3 = ARMRegisters::r3; // FIXME! | |
413 | static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0 | |
414 | static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1 | |
415 | static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r2; | |
416 | ||
417 | static GPRReg toRegister(unsigned index) | |
418 | { | |
419 | ASSERT(index < numberOfRegisters); | |
420 | static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 }; | |
421 | return registerForIndex[index]; | |
422 | } | |
423 | ||
424 | static unsigned toIndex(GPRReg reg) | |
425 | { | |
426 | ASSERT(reg != InvalidGPRReg); | |
427 | ASSERT(reg < 16); | |
428 | static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex }; | |
429 | unsigned result = indexForRegister[reg]; | |
430 | ASSERT(result != InvalidIndex); | |
431 | return result; | |
432 | } | |
433 | ||
434 | static const char* debugName(GPRReg reg) | |
435 | { | |
436 | ASSERT(reg != InvalidGPRReg); | |
437 | ASSERT(reg < 16); | |
438 | static const char* nameForRegister[16] = { | |
439 | "r0", "r1", "r2", "r3", | |
440 | "r4", "r5", "r6", "r7", | |
441 | "r8", "r9", "r10", "r11", | |
442 | "r12", "r13", "r14", "r15" | |
443 | }; | |
444 | return nameForRegister[reg]; | |
445 | } | |
14957cd0 A |
446 | private: |
447 | ||
448 | static const unsigned InvalidIndex = 0xffffffff; | |
449 | }; | |
450 | ||
6fe7ccc8 A |
451 | #endif |
452 | ||
14957cd0 A |
453 | typedef RegisterBank<GPRInfo>::iterator gpr_iterator; |
454 | ||
455 | } } // namespace JSC::DFG | |
456 | ||
457 | #endif | |
458 | #endif |