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