2 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "MacroAssembler.h"
30 #include <wtf/PrintStream.h>
34 enum NoResultTag { NoResult };
36 // We use the same conventions in the basline JIT as in the LLint. If you
37 // change mappings in the GPRInfo, you should change them in the offlineasm
38 // compiler adequately. The register naming conventions are described at the
39 // top of the LowLevelInterpreter.asm file.
41 typedef MacroAssembler::RegisterID GPRReg;
42 #define InvalidGPRReg ((::JSC::GPRReg)-1)
50 : m_gpr(InvalidGPRReg)
54 explicit JSValueRegs(GPRReg gpr)
59 static JSValueRegs payloadOnly(GPRReg gpr)
61 return JSValueRegs(gpr);
64 static JSValueRegs withTwoAvailableRegs(GPRReg gpr, GPRReg)
66 return JSValueRegs(gpr);
69 bool operator!() const { return m_gpr == InvalidGPRReg; }
70 explicit operator bool() const { return m_gpr != InvalidGPRReg; }
72 bool operator==(JSValueRegs other) { return m_gpr == other.m_gpr; }
73 bool operator!=(JSValueRegs other) { return !(*this == other); }
75 GPRReg gpr() const { return m_gpr; }
76 GPRReg tagGPR() const { return InvalidGPRReg; }
77 GPRReg payloadGPR() const { return m_gpr; }
79 bool uses(GPRReg gpr) const { return m_gpr == gpr; }
81 void dump(PrintStream&) const;
90 : m_offset(notAddress())
91 , m_base(InvalidGPRReg)
95 JSValueSource(JSValueRegs regs)
96 : m_offset(notAddress())
101 explicit JSValueSource(GPRReg gpr)
102 : m_offset(notAddress())
107 JSValueSource(MacroAssembler::Address address)
108 : m_offset(address.offset)
109 , m_base(address.base)
111 ASSERT(m_offset != notAddress());
112 ASSERT(m_base != InvalidGPRReg);
115 static JSValueSource unboxedCell(GPRReg payloadGPR)
117 return JSValueSource(payloadGPR);
120 bool operator!() const { return m_base == InvalidGPRReg; }
121 explicit operator bool() const { return m_base != InvalidGPRReg; }
123 bool isAddress() const { return m_offset != notAddress(); }
125 int32_t offset() const
139 ASSERT(!isAddress());
143 JSValueRegs regs() const
145 return JSValueRegs(gpr());
148 MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); }
151 static inline int32_t notAddress() { return 0x80000000; }
156 #endif // USE(JSVALUE64)
158 #if USE(JSVALUE32_64)
162 : m_tagGPR(static_cast<int8_t>(InvalidGPRReg))
163 , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg))
167 JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
169 , m_payloadGPR(payloadGPR)
173 static JSValueRegs withTwoAvailableRegs(GPRReg gpr1, GPRReg gpr2)
175 return JSValueRegs(gpr1, gpr2);
178 static JSValueRegs payloadOnly(GPRReg gpr)
180 return JSValueRegs(InvalidGPRReg, gpr);
183 bool operator!() const { return !static_cast<bool>(*this); }
184 explicit operator bool() const
186 return static_cast<GPRReg>(m_tagGPR) != InvalidGPRReg
187 || static_cast<GPRReg>(m_payloadGPR) != InvalidGPRReg;
190 bool operator==(JSValueRegs other) const
192 return m_tagGPR == other.m_tagGPR
193 && m_payloadGPR == other.m_payloadGPR;
195 bool operator!=(JSValueRegs other) const { return !(*this == other); }
197 GPRReg tagGPR() const { return static_cast<GPRReg>(m_tagGPR); }
198 GPRReg payloadGPR() const { return static_cast<GPRReg>(m_payloadGPR); }
199 GPRReg gpr(WhichValueWord which) const
207 ASSERT_NOT_REACHED();
211 bool uses(GPRReg gpr) const { return m_tagGPR == gpr || m_payloadGPR == gpr; }
213 void dump(PrintStream&) const;
220 class JSValueSource {
223 : m_offset(notAddress())
224 , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg))
225 , m_payload(static_cast<int8_t>(InvalidGPRReg))
230 JSValueSource(JSValueRegs regs)
231 : m_offset(notAddress())
232 , m_baseOrTag(regs.tagGPR())
233 , m_payload(regs.payloadGPR())
238 JSValueSource(GPRReg tagGPR, GPRReg payloadGPR)
239 : m_offset(notAddress())
240 , m_baseOrTag(static_cast<int8_t>(tagGPR))
241 , m_payload(static_cast<int8_t>(payloadGPR))
246 JSValueSource(MacroAssembler::Address address)
247 : m_offset(address.offset)
248 , m_baseOrTag(static_cast<int8_t>(address.base))
249 , m_payload(static_cast<int8_t>(InvalidGPRReg))
252 ASSERT(m_offset != notAddress());
253 ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
256 static JSValueSource unboxedCell(GPRReg payloadGPR)
258 JSValueSource result;
259 result.m_offset = notAddress();
260 result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg);
261 result.m_payload = static_cast<int8_t>(payloadGPR);
262 result.m_tagType = static_cast<int8_t>(JSValue::CellTag);
266 bool operator!() const { return !static_cast<bool>(*this); }
267 explicit operator bool() const
269 return static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg
270 || static_cast<GPRReg>(m_payload) != InvalidGPRReg;
273 bool isAddress() const
276 return m_offset != notAddress();
279 int32_t offset() const
288 return static_cast<GPRReg>(m_baseOrTag);
291 GPRReg tagGPR() const
293 ASSERT(!isAddress() && static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
294 return static_cast<GPRReg>(m_baseOrTag);
297 GPRReg payloadGPR() const
299 ASSERT(!isAddress());
300 return static_cast<GPRReg>(m_payload);
303 bool hasKnownTag() const
306 ASSERT(!isAddress());
307 return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg;
312 return static_cast<int32_t>(m_tagType);
315 JSValueRegs regs() const
317 return JSValueRegs(tagGPR(), payloadGPR());
320 MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
323 static inline int32_t notAddress() { return 0x80000000; }
328 int8_t m_tagType; // Contains the low bits of the tag.
330 #endif // USE(JSVALUE32_64)
333 #define NUMBER_OF_ARGUMENT_REGISTERS 0u
334 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
338 typedef GPRReg RegisterType;
339 static const unsigned numberOfRegisters = 6;
340 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
342 // Temporary registers.
343 static const GPRReg regT0 = X86Registers::eax;
344 static const GPRReg regT1 = X86Registers::edx;
345 static const GPRReg regT2 = X86Registers::ecx;
346 static const GPRReg regT3 = X86Registers::ebx; // Callee-save
347 static const GPRReg regT4 = X86Registers::esi; // Callee-save
348 static const GPRReg regT5 = X86Registers::edi; // Callee-save
349 static const GPRReg callFrameRegister = X86Registers::ebp;
350 // These constants provide the names for the general purpose argument & return value registers.
351 static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
352 static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
353 static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
354 static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
355 static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
356 static const GPRReg returnValueGPR = X86Registers::eax; // regT0
357 static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
358 static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
360 static GPRReg toRegister(unsigned index)
362 ASSERT(index < numberOfRegisters);
363 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 };
364 return registerForIndex[index];
367 static GPRReg toArgumentRegister(unsigned)
369 UNREACHABLE_FOR_PLATFORM();
370 return InvalidGPRReg;
373 static unsigned toIndex(GPRReg reg)
375 ASSERT(reg != InvalidGPRReg);
376 ASSERT(static_cast<int>(reg) < 8);
377 static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, 5 };
378 unsigned result = indexForRegister[reg];
382 static const char* debugName(GPRReg reg)
384 ASSERT(reg != InvalidGPRReg);
385 return MacroAssembler::gprName(reg);
388 static const unsigned InvalidIndex = 0xffffffff;
395 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
396 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
398 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
399 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
404 typedef GPRReg RegisterType;
405 static const unsigned numberOfRegisters = 11;
406 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
408 // These registers match the baseline JIT.
409 static const GPRReg callFrameRegister = X86Registers::ebp;
410 static const GPRReg tagTypeNumberRegister = X86Registers::r14;
411 static const GPRReg tagMaskRegister = X86Registers::r15;
413 // Temporary registers.
414 static const GPRReg regT0 = X86Registers::eax;
416 static const GPRReg regT1 = X86Registers::esi;
417 static const GPRReg regT2 = X86Registers::edx;
418 static const GPRReg regT3 = X86Registers::ecx;
419 static const GPRReg regT4 = X86Registers::r8;
420 static const GPRReg regT5 = X86Registers::r10;
421 static const GPRReg regT6 = X86Registers::edi;
422 static const GPRReg regT7 = X86Registers::r9;
424 static const GPRReg regT1 = X86Registers::edx;
425 static const GPRReg regT2 = X86Registers::r8;
426 static const GPRReg regT3 = X86Registers::r9;
427 static const GPRReg regT4 = X86Registers::r10;
428 static const GPRReg regT5 = X86Registers::ecx;
431 static const GPRReg regCS0 = X86Registers::ebx;
434 static const GPRReg regCS1 = X86Registers::r12;
435 static const GPRReg regCS2 = X86Registers::r13;
436 static const GPRReg regCS3 = X86Registers::r14;
437 static const GPRReg regCS4 = X86Registers::r15;
439 static const GPRReg regCS1 = X86Registers::esi;
440 static const GPRReg regCS2 = X86Registers::edi;
441 static const GPRReg regCS3 = X86Registers::r12;
442 static const GPRReg regCS4 = X86Registers::r13;
443 static const GPRReg regCS5 = X86Registers::r14;
444 static const GPRReg regCS6 = X86Registers::r15;
447 // These constants provide the names for the general purpose argument & return value registers.
449 static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
450 static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
451 static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
452 static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
453 static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
454 static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
456 static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
457 static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
458 static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
459 static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
461 static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
462 static const GPRReg returnValueGPR = X86Registers::eax; // regT0
463 static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
464 static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
465 static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
467 // FIXME: I believe that all uses of this are dead in the sense that it just causes the scratch
468 // register allocator to select a different register and potentially spill things. It would be better
469 // if we instead had a more explicit way of saying that we don't have a scratch register.
470 static const GPRReg patchpointScratchRegister;
472 static GPRReg toRegister(unsigned index)
474 ASSERT(index < numberOfRegisters);
476 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
478 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
480 return registerForIndex[index];
483 static GPRReg toArgumentRegister(unsigned index)
485 ASSERT(index < numberOfArgumentRegisters);
487 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 };
489 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
491 return registerForIndex[index];
494 static unsigned toIndex(GPRReg reg)
496 ASSERT(reg != InvalidGPRReg);
497 ASSERT(static_cast<int>(reg) < 16);
499 static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
501 static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
503 return indexForRegister[reg];
506 static const char* debugName(GPRReg reg)
508 ASSERT(reg != InvalidGPRReg);
509 return MacroAssembler::gprName(reg);
512 static const std::array<GPRReg, 3>& reservedRegisters()
514 static const std::array<GPRReg, 3> reservedRegisters { {
515 MacroAssembler::s_scratchRegister,
516 tagTypeNumberRegister,
519 return reservedRegisters;
522 static const unsigned InvalidIndex = 0xffffffff;
525 #endif // CPU(X86_64)
528 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
529 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
533 typedef GPRReg RegisterType;
534 static const unsigned numberOfRegisters = 9;
535 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
537 // Temporary registers.
538 static const GPRReg regT0 = ARMRegisters::r0;
539 static const GPRReg regT1 = ARMRegisters::r1;
540 static const GPRReg regT2 = ARMRegisters::r2;
541 static const GPRReg regT3 = ARMRegisters::r3;
542 static const GPRReg regT4 = ARMRegisters::r8;
543 static const GPRReg regT5 = ARMRegisters::r9;
544 static const GPRReg regT6 = ARMRegisters::r10;
546 static const GPRReg regT7 = ARMRegisters::r11;
548 static const GPRReg regT7 = ARMRegisters::r7;
550 static const GPRReg regT8 = ARMRegisters::r4;
551 // These registers match the baseline JIT.
552 static const GPRReg callFrameRegister = ARMRegisters::fp;
553 // These constants provide the names for the general purpose argument & return value registers.
554 static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
555 static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
556 static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
557 static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
558 static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
559 static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
560 static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
561 static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
562 static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
564 static GPRReg toRegister(unsigned index)
566 ASSERT(index < numberOfRegisters);
567 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
568 return registerForIndex[index];
571 static GPRReg toArgumentRegister(unsigned index)
573 ASSERT(index < numberOfArgumentRegisters);
574 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
575 return registerForIndex[index];
578 static unsigned toIndex(GPRReg reg)
580 ASSERT(reg != InvalidGPRReg);
581 ASSERT(static_cast<int>(reg) < 16);
582 static const unsigned indexForRegister[16] =
584 { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
586 { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
588 unsigned result = indexForRegister[reg];
592 static const char* debugName(GPRReg reg)
594 ASSERT(reg != InvalidGPRReg);
595 return MacroAssembler::gprName(reg);
598 static const unsigned InvalidIndex = 0xffffffff;
604 #define NUMBER_OF_ARGUMENT_REGISTERS 8u
605 // Callee Saves includes x19..x28 and FP registers q8..q15
606 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
610 typedef GPRReg RegisterType;
611 static const unsigned numberOfRegisters = 16;
612 static const unsigned numberOfArgumentRegisters = 8;
614 // These registers match the baseline JIT.
615 static const GPRReg callFrameRegister = ARM64Registers::fp;
616 static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
617 static const GPRReg tagMaskRegister = ARM64Registers::x28;
618 static const GPRReg dataTempRegister = MacroAssembler::dataTempRegister;
619 static const GPRReg memoryTempRegister = MacroAssembler::memoryTempRegister;
620 // Temporary registers.
621 static const GPRReg regT0 = ARM64Registers::x0;
622 static const GPRReg regT1 = ARM64Registers::x1;
623 static const GPRReg regT2 = ARM64Registers::x2;
624 static const GPRReg regT3 = ARM64Registers::x3;
625 static const GPRReg regT4 = ARM64Registers::x4;
626 static const GPRReg regT5 = ARM64Registers::x5;
627 static const GPRReg regT6 = ARM64Registers::x6;
628 static const GPRReg regT7 = ARM64Registers::x7;
629 static const GPRReg regT8 = ARM64Registers::x8;
630 static const GPRReg regT9 = ARM64Registers::x9;
631 static const GPRReg regT10 = ARM64Registers::x10;
632 static const GPRReg regT11 = ARM64Registers::x11;
633 static const GPRReg regT12 = ARM64Registers::x12;
634 static const GPRReg regT13 = ARM64Registers::x13;
635 static const GPRReg regT14 = ARM64Registers::x14;
636 static const GPRReg regT15 = ARM64Registers::x15;
637 static const GPRReg regCS0 = ARM64Registers::x19; // Used by FTL only
638 static const GPRReg regCS1 = ARM64Registers::x20; // Used by FTL only
639 static const GPRReg regCS2 = ARM64Registers::x21; // Used by FTL only
640 static const GPRReg regCS3 = ARM64Registers::x22; // Used by FTL only
641 static const GPRReg regCS4 = ARM64Registers::x23; // Used by FTL only
642 static const GPRReg regCS5 = ARM64Registers::x24; // Used by FTL only
643 static const GPRReg regCS6 = ARM64Registers::x25; // Used by FTL only
644 static const GPRReg regCS7 = ARM64Registers::x26;
645 static const GPRReg regCS8 = ARM64Registers::x27; // tagTypeNumber
646 static const GPRReg regCS9 = ARM64Registers::x28; // tagMask
647 // These constants provide the names for the general purpose argument & return value registers.
648 static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
649 static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
650 static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
651 static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
652 static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
653 static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
654 static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
655 static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
656 static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
657 static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
658 static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
659 static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
660 static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
661 static const GPRReg nonPreservedNonArgumentGPR = ARM64Registers::x8;
662 static const GPRReg patchpointScratchRegister;
664 // GPRReg mapping is direct, the machine register numbers can
665 // be used directly as indices into the GPR RegisterBank.
666 COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
667 COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
668 COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
669 COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
670 COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
671 COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
672 COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
673 COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
674 COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
675 COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
676 COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
677 COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
678 COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
679 COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
680 COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
681 COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
682 static GPRReg toRegister(unsigned index)
684 return (GPRReg)index;
686 static unsigned toIndex(GPRReg reg)
690 return (unsigned)reg;
693 static GPRReg toArgumentRegister(unsigned index)
695 ASSERT(index < numberOfArgumentRegisters);
696 return toRegister(index);
699 static const char* debugName(GPRReg reg)
701 ASSERT(reg != InvalidGPRReg);
702 return MacroAssembler::gprName(reg);
705 static const std::array<GPRReg, 4>& reservedRegisters()
707 static const std::array<GPRReg, 4> reservedRegisters { {
710 tagTypeNumberRegister,
713 return reservedRegisters;
716 static const unsigned InvalidIndex = 0xffffffff;
722 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
723 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
727 typedef GPRReg RegisterType;
728 static const unsigned numberOfRegisters = 7;
729 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
731 // regT0 must be v0 for returning a 32-bit value.
732 // regT1 must be v1 for returning a pair of 32-bit value.
734 // Temporary registers.
735 static const GPRReg regT0 = MIPSRegisters::v0;
736 static const GPRReg regT1 = MIPSRegisters::v1;
737 static const GPRReg regT2 = MIPSRegisters::t2;
738 static const GPRReg regT3 = MIPSRegisters::t3;
739 static const GPRReg regT4 = MIPSRegisters::t4;
740 static const GPRReg regT5 = MIPSRegisters::t5;
741 static const GPRReg regT6 = MIPSRegisters::t6;
742 // These registers match the baseline JIT.
743 static const GPRReg callFrameRegister = MIPSRegisters::fp;
744 // These constants provide the names for the general purpose argument & return value registers.
745 static const GPRReg argumentGPR0 = MIPSRegisters::a0;
746 static const GPRReg argumentGPR1 = MIPSRegisters::a1;
747 static const GPRReg argumentGPR2 = MIPSRegisters::a2;
748 static const GPRReg argumentGPR3 = MIPSRegisters::a3;
749 static const GPRReg nonArgGPR0 = regT4;
750 static const GPRReg returnValueGPR = regT0;
751 static const GPRReg returnValueGPR2 = regT1;
752 static const GPRReg nonPreservedNonReturnGPR = regT2;
754 static GPRReg toRegister(unsigned index)
756 ASSERT(index < numberOfRegisters);
757 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
758 return registerForIndex[index];
761 static GPRReg toArgumentRegister(unsigned index)
763 ASSERT(index < numberOfArgumentRegisters);
764 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
765 return registerForIndex[index];
768 static unsigned toIndex(GPRReg reg)
770 ASSERT(reg != InvalidGPRReg);
772 static const unsigned indexForRegister[32] = {
773 InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
774 InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
775 InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
776 InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
778 unsigned result = indexForRegister[reg];
782 static const char* debugName(GPRReg reg)
784 ASSERT(reg != InvalidGPRReg);
785 return MacroAssembler::gprName(reg);
788 static const unsigned InvalidIndex = 0xffffffff;
793 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
794 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
795 // passing results of one opcode to the next. Hence:
796 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
797 #if USE(JSVALUE32_64)
798 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
801 inline GPRReg extractResult(GPRReg result) { return result; }
803 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
805 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
807 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
809 #endif // ENABLE(JIT)
815 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
818 out.print("%", JSC::GPRInfo::debugName(reg));
820 out.printf("%%r%d", reg);