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