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