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