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/arm/constants-arm.h" 47 #include "src/assembler.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 DCHECK(reg.code() < kMaxNumAllocatableRegisters); 104 return reg.code(); 105 } 106 FromAllocationIndexRegister107 static Register FromAllocationIndex(int index) { 108 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); 109 return from_code(index); 110 } 111 AllocationIndexToStringRegister112 static const char* AllocationIndexToString(int index) { 113 DCHECK(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 DCHECK(is_valid()); 140 return code_; 141 } bitRegister142 int bit() const { 143 DCHECK(is_valid()); 144 return 1 << code_; 145 } 146 set_codeRegister147 void set_code(int code) { 148 code_ = code; 149 DCHECK(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 DCHECK(is_valid()); 186 return code_; 187 } bitSwVfpRegister188 int bit() const { 189 DCHECK(is_valid()); 190 return 1 << code_; 191 } split_codeSwVfpRegister192 void split_code(int* vm, int* m) const { 193 DCHECK(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 DCHECK(is_valid()); 236 return code_; 237 } bitDwVfpRegister238 int bit() const { 239 DCHECK(is_valid()); 240 return 1 << code_; 241 } split_codeDwVfpRegister242 void split_code(int* vm, int* m) const { 243 DCHECK(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 DCHECK(is_valid()); 275 return code_; 276 } lowLowDwVfpRegister277 SwVfpRegister low() const { 278 SwVfpRegister reg; 279 reg.code_ = code_ * 2; 280 281 DCHECK(reg.is_valid()); 282 return reg; 283 } highLowDwVfpRegister284 SwVfpRegister high() const { 285 SwVfpRegister reg; 286 reg.code_ = (code_ * 2) + 1; 287 288 DCHECK(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 DCHECK(is_valid()); 311 return code_; 312 } split_codeQwNeonRegister313 void split_code(int* vm, int* m) const { 314 DCHECK(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 DCHECK(is_valid()); 429 return code_; 430 } bitCRegister431 int bit() const { 432 DCHECK(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 the number of actual instructions required to implement the given 522 // instruction for this particular operand. This can be a single instruction, 523 // if no load into the ip register is necessary, or anything between 2 and 4 524 // instructions when we need to load from the constant pool (depending upon 525 // whether the constant pool entry is in the small or extended section). If 526 // the instruction this operand is used for is a MOV or MVN instruction the 527 // actual instruction to use is required for this calculation. For other 528 // instructions instr is ignored. 529 // 530 // The value returned is only valid as long as no entries are added to the 531 // constant pool between this call and the actual instruction being emitted. 532 int instructions_required(const Assembler* assembler, Instr instr = 0) const; 533 bool must_output_reloc_info(const Assembler* assembler) const; 534 immediate()535 inline int32_t immediate() const { 536 DCHECK(!rm_.is_valid()); 537 return imm32_; 538 } 539 rm()540 Register rm() const { return rm_; } rs()541 Register rs() const { return rs_; } shift_op()542 ShiftOp shift_op() const { return shift_op_; } 543 544 private: 545 Register rm_; 546 Register rs_; 547 ShiftOp shift_op_; 548 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 549 int32_t imm32_; // valid if rm_ == no_reg 550 RelocInfo::Mode rmode_; 551 552 friend class Assembler; 553 }; 554 555 556 // Class MemOperand represents a memory operand in load and store instructions 557 class MemOperand BASE_EMBEDDED { 558 public: 559 // [rn +/- offset] Offset/NegOffset 560 // [rn +/- offset]! PreIndex/NegPreIndex 561 // [rn], +/- offset PostIndex/NegPostIndex 562 // offset is any signed 32-bit value; offset is first loaded to register ip if 563 // it does not fit the addressing mode (12-bit unsigned and sign bit) 564 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset); 565 566 // [rn +/- rm] Offset/NegOffset 567 // [rn +/- rm]! PreIndex/NegPreIndex 568 // [rn], +/- rm PostIndex/NegPostIndex 569 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset); 570 571 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset 572 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex 573 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex 574 explicit MemOperand(Register rn, Register rm, 575 ShiftOp shift_op, int shift_imm, AddrMode am = Offset); 576 INLINE(static MemOperand PointerAddressFromSmiKey(Register array, 577 Register key, 578 AddrMode am = Offset)) { 579 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 580 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am); 581 } 582 set_offset(int32_t offset)583 void set_offset(int32_t offset) { 584 DCHECK(rm_.is(no_reg)); 585 offset_ = offset; 586 } 587 offset()588 uint32_t offset() const { 589 DCHECK(rm_.is(no_reg)); 590 return offset_; 591 } 592 rn()593 Register rn() const { return rn_; } rm()594 Register rm() const { return rm_; } am()595 AddrMode am() const { return am_; } 596 OffsetIsUint12Encodable()597 bool OffsetIsUint12Encodable() const { 598 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_); 599 } 600 601 private: 602 Register rn_; // base 603 Register rm_; // register offset 604 int32_t offset_; // valid if rm_ == no_reg 605 ShiftOp shift_op_; 606 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 607 AddrMode am_; // bits P, U, and W 608 609 friend class Assembler; 610 }; 611 612 613 // Class NeonMemOperand represents a memory operand in load and 614 // store NEON instructions 615 class NeonMemOperand BASE_EMBEDDED { 616 public: 617 // [rn {:align}] Offset 618 // [rn {:align}]! PostIndex 619 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0); 620 621 // [rn {:align}], rm PostIndex 622 explicit NeonMemOperand(Register rn, Register rm, int align = 0); 623 rn()624 Register rn() const { return rn_; } rm()625 Register rm() const { return rm_; } align()626 int align() const { return align_; } 627 628 private: 629 void SetAlignment(int align); 630 631 Register rn_; // base 632 Register rm_; // register increment 633 int align_; 634 }; 635 636 637 // Class NeonListOperand represents a list of NEON registers 638 class NeonListOperand BASE_EMBEDDED { 639 public: 640 explicit NeonListOperand(DoubleRegister base, int registers_count = 1); base()641 DoubleRegister base() const { return base_; } type()642 NeonListType type() const { return type_; } 643 private: 644 DoubleRegister base_; 645 NeonListType type_; 646 }; 647 648 649 // Class used to build a constant pool. 650 class ConstantPoolBuilder BASE_EMBEDDED { 651 public: 652 ConstantPoolBuilder(); 653 ConstantPoolArray::LayoutSection AddEntry(Assembler* assm, 654 const RelocInfo& rinfo); 655 void Relocate(int pc_delta); 656 bool IsEmpty(); 657 Handle<ConstantPoolArray> New(Isolate* isolate); 658 void Populate(Assembler* assm, ConstantPoolArray* constant_pool); 659 current_section()660 inline ConstantPoolArray::LayoutSection current_section() const { 661 return current_section_; 662 } 663 number_of_entries(ConstantPoolArray::LayoutSection section)664 inline ConstantPoolArray::NumberOfEntries* number_of_entries( 665 ConstantPoolArray::LayoutSection section) { 666 return &number_of_entries_[section]; 667 } 668 small_entries()669 inline ConstantPoolArray::NumberOfEntries* small_entries() { 670 return number_of_entries(ConstantPoolArray::SMALL_SECTION); 671 } 672 extended_entries()673 inline ConstantPoolArray::NumberOfEntries* extended_entries() { 674 return number_of_entries(ConstantPoolArray::EXTENDED_SECTION); 675 } 676 677 private: 678 struct ConstantPoolEntry { ConstantPoolEntryConstantPoolEntry679 ConstantPoolEntry(RelocInfo rinfo, ConstantPoolArray::LayoutSection section, 680 int merged_index) 681 : rinfo_(rinfo), section_(section), merged_index_(merged_index) {} 682 683 RelocInfo rinfo_; 684 ConstantPoolArray::LayoutSection section_; 685 int merged_index_; 686 }; 687 688 ConstantPoolArray::Type GetConstantPoolType(RelocInfo::Mode rmode); 689 690 std::vector<ConstantPoolEntry> entries_; 691 ConstantPoolArray::LayoutSection current_section_; 692 ConstantPoolArray::NumberOfEntries number_of_entries_[2]; 693 }; 694 695 struct VmovIndex { 696 unsigned char index; 697 }; 698 const VmovIndex VmovIndexLo = { 0 }; 699 const VmovIndex VmovIndexHi = { 1 }; 700 701 class Assembler : public AssemblerBase { 702 public: 703 // Create an assembler. Instructions and relocation information are emitted 704 // into a buffer, with the instructions starting from the beginning and the 705 // relocation information starting from the end of the buffer. See CodeDesc 706 // for a detailed comment on the layout (globals.h). 707 // 708 // If the provided buffer is NULL, the assembler allocates and grows its own 709 // buffer, and buffer_size determines the initial buffer size. The buffer is 710 // owned by the assembler and deallocated upon destruction of the assembler. 711 // 712 // If the provided buffer is not NULL, the assembler uses the provided buffer 713 // for code generation and assumes its size to be buffer_size. If the buffer 714 // is too small, a fatal error occurs. No deallocation of the buffer is done 715 // upon destruction of the assembler. 716 Assembler(Isolate* isolate, void* buffer, int buffer_size); 717 virtual ~Assembler(); 718 719 // GetCode emits any pending (non-emitted) code and fills the descriptor 720 // desc. GetCode() is idempotent; it returns the same result if no other 721 // Assembler functions are invoked in between GetCode() calls. 722 void GetCode(CodeDesc* desc); 723 724 // Label operations & relative jumps (PPUM Appendix D) 725 // 726 // Takes a branch opcode (cc) and a label (L) and generates 727 // either a backward branch or a forward branch and links it 728 // to the label fixup chain. Usage: 729 // 730 // Label L; // unbound label 731 // j(cc, &L); // forward branch to unbound label 732 // bind(&L); // bind label to the current pc 733 // j(cc, &L); // backward branch to bound label 734 // bind(&L); // illegal: a label may be bound only once 735 // 736 // Note: The same Label can be used for forward and backward branches 737 // but it may be bound only once. 738 739 void bind(Label* L); // binds an unbound label L to the current code position 740 741 // Returns the branch offset to the given label from the current code position 742 // Links the label to the current position if it is still unbound 743 // Manages the jump elimination optimization if the second parameter is true. 744 int branch_offset(Label* L, bool jump_elimination_allowed); 745 746 // Returns true if the given pc address is the start of a constant pool load 747 // instruction sequence. 748 INLINE(static bool is_constant_pool_load(Address pc)); 749 750 // Return the address in the constant pool of the code target address used by 751 // the branch/call instruction at pc, or the object in a mov. 752 INLINE(static Address constant_pool_entry_address( 753 Address pc, ConstantPoolArray* constant_pool)); 754 755 // Read/Modify the code target address in the branch/call instruction at pc. 756 INLINE(static Address target_address_at(Address pc, 757 ConstantPoolArray* constant_pool)); 758 INLINE(static void set_target_address_at(Address pc, 759 ConstantPoolArray* constant_pool, 760 Address target, 761 ICacheFlushMode icache_flush_mode = 762 FLUSH_ICACHE_IF_NEEDED)); INLINE(static Address target_address_at (Address pc,Code * code))763 INLINE(static Address target_address_at(Address pc, Code* code)) { 764 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 765 return target_address_at(pc, constant_pool); 766 } INLINE(static void set_target_address_at (Address pc,Code * code,Address target,ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED))767 INLINE(static void set_target_address_at(Address pc, 768 Code* code, 769 Address target, 770 ICacheFlushMode icache_flush_mode = 771 FLUSH_ICACHE_IF_NEEDED)) { 772 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 773 set_target_address_at(pc, constant_pool, target, icache_flush_mode); 774 } 775 776 // Return the code target address at a call site from the return address 777 // of that call in the instruction stream. 778 INLINE(static Address target_address_from_return_address(Address pc)); 779 780 // Given the address of the beginning of a call, return the address 781 // in the instruction stream that the call will return from. 782 INLINE(static Address return_address_from_call_start(Address pc)); 783 784 // Return the code target address of the patch debug break slot 785 INLINE(static Address break_address_from_return_address(Address pc)); 786 787 // This sets the branch destination (which is in the constant pool on ARM). 788 // This is for calls and branches within generated code. 789 inline static void deserialization_set_special_target_at( 790 Address constant_pool_entry, Code* code, Address target); 791 792 // Here we are patching the address in the constant pool, not the actual call 793 // instruction. The address in the constant pool is the same size as a 794 // pointer. 795 static const int kSpecialTargetSize = kPointerSize; 796 797 // Size of an instruction. 798 static const int kInstrSize = sizeof(Instr); 799 800 // Distance between start of patched return sequence and the emitted address 801 // to jump to. 802 // Patched return sequence is: 803 // ldr ip, [pc, #0] @ emited address and start 804 // blx ip 805 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; 806 807 // Distance between start of patched debug break slot and the emitted address 808 // to jump to. 809 // Patched debug break slot code is: 810 // ldr ip, [pc, #0] @ emited address and start 811 // blx ip 812 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 813 814 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize; 815 816 // Difference between address of current opcode and value read from pc 817 // register. 818 static const int kPcLoadDelta = 8; 819 820 static const int kJSReturnSequenceInstructions = 4; 821 static const int kDebugBreakSlotInstructions = 3; 822 static const int kDebugBreakSlotLength = 823 kDebugBreakSlotInstructions * kInstrSize; 824 825 // --------------------------------------------------------------------------- 826 // Code generation 827 828 // Insert the smallest number of nop instructions 829 // possible to align the pc offset to a multiple 830 // of m. m must be a power of 2 (>= 4). 831 void Align(int m); 832 // Aligns code to something that's optimal for a jump target for the platform. 833 void CodeTargetAlign(); 834 835 // Branch instructions 836 void b(int branch_offset, Condition cond = al); 837 void bl(int branch_offset, Condition cond = al); 838 void blx(int branch_offset); // v5 and above 839 void blx(Register target, Condition cond = al); // v5 and above 840 void bx(Register target, Condition cond = al); // v5 and above, plus v4t 841 842 // Convenience branch instructions using labels 843 void b(Label* L, Condition cond = al) { 844 b(branch_offset(L, cond == al), cond); 845 } b(Condition cond,Label * L)846 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } 847 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } bl(Condition cond,Label * L)848 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } blx(Label * L)849 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above 850 851 // Data-processing instructions 852 853 void and_(Register dst, Register src1, const Operand& src2, 854 SBit s = LeaveCC, Condition cond = al); 855 856 void eor(Register dst, Register src1, const Operand& src2, 857 SBit s = LeaveCC, Condition cond = al); 858 859 void sub(Register dst, Register src1, const Operand& src2, 860 SBit s = LeaveCC, Condition cond = al); 861 void sub(Register dst, Register src1, Register src2, 862 SBit s = LeaveCC, Condition cond = al) { 863 sub(dst, src1, Operand(src2), s, cond); 864 } 865 866 void rsb(Register dst, Register src1, const Operand& src2, 867 SBit s = LeaveCC, Condition cond = al); 868 869 void add(Register dst, Register src1, const Operand& src2, 870 SBit s = LeaveCC, Condition cond = al); 871 void add(Register dst, Register src1, Register src2, 872 SBit s = LeaveCC, Condition cond = al) { 873 add(dst, src1, Operand(src2), s, cond); 874 } 875 876 void adc(Register dst, Register src1, const Operand& src2, 877 SBit s = LeaveCC, Condition cond = al); 878 879 void sbc(Register dst, Register src1, const Operand& src2, 880 SBit s = LeaveCC, Condition cond = al); 881 882 void rsc(Register dst, Register src1, const Operand& src2, 883 SBit s = LeaveCC, Condition cond = al); 884 885 void tst(Register src1, const Operand& src2, Condition cond = al); 886 void tst(Register src1, Register src2, Condition cond = al) { 887 tst(src1, Operand(src2), cond); 888 } 889 890 void teq(Register src1, const Operand& src2, Condition cond = al); 891 892 void cmp(Register src1, const Operand& src2, Condition cond = al); 893 void cmp(Register src1, Register src2, Condition cond = al) { 894 cmp(src1, Operand(src2), cond); 895 } 896 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al); 897 898 void cmn(Register src1, const Operand& src2, Condition cond = al); 899 900 void orr(Register dst, Register src1, const Operand& src2, 901 SBit s = LeaveCC, Condition cond = al); 902 void orr(Register dst, Register src1, Register src2, 903 SBit s = LeaveCC, Condition cond = al) { 904 orr(dst, src1, Operand(src2), s, cond); 905 } 906 907 void mov(Register dst, const Operand& src, 908 SBit s = LeaveCC, Condition cond = al); 909 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) { 910 mov(dst, Operand(src), s, cond); 911 } 912 913 // Load the position of the label relative to the generated code object 914 // pointer in a register. 915 void mov_label_offset(Register dst, Label* label); 916 917 // ARMv7 instructions for loading a 32 bit immediate in two instructions. 918 // The constant for movw and movt should be in the range 0-0xffff. 919 void movw(Register reg, uint32_t immediate, Condition cond = al); 920 void movt(Register reg, uint32_t immediate, Condition cond = al); 921 922 void bic(Register dst, Register src1, const Operand& src2, 923 SBit s = LeaveCC, Condition cond = al); 924 925 void mvn(Register dst, const Operand& src, 926 SBit s = LeaveCC, Condition cond = al); 927 928 // Shift instructions 929 930 void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, 931 Condition cond = al) { 932 if (src2.is_reg()) { 933 mov(dst, Operand(src1, ASR, src2.rm()), s, cond); 934 } else { 935 mov(dst, Operand(src1, ASR, src2.immediate()), s, cond); 936 } 937 } 938 939 void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, 940 Condition cond = al) { 941 if (src2.is_reg()) { 942 mov(dst, Operand(src1, LSL, src2.rm()), s, cond); 943 } else { 944 mov(dst, Operand(src1, LSL, src2.immediate()), s, cond); 945 } 946 } 947 948 void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, 949 Condition cond = al) { 950 if (src2.is_reg()) { 951 mov(dst, Operand(src1, LSR, src2.rm()), s, cond); 952 } else { 953 mov(dst, Operand(src1, LSR, src2.immediate()), s, cond); 954 } 955 } 956 957 // Multiply instructions 958 959 void mla(Register dst, Register src1, Register src2, Register srcA, 960 SBit s = LeaveCC, Condition cond = al); 961 962 void mls(Register dst, Register src1, Register src2, Register srcA, 963 Condition cond = al); 964 965 void sdiv(Register dst, Register src1, Register src2, 966 Condition cond = al); 967 968 void udiv(Register dst, Register src1, Register src2, Condition cond = al); 969 970 void mul(Register dst, Register src1, Register src2, 971 SBit s = LeaveCC, Condition cond = al); 972 973 void smlal(Register dstL, Register dstH, Register src1, Register src2, 974 SBit s = LeaveCC, Condition cond = al); 975 976 void smull(Register dstL, Register dstH, Register src1, Register src2, 977 SBit s = LeaveCC, Condition cond = al); 978 979 void umlal(Register dstL, Register dstH, Register src1, Register src2, 980 SBit s = LeaveCC, Condition cond = al); 981 982 void umull(Register dstL, Register dstH, Register src1, Register src2, 983 SBit s = LeaveCC, Condition cond = al); 984 985 // Miscellaneous arithmetic instructions 986 987 void clz(Register dst, Register src, Condition cond = al); // v5 and above 988 989 // Saturating instructions. v6 and above. 990 991 // Unsigned saturate. 992 // 993 // Saturate an optionally shifted signed value to an unsigned range. 994 // 995 // usat dst, #satpos, src 996 // usat dst, #satpos, src, lsl #sh 997 // usat dst, #satpos, src, asr #sh 998 // 999 // Register dst will contain: 1000 // 1001 // 0, if s < 0 1002 // (1 << satpos) - 1, if s > ((1 << satpos) - 1) 1003 // s, otherwise 1004 // 1005 // where s is the contents of src after shifting (if used.) 1006 void usat(Register dst, int satpos, const Operand& src, Condition cond = al); 1007 1008 // Bitfield manipulation instructions. v7 and above. 1009 1010 void ubfx(Register dst, Register src, int lsb, int width, 1011 Condition cond = al); 1012 1013 void sbfx(Register dst, Register src, int lsb, int width, 1014 Condition cond = al); 1015 1016 void bfc(Register dst, int lsb, int width, Condition cond = al); 1017 1018 void bfi(Register dst, Register src, int lsb, int width, 1019 Condition cond = al); 1020 1021 void pkhbt(Register dst, Register src1, const Operand& src2, 1022 Condition cond = al); 1023 1024 void pkhtb(Register dst, Register src1, const Operand& src2, 1025 Condition cond = al); 1026 1027 void uxtb(Register dst, const Operand& src, Condition cond = al); 1028 1029 void uxtab(Register dst, Register src1, const Operand& src2, 1030 Condition cond = al); 1031 1032 void uxtb16(Register dst, const Operand& src, Condition cond = al); 1033 1034 // Status register access instructions 1035 1036 void mrs(Register dst, SRegister s, Condition cond = al); 1037 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al); 1038 1039 // Load/Store instructions 1040 void ldr(Register dst, const MemOperand& src, Condition cond = al); 1041 void str(Register src, const MemOperand& dst, Condition cond = al); 1042 void ldrb(Register dst, const MemOperand& src, Condition cond = al); 1043 void strb(Register src, const MemOperand& dst, Condition cond = al); 1044 void ldrh(Register dst, const MemOperand& src, Condition cond = al); 1045 void strh(Register src, const MemOperand& dst, Condition cond = al); 1046 void ldrsb(Register dst, const MemOperand& src, Condition cond = al); 1047 void ldrsh(Register dst, const MemOperand& src, Condition cond = al); 1048 void ldrd(Register dst1, 1049 Register dst2, 1050 const MemOperand& src, Condition cond = al); 1051 void strd(Register src1, 1052 Register src2, 1053 const MemOperand& dst, Condition cond = al); 1054 1055 // Preload instructions 1056 void pld(const MemOperand& address); 1057 1058 // Load/Store multiple instructions 1059 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); 1060 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); 1061 1062 // Exception-generating instructions and debugging support 1063 void stop(const char* msg, 1064 Condition cond = al, 1065 int32_t code = kDefaultStopCode); 1066 1067 void bkpt(uint32_t imm16); // v5 and above 1068 void svc(uint32_t imm24, Condition cond = al); 1069 1070 // Coprocessor instructions 1071 1072 void cdp(Coprocessor coproc, int opcode_1, 1073 CRegister crd, CRegister crn, CRegister crm, 1074 int opcode_2, Condition cond = al); 1075 1076 void cdp2(Coprocessor coproc, int opcode_1, 1077 CRegister crd, CRegister crn, CRegister crm, 1078 int opcode_2); // v5 and above 1079 1080 void mcr(Coprocessor coproc, int opcode_1, 1081 Register rd, CRegister crn, CRegister crm, 1082 int opcode_2 = 0, Condition cond = al); 1083 1084 void mcr2(Coprocessor coproc, int opcode_1, 1085 Register rd, CRegister crn, CRegister crm, 1086 int opcode_2 = 0); // v5 and above 1087 1088 void mrc(Coprocessor coproc, int opcode_1, 1089 Register rd, CRegister crn, CRegister crm, 1090 int opcode_2 = 0, Condition cond = al); 1091 1092 void mrc2(Coprocessor coproc, int opcode_1, 1093 Register rd, CRegister crn, CRegister crm, 1094 int opcode_2 = 0); // v5 and above 1095 1096 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, 1097 LFlag l = Short, Condition cond = al); 1098 void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 1099 LFlag l = Short, Condition cond = al); 1100 1101 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 1102 LFlag l = Short); // v5 and above 1103 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 1104 LFlag l = Short); // v5 and above 1105 1106 // Support for VFP. 1107 // All these APIs support S0 to S31 and D0 to D31. 1108 1109 void vldr(const DwVfpRegister dst, 1110 const Register base, 1111 int offset, 1112 const Condition cond = al); 1113 void vldr(const DwVfpRegister dst, 1114 const MemOperand& src, 1115 const Condition cond = al); 1116 1117 void vldr(const SwVfpRegister dst, 1118 const Register base, 1119 int offset, 1120 const Condition cond = al); 1121 void vldr(const SwVfpRegister dst, 1122 const MemOperand& src, 1123 const Condition cond = al); 1124 1125 void vstr(const DwVfpRegister src, 1126 const Register base, 1127 int offset, 1128 const Condition cond = al); 1129 void vstr(const DwVfpRegister src, 1130 const MemOperand& dst, 1131 const Condition cond = al); 1132 1133 void vstr(const SwVfpRegister src, 1134 const Register base, 1135 int offset, 1136 const Condition cond = al); 1137 void vstr(const SwVfpRegister src, 1138 const MemOperand& dst, 1139 const Condition cond = al); 1140 1141 void vldm(BlockAddrMode am, 1142 Register base, 1143 DwVfpRegister first, 1144 DwVfpRegister last, 1145 Condition cond = al); 1146 1147 void vstm(BlockAddrMode am, 1148 Register base, 1149 DwVfpRegister first, 1150 DwVfpRegister last, 1151 Condition cond = al); 1152 1153 void vldm(BlockAddrMode am, 1154 Register base, 1155 SwVfpRegister first, 1156 SwVfpRegister last, 1157 Condition cond = al); 1158 1159 void vstm(BlockAddrMode am, 1160 Register base, 1161 SwVfpRegister first, 1162 SwVfpRegister last, 1163 Condition cond = al); 1164 1165 void vmov(const DwVfpRegister dst, 1166 double imm, 1167 const Register scratch = no_reg); 1168 void vmov(const SwVfpRegister dst, 1169 const SwVfpRegister src, 1170 const Condition cond = al); 1171 void vmov(const DwVfpRegister dst, 1172 const DwVfpRegister src, 1173 const Condition cond = al); 1174 void vmov(const DwVfpRegister dst, 1175 const VmovIndex index, 1176 const Register src, 1177 const Condition cond = al); 1178 void vmov(const Register dst, 1179 const VmovIndex index, 1180 const DwVfpRegister src, 1181 const Condition cond = al); 1182 void vmov(const DwVfpRegister dst, 1183 const Register src1, 1184 const Register src2, 1185 const Condition cond = al); 1186 void vmov(const Register dst1, 1187 const Register dst2, 1188 const DwVfpRegister src, 1189 const Condition cond = al); 1190 void vmov(const SwVfpRegister dst, 1191 const Register src, 1192 const Condition cond = al); 1193 void vmov(const Register dst, 1194 const SwVfpRegister src, 1195 const Condition cond = al); 1196 void vcvt_f64_s32(const DwVfpRegister dst, 1197 const SwVfpRegister src, 1198 VFPConversionMode mode = kDefaultRoundToZero, 1199 const Condition cond = al); 1200 void vcvt_f32_s32(const SwVfpRegister dst, 1201 const SwVfpRegister src, 1202 VFPConversionMode mode = kDefaultRoundToZero, 1203 const Condition cond = al); 1204 void vcvt_f64_u32(const DwVfpRegister dst, 1205 const SwVfpRegister src, 1206 VFPConversionMode mode = kDefaultRoundToZero, 1207 const Condition cond = al); 1208 void vcvt_s32_f64(const SwVfpRegister dst, 1209 const DwVfpRegister src, 1210 VFPConversionMode mode = kDefaultRoundToZero, 1211 const Condition cond = al); 1212 void vcvt_u32_f64(const SwVfpRegister dst, 1213 const DwVfpRegister src, 1214 VFPConversionMode mode = kDefaultRoundToZero, 1215 const Condition cond = al); 1216 void vcvt_f64_f32(const DwVfpRegister dst, 1217 const SwVfpRegister src, 1218 VFPConversionMode mode = kDefaultRoundToZero, 1219 const Condition cond = al); 1220 void vcvt_f32_f64(const SwVfpRegister dst, 1221 const DwVfpRegister src, 1222 VFPConversionMode mode = kDefaultRoundToZero, 1223 const Condition cond = al); 1224 void vcvt_f64_s32(const DwVfpRegister dst, 1225 int fraction_bits, 1226 const Condition cond = al); 1227 1228 void vneg(const DwVfpRegister dst, 1229 const DwVfpRegister src, 1230 const Condition cond = al); 1231 void vabs(const DwVfpRegister dst, 1232 const DwVfpRegister src, 1233 const Condition cond = al); 1234 void vadd(const DwVfpRegister dst, 1235 const DwVfpRegister src1, 1236 const DwVfpRegister src2, 1237 const Condition cond = al); 1238 void vsub(const DwVfpRegister dst, 1239 const DwVfpRegister src1, 1240 const DwVfpRegister src2, 1241 const Condition cond = al); 1242 void vmul(const DwVfpRegister dst, 1243 const DwVfpRegister src1, 1244 const DwVfpRegister src2, 1245 const Condition cond = al); 1246 void vmla(const DwVfpRegister dst, 1247 const DwVfpRegister src1, 1248 const DwVfpRegister src2, 1249 const Condition cond = al); 1250 void vmls(const DwVfpRegister dst, 1251 const DwVfpRegister src1, 1252 const DwVfpRegister src2, 1253 const Condition cond = al); 1254 void vdiv(const DwVfpRegister dst, 1255 const DwVfpRegister src1, 1256 const DwVfpRegister src2, 1257 const Condition cond = al); 1258 void vcmp(const DwVfpRegister src1, 1259 const DwVfpRegister src2, 1260 const Condition cond = al); 1261 void vcmp(const DwVfpRegister src1, 1262 const double src2, 1263 const Condition cond = al); 1264 void vmrs(const Register dst, 1265 const Condition cond = al); 1266 void vmsr(const Register dst, 1267 const Condition cond = al); 1268 void vsqrt(const DwVfpRegister dst, 1269 const DwVfpRegister src, 1270 const Condition cond = al); 1271 1272 // Support for NEON. 1273 // All these APIs support D0 to D31 and Q0 to Q15. 1274 1275 void vld1(NeonSize size, 1276 const NeonListOperand& dst, 1277 const NeonMemOperand& src); 1278 void vst1(NeonSize size, 1279 const NeonListOperand& src, 1280 const NeonMemOperand& dst); 1281 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src); 1282 1283 // Pseudo instructions 1284 1285 // Different nop operations are used by the code generator to detect certain 1286 // states of the generated code. 1287 enum NopMarkerTypes { 1288 NON_MARKING_NOP = 0, 1289 DEBUG_BREAK_NOP, 1290 // IC markers. 1291 PROPERTY_ACCESS_INLINED, 1292 PROPERTY_ACCESS_INLINED_CONTEXT, 1293 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 1294 // Helper values. 1295 LAST_CODE_MARKER, 1296 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 1297 }; 1298 1299 void nop(int type = 0); // 0 is the default non-marking type. 1300 1301 void push(Register src, Condition cond = al) { 1302 str(src, MemOperand(sp, 4, NegPreIndex), cond); 1303 } 1304 1305 void pop(Register dst, Condition cond = al) { 1306 ldr(dst, MemOperand(sp, 4, PostIndex), cond); 1307 } 1308 pop()1309 void pop() { 1310 add(sp, sp, Operand(kPointerSize)); 1311 } 1312 1313 // Jump unconditionally to given label. jmp(Label * L)1314 void jmp(Label* L) { b(L, al); } 1315 1316 // Check the code size generated from label to here. SizeOfCodeGeneratedSince(Label * label)1317 int SizeOfCodeGeneratedSince(Label* label) { 1318 return pc_offset() - label->pos(); 1319 } 1320 1321 // Check the number of instructions generated from label to here. InstructionsGeneratedSince(Label * label)1322 int InstructionsGeneratedSince(Label* label) { 1323 return SizeOfCodeGeneratedSince(label) / kInstrSize; 1324 } 1325 1326 // Check whether an immediate fits an addressing mode 1 instruction. 1327 static bool ImmediateFitsAddrMode1Instruction(int32_t imm32); 1328 1329 // Check whether an immediate fits an addressing mode 2 instruction. 1330 bool ImmediateFitsAddrMode2Instruction(int32_t imm32); 1331 1332 // Class for scoping postponing the constant pool generation. 1333 class BlockConstPoolScope { 1334 public: BlockConstPoolScope(Assembler * assem)1335 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { 1336 assem_->StartBlockConstPool(); 1337 } ~BlockConstPoolScope()1338 ~BlockConstPoolScope() { 1339 assem_->EndBlockConstPool(); 1340 } 1341 1342 private: 1343 Assembler* assem_; 1344 1345 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); 1346 }; 1347 1348 // Debugging 1349 1350 // Mark address of the ExitJSFrame code. 1351 void RecordJSReturn(); 1352 1353 // Mark address of a debug break slot. 1354 void RecordDebugBreakSlot(); 1355 1356 // Record the AST id of the CallIC being compiled, so that it can be placed 1357 // in the relocation information. SetRecordedAstId(TypeFeedbackId ast_id)1358 void SetRecordedAstId(TypeFeedbackId ast_id) { 1359 DCHECK(recorded_ast_id_.IsNone()); 1360 recorded_ast_id_ = ast_id; 1361 } 1362 RecordedAstId()1363 TypeFeedbackId RecordedAstId() { 1364 DCHECK(!recorded_ast_id_.IsNone()); 1365 return recorded_ast_id_; 1366 } 1367 ClearRecordedAstId()1368 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); } 1369 1370 // Record a comment relocation entry that can be used by a disassembler. 1371 // Use --code-comments to enable. 1372 void RecordComment(const char* msg); 1373 1374 // Record the emission of a constant pool. 1375 // 1376 // The emission of constant pool depends on the size of the code generated and 1377 // the number of RelocInfo recorded. 1378 // The Debug mechanism needs to map code offsets between two versions of a 1379 // function, compiled with and without debugger support (see for example 1380 // Debug::PrepareForBreakPoints()). 1381 // Compiling functions with debugger support generates additional code 1382 // (DebugCodegen::GenerateSlot()). This may affect the emission of the 1383 // constant pools and cause the version of the code with debugger support to 1384 // have constant pools generated in different places. 1385 // Recording the position and size of emitted constant pools allows to 1386 // correctly compute the offset mappings between the different versions of a 1387 // function in all situations. 1388 // 1389 // The parameter indicates the size of the constant pool (in bytes), including 1390 // the marker and branch over the data. 1391 void RecordConstPool(int size); 1392 1393 // Writes a single byte or word of data in the code stream. Used 1394 // for inline tables, e.g., jump-tables. The constant pool should be 1395 // emitted before any use of db and dd to ensure that constant pools 1396 // are not emitted as part of the tables generated. 1397 void db(uint8_t data); 1398 void dd(uint32_t data); 1399 1400 // Emits the address of the code stub's first instruction. 1401 void emit_code_stub_address(Code* stub); 1402 positions_recorder()1403 PositionsRecorder* positions_recorder() { return &positions_recorder_; } 1404 1405 // Read/patch instructions instr_at(int pos)1406 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } instr_at_put(int pos,Instr instr)1407 void instr_at_put(int pos, Instr instr) { 1408 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 1409 } instr_at(byte * pc)1410 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } instr_at_put(byte * pc,Instr instr)1411 static void instr_at_put(byte* pc, Instr instr) { 1412 *reinterpret_cast<Instr*>(pc) = instr; 1413 } 1414 static Condition GetCondition(Instr instr); 1415 static bool IsBranch(Instr instr); 1416 static int GetBranchOffset(Instr instr); 1417 static bool IsLdrRegisterImmediate(Instr instr); 1418 static bool IsVldrDRegisterImmediate(Instr instr); 1419 static Instr GetConsantPoolLoadPattern(); 1420 static Instr GetConsantPoolLoadMask(); 1421 static bool IsLdrPpRegOffset(Instr instr); 1422 static Instr GetLdrPpRegOffsetPattern(); 1423 static bool IsLdrPpImmediateOffset(Instr instr); 1424 static bool IsVldrDPpImmediateOffset(Instr instr); 1425 static int GetLdrRegisterImmediateOffset(Instr instr); 1426 static int GetVldrDRegisterImmediateOffset(Instr instr); 1427 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset); 1428 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset); 1429 static bool IsStrRegisterImmediate(Instr instr); 1430 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset); 1431 static bool IsAddRegisterImmediate(Instr instr); 1432 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset); 1433 static Register GetRd(Instr instr); 1434 static Register GetRn(Instr instr); 1435 static Register GetRm(Instr instr); 1436 static bool IsPush(Instr instr); 1437 static bool IsPop(Instr instr); 1438 static bool IsStrRegFpOffset(Instr instr); 1439 static bool IsLdrRegFpOffset(Instr instr); 1440 static bool IsStrRegFpNegOffset(Instr instr); 1441 static bool IsLdrRegFpNegOffset(Instr instr); 1442 static bool IsLdrPcImmediateOffset(Instr instr); 1443 static bool IsVldrDPcImmediateOffset(Instr instr); 1444 static bool IsBlxReg(Instr instr); 1445 static bool IsBlxIp(Instr instr); 1446 static bool IsTstImmediate(Instr instr); 1447 static bool IsCmpRegister(Instr instr); 1448 static bool IsCmpImmediate(Instr instr); 1449 static Register GetCmpImmediateRegister(Instr instr); 1450 static int GetCmpImmediateRawImmediate(Instr instr); 1451 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); 1452 static bool IsMovImmed(Instr instr); 1453 static bool IsOrrImmed(Instr instr); 1454 static bool IsMovT(Instr instr); 1455 static Instr GetMovTPattern(); 1456 static bool IsMovW(Instr instr); 1457 static Instr GetMovWPattern(); 1458 static Instr EncodeMovwImmediate(uint32_t immediate); 1459 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate); 1460 static int DecodeShiftImm(Instr instr); 1461 static Instr PatchShiftImm(Instr instr, int immed); 1462 1463 // Constants in pools are accessed via pc relative addressing, which can 1464 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point 1465 // PC-relative loads, thereby defining a maximum distance between the 1466 // instruction and the accessed constant. 1467 static const int kMaxDistToIntPool = 4*KB; 1468 static const int kMaxDistToFPPool = 1*KB; 1469 // All relocations could be integer, it therefore acts as the limit. 1470 static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize; 1471 static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize; 1472 1473 // Postpone the generation of the constant pool for the specified number of 1474 // instructions. 1475 void BlockConstPoolFor(int instructions); 1476 1477 // Check if is time to emit a constant pool. 1478 void CheckConstPool(bool force_emit, bool require_jump); 1479 1480 // Allocate a constant pool of the correct size for the generated code. 1481 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); 1482 1483 // Generate the constant pool for the generated code. 1484 void PopulateConstantPool(ConstantPoolArray* constant_pool); 1485 is_constant_pool_available()1486 bool is_constant_pool_available() const { return constant_pool_available_; } 1487 use_extended_constant_pool()1488 bool use_extended_constant_pool() const { 1489 return constant_pool_builder_.current_section() == 1490 ConstantPoolArray::EXTENDED_SECTION; 1491 } 1492 1493 1494 protected: 1495 // Relocation for a type-recording IC has the AST id added to it. This 1496 // member variable is a way to pass the information from the call site to 1497 // the relocation info. 1498 TypeFeedbackId recorded_ast_id_; 1499 buffer_space()1500 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 1501 1502 // Decode branch instruction at pos and return branch target pos 1503 int target_at(int pos); 1504 1505 // Patch branch instruction at pos to branch to given branch target pos 1506 void target_at_put(int pos, int target_pos); 1507 1508 // Prevent contant pool emission until EndBlockConstPool is called. 1509 // Call to this function can be nested but must be followed by an equal 1510 // number of call to EndBlockConstpool. StartBlockConstPool()1511 void StartBlockConstPool() { 1512 if (const_pool_blocked_nesting_++ == 0) { 1513 // Prevent constant pool checks happening by setting the next check to 1514 // the biggest possible offset. 1515 next_buffer_check_ = kMaxInt; 1516 } 1517 } 1518 1519 // Resume constant pool emission. Need to be called as many time as 1520 // StartBlockConstPool to have an effect. EndBlockConstPool()1521 void EndBlockConstPool() { 1522 if (--const_pool_blocked_nesting_ == 0) { 1523 #ifdef DEBUG 1524 // Max pool start (if we need a jump and an alignment). 1525 int start = pc_offset() + kInstrSize + 2 * kPointerSize; 1526 // Check the constant pool hasn't been blocked for too long. 1527 DCHECK((num_pending_32_bit_reloc_info_ == 0) || 1528 (start + num_pending_64_bit_reloc_info_ * kDoubleSize < 1529 (first_const_pool_32_use_ + kMaxDistToIntPool))); 1530 DCHECK((num_pending_64_bit_reloc_info_ == 0) || 1531 (start < (first_const_pool_64_use_ + kMaxDistToFPPool))); 1532 #endif 1533 // Two cases: 1534 // * no_const_pool_before_ >= next_buffer_check_ and the emission is 1535 // still blocked 1536 // * no_const_pool_before_ < next_buffer_check_ and the next emit will 1537 // trigger a check. 1538 next_buffer_check_ = no_const_pool_before_; 1539 } 1540 } 1541 is_const_pool_blocked()1542 bool is_const_pool_blocked() const { 1543 return (const_pool_blocked_nesting_ > 0) || 1544 (pc_offset() < no_const_pool_before_); 1545 } 1546 set_constant_pool_available(bool available)1547 void set_constant_pool_available(bool available) { 1548 constant_pool_available_ = available; 1549 } 1550 1551 private: 1552 int next_buffer_check_; // pc offset of next buffer check 1553 1554 // Code generation 1555 // The relocation writer's position is at least kGap bytes below the end of 1556 // the generated instructions. This is so that multi-instruction sequences do 1557 // not have to check for overflow. The same is true for writes of large 1558 // relocation info entries. 1559 static const int kGap = 32; 1560 1561 // Constant pool generation 1562 // Pools are emitted in the instruction stream, preferably after unconditional 1563 // jumps or after returns from functions (in dead code locations). 1564 // If a long code sequence does not contain unconditional jumps, it is 1565 // necessary to emit the constant pool before the pool gets too far from the 1566 // location it is accessed from. In this case, we emit a jump over the emitted 1567 // constant pool. 1568 // Constants in the pool may be addresses of functions that gets relocated; 1569 // if so, a relocation info entry is associated to the constant pool entry. 1570 1571 // Repeated checking whether the constant pool should be emitted is rather 1572 // expensive. By default we only check again once a number of instructions 1573 // has been generated. That also means that the sizing of the buffers is not 1574 // an exact science, and that we rely on some slop to not overrun buffers. 1575 static const int kCheckPoolIntervalInst = 32; 1576 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize; 1577 1578 1579 // Emission of the constant pool may be blocked in some code sequences. 1580 int const_pool_blocked_nesting_; // Block emission if this is not zero. 1581 int no_const_pool_before_; // Block emission before this pc offset. 1582 1583 // Keep track of the first instruction requiring a constant pool entry 1584 // since the previous constant pool was emitted. 1585 int first_const_pool_32_use_; 1586 int first_const_pool_64_use_; 1587 1588 // Relocation info generation 1589 // Each relocation is encoded as a variable size value 1590 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1591 RelocInfoWriter reloc_info_writer; 1592 1593 // Relocation info records are also used during code generation as temporary 1594 // containers for constants and code target addresses until they are emitted 1595 // to the constant pool. These pending relocation info records are temporarily 1596 // stored in a separate buffer until a constant pool is emitted. 1597 // If every instruction in a long sequence is accessing the pool, we need one 1598 // pending relocation entry per instruction. 1599 1600 // The buffers of pending relocation info. 1601 RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo]; 1602 RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo]; 1603 // Number of pending reloc info entries in the 32 bits buffer. 1604 int num_pending_32_bit_reloc_info_; 1605 // Number of pending reloc info entries in the 64 bits buffer. 1606 int num_pending_64_bit_reloc_info_; 1607 1608 ConstantPoolBuilder constant_pool_builder_; 1609 1610 // The bound position, before this we cannot do instruction elimination. 1611 int last_bound_pos_; 1612 1613 // Indicates whether the constant pool can be accessed, which is only possible 1614 // if the pp register points to the current code object's constant pool. 1615 bool constant_pool_available_; 1616 1617 // Code emission 1618 inline void CheckBuffer(); 1619 void GrowBuffer(); 1620 inline void emit(Instr x); 1621 1622 // 32-bit immediate values 1623 void move_32_bit_immediate(Register rd, 1624 const Operand& x, 1625 Condition cond = al); 1626 1627 // Instruction generation 1628 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); 1629 void addrmod2(Instr instr, Register rd, const MemOperand& x); 1630 void addrmod3(Instr instr, Register rd, const MemOperand& x); 1631 void addrmod4(Instr instr, Register rn, RegList rl); 1632 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); 1633 1634 // Labels 1635 void print(Label* L); 1636 void bind_to(Label* L, int pos); 1637 void next(Label* L); 1638 1639 enum UseConstantPoolMode { 1640 USE_CONSTANT_POOL, 1641 DONT_USE_CONSTANT_POOL 1642 }; 1643 1644 // Record reloc info for current pc_ 1645 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1646 void RecordRelocInfo(const RelocInfo& rinfo); 1647 ConstantPoolArray::LayoutSection ConstantPoolAddEntry(const RelocInfo& rinfo); 1648 1649 friend class RelocInfo; 1650 friend class CodePatcher; 1651 friend class BlockConstPoolScope; 1652 friend class FrameAndConstantPoolScope; 1653 friend class ConstantPoolUnavailableScope; 1654 1655 PositionsRecorder positions_recorder_; 1656 friend class PositionsRecorder; 1657 friend class EnsureSpace; 1658 }; 1659 1660 1661 class EnsureSpace BASE_EMBEDDED { 1662 public: EnsureSpace(Assembler * assembler)1663 explicit EnsureSpace(Assembler* assembler) { 1664 assembler->CheckBuffer(); 1665 } 1666 }; 1667 1668 1669 } } // namespace v8::internal 1670 1671 #endif // V8_ARM_ASSEMBLER_ARM_H_ 1672