ffc757d00ae4d3e9a5a310bd6ec7121c40075fd9
[WebKit-https.git] / Source / JavaScriptCore / jit / GPRInfo.h
1 /*
2  * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include "MacroAssembler.h"
29 #include <array>
30 #include <wtf/PrintStream.h>
31
32 namespace JSC {
33
34 enum NoResultTag { NoResult };
35
36 // We use the same conventions in the basline JIT as in the LLint. If you
37 // change mappings in the GPRInfo, you should change them in the offlineasm
38 // compiler adequately. The register naming conventions are described at the
39 // top of the LowLevelInterpreter.asm file.
40
41 typedef MacroAssembler::RegisterID GPRReg;
42 #define InvalidGPRReg ((::JSC::GPRReg)-1)
43
44 #if ENABLE(JIT)
45
46 #if USE(JSVALUE64)
47 class JSValueRegs {
48 public:
49     JSValueRegs()
50         : m_gpr(InvalidGPRReg)
51     {
52     }
53     
54     explicit JSValueRegs(GPRReg gpr)
55         : m_gpr(gpr)
56     {
57     }
58     
59     static JSValueRegs payloadOnly(GPRReg gpr)
60     {
61         return JSValueRegs(gpr);
62     }
63     
64     static JSValueRegs withTwoAvailableRegs(GPRReg gpr, GPRReg)
65     {
66         return JSValueRegs(gpr);
67     }
68     
69     bool operator!() const { return m_gpr == InvalidGPRReg; }
70     explicit operator bool() const { return m_gpr != InvalidGPRReg; }
71
72     bool operator==(JSValueRegs other) { return m_gpr == other.m_gpr; }
73     bool operator!=(JSValueRegs other) { return !(*this == other); }
74     
75     GPRReg gpr() const { return m_gpr; }
76     GPRReg tagGPR() const { return InvalidGPRReg; }
77     GPRReg payloadGPR() const { return m_gpr; }
78     
79     bool uses(GPRReg gpr) const { return m_gpr == gpr; }
80     
81     void dump(PrintStream&) const;
82     
83 private:
84     GPRReg m_gpr;
85 };
86
87 class JSValueSource {
88 public:
89     JSValueSource()
90         : m_offset(notAddress())
91         , m_base(InvalidGPRReg)
92     {
93     }
94     
95     JSValueSource(JSValueRegs regs)
96         : m_offset(notAddress())
97         , m_base(regs.gpr())
98     {
99     }
100     
101     explicit JSValueSource(GPRReg gpr)
102         : m_offset(notAddress())
103         , m_base(gpr)
104     {
105     }
106     
107     JSValueSource(MacroAssembler::Address address)
108         : m_offset(address.offset)
109         , m_base(address.base)
110     {
111         ASSERT(m_offset != notAddress());
112         ASSERT(m_base != InvalidGPRReg);
113     }
114     
115     static JSValueSource unboxedCell(GPRReg payloadGPR)
116     {
117         return JSValueSource(payloadGPR);
118     }
119     
120     bool operator!() const { return m_base == InvalidGPRReg; }
121     explicit operator bool() const { return m_base != InvalidGPRReg; }
122     
123     bool isAddress() const { return m_offset != notAddress(); }
124     
125     int32_t offset() const
126     {
127         ASSERT(isAddress());
128         return m_offset;
129     }
130     
131     GPRReg base() const
132     {
133         ASSERT(isAddress());
134         return m_base;
135     }
136     
137     GPRReg gpr() const
138     {
139         ASSERT(!isAddress());
140         return m_base;
141     }
142     
143     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         return MacroAssembler::gprName(reg);
386     }
387
388     static const unsigned InvalidIndex = 0xffffffff;
389 };
390
391 #endif // CPU(X86)
392
393 #if CPU(X86_64)
394 #if !OS(WINDOWS)
395 #define NUMBER_OF_ARGUMENT_REGISTERS 6u
396 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
397 #else
398 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
399 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
400 #endif
401
402 class GPRInfo {
403 public:
404     typedef GPRReg RegisterType;
405     static const unsigned numberOfRegisters = 11;
406     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
407
408     // These registers match the baseline JIT.
409     static const GPRReg callFrameRegister = X86Registers::ebp;
410     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
411     static const GPRReg tagMaskRegister = X86Registers::r15;
412
413     // Temporary registers.
414     static const GPRReg regT0 = X86Registers::eax;
415 #if !OS(WINDOWS)
416     static const GPRReg regT1 = X86Registers::esi;
417     static const GPRReg regT2 = X86Registers::edx;
418     static const GPRReg regT3 = X86Registers::ecx;
419     static const GPRReg regT4 = X86Registers::r8;
420     static const GPRReg regT5 = X86Registers::r10;
421     static const GPRReg regT6 = X86Registers::edi;
422     static const GPRReg regT7 = X86Registers::r9;
423 #else
424     static const GPRReg regT1 = X86Registers::edx;
425     static const GPRReg regT2 = X86Registers::r8;
426     static const GPRReg regT3 = X86Registers::r9;
427     static const GPRReg regT4 = X86Registers::r10;
428     static const GPRReg regT5 = X86Registers::ecx;
429 #endif
430
431     static const GPRReg regCS0 = X86Registers::ebx;
432
433 #if !OS(WINDOWS)
434     static const GPRReg regCS1 = X86Registers::r12;
435     static const GPRReg regCS2 = X86Registers::r13;
436     static const GPRReg regCS3 = X86Registers::r14;
437     static const GPRReg regCS4 = X86Registers::r15;
438 #else
439     static const GPRReg regCS1 = X86Registers::esi;
440     static const GPRReg regCS2 = X86Registers::edi;
441     static const GPRReg regCS3 = X86Registers::r12;
442     static const GPRReg regCS4 = X86Registers::r13;
443     static const GPRReg regCS5 = X86Registers::r14;
444     static const GPRReg regCS6 = X86Registers::r15;
445 #endif
446
447     // These constants provide the names for the general purpose argument & return value registers.
448 #if !OS(WINDOWS)
449     static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
450     static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
451     static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
452     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
453     static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
454     static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
455 #else
456     static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
457     static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
458     static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
459     static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
460 #endif
461     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
462     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
463     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
464     static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
465     static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
466
467     // FIXME: I believe that all uses of this are dead in the sense that it just causes the scratch
468     // register allocator to select a different register and potentially spill things. It would be better
469     // if we instead had a more explicit way of saying that we don't have a scratch register.
470     static const GPRReg patchpointScratchRegister;
471
472     static GPRReg toRegister(unsigned index)
473     {
474         ASSERT(index < numberOfRegisters);
475 #if !OS(WINDOWS)
476         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
477 #else
478         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
479 #endif
480         return registerForIndex[index];
481     }
482     
483     static GPRReg toArgumentRegister(unsigned index)
484     {
485         ASSERT(index < numberOfArgumentRegisters);
486 #if !OS(WINDOWS)
487         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 };
488 #else
489         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
490 #endif
491         return registerForIndex[index];
492     }
493     
494     static unsigned toIndex(GPRReg reg)
495     {
496         ASSERT(reg != InvalidGPRReg);
497         ASSERT(static_cast<int>(reg) < 16);
498 #if !OS(WINDOWS)
499         static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
500 #else
501         static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
502 #endif
503         return indexForRegister[reg];
504     }
505
506     static const char* debugName(GPRReg reg)
507     {
508         ASSERT(reg != InvalidGPRReg);
509         return MacroAssembler::gprName(reg);
510     }
511
512     static const std::array<GPRReg, 3>& reservedRegisters()
513     {
514         static const std::array<GPRReg, 3> reservedRegisters { {
515             MacroAssembler::s_scratchRegister,
516             tagTypeNumberRegister,
517             tagMaskRegister,
518         } };
519         return reservedRegisters;
520     }
521     
522     static const unsigned InvalidIndex = 0xffffffff;
523 };
524
525 #endif // CPU(X86_64)
526
527 #if CPU(ARM)
528 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
529 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
530
531 class GPRInfo {
532 public:
533     typedef GPRReg RegisterType;
534     static const unsigned numberOfRegisters = 9;
535     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
536
537     // Temporary registers.
538     static const GPRReg regT0 = ARMRegisters::r0;
539     static const GPRReg regT1 = ARMRegisters::r1;
540     static const GPRReg regT2 = ARMRegisters::r2;
541     static const GPRReg regT3 = ARMRegisters::r3;
542     static const GPRReg regT4 = ARMRegisters::r8;
543     static const GPRReg regT5 = ARMRegisters::r9;
544     static const GPRReg regT6 = ARMRegisters::r10;
545 #if CPU(ARM_THUMB2)
546     static const GPRReg regT7 = ARMRegisters::r11;
547 #else 
548     static const GPRReg regT7 = ARMRegisters::r7;
549 #endif
550     static const GPRReg regT8 = ARMRegisters::r4;
551     // These registers match the baseline JIT.
552     static const GPRReg callFrameRegister = ARMRegisters::fp;
553     // These constants provide the names for the general purpose argument & return value registers.
554     static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
555     static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
556     static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
557     static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
558     static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
559     static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
560     static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
561     static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
562     static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
563
564     static GPRReg toRegister(unsigned index)
565     {
566         ASSERT(index < numberOfRegisters);
567         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
568         return registerForIndex[index];
569     }
570
571     static GPRReg toArgumentRegister(unsigned index)
572     {
573         ASSERT(index < numberOfArgumentRegisters);
574         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
575         return registerForIndex[index];
576     }
577
578     static unsigned toIndex(GPRReg reg)
579     {
580         ASSERT(reg != InvalidGPRReg);
581         ASSERT(static_cast<int>(reg) < 16);
582         static const unsigned indexForRegister[16] =
583 #if CPU(ARM_THUMB2)
584             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
585 #else
586             { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
587 #endif
588         unsigned result = indexForRegister[reg];
589         return result;
590     }
591
592     static const char* debugName(GPRReg reg)
593     {
594         ASSERT(reg != InvalidGPRReg);
595         return MacroAssembler::gprName(reg);
596     }
597
598     static const unsigned InvalidIndex = 0xffffffff;
599 };
600
601 #endif // CPU(ARM)
602
603 #if CPU(ARM64)
604 #define NUMBER_OF_ARGUMENT_REGISTERS 8u
605 // Callee Saves includes x19..x28 and FP registers q8..q15
606 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
607
608 class GPRInfo {
609 public:
610     typedef GPRReg RegisterType;
611     static const unsigned numberOfRegisters = 16;
612     static const unsigned numberOfArgumentRegisters = 8;
613
614     // These registers match the baseline JIT.
615     static const GPRReg callFrameRegister = ARM64Registers::fp;
616     static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
617     static const GPRReg tagMaskRegister = ARM64Registers::x28;
618     static const GPRReg dataTempRegister = MacroAssembler::dataTempRegister;
619     static const GPRReg memoryTempRegister = MacroAssembler::memoryTempRegister;
620     // Temporary registers.
621     static const GPRReg regT0 = ARM64Registers::x0;
622     static const GPRReg regT1 = ARM64Registers::x1;
623     static const GPRReg regT2 = ARM64Registers::x2;
624     static const GPRReg regT3 = ARM64Registers::x3;
625     static const GPRReg regT4 = ARM64Registers::x4;
626     static const GPRReg regT5 = ARM64Registers::x5;
627     static const GPRReg regT6 = ARM64Registers::x6;
628     static const GPRReg regT7 = ARM64Registers::x7;
629     static const GPRReg regT8 = ARM64Registers::x8;
630     static const GPRReg regT9 = ARM64Registers::x9;
631     static const GPRReg regT10 = ARM64Registers::x10;
632     static const GPRReg regT11 = ARM64Registers::x11;
633     static const GPRReg regT12 = ARM64Registers::x12;
634     static const GPRReg regT13 = ARM64Registers::x13;
635     static const GPRReg regT14 = ARM64Registers::x14;
636     static const GPRReg regT15 = ARM64Registers::x15;
637     static const GPRReg regCS0 = ARM64Registers::x19; // Used by FTL only
638     static const GPRReg regCS1 = ARM64Registers::x20; // Used by FTL only
639     static const GPRReg regCS2 = ARM64Registers::x21; // Used by FTL only
640     static const GPRReg regCS3 = ARM64Registers::x22; // Used by FTL only
641     static const GPRReg regCS4 = ARM64Registers::x23; // Used by FTL only
642     static const GPRReg regCS5 = ARM64Registers::x24; // Used by FTL only
643     static const GPRReg regCS6 = ARM64Registers::x25; // Used by FTL only
644     static const GPRReg regCS7 = ARM64Registers::x26;
645     static const GPRReg regCS8 = ARM64Registers::x27; // tagTypeNumber
646     static const GPRReg regCS9 = ARM64Registers::x28; // tagMask
647     // These constants provide the names for the general purpose argument & return value registers.
648     static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
649     static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
650     static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
651     static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
652     static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
653     static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
654     static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
655     static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
656     static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
657     static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
658     static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
659     static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
660     static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
661     static const GPRReg nonPreservedNonArgumentGPR = ARM64Registers::x8;
662     static const GPRReg patchpointScratchRegister;
663
664     // GPRReg mapping is direct, the machine register numbers can
665     // be used directly as indices into the GPR RegisterBank.
666     COMPILE_ASSERT(ARM64Registers::q0 == 0, q0_is_0);
667     COMPILE_ASSERT(ARM64Registers::q1 == 1, q1_is_1);
668     COMPILE_ASSERT(ARM64Registers::q2 == 2, q2_is_2);
669     COMPILE_ASSERT(ARM64Registers::q3 == 3, q3_is_3);
670     COMPILE_ASSERT(ARM64Registers::q4 == 4, q4_is_4);
671     COMPILE_ASSERT(ARM64Registers::q5 == 5, q5_is_5);
672     COMPILE_ASSERT(ARM64Registers::q6 == 6, q6_is_6);
673     COMPILE_ASSERT(ARM64Registers::q7 == 7, q7_is_7);
674     COMPILE_ASSERT(ARM64Registers::q8 == 8, q8_is_8);
675     COMPILE_ASSERT(ARM64Registers::q9 == 9, q9_is_9);
676     COMPILE_ASSERT(ARM64Registers::q10 == 10, q10_is_10);
677     COMPILE_ASSERT(ARM64Registers::q11 == 11, q11_is_11);
678     COMPILE_ASSERT(ARM64Registers::q12 == 12, q12_is_12);
679     COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
680     COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
681     COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
682     static GPRReg toRegister(unsigned index)
683     {
684         return (GPRReg)index;
685     }
686     static unsigned toIndex(GPRReg reg)
687     {
688         if (reg > regT15)
689             return InvalidIndex;
690         return (unsigned)reg;
691     }
692
693     static GPRReg toArgumentRegister(unsigned index)
694     {
695         ASSERT(index < numberOfArgumentRegisters);
696         return toRegister(index);
697     }
698
699     static const char* debugName(GPRReg reg)
700     {
701         ASSERT(reg != InvalidGPRReg);
702         return MacroAssembler::gprName(reg);
703     }
704
705     static const std::array<GPRReg, 4>& reservedRegisters()
706     {
707         static const std::array<GPRReg, 4> reservedRegisters { {
708             dataTempRegister,
709             memoryTempRegister,
710             tagTypeNumberRegister,
711             tagMaskRegister,
712         } };
713         return reservedRegisters;
714     }
715     
716     static const unsigned InvalidIndex = 0xffffffff;
717 };
718
719 #endif // CPU(ARM64)
720
721 #if CPU(MIPS)
722 #define NUMBER_OF_ARGUMENT_REGISTERS 4u
723 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
724
725 class GPRInfo {
726 public:
727     typedef GPRReg RegisterType;
728     static const unsigned numberOfRegisters = 7;
729     static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
730
731     // regT0 must be v0 for returning a 32-bit value.
732     // regT1 must be v1 for returning a pair of 32-bit value.
733
734     // Temporary registers.
735     static const GPRReg regT0 = MIPSRegisters::v0;
736     static const GPRReg regT1 = MIPSRegisters::v1;
737     static const GPRReg regT2 = MIPSRegisters::t2;
738     static const GPRReg regT3 = MIPSRegisters::t3;
739     static const GPRReg regT4 = MIPSRegisters::t4;
740     static const GPRReg regT5 = MIPSRegisters::t5;
741     static const GPRReg regT6 = MIPSRegisters::t6;
742     // These registers match the baseline JIT.
743     static const GPRReg callFrameRegister = MIPSRegisters::fp;
744     // These constants provide the names for the general purpose argument & return value registers.
745     static const GPRReg argumentGPR0 = MIPSRegisters::a0;
746     static const GPRReg argumentGPR1 = MIPSRegisters::a1;
747     static const GPRReg argumentGPR2 = MIPSRegisters::a2;
748     static const GPRReg argumentGPR3 = MIPSRegisters::a3;
749     static const GPRReg nonArgGPR0 = regT4;
750     static const GPRReg returnValueGPR = regT0;
751     static const GPRReg returnValueGPR2 = regT1;
752     static const GPRReg nonPreservedNonReturnGPR = regT2;
753
754     static GPRReg toRegister(unsigned index)
755     {
756         ASSERT(index < numberOfRegisters);
757         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
758         return registerForIndex[index];
759     }
760
761     static GPRReg toArgumentRegister(unsigned index)
762     {
763         ASSERT(index < numberOfArgumentRegisters);
764         static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 };
765         return registerForIndex[index];
766     }
767
768     static unsigned toIndex(GPRReg reg)
769     {
770         ASSERT(reg != InvalidGPRReg);
771         ASSERT(reg < 32);
772         static const unsigned indexForRegister[32] = {
773             InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
774             InvalidIndex, InvalidIndex, 2, 3, 4, 5, 6, InvalidIndex,
775             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
776             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
777         };
778         unsigned result = indexForRegister[reg];
779         return result;
780     }
781
782     static const char* debugName(GPRReg reg)
783     {
784         ASSERT(reg != InvalidGPRReg);
785         return MacroAssembler::gprName(reg);
786     }
787
788     static const unsigned InvalidIndex = 0xffffffff;
789 };
790
791 #endif // CPU(MIPS)
792
793 // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit)
794 // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
795 // passing results of one opcode to the next. Hence:
796 COMPILE_ASSERT(GPRInfo::regT0 == GPRInfo::returnValueGPR, regT0_must_equal_returnValueGPR);
797 #if USE(JSVALUE32_64)
798 COMPILE_ASSERT(GPRInfo::regT1 == GPRInfo::returnValueGPR2, regT1_must_equal_returnValueGPR2);
799 #endif
800
801 inline GPRReg extractResult(GPRReg result) { return result; }
802 #if USE(JSVALUE64)
803 inline GPRReg extractResult(JSValueRegs result) { return result.gpr(); }
804 #else
805 inline JSValueRegs extractResult(JSValueRegs result) { return result; }
806 #endif
807 inline NoResultTag extractResult(NoResultTag) { return NoResult; }
808
809 #endif // ENABLE(JIT)
810
811 } // namespace JSC
812
813 namespace WTF {
814
815 inline void printInternal(PrintStream& out, JSC::GPRReg reg)
816 {
817 #if ENABLE(JIT)
818     out.print("%", JSC::GPRInfo::debugName(reg));
819 #else
820     out.printf("%%r%d", reg);
821 #endif
822 }
823
824 } // namespace WTF