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