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"
56 typedef JSC::MacroAssembler::RegisterID RegisterID
;
58 // Homed and scratch registers for working with Values on x64.
59 #if defined(JS_CPU_X64)
60 static const RegisterID TypeMaskReg
= JSC::X86Registers::r13
;
61 static const RegisterID PayloadMaskReg
= JSC::X86Registers::r14
;
62 static const RegisterID ValueReg
= JSC::X86Registers::r10
;
65 // Register that homes the current JSStackFrame.
66 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
67 static const RegisterID JSFrameReg
= JSC::X86Registers::ebx
;
68 #elif defined(JS_CPU_ARM)
69 static const RegisterID JSFrameReg
= JSC::ARMRegisters::r11
;
72 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
73 static const RegisterID ReturnReg
= JSC::X86Registers::eax
;
74 # if defined(JS_CPU_X86) || defined(_MSC_VER)
75 static const RegisterID ArgReg0
= JSC::X86Registers::ecx
;
76 static const RegisterID ArgReg1
= JSC::X86Registers::edx
;
77 # if defined(JS_CPU_X64)
78 static const RegisterID ArgReg2
= JSC::X86Registers::r8
;
81 static const RegisterID ArgReg0
= JSC::X86Registers::edi
;
82 static const RegisterID ArgReg1
= JSC::X86Registers::esi
;
83 static const RegisterID ArgReg2
= JSC::X86Registers::edx
;
86 static const RegisterID ReturnReg
= JSC::ARMRegisters::r0
;
87 static const RegisterID ArgReg0
= JSC::ARMRegisters::r0
;
88 static const RegisterID ArgReg1
= JSC::ARMRegisters::r1
;
89 static const RegisterID ArgReg2
= JSC::ARMRegisters::r2
;
92 static const RegisterID StackPointer
= JSC::MacroAssembler::stackPointerRegister
;
94 static inline uint32
maskReg(RegisterID reg
) {
98 static inline uint32
mask2Regs(RegisterID reg1
, RegisterID reg2
) {
99 return maskReg(reg1
) | maskReg(reg2
);
102 static inline uint32
mask3Regs(RegisterID reg1
, RegisterID reg2
, RegisterID reg3
) {
103 return maskReg(reg1
) | maskReg(reg2
) | maskReg(reg3
);
106 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
107 static const uint32 TempRegs
=
108 (1 << JSC::X86Registers::eax
)
109 | (1 << JSC::X86Registers::ecx
)
110 | (1 << JSC::X86Registers::edx
)
111 # if defined(JS_CPU_X64)
112 | (1 << JSC::X86Registers::r8
)
113 | (1 << JSC::X86Registers::r9
)
114 # if !defined(_MSC_VER)
115 | (1 << JSC::X86Registers::esi
)
116 | (1 << JSC::X86Registers::edi
)
121 # if defined(JS_CPU_X64)
122 static const uint32 SavedRegs
=
123 /* r11 is scratchRegister, used by JSC. */
124 (1 << JSC::X86Registers::r12
)
125 // r13 is TypeMaskReg.
126 // r14 is PayloadMaskReg.
127 | (1 << JSC::X86Registers::r15
)
128 # if defined(_MSC_VER)
129 | (1 << JSC::X86Registers::esi
)
130 | (1 << JSC::X86Registers::edi
)
133 static const uint32 SavedRegs
=
134 (1 << JSC::X86Registers::esi
)
135 | (1 << JSC::X86Registers::edi
)
139 # if defined(JS_CPU_X86)
140 static const uint32 SingleByteRegs
= (TempRegs
| SavedRegs
) &
141 ~((1 << JSC::X86Registers::esi
) |
142 (1 << JSC::X86Registers::edi
) |
143 (1 << JSC::X86Registers::ebp
) |
144 (1 << JSC::X86Registers::esp
));
145 # elif defined(JS_CPU_X64)
146 static const uint32 SingleByteRegs
= TempRegs
| SavedRegs
;
149 #elif defined(JS_CPU_ARM)
150 static const uint32 TempRegs
=
151 (1 << JSC::ARMRegisters::r0
)
152 | (1 << JSC::ARMRegisters::r1
)
153 | (1 << JSC::ARMRegisters::r2
);
154 // r3 is reserved as a scratch register for the assembler.
156 static const uint32 SavedRegs
=
157 (1 << JSC::ARMRegisters::r4
)
158 | (1 << JSC::ARMRegisters::r5
)
159 | (1 << JSC::ARMRegisters::r6
)
160 | (1 << JSC::ARMRegisters::r7
)
161 // r8 is reserved as a scratch register for the assembler.
162 | (1 << JSC::ARMRegisters::r9
)
163 | (1 << JSC::ARMRegisters::r10
);
164 // r11 is reserved for JSFrameReg.
165 // r12 is IP, and is used for stub calls.
166 // r13 is SP and must always point to VMFrame whilst in generated code.
167 // r14 is LR and is used for return sequences.
168 // r15 is PC (program counter).
170 static const uint32 SingleByteRegs
= TempRegs
| SavedRegs
;
172 # error "Unsupported platform"
175 static const uint32 AvailRegs
= SavedRegs
| TempRegs
;
177 static bool isSaved(RegisterID reg
) {
178 uint32 mask
= maskReg(reg
);
179 JS_ASSERT(mask
& AvailRegs
);
180 return bool(mask
& SavedRegs
);
183 static inline uint32
numArgRegs(CallConvention convention
) {
184 #if defined(JS_CPU_X86)
185 # if defined(JS_NO_FASTCALL)
188 return (convention
== FastCall
) ? 2 : 0;
190 #elif defined(JS_CPU_X64)
196 #elif defined(JS_CPU_ARM)
201 static inline bool regForArg(CallConvention conv
, uint32 i
, RegisterID
*reg
) {
202 #if defined(JS_CPU_X86)
203 static const RegisterID regs
[] = {
204 JSC::X86Registers::ecx
,
205 JSC::X86Registers::edx
208 # if defined(JS_NO_FASTCALL)
211 if (conv
== NormalCall
)
214 #elif defined(JS_CPU_X64)
216 static const RegisterID regs
[] = {
217 JSC::X86Registers::ecx
,
218 JSC::X86Registers::edx
,
219 JSC::X86Registers::r8
,
220 JSC::X86Registers::r9
223 static const RegisterID regs
[] = {
224 JSC::X86Registers::edi
,
225 JSC::X86Registers::esi
,
226 JSC::X86Registers::edx
,
227 JSC::X86Registers::ecx
,
228 JSC::X86Registers::r8
,
229 JSC::X86Registers::r9
232 #elif defined(JS_CPU_ARM)
233 static const RegisterID regs
[] = {
234 JSC::ARMRegisters::r0
,
235 JSC::ARMRegisters::r1
,
236 JSC::ARMRegisters::r2
,
237 JSC::ARMRegisters::r3
240 JS_ASSERT(numArgRegs(conv
) == JS_ARRAY_LENGTH(regs
));
241 if (i
> JS_ARRAY_LENGTH(regs
))
248 : freeMask(AvailRegs
)
251 Registers(uint32 freeMask
)
255 Registers(const Registers
&other
)
256 : freeMask(other
.freeMask
)
259 Registers
& operator =(const Registers
&other
)
261 freeMask
= other
.freeMask
;
266 freeMask
= AvailRegs
;
273 bool empty(uint32 mask
) const {
274 return !(freeMask
& mask
);
277 RegisterID
peekReg() {
280 JS_FLOOR_LOG2(ireg
, freeMask
);
281 RegisterID reg
= (RegisterID
)ireg
;
285 RegisterID
takeAnyReg() {
286 RegisterID reg
= peekReg();
291 bool hasRegInMask(uint32 mask
) const {
292 Registers
temp(freeMask
& mask
);
293 return !temp
.empty();
296 RegisterID
takeRegInMask(uint32 mask
) {
297 Registers
temp(freeMask
& mask
);
298 RegisterID reg
= temp
.takeAnyReg();
303 bool hasReg(RegisterID reg
) const {
304 return !!(freeMask
& (1 << reg
));
307 void putRegUnchecked(RegisterID reg
) {
308 freeMask
|= (1 << reg
);
311 void putReg(RegisterID reg
) {
312 JS_ASSERT(!hasReg(reg
));
313 putRegUnchecked(reg
);
316 void takeReg(RegisterID reg
) {
317 JS_ASSERT(hasReg(reg
));
318 takeRegUnchecked(reg
);
321 void takeRegUnchecked(RegisterID reg
) {
322 freeMask
&= ~(1 << reg
);
325 bool operator ==(const Registers
&other
) {
326 return freeMask
== other
.freeMask
;
335 typedef JSC::MacroAssembler::FPRegisterID FPRegisterID
;
337 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
338 static const uint32 TotalFPRegisters
= 8;
339 static const uint32 TempFPRegs
=
340 (1 << JSC::X86Registers::xmm0
)
341 | (1 << JSC::X86Registers::xmm1
)
342 | (1 << JSC::X86Registers::xmm2
)
343 | (1 << JSC::X86Registers::xmm3
)
344 | (1 << JSC::X86Registers::xmm4
)
345 | (1 << JSC::X86Registers::xmm5
)
346 | (1 << JSC::X86Registers::xmm6
)
347 | (1 << JSC::X86Registers::xmm7
);
348 /* FIXME: Temporary hack until FPRegister allocation exists. */
349 static const FPRegisterID First
= JSC::X86Registers::xmm0
;
350 static const FPRegisterID Second
= JSC::X86Registers::xmm1
;
351 static const FPRegisterID Temp0
= JSC::X86Registers::xmm2
;
352 static const FPRegisterID Temp1
= JSC::X86Registers::xmm3
;
353 #elif defined(JS_CPU_ARM)
354 static const uint32 TotalFPRegisters
= 4;
355 static const uint32 TempFPRegs
=
356 (1 << JSC::ARMRegisters::d0
)
357 | (1 << JSC::ARMRegisters::d1
)
358 | (1 << JSC::ARMRegisters::d2
)
359 | (1 << JSC::ARMRegisters::d3
);
360 /* FIXME: Temporary hack until FPRegister allocation exists. */
361 static const FPRegisterID First
= JSC::ARMRegisters::d0
;
362 static const FPRegisterID Second
= JSC::ARMRegisters::d1
;
363 static const FPRegisterID Temp0
= JSC::ARMRegisters::d2
;
364 static const FPRegisterID Temp1
= JSC::ARMRegisters::d3
;
366 # error "Unsupported platform"
369 static const uint32 AvailFPRegs
= TempFPRegs
;
372 : freeFPMask(AvailFPRegs
)
375 FPRegisters(uint32 freeFPMask
)
376 : freeFPMask(freeFPMask
)
379 FPRegisters(const FPRegisters
&other
)
380 : freeFPMask(other
.freeFPMask
)
383 FPRegisters
& operator =(const FPRegisters
&other
)
385 freeFPMask
= other
.freeFPMask
;
390 freeFPMask
= AvailFPRegs
;
397 bool empty(uint32 mask
) const {
398 return !(freeFPMask
& mask
);
401 FPRegisterID
takeAnyReg() {
404 JS_FLOOR_LOG2(ireg
, freeFPMask
);
405 FPRegisterID reg
= (FPRegisterID
)ireg
;
410 bool hasRegInMask(uint32 mask
) const {
411 FPRegisters
temp(freeFPMask
& mask
);
412 return !temp
.empty();
415 FPRegisterID
takeRegInMask(uint32 mask
) {
416 FPRegisters
temp(freeFPMask
& mask
);
417 FPRegisterID reg
= temp
.takeAnyReg();
422 bool hasReg(FPRegisterID fpreg
) const {
423 return !!(freeFPMask
& (1 << fpreg
));
426 void putRegUnchecked(FPRegisterID fpreg
) {
427 freeFPMask
|= (1 << fpreg
);
430 void putReg(FPRegisterID fpreg
) {
431 JS_ASSERT(!hasReg(fpreg
));
432 putRegUnchecked(fpreg
);
435 void takeReg(FPRegisterID fpreg
) {
436 JS_ASSERT(hasReg(fpreg
));
437 freeFPMask
&= ~(1 << fpreg
);
440 bool operator ==(const FPRegisters
&other
) {
441 return freeFPMask
== other
.freeFPMask
;
447 static const JSC::MacroAssembler::RegisterID JSFrameReg
= Registers::JSFrameReg
;
449 } /* namespace mjit */
453 #endif /* jsjaeger_regstate_h__ */