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