1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=4 sw=4 et tw=99:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
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/
11 : *
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.
16 : *
17 : * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 : * May 28, 2008.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Brendan Eich <brendan@mozilla.org>
22 : *
23 : * Contributor(s):
24 : * David Anderson <danderson@mozilla.com>
25 : *
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.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #if !defined jsjaeger_regstate_h__ && defined JS_METHODJIT
41 : #define jsjaeger_regstate_h__
42 :
43 : #include "mozilla/Util.h"
44 :
45 : #include "assembler/assembler/MacroAssembler.h"
46 :
47 : namespace js {
48 :
49 : namespace mjit {
50 :
51 : /* Common handling for both general purpose and floating point registers. */
52 :
53 : struct AnyRegisterID {
54 : unsigned reg_;
55 :
56 110217522 : AnyRegisterID()
57 110217522 : : reg_((unsigned)-1)
58 110217522 : { pin(); }
59 :
60 1544616473 : AnyRegisterID(const AnyRegisterID &o)
61 1544616473 : : reg_(o.reg_)
62 1544616473 : { pin(); }
63 :
64 282758876 : AnyRegisterID(JSC::MacroAssembler::RegisterID reg)
65 282758876 : : reg_((unsigned)reg)
66 282758876 : { pin(); }
67 :
68 123079388 : AnyRegisterID(JSC::MacroAssembler::FPRegisterID reg)
69 123079388 : : reg_(JSC::MacroAssembler::TotalRegisters + (unsigned)reg)
70 123079388 : { pin(); }
71 :
72 : static inline AnyRegisterID fromRaw(unsigned reg);
73 :
74 : inline JSC::MacroAssembler::RegisterID reg();
75 : inline JSC::MacroAssembler::FPRegisterID fpreg();
76 :
77 643661 : bool isSet() { return reg_ != unsigned(-1); }
78 1317806 : bool isReg() { return reg_ < JSC::MacroAssembler::TotalRegisters; }
79 342882 : bool isFPReg() { return isSet() && !isReg(); }
80 :
81 : inline const char * name();
82 :
83 : private:
84 2060672259 : unsigned * pin() {
85 : /*
86 : * Workaround for apparent compiler bug in GCC 4.2. If GCC thinks that reg_
87 : * cannot escape then it compiles isReg() and other accesses to reg_ incorrectly.
88 : */
89 : static unsigned *v;
90 2060672259 : v = ®_;
91 2060672259 : return v;
92 : }
93 : };
94 :
95 : struct Registers {
96 :
97 : /* General purpose registers. */
98 :
99 : static const uint32_t TotalRegisters = JSC::MacroAssembler::TotalRegisters;
100 :
101 : enum CallConvention {
102 : NormalCall,
103 : FastCall
104 : };
105 :
106 : typedef JSC::MacroAssembler::RegisterID RegisterID;
107 :
108 : // Homed and scratch registers for working with Values on x64.
109 : #if defined(JS_CPU_X64)
110 : static const RegisterID TypeMaskReg = JSC::X86Registers::r13;
111 : static const RegisterID PayloadMaskReg = JSC::X86Registers::r14;
112 : static const RegisterID ValueReg = JSC::X86Registers::r10;
113 : static const RegisterID ScratchReg = JSC::X86Registers::r11;
114 : #endif
115 :
116 : // Register that homes the current JSStackFrame.
117 : #if defined(JS_CPU_X86)
118 : static const RegisterID JSFrameReg = JSC::X86Registers::ebp;
119 : #elif defined(JS_CPU_X64)
120 : static const RegisterID JSFrameReg = JSC::X86Registers::ebx;
121 : #elif defined(JS_CPU_ARM)
122 : static const RegisterID JSFrameReg = JSC::ARMRegisters::r10;
123 : #elif defined(JS_CPU_SPARC)
124 : static const RegisterID JSFrameReg = JSC::SparcRegisters::l0;
125 : #elif defined(JS_CPU_MIPS)
126 : static const RegisterID JSFrameReg = JSC::MIPSRegisters::s0;
127 : #endif
128 :
129 : #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
130 : static const RegisterID ReturnReg = JSC::X86Registers::eax;
131 : # if defined(JS_CPU_X86) || defined(_WIN64)
132 : static const RegisterID ArgReg0 = JSC::X86Registers::ecx;
133 : static const RegisterID ArgReg1 = JSC::X86Registers::edx;
134 : # if defined(JS_CPU_X64)
135 : static const RegisterID ArgReg2 = JSC::X86Registers::r8;
136 : static const RegisterID ArgReg3 = JSC::X86Registers::r9;
137 : # endif
138 : # else
139 : static const RegisterID ArgReg0 = JSC::X86Registers::edi;
140 : static const RegisterID ArgReg1 = JSC::X86Registers::esi;
141 : static const RegisterID ArgReg2 = JSC::X86Registers::edx;
142 : static const RegisterID ArgReg3 = JSC::X86Registers::ecx;
143 : # endif
144 : #elif JS_CPU_ARM
145 : static const RegisterID ReturnReg = JSC::ARMRegisters::r0;
146 : static const RegisterID ArgReg0 = JSC::ARMRegisters::r0;
147 : static const RegisterID ArgReg1 = JSC::ARMRegisters::r1;
148 : static const RegisterID ArgReg2 = JSC::ARMRegisters::r2;
149 : #elif JS_CPU_SPARC
150 : static const RegisterID ReturnReg = JSC::SparcRegisters::o0;
151 : static const RegisterID ArgReg0 = JSC::SparcRegisters::o0;
152 : static const RegisterID ArgReg1 = JSC::SparcRegisters::o1;
153 : static const RegisterID ArgReg2 = JSC::SparcRegisters::o2;
154 : static const RegisterID ArgReg3 = JSC::SparcRegisters::o3;
155 : static const RegisterID ArgReg4 = JSC::SparcRegisters::o4;
156 : static const RegisterID ArgReg5 = JSC::SparcRegisters::o5;
157 : #elif JS_CPU_MIPS
158 : static const RegisterID ReturnReg = JSC::MIPSRegisters::v0;
159 : static const RegisterID ArgReg0 = JSC::MIPSRegisters::a0;
160 : static const RegisterID ArgReg1 = JSC::MIPSRegisters::a1;
161 : static const RegisterID ArgReg2 = JSC::MIPSRegisters::a2;
162 : static const RegisterID ArgReg3 = JSC::MIPSRegisters::a3;
163 : #endif
164 :
165 : static const RegisterID StackPointer = JSC::MacroAssembler::stackPointerRegister;
166 :
167 906698 : static inline uint32_t maskReg(RegisterID reg) {
168 906698 : return (1 << reg);
169 : }
170 :
171 0 : static inline uint32_t mask2Regs(RegisterID reg1, RegisterID reg2) {
172 0 : return maskReg(reg1) | maskReg(reg2);
173 : }
174 :
175 : static inline uint32_t mask3Regs(RegisterID reg1, RegisterID reg2, RegisterID reg3) {
176 : return maskReg(reg1) | maskReg(reg2) | maskReg(reg3);
177 : }
178 :
179 : #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
180 : static const uint32_t TempRegs =
181 : (1 << JSC::X86Registers::eax)
182 : # if defined(JS_CPU_X86)
183 : | (1 << JSC::X86Registers::ebx)
184 : # endif
185 : | (1 << JSC::X86Registers::ecx)
186 : | (1 << JSC::X86Registers::edx)
187 : # if defined(JS_CPU_X64)
188 : | (1 << JSC::X86Registers::r8)
189 : | (1 << JSC::X86Registers::r9)
190 : # if !defined(_WIN64)
191 : | (1 << JSC::X86Registers::esi)
192 : | (1 << JSC::X86Registers::edi)
193 : # endif
194 : # endif
195 : ;
196 :
197 : # if defined(JS_CPU_X64)
198 : static const uint32_t SavedRegs =
199 : /* r11 is scratchRegister, used by JSC. */
200 : (1 << JSC::X86Registers::r12)
201 : // r13 is TypeMaskReg.
202 : // r14 is PayloadMaskReg.
203 : | (1 << JSC::X86Registers::r15)
204 : # if defined(_WIN64)
205 : | (1 << JSC::X86Registers::esi)
206 : | (1 << JSC::X86Registers::edi)
207 : # endif
208 : # else
209 : static const uint32_t SavedRegs =
210 : (1 << JSC::X86Registers::esi)
211 : | (1 << JSC::X86Registers::edi)
212 : # endif
213 : ;
214 :
215 : # if defined(JS_CPU_X86)
216 : static const uint32_t SingleByteRegs = (TempRegs | SavedRegs) &
217 : ~((1 << JSC::X86Registers::esi) |
218 : (1 << JSC::X86Registers::edi) |
219 : (1 << JSC::X86Registers::ebp) |
220 : (1 << JSC::X86Registers::esp));
221 : # elif defined(JS_CPU_X64)
222 : static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
223 : # endif
224 :
225 : #elif defined(JS_CPU_ARM)
226 : static const uint32_t TempRegs =
227 : (1 << JSC::ARMRegisters::r0)
228 : | (1 << JSC::ARMRegisters::r1)
229 : | (1 << JSC::ARMRegisters::r2);
230 : // r3 is reserved as a scratch register for the assembler.
231 : // r12 is IP, and is used for stub calls.
232 :
233 : static const uint32_t SavedRegs =
234 : (1 << JSC::ARMRegisters::r4)
235 : | (1 << JSC::ARMRegisters::r5)
236 : | (1 << JSC::ARMRegisters::r6)
237 : | (1 << JSC::ARMRegisters::r7)
238 : // r8 is reserved as a scratch register for the assembler.
239 : | (1 << JSC::ARMRegisters::r9);
240 : // r10 is reserved for JSFrameReg.
241 : // r13 is SP and must always point to VMFrame whilst in generated code.
242 : // r14 is LR and is used for return sequences.
243 : // r15 is PC (program counter).
244 :
245 : static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
246 : #elif defined(JS_CPU_SPARC)
247 : static const uint32_t TempRegs =
248 : (1 << JSC::SparcRegisters::o0)
249 : | (1 << JSC::SparcRegisters::o1)
250 : | (1 << JSC::SparcRegisters::o2)
251 : | (1 << JSC::SparcRegisters::o3)
252 : | (1 << JSC::SparcRegisters::o4)
253 : | (1 << JSC::SparcRegisters::o5);
254 :
255 : static const uint32_t SavedRegs =
256 : (1 << JSC::SparcRegisters::l2)
257 : | (1 << JSC::SparcRegisters::l3)
258 : | (1 << JSC::SparcRegisters::l4)
259 : | (1 << JSC::SparcRegisters::l5)
260 : | (1 << JSC::SparcRegisters::l6)
261 : | (1 << JSC::SparcRegisters::l7);
262 :
263 : static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
264 : #elif defined(JS_CPU_MIPS)
265 : static const uint32_t TempRegs =
266 : (1 << JSC::MIPSRegisters::at)
267 : | (1 << JSC::MIPSRegisters::v0)
268 : | (1 << JSC::MIPSRegisters::v1)
269 : | (1 << JSC::MIPSRegisters::a0)
270 : | (1 << JSC::MIPSRegisters::a1)
271 : | (1 << JSC::MIPSRegisters::a2)
272 : | (1 << JSC::MIPSRegisters::a3)
273 : | (1 << JSC::MIPSRegisters::t5)
274 : | (1 << JSC::MIPSRegisters::t6)
275 : | (1 << JSC::MIPSRegisters::t7);
276 : /* t0-t4,t9 is reserved as a scratch register for the assembler.
277 : We don't use t8 ($24), as we limit ourselves within $0 to $23 to
278 : leave the bitmask for 8 FP registers. */
279 :
280 : static const uint32_t SavedRegs =
281 : (1 << JSC::MIPSRegisters::s1)
282 : | (1 << JSC::MIPSRegisters::s2)
283 : | (1 << JSC::MIPSRegisters::s3)
284 : | (1 << JSC::MIPSRegisters::s4)
285 : | (1 << JSC::MIPSRegisters::s5)
286 : | (1 << JSC::MIPSRegisters::s6)
287 : | (1 << JSC::MIPSRegisters::s7);
288 : // s0 is reserved for JSFrameReg.
289 :
290 : static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
291 : #else
292 : # error "Unsupported platform"
293 : #endif
294 :
295 : static const uint32_t AvailRegs = SavedRegs | TempRegs;
296 :
297 : static bool isAvail(RegisterID reg) {
298 : uint32_t mask = maskReg(reg);
299 : return bool(mask & AvailRegs);
300 : }
301 :
302 1670 : static bool isSaved(RegisterID reg) {
303 1670 : uint32_t mask = maskReg(reg);
304 1670 : JS_ASSERT(mask & AvailRegs);
305 1670 : return bool(mask & SavedRegs);
306 : }
307 :
308 14753743 : static inline uint32_t numArgRegs(CallConvention convention) {
309 : #if defined(JS_CPU_X86)
310 : # if defined(JS_NO_FASTCALL)
311 : return 0;
312 : # else
313 14753743 : return (convention == FastCall) ? 2 : 0;
314 : # endif
315 : #elif defined(JS_CPU_X64)
316 : # ifdef _WIN64
317 : return 4;
318 : # else
319 : return 6;
320 : # endif
321 : #elif defined(JS_CPU_ARM)
322 : return 4;
323 : #elif defined(JS_CPU_SPARC)
324 : return 6;
325 : #elif defined(JS_CPU_MIPS)
326 : return 4;
327 : #endif
328 : }
329 :
330 9848128 : static inline bool regForArg(CallConvention conv, uint32_t i, RegisterID *reg) {
331 : #if defined(JS_CPU_X86)
332 : static const RegisterID regs[] = {
333 : JSC::X86Registers::ecx,
334 : JSC::X86Registers::edx
335 : };
336 :
337 : # if defined(JS_NO_FASTCALL)
338 : return false;
339 : # else
340 9848128 : if (conv == NormalCall)
341 107940 : return false;
342 : # endif
343 : #elif defined(JS_CPU_X64)
344 : # ifdef _WIN64
345 : static const RegisterID regs[] = {
346 : JSC::X86Registers::ecx,
347 : JSC::X86Registers::edx,
348 : JSC::X86Registers::r8,
349 : JSC::X86Registers::r9
350 : };
351 : # else
352 : static const RegisterID regs[] = {
353 : JSC::X86Registers::edi,
354 : JSC::X86Registers::esi,
355 : JSC::X86Registers::edx,
356 : JSC::X86Registers::ecx,
357 : JSC::X86Registers::r8,
358 : JSC::X86Registers::r9
359 : };
360 : # endif
361 : #elif defined(JS_CPU_ARM)
362 : static const RegisterID regs[] = {
363 : JSC::ARMRegisters::r0,
364 : JSC::ARMRegisters::r1,
365 : JSC::ARMRegisters::r2,
366 : JSC::ARMRegisters::r3
367 : };
368 : #elif defined(JS_CPU_SPARC)
369 : static const RegisterID regs[] = {
370 : JSC::SparcRegisters::o0,
371 : JSC::SparcRegisters::o1,
372 : JSC::SparcRegisters::o2,
373 : JSC::SparcRegisters::o3,
374 : JSC::SparcRegisters::o4,
375 : JSC::SparcRegisters::o5
376 : };
377 : #elif defined(JS_CPU_MIPS)
378 : static const RegisterID regs[] = {
379 : JSC::MIPSRegisters::a0,
380 : JSC::MIPSRegisters::a1,
381 : JSC::MIPSRegisters::a2,
382 : JSC::MIPSRegisters::a3,
383 : };
384 : #endif
385 9740188 : JS_ASSERT(numArgRegs(conv) == mozilla::ArrayLength(regs));
386 9740188 : if (i > mozilla::ArrayLength(regs))
387 0 : return false;
388 9740188 : *reg = regs[i];
389 9740188 : return true;
390 : }
391 :
392 : /* Floating point registers. */
393 :
394 : typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
395 :
396 : #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
397 : #ifdef _WIN64
398 : /* xmm0-xmm5 are scratch register on Win64 ABI */
399 : static const uint32_t TotalFPRegisters = 5;
400 : static const FPRegisterID FPConversionTemp = JSC::X86Registers::xmm5;
401 : #else
402 : static const uint32_t TotalFPRegisters = 7;
403 : static const FPRegisterID FPConversionTemp = JSC::X86Registers::xmm7;
404 : #endif
405 : static const uint32_t TempFPRegs = (
406 : (1 << JSC::X86Registers::xmm0)
407 : | (1 << JSC::X86Registers::xmm1)
408 : | (1 << JSC::X86Registers::xmm2)
409 : | (1 << JSC::X86Registers::xmm3)
410 : | (1 << JSC::X86Registers::xmm4)
411 : #ifndef _WIN64
412 : | (1 << JSC::X86Registers::xmm5)
413 : | (1 << JSC::X86Registers::xmm6)
414 : #endif
415 : ) << TotalRegisters;
416 : #elif defined(JS_CPU_ARM)
417 : static const uint32_t TotalFPRegisters = 3;
418 : static const uint32_t TempFPRegs = (
419 : (1 << JSC::ARMRegisters::d0)
420 : | (1 << JSC::ARMRegisters::d1)
421 : | (1 << JSC::ARMRegisters::d2)
422 : ) << TotalRegisters;
423 : static const FPRegisterID FPConversionTemp = JSC::ARMRegisters::d3;
424 : #elif defined(JS_CPU_SPARC)
425 : static const uint32_t TotalFPRegisters = 8;
426 : static const uint32_t TempFPRegs = (uint32_t)(
427 : (1 << JSC::SparcRegisters::f0)
428 : | (1 << JSC::SparcRegisters::f2)
429 : | (1 << JSC::SparcRegisters::f4)
430 : | (1 << JSC::SparcRegisters::f6)
431 : ) << TotalRegisters;
432 : static const FPRegisterID FPConversionTemp = JSC::SparcRegisters::f8;
433 : #elif defined(JS_CPU_MIPS)
434 : /* TotalRegisters is 24, so TotalFPRegisters can be 8 to have a 32-bit
435 : bit mask.
436 : Note that the O32 ABI can access only even FP registers. */
437 : static const uint32_t TotalFPRegisters = 8;
438 : static const uint32_t TempFPRegs = (uint32_t)(
439 : (1 << JSC::MIPSRegisters::f0)
440 : | (1 << JSC::MIPSRegisters::f2)
441 : | (1 << JSC::MIPSRegisters::f4)
442 : | (1 << JSC::MIPSRegisters::f6)
443 : ) << TotalRegisters;
444 : // f16 is reserved as a scratch register for the assembler.
445 : static const FPRegisterID FPConversionTemp = JSC::MIPSRegisters::f18;
446 : #else
447 : # error "Unsupported platform"
448 : #endif
449 :
450 : /* Temp reg that can be clobbered when setting up a fallible fast or ABI call. */
451 : #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
452 : static const RegisterID ClobberInCall = JSC::X86Registers::ecx;
453 : #elif defined(JS_CPU_ARM)
454 : static const RegisterID ClobberInCall = JSC::ARMRegisters::r2;
455 : #elif defined(JS_CPU_SPARC)
456 : static const RegisterID ClobberInCall = JSC::SparcRegisters::l1;
457 : #elif defined(JS_CPU_MIPS)
458 : static const RegisterID ClobberInCall = JSC::MIPSRegisters::at;
459 : #endif
460 :
461 : static const uint32_t AvailFPRegs = TempFPRegs;
462 :
463 : static inline uint32_t maskReg(FPRegisterID reg) {
464 : return (1 << reg) << TotalRegisters;
465 : }
466 :
467 : /* Common code. */
468 :
469 : static const uint32_t TotalAnyRegisters = TotalRegisters + TotalFPRegisters;
470 : static const uint32_t TempAnyRegs = TempRegs | TempFPRegs;
471 : static const uint32_t AvailAnyRegs = AvailRegs | AvailFPRegs;
472 :
473 4444050 : static inline uint32_t maskReg(AnyRegisterID reg) {
474 4444050 : return (1 << reg.reg_);
475 : }
476 :
477 : /* Get a register which is not live before a FASTCALL. */
478 4765013 : static inline RegisterID tempCallReg() {
479 4765013 : Registers regs(TempRegs);
480 4765013 : regs.takeReg(Registers::ArgReg0);
481 4765013 : regs.takeReg(Registers::ArgReg1);
482 4765013 : return regs.takeAnyReg().reg();
483 : }
484 :
485 : /* Get a register which is not live before a normal ABI call with at most four args. */
486 35521 : static inline Registers tempCallRegMask() {
487 35521 : Registers regs(AvailRegs);
488 : #ifndef JS_CPU_X86
489 : regs.takeReg(ArgReg0);
490 : regs.takeReg(ArgReg1);
491 : regs.takeReg(ArgReg2);
492 : #if defined(JS_CPU_SPARC) || defined(JS_CPU_X64)
493 : regs.takeReg(ArgReg3);
494 : #endif
495 : #endif
496 : return regs;
497 : }
498 :
499 51805399 : Registers(uint32_t freeMask)
500 51805399 : : freeMask(freeMask)
501 51805399 : { }
502 :
503 1870165 : Registers(const Registers &other)
504 1870165 : : freeMask(other.freeMask)
505 1870165 : { }
506 :
507 8202707 : Registers & operator =(const Registers &other)
508 : {
509 8202707 : freeMask = other.freeMask;
510 8202707 : return *this;
511 : }
512 :
513 100742101 : bool empty(uint32_t mask) const {
514 100742101 : return !(freeMask & mask);
515 : }
516 :
517 82493417 : bool empty() const {
518 82493417 : return !freeMask;
519 : }
520 :
521 90262055 : AnyRegisterID peekReg(uint32_t mask) {
522 90262055 : JS_ASSERT(!empty(mask));
523 : unsigned ireg;
524 90262055 : JS_FLOOR_LOG2(ireg, freeMask & mask);
525 90262055 : return AnyRegisterID::fromRaw(ireg);
526 : }
527 :
528 : AnyRegisterID peekReg() {
529 : return peekReg(freeMask);
530 : }
531 :
532 85984861 : AnyRegisterID takeAnyReg(uint32_t mask) {
533 85984861 : AnyRegisterID reg = peekReg(mask);
534 85984861 : takeReg(reg);
535 : return reg;
536 : }
537 :
538 78393971 : AnyRegisterID takeAnyReg() {
539 78393971 : return takeAnyReg(freeMask);
540 : }
541 :
542 194754032 : bool hasReg(AnyRegisterID reg) const {
543 194754032 : return !!(freeMask & (1 << reg.reg_));
544 : }
545 :
546 6045981 : bool hasRegInMask(uint32_t mask) const {
547 6045981 : return !!(freeMask & mask);
548 : }
549 :
550 : bool hasAllRegs(uint32_t mask) const {
551 : return (freeMask & mask) == mask;
552 : }
553 :
554 17207283 : void putRegUnchecked(AnyRegisterID reg) {
555 17207283 : freeMask |= (1 << reg.reg_);
556 17207283 : }
557 :
558 17207283 : void putReg(AnyRegisterID reg) {
559 17207283 : JS_ASSERT(!hasReg(reg));
560 17207283 : putRegUnchecked(reg);
561 17207283 : }
562 :
563 132498186 : void takeReg(AnyRegisterID reg) {
564 132498186 : JS_ASSERT(hasReg(reg));
565 132498186 : takeRegUnchecked(reg);
566 132498186 : }
567 :
568 142238374 : void takeRegUnchecked(AnyRegisterID reg) {
569 142238374 : freeMask &= ~(1 << reg.reg_);
570 142238374 : }
571 :
572 17343229 : bool operator ==(const Registers &other) {
573 17343229 : return freeMask == other.freeMask;
574 : }
575 :
576 : uint32_t freeMask;
577 : };
578 :
579 : static const JSC::MacroAssembler::RegisterID JSFrameReg = Registers::JSFrameReg;
580 :
581 : AnyRegisterID
582 107930825 : AnyRegisterID::fromRaw(unsigned reg_)
583 : {
584 107930825 : JS_ASSERT(reg_ < Registers::TotalAnyRegisters);
585 107930825 : AnyRegisterID reg;
586 107930825 : reg.reg_ = reg_;
587 : return reg;
588 : }
589 :
590 : JSC::MacroAssembler::RegisterID
591 26027638 : AnyRegisterID::reg()
592 : {
593 26027638 : JS_ASSERT(reg_ < Registers::TotalRegisters);
594 26027638 : return (JSC::MacroAssembler::RegisterID) reg_;
595 : }
596 :
597 : JSC::MacroAssembler::FPRegisterID
598 1407011 : AnyRegisterID::fpreg()
599 : {
600 0 : JS_ASSERT(reg_ >= Registers::TotalRegisters &&
601 1407011 : reg_ < Registers::TotalAnyRegisters);
602 1407011 : return (JSC::MacroAssembler::FPRegisterID) (reg_ - Registers::TotalRegisters);
603 : }
604 :
605 : const char *
606 611996 : AnyRegisterID::name()
607 : {
608 : #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
609 611996 : return isReg() ? JSC::X86Registers::nameIReg(reg()) : JSC::X86Registers::nameFPReg(fpreg());
610 : #elif defined(JS_CPU_ARM)
611 : return isReg() ? JSC::ARMAssembler::nameGpReg(reg()) : JSC::ARMAssembler::nameFpRegD(fpreg());
612 : #else
613 : return "???";
614 : #endif
615 : }
616 :
617 : } /* namespace mjit */
618 :
619 : } /* namespace js */
620 :
621 : #endif /* jsjaeger_regstate_h__ */
622 :
|