JSVALUE64: Pass arguments in platform argument registers when making JavaScript calls
[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) const { return m_gpr == other.m_gpr; }
73     bool operator!=(JSValueRegs other) const { 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_JS_FUNCTION_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 nonArgGPR1 = X86Registers::edi; // regT5
358     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
359     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
360     static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
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 unsigned toArgumentIndex(GPRReg reg)
385     {
386         ASSERT(reg != InvalidGPRReg);
387         ASSERT(static_cast<int>(reg) < 8);
388         static const unsigned indexForArgumentRegister[8] = { 2, 0, 1, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
389         return indexForArgumentRegister[reg];
390     }
391
392     static const char* debugName(GPRReg reg)
393     {
394         ASSERT(reg != InvalidGPRReg);
395         ASSERT(static_cast<int>(reg) < 8);
396         static const char* nameForRegister[8] = {
397             "eax", "ecx", "edx", "ebx",
398             "esp", "ebp", "esi", "edi",
399         };
400         return nameForRegister[reg];
401     }
402
403     static const unsigned InvalidIndex = 0xffffffff;
404 };
405
406 #endif // CPU(X86)
407
408 #if CPU(X86_64)
409 #if !OS(WINDOWS)
410 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
411 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
412 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS (NUMBER_OF_ARGUMENT_REGISTERS - 2u)
413 #else
414 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
415 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
416 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
417 #endif
418
419 class GPRInfo {
420 public:
421     typedef GPRReg RegisterType;
422     static const unsigned numberOfRegisters = 11;
423     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
424
425     // These registers match the baseline JIT.
426     static const GPRReg callFrameRegister = X86Registers::ebp;
427     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
428     static const GPRReg tagMaskRegister = X86Registers::r15;
429
430     // Temporary registers.
431     static const GPRReg regT0 = X86Registers::eax;
432 #if !OS(WINDOWS)
433     static const GPRReg regT1 = X86Registers::esi;
434     static const GPRReg regT2 = X86Registers::edx;
435     static const GPRReg regT3 = X86Registers::ecx;
436     static const GPRReg regT4 = X86Registers::r8;
437     static const GPRReg regT5 = X86Registers::r10;
438     static const GPRReg regT6 = X86Registers::edi;
439     static const GPRReg regT7 = X86Registers::r9;
440 #else
441     static const GPRReg regT1 = X86Registers::edx;
442     static const GPRReg regT2 = X86Registers::r8;
443     static const GPRReg regT3 = X86Registers::r9;
444     static const GPRReg regT4 = X86Registers::r10;
445     static const GPRReg regT5 = X86Registers::ecx;
446 #endif
447
448     static const GPRReg regCS0 = X86Registers::ebx;
449
450 #if !OS(WINDOWS)
451     static const GPRReg regCS1 = X86Registers::r12;
452     static const GPRReg regCS2 = X86Registers::r13;
453     static const GPRReg regCS3 = X86Registers::r14;
454     static const GPRReg regCS4 = X86Registers::r15;
455 #else
456     static const GPRReg regCS1 = X86Registers::esi;
457     static const GPRReg regCS2 = X86Registers::edi;
458     static const GPRReg regCS3 = X86Registers::r12;
459     static const GPRReg regCS4 = X86Registers::r13;
460     static const GPRReg regCS5 = X86Registers::r14;
461     static const GPRReg regCS6 = X86Registers::r15;
462 #endif
463
464     // These constants provide the names for the general purpose argument & return value registers.
465 #if !OS(WINDOWS)
466     static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
467     static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
468     static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
469     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
470     static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
471     static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
472 #else
473     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
474     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
475     static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
476     static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
477 #endif
478     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
479     static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
480     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
481     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
482     static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
483     static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
484
485     // FIXME: I believe that all uses of this are dead in the sense that it just causes the scratch
486     // register allocator to select a different register and potentially spill things. It would be better
487     // if we instead had a more explicit way of saying that we don't have a scratch register.
488     static const GPRReg patchpointScratchRegister;
489
490     static GPRReg toRegister(unsigned index)
491     {
492         ASSERT(index < numberOfRegisters);
493 #if !OS(WINDOWS)
494         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
495 #else
496         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
497 #endif
498         return registerForIndex[index];
499     }
500     
501     static GPRReg toArgumentRegister(unsigned index)
502     {
503         ASSERT(index < numberOfArgumentRegisters);
504 #if !OS(WINDOWS)
505         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 };
506 #else
507         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
508 #endif
509         return registerForIndex[index];
510     }
511     
512     static unsigned toIndex(GPRReg reg)
513     {
514         ASSERT(reg != InvalidGPRReg);
515         ASSERT(static_cast<int>(reg) < 16);
516 #if !OS(WINDOWS)
517         static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
518 #else
519         static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
520 #endif
521         return indexForRegister[reg];
522     }
523
524     static unsigned toArgumentIndex(GPRReg reg)
525     {
526         ASSERT(reg != InvalidGPRReg);
527         ASSERT(static_cast<int>(reg) < 16);
528 #if !OS(WINDOWS)
529         static const unsigned indexForArgumentRegister[16] = { InvalidIndex, 3, 2, InvalidIndex, InvalidIndex, InvalidIndex, 1, 0, 4, 5, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
530 #else
531         static const unsigned indexForArgumentRegister[16] = { InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
532 #endif
533         return indexForArgumentRegister[reg];
534     }
535     
536     static const char* debugName(GPRReg reg)
537     {
538         ASSERT(reg != InvalidGPRReg);
539         ASSERT(static_cast<int>(reg) < 16);
540         static const char* nameForRegister[16] = {
541             "rax", "rcx", "rdx", "rbx",
542             "rsp", "rbp", "rsi", "rdi",
543             "r8", "r9", "r10", "r11",
544             "r12", "r13", "r14", "r15"
545         };
546         return nameForRegister[reg];
547     }
548
549     static const std::array<GPRReg, 3>& reservedRegisters()
550     {
551         static const std::array<GPRReg, 3> reservedRegisters { {
552             MacroAssembler::s_scratchRegister,
553             tagTypeNumberRegister,
554             tagMaskRegister,
555         } };
556         return reservedRegisters;
557     }
558     
559     static const unsigned InvalidIndex = 0xffffffff;
560 };
561
562 #endif // CPU(X86_64)
563
564 #if CPU(ARM)
565 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
566 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
567 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
568
569 class GPRInfo {
570 public:
571     typedef GPRReg RegisterType;
572     static const unsigned numberOfRegisters = 9;
573     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
574
575     // Temporary registers.
576     static const GPRReg regT0 = ARMRegisters::r0;
577     static const GPRReg regT1 = ARMRegisters::r1;
578     static const GPRReg regT2 = ARMRegisters::r2;
579     static const GPRReg regT3 = ARMRegisters::r3;
580     static const GPRReg regT4 = ARMRegisters::r8;
581     static const GPRReg regT5 = ARMRegisters::r9;
582     static const GPRReg regT6 = ARMRegisters::r10;
583 #if CPU(ARM_THUMB2)
584     static const GPRReg regT7 = ARMRegisters::r11;
585 #else 
586     static const GPRReg regT7 = ARMRegisters::r7;
587 #endif
588     static const GPRReg regT8 = ARMRegisters::r4;
589     // These registers match the baseline JIT.
590     static const GPRReg callFrameRegister = ARMRegisters::fp;
591     // These constants provide the names for the general purpose argument & return value registers.
592     static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
593     static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
594     static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
595     static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
596     static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
597     static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
598     static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
599     static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
600     static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
601
602     static GPRReg toRegister(unsigned index)
603     {
604         ASSERT(index < numberOfRegisters);
605         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
606         return registerForIndex[index];
607     }
608
609     static GPRReg toArgumentRegister(unsigned index)
610     {
611         ASSERT(index < numberOfArgumentRegisters);
612         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
613         return registerForIndex[index];
614     }
615
616     static unsigned toIndex(GPRReg reg)
617     {
618         ASSERT(reg != InvalidGPRReg);
619         ASSERT(static_cast<int>(reg) < 16);
620         static const unsigned indexForRegister[16] =
621 #if CPU(ARM_THUMB2)
622             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
623 #else
624             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
625 #endif
626         unsigned result = indexForRegister[reg];
627         return result;
628     }
629
630     static unsigned toArgumentIndex(GPRReg reg)
631     {
632         ASSERT(reg != InvalidGPRReg);
633         ASSERT(static_cast<int>(reg) < 16);
634         if (reg > argumentGPR3)
635             return InvalidIndex;
636         return (unsigned)reg;
637     }
638     
639     static const char* debugName(GPRReg reg)
640     {
641         ASSERT(reg != InvalidGPRReg);
642         ASSERT(static_cast<int>(reg) < 16);
643         static const char* nameForRegister[16] = {
644             "r0", "r1", "r2", "r3",
645             "r4", "r5", "r6", "r7",
646             "r8", "r9", "r10", "r11",
647             "r12", "r13", "r14", "r15"
648         };
649         return nameForRegister[reg];
650     }
651
652     static const unsigned InvalidIndex = 0xffffffff;
653 };
654
655 #endif // CPU(ARM)
656
657 #if CPU(ARM64)
658 #define NUMBER_OF_ARGUMENT_REGISTERS 8u
659 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS (NUMBER_OF_ARGUMENT_REGISTERS - 2u)
660 // Callee Saves includes x19..x28 and FP registers q8..q15
661 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
662
663 class GPRInfo {
664 public:
665     typedef GPRReg RegisterType;
666     static const unsigned numberOfRegisters = 16;
667     static const unsigned numberOfArgumentRegisters = 8;
668
669     // These registers match the baseline JIT.
670     static const GPRReg callFrameRegister = ARM64Registers::fp;
671     static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
672     static const GPRReg tagMaskRegister = ARM64Registers::x28;
673     static const GPRReg dataTempRegister = MacroAssembler::dataTempRegister;
674     static const GPRReg memoryTempRegister = MacroAssembler::memoryTempRegister;
675     // Temporary registers.
676     static const GPRReg regT0 = ARM64Registers::x0;
677     static const GPRReg regT1 = ARM64Registers::x1;
678     static const GPRReg regT2 = ARM64Registers::x2;
679     static const GPRReg regT3 = ARM64Registers::x3;
680     static const GPRReg regT4 = ARM64Registers::x4;
681     static const GPRReg regT5 = ARM64Registers::x5;
682     static const GPRReg regT6 = ARM64Registers::x6;
683     static const GPRReg regT7 = ARM64Registers::x7;
684     static const GPRReg regT8 = ARM64Registers::x8;
685     static const GPRReg regT9 = ARM64Registers::x9;
686     static const GPRReg regT10 = ARM64Registers::x10;
687     static const GPRReg regT11 = ARM64Registers::x11;
688     static const GPRReg regT12 = ARM64Registers::x12;
689     static const GPRReg regT13 = ARM64Registers::x13;
690     static const GPRReg regT14 = ARM64Registers::x14;
691     static const GPRReg regT15 = ARM64Registers::x15;
692     static const GPRReg regCS0 = ARM64Registers::x19; // Used by FTL only
693     static const GPRReg regCS1 = ARM64Registers::x20; // Used by FTL only
694     static const GPRReg regCS2 = ARM64Registers::x21; // Used by FTL only
695     static const GPRReg regCS3 = ARM64Registers::x22; // Used by FTL only
696     static const GPRReg regCS4 = ARM64Registers::x23; // Used by FTL only
697     static const GPRReg regCS5 = ARM64Registers::x24; // Used by FTL only
698     static const GPRReg regCS6 = ARM64Registers::x25; // Used by FTL only
699     static const GPRReg regCS7 = ARM64Registers::x26;
700     static const GPRReg regCS8 = ARM64Registers::x27; // tagTypeNumber
701     static const GPRReg regCS9 = ARM64Registers::x28; // tagMask
702     // These constants provide the names for the general purpose argument & return value registers.
703     static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
704     static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
705     static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
706     static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
707     static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
708     static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
709     static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
710     static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
711     static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
712     static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
713     static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
714     static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
715     static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
716     static const GPRReg nonPreservedNonArgumentGPR = ARM64Registers::x8;
717     static const GPRReg patchpointScratchRegister;
718
719     // GPRReg mapping is direct, the machine register numbers can
720     // be used directly as indices into the GPR RegisterBank.
721     COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
722     COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
723     COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
724     COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
725     COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
726     COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
727     COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
728     COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
729     COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
730     COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
731     COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
732     COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
733     COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
734     COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
735     COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
736     COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
737
738     static GPRReg toRegister(unsigned index)
739     {
740         return (GPRReg)index;
741     }
742     static unsigned toIndex(GPRReg reg)
743     {
744         if (reg > regT15)
745             return InvalidIndex;
746         return (unsigned)reg;
747     }
748
749     static GPRReg toArgumentRegister(unsigned index)
750     {
751         ASSERT(index < numberOfArgumentRegisters);
752         return toRegister(index);
753     }
754
755     static unsigned toArgumentIndex(GPRReg reg)
756     {
757         ASSERT(reg != InvalidGPRReg);
758         if (reg > argumentGPR7)
759             return InvalidIndex;
760         return (unsigned)reg;
761     }
762
763     static const char* debugName(GPRReg reg)
764     {
765         ASSERT(reg != InvalidGPRReg);
766         ASSERT(static_cast<unsigned>(reg) < 32);
767         static const char* nameForRegister[32] = {
768             "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
769             "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
770             "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
771             "r24", "r25", "r26", "r27", "r28", "fp", "lr", "sp"
772         };
773         return nameForRegister[reg];
774     }
775
776     static const std::array<GPRReg, 4>& reservedRegisters()
777     {
778         static const std::array<GPRReg, 4> reservedRegisters { {
779             dataTempRegister,
780             memoryTempRegister,
781             tagTypeNumberRegister,
782             tagMaskRegister,
783         } };
784         return reservedRegisters;
785     }
786     
787     static const unsigned InvalidIndex = 0xffffffff;
788 };
789
790 #endif // CPU(ARM64)
791
792 #if CPU(MIPS)
793 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
794 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
795 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
796
797 class GPRInfo {
798 public:
799     typedef GPRReg RegisterType;
800     static const unsigned numberOfRegisters = 7;
801     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
802
803     // regT0 must be v0 for returning a 32-bit value.
804     // regT1 must be v1 for returning a pair of 32-bit value.
805
806     // Temporary registers.
807     static const GPRReg regT0 = MIPSRegisters::v0;
808     static const GPRReg regT1 = MIPSRegisters::v1;
809     static const GPRReg regT2 = MIPSRegisters::t2;
810     static const GPRReg regT3 = MIPSRegisters::t3;
811     static const GPRReg regT4 = MIPSRegisters::t4;
812     static const GPRReg regT5 = MIPSRegisters::t5;
813     static const GPRReg regT6 = MIPSRegisters::t6;
814     // These registers match the baseline JIT.
815     static const GPRReg callFrameRegister = MIPSRegisters::fp;
816     // These constants provide the names for the general purpose argument & return value registers.
817     static const GPRReg argumentGPR0 = MIPSRegisters::a0;
818     static const GPRReg argumentGPR1 = MIPSRegisters::a1;
819     static const GPRReg argumentGPR2 = MIPSRegisters::a2;
820     static const GPRReg argumentGPR3 = MIPSRegisters::a3;
821     static const GPRReg nonArgGPR0 = regT4;
822     static const GPRReg nonArgGPR1 = regT5;
823     static const GPRReg returnValueGPR = regT0;
824     static const GPRReg returnValueGPR2 = regT1;
825     static const GPRReg nonPreservedNonReturnGPR = regT2;
826
827     static GPRReg toRegister(unsigned index)
828     {
829         ASSERT(index < numberOfRegisters);
830         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
831         return registerForIndex[index];
832     }
833
834     static GPRReg toArgumentRegister(unsigned index)
835     {
836         ASSERT(index < numberOfArgumentRegisters);
837         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
838         return registerForIndex[index];
839     }
840
841     static unsigned toIndex(GPRReg reg)
842     {
843         ASSERT(reg != InvalidGPRReg);
844         ASSERT(reg < 32);
845         static const unsigned indexForRegister[32] = {
846             InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
847             InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
848             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
849             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
850         };
851         unsigned result = indexForRegister[reg];
852         return result;
853     }
854
855     static const char* debugName(GPRReg reg)
856     {
857         ASSERT(reg != InvalidGPRReg);
858         ASSERT(reg < 16);
859         static const char* nameForRegister[16] = {
860             "zero", "at", "v0", "v1",
861             "a0", "a1", "a2", "a3",
862             "t0", "t1", "t2", "t3",
863             "t4", "t5", "t6", "t7"
864         };
865         return nameForRegister[reg];
866     }
867
868     static const unsigned InvalidIndex = 0xffffffff;
869 };
870
871 #endif // CPU(MIPS)
872
873 #if CPU(SH4)
874 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
875 #define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
876 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
877
878 class GPRInfo {
879 public:
880     typedef GPRReg RegisterType;
881     static const unsigned numberOfRegisters = 10;
882
883     // Note: regT3 is required to be callee-preserved.
884
885     // Temporary registers.
886     static const GPRReg regT0 = SH4Registers::r0;
887     static const GPRReg regT1 = SH4Registers::r1;
888     static const GPRReg regT2 = SH4Registers::r6;
889     static const GPRReg regT3 = SH4Registers::r7;
890     static const GPRReg regT4 = SH4Registers::r2;
891     static const GPRReg regT5 = SH4Registers::r3;
892     static const GPRReg regT6 = SH4Registers::r4;
893     static const GPRReg regT7 = SH4Registers::r5;
894     static const GPRReg regT8 = SH4Registers::r8;
895     static const GPRReg regT9 = SH4Registers::r9;
896     // These registers match the baseline JIT.
897     static const GPRReg cachedResultRegister = regT0;
898     static const GPRReg cachedResultRegister2 = regT1;
899     static const GPRReg callFrameRegister = SH4Registers::fp;
900     // These constants provide the names for the general purpose argument & return value registers.
901     static const GPRReg argumentGPR0 = SH4Registers::r4; // regT6
902     static const GPRReg argumentGPR1 = SH4Registers::r5; // regT7
903     static const GPRReg argumentGPR2 = SH4Registers::r6; // regT2
904     static const GPRReg argumentGPR3 = SH4Registers::r7; // regT3
905     static const GPRReg nonArgGPR0 = regT4;
906     static const GPRReg nonArgGPR1 = regT5;
907     static const GPRReg returnValueGPR = regT0;
908     static const GPRReg returnValueGPR2 = regT1;
909     static const GPRReg nonPreservedNonReturnGPR = regT2;
910
911     static GPRReg toRegister(unsigned index)
912     {
913         ASSERT(index < numberOfRegisters);
914         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9 };
915         return registerForIndex[index];
916     }
917
918     static unsigned toIndex(GPRReg reg)
919     {
920         ASSERT(reg != InvalidGPRReg);
921         ASSERT(reg < 14);
922         static const unsigned indexForRegister[14] = { 0, 1, 4, 5, 6, 7, 2, 3, 8, 9, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
923         unsigned result = indexForRegister[reg];
924         return result;
925     }
926
927     static const char* debugName(GPRReg reg)
928     {
929         ASSERT(reg != InvalidGPRReg);
930         ASSERT(reg < 16);
931         static const char* nameForRegister[16] = {
932             "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
933             "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
934         };
935         return nameForRegister[reg];
936     }
937
938     static const unsigned InvalidIndex = 0xffffffff;
939 };
940
941 #endif // CPU(SH4)
942
943 inline GPRReg argumentRegisterFor(unsigned argumentIndex)
944 {
945 #if NUMBER_OF_ARGUMENT_REGISTERS
946     if (argumentIndex >= NUMBER_OF_ARGUMENT_REGISTERS)
947         return InvalidGPRReg;
948     return GPRInfo::toArgumentRegister(argumentIndex);
949 #else
950     UNUSED_PARAM(argumentIndex);
951     RELEASE_ASSERT_NOT_REACHED();
952     return InvalidGPRReg;
953 #endif
954 }
955
956 inline GPRReg argumentRegisterForCallee()
957 {
958 #if NUMBER_OF_ARGUMENT_REGISTERS
959     return argumentRegisterFor(0);
960 #else
961     return GPRInfo::regT0;
962 #endif
963 }
964
965 inline GPRReg argumentRegisterForArgumentCount()
966 {
967     return argumentRegisterFor(1);
968 }
969
970 inline unsigned argumentRegisterIndexForJSFunctionArgument(unsigned argument)
971 {
972     return argument + 2;
973 }
974
975 inline unsigned jsFunctionArgumentForArgumentRegisterIndex(unsigned index)
976 {
977 #if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS > 0
978     ASSERT(index >= 2);
979     return index - 2;
980 #else
981     UNUSED_PARAM(index);
982     RELEASE_ASSERT_NOT_REACHED();
983     return 0;
984 #endif
985 }
986
987 inline unsigned jsFunctionArgumentForArgumentRegister(GPRReg gpr)
988 {
989 #if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS > 0
990     unsigned argumentRegisterIndex = GPRInfo::toArgumentIndex(gpr);
991     ASSERT(argumentRegisterIndex != GPRInfo::InvalidIndex);
992     return jsFunctionArgumentForArgumentRegisterIndex(argumentRegisterIndex);
993 #else
994     UNUSED_PARAM(gpr);
995     RELEASE_ASSERT_NOT_REACHED();
996     return 0;
997 #endif
998 }
999
1000 inline GPRReg argumentRegisterForFunctionArgument(unsigned argumentIndex)
1001 {
1002     return argumentRegisterFor(argumentRegisterIndexForJSFunctionArgument(argumentIndex));
1003 }
1004
1005 inline unsigned numberOfRegisterArgumentsFor(unsigned argumentCount)
1006 {
1007     return std::min(argumentCount, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
1008 }
1009
1010 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
1011 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
1012 // passing results of one opcode to the next. Hence:
1013 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
1014 #if USE(JSVALUE32_64)
1015 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
1016 #endif
1017
1018 inline GPRReg extractResult(GPRReg result) { return result; }
1019 #if USE(JSVALUE64)
1020 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
1021 #else
1022 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
1023 #endif
1024 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
1025
1026 #endif // ENABLE(JIT)
1027
1028 } // namespace JSC
1029
1030 namespace WTF {
1031
1032 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
1033 {
1034 #if ENABLE(JIT)
1035     out.print("%", JSC::GPRInfo::debugName(reg));
1036 #else
1037     out.printf("%%r%d", reg);
1038 #endif
1039 }
1040
1041 } // namespace WTF