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