2 * Copyright (C) 2011, 2013-2016 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) const { return m_gpr == other.m_gpr; }
73 bool operator!=(JSValueRegs other) const { 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_JS_FUNCTION_ARGUMENT_REGISTERS 0u
335 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
339 typedef GPRReg RegisterType;
340 static const unsigned numberOfRegisters = 6;
341 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
343 // Temporary registers.
344 static const GPRReg regT0 = X86Registers::eax;
345 static const GPRReg regT1 = X86Registers::edx;
346 static const GPRReg regT2 = X86Registers::ecx;
347 static const GPRReg regT3 = X86Registers::ebx; // Callee-save
348 static const GPRReg regT4 = X86Registers::esi; // Callee-save
349 static const GPRReg regT5 = X86Registers::edi; // Callee-save
350 static const GPRReg callFrameRegister = X86Registers::ebp;
351 // These constants provide the names for the general purpose argument & return value registers.
352 static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
353 static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
354 static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
355 static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
356 static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
357 static const GPRReg nonArgGPR1 = X86Registers::edi; // regT5
358 static const GPRReg returnValueGPR = X86Registers::eax; // regT0
359 static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
360 static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
362 static GPRReg toRegister(unsigned index)
364 ASSERT(index < numberOfRegisters);
365 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 };
366 return registerForIndex[index];
369 static GPRReg toArgumentRegister(unsigned)
371 UNREACHABLE_FOR_PLATFORM();
372 return InvalidGPRReg;
375 static unsigned toIndex(GPRReg reg)
377 ASSERT(reg != InvalidGPRReg);
378 ASSERT(static_cast<int>(reg) < 8);
379 static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, 5 };
380 unsigned result = indexForRegister[reg];
384 static unsigned toArgumentIndex(GPRReg reg)
386 ASSERT(reg != InvalidGPRReg);
387 ASSERT(static_cast<int>(reg) < 8);
388 static const unsigned indexForArgumentRegister[8] = { 2, 0, 1, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
389 return indexForArgumentRegister[reg];
392 static const char* debugName(GPRReg reg)
394 ASSERT(reg != InvalidGPRReg);
395 ASSERT(static_cast<int>(reg) < 8);
396 static const char* nameForRegister[8] = {
397 "eax", "ecx", "edx", "ebx",
398 "esp", "ebp", "esi", "edi",
400 return nameForRegister[reg];
403 static const unsigned InvalidIndex = 0xffffffff;
410 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
411 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
412 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS (NUMBER_OF_ARGUMENT_REGISTERS - 2u)
414 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
415 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
416 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
421 typedef GPRReg RegisterType;
422 static const unsigned numberOfRegisters = 11;
423 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
425 // These registers match the baseline JIT.
426 static const GPRReg callFrameRegister = X86Registers::ebp;
427 static const GPRReg tagTypeNumberRegister = X86Registers::r14;
428 static const GPRReg tagMaskRegister = X86Registers::r15;
430 // Temporary registers.
431 static const GPRReg regT0 = X86Registers::eax;
433 static const GPRReg regT1 = X86Registers::esi;
434 static const GPRReg regT2 = X86Registers::edx;
435 static const GPRReg regT3 = X86Registers::ecx;
436 static const GPRReg regT4 = X86Registers::r8;
437 static const GPRReg regT5 = X86Registers::r10;
438 static const GPRReg regT6 = X86Registers::edi;
439 static const GPRReg regT7 = X86Registers::r9;
441 static const GPRReg regT1 = X86Registers::edx;
442 static const GPRReg regT2 = X86Registers::r8;
443 static const GPRReg regT3 = X86Registers::r9;
444 static const GPRReg regT4 = X86Registers::r10;
445 static const GPRReg regT5 = X86Registers::ecx;
448 static const GPRReg regCS0 = X86Registers::ebx;
451 static const GPRReg regCS1 = X86Registers::r12;
452 static const GPRReg regCS2 = X86Registers::r13;
453 static const GPRReg regCS3 = X86Registers::r14;
454 static const GPRReg regCS4 = X86Registers::r15;
456 static const GPRReg regCS1 = X86Registers::esi;
457 static const GPRReg regCS2 = X86Registers::edi;
458 static const GPRReg regCS3 = X86Registers::r12;
459 static const GPRReg regCS4 = X86Registers::r13;
460 static const GPRReg regCS5 = X86Registers::r14;
461 static const GPRReg regCS6 = X86Registers::r15;
464 // These constants provide the names for the general purpose argument & return value registers.
466 static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
467 static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
468 static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
469 static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
470 static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
471 static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
473 static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
474 static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
475 static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
476 static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
478 static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
479 static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
480 static const GPRReg returnValueGPR = X86Registers::eax; // regT0
481 static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
482 static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
483 static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
485 // FIXME: I believe that all uses of this are dead in the sense that it just causes the scratch
486 // register allocator to select a different register and potentially spill things. It would be better
487 // if we instead had a more explicit way of saying that we don't have a scratch register.
488 static const GPRReg patchpointScratchRegister;
490 static GPRReg toRegister(unsigned index)
492 ASSERT(index < numberOfRegisters);
494 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
496 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
498 return registerForIndex[index];
501 static GPRReg toArgumentRegister(unsigned index)
503 ASSERT(index < numberOfArgumentRegisters);
505 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 };
507 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
509 return registerForIndex[index];
512 static unsigned toIndex(GPRReg reg)
514 ASSERT(reg != InvalidGPRReg);
515 ASSERT(static_cast<int>(reg) < 16);
517 static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
519 static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
521 return indexForRegister[reg];
524 static unsigned toArgumentIndex(GPRReg reg)
526 ASSERT(reg != InvalidGPRReg);
527 ASSERT(static_cast<int>(reg) < 16);
529 static const unsigned indexForArgumentRegister[16] = { InvalidIndex, 3, 2, InvalidIndex, InvalidIndex, InvalidIndex, 1, 0, 4, 5, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
531 static const unsigned indexForArgumentRegister[16] = { InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
533 return indexForArgumentRegister[reg];
536 static const char* debugName(GPRReg reg)
538 ASSERT(reg != InvalidGPRReg);
539 ASSERT(static_cast<int>(reg) < 16);
540 static const char* nameForRegister[16] = {
541 "rax", "rcx", "rdx", "rbx",
542 "rsp", "rbp", "rsi", "rdi",
543 "r8", "r9", "r10", "r11",
544 "r12", "r13", "r14", "r15"
546 return nameForRegister[reg];
549 static const std::array<GPRReg, 3>& reservedRegisters()
551 static const std::array<GPRReg, 3> reservedRegisters { {
552 MacroAssembler::s_scratchRegister,
553 tagTypeNumberRegister,
556 return reservedRegisters;
559 static const unsigned InvalidIndex = 0xffffffff;
562 #endif // CPU(X86_64)
565 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
566 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
567 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
571 typedef GPRReg RegisterType;
572 static const unsigned numberOfRegisters = 9;
573 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
575 // Temporary registers.
576 static const GPRReg regT0 = ARMRegisters::r0;
577 static const GPRReg regT1 = ARMRegisters::r1;
578 static const GPRReg regT2 = ARMRegisters::r2;
579 static const GPRReg regT3 = ARMRegisters::r3;
580 static const GPRReg regT4 = ARMRegisters::r8;
581 static const GPRReg regT5 = ARMRegisters::r9;
582 static const GPRReg regT6 = ARMRegisters::r10;
584 static const GPRReg regT7 = ARMRegisters::r11;
586 static const GPRReg regT7 = ARMRegisters::r7;
588 static const GPRReg regT8 = ARMRegisters::r4;
589 // These registers match the baseline JIT.
590 static const GPRReg callFrameRegister = ARMRegisters::fp;
591 // These constants provide the names for the general purpose argument & return value registers.
592 static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
593 static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
594 static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
595 static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
596 static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
597 static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
598 static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
599 static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
600 static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
602 static GPRReg toRegister(unsigned index)
604 ASSERT(index < numberOfRegisters);
605 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
606 return registerForIndex[index];
609 static GPRReg toArgumentRegister(unsigned index)
611 ASSERT(index < numberOfArgumentRegisters);
612 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
613 return registerForIndex[index];
616 static unsigned toIndex(GPRReg reg)
618 ASSERT(reg != InvalidGPRReg);
619 ASSERT(static_cast<int>(reg) < 16);
620 static const unsigned indexForRegister[16] =
622 { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
624 { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
626 unsigned result = indexForRegister[reg];
630 static unsigned toArgumentIndex(GPRReg reg)
632 ASSERT(reg != InvalidGPRReg);
633 ASSERT(static_cast<int>(reg) < 16);
634 if (reg > argumentGPR3)
636 return (unsigned)reg;
639 static const char* debugName(GPRReg reg)
641 ASSERT(reg != InvalidGPRReg);
642 ASSERT(static_cast<int>(reg) < 16);
643 static const char* nameForRegister[16] = {
644 "r0", "r1", "r2", "r3",
645 "r4", "r5", "r6", "r7",
646 "r8", "r9", "r10", "r11",
647 "r12", "r13", "r14", "r15"
649 return nameForRegister[reg];
652 static const unsigned InvalidIndex = 0xffffffff;
658 #define NUMBER_OF_ARGUMENT_REGISTERS 8u
659 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS (NUMBER_OF_ARGUMENT_REGISTERS - 2u)
660 // Callee Saves includes x19..x28 and FP registers q8..q15
661 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
665 typedef GPRReg RegisterType;
666 static const unsigned numberOfRegisters = 16;
667 static const unsigned numberOfArgumentRegisters = 8;
669 // These registers match the baseline JIT.
670 static const GPRReg callFrameRegister = ARM64Registers::fp;
671 static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
672 static const GPRReg tagMaskRegister = ARM64Registers::x28;
673 static const GPRReg dataTempRegister = MacroAssembler::dataTempRegister;
674 static const GPRReg memoryTempRegister = MacroAssembler::memoryTempRegister;
675 // Temporary registers.
676 static const GPRReg regT0 = ARM64Registers::x0;
677 static const GPRReg regT1 = ARM64Registers::x1;
678 static const GPRReg regT2 = ARM64Registers::x2;
679 static const GPRReg regT3 = ARM64Registers::x3;
680 static const GPRReg regT4 = ARM64Registers::x4;
681 static const GPRReg regT5 = ARM64Registers::x5;
682 static const GPRReg regT6 = ARM64Registers::x6;
683 static const GPRReg regT7 = ARM64Registers::x7;
684 static const GPRReg regT8 = ARM64Registers::x8;
685 static const GPRReg regT9 = ARM64Registers::x9;
686 static const GPRReg regT10 = ARM64Registers::x10;
687 static const GPRReg regT11 = ARM64Registers::x11;
688 static const GPRReg regT12 = ARM64Registers::x12;
689 static const GPRReg regT13 = ARM64Registers::x13;
690 static const GPRReg regT14 = ARM64Registers::x14;
691 static const GPRReg regT15 = ARM64Registers::x15;
692 static const GPRReg regCS0 = ARM64Registers::x19; // Used by FTL only
693 static const GPRReg regCS1 = ARM64Registers::x20; // Used by FTL only
694 static const GPRReg regCS2 = ARM64Registers::x21; // Used by FTL only
695 static const GPRReg regCS3 = ARM64Registers::x22; // Used by FTL only
696 static const GPRReg regCS4 = ARM64Registers::x23; // Used by FTL only
697 static const GPRReg regCS5 = ARM64Registers::x24; // Used by FTL only
698 static const GPRReg regCS6 = ARM64Registers::x25; // Used by FTL only
699 static const GPRReg regCS7 = ARM64Registers::x26;
700 static const GPRReg regCS8 = ARM64Registers::x27; // tagTypeNumber
701 static const GPRReg regCS9 = ARM64Registers::x28; // tagMask
702 // These constants provide the names for the general purpose argument & return value registers.
703 static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
704 static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
705 static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
706 static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
707 static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
708 static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
709 static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
710 static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
711 static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
712 static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
713 static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
714 static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
715 static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
716 static const GPRReg nonPreservedNonArgumentGPR = ARM64Registers::x8;
717 static const GPRReg patchpointScratchRegister;
719 // GPRReg mapping is direct, the machine register numbers can
720 // be used directly as indices into the GPR RegisterBank.
721 COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
722 COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
723 COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
724 COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
725 COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
726 COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
727 COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
728 COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
729 COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
730 COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
731 COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
732 COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
733 COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
734 COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
735 COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
736 COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
738 static GPRReg toRegister(unsigned index)
740 return (GPRReg)index;
742 static unsigned toIndex(GPRReg reg)
746 return (unsigned)reg;
749 static GPRReg toArgumentRegister(unsigned index)
751 ASSERT(index < numberOfArgumentRegisters);
752 return toRegister(index);
755 static unsigned toArgumentIndex(GPRReg reg)
757 ASSERT(reg != InvalidGPRReg);
758 if (reg > argumentGPR7)
760 return (unsigned)reg;
763 static const char* debugName(GPRReg reg)
765 ASSERT(reg != InvalidGPRReg);
766 ASSERT(static_cast<unsigned>(reg) < 32);
767 static const char* nameForRegister[32] = {
768 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
769 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
770 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
771 "r24", "r25", "r26", "r27", "r28", "fp", "lr", "sp"
773 return nameForRegister[reg];
776 static const std::array<GPRReg, 4>& reservedRegisters()
778 static const std::array<GPRReg, 4> reservedRegisters { {
781 tagTypeNumberRegister,
784 return reservedRegisters;
787 static const unsigned InvalidIndex = 0xffffffff;
793 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
794 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
795 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
799 typedef GPRReg RegisterType;
800 static const unsigned numberOfRegisters = 7;
801 static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
803 // regT0 must be v0 for returning a 32-bit value.
804 // regT1 must be v1 for returning a pair of 32-bit value.
806 // Temporary registers.
807 static const GPRReg regT0 = MIPSRegisters::v0;
808 static const GPRReg regT1 = MIPSRegisters::v1;
809 static const GPRReg regT2 = MIPSRegisters::t2;
810 static const GPRReg regT3 = MIPSRegisters::t3;
811 static const GPRReg regT4 = MIPSRegisters::t4;
812 static const GPRReg regT5 = MIPSRegisters::t5;
813 static const GPRReg regT6 = MIPSRegisters::t6;
814 // These registers match the baseline JIT.
815 static const GPRReg callFrameRegister = MIPSRegisters::fp;
816 // These constants provide the names for the general purpose argument & return value registers.
817 static const GPRReg argumentGPR0 = MIPSRegisters::a0;
818 static const GPRReg argumentGPR1 = MIPSRegisters::a1;
819 static const GPRReg argumentGPR2 = MIPSRegisters::a2;
820 static const GPRReg argumentGPR3 = MIPSRegisters::a3;
821 static const GPRReg nonArgGPR0 = regT4;
822 static const GPRReg nonArgGPR1 = regT5;
823 static const GPRReg returnValueGPR = regT0;
824 static const GPRReg returnValueGPR2 = regT1;
825 static const GPRReg nonPreservedNonReturnGPR = regT2;
827 static GPRReg toRegister(unsigned index)
829 ASSERT(index < numberOfRegisters);
830 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
831 return registerForIndex[index];
834 static GPRReg toArgumentRegister(unsigned index)
836 ASSERT(index < numberOfArgumentRegisters);
837 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
838 return registerForIndex[index];
841 static unsigned toIndex(GPRReg reg)
843 ASSERT(reg != InvalidGPRReg);
845 static const unsigned indexForRegister[32] = {
846 InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
847 InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
848 InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
849 InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
851 unsigned result = indexForRegister[reg];
855 static const char* debugName(GPRReg reg)
857 ASSERT(reg != InvalidGPRReg);
859 static const char* nameForRegister[16] = {
860 "zero", "at", "v0", "v1",
861 "a0", "a1", "a2", "a3",
862 "t0", "t1", "t2", "t3",
863 "t4", "t5", "t6", "t7"
865 return nameForRegister[reg];
868 static const unsigned InvalidIndex = 0xffffffff;
874 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
875 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
876 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
880 typedef GPRReg RegisterType;
881 static const unsigned numberOfRegisters = 10;
883 // Note: regT3 is required to be callee-preserved.
885 // Temporary registers.
886 static const GPRReg regT0 = SH4Registers::r0;
887 static const GPRReg regT1 = SH4Registers::r1;
888 static const GPRReg regT2 = SH4Registers::r6;
889 static const GPRReg regT3 = SH4Registers::r7;
890 static const GPRReg regT4 = SH4Registers::r2;
891 static const GPRReg regT5 = SH4Registers::r3;
892 static const GPRReg regT6 = SH4Registers::r4;
893 static const GPRReg regT7 = SH4Registers::r5;
894 static const GPRReg regT8 = SH4Registers::r8;
895 static const GPRReg regT9 = SH4Registers::r9;
896 // These registers match the baseline JIT.
897 static const GPRReg cachedResultRegister = regT0;
898 static const GPRReg cachedResultRegister2 = regT1;
899 static const GPRReg callFrameRegister = SH4Registers::fp;
900 // These constants provide the names for the general purpose argument & return value registers.
901 static const GPRReg argumentGPR0 = SH4Registers::r4; // regT6
902 static const GPRReg argumentGPR1 = SH4Registers::r5; // regT7
903 static const GPRReg argumentGPR2 = SH4Registers::r6; // regT2
904 static const GPRReg argumentGPR3 = SH4Registers::r7; // regT3
905 static const GPRReg nonArgGPR0 = regT4;
906 static const GPRReg nonArgGPR1 = regT5;
907 static const GPRReg returnValueGPR = regT0;
908 static const GPRReg returnValueGPR2 = regT1;
909 static const GPRReg nonPreservedNonReturnGPR = regT2;
911 static GPRReg toRegister(unsigned index)
913 ASSERT(index < numberOfRegisters);
914 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9 };
915 return registerForIndex[index];
918 static unsigned toIndex(GPRReg reg)
920 ASSERT(reg != InvalidGPRReg);
922 static const unsigned indexForRegister[14] = { 0, 1, 4, 5, 6, 7, 2, 3, 8, 9, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
923 unsigned result = indexForRegister[reg];
927 static const char* debugName(GPRReg reg)
929 ASSERT(reg != InvalidGPRReg);
931 static const char* nameForRegister[16] = {
932 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
933 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
935 return nameForRegister[reg];
938 static const unsigned InvalidIndex = 0xffffffff;
943 inline GPRReg argumentRegisterFor(unsigned argumentIndex)
945 #if NUMBER_OF_ARGUMENT_REGISTERS
946 if (argumentIndex >= NUMBER_OF_ARGUMENT_REGISTERS)
947 return InvalidGPRReg;
948 return GPRInfo::toArgumentRegister(argumentIndex);
950 UNUSED_PARAM(argumentIndex);
951 RELEASE_ASSERT_NOT_REACHED();
952 return InvalidGPRReg;
956 inline GPRReg argumentRegisterForCallee()
958 #if NUMBER_OF_ARGUMENT_REGISTERS
959 return argumentRegisterFor(0);
961 return GPRInfo::regT0;
965 inline GPRReg argumentRegisterForArgumentCount()
967 return argumentRegisterFor(1);
970 inline unsigned argumentRegisterIndexForJSFunctionArgument(unsigned argument)
975 inline unsigned jsFunctionArgumentForArgumentRegisterIndex(unsigned index)
977 #if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS > 0
982 RELEASE_ASSERT_NOT_REACHED();
987 inline unsigned jsFunctionArgumentForArgumentRegister(GPRReg gpr)
989 #if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS > 0
990 unsigned argumentRegisterIndex = GPRInfo::toArgumentIndex(gpr);
991 ASSERT(argumentRegisterIndex != GPRInfo::InvalidIndex);
992 return jsFunctionArgumentForArgumentRegisterIndex(argumentRegisterIndex);
995 RELEASE_ASSERT_NOT_REACHED();
1000 inline GPRReg argumentRegisterForFunctionArgument(unsigned argumentIndex)
1002 return argumentRegisterFor(argumentRegisterIndexForJSFunctionArgument(argumentIndex));
1005 inline unsigned numberOfRegisterArgumentsFor(unsigned argumentCount)
1007 return std::min(argumentCount, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
1010 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
1011 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
1012 // passing results of one opcode to the next. Hence:
1013 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
1014 #if USE(JSVALUE32_64)
1015 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
1018 inline GPRReg extractResult(GPRReg result) { return result; }
1020 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
1022 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
1024 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
1026 #endif // ENABLE(JIT)
1032 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
1035 out.print("%", JSC::GPRInfo::debugName(reg));
1037 out.printf("%%r%d", reg);