3d6a4c6ce244f24e3765faf65a74a87b0583a6ab
[WebKit-https.git] / Source / JavaScriptCore / jit / GPRInfo.h
1 /*
2  * Copyright (C) 2011, 2013-2016 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     JSValueRegs regs() const
144     {
145         return JSValueRegs(gpr());
146     }
147     
148     MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); }
149     
150 private:
151     static inline int32_t notAddress() { return 0x80000000; }     
152           
153     int32_t m_offset;
154     GPRReg m_base;
155 };
156 #endif // USE(JSVALUE64)
157
158 #if USE(JSVALUE32_64)
159 class JSValueRegs {
160 public:
161     JSValueRegs()
162         : m_tagGPR(static_cast<int8_t>(InvalidGPRReg))
163         , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg))
164     {
165     }
166     
167     JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
168         : m_tagGPR(tagGPR)
169         , m_payloadGPR(payloadGPR)
170     {
171     }
172     
173     static JSValueRegs withTwoAvailableRegs(GPRReg gpr1, GPRReg gpr2)
174     {
175         return JSValueRegs(gpr1, gpr2);
176     }
177     
178     static JSValueRegs payloadOnly(GPRReg gpr)
179     {
180         return JSValueRegs(InvalidGPRReg, gpr);
181     }
182     
183     bool operator!() const { return !static_cast<bool>(*this); }
184     explicit operator bool() const
185     {
186         return static_cast<GPRReg>(m_tagGPR) != InvalidGPRReg
187             || static_cast<GPRReg>(m_payloadGPR) != InvalidGPRReg;
188     }
189
190     bool operator==(JSValueRegs other) const
191     {
192         return m_tagGPR == other.m_tagGPR
193             && m_payloadGPR == other.m_payloadGPR;
194     }
195     bool operator!=(JSValueRegs other) const { return !(*this == other); }
196     
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
200     {
201         switch (which) {
202         case TagWord:
203             return tagGPR();
204         case PayloadWord:
205             return payloadGPR();
206         }
207         ASSERT_NOT_REACHED();
208         return tagGPR();
209     }
210
211     bool uses(GPRReg gpr) const { return m_tagGPR == gpr || m_payloadGPR == gpr; }
212     
213     void dump(PrintStream&) const;
214     
215 private:
216     int8_t m_tagGPR;
217     int8_t m_payloadGPR;
218 };
219
220 class JSValueSource {
221 public:
222     JSValueSource()
223         : m_offset(notAddress())
224         , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg))
225         , m_payload(static_cast<int8_t>(InvalidGPRReg))
226         , m_tagType(0)
227     {
228     }
229     
230     JSValueSource(JSValueRegs regs)
231         : m_offset(notAddress())
232         , m_baseOrTag(regs.tagGPR())
233         , m_payload(regs.payloadGPR())
234         , m_tagType(0)
235     {
236     }
237     
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))
242         , m_tagType(0)
243     {
244     }
245     
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))
250         , m_tagType(0)
251     {
252         ASSERT(m_offset != notAddress());
253         ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
254     }
255     
256     static JSValueSource unboxedCell(GPRReg payloadGPR)
257     {
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);
263         return result;
264     }
265
266     bool operator!() const { return !static_cast<bool>(*this); }
267     explicit operator bool() const
268     {
269         return static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg
270             || static_cast<GPRReg>(m_payload) != InvalidGPRReg;
271     }
272     
273     bool isAddress() const
274     {
275         ASSERT(!!*this);
276         return m_offset != notAddress();
277     }
278     
279     int32_t offset() const
280     {
281         ASSERT(isAddress());
282         return m_offset;
283     }
284     
285     GPRReg base() const
286     {
287         ASSERT(isAddress());
288         return static_cast<GPRReg>(m_baseOrTag);
289     }
290     
291     GPRReg tagGPR() const
292     {
293         ASSERT(!isAddress() && static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
294         return static_cast<GPRReg>(m_baseOrTag);
295     }
296     
297     GPRReg payloadGPR() const
298     {
299         ASSERT(!isAddress());
300         return static_cast<GPRReg>(m_payload);
301     }
302     
303     bool hasKnownTag() const
304     {
305         ASSERT(!!*this);
306         ASSERT(!isAddress());
307         return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg;
308     }
309     
310     uint32_t tag() const
311     {
312         return static_cast<int32_t>(m_tagType);
313     }
314     
315     JSValueRegs regs() const
316     {
317         return JSValueRegs(tagGPR(), payloadGPR());
318     }
319     
320     MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
321     
322 private:
323     static inline int32_t notAddress() { return 0x80000000; }     
324           
325     int32_t m_offset;
326     int8_t m_baseOrTag;
327     int8_t m_payload; 
328     int8_t m_tagType; // Contains the low bits of the tag.
329 };
330 #endif // USE(JSVALUE32_64)
331
332 #if CPU(X86)
333 #define NUMBER_OF_ARGUMENT_REGISTERS 0u
334 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
335
336 class GPRInfo {
337 public:
338     typedef GPRReg RegisterType;
339     static const unsigned numberOfRegisters = 6;
340     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
341
342     // Temporary registers.
343     static const GPRReg regT0 = X86Registers::eax;
344     static const GPRReg regT1 = X86Registers::edx;
345     static const GPRReg regT2 = X86Registers::ecx;
346     static const GPRReg regT3 = X86Registers::ebx; // Callee-save
347     static const GPRReg regT4 = X86Registers::esi; // Callee-save
348     static const GPRReg regT5 = X86Registers::edi; // Callee-save
349     static const GPRReg callFrameRegister = X86Registers::ebp;
350     // These constants provide the names for the general purpose argument & return value registers.
351     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
352     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
353     static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
354     static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
355     static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
356     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
357     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
358     static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
359
360     static GPRReg toRegister(unsigned index)
361     {
362         ASSERT(index < numberOfRegisters);
363         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 };
364         return registerForIndex[index];
365     }
366
367     static GPRReg toArgumentRegister(unsigned)
368     {
369         UNREACHABLE_FOR_PLATFORM();
370         return InvalidGPRReg;
371     }
372
373     static unsigned toIndex(GPRReg reg)
374     {
375         ASSERT(reg != InvalidGPRReg);
376         ASSERT(static_cast<int>(reg) < 8);
377         static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, 5 };
378         unsigned result = indexForRegister[reg];
379         return result;
380     }
381
382     static const char* debugName(GPRReg reg)
383     {
384         ASSERT(reg != InvalidGPRReg);
385         ASSERT(static_cast<int>(reg) < 8);
386         static const char* nameForRegister[8] = {
387             "eax", "ecx", "edx", "ebx",
388             "esp", "ebp", "esi", "edi",
389         };
390         return nameForRegister[reg];
391     }
392
393     static const unsigned InvalidIndex = 0xffffffff;
394 };
395
396 #endif // CPU(X86)
397
398 #if CPU(X86_64)
399 #if !OS(WINDOWS)
400 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
401 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
402 #else
403 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
404 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
405 #endif
406
407 class GPRInfo {
408 public:
409     typedef GPRReg RegisterType;
410     static const unsigned numberOfRegisters = 11;
411     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
412
413     // These registers match the baseline JIT.
414     static const GPRReg callFrameRegister = X86Registers::ebp;
415     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
416     static const GPRReg tagMaskRegister = X86Registers::r15;
417
418     // Temporary registers.
419     static const GPRReg regT0 = X86Registers::eax;
420 #if !OS(WINDOWS)
421     static const GPRReg regT1 = X86Registers::esi;
422     static const GPRReg regT2 = X86Registers::edx;
423     static const GPRReg regT3 = X86Registers::ecx;
424     static const GPRReg regT4 = X86Registers::r8;
425     static const GPRReg regT5 = X86Registers::r10;
426     static const GPRReg regT6 = X86Registers::edi;
427     static const GPRReg regT7 = X86Registers::r9;
428 #else
429     static const GPRReg regT1 = X86Registers::edx;
430     static const GPRReg regT2 = X86Registers::r8;
431     static const GPRReg regT3 = X86Registers::r9;
432     static const GPRReg regT4 = X86Registers::r10;
433     static const GPRReg regT5 = X86Registers::ecx;
434 #endif
435
436     static const GPRReg regCS0 = X86Registers::ebx;
437
438 #if !OS(WINDOWS)
439     static const GPRReg regCS1 = X86Registers::r12;
440     static const GPRReg regCS2 = X86Registers::r13;
441     static const GPRReg regCS3 = X86Registers::r14;
442     static const GPRReg regCS4 = X86Registers::r15;
443 #else
444     static const GPRReg regCS1 = X86Registers::esi;
445     static const GPRReg regCS2 = X86Registers::edi;
446     static const GPRReg regCS3 = X86Registers::r12;
447     static const GPRReg regCS4 = X86Registers::r13;
448     static const GPRReg regCS5 = X86Registers::r14;
449     static const GPRReg regCS6 = X86Registers::r15;
450 #endif
451
452     // These constants provide the names for the general purpose argument & return value registers.
453 #if !OS(WINDOWS)
454     static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
455     static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
456     static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
457     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
458     static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
459     static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
460 #else
461     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
462     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
463     static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
464     static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
465 #endif
466     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
467     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
468     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
469     static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
470     static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
471
472     // FIXME: I believe that all uses of this are dead in the sense that it just causes the scratch
473     // register allocator to select a different register and potentially spill things. It would be better
474     // if we instead had a more explicit way of saying that we don't have a scratch register.
475     static const GPRReg patchpointScratchRegister;
476
477     static GPRReg toRegister(unsigned index)
478     {
479         ASSERT(index < numberOfRegisters);
480 #if !OS(WINDOWS)
481         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
482 #else
483         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
484 #endif
485         return registerForIndex[index];
486     }
487     
488     static GPRReg toArgumentRegister(unsigned index)
489     {
490         ASSERT(index < numberOfArgumentRegisters);
491 #if !OS(WINDOWS)
492         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 };
493 #else
494         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
495 #endif
496         return registerForIndex[index];
497     }
498     
499     static unsigned toIndex(GPRReg reg)
500     {
501         ASSERT(reg != InvalidGPRReg);
502         ASSERT(static_cast<int>(reg) < 16);
503 #if !OS(WINDOWS)
504         static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
505 #else
506         static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
507 #endif
508         return indexForRegister[reg];
509     }
510
511     static const char* debugName(GPRReg reg)
512     {
513         ASSERT(reg != InvalidGPRReg);
514         ASSERT(static_cast<int>(reg) < 16);
515         static const char* nameForRegister[16] = {
516             "rax", "rcx", "rdx", "rbx",
517             "rsp", "rbp", "rsi", "rdi",
518             "r8", "r9", "r10", "r11",
519             "r12", "r13", "r14", "r15"
520         };
521         return nameForRegister[reg];
522     }
523
524     static const std::array<GPRReg, 3>& reservedRegisters()
525     {
526         static const std::array<GPRReg, 3> reservedRegisters { {
527             MacroAssembler::s_scratchRegister,
528             tagTypeNumberRegister,
529             tagMaskRegister,
530         } };
531         return reservedRegisters;
532     }
533     
534     static const unsigned InvalidIndex = 0xffffffff;
535 };
536
537 #endif // CPU(X86_64)
538
539 #if CPU(ARM)
540 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
541 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
542
543 class GPRInfo {
544 public:
545     typedef GPRReg RegisterType;
546     static const unsigned numberOfRegisters = 9;
547     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
548
549     // Temporary registers.
550     static const GPRReg regT0 = ARMRegisters::r0;
551     static const GPRReg regT1 = ARMRegisters::r1;
552     static const GPRReg regT2 = ARMRegisters::r2;
553     static const GPRReg regT3 = ARMRegisters::r3;
554     static const GPRReg regT4 = ARMRegisters::r8;
555     static const GPRReg regT5 = ARMRegisters::r9;
556     static const GPRReg regT6 = ARMRegisters::r10;
557 #if CPU(ARM_THUMB2)
558     static const GPRReg regT7 = ARMRegisters::r11;
559 #else 
560     static const GPRReg regT7 = ARMRegisters::r7;
561 #endif
562     static const GPRReg regT8 = ARMRegisters::r4;
563     // These registers match the baseline JIT.
564     static const GPRReg callFrameRegister = ARMRegisters::fp;
565     // These constants provide the names for the general purpose argument & return value registers.
566     static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
567     static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
568     static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
569     static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
570     static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
571     static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
572     static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
573     static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
574     static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
575
576     static GPRReg toRegister(unsigned index)
577     {
578         ASSERT(index < numberOfRegisters);
579         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
580         return registerForIndex[index];
581     }
582
583     static GPRReg toArgumentRegister(unsigned index)
584     {
585         ASSERT(index < numberOfArgumentRegisters);
586         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
587         return registerForIndex[index];
588     }
589
590     static unsigned toIndex(GPRReg reg)
591     {
592         ASSERT(reg != InvalidGPRReg);
593         ASSERT(static_cast<int>(reg) < 16);
594         static const unsigned indexForRegister[16] =
595 #if CPU(ARM_THUMB2)
596             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
597 #else
598             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
599 #endif
600         unsigned result = indexForRegister[reg];
601         return result;
602     }
603
604     static const char* debugName(GPRReg reg)
605     {
606         ASSERT(reg != InvalidGPRReg);
607         ASSERT(static_cast<int>(reg) < 16);
608         static const char* nameForRegister[16] = {
609             "r0", "r1", "r2", "r3",
610             "r4", "r5", "r6", "r7",
611             "r8", "r9", "r10", "r11",
612             "r12", "r13", "r14", "r15"
613         };
614         return nameForRegister[reg];
615     }
616
617     static const unsigned InvalidIndex = 0xffffffff;
618 };
619
620 #endif // CPU(ARM)
621
622 #if CPU(ARM64)
623 #define NUMBER_OF_ARGUMENT_REGISTERS 8u
624 // Callee Saves includes x19..x28 and FP registers q8..q15
625 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
626
627 class GPRInfo {
628 public:
629     typedef GPRReg RegisterType;
630     static const unsigned numberOfRegisters = 16;
631     static const unsigned numberOfArgumentRegisters = 8;
632
633     // These registers match the baseline JIT.
634     static const GPRReg callFrameRegister = ARM64Registers::fp;
635     static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
636     static const GPRReg tagMaskRegister = ARM64Registers::x28;
637     static const GPRReg dataTempRegister = MacroAssembler::dataTempRegister;
638     static const GPRReg memoryTempRegister = MacroAssembler::memoryTempRegister;
639     // Temporary registers.
640     static const GPRReg regT0 = ARM64Registers::x0;
641     static const GPRReg regT1 = ARM64Registers::x1;
642     static const GPRReg regT2 = ARM64Registers::x2;
643     static const GPRReg regT3 = ARM64Registers::x3;
644     static const GPRReg regT4 = ARM64Registers::x4;
645     static const GPRReg regT5 = ARM64Registers::x5;
646     static const GPRReg regT6 = ARM64Registers::x6;
647     static const GPRReg regT7 = ARM64Registers::x7;
648     static const GPRReg regT8 = ARM64Registers::x8;
649     static const GPRReg regT9 = ARM64Registers::x9;
650     static const GPRReg regT10 = ARM64Registers::x10;
651     static const GPRReg regT11 = ARM64Registers::x11;
652     static const GPRReg regT12 = ARM64Registers::x12;
653     static const GPRReg regT13 = ARM64Registers::x13;
654     static const GPRReg regT14 = ARM64Registers::x14;
655     static const GPRReg regT15 = ARM64Registers::x15;
656     static const GPRReg regCS0 = ARM64Registers::x19; // Used by FTL only
657     static const GPRReg regCS1 = ARM64Registers::x20; // Used by FTL only
658     static const GPRReg regCS2 = ARM64Registers::x21; // Used by FTL only
659     static const GPRReg regCS3 = ARM64Registers::x22; // Used by FTL only
660     static const GPRReg regCS4 = ARM64Registers::x23; // Used by FTL only
661     static const GPRReg regCS5 = ARM64Registers::x24; // Used by FTL only
662     static const GPRReg regCS6 = ARM64Registers::x25; // Used by FTL only
663     static const GPRReg regCS7 = ARM64Registers::x26;
664     static const GPRReg regCS8 = ARM64Registers::x27; // tagTypeNumber
665     static const GPRReg regCS9 = ARM64Registers::x28; // tagMask
666     // These constants provide the names for the general purpose argument & return value registers.
667     static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
668     static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
669     static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
670     static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
671     static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
672     static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
673     static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
674     static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
675     static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
676     static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
677     static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
678     static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
679     static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
680     static const GPRReg nonPreservedNonArgumentGPR = ARM64Registers::x8;
681     static const GPRReg patchpointScratchRegister;
682
683     // GPRReg mapping is direct, the machine register numbers can
684     // be used directly as indices into the GPR RegisterBank.
685     COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
686     COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
687     COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
688     COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
689     COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
690     COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
691     COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
692     COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
693     COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
694     COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
695     COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
696     COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
697     COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
698     COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
699     COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
700     COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
701     static GPRReg toRegister(unsigned index)
702     {
703         return (GPRReg)index;
704     }
705     static unsigned toIndex(GPRReg reg)
706     {
707         if (reg > regT15)
708             return InvalidIndex;
709         return (unsigned)reg;
710     }
711
712     static GPRReg toArgumentRegister(unsigned index)
713     {
714         ASSERT(index < numberOfArgumentRegisters);
715         return toRegister(index);
716     }
717
718     static const char* debugName(GPRReg reg)
719     {
720         ASSERT(reg != InvalidGPRReg);
721         ASSERT(static_cast<unsigned>(reg) < 32);
722         static const char* nameForRegister[32] = {
723             "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
724             "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
725             "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
726             "r24", "r25", "r26", "r27", "r28", "fp", "lr", "sp"
727         };
728         return nameForRegister[reg];
729     }
730
731     static const std::array<GPRReg, 4>& reservedRegisters()
732     {
733         static const std::array<GPRReg, 4> reservedRegisters { {
734             dataTempRegister,
735             memoryTempRegister,
736             tagTypeNumberRegister,
737             tagMaskRegister,
738         } };
739         return reservedRegisters;
740     }
741     
742     static const unsigned InvalidIndex = 0xffffffff;
743 };
744
745 #endif // CPU(ARM64)
746
747 #if CPU(MIPS)
748 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
749 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
750
751 class GPRInfo {
752 public:
753     typedef GPRReg RegisterType;
754     static const unsigned numberOfRegisters = 7;
755     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
756
757     // regT0 must be v0 for returning a 32-bit value.
758     // regT1 must be v1 for returning a pair of 32-bit value.
759
760     // Temporary registers.
761     static const GPRReg regT0 = MIPSRegisters::v0;
762     static const GPRReg regT1 = MIPSRegisters::v1;
763     static const GPRReg regT2 = MIPSRegisters::t2;
764     static const GPRReg regT3 = MIPSRegisters::t3;
765     static const GPRReg regT4 = MIPSRegisters::t4;
766     static const GPRReg regT5 = MIPSRegisters::t5;
767     static const GPRReg regT6 = MIPSRegisters::t6;
768     // These registers match the baseline JIT.
769     static const GPRReg callFrameRegister = MIPSRegisters::fp;
770     // These constants provide the names for the general purpose argument & return value registers.
771     static const GPRReg argumentGPR0 = MIPSRegisters::a0;
772     static const GPRReg argumentGPR1 = MIPSRegisters::a1;
773     static const GPRReg argumentGPR2 = MIPSRegisters::a2;
774     static const GPRReg argumentGPR3 = MIPSRegisters::a3;
775     static const GPRReg nonArgGPR0 = regT4;
776     static const GPRReg returnValueGPR = regT0;
777     static const GPRReg returnValueGPR2 = regT1;
778     static const GPRReg nonPreservedNonReturnGPR = regT2;
779
780     static GPRReg toRegister(unsigned index)
781     {
782         ASSERT(index < numberOfRegisters);
783         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
784         return registerForIndex[index];
785     }
786
787     static GPRReg toArgumentRegister(unsigned index)
788     {
789         ASSERT(index < numberOfArgumentRegisters);
790         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
791         return registerForIndex[index];
792     }
793
794     static unsigned toIndex(GPRReg reg)
795     {
796         ASSERT(reg != InvalidGPRReg);
797         ASSERT(reg < 32);
798         static const unsigned indexForRegister[32] = {
799             InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
800             InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
801             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
802             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
803         };
804         unsigned result = indexForRegister[reg];
805         return result;
806     }
807
808     static const char* debugName(GPRReg reg)
809     {
810         ASSERT(reg != InvalidGPRReg);
811         ASSERT(reg < 16);
812         static const char* nameForRegister[16] = {
813             "zero", "at", "v0", "v1",
814             "a0", "a1", "a2", "a3",
815             "t0", "t1", "t2", "t3",
816             "t4", "t5", "t6", "t7"
817         };
818         return nameForRegister[reg];
819     }
820
821     static const unsigned InvalidIndex = 0xffffffff;
822 };
823
824 #endif // CPU(MIPS)
825
826 #if CPU(SH4)
827 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
828 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
829
830 class GPRInfo {
831 public:
832     typedef GPRReg RegisterType;
833     static const unsigned numberOfRegisters = 10;
834
835     // Note: regT3 is required to be callee-preserved.
836
837     // Temporary registers.
838     static const GPRReg regT0 = SH4Registers::r0;
839     static const GPRReg regT1 = SH4Registers::r1;
840     static const GPRReg regT2 = SH4Registers::r6;
841     static const GPRReg regT3 = SH4Registers::r7;
842     static const GPRReg regT4 = SH4Registers::r2;
843     static const GPRReg regT5 = SH4Registers::r3;
844     static const GPRReg regT6 = SH4Registers::r4;
845     static const GPRReg regT7 = SH4Registers::r5;
846     static const GPRReg regT8 = SH4Registers::r8;
847     static const GPRReg regT9 = SH4Registers::r9;
848     // These registers match the baseline JIT.
849     static const GPRReg cachedResultRegister = regT0;
850     static const GPRReg cachedResultRegister2 = regT1;
851     static const GPRReg callFrameRegister = SH4Registers::fp;
852     // These constants provide the names for the general purpose argument & return value registers.
853     static const GPRReg argumentGPR0 = SH4Registers::r4; // regT6
854     static const GPRReg argumentGPR1 = SH4Registers::r5; // regT7
855     static const GPRReg argumentGPR2 = SH4Registers::r6; // regT2
856     static const GPRReg argumentGPR3 = SH4Registers::r7; // regT3
857     static const GPRReg nonArgGPR0 = regT4;
858     static const GPRReg returnValueGPR = regT0;
859     static const GPRReg returnValueGPR2 = regT1;
860     static const GPRReg nonPreservedNonReturnGPR = regT2;
861
862     static GPRReg toRegister(unsigned index)
863     {
864         ASSERT(index < numberOfRegisters);
865         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9 };
866         return registerForIndex[index];
867     }
868
869     static unsigned toIndex(GPRReg reg)
870     {
871         ASSERT(reg != InvalidGPRReg);
872         ASSERT(reg < 14);
873         static const unsigned indexForRegister[14] = { 0, 1, 4, 5, 6, 7, 2, 3, 8, 9, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
874         unsigned result = indexForRegister[reg];
875         return result;
876     }
877
878     static const char* debugName(GPRReg reg)
879     {
880         ASSERT(reg != InvalidGPRReg);
881         ASSERT(reg < 16);
882         static const char* nameForRegister[16] = {
883             "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
884             "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
885         };
886         return nameForRegister[reg];
887     }
888
889     static const unsigned InvalidIndex = 0xffffffff;
890 };
891
892 #endif // CPU(SH4)
893
894 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
895 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
896 // passing results of one opcode to the next. Hence:
897 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
898 #if USE(JSVALUE32_64)
899 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
900 #endif
901
902 inline GPRReg extractResult(GPRReg result) { return result; }
903 #if USE(JSVALUE64)
904 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
905 #else
906 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
907 #endif
908 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
909
910 #endif // ENABLE(JIT)
911
912 } // namespace JSC
913
914 namespace WTF {
915
916 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
917 {
918 #if ENABLE(JIT)
919     out.print("%", JSC::GPRInfo::debugName(reg));
920 #else
921     out.printf("%%r%d", reg);
922 #endif
923 }
924
925 } // namespace WTF