1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 2 // 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 // 8 // - Redistributions of source code must retain the above copyright notice, 9 // this list of conditions and the following disclaimer. 10 // 11 // - Redistribution in binary form must reproduce the above copyright 12 // notice, this list of conditions and the following disclaimer in the 13 // documentation and/or other materials provided with the 14 // distribution. 15 // 16 // - Neither the name of Sun Microsystems or the names of contributors may 17 // be used to endorse or promote products derived from this software without 18 // specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 // OF THE POSSIBILITY OF SUCH DAMAGE. 32 33 // The original source code covered by the above license above has been 34 // modified significantly by Google Inc. 35 // Copyright 2012 the V8 project authors. All rights reserved. 36 37 // A light-weight ARM Assembler 38 // Generates user mode instructions for the ARM architecture up to version 5 39 40 #ifndef V8_ARM_ASSEMBLER_ARM_H_ 41 #define V8_ARM_ASSEMBLER_ARM_H_ 42 #include <stdio.h> 43 #include "assembler.h" 44 #include "constants-arm.h" 45 #include "serialize.h" 46 47 namespace v8 { 48 namespace internal { 49 50 // CpuFeatures keeps track of which features are supported by the target CPU. 51 // Supported features must be enabled by a CpuFeatureScope before use. 52 class CpuFeatures : public AllStatic { 53 public: 54 // Detect features of the target CPU. Set safe defaults if the serializer 55 // is enabled (snapshots must be portable). 56 static void Probe(); 57 58 // Display target use when compiling. 59 static void PrintTarget(); 60 61 // Display features. 62 static void PrintFeatures(); 63 64 // Check whether a feature is supported by the target CPU. 65 static bool IsSupported(CpuFeature f) { 66 ASSERT(initialized_); 67 return (supported_ & (1u << f)) != 0; 68 } 69 70 static bool IsFoundByRuntimeProbingOnly(CpuFeature f) { 71 ASSERT(initialized_); 72 return (found_by_runtime_probing_only_ & 73 (static_cast<uint64_t>(1) << f)) != 0; 74 } 75 76 static bool IsSafeForSnapshot(CpuFeature f) { 77 return (IsSupported(f) && 78 (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f))); 79 } 80 81 static unsigned cache_line_size() { return cache_line_size_; } 82 83 private: 84 #ifdef DEBUG 85 static bool initialized_; 86 #endif 87 static unsigned supported_; 88 static unsigned found_by_runtime_probing_only_; 89 static unsigned cache_line_size_; 90 91 friend class ExternalReference; 92 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); 93 }; 94 95 96 // CPU Registers. 97 // 98 // 1) We would prefer to use an enum, but enum values are assignment- 99 // compatible with int, which has caused code-generation bugs. 100 // 101 // 2) We would prefer to use a class instead of a struct but we don't like 102 // the register initialization to depend on the particular initialization 103 // order (which appears to be different on OS X, Linux, and Windows for the 104 // installed versions of C++ we tried). Using a struct permits C-style 105 // "initialization". Also, the Register objects cannot be const as this 106 // forces initialization stubs in MSVC, making us dependent on initialization 107 // order. 108 // 109 // 3) By not using an enum, we are possibly preventing the compiler from 110 // doing certain constant folds, which may significantly reduce the 111 // code generated for some assembly instructions (because they boil down 112 // to a few constants). If this is a problem, we could change the code 113 // such that we use an enum in optimized mode, and the struct in debug 114 // mode. This way we get the compile-time error checking in debug mode 115 // and best performance in optimized code. 116 117 // Core register 118 struct Register { 119 static const int kNumRegisters = 16; 120 static const int kMaxNumAllocatableRegisters = 8; 121 static const int kSizeInBytes = 4; 122 123 inline static int NumAllocatableRegisters(); 124 125 static int ToAllocationIndex(Register reg) { 126 ASSERT(reg.code() < kMaxNumAllocatableRegisters); 127 return reg.code(); 128 } 129 130 static Register FromAllocationIndex(int index) { 131 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 132 return from_code(index); 133 } 134 135 static const char* AllocationIndexToString(int index) { 136 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 137 const char* const names[] = { 138 "r0", 139 "r1", 140 "r2", 141 "r3", 142 "r4", 143 "r5", 144 "r6", 145 "r7", 146 }; 147 return names[index]; 148 } 149 150 static Register from_code(int code) { 151 Register r = { code }; 152 return r; 153 } 154 155 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 156 bool is(Register reg) const { return code_ == reg.code_; } 157 int code() const { 158 ASSERT(is_valid()); 159 return code_; 160 } 161 int bit() const { 162 ASSERT(is_valid()); 163 return 1 << code_; 164 } 165 166 void set_code(int code) { 167 code_ = code; 168 ASSERT(is_valid()); 169 } 170 171 // Unfortunately we can't make this private in a struct. 172 int code_; 173 }; 174 175 // These constants are used in several locations, including static initializers 176 const int kRegister_no_reg_Code = -1; 177 const int kRegister_r0_Code = 0; 178 const int kRegister_r1_Code = 1; 179 const int kRegister_r2_Code = 2; 180 const int kRegister_r3_Code = 3; 181 const int kRegister_r4_Code = 4; 182 const int kRegister_r5_Code = 5; 183 const int kRegister_r6_Code = 6; 184 const int kRegister_r7_Code = 7; 185 const int kRegister_r8_Code = 8; 186 const int kRegister_r9_Code = 9; 187 const int kRegister_r10_Code = 10; 188 const int kRegister_fp_Code = 11; 189 const int kRegister_ip_Code = 12; 190 const int kRegister_sp_Code = 13; 191 const int kRegister_lr_Code = 14; 192 const int kRegister_pc_Code = 15; 193 194 const Register no_reg = { kRegister_no_reg_Code }; 195 196 const Register r0 = { kRegister_r0_Code }; 197 const Register r1 = { kRegister_r1_Code }; 198 const Register r2 = { kRegister_r2_Code }; 199 const Register r3 = { kRegister_r3_Code }; 200 const Register r4 = { kRegister_r4_Code }; 201 const Register r5 = { kRegister_r5_Code }; 202 const Register r6 = { kRegister_r6_Code }; 203 const Register r7 = { kRegister_r7_Code }; 204 // Used as context register. 205 const Register r8 = { kRegister_r8_Code }; 206 // Used as lithium codegen scratch register. 207 const Register r9 = { kRegister_r9_Code }; 208 // Used as roots register. 209 const Register r10 = { kRegister_r10_Code }; 210 const Register fp = { kRegister_fp_Code }; 211 const Register ip = { kRegister_ip_Code }; 212 const Register sp = { kRegister_sp_Code }; 213 const Register lr = { kRegister_lr_Code }; 214 const Register pc = { kRegister_pc_Code }; 215 216 // Single word VFP register. 217 struct SwVfpRegister { 218 static const int kSizeInBytes = 4; 219 bool is_valid() const { return 0 <= code_ && code_ < 32; } 220 bool is(SwVfpRegister reg) const { return code_ == reg.code_; } 221 int code() const { 222 ASSERT(is_valid()); 223 return code_; 224 } 225 int bit() const { 226 ASSERT(is_valid()); 227 return 1 << code_; 228 } 229 void split_code(int* vm, int* m) const { 230 ASSERT(is_valid()); 231 *m = code_ & 0x1; 232 *vm = code_ >> 1; 233 } 234 235 int code_; 236 }; 237 238 239 // Double word VFP register. 240 struct DwVfpRegister { 241 static const int kMaxNumRegisters = 32; 242 // A few double registers are reserved: one as a scratch register and one to 243 // hold 0.0, that does not fit in the immediate field of vmov instructions. 244 // d14: 0.0 245 // d15: scratch register. 246 static const int kNumReservedRegisters = 2; 247 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters - 248 kNumReservedRegisters; 249 static const int kSizeInBytes = 8; 250 251 // Note: the number of registers can be different at snapshot and run-time. 252 // Any code included in the snapshot must be able to run both with 16 or 32 253 // registers. 254 inline static int NumRegisters(); 255 inline static int NumAllocatableRegisters(); 256 257 inline static int ToAllocationIndex(DwVfpRegister reg); 258 static const char* AllocationIndexToString(int index); 259 inline static DwVfpRegister FromAllocationIndex(int index); 260 261 static DwVfpRegister from_code(int code) { 262 DwVfpRegister r = { code }; 263 return r; 264 } 265 266 bool is_valid() const { 267 return 0 <= code_ && code_ < kMaxNumRegisters; 268 } 269 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 270 int code() const { 271 ASSERT(is_valid()); 272 return code_; 273 } 274 int bit() const { 275 ASSERT(is_valid()); 276 return 1 << code_; 277 } 278 void split_code(int* vm, int* m) const { 279 ASSERT(is_valid()); 280 *m = (code_ & 0x10) >> 4; 281 *vm = code_ & 0x0F; 282 } 283 284 int code_; 285 }; 286 287 288 typedef DwVfpRegister DoubleRegister; 289 290 291 // Double word VFP register d0-15. 292 struct LowDwVfpRegister { 293 public: 294 static const int kMaxNumLowRegisters = 16; 295 operator DwVfpRegister() const { 296 DwVfpRegister r = { code_ }; 297 return r; 298 } 299 static LowDwVfpRegister from_code(int code) { 300 LowDwVfpRegister r = { code }; 301 return r; 302 } 303 304 bool is_valid() const { 305 return 0 <= code_ && code_ < kMaxNumLowRegisters; 306 } 307 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 308 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; } 309 int code() const { 310 ASSERT(is_valid()); 311 return code_; 312 } 313 SwVfpRegister low() const { 314 SwVfpRegister reg; 315 reg.code_ = code_ * 2; 316 317 ASSERT(reg.is_valid()); 318 return reg; 319 } 320 SwVfpRegister high() const { 321 SwVfpRegister reg; 322 reg.code_ = (code_ * 2) + 1; 323 324 ASSERT(reg.is_valid()); 325 return reg; 326 } 327 328 int code_; 329 }; 330 331 332 // Quad word NEON register. 333 struct QwNeonRegister { 334 static const int kMaxNumRegisters = 16; 335 336 static QwNeonRegister from_code(int code) { 337 QwNeonRegister r = { code }; 338 return r; 339 } 340 341 bool is_valid() const { 342 return (0 <= code_) && (code_ < kMaxNumRegisters); 343 } 344 bool is(QwNeonRegister reg) const { return code_ == reg.code_; } 345 int code() const { 346 ASSERT(is_valid()); 347 return code_; 348 } 349 void split_code(int* vm, int* m) const { 350 ASSERT(is_valid()); 351 *m = (code_ & 0x10) >> 4; 352 *vm = code_ & 0x0F; 353 } 354 355 int code_; 356 }; 357 358 359 typedef QwNeonRegister QuadRegister; 360 361 362 // Support for the VFP registers s0 to s31 (d0 to d15). 363 // Note that "s(N):s(N+1)" is the same as "d(N/2)". 364 const SwVfpRegister s0 = { 0 }; 365 const SwVfpRegister s1 = { 1 }; 366 const SwVfpRegister s2 = { 2 }; 367 const SwVfpRegister s3 = { 3 }; 368 const SwVfpRegister s4 = { 4 }; 369 const SwVfpRegister s5 = { 5 }; 370 const SwVfpRegister s6 = { 6 }; 371 const SwVfpRegister s7 = { 7 }; 372 const SwVfpRegister s8 = { 8 }; 373 const SwVfpRegister s9 = { 9 }; 374 const SwVfpRegister s10 = { 10 }; 375 const SwVfpRegister s11 = { 11 }; 376 const SwVfpRegister s12 = { 12 }; 377 const SwVfpRegister s13 = { 13 }; 378 const SwVfpRegister s14 = { 14 }; 379 const SwVfpRegister s15 = { 15 }; 380 const SwVfpRegister s16 = { 16 }; 381 const SwVfpRegister s17 = { 17 }; 382 const SwVfpRegister s18 = { 18 }; 383 const SwVfpRegister s19 = { 19 }; 384 const SwVfpRegister s20 = { 20 }; 385 const SwVfpRegister s21 = { 21 }; 386 const SwVfpRegister s22 = { 22 }; 387 const SwVfpRegister s23 = { 23 }; 388 const SwVfpRegister s24 = { 24 }; 389 const SwVfpRegister s25 = { 25 }; 390 const SwVfpRegister s26 = { 26 }; 391 const SwVfpRegister s27 = { 27 }; 392 const SwVfpRegister s28 = { 28 }; 393 const SwVfpRegister s29 = { 29 }; 394 const SwVfpRegister s30 = { 30 }; 395 const SwVfpRegister s31 = { 31 }; 396 397 const DwVfpRegister no_dreg = { -1 }; 398 const LowDwVfpRegister d0 = { 0 }; 399 const LowDwVfpRegister d1 = { 1 }; 400 const LowDwVfpRegister d2 = { 2 }; 401 const LowDwVfpRegister d3 = { 3 }; 402 const LowDwVfpRegister d4 = { 4 }; 403 const LowDwVfpRegister d5 = { 5 }; 404 const LowDwVfpRegister d6 = { 6 }; 405 const LowDwVfpRegister d7 = { 7 }; 406 const LowDwVfpRegister d8 = { 8 }; 407 const LowDwVfpRegister d9 = { 9 }; 408 const LowDwVfpRegister d10 = { 10 }; 409 const LowDwVfpRegister d11 = { 11 }; 410 const LowDwVfpRegister d12 = { 12 }; 411 const LowDwVfpRegister d13 = { 13 }; 412 const LowDwVfpRegister d14 = { 14 }; 413 const LowDwVfpRegister d15 = { 15 }; 414 const DwVfpRegister d16 = { 16 }; 415 const DwVfpRegister d17 = { 17 }; 416 const DwVfpRegister d18 = { 18 }; 417 const DwVfpRegister d19 = { 19 }; 418 const DwVfpRegister d20 = { 20 }; 419 const DwVfpRegister d21 = { 21 }; 420 const DwVfpRegister d22 = { 22 }; 421 const DwVfpRegister d23 = { 23 }; 422 const DwVfpRegister d24 = { 24 }; 423 const DwVfpRegister d25 = { 25 }; 424 const DwVfpRegister d26 = { 26 }; 425 const DwVfpRegister d27 = { 27 }; 426 const DwVfpRegister d28 = { 28 }; 427 const DwVfpRegister d29 = { 29 }; 428 const DwVfpRegister d30 = { 30 }; 429 const DwVfpRegister d31 = { 31 }; 430 431 const QwNeonRegister q0 = { 0 }; 432 const QwNeonRegister q1 = { 1 }; 433 const QwNeonRegister q2 = { 2 }; 434 const QwNeonRegister q3 = { 3 }; 435 const QwNeonRegister q4 = { 4 }; 436 const QwNeonRegister q5 = { 5 }; 437 const QwNeonRegister q6 = { 6 }; 438 const QwNeonRegister q7 = { 7 }; 439 const QwNeonRegister q8 = { 8 }; 440 const QwNeonRegister q9 = { 9 }; 441 const QwNeonRegister q10 = { 10 }; 442 const QwNeonRegister q11 = { 11 }; 443 const QwNeonRegister q12 = { 12 }; 444 const QwNeonRegister q13 = { 13 }; 445 const QwNeonRegister q14 = { 14 }; 446 const QwNeonRegister q15 = { 15 }; 447 448 449 // Aliases for double registers. Defined using #define instead of 450 // "static const DwVfpRegister&" because Clang complains otherwise when a 451 // compilation unit that includes this header doesn't use the variables. 452 #define kFirstCalleeSavedDoubleReg d8 453 #define kLastCalleeSavedDoubleReg d15 454 #define kDoubleRegZero d14 455 #define kScratchDoubleReg d15 456 457 458 // Coprocessor register 459 struct CRegister { 460 bool is_valid() const { return 0 <= code_ && code_ < 16; } 461 bool is(CRegister creg) const { return code_ == creg.code_; } 462 int code() const { 463 ASSERT(is_valid()); 464 return code_; 465 } 466 int bit() const { 467 ASSERT(is_valid()); 468 return 1 << code_; 469 } 470 471 // Unfortunately we can't make this private in a struct. 472 int code_; 473 }; 474 475 476 const CRegister no_creg = { -1 }; 477 478 const CRegister cr0 = { 0 }; 479 const CRegister cr1 = { 1 }; 480 const CRegister cr2 = { 2 }; 481 const CRegister cr3 = { 3 }; 482 const CRegister cr4 = { 4 }; 483 const CRegister cr5 = { 5 }; 484 const CRegister cr6 = { 6 }; 485 const CRegister cr7 = { 7 }; 486 const CRegister cr8 = { 8 }; 487 const CRegister cr9 = { 9 }; 488 const CRegister cr10 = { 10 }; 489 const CRegister cr11 = { 11 }; 490 const CRegister cr12 = { 12 }; 491 const CRegister cr13 = { 13 }; 492 const CRegister cr14 = { 14 }; 493 const CRegister cr15 = { 15 }; 494 495 496 // Coprocessor number 497 enum Coprocessor { 498 p0 = 0, 499 p1 = 1, 500 p2 = 2, 501 p3 = 3, 502 p4 = 4, 503 p5 = 5, 504 p6 = 6, 505 p7 = 7, 506 p8 = 8, 507 p9 = 9, 508 p10 = 10, 509 p11 = 11, 510 p12 = 12, 511 p13 = 13, 512 p14 = 14, 513 p15 = 15 514 }; 515 516 517 // ----------------------------------------------------------------------------- 518 // Machine instruction Operands 519 520 // Class Operand represents a shifter operand in data processing instructions 521 class Operand BASE_EMBEDDED { 522 public: 523 // immediate 524 INLINE(explicit Operand(int32_t immediate, 525 RelocInfo::Mode rmode = RelocInfo::NONE32)); 526 INLINE(static Operand Zero()) { 527 return Operand(static_cast<int32_t>(0)); 528 } 529 INLINE(explicit Operand(const ExternalReference& f)); 530 explicit Operand(Handle<Object> handle); 531 INLINE(explicit Operand(Smi* value)); 532 533 // rm 534 INLINE(explicit Operand(Register rm)); 535 536 // rm <shift_op> shift_imm 537 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); 538 INLINE(static Operand SmiUntag(Register rm)) { 539 return Operand(rm, ASR, kSmiTagSize); 540 } 541 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) { 542 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 543 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize); 544 } 545 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) { 546 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2); 547 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize); 548 } 549 550 // rm <shift_op> rs 551 explicit Operand(Register rm, ShiftOp shift_op, Register rs); 552 553 // Return true if this is a register operand. 554 INLINE(bool is_reg() const); 555 556 // Return true if this operand fits in one instruction so that no 557 // 2-instruction solution with a load into the ip register is necessary. If 558 // the instruction this operand is used for is a MOV or MVN instruction the 559 // actual instruction to use is required for this calculation. For other 560 // instructions instr is ignored. 561 bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const; 562 bool must_output_reloc_info(const Assembler* assembler) const; 563 564 inline int32_t immediate() const { 565 ASSERT(!rm_.is_valid()); 566 return imm32_; 567 } 568 569 Register rm() const { return rm_; } 570 Register rs() const { return rs_; } 571 ShiftOp shift_op() const { return shift_op_; } 572 573 private: 574 Register rm_; 575 Register rs_; 576 ShiftOp shift_op_; 577 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 578 int32_t imm32_; // valid if rm_ == no_reg 579 RelocInfo::Mode rmode_; 580 581 friend class Assembler; 582 }; 583 584 585 // Class MemOperand represents a memory operand in load and store instructions 586 class MemOperand BASE_EMBEDDED { 587 public: 588 // [rn +/- offset] Offset/NegOffset 589 // [rn +/- offset]! PreIndex/NegPreIndex 590 // [rn], +/- offset PostIndex/NegPostIndex 591 // offset is any signed 32-bit value; offset is first loaded to register ip if 592 // it does not fit the addressing mode (12-bit unsigned and sign bit) 593 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset); 594 595 // [rn +/- rm] Offset/NegOffset 596 // [rn +/- rm]! PreIndex/NegPreIndex 597 // [rn], +/- rm PostIndex/NegPostIndex 598 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset); 599 600 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset 601 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex 602 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex 603 explicit MemOperand(Register rn, Register rm, 604 ShiftOp shift_op, int shift_imm, AddrMode am = Offset); 605 INLINE(static MemOperand PointerAddressFromSmiKey(Register array, 606 Register key, 607 AddrMode am = Offset)) { 608 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 609 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am); 610 } 611 612 void set_offset(int32_t offset) { 613 ASSERT(rm_.is(no_reg)); 614 offset_ = offset; 615 } 616 617 uint32_t offset() const { 618 ASSERT(rm_.is(no_reg)); 619 return offset_; 620 } 621 622 Register rn() const { return rn_; } 623 Register rm() const { return rm_; } 624 AddrMode am() const { return am_; } 625 626 bool OffsetIsUint12Encodable() const { 627 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_); 628 } 629 630 private: 631 Register rn_; // base 632 Register rm_; // register offset 633 int32_t offset_; // valid if rm_ == no_reg 634 ShiftOp shift_op_; 635 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 636 AddrMode am_; // bits P, U, and W 637 638 friend class Assembler; 639 }; 640 641 642 // Class NeonMemOperand represents a memory operand in load and 643 // store NEON instructions 644 class NeonMemOperand BASE_EMBEDDED { 645 public: 646 // [rn {:align}] Offset 647 // [rn {:align}]! PostIndex 648 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0); 649 650 // [rn {:align}], rm PostIndex 651 explicit NeonMemOperand(Register rn, Register rm, int align = 0); 652 653 Register rn() const { return rn_; } 654 Register rm() const { return rm_; } 655 int align() const { return align_; } 656 657 private: 658 void SetAlignment(int align); 659 660 Register rn_; // base 661 Register rm_; // register increment 662 int align_; 663 }; 664 665 666 // Class NeonListOperand represents a list of NEON registers 667 class NeonListOperand BASE_EMBEDDED { 668 public: 669 explicit NeonListOperand(DoubleRegister base, int registers_count = 1); 670 DoubleRegister base() const { return base_; } 671 NeonListType type() const { return type_; } 672 private: 673 DoubleRegister base_; 674 NeonListType type_; 675 }; 676 677 extern const Instr kMovLrPc; 678 extern const Instr kLdrPCMask; 679 extern const Instr kLdrPCPattern; 680 extern const Instr kBlxRegMask; 681 extern const Instr kBlxRegPattern; 682 extern const Instr kBlxIp; 683 684 extern const Instr kMovMvnMask; 685 extern const Instr kMovMvnPattern; 686 extern const Instr kMovMvnFlip; 687 688 extern const Instr kMovLeaveCCMask; 689 extern const Instr kMovLeaveCCPattern; 690 extern const Instr kMovwMask; 691 extern const Instr kMovwPattern; 692 extern const Instr kMovwLeaveCCFlip; 693 694 extern const Instr kCmpCmnMask; 695 extern const Instr kCmpCmnPattern; 696 extern const Instr kCmpCmnFlip; 697 extern const Instr kAddSubFlip; 698 extern const Instr kAndBicFlip; 699 700 struct VmovIndex { 701 unsigned char index; 702 }; 703 const VmovIndex VmovIndexLo = { 0 }; 704 const VmovIndex VmovIndexHi = { 1 }; 705 706 class Assembler : public AssemblerBase { 707 public: 708 // Create an assembler. Instructions and relocation information are emitted 709 // into a buffer, with the instructions starting from the beginning and the 710 // relocation information starting from the end of the buffer. See CodeDesc 711 // for a detailed comment on the layout (globals.h). 712 // 713 // If the provided buffer is NULL, the assembler allocates and grows its own 714 // buffer, and buffer_size determines the initial buffer size. The buffer is 715 // owned by the assembler and deallocated upon destruction of the assembler. 716 // 717 // If the provided buffer is not NULL, the assembler uses the provided buffer 718 // for code generation and assumes its size to be buffer_size. If the buffer 719 // is too small, a fatal error occurs. No deallocation of the buffer is done 720 // upon destruction of the assembler. 721 Assembler(Isolate* isolate, void* buffer, int buffer_size); 722 virtual ~Assembler(); 723 724 // GetCode emits any pending (non-emitted) code and fills the descriptor 725 // desc. GetCode() is idempotent; it returns the same result if no other 726 // Assembler functions are invoked in between GetCode() calls. 727 void GetCode(CodeDesc* desc); 728 729 // Label operations & relative jumps (PPUM Appendix D) 730 // 731 // Takes a branch opcode (cc) and a label (L) and generates 732 // either a backward branch or a forward branch and links it 733 // to the label fixup chain. Usage: 734 // 735 // Label L; // unbound label 736 // j(cc, &L); // forward branch to unbound label 737 // bind(&L); // bind label to the current pc 738 // j(cc, &L); // backward branch to bound label 739 // bind(&L); // illegal: a label may be bound only once 740 // 741 // Note: The same Label can be used for forward and backward branches 742 // but it may be bound only once. 743 744 void bind(Label* L); // binds an unbound label L to the current code position 745 746 // Returns the branch offset to the given label from the current code position 747 // Links the label to the current position if it is still unbound 748 // Manages the jump elimination optimization if the second parameter is true. 749 int branch_offset(Label* L, bool jump_elimination_allowed); 750 751 // Puts a labels target address at the given position. 752 // The high 8 bits are set to zero. 753 void label_at_put(Label* L, int at_offset); 754 755 // Return the address in the constant pool of the code target address used by 756 // the branch/call instruction at pc, or the object in a mov. 757 INLINE(static Address target_pointer_address_at(Address pc)); 758 759 // Read/Modify the pointer in the branch/call/move instruction at pc. 760 INLINE(static Address target_pointer_at(Address pc)); 761 INLINE(static void set_target_pointer_at(Address pc, Address target)); 762 763 // Read/Modify the code target address in the branch/call instruction at pc. 764 INLINE(static Address target_address_at(Address pc)); 765 INLINE(static void set_target_address_at(Address pc, Address target)); 766 767 // Return the code target address at a call site from the return address 768 // of that call in the instruction stream. 769 INLINE(static Address target_address_from_return_address(Address pc)); 770 771 // Given the address of the beginning of a call, return the address 772 // in the instruction stream that the call will return from. 773 INLINE(static Address return_address_from_call_start(Address pc)); 774 775 // This sets the branch destination (which is in the constant pool on ARM). 776 // This is for calls and branches within generated code. 777 inline static void deserialization_set_special_target_at( 778 Address constant_pool_entry, Address target); 779 780 // This sets the branch destination (which is in the constant pool on ARM). 781 // This is for calls and branches to runtime code. 782 inline static void set_external_target_at(Address constant_pool_entry, 783 Address target); 784 785 // Here we are patching the address in the constant pool, not the actual call 786 // instruction. The address in the constant pool is the same size as a 787 // pointer. 788 static const int kSpecialTargetSize = kPointerSize; 789 790 // Size of an instruction. 791 static const int kInstrSize = sizeof(Instr); 792 793 // Distance between start of patched return sequence and the emitted address 794 // to jump to. 795 // Patched return sequence is: 796 // ldr ip, [pc, #0] @ emited address and start 797 // blx ip 798 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; 799 800 // Distance between start of patched debug break slot and the emitted address 801 // to jump to. 802 // Patched debug break slot code is: 803 // ldr ip, [pc, #0] @ emited address and start 804 // blx ip 805 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 806 807 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize; 808 809 // Difference between address of current opcode and value read from pc 810 // register. 811 static const int kPcLoadDelta = 8; 812 813 static const int kJSReturnSequenceInstructions = 4; 814 static const int kDebugBreakSlotInstructions = 3; 815 static const int kDebugBreakSlotLength = 816 kDebugBreakSlotInstructions * kInstrSize; 817 818 // --------------------------------------------------------------------------- 819 // Code generation 820 821 // Insert the smallest number of nop instructions 822 // possible to align the pc offset to a multiple 823 // of m. m must be a power of 2 (>= 4). 824 void Align(int m); 825 // Aligns code to something that's optimal for a jump target for the platform. 826 void CodeTargetAlign(); 827 828 // Branch instructions 829 void b(int branch_offset, Condition cond = al); 830 void bl(int branch_offset, Condition cond = al); 831 void blx(int branch_offset); // v5 and above 832 void blx(Register target, Condition cond = al); // v5 and above 833 void bx(Register target, Condition cond = al); // v5 and above, plus v4t 834 835 // Convenience branch instructions using labels 836 void b(Label* L, Condition cond = al) { 837 b(branch_offset(L, cond == al), cond); 838 } 839 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } 840 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } 841 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } 842 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above 843 844 // Data-processing instructions 845 846 void and_(Register dst, Register src1, const Operand& src2, 847 SBit s = LeaveCC, Condition cond = al); 848 849 void eor(Register dst, Register src1, const Operand& src2, 850 SBit s = LeaveCC, Condition cond = al); 851 852 void sub(Register dst, Register src1, const Operand& src2, 853 SBit s = LeaveCC, Condition cond = al); 854 void sub(Register dst, Register src1, Register src2, 855 SBit s = LeaveCC, Condition cond = al) { 856 sub(dst, src1, Operand(src2), s, cond); 857 } 858 859 void rsb(Register dst, Register src1, const Operand& src2, 860 SBit s = LeaveCC, Condition cond = al); 861 862 void add(Register dst, Register src1, const Operand& src2, 863 SBit s = LeaveCC, Condition cond = al); 864 void add(Register dst, Register src1, Register src2, 865 SBit s = LeaveCC, Condition cond = al) { 866 add(dst, src1, Operand(src2), s, cond); 867 } 868 869 void adc(Register dst, Register src1, const Operand& src2, 870 SBit s = LeaveCC, Condition cond = al); 871 872 void sbc(Register dst, Register src1, const Operand& src2, 873 SBit s = LeaveCC, Condition cond = al); 874 875 void rsc(Register dst, Register src1, const Operand& src2, 876 SBit s = LeaveCC, Condition cond = al); 877 878 void tst(Register src1, const Operand& src2, Condition cond = al); 879 void tst(Register src1, Register src2, Condition cond = al) { 880 tst(src1, Operand(src2), cond); 881 } 882 883 void teq(Register src1, const Operand& src2, Condition cond = al); 884 885 void cmp(Register src1, const Operand& src2, Condition cond = al); 886 void cmp(Register src1, Register src2, Condition cond = al) { 887 cmp(src1, Operand(src2), cond); 888 } 889 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al); 890 891 void cmn(Register src1, const Operand& src2, Condition cond = al); 892 893 void orr(Register dst, Register src1, const Operand& src2, 894 SBit s = LeaveCC, Condition cond = al); 895 void orr(Register dst, Register src1, Register src2, 896 SBit s = LeaveCC, Condition cond = al) { 897 orr(dst, src1, Operand(src2), s, cond); 898 } 899 900 void mov(Register dst, const Operand& src, 901 SBit s = LeaveCC, Condition cond = al); 902 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) { 903 mov(dst, Operand(src), s, cond); 904 } 905 906 // ARMv7 instructions for loading a 32 bit immediate in two instructions. 907 // This may actually emit a different mov instruction, but on an ARMv7 it 908 // is guaranteed to only emit one instruction. 909 void movw(Register reg, uint32_t immediate, Condition cond = al); 910 // The constant for movt should be in the range 0-0xffff. 911 void movt(Register reg, uint32_t immediate, Condition cond = al); 912 913 void bic(Register dst, Register src1, const Operand& src2, 914 SBit s = LeaveCC, Condition cond = al); 915 916 void mvn(Register dst, const Operand& src, 917 SBit s = LeaveCC, Condition cond = al); 918 919 // Multiply instructions 920 921 void mla(Register dst, Register src1, Register src2, Register srcA, 922 SBit s = LeaveCC, Condition cond = al); 923 924 void mls(Register dst, Register src1, Register src2, Register srcA, 925 Condition cond = al); 926 927 void sdiv(Register dst, Register src1, Register src2, 928 Condition cond = al); 929 930 void mul(Register dst, Register src1, Register src2, 931 SBit s = LeaveCC, Condition cond = al); 932 933 void smlal(Register dstL, Register dstH, Register src1, Register src2, 934 SBit s = LeaveCC, Condition cond = al); 935 936 void smull(Register dstL, Register dstH, Register src1, Register src2, 937 SBit s = LeaveCC, Condition cond = al); 938 939 void umlal(Register dstL, Register dstH, Register src1, Register src2, 940 SBit s = LeaveCC, Condition cond = al); 941 942 void umull(Register dstL, Register dstH, Register src1, Register src2, 943 SBit s = LeaveCC, Condition cond = al); 944 945 // Miscellaneous arithmetic instructions 946 947 void clz(Register dst, Register src, Condition cond = al); // v5 and above 948 949 // Saturating instructions. v6 and above. 950 951 // Unsigned saturate. 952 // 953 // Saturate an optionally shifted signed value to an unsigned range. 954 // 955 // usat dst, #satpos, src 956 // usat dst, #satpos, src, lsl #sh 957 // usat dst, #satpos, src, asr #sh 958 // 959 // Register dst will contain: 960 // 961 // 0, if s < 0 962 // (1 << satpos) - 1, if s > ((1 << satpos) - 1) 963 // s, otherwise 964 // 965 // where s is the contents of src after shifting (if used.) 966 void usat(Register dst, int satpos, const Operand& src, Condition cond = al); 967 968 // Bitfield manipulation instructions. v7 and above. 969 970 void ubfx(Register dst, Register src, int lsb, int width, 971 Condition cond = al); 972 973 void sbfx(Register dst, Register src, int lsb, int width, 974 Condition cond = al); 975 976 void bfc(Register dst, int lsb, int width, Condition cond = al); 977 978 void bfi(Register dst, Register src, int lsb, int width, 979 Condition cond = al); 980 981 void pkhbt(Register dst, Register src1, const Operand& src2, 982 Condition cond = al); 983 984 void pkhtb(Register dst, Register src1, const Operand& src2, 985 Condition cond = al); 986 987 void uxtb(Register dst, const Operand& src, Condition cond = al); 988 989 void uxtab(Register dst, Register src1, const Operand& src2, 990 Condition cond = al); 991 992 void uxtb16(Register dst, const Operand& src, Condition cond = al); 993 994 // Status register access instructions 995 996 void mrs(Register dst, SRegister s, Condition cond = al); 997 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al); 998 999 // Load/Store instructions 1000 void ldr(Register dst, const MemOperand& src, Condition cond = al); 1001 void str(Register src, const MemOperand& dst, Condition cond = al); 1002 void ldrb(Register dst, const MemOperand& src, Condition cond = al); 1003 void strb(Register src, const MemOperand& dst, Condition cond = al); 1004 void ldrh(Register dst, const MemOperand& src, Condition cond = al); 1005 void strh(Register src, const MemOperand& dst, Condition cond = al); 1006 void ldrsb(Register dst, const MemOperand& src, Condition cond = al); 1007 void ldrsh(Register dst, const MemOperand& src, Condition cond = al); 1008 void ldrd(Register dst1, 1009 Register dst2, 1010 const MemOperand& src, Condition cond = al); 1011 void strd(Register src1, 1012 Register src2, 1013 const MemOperand& dst, Condition cond = al); 1014 1015 // Preload instructions 1016 void pld(const MemOperand& address); 1017 1018 // Load/Store multiple instructions 1019 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); 1020 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); 1021 1022 // Exception-generating instructions and debugging support 1023 void stop(const char* msg, 1024 Condition cond = al, 1025 int32_t code = kDefaultStopCode); 1026 1027 void bkpt(uint32_t imm16); // v5 and above 1028 void svc(uint32_t imm24, Condition cond = al); 1029 1030 // Coprocessor instructions 1031 1032 void cdp(Coprocessor coproc, int opcode_1, 1033 CRegister crd, CRegister crn, CRegister crm, 1034 int opcode_2, Condition cond = al); 1035 1036 void cdp2(Coprocessor coproc, int opcode_1, 1037 CRegister crd, CRegister crn, CRegister crm, 1038 int opcode_2); // v5 and above 1039 1040 void mcr(Coprocessor coproc, int opcode_1, 1041 Register rd, CRegister crn, CRegister crm, 1042 int opcode_2 = 0, Condition cond = al); 1043 1044 void mcr2(Coprocessor coproc, int opcode_1, 1045 Register rd, CRegister crn, CRegister crm, 1046 int opcode_2 = 0); // v5 and above 1047 1048 void mrc(Coprocessor coproc, int opcode_1, 1049 Register rd, CRegister crn, CRegister crm, 1050 int opcode_2 = 0, Condition cond = al); 1051 1052 void mrc2(Coprocessor coproc, int opcode_1, 1053 Register rd, CRegister crn, CRegister crm, 1054 int opcode_2 = 0); // v5 and above 1055 1056 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, 1057 LFlag l = Short, Condition cond = al); 1058 void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 1059 LFlag l = Short, Condition cond = al); 1060 1061 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 1062 LFlag l = Short); // v5 and above 1063 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 1064 LFlag l = Short); // v5 and above 1065 1066 // Support for VFP. 1067 // All these APIs support S0 to S31 and D0 to D31. 1068 1069 void vldr(const DwVfpRegister dst, 1070 const Register base, 1071 int offset, 1072 const Condition cond = al); 1073 void vldr(const DwVfpRegister dst, 1074 const MemOperand& src, 1075 const Condition cond = al); 1076 1077 void vldr(const SwVfpRegister dst, 1078 const Register base, 1079 int offset, 1080 const Condition cond = al); 1081 void vldr(const SwVfpRegister dst, 1082 const MemOperand& src, 1083 const Condition cond = al); 1084 1085 void vstr(const DwVfpRegister src, 1086 const Register base, 1087 int offset, 1088 const Condition cond = al); 1089 void vstr(const DwVfpRegister src, 1090 const MemOperand& dst, 1091 const Condition cond = al); 1092 1093 void vstr(const SwVfpRegister src, 1094 const Register base, 1095 int offset, 1096 const Condition cond = al); 1097 void vstr(const SwVfpRegister src, 1098 const MemOperand& dst, 1099 const Condition cond = al); 1100 1101 void vldm(BlockAddrMode am, 1102 Register base, 1103 DwVfpRegister first, 1104 DwVfpRegister last, 1105 Condition cond = al); 1106 1107 void vstm(BlockAddrMode am, 1108 Register base, 1109 DwVfpRegister first, 1110 DwVfpRegister last, 1111 Condition cond = al); 1112 1113 void vldm(BlockAddrMode am, 1114 Register base, 1115 SwVfpRegister first, 1116 SwVfpRegister last, 1117 Condition cond = al); 1118 1119 void vstm(BlockAddrMode am, 1120 Register base, 1121 SwVfpRegister first, 1122 SwVfpRegister last, 1123 Condition cond = al); 1124 1125 void vmov(const DwVfpRegister dst, 1126 double imm, 1127 const Register scratch = no_reg); 1128 void vmov(const SwVfpRegister dst, 1129 const SwVfpRegister src, 1130 const Condition cond = al); 1131 void vmov(const DwVfpRegister dst, 1132 const DwVfpRegister src, 1133 const Condition cond = al); 1134 void vmov(const DwVfpRegister dst, 1135 const VmovIndex index, 1136 const Register src, 1137 const Condition cond = al); 1138 void vmov(const Register dst, 1139 const VmovIndex index, 1140 const DwVfpRegister src, 1141 const Condition cond = al); 1142 void vmov(const DwVfpRegister dst, 1143 const Register src1, 1144 const Register src2, 1145 const Condition cond = al); 1146 void vmov(const Register dst1, 1147 const Register dst2, 1148 const DwVfpRegister src, 1149 const Condition cond = al); 1150 void vmov(const SwVfpRegister dst, 1151 const Register src, 1152 const Condition cond = al); 1153 void vmov(const Register dst, 1154 const SwVfpRegister src, 1155 const Condition cond = al); 1156 void vcvt_f64_s32(const DwVfpRegister dst, 1157 const SwVfpRegister src, 1158 VFPConversionMode mode = kDefaultRoundToZero, 1159 const Condition cond = al); 1160 void vcvt_f32_s32(const SwVfpRegister dst, 1161 const SwVfpRegister src, 1162 VFPConversionMode mode = kDefaultRoundToZero, 1163 const Condition cond = al); 1164 void vcvt_f64_u32(const DwVfpRegister dst, 1165 const SwVfpRegister src, 1166 VFPConversionMode mode = kDefaultRoundToZero, 1167 const Condition cond = al); 1168 void vcvt_s32_f64(const SwVfpRegister dst, 1169 const DwVfpRegister src, 1170 VFPConversionMode mode = kDefaultRoundToZero, 1171 const Condition cond = al); 1172 void vcvt_u32_f64(const SwVfpRegister dst, 1173 const DwVfpRegister src, 1174 VFPConversionMode mode = kDefaultRoundToZero, 1175 const Condition cond = al); 1176 void vcvt_f64_f32(const DwVfpRegister dst, 1177 const SwVfpRegister src, 1178 VFPConversionMode mode = kDefaultRoundToZero, 1179 const Condition cond = al); 1180 void vcvt_f32_f64(const SwVfpRegister dst, 1181 const DwVfpRegister src, 1182 VFPConversionMode mode = kDefaultRoundToZero, 1183 const Condition cond = al); 1184 void vcvt_f64_s32(const DwVfpRegister dst, 1185 int fraction_bits, 1186 const Condition cond = al); 1187 1188 void vneg(const DwVfpRegister dst, 1189 const DwVfpRegister src, 1190 const Condition cond = al); 1191 void vabs(const DwVfpRegister dst, 1192 const DwVfpRegister src, 1193 const Condition cond = al); 1194 void vadd(const DwVfpRegister dst, 1195 const DwVfpRegister src1, 1196 const DwVfpRegister src2, 1197 const Condition cond = al); 1198 void vsub(const DwVfpRegister dst, 1199 const DwVfpRegister src1, 1200 const DwVfpRegister src2, 1201 const Condition cond = al); 1202 void vmul(const DwVfpRegister dst, 1203 const DwVfpRegister src1, 1204 const DwVfpRegister src2, 1205 const Condition cond = al); 1206 void vmla(const DwVfpRegister dst, 1207 const DwVfpRegister src1, 1208 const DwVfpRegister src2, 1209 const Condition cond = al); 1210 void vmls(const DwVfpRegister dst, 1211 const DwVfpRegister src1, 1212 const DwVfpRegister src2, 1213 const Condition cond = al); 1214 void vdiv(const DwVfpRegister dst, 1215 const DwVfpRegister src1, 1216 const DwVfpRegister src2, 1217 const Condition cond = al); 1218 void vcmp(const DwVfpRegister src1, 1219 const DwVfpRegister src2, 1220 const Condition cond = al); 1221 void vcmp(const DwVfpRegister src1, 1222 const double src2, 1223 const Condition cond = al); 1224 void vmrs(const Register dst, 1225 const Condition cond = al); 1226 void vmsr(const Register dst, 1227 const Condition cond = al); 1228 void vsqrt(const DwVfpRegister dst, 1229 const DwVfpRegister src, 1230 const Condition cond = al); 1231 1232 // Support for NEON. 1233 // All these APIs support D0 to D31 and Q0 to Q15. 1234 1235 void vld1(NeonSize size, 1236 const NeonListOperand& dst, 1237 const NeonMemOperand& src); 1238 void vst1(NeonSize size, 1239 const NeonListOperand& src, 1240 const NeonMemOperand& dst); 1241 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src); 1242 1243 // Pseudo instructions 1244 1245 // Different nop operations are used by the code generator to detect certain 1246 // states of the generated code. 1247 enum NopMarkerTypes { 1248 NON_MARKING_NOP = 0, 1249 DEBUG_BREAK_NOP, 1250 // IC markers. 1251 PROPERTY_ACCESS_INLINED, 1252 PROPERTY_ACCESS_INLINED_CONTEXT, 1253 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 1254 // Helper values. 1255 LAST_CODE_MARKER, 1256 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 1257 }; 1258 1259 void nop(int type = 0); // 0 is the default non-marking type. 1260 1261 void push(Register src, Condition cond = al) { 1262 str(src, MemOperand(sp, 4, NegPreIndex), cond); 1263 } 1264 1265 void pop(Register dst, Condition cond = al) { 1266 ldr(dst, MemOperand(sp, 4, PostIndex), cond); 1267 } 1268 1269 void pop() { 1270 add(sp, sp, Operand(kPointerSize)); 1271 } 1272 1273 // Jump unconditionally to given label. 1274 void jmp(Label* L) { b(L, al); } 1275 1276 static bool use_immediate_embedded_pointer_loads( 1277 const Assembler* assembler) { 1278 return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && 1279 (assembler == NULL || !assembler->predictable_code_size()); 1280 } 1281 1282 // Check the code size generated from label to here. 1283 int SizeOfCodeGeneratedSince(Label* label) { 1284 return pc_offset() - label->pos(); 1285 } 1286 1287 // Check the number of instructions generated from label to here. 1288 int InstructionsGeneratedSince(Label* label) { 1289 return SizeOfCodeGeneratedSince(label) / kInstrSize; 1290 } 1291 1292 // Check whether an immediate fits an addressing mode 1 instruction. 1293 bool ImmediateFitsAddrMode1Instruction(int32_t imm32); 1294 1295 // Class for scoping postponing the constant pool generation. 1296 class BlockConstPoolScope { 1297 public: 1298 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { 1299 assem_->StartBlockConstPool(); 1300 } 1301 ~BlockConstPoolScope() { 1302 assem_->EndBlockConstPool(); 1303 } 1304 1305 private: 1306 Assembler* assem_; 1307 1308 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); 1309 }; 1310 1311 // Debugging 1312 1313 // Mark address of the ExitJSFrame code. 1314 void RecordJSReturn(); 1315 1316 // Mark address of a debug break slot. 1317 void RecordDebugBreakSlot(); 1318 1319 // Record the AST id of the CallIC being compiled, so that it can be placed 1320 // in the relocation information. 1321 void SetRecordedAstId(TypeFeedbackId ast_id) { 1322 ASSERT(recorded_ast_id_.IsNone()); 1323 recorded_ast_id_ = ast_id; 1324 } 1325 1326 TypeFeedbackId RecordedAstId() { 1327 ASSERT(!recorded_ast_id_.IsNone()); 1328 return recorded_ast_id_; 1329 } 1330 1331 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); } 1332 1333 // Record a comment relocation entry that can be used by a disassembler. 1334 // Use --code-comments to enable. 1335 void RecordComment(const char* msg); 1336 1337 // Record the emission of a constant pool. 1338 // 1339 // The emission of constant pool depends on the size of the code generated and 1340 // the number of RelocInfo recorded. 1341 // The Debug mechanism needs to map code offsets between two versions of a 1342 // function, compiled with and without debugger support (see for example 1343 // Debug::PrepareForBreakPoints()). 1344 // Compiling functions with debugger support generates additional code 1345 // (Debug::GenerateSlot()). This may affect the emission of the constant 1346 // pools and cause the version of the code with debugger support to have 1347 // constant pools generated in different places. 1348 // Recording the position and size of emitted constant pools allows to 1349 // correctly compute the offset mappings between the different versions of a 1350 // function in all situations. 1351 // 1352 // The parameter indicates the size of the constant pool (in bytes), including 1353 // the marker and branch over the data. 1354 void RecordConstPool(int size); 1355 1356 // Writes a single byte or word of data in the code stream. Used 1357 // for inline tables, e.g., jump-tables. The constant pool should be 1358 // emitted before any use of db and dd to ensure that constant pools 1359 // are not emitted as part of the tables generated. 1360 void db(uint8_t data); 1361 void dd(uint32_t data); 1362 1363 PositionsRecorder* positions_recorder() { return &positions_recorder_; } 1364 1365 // Read/patch instructions 1366 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 1367 void instr_at_put(int pos, Instr instr) { 1368 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 1369 } 1370 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 1371 static void instr_at_put(byte* pc, Instr instr) { 1372 *reinterpret_cast<Instr*>(pc) = instr; 1373 } 1374 static Condition GetCondition(Instr instr); 1375 static bool IsBranch(Instr instr); 1376 static int GetBranchOffset(Instr instr); 1377 static bool IsLdrRegisterImmediate(Instr instr); 1378 static bool IsVldrDRegisterImmediate(Instr instr); 1379 static int GetLdrRegisterImmediateOffset(Instr instr); 1380 static int GetVldrDRegisterImmediateOffset(Instr instr); 1381 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset); 1382 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset); 1383 static bool IsStrRegisterImmediate(Instr instr); 1384 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset); 1385 static bool IsAddRegisterImmediate(Instr instr); 1386 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset); 1387 static Register GetRd(Instr instr); 1388 static Register GetRn(Instr instr); 1389 static Register GetRm(Instr instr); 1390 static bool IsPush(Instr instr); 1391 static bool IsPop(Instr instr); 1392 static bool IsStrRegFpOffset(Instr instr); 1393 static bool IsLdrRegFpOffset(Instr instr); 1394 static bool IsStrRegFpNegOffset(Instr instr); 1395 static bool IsLdrRegFpNegOffset(Instr instr); 1396 static bool IsLdrPcImmediateOffset(Instr instr); 1397 static bool IsVldrDPcImmediateOffset(Instr instr); 1398 static bool IsTstImmediate(Instr instr); 1399 static bool IsCmpRegister(Instr instr); 1400 static bool IsCmpImmediate(Instr instr); 1401 static Register GetCmpImmediateRegister(Instr instr); 1402 static int GetCmpImmediateRawImmediate(Instr instr); 1403 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); 1404 static bool IsMovT(Instr instr); 1405 static bool IsMovW(Instr instr); 1406 1407 // Constants in pools are accessed via pc relative addressing, which can 1408 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point 1409 // PC-relative loads, thereby defining a maximum distance between the 1410 // instruction and the accessed constant. 1411 static const int kMaxDistToIntPool = 4*KB; 1412 static const int kMaxDistToFPPool = 1*KB; 1413 // All relocations could be integer, it therefore acts as the limit. 1414 static const int kMaxNumPendingRelocInfo = kMaxDistToIntPool/kInstrSize; 1415 1416 // Postpone the generation of the constant pool for the specified number of 1417 // instructions. 1418 void BlockConstPoolFor(int instructions); 1419 1420 // Check if is time to emit a constant pool. 1421 void CheckConstPool(bool force_emit, bool require_jump); 1422 1423 protected: 1424 // Relocation for a type-recording IC has the AST id added to it. This 1425 // member variable is a way to pass the information from the call site to 1426 // the relocation info. 1427 TypeFeedbackId recorded_ast_id_; 1428 1429 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 1430 1431 // Decode branch instruction at pos and return branch target pos 1432 int target_at(int pos); 1433 1434 // Patch branch instruction at pos to branch to given branch target pos 1435 void target_at_put(int pos, int target_pos); 1436 1437 // Prevent contant pool emission until EndBlockConstPool is called. 1438 // Call to this function can be nested but must be followed by an equal 1439 // number of call to EndBlockConstpool. 1440 void StartBlockConstPool() { 1441 if (const_pool_blocked_nesting_++ == 0) { 1442 // Prevent constant pool checks happening by setting the next check to 1443 // the biggest possible offset. 1444 next_buffer_check_ = kMaxInt; 1445 } 1446 } 1447 1448 // Resume constant pool emission. Need to be called as many time as 1449 // StartBlockConstPool to have an effect. 1450 void EndBlockConstPool() { 1451 if (--const_pool_blocked_nesting_ == 0) { 1452 // Check the constant pool hasn't been blocked for too long. 1453 ASSERT((num_pending_reloc_info_ == 0) || 1454 (pc_offset() < (first_const_pool_use_ + kMaxDistToIntPool))); 1455 ASSERT((num_pending_64_bit_reloc_info_ == 0) || 1456 (pc_offset() < (first_const_pool_use_ + kMaxDistToFPPool))); 1457 // Two cases: 1458 // * no_const_pool_before_ >= next_buffer_check_ and the emission is 1459 // still blocked 1460 // * no_const_pool_before_ < next_buffer_check_ and the next emit will 1461 // trigger a check. 1462 next_buffer_check_ = no_const_pool_before_; 1463 } 1464 } 1465 1466 bool is_const_pool_blocked() const { 1467 return (const_pool_blocked_nesting_ > 0) || 1468 (pc_offset() < no_const_pool_before_); 1469 } 1470 1471 private: 1472 int next_buffer_check_; // pc offset of next buffer check 1473 1474 // Code generation 1475 // The relocation writer's position is at least kGap bytes below the end of 1476 // the generated instructions. This is so that multi-instruction sequences do 1477 // not have to check for overflow. The same is true for writes of large 1478 // relocation info entries. 1479 static const int kGap = 32; 1480 1481 // Constant pool generation 1482 // Pools are emitted in the instruction stream, preferably after unconditional 1483 // jumps or after returns from functions (in dead code locations). 1484 // If a long code sequence does not contain unconditional jumps, it is 1485 // necessary to emit the constant pool before the pool gets too far from the 1486 // location it is accessed from. In this case, we emit a jump over the emitted 1487 // constant pool. 1488 // Constants in the pool may be addresses of functions that gets relocated; 1489 // if so, a relocation info entry is associated to the constant pool entry. 1490 1491 // Repeated checking whether the constant pool should be emitted is rather 1492 // expensive. By default we only check again once a number of instructions 1493 // has been generated. That also means that the sizing of the buffers is not 1494 // an exact science, and that we rely on some slop to not overrun buffers. 1495 static const int kCheckPoolIntervalInst = 32; 1496 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize; 1497 1498 1499 // Emission of the constant pool may be blocked in some code sequences. 1500 int const_pool_blocked_nesting_; // Block emission if this is not zero. 1501 int no_const_pool_before_; // Block emission before this pc offset. 1502 1503 // Keep track of the first instruction requiring a constant pool entry 1504 // since the previous constant pool was emitted. 1505 int first_const_pool_use_; 1506 1507 // Relocation info generation 1508 // Each relocation is encoded as a variable size value 1509 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1510 RelocInfoWriter reloc_info_writer; 1511 1512 // Relocation info records are also used during code generation as temporary 1513 // containers for constants and code target addresses until they are emitted 1514 // to the constant pool. These pending relocation info records are temporarily 1515 // stored in a separate buffer until a constant pool is emitted. 1516 // If every instruction in a long sequence is accessing the pool, we need one 1517 // pending relocation entry per instruction. 1518 1519 // the buffer of pending relocation info 1520 RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo]; 1521 // number of pending reloc info entries in the buffer 1522 int num_pending_reloc_info_; 1523 // Number of pending reloc info entries included above which also happen to 1524 // be 64-bit. 1525 int num_pending_64_bit_reloc_info_; 1526 1527 // The bound position, before this we cannot do instruction elimination. 1528 int last_bound_pos_; 1529 1530 // Code emission 1531 inline void CheckBuffer(); 1532 void GrowBuffer(); 1533 inline void emit(Instr x); 1534 1535 // 32-bit immediate values 1536 void move_32_bit_immediate(Condition cond, 1537 Register rd, 1538 SBit s, 1539 const Operand& x); 1540 1541 // Instruction generation 1542 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); 1543 void addrmod2(Instr instr, Register rd, const MemOperand& x); 1544 void addrmod3(Instr instr, Register rd, const MemOperand& x); 1545 void addrmod4(Instr instr, Register rn, RegList rl); 1546 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); 1547 1548 // Labels 1549 void print(Label* L); 1550 void bind_to(Label* L, int pos); 1551 void next(Label* L); 1552 1553 enum UseConstantPoolMode { 1554 USE_CONSTANT_POOL, 1555 DONT_USE_CONSTANT_POOL 1556 }; 1557 1558 // Record reloc info for current pc_ 1559 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0, 1560 UseConstantPoolMode mode = USE_CONSTANT_POOL); 1561 void RecordRelocInfo(double data); 1562 void RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo); 1563 1564 friend class RegExpMacroAssemblerARM; 1565 friend class RelocInfo; 1566 friend class CodePatcher; 1567 friend class BlockConstPoolScope; 1568 1569 PositionsRecorder positions_recorder_; 1570 friend class PositionsRecorder; 1571 friend class EnsureSpace; 1572 }; 1573 1574 1575 class EnsureSpace BASE_EMBEDDED { 1576 public: 1577 explicit EnsureSpace(Assembler* assembler) { 1578 assembler->CheckBuffer(); 1579 } 1580 }; 1581 1582 1583 } } // namespace v8::internal 1584 1585 #endif // V8_ARM_ASSEMBLER_ARM_H_ 1586