1/* 2 * Copyright (C) 2011 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 DFGGPRInfo_h 27#define DFGGPRInfo_h 28 29#include <wtf/Platform.h> 30 31#if ENABLE(DFG_JIT) 32 33#include "DFGRegisterBank.h" 34#include "MacroAssembler.h" 35 36namespace JSC { namespace DFG { 37 38typedef MacroAssembler::RegisterID GPRReg; 39#define InvalidGPRReg ((GPRReg)-1) 40 41#if USE(JSVALUE64) 42class JSValueRegs { 43public: 44 JSValueRegs() 45 : m_gpr(InvalidGPRReg) 46 { 47 } 48 49 explicit JSValueRegs(GPRReg gpr) 50 : m_gpr(gpr) 51 { 52 } 53 54 bool operator!() const { return m_gpr == InvalidGPRReg; } 55 56 GPRReg gpr() const { return m_gpr; } 57 58private: 59 GPRReg m_gpr; 60}; 61 62class JSValueSource { 63public: 64 JSValueSource() 65 : m_offset(notAddress()) 66 , m_base(InvalidGPRReg) 67 { 68 } 69 70 JSValueSource(JSValueRegs regs) 71 : m_offset(notAddress()) 72 , m_base(regs.gpr()) 73 { 74 } 75 76 explicit JSValueSource(GPRReg gpr) 77 : m_offset(notAddress()) 78 , m_base(gpr) 79 { 80 } 81 82 JSValueSource(MacroAssembler::Address address) 83 : m_offset(address.offset) 84 , m_base(address.base) 85 { 86 ASSERT(m_offset != notAddress()); 87 ASSERT(m_base != InvalidGPRReg); 88 } 89 90 static JSValueSource unboxedCell(GPRReg payloadGPR) 91 { 92 return JSValueSource(payloadGPR); 93 } 94 95 bool operator!() const { return m_base == InvalidGPRReg; } 96 97 bool isAddress() const { return m_offset != notAddress(); } 98 99 int32_t offset() const 100 { 101 ASSERT(isAddress()); 102 return m_offset; 103 } 104 105 GPRReg base() const 106 { 107 ASSERT(isAddress()); 108 return m_base; 109 } 110 111 GPRReg gpr() const 112 { 113 ASSERT(!isAddress()); 114 return m_base; 115 } 116 117 MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); } 118 119private: 120 static inline int32_t notAddress() { return 0x80000000; } 121 122 int32_t m_offset; 123 GPRReg m_base; 124}; 125#endif 126 127#if USE(JSVALUE32_64) 128class JSValueRegs { 129public: 130 JSValueRegs() 131 : m_tagGPR(static_cast<int8_t>(InvalidGPRReg)) 132 , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg)) 133 { 134 } 135 136 JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR) 137 : m_tagGPR(tagGPR) 138 , m_payloadGPR(payloadGPR) 139 { 140 ASSERT((static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg) == (static_cast<GPRReg>(payloadGPR) == InvalidGPRReg)); 141 } 142 143 bool operator!() const { return static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg; } 144 145 GPRReg tagGPR() const { return static_cast<GPRReg>(m_tagGPR); } 146 GPRReg payloadGPR() const { return static_cast<GPRReg>(m_payloadGPR); } 147 148private: 149 int8_t m_tagGPR; 150 int8_t m_payloadGPR; 151}; 152 153class JSValueSource { 154public: 155 JSValueSource() 156 : m_offset(notAddress()) 157 , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg)) 158 , m_payload(static_cast<int8_t>(InvalidGPRReg)) 159 , m_tagType(0) 160 { 161 } 162 163 JSValueSource(JSValueRegs regs) 164 : m_offset(notAddress()) 165 , m_baseOrTag(regs.tagGPR()) 166 , m_payload(regs.payloadGPR()) 167 , m_tagType(0) 168 { 169 } 170 171 JSValueSource(GPRReg tagGPR, GPRReg payloadGPR) 172 : m_offset(notAddress()) 173 , m_baseOrTag(static_cast<int8_t>(tagGPR)) 174 , m_payload(static_cast<int8_t>(payloadGPR)) 175 , m_tagType(0) 176 { 177 } 178 179 JSValueSource(MacroAssembler::Address address) 180 : m_offset(address.offset) 181 , m_baseOrTag(static_cast<int8_t>(address.base)) 182 , m_payload(static_cast<int8_t>(InvalidGPRReg)) 183 , m_tagType(0) 184 { 185 ASSERT(m_offset != notAddress()); 186 ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg); 187 } 188 189 static JSValueSource unboxedCell(GPRReg payloadGPR) 190 { 191 JSValueSource result; 192 result.m_offset = notAddress(); 193 result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg); 194 result.m_payload = static_cast<int8_t>(payloadGPR); 195 result.m_tagType = static_cast<int8_t>(JSValue::CellTag); 196 return result; 197 } 198 199 bool operator!() const { return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg && static_cast<GPRReg>(m_payload) == InvalidGPRReg; } 200 201 bool isAddress() const 202 { 203 ASSERT(!!*this); 204 return m_offset != notAddress(); 205 } 206 207 int32_t offset() const 208 { 209 ASSERT(isAddress()); 210 return m_offset; 211 } 212 213 GPRReg base() const 214 { 215 ASSERT(isAddress()); 216 return static_cast<GPRReg>(m_baseOrTag); 217 } 218 219 GPRReg tagGPR() const 220 { 221 ASSERT(!isAddress() && static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg); 222 return static_cast<GPRReg>(m_baseOrTag); 223 } 224 225 GPRReg payloadGPR() const 226 { 227 ASSERT(!isAddress()); 228 return static_cast<GPRReg>(m_payload); 229 } 230 231 bool hasKnownTag() const 232 { 233 ASSERT(!!*this); 234 ASSERT(!isAddress()); 235 return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg; 236 } 237 238 uint32_t tag() const 239 { 240 return static_cast<int32_t>(m_tagType); 241 } 242 243 MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); } 244 245private: 246 static inline int32_t notAddress() { return 0x80000000; } 247 248 int32_t m_offset; 249 int8_t m_baseOrTag; 250 int8_t m_payload; 251 int8_t m_tagType; // Contains the low bits of the tag. 252}; 253#endif 254 255#if CPU(X86) 256#define NUMBER_OF_ARGUMENT_REGISTERS 0 257 258class GPRInfo { 259public: 260 typedef GPRReg RegisterType; 261 static const unsigned numberOfRegisters = 5; 262 263 // Temporary registers. 264 static const GPRReg regT0 = X86Registers::eax; 265 static const GPRReg regT1 = X86Registers::edx; 266 static const GPRReg regT2 = X86Registers::ecx; 267 static const GPRReg regT3 = X86Registers::ebx; 268 static const GPRReg regT4 = X86Registers::esi; 269 // These registers match the baseline JIT. 270 static const GPRReg cachedResultRegister = regT0; 271 static const GPRReg cachedResultRegister2 = regT1; 272 static const GPRReg callFrameRegister = X86Registers::edi; 273 // These constants provide the names for the general purpose argument & return value registers. 274 static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2 275 static const GPRReg argumentGPR1 = X86Registers::edx; // regT1 276 static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0 277 static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3 278 static const GPRReg nonArgGPR2 = X86Registers::esi; // regT4 279 static const GPRReg returnValueGPR = X86Registers::eax; // regT0 280 static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 281 static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx; 282 283 static GPRReg toRegister(unsigned index) 284 { 285 ASSERT(index < numberOfRegisters); 286 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4 }; 287 return registerForIndex[index]; 288 } 289 290 static unsigned toIndex(GPRReg reg) 291 { 292 ASSERT(reg != InvalidGPRReg); 293 ASSERT(static_cast<int>(reg) < 8); 294 static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, InvalidIndex }; 295 unsigned result = indexForRegister[reg]; 296 ASSERT(result != InvalidIndex); 297 return result; 298 } 299 300 static const char* debugName(GPRReg reg) 301 { 302 ASSERT(reg != InvalidGPRReg); 303 ASSERT(static_cast<int>(reg) < 8); 304 static const char* nameForRegister[8] = { 305 "eax", "ecx", "edx", "ebx", 306 "esp", "ebp", "esi", "edi", 307 }; 308 return nameForRegister[reg]; 309 } 310private: 311 312 static const unsigned InvalidIndex = 0xffffffff; 313}; 314 315#endif 316 317#if CPU(X86_64) 318#define NUMBER_OF_ARGUMENT_REGISTERS 6 319 320class GPRInfo { 321public: 322 typedef GPRReg RegisterType; 323 static const unsigned numberOfRegisters = 9; 324 325 // These registers match the baseline JIT. 326 static const GPRReg cachedResultRegister = X86Registers::eax; 327 static const GPRReg callFrameRegister = X86Registers::r13; 328 static const GPRReg tagTypeNumberRegister = X86Registers::r14; 329 static const GPRReg tagMaskRegister = X86Registers::r15; 330 // Temporary registers. 331 static const GPRReg regT0 = X86Registers::eax; 332 static const GPRReg regT1 = X86Registers::edx; 333 static const GPRReg regT2 = X86Registers::ecx; 334 static const GPRReg regT3 = X86Registers::ebx; 335 static const GPRReg regT4 = X86Registers::edi; 336 static const GPRReg regT5 = X86Registers::esi; 337 static const GPRReg regT6 = X86Registers::r8; 338 static const GPRReg regT7 = X86Registers::r9; 339 static const GPRReg regT8 = X86Registers::r10; 340 // These constants provide the names for the general purpose argument & return value registers. 341 static const GPRReg argumentGPR0 = X86Registers::edi; // regT4 342 static const GPRReg argumentGPR1 = X86Registers::esi; // regT5 343 static const GPRReg argumentGPR2 = X86Registers::edx; // regT1 344 static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2 345 static const GPRReg argumentGPR4 = X86Registers::r8; // regT6 346 static const GPRReg argumentGPR5 = X86Registers::r9; // regT7 347 static const GPRReg nonArgGPR0 = X86Registers::eax; // regT0 348 static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3 349 static const GPRReg nonArgGPR2 = X86Registers::r10; // regT8 350 static const GPRReg returnValueGPR = X86Registers::eax; // regT0 351 static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 352 static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi; 353 354 static GPRReg toRegister(unsigned index) 355 { 356 ASSERT(index < numberOfRegisters); 357 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 }; 358 return registerForIndex[index]; 359 } 360 361 static unsigned toIndex(GPRReg reg) 362 { 363 ASSERT(reg != InvalidGPRReg); 364 ASSERT(static_cast<int>(reg) < 16); 365 static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex }; 366 unsigned result = indexForRegister[reg]; 367 ASSERT(result != InvalidIndex); 368 return result; 369 } 370 371 static const char* debugName(GPRReg reg) 372 { 373 ASSERT(reg != InvalidGPRReg); 374 ASSERT(static_cast<int>(reg) < 16); 375 static const char* nameForRegister[16] = { 376 "rax", "rcx", "rdx", "rbx", 377 "rsp", "rbp", "rsi", "rdi", 378 "r8", "r9", "r10", "r11", 379 "r12", "r13", "r14", "r15" 380 }; 381 return nameForRegister[reg]; 382 } 383private: 384 385 static const unsigned InvalidIndex = 0xffffffff; 386}; 387 388#endif 389 390#if CPU(ARM) 391#define NUMBER_OF_ARGUMENT_REGISTERS 4 392 393class GPRInfo { 394public: 395 typedef GPRReg RegisterType; 396 static const unsigned numberOfRegisters = 8; 397 398 // Temporary registers. 399 static const GPRReg regT0 = ARMRegisters::r0; 400 static const GPRReg regT1 = ARMRegisters::r1; 401 static const GPRReg regT2 = ARMRegisters::r2; 402 static const GPRReg regT3 = ARMRegisters::r4; 403 static const GPRReg regT4 = ARMRegisters::r8; 404 static const GPRReg regT5 = ARMRegisters::r9; 405 static const GPRReg regT6 = ARMRegisters::r10; 406 static const GPRReg regT7 = ARMRegisters::r11; 407 // These registers match the baseline JIT. 408 static const GPRReg cachedResultRegister = regT0; 409 static const GPRReg cachedResultRegister2 = regT1; 410 static const GPRReg callFrameRegister = ARMRegisters::r5; 411 // These constants provide the names for the general purpose argument & return value registers. 412 static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0 413 static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1 414 static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2 415 // FIXME: r3 is currently used be the MacroAssembler as a temporary - it seems 416 // This could threoretically be a problem if this is used in code generation 417 // between the arguments being set up, and the call being made. That said, 418 // any change introducing a problem here is likely to be immediately apparent! 419 static const GPRReg argumentGPR3 = ARMRegisters::r3; // FIXME! 420 static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT3 421 static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4 422 static const GPRReg nonArgGPR2 = ARMRegisters::r9; // regT5 423 static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0 424 static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1 425 static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r2; 426 427 static GPRReg toRegister(unsigned index) 428 { 429 ASSERT(index < numberOfRegisters); 430 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 }; 431 return registerForIndex[index]; 432 } 433 434 static unsigned toIndex(GPRReg reg) 435 { 436 ASSERT(static_cast<unsigned>(reg) != InvalidGPRReg); 437 ASSERT(static_cast<unsigned>(reg) < 16); 438 static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex }; 439 unsigned result = indexForRegister[reg]; 440 ASSERT(result != InvalidIndex); 441 return result; 442 } 443 444 static const char* debugName(GPRReg reg) 445 { 446 ASSERT(static_cast<unsigned>(reg) != InvalidGPRReg); 447 ASSERT(static_cast<unsigned>(reg) < 16); 448 static const char* nameForRegister[16] = { 449 "r0", "r1", "r2", "r3", 450 "r4", "r5", "r6", "r7", 451 "r8", "r9", "r10", "r11", 452 "r12", "r13", "r14", "r15" 453 }; 454 return nameForRegister[reg]; 455 } 456private: 457 458 static const unsigned InvalidIndex = 0xffffffff; 459}; 460 461#endif 462 463#if CPU(MIPS) 464#define NUMBER_OF_ARGUMENT_REGISTERS 4 465 466class GPRInfo { 467public: 468 typedef GPRReg RegisterType; 469 static const unsigned numberOfRegisters = 6; 470 471 // Temporary registers. 472 static const GPRReg regT0 = MIPSRegisters::v0; 473 static const GPRReg regT1 = MIPSRegisters::v1; 474 static const GPRReg regT2 = MIPSRegisters::t4; 475 static const GPRReg regT3 = MIPSRegisters::t5; 476 static const GPRReg regT4 = MIPSRegisters::t6; 477 static const GPRReg regT5 = MIPSRegisters::t7; 478 // These registers match the baseline JIT. 479 static const GPRReg cachedResultRegister = regT0; 480 static const GPRReg cachedResultRegister2 = regT1; 481 static const GPRReg callFrameRegister = MIPSRegisters::s0; 482 // These constants provide the names for the general purpose argument & return value registers. 483 static const GPRReg argumentGPR0 = MIPSRegisters::a0; 484 static const GPRReg argumentGPR1 = MIPSRegisters::a1; 485 static const GPRReg argumentGPR2 = MIPSRegisters::a2; 486 static const GPRReg argumentGPR3 = MIPSRegisters::a3; 487 static const GPRReg nonArgGPR0 = regT2; 488 static const GPRReg nonArgGPR1 = regT3; 489 static const GPRReg nonArgGPR2 = regT4; 490 static const GPRReg returnValueGPR = regT0; 491 static const GPRReg returnValueGPR2 = regT1; 492 static const GPRReg nonPreservedNonReturnGPR = regT5; 493 494 static GPRReg toRegister(unsigned index) 495 { 496 ASSERT(index < numberOfRegisters); 497 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 }; 498 return registerForIndex[index]; 499 } 500 501 static unsigned toIndex(GPRReg reg) 502 { 503 ASSERT(reg != InvalidGPRReg); 504 ASSERT(reg < 16); 505 static const unsigned indexForRegister[16] = { InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 3, 4, 5 }; 506 unsigned result = indexForRegister[reg]; 507 ASSERT(result != InvalidIndex); 508 return result; 509 } 510 511 static const char* debugName(GPRReg reg) 512 { 513 ASSERT(reg != InvalidGPRReg); 514 ASSERT(reg < 16); 515 static const char* nameForRegister[16] = { 516 "zero", "at", "v0", "v1", 517 "a0", "a1", "a2", "a3", 518 "t0", "t1", "t2", "t3", 519 "t4", "t5", "t6", "t7" 520 }; 521 return nameForRegister[reg]; 522 } 523private: 524 525 static const unsigned InvalidIndex = 0xffffffff; 526}; 527 528#endif 529 530typedef RegisterBank<GPRInfo>::iterator gpr_iterator; 531 532} } // namespace JSC::DFG 533 534#endif 535#endif 536