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