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