CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / js / src / methodjit / MachineRegs.h
blob149f1883ed8da4a61d5ba7369c8b5a271456b9ed
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 {
51 enum CallConvention {
52 NormalCall,
53 FastCall
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;
63 #endif
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;
70 #endif
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;
79 # endif
80 # else
81 static const RegisterID ArgReg0 = JSC::X86Registers::edi;
82 static const RegisterID ArgReg1 = JSC::X86Registers::esi;
83 static const RegisterID ArgReg2 = JSC::X86Registers::edx;
84 # endif
85 #elif JS_CPU_ARM
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;
90 #endif
92 static const RegisterID StackPointer = JSC::MacroAssembler::stackPointerRegister;
94 static inline uint32 maskReg(RegisterID reg) {
95 return (1 << 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)
117 # endif
118 # endif
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)
131 # endif
132 # else
133 static const uint32 SavedRegs =
134 (1 << JSC::X86Registers::esi)
135 | (1 << JSC::X86Registers::edi)
136 # endif
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;
147 # endif
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;
171 #else
172 # error "Unsupported platform"
173 #endif
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)
186 return 0;
187 # else
188 return (convention == FastCall) ? 2 : 0;
189 # endif
190 #elif defined(JS_CPU_X64)
191 # ifdef _WIN64
192 return 4;
193 # else
194 return 6;
195 # endif
196 #elif defined(JS_CPU_ARM)
197 return 4;
198 #endif
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)
209 return false;
210 # else
211 if (conv == NormalCall)
212 return false;
213 # endif
214 #elif defined(JS_CPU_X64)
215 # ifdef _WIN64
216 static const RegisterID regs[] = {
217 JSC::X86Registers::ecx,
218 JSC::X86Registers::edx,
219 JSC::X86Registers::r8,
220 JSC::X86Registers::r9
222 # else
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
231 # endif
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
239 #endif
240 JS_ASSERT(numArgRegs(conv) == JS_ARRAY_LENGTH(regs));
241 if (i > JS_ARRAY_LENGTH(regs))
242 return false;
243 *reg = regs[i];
244 return true;
247 Registers()
248 : freeMask(AvailRegs)
251 Registers(uint32 freeMask)
252 : freeMask(freeMask)
255 Registers(const Registers &other)
256 : freeMask(other.freeMask)
259 Registers & operator =(const Registers &other)
261 freeMask = other.freeMask;
262 return *this;
265 void reset() {
266 freeMask = AvailRegs;
269 bool empty() const {
270 return !freeMask;
273 bool empty(uint32 mask) const {
274 return !(freeMask & mask);
277 RegisterID peekReg() {
278 JS_ASSERT(!empty());
279 int ireg;
280 JS_FLOOR_LOG2(ireg, freeMask);
281 RegisterID reg = (RegisterID)ireg;
282 return reg;
285 RegisterID takeAnyReg() {
286 RegisterID reg = peekReg();
287 takeReg(reg);
288 return reg;
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();
299 takeReg(reg);
300 return reg;
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;
329 uint32 freeMask;
333 struct FPRegisters {
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;
365 #else
366 # error "Unsupported platform"
367 #endif
369 static const uint32 AvailFPRegs = TempFPRegs;
371 FPRegisters()
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;
386 return *this;
389 void reset() {
390 freeFPMask = AvailFPRegs;
393 bool empty() const {
394 return !freeFPMask;
397 bool empty(uint32 mask) const {
398 return !(freeFPMask & mask);
401 FPRegisterID takeAnyReg() {
402 JS_ASSERT(!empty());
403 int ireg;
404 JS_FLOOR_LOG2(ireg, freeFPMask);
405 FPRegisterID reg = (FPRegisterID)ireg;
406 takeReg(reg);
407 return reg;
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();
418 takeReg(reg);
419 return reg;
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;
444 uint32 freeFPMask;
447 static const JSC::MacroAssembler::RegisterID JSFrameReg = Registers::JSFrameReg;
449 } /* namespace mjit */
451 } /* namespace js */
453 #endif /* jsjaeger_regstate_h__ */