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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
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__
44 #include "assembler/assembler/MacroAssembler.h"
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
;
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
;
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
;
77 static const RegisterID ArgReg0
= JSC::X86Registers::edi
;
78 static const RegisterID ArgReg1
= JSC::X86Registers::esi
;
79 static const RegisterID ArgReg2
= JSC::X86Registers::edx
;
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
;
88 static const RegisterID StackPointer
= JSC::MacroAssembler::stackPointerRegister
;
90 static inline uint32
maskReg(RegisterID 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
)
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.
125 # if defined(_MSC_VER)
126 | (1 << JSC::X86Registers::esi
)
127 | (1 << JSC::X86Registers::edi
)
130 static const uint32 SavedRegs
=
131 (1 << JSC::X86Registers::esi
)
132 | (1 << JSC::X86Registers::edi
)
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
;
165 # error "Unsupported platform"
168 static const uint32 AvailRegs
= SavedRegs
| TempRegs
;
171 : freeMask(AvailRegs
)
174 Registers(uint32 freeMask
)
178 Registers(const Registers
&other
)
179 : freeMask(other
.freeMask
)
182 Registers
& operator =(const Registers
&other
)
184 freeMask
= other
.freeMask
;
189 freeMask
= AvailRegs
;
196 bool empty(uint32 mask
) const {
197 return !(freeMask
& mask
);
200 RegisterID
peekReg() {
203 JS_FLOOR_LOG2(ireg
, freeMask
);
204 RegisterID reg
= (RegisterID
)ireg
;
208 RegisterID
takeAnyReg() {
209 RegisterID reg
= peekReg();
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();
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
;
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
;
285 # error "Unsupported platform"
288 static const uint32 AvailFPRegs
= TempFPRegs
;
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
;
309 freeFPMask
= AvailFPRegs
;
316 bool empty(uint32 mask
) const {
317 return !(freeFPMask
& mask
);
320 FPRegisterID
takeAnyReg() {
323 JS_FLOOR_LOG2(ireg
, freeFPMask
);
324 FPRegisterID reg
= (FPRegisterID
)ireg
;
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();
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
;
366 static const JSC::MacroAssembler::RegisterID JSFrameReg
= Registers::JSFrameReg
;
368 } /* namespace mjit */
372 #endif /* jsjaeger_regstate_h__ */