Refactor and improve GETELEM IC (bug 602641, r=dmandelin).
[mozilla-central.git] / js / src / methodjit / MachineRegs.h
blob9d0b2fcde45ddb984c1a2f7453b37b2ae6b349f0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * May 28, 2008.
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
23 * Contributor(s):
24 * David Anderson <danderson@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #if !defined jsjaeger_regstate_h__ && defined JS_METHODJIT
41 #define jsjaeger_regstate_h__
43 #include "jsbit.h"
44 #include "assembler/assembler/MacroAssembler.h"
46 namespace js {
48 namespace mjit {
50 struct Registers {
52 typedef JSC::MacroAssembler::RegisterID RegisterID;
54 // Homed and scratch registers for working with Values on x64.
55 #if defined(JS_CPU_X64)
56 static const RegisterID TypeMaskReg = JSC::X86Registers::r13;
57 static const RegisterID PayloadMaskReg = JSC::X86Registers::r14;
58 static const RegisterID ValueReg = JSC::X86Registers::r15;
59 #endif
61 // Register that homes the current JSStackFrame.
62 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
63 static const RegisterID JSFrameReg = JSC::X86Registers::ebx;
64 #elif defined(JS_CPU_ARM)
65 static const RegisterID JSFrameReg = JSC::ARMRegisters::r11;
66 #endif
68 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
69 static const RegisterID ReturnReg = JSC::X86Registers::eax;
70 # if defined(JS_CPU_X86) || defined(_MSC_VER)
71 static const RegisterID ArgReg0 = JSC::X86Registers::ecx;
72 static const RegisterID ArgReg1 = JSC::X86Registers::edx;
73 # if defined(JS_CPU_X64)
74 static const RegisterID ArgReg2 = JSC::X86Registers::r8;
75 # endif
76 # else
77 static const RegisterID ArgReg0 = JSC::X86Registers::edi;
78 static const RegisterID ArgReg1 = JSC::X86Registers::esi;
79 static const RegisterID ArgReg2 = JSC::X86Registers::edx;
80 # endif
81 #elif JS_CPU_ARM
82 static const RegisterID ReturnReg = JSC::ARMRegisters::r0;
83 static const RegisterID ArgReg0 = JSC::ARMRegisters::r0;
84 static const RegisterID ArgReg1 = JSC::ARMRegisters::r1;
85 static const RegisterID ArgReg2 = JSC::ARMRegisters::r2;
86 #endif
88 static const RegisterID StackPointer = JSC::MacroAssembler::stackPointerRegister;
90 static inline uint32 maskReg(RegisterID reg) {
91 return (1 << reg);
94 static inline uint32 mask2Regs(RegisterID reg1, RegisterID reg2) {
95 return maskReg(reg1) | maskReg(reg2);
98 static inline uint32 mask3Regs(RegisterID reg1, RegisterID reg2, RegisterID reg3) {
99 return maskReg(reg1) | maskReg(reg2) | maskReg(reg3);
102 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
103 static const uint32 TempRegs =
104 (1 << JSC::X86Registers::eax)
105 | (1 << JSC::X86Registers::ecx)
106 | (1 << JSC::X86Registers::edx)
107 # if defined(JS_CPU_X64)
108 | (1 << JSC::X86Registers::r8)
109 | (1 << JSC::X86Registers::r9)
110 | (1 << JSC::X86Registers::r10)
111 # if !defined(_MSC_VER)
112 | (1 << JSC::X86Registers::esi)
113 | (1 << JSC::X86Registers::edi)
114 # endif
115 # endif
118 # if defined(JS_CPU_X64)
119 static const uint32 SavedRegs =
120 /* r11 is scratchRegister, used by JSC. */
121 (1 << JSC::X86Registers::r12)
122 // r13 is TypeMaskReg.
123 // r14 is PayloadMaskReg.
124 // r15 is ValueReg.
125 # if defined(_MSC_VER)
126 | (1 << JSC::X86Registers::esi)
127 | (1 << JSC::X86Registers::edi)
128 # endif
129 # else
130 static const uint32 SavedRegs =
131 (1 << JSC::X86Registers::esi)
132 | (1 << JSC::X86Registers::edi)
133 # endif
136 static const uint32 SingleByteRegs = (TempRegs | SavedRegs) &
137 ~((1 << JSC::X86Registers::esi) |
138 (1 << JSC::X86Registers::edi) |
139 (1 << JSC::X86Registers::ebp) |
140 (1 << JSC::X86Registers::esp));
142 #elif defined(JS_CPU_ARM)
143 static const uint32 TempRegs =
144 (1 << JSC::ARMRegisters::r0)
145 | (1 << JSC::ARMRegisters::r1)
146 | (1 << JSC::ARMRegisters::r2);
147 // r3 is reserved as a scratch register for the assembler.
149 static const uint32 SavedRegs =
150 (1 << JSC::ARMRegisters::r4)
151 | (1 << JSC::ARMRegisters::r5)
152 | (1 << JSC::ARMRegisters::r6)
153 | (1 << JSC::ARMRegisters::r7)
154 // r8 is reserved as a scratch register for the assembler.
155 | (1 << JSC::ARMRegisters::r9)
156 | (1 << JSC::ARMRegisters::r10);
157 // r11 is reserved for JSFrameReg.
158 // r12 is IP, and is used for stub calls.
159 // r13 is SP and must always point to VMFrame whilst in generated code.
160 // r14 is LR and is used for return sequences.
161 // r15 is PC (program counter).
163 static const uint32 SingleByteRegs = TempRegs | SavedRegs;
164 #else
165 # error "Unsupported platform"
166 #endif
168 static const uint32 AvailRegs = SavedRegs | TempRegs;
170 Registers()
171 : freeMask(AvailRegs)
174 Registers(uint32 freeMask)
175 : freeMask(freeMask)
178 Registers(const Registers &other)
179 : freeMask(other.freeMask)
182 Registers & operator =(const Registers &other)
184 freeMask = other.freeMask;
185 return *this;
188 void reset() {
189 freeMask = AvailRegs;
192 bool empty() const {
193 return !freeMask;
196 bool empty(uint32 mask) const {
197 return !(freeMask & mask);
200 RegisterID peekReg() {
201 JS_ASSERT(!empty());
202 int ireg;
203 JS_FLOOR_LOG2(ireg, freeMask);
204 RegisterID reg = (RegisterID)ireg;
205 return reg;
208 RegisterID takeAnyReg() {
209 RegisterID reg = peekReg();
210 takeReg(reg);
211 return reg;
214 bool hasRegInMask(uint32 mask) const {
215 Registers temp(freeMask & mask);
216 return !temp.empty();
219 RegisterID takeRegInMask(uint32 mask) {
220 Registers temp(freeMask & mask);
221 RegisterID reg = temp.takeAnyReg();
222 takeReg(reg);
223 return reg;
226 bool hasReg(RegisterID reg) const {
227 return !!(freeMask & (1 << reg));
230 void putRegUnchecked(RegisterID reg) {
231 freeMask |= (1 << reg);
234 void putReg(RegisterID reg) {
235 JS_ASSERT(!hasReg(reg));
236 putRegUnchecked(reg);
239 void takeReg(RegisterID reg) {
240 JS_ASSERT(hasReg(reg));
241 freeMask &= ~(1 << reg);
244 bool operator ==(const Registers &other) {
245 return freeMask == other.freeMask;
248 uint32 freeMask;
252 struct FPRegisters {
254 typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
256 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
257 static const uint32 TotalFPRegisters = 8;
258 static const uint32 TempFPRegs =
259 (1 << JSC::X86Registers::xmm0)
260 | (1 << JSC::X86Registers::xmm1)
261 | (1 << JSC::X86Registers::xmm2)
262 | (1 << JSC::X86Registers::xmm3)
263 | (1 << JSC::X86Registers::xmm4)
264 | (1 << JSC::X86Registers::xmm5)
265 | (1 << JSC::X86Registers::xmm6)
266 | (1 << JSC::X86Registers::xmm7);
267 /* FIXME: Temporary hack until FPRegister allocation exists. */
268 static const FPRegisterID First = JSC::X86Registers::xmm0;
269 static const FPRegisterID Second = JSC::X86Registers::xmm1;
270 static const FPRegisterID Temp0 = JSC::X86Registers::xmm2;
271 static const FPRegisterID Temp1 = JSC::X86Registers::xmm3;
272 #elif defined(JS_CPU_ARM)
273 static const uint32 TotalFPRegisters = 4;
274 static const uint32 TempFPRegs =
275 (1 << JSC::ARMRegisters::d0)
276 | (1 << JSC::ARMRegisters::d1)
277 | (1 << JSC::ARMRegisters::d2)
278 | (1 << JSC::ARMRegisters::d3);
279 /* FIXME: Temporary hack until FPRegister allocation exists. */
280 static const FPRegisterID First = JSC::ARMRegisters::d0;
281 static const FPRegisterID Second = JSC::ARMRegisters::d1;
282 static const FPRegisterID Temp0 = JSC::ARMRegisters::d2;
283 static const FPRegisterID Temp1 = JSC::ARMRegisters::d3;
284 #else
285 # error "Unsupported platform"
286 #endif
288 static const uint32 AvailFPRegs = TempFPRegs;
290 FPRegisters()
291 : freeFPMask(AvailFPRegs)
294 FPRegisters(uint32 freeFPMask)
295 : freeFPMask(freeFPMask)
298 FPRegisters(const FPRegisters &other)
299 : freeFPMask(other.freeFPMask)
302 FPRegisters & operator =(const FPRegisters &other)
304 freeFPMask = other.freeFPMask;
305 return *this;
308 void reset() {
309 freeFPMask = AvailFPRegs;
312 bool empty() const {
313 return !freeFPMask;
316 bool empty(uint32 mask) const {
317 return !(freeFPMask & mask);
320 FPRegisterID takeAnyReg() {
321 JS_ASSERT(!empty());
322 int ireg;
323 JS_FLOOR_LOG2(ireg, freeFPMask);
324 FPRegisterID reg = (FPRegisterID)ireg;
325 takeReg(reg);
326 return reg;
329 bool hasRegInMask(uint32 mask) const {
330 FPRegisters temp(freeFPMask & mask);
331 return !temp.empty();
334 FPRegisterID takeRegInMask(uint32 mask) {
335 FPRegisters temp(freeFPMask & mask);
336 FPRegisterID reg = temp.takeAnyReg();
337 takeReg(reg);
338 return reg;
341 bool hasReg(FPRegisterID fpreg) const {
342 return !!(freeFPMask & (1 << fpreg));
345 void putRegUnchecked(FPRegisterID fpreg) {
346 freeFPMask |= (1 << fpreg);
349 void putReg(FPRegisterID fpreg) {
350 JS_ASSERT(!hasReg(fpreg));
351 putRegUnchecked(fpreg);
354 void takeReg(FPRegisterID fpreg) {
355 JS_ASSERT(hasReg(fpreg));
356 freeFPMask &= ~(1 << fpreg);
359 bool operator ==(const FPRegisters &other) {
360 return freeFPMask == other.freeFPMask;
363 uint32 freeFPMask;
366 static const JSC::MacroAssembler::RegisterID JSFrameReg = Registers::JSFrameReg;
368 } /* namespace mjit */
370 } /* namespace js */
372 #endif /* jsjaeger_regstate_h__ */