Move DFG::OSRExitCompiler methods into DFG::OSRExit [step 3].
[WebKit-https.git] / Source / JavaScriptCore / jit / GPRInfo.h
1 /*
2  * Copyright (C) 2011-2017 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 #define InvalidGPRReg ((::JSC::GPRReg)-1)
43
44 #if ENABLE(JIT)
45
46 #if USE(JSVALUE64)
47 class JSValueRegs {
48 public:
49     JSValueRegs()
50         : m_gpr(InvalidGPRReg)
51     {
52     }
53     
54     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(static_cast<int8_t>(InvalidGPRReg))
165         , m_payloadGPR(static_cast<int8_t>(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 static_cast<GPRReg>(m_tagGPR); }
200     GPRReg payloadGPR() const { return static_cast<GPRReg>(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     int8_t m_tagGPR;
219     int8_t m_payloadGPR;
220 };
221
222 class JSValueSource {
223 public:
224     JSValueSource()
225         : m_offset(notAddress())
226         , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg))
227         , m_payload(static_cast<int8_t>(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(static_cast<int8_t>(tagGPR))
243         , m_payload(static_cast<int8_t>(payloadGPR))
244         , m_tagType(0)
245     {
246     }
247     
248     JSValueSource(MacroAssembler::Address address)
249         : m_offset(address.offset)
250         , m_baseOrTag(static_cast<int8_t>(address.base))
251         , m_payload(static_cast<int8_t>(InvalidGPRReg))
252         , m_tagType(0)
253     {
254         ASSERT(m_offset != notAddress());
255         ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
256     }
257     
258     static JSValueSource unboxedCell(GPRReg payloadGPR)
259     {
260         JSValueSource result;
261         result.m_offset = notAddress();
262         result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg);
263         result.m_payload = static_cast<int8_t>(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 static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg
272             || static_cast<GPRReg>(m_payload) != InvalidGPRReg;
273     }
274     
275     bool isAddress() const
276     {
277         ASSERT(!!*this);
278         return m_offset != notAddress();
279     }
280     
281     int32_t offset() const
282     {
283         ASSERT(isAddress());
284         return m_offset;
285     }
286     
287     GPRReg base() const
288     {
289         ASSERT(isAddress());
290         return static_cast<GPRReg>(m_baseOrTag);
291     }
292     
293     GPRReg tagGPR() const
294     {
295         ASSERT(!isAddress() && static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
296         return static_cast<GPRReg>(m_baseOrTag);
297     }
298     
299     GPRReg payloadGPR() const
300     {
301         ASSERT(!isAddress());
302         return static_cast<GPRReg>(m_payload);
303     }
304     
305     bool hasKnownTag() const
306     {
307         ASSERT(!!*this);
308         ASSERT(!isAddress());
309         return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg;
310     }
311     
312     uint32_t tag() const
313     {
314         return static_cast<int32_t>(m_tagType);
315     }
316     
317     JSValueRegs regs() const
318     {
319         return JSValueRegs(tagGPR(), payloadGPR());
320     }
321     
322     MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
323     
324 private:
325     static inline int32_t notAddress() { return 0x80000000; }     
326           
327     int32_t m_offset;
328     int8_t m_baseOrTag;
329     int8_t m_payload; 
330     int8_t m_tagType; // Contains the low bits of the tag.
331 };
332 #endif // USE(JSVALUE32_64)
333
334 #if CPU(X86)
335 #define NUMBER_OF_ARGUMENT_REGISTERS 0u
336 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
337
338 class GPRInfo {
339 public:
340     typedef GPRReg RegisterType;
341     static const unsigned numberOfRegisters = 6;
342     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
343
344     // Temporary registers.
345     static const GPRReg regT0 = X86Registers::eax;
346     static const GPRReg regT1 = X86Registers::edx;
347     static const GPRReg regT2 = X86Registers::ecx;
348     static const GPRReg regT3 = X86Registers::ebx; // Callee-save
349     static const GPRReg regT4 = X86Registers::esi; // Callee-save
350     static const GPRReg regT5 = X86Registers::edi; // Callee-save
351     static const GPRReg callFrameRegister = X86Registers::ebp;
352     // These constants provide the names for the general purpose argument & return value registers.
353     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
354     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
355     static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
356     static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
357     static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
358     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
359     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
360     static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
361
362     static GPRReg toRegister(unsigned index)
363     {
364         ASSERT(index < numberOfRegisters);
365         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 };
366         return registerForIndex[index];
367     }
368
369     static GPRReg toArgumentRegister(unsigned)
370     {
371         UNREACHABLE_FOR_PLATFORM();
372         return InvalidGPRReg;
373     }
374
375     static unsigned toIndex(GPRReg reg)
376     {
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];
381         return result;
382     }
383
384     static const char* debugName(GPRReg reg)
385     {
386         ASSERT(reg != InvalidGPRReg);
387         return MacroAssembler::gprName(reg);
388     }
389
390     static const unsigned InvalidIndex = 0xffffffff;
391 };
392
393 #endif // CPU(X86)
394
395 #if CPU(X86_64)
396 #if !OS(WINDOWS)
397 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
398 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
399 #else
400 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
401 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
402 #endif
403
404 class GPRInfo {
405 public:
406     typedef GPRReg RegisterType;
407     static const unsigned numberOfRegisters = 11;
408     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
409
410     // These registers match the baseline JIT.
411     static const GPRReg callFrameRegister = X86Registers::ebp;
412     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
413     static const GPRReg tagMaskRegister = X86Registers::r15;
414
415     // Temporary registers.
416     static const GPRReg regT0 = X86Registers::eax;
417 #if !OS(WINDOWS)
418     static const GPRReg regT1 = X86Registers::esi;
419     static const GPRReg regT2 = X86Registers::edx;
420     static const GPRReg regT3 = X86Registers::ecx;
421     static const GPRReg regT4 = X86Registers::r8;
422     static const GPRReg regT5 = X86Registers::r10;
423     static const GPRReg regT6 = X86Registers::edi;
424     static const GPRReg regT7 = X86Registers::r9;
425 #else
426     static const GPRReg regT1 = X86Registers::edx;
427     static const GPRReg regT2 = X86Registers::r8;
428     static const GPRReg regT3 = X86Registers::r9;
429     static const GPRReg regT4 = X86Registers::r10;
430     static const GPRReg regT5 = X86Registers::ecx;
431 #endif
432
433     static const GPRReg regCS0 = X86Registers::ebx;
434
435 #if !OS(WINDOWS)
436     static const GPRReg regCS1 = X86Registers::r12;
437     static const GPRReg regCS2 = X86Registers::r13;
438     static const GPRReg regCS3 = X86Registers::r14;
439     static const GPRReg regCS4 = X86Registers::r15;
440 #else
441     static const GPRReg regCS1 = X86Registers::esi;
442     static const GPRReg regCS2 = X86Registers::edi;
443     static const GPRReg regCS3 = X86Registers::r12;
444     static const GPRReg regCS4 = X86Registers::r13;
445     static const GPRReg regCS5 = X86Registers::r14;
446     static const GPRReg regCS6 = X86Registers::r15;
447 #endif
448
449     // These constants provide the names for the general purpose argument & return value registers.
450 #if !OS(WINDOWS)
451     static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
452     static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
453     static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
454     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
455     static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
456     static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
457 #else
458     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
459     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
460     static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
461     static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
462 #endif
463     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
464     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
465     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
466     static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
467     static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
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 nonPreservedNonArgumentGPR = ARM64Registers::x8;
664     static const GPRReg patchpointScratchRegister;
665
666     // GPRReg mapping is direct, the machine register numbers can
667     // be used directly as indices into the GPR RegisterBank.
668     COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
669     COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
670     COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
671     COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
672     COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
673     COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
674     COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
675     COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
676     COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
677     COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
678     COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
679     COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
680     COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
681     COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
682     COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
683     COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
684     static GPRReg toRegister(unsigned index)
685     {
686         return (GPRReg)index;
687     }
688     static unsigned toIndex(GPRReg reg)
689     {
690         if (reg > regT15)
691             return InvalidIndex;
692         return (unsigned)reg;
693     }
694
695     static GPRReg toArgumentRegister(unsigned index)
696     {
697         ASSERT(index < numberOfArgumentRegisters);
698         return toRegister(index);
699     }
700
701     static const char* debugName(GPRReg reg)
702     {
703         ASSERT(reg != InvalidGPRReg);
704         return MacroAssembler::gprName(reg);
705     }
706
707     static const std::array<GPRReg, 4>& reservedRegisters()
708     {
709         static const std::array<GPRReg, 4> reservedRegisters { {
710             dataTempRegister,
711             memoryTempRegister,
712             tagTypeNumberRegister,
713             tagMaskRegister,
714         } };
715         return reservedRegisters;
716     }
717     
718     static const unsigned InvalidIndex = 0xffffffff;
719 };
720
721 #endif // CPU(ARM64)
722
723 #if CPU(MIPS)
724 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
725 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
726
727 class GPRInfo {
728 public:
729     typedef GPRReg RegisterType;
730     static const unsigned numberOfRegisters = 7;
731     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
732
733     // regT0 must be v0 for returning a 32-bit value.
734     // regT1 must be v1 for returning a pair of 32-bit value.
735
736     // Temporary registers.
737     static const GPRReg regT0 = MIPSRegisters::v0;
738     static const GPRReg regT1 = MIPSRegisters::v1;
739     static const GPRReg regT2 = MIPSRegisters::t2;
740     static const GPRReg regT3 = MIPSRegisters::t3;
741     static const GPRReg regT4 = MIPSRegisters::t4;
742     static const GPRReg regT5 = MIPSRegisters::t5;
743     static const GPRReg regT6 = MIPSRegisters::t6;
744     // These registers match the baseline JIT.
745     static const GPRReg callFrameRegister = MIPSRegisters::fp;
746     // These constants provide the names for the general purpose argument & return value registers.
747     static const GPRReg argumentGPR0 = MIPSRegisters::a0;
748     static const GPRReg argumentGPR1 = MIPSRegisters::a1;
749     static const GPRReg argumentGPR2 = MIPSRegisters::a2;
750     static const GPRReg argumentGPR3 = MIPSRegisters::a3;
751     static const GPRReg nonArgGPR0 = regT4;
752     static const GPRReg returnValueGPR = regT0;
753     static const GPRReg returnValueGPR2 = regT1;
754     static const GPRReg nonPreservedNonReturnGPR = regT2;
755
756     static GPRReg toRegister(unsigned index)
757     {
758         ASSERT(index < numberOfRegisters);
759         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
760         return registerForIndex[index];
761     }
762
763     static GPRReg toArgumentRegister(unsigned index)
764     {
765         ASSERT(index < numberOfArgumentRegisters);
766         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
767         return registerForIndex[index];
768     }
769
770     static unsigned toIndex(GPRReg reg)
771     {
772         ASSERT(reg != InvalidGPRReg);
773         ASSERT(reg < 32);
774         static const unsigned indexForRegister[32] = {
775             InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
776             InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
777             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
778             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
779         };
780         unsigned result = indexForRegister[reg];
781         return result;
782     }
783
784     static const char* debugName(GPRReg reg)
785     {
786         ASSERT(reg != InvalidGPRReg);
787         return MacroAssembler::gprName(reg);
788     }
789
790     static const unsigned InvalidIndex = 0xffffffff;
791 };
792
793 #endif // CPU(MIPS)
794
795 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
796 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
797 // passing results of one opcode to the next. Hence:
798 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
799 #if USE(JSVALUE32_64)
800 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
801 #endif
802
803 inline GPRReg extractResult(GPRReg result) { return result; }
804 #if USE(JSVALUE64)
805 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
806 #else
807 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
808 #endif
809 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
810
811 #endif // ENABLE(JIT)
812
813 } // namespace JSC
814
815 namespace WTF {
816
817 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
818 {
819 #if ENABLE(JIT)
820     out.print("%", JSC::GPRInfo::debugName(reg));
821 #else
822     out.printf("%%r%d", reg);
823 #endif
824 }
825
826 } // namespace WTF