[JSC] Add GPRReg::InvalidGPRReg and FPRReg::InvalidFPRReg
[WebKit-https.git] / Source / JavaScriptCore / jit / GPRInfo.h
1 /*
2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #pragma once
27
28 #include "MacroAssembler.h"
29 #include <array>
30 #include <wtf/PrintStream.h>
31
32 namespace JSC {
33
34 enum NoResultTag { NoResult };
35
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.
40
41 typedef MacroAssembler::RegisterID GPRReg;
42 static constexpr GPRReg InvalidGPRReg { GPRReg::InvalidGPRReg };
43
44 #if ENABLE(JIT)
45
46 #if USE(JSVALUE64)
47 class JSValueRegs {
48 public:
49     constexpr JSValueRegs()
50         : m_gpr(InvalidGPRReg)
51     {
52     }
53     
54     constexpr explicit JSValueRegs(GPRReg gpr)
55         : m_gpr(gpr)
56     {
57     }
58     
59     static JSValueRegs payloadOnly(GPRReg gpr)
60     {
61         return JSValueRegs(gpr);
62     }
63     
64     static JSValueRegs withTwoAvailableRegs(GPRReg gpr, GPRReg)
65     {
66         return JSValueRegs(gpr);
67     }
68     
69     bool operator!() const { return m_gpr == InvalidGPRReg; }
70     explicit operator bool() const { return m_gpr != InvalidGPRReg; }
71
72     bool operator==(JSValueRegs other) { return m_gpr == other.m_gpr; }
73     bool operator!=(JSValueRegs other) { return !(*this == other); }
74     
75     GPRReg gpr() const { return m_gpr; }
76     GPRReg tagGPR() const { return InvalidGPRReg; }
77     GPRReg payloadGPR() const { return m_gpr; }
78     
79     bool uses(GPRReg gpr) const { return m_gpr == gpr; }
80     
81     void dump(PrintStream&) const;
82     
83 private:
84     GPRReg m_gpr;
85 };
86
87 class JSValueSource {
88 public:
89     JSValueSource()
90         : m_offset(notAddress())
91         , m_base(InvalidGPRReg)
92     {
93     }
94     
95     JSValueSource(JSValueRegs regs)
96         : m_offset(notAddress())
97         , m_base(regs.gpr())
98     {
99     }
100     
101     explicit JSValueSource(GPRReg gpr)
102         : m_offset(notAddress())
103         , m_base(gpr)
104     {
105     }
106     
107     JSValueSource(MacroAssembler::Address address)
108         : m_offset(address.offset)
109         , m_base(address.base)
110     {
111         ASSERT(m_offset != notAddress());
112         ASSERT(m_base != InvalidGPRReg);
113     }
114     
115     static JSValueSource unboxedCell(GPRReg payloadGPR)
116     {
117         return JSValueSource(payloadGPR);
118     }
119     
120     bool operator!() const { return m_base == InvalidGPRReg; }
121     explicit operator bool() const { return m_base != InvalidGPRReg; }
122     
123     bool isAddress() const { return m_offset != notAddress(); }
124     
125     int32_t offset() const
126     {
127         ASSERT(isAddress());
128         return m_offset;
129     }
130     
131     GPRReg base() const
132     {
133         ASSERT(isAddress());
134         return m_base;
135     }
136     
137     GPRReg gpr() const
138     {
139         ASSERT(!isAddress());
140         return m_base;
141     }
142
143     GPRReg payloadGPR() const { return gpr(); }
144
145     JSValueRegs regs() const
146     {
147         return JSValueRegs(gpr());
148     }
149     
150     MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); }
151     
152 private:
153     static inline int32_t notAddress() { return 0x80000000; }     
154           
155     int32_t m_offset;
156     GPRReg m_base;
157 };
158 #endif // USE(JSVALUE64)
159
160 #if USE(JSVALUE32_64)
161 class JSValueRegs {
162 public:
163     JSValueRegs()
164         : m_tagGPR(InvalidGPRReg)
165         , m_payloadGPR(InvalidGPRReg)
166     {
167     }
168     
169     JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
170         : m_tagGPR(tagGPR)
171         , m_payloadGPR(payloadGPR)
172     {
173     }
174     
175     static JSValueRegs withTwoAvailableRegs(GPRReg gpr1, GPRReg gpr2)
176     {
177         return JSValueRegs(gpr1, gpr2);
178     }
179     
180     static JSValueRegs payloadOnly(GPRReg gpr)
181     {
182         return JSValueRegs(InvalidGPRReg, gpr);
183     }
184     
185     bool operator!() const { return !static_cast<bool>(*this); }
186     explicit operator bool() const
187     {
188         return static_cast<GPRReg>(m_tagGPR) != InvalidGPRReg
189             || static_cast<GPRReg>(m_payloadGPR) != InvalidGPRReg;
190     }
191
192     bool operator==(JSValueRegs other) const
193     {
194         return m_tagGPR == other.m_tagGPR
195             && m_payloadGPR == other.m_payloadGPR;
196     }
197     bool operator!=(JSValueRegs other) const { return !(*this == other); }
198     
199     GPRReg tagGPR() const { return m_tagGPR; }
200     GPRReg payloadGPR() const { return m_payloadGPR; }
201     GPRReg gpr(WhichValueWord which) const
202     {
203         switch (which) {
204         case TagWord:
205             return tagGPR();
206         case PayloadWord:
207             return payloadGPR();
208         }
209         ASSERT_NOT_REACHED();
210         return tagGPR();
211     }
212
213     bool uses(GPRReg gpr) const { return m_tagGPR == gpr || m_payloadGPR == gpr; }
214     
215     void dump(PrintStream&) const;
216     
217 private:
218     GPRReg m_tagGPR;
219     GPRReg m_payloadGPR;
220 };
221
222 class JSValueSource {
223 public:
224     JSValueSource()
225         : m_offset(notAddress())
226         , m_baseOrTag(InvalidGPRReg)
227         , m_payload(InvalidGPRReg)
228         , m_tagType(0)
229     {
230     }
231     
232     JSValueSource(JSValueRegs regs)
233         : m_offset(notAddress())
234         , m_baseOrTag(regs.tagGPR())
235         , m_payload(regs.payloadGPR())
236         , m_tagType(0)
237     {
238     }
239     
240     JSValueSource(GPRReg tagGPR, GPRReg payloadGPR)
241         : m_offset(notAddress())
242         , m_baseOrTag(tagGPR)
243         , m_payload(payloadGPR)
244         , m_tagType(0)
245     {
246     }
247     
248     JSValueSource(MacroAssembler::Address address)
249         : m_offset(address.offset)
250         , m_baseOrTag(address.base)
251         , m_payload(InvalidGPRReg)
252         , m_tagType(0)
253     {
254         ASSERT(m_offset != notAddress());
255         ASSERT(m_baseOrTag != InvalidGPRReg);
256     }
257     
258     static JSValueSource unboxedCell(GPRReg payloadGPR)
259     {
260         JSValueSource result;
261         result.m_offset = notAddress();
262         result.m_baseOrTag = InvalidGPRReg;
263         result.m_payload = payloadGPR;
264         result.m_tagType = static_cast<int8_t>(JSValue::CellTag);
265         return result;
266     }
267
268     bool operator!() const { return !static_cast<bool>(*this); }
269     explicit operator bool() const
270     {
271         return m_baseOrTag != InvalidGPRReg || m_payload != InvalidGPRReg;
272     }
273     
274     bool isAddress() const
275     {
276         ASSERT(!!*this);
277         return m_offset != notAddress();
278     }
279     
280     int32_t offset() const
281     {
282         ASSERT(isAddress());
283         return m_offset;
284     }
285     
286     GPRReg base() const
287     {
288         ASSERT(isAddress());
289         return m_baseOrTag;
290     }
291     
292     GPRReg tagGPR() const
293     {
294         ASSERT(!isAddress() && m_baseOrTag != InvalidGPRReg);
295         return m_baseOrTag;
296     }
297     
298     GPRReg payloadGPR() const
299     {
300         ASSERT(!isAddress());
301         return m_payload;
302     }
303     
304     bool hasKnownTag() const
305     {
306         ASSERT(!!*this);
307         ASSERT(!isAddress());
308         return m_baseOrTag == InvalidGPRReg;
309     }
310     
311     uint32_t tag() const
312     {
313         return static_cast<int32_t>(m_tagType);
314     }
315     
316     JSValueRegs regs() const
317     {
318         return JSValueRegs(tagGPR(), payloadGPR());
319     }
320     
321     MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
322     
323 private:
324     static inline int32_t notAddress() { return 0x80000000; }     
325           
326     int32_t m_offset;
327     GPRReg m_baseOrTag;
328     GPRReg m_payload;
329     int8_t m_tagType; // Contains the low bits of the tag.
330 };
331 #endif // USE(JSVALUE32_64)
332
333 #if CPU(X86)
334 #define NUMBER_OF_ARGUMENT_REGISTERS 0u
335 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
336
337 class GPRInfo {
338 public:
339     typedef GPRReg RegisterType;
340     static const unsigned numberOfRegisters = 6;
341     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
342
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 returnValueGPR = X86Registers::eax; // regT0
358     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
359     static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
360
361     static GPRReg toRegister(unsigned index)
362     {
363         ASSERT(index < numberOfRegisters);
364         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 };
365         return registerForIndex[index];
366     }
367
368     static GPRReg toArgumentRegister(unsigned)
369     {
370         UNREACHABLE_FOR_PLATFORM();
371         return InvalidGPRReg;
372     }
373
374     static unsigned toIndex(GPRReg reg)
375     {
376         ASSERT(reg != InvalidGPRReg);
377         ASSERT(static_cast<int>(reg) < 8);
378         static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, 5 };
379         unsigned result = indexForRegister[reg];
380         return result;
381     }
382
383     static const char* debugName(GPRReg reg)
384     {
385         ASSERT(reg != InvalidGPRReg);
386         return MacroAssembler::gprName(reg);
387     }
388
389     static const unsigned InvalidIndex = 0xffffffff;
390 };
391
392 #endif // CPU(X86)
393
394 #if CPU(X86_64)
395 #if !OS(WINDOWS)
396 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
397 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
398 #else
399 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
400 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
401 #endif
402
403 class GPRInfo {
404 public:
405     typedef GPRReg RegisterType;
406     static const unsigned numberOfRegisters = 11;
407     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
408
409     // These registers match the baseline JIT.
410     static const GPRReg callFrameRegister = X86Registers::ebp;
411     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
412     static const GPRReg tagMaskRegister = X86Registers::r15;
413
414     // Temporary registers.
415     static const GPRReg regT0 = X86Registers::eax;
416 #if !OS(WINDOWS)
417     static const GPRReg regT1 = X86Registers::esi;
418     static const GPRReg regT2 = X86Registers::edx;
419     static const GPRReg regT3 = X86Registers::ecx;
420     static const GPRReg regT4 = X86Registers::r8;
421     static const GPRReg regT5 = X86Registers::r10;
422     static const GPRReg regT6 = X86Registers::edi;
423     static const GPRReg regT7 = X86Registers::r9;
424 #else
425     static const GPRReg regT1 = X86Registers::edx;
426     static const GPRReg regT2 = X86Registers::r8;
427     static const GPRReg regT3 = X86Registers::r9;
428     static const GPRReg regT4 = X86Registers::r10;
429     static const GPRReg regT5 = X86Registers::ecx;
430 #endif
431
432     static const GPRReg regCS0 = X86Registers::ebx;
433
434 #if !OS(WINDOWS)
435     static const GPRReg regCS1 = X86Registers::r12;
436     static const GPRReg regCS2 = X86Registers::r13;
437     static const GPRReg regCS3 = X86Registers::r14;
438     static const GPRReg regCS4 = X86Registers::r15;
439 #else
440     static const GPRReg regCS1 = X86Registers::esi;
441     static const GPRReg regCS2 = X86Registers::edi;
442     static const GPRReg regCS3 = X86Registers::r12;
443     static const GPRReg regCS4 = X86Registers::r13;
444     static const GPRReg regCS5 = X86Registers::r14;
445     static const GPRReg regCS6 = X86Registers::r15;
446 #endif
447
448     // These constants provide the names for the general purpose argument & return value registers.
449 #if !OS(WINDOWS)
450     static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
451     static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
452     static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
453     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
454     static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
455     static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
456 #else
457     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
458     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
459     static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
460     static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
461 #endif
462     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
463     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
464     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
465     static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
466     static const GPRReg nonPreservedNonArgumentGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
467     static const GPRReg nonPreservedNonArgumentGPR1 = X86Registers::eax;
468
469     // FIXME: I believe that all uses of this are dead in the sense that it just causes the scratch
470     // register allocator to select a different register and potentially spill things. It would be better
471     // if we instead had a more explicit way of saying that we don't have a scratch register.
472     static const GPRReg patchpointScratchRegister;
473
474     static GPRReg toRegister(unsigned index)
475     {
476         ASSERT(index < numberOfRegisters);
477 #if !OS(WINDOWS)
478         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
479 #else
480         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
481 #endif
482         return registerForIndex[index];
483     }
484     
485     static GPRReg toArgumentRegister(unsigned index)
486     {
487         ASSERT(index < numberOfArgumentRegisters);
488 #if !OS(WINDOWS)
489         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 };
490 #else
491         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
492 #endif
493         return registerForIndex[index];
494     }
495     
496     static unsigned toIndex(GPRReg reg)
497     {
498         ASSERT(reg != InvalidGPRReg);
499         ASSERT(static_cast<int>(reg) < 16);
500 #if !OS(WINDOWS)
501         static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
502 #else
503         static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
504 #endif
505         return indexForRegister[reg];
506     }
507
508     static const char* debugName(GPRReg reg)
509     {
510         ASSERT(reg != InvalidGPRReg);
511         return MacroAssembler::gprName(reg);
512     }
513
514     static const std::array<GPRReg, 3>& reservedRegisters()
515     {
516         static const std::array<GPRReg, 3> reservedRegisters { {
517             MacroAssembler::s_scratchRegister,
518             tagTypeNumberRegister,
519             tagMaskRegister,
520         } };
521         return reservedRegisters;
522     }
523     
524     static const unsigned InvalidIndex = 0xffffffff;
525 };
526
527 #endif // CPU(X86_64)
528
529 #if CPU(ARM)
530 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
531 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
532
533 class GPRInfo {
534 public:
535     typedef GPRReg RegisterType;
536     static const unsigned numberOfRegisters = 9;
537     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
538
539     // Temporary registers.
540     static const GPRReg regT0 = ARMRegisters::r0;
541     static const GPRReg regT1 = ARMRegisters::r1;
542     static const GPRReg regT2 = ARMRegisters::r2;
543     static const GPRReg regT3 = ARMRegisters::r3;
544     static const GPRReg regT4 = ARMRegisters::r8;
545     static const GPRReg regT5 = ARMRegisters::r9;
546     static const GPRReg regT6 = ARMRegisters::r10;
547 #if CPU(ARM_THUMB2)
548     static const GPRReg regT7 = ARMRegisters::r11;
549 #else 
550     static const GPRReg regT7 = ARMRegisters::r7;
551 #endif
552     static const GPRReg regT8 = ARMRegisters::r4;
553     // These registers match the baseline JIT.
554     static const GPRReg callFrameRegister = ARMRegisters::fp;
555     // These constants provide the names for the general purpose argument & return value registers.
556     static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
557     static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
558     static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
559     static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
560     static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
561     static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
562     static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
563     static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
564     static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
565
566     static GPRReg toRegister(unsigned index)
567     {
568         ASSERT(index < numberOfRegisters);
569         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
570         return registerForIndex[index];
571     }
572
573     static GPRReg toArgumentRegister(unsigned index)
574     {
575         ASSERT(index < numberOfArgumentRegisters);
576         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
577         return registerForIndex[index];
578     }
579
580     static unsigned toIndex(GPRReg reg)
581     {
582         ASSERT(reg != InvalidGPRReg);
583         ASSERT(static_cast<int>(reg) < 16);
584         static const unsigned indexForRegister[16] =
585 #if CPU(ARM_THUMB2)
586             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
587 #else
588             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
589 #endif
590         unsigned result = indexForRegister[reg];
591         return result;
592     }
593
594     static const char* debugName(GPRReg reg)
595     {
596         ASSERT(reg != InvalidGPRReg);
597         return MacroAssembler::gprName(reg);
598     }
599
600     static const unsigned InvalidIndex = 0xffffffff;
601 };
602
603 #endif // CPU(ARM)
604
605 #if CPU(ARM64)
606 #define NUMBER_OF_ARGUMENT_REGISTERS 8u
607 // Callee Saves includes x19..x28 and FP registers q8..q15
608 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
609
610 class GPRInfo {
611 public:
612     typedef GPRReg RegisterType;
613     static const unsigned numberOfRegisters = 16;
614     static const unsigned numberOfArgumentRegisters = 8;
615
616     // These registers match the baseline JIT.
617     static const GPRReg callFrameRegister = ARM64Registers::fp;
618     static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
619     static const GPRReg tagMaskRegister = ARM64Registers::x28;
620     static const GPRReg dataTempRegister = MacroAssembler::dataTempRegister;
621     static const GPRReg memoryTempRegister = MacroAssembler::memoryTempRegister;
622     // Temporary registers.
623     static const GPRReg regT0 = ARM64Registers::x0;
624     static const GPRReg regT1 = ARM64Registers::x1;
625     static const GPRReg regT2 = ARM64Registers::x2;
626     static const GPRReg regT3 = ARM64Registers::x3;
627     static const GPRReg regT4 = ARM64Registers::x4;
628     static const GPRReg regT5 = ARM64Registers::x5;
629     static const GPRReg regT6 = ARM64Registers::x6;
630     static const GPRReg regT7 = ARM64Registers::x7;
631     static const GPRReg regT8 = ARM64Registers::x8;
632     static const GPRReg regT9 = ARM64Registers::x9;
633     static const GPRReg regT10 = ARM64Registers::x10;
634     static const GPRReg regT11 = ARM64Registers::x11;
635     static const GPRReg regT12 = ARM64Registers::x12;
636     static const GPRReg regT13 = ARM64Registers::x13;
637     static const GPRReg regT14 = ARM64Registers::x14;
638     static const GPRReg regT15 = ARM64Registers::x15;
639     static const GPRReg regCS0 = ARM64Registers::x19; // Used by FTL only
640     static const GPRReg regCS1 = ARM64Registers::x20; // Used by FTL only
641     static const GPRReg regCS2 = ARM64Registers::x21; // Used by FTL only
642     static const GPRReg regCS3 = ARM64Registers::x22; // Used by FTL only
643     static const GPRReg regCS4 = ARM64Registers::x23; // Used by FTL only
644     static const GPRReg regCS5 = ARM64Registers::x24; // Used by FTL only
645     static const GPRReg regCS6 = ARM64Registers::x25; // Used by FTL only
646     static const GPRReg regCS7 = ARM64Registers::x26;
647     static const GPRReg regCS8 = ARM64Registers::x27; // tagTypeNumber
648     static const GPRReg regCS9 = ARM64Registers::x28; // tagMask
649     // These constants provide the names for the general purpose argument & return value registers.
650     static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
651     static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
652     static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
653     static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
654     static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
655     static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
656     static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
657     static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
658     static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
659     static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
660     static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
661     static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
662     static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
663     static const GPRReg nonPreservedNonArgumentGPR0 = ARM64Registers::x8;
664     static const GPRReg nonPreservedNonArgumentGPR1 = ARM64Registers::x9;
665     static const GPRReg patchpointScratchRegister;
666
667     // GPRReg mapping is direct, the machine register numbers can
668     // be used directly as indices into the GPR RegisterBank.
669     COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
670     COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
671     COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
672     COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
673     COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
674     COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
675     COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
676     COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
677     COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
678     COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
679     COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
680     COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
681     COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
682     COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
683     COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
684     COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
685     static GPRReg toRegister(unsigned index)
686     {
687         return (GPRReg)index;
688     }
689     static unsigned toIndex(GPRReg reg)
690     {
691         if (reg > regT15)
692             return InvalidIndex;
693         return (unsigned)reg;
694     }
695
696     static GPRReg toArgumentRegister(unsigned index)
697     {
698         ASSERT(index < numberOfArgumentRegisters);
699         return toRegister(index);
700     }
701
702     static const char* debugName(GPRReg reg)
703     {
704         ASSERT(reg != InvalidGPRReg);
705         return MacroAssembler::gprName(reg);
706     }
707
708     static const std::array<GPRReg, 4>& reservedRegisters()
709     {
710         static const std::array<GPRReg, 4> reservedRegisters { {
711             dataTempRegister,
712             memoryTempRegister,
713             tagTypeNumberRegister,
714             tagMaskRegister,
715         } };
716         return reservedRegisters;
717     }
718     
719     static const unsigned InvalidIndex = 0xffffffff;
720 };
721
722 #endif // CPU(ARM64)
723
724 #if CPU(MIPS)
725 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
726 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
727
728 class GPRInfo {
729 public:
730     typedef GPRReg RegisterType;
731     static const unsigned numberOfRegisters = 11;
732     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
733
734     // regT0 must be v0 for returning a 32-bit value.
735     // regT1 must be v1 for returning a pair of 32-bit value.
736
737     // Temporary registers.
738     static const GPRReg regT0 = MIPSRegisters::v0;
739     static const GPRReg regT1 = MIPSRegisters::v1;
740     static const GPRReg regT2 = MIPSRegisters::t2;
741     static const GPRReg regT3 = MIPSRegisters::t3;
742     static const GPRReg regT4 = MIPSRegisters::t4;
743     static const GPRReg regT5 = MIPSRegisters::t5;
744     static const GPRReg regT6 = MIPSRegisters::t6;
745     static const GPRReg regT7 = MIPSRegisters::a0;
746     static const GPRReg regT8 = MIPSRegisters::a1;
747     static const GPRReg regT9 = MIPSRegisters::a2;
748     static const GPRReg regT10 = MIPSRegisters::a3;
749     // These registers match the baseline JIT.
750     static const GPRReg callFrameRegister = MIPSRegisters::fp;
751     // These constants provide the names for the general purpose argument & return value registers.
752     static const GPRReg argumentGPR0 = MIPSRegisters::a0;
753     static const GPRReg argumentGPR1 = MIPSRegisters::a1;
754     static const GPRReg argumentGPR2 = MIPSRegisters::a2;
755     static const GPRReg argumentGPR3 = MIPSRegisters::a3;
756     static const GPRReg nonArgGPR0 = regT4;
757     static const GPRReg returnValueGPR = regT0;
758     static const GPRReg returnValueGPR2 = regT1;
759     static const GPRReg nonPreservedNonReturnGPR = regT2;
760
761     static GPRReg toRegister(unsigned index)
762     {
763         ASSERT(index < numberOfRegisters);
764         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9, regT10 };
765         return registerForIndex[index];
766     }
767
768     static GPRReg toArgumentRegister(unsigned index)
769     {
770         ASSERT(index < numberOfArgumentRegisters);
771         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
772         return registerForIndex[index];
773     }
774
775     static unsigned toIndex(GPRReg reg)
776     {
777         ASSERT(reg != InvalidGPRReg);
778         ASSERT(reg < 32);
779         static const unsigned indexForRegister[32] = {
780             InvalidIndex, InvalidIndex, 0, 1, 7, 8, 9, 10,
781             InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
782             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
783             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
784         };
785         unsigned result = indexForRegister[reg];
786         return result;
787     }
788
789     static const char* debugName(GPRReg reg)
790     {
791         ASSERT(reg != InvalidGPRReg);
792         return MacroAssembler::gprName(reg);
793     }
794
795     static const unsigned InvalidIndex = 0xffffffff;
796 };
797
798 #endif // CPU(MIPS)
799
800 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
801 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
802 // passing results of one opcode to the next. Hence:
803 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
804 #if USE(JSVALUE32_64)
805 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
806 #endif
807
808 inline GPRReg extractResult(GPRReg result) { return result; }
809 #if USE(JSVALUE64)
810 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
811 #else
812 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
813 #endif
814 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
815
816 // We use this hack to get the GPRInfo from the GPRReg type in templates because our code is bad and we should feel bad..
817 constexpr GPRInfo toInfoFromReg(GPRReg) { return GPRInfo(); }
818
819 #endif // ENABLE(JIT)
820
821 } // namespace JSC
822
823 namespace WTF {
824
825 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
826 {
827 #if ENABLE(JIT)
828     out.print("%", JSC::GPRInfo::debugName(reg));
829 #else
830     out.printf("%%r%d", reg);
831 #endif
832 }
833
834 } // namespace WTF