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