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 #include "src/arm/assembler-arm.h" 38 39 #if V8_TARGET_ARCH_ARM 40 41 #include "src/arm/assembler-arm-inl.h" 42 #include "src/base/bits.h" 43 #include "src/base/cpu.h" 44 #include "src/macro-assembler.h" 45 46 namespace v8 { 47 namespace internal { 48 49 // Get the CPU features enabled by the build. For cross compilation the 50 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS 51 // can be defined to enable ARMv7 and VFPv3 instructions when building the 52 // snapshot. 53 static unsigned CpuFeaturesImpliedByCompiler() { 54 unsigned answer = 0; 55 #ifdef CAN_USE_ARMV8_INSTRUCTIONS 56 if (FLAG_enable_armv8) { 57 answer |= 1u << ARMv8; 58 // ARMv8 always features VFP and NEON. 59 answer |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS; 60 answer |= 1u << SUDIV | 1u << MLS; 61 } 62 #endif // CAN_USE_ARMV8_INSTRUCTIONS 63 #ifdef CAN_USE_ARMV7_INSTRUCTIONS 64 if (FLAG_enable_armv7) answer |= 1u << ARMv7; 65 #endif // CAN_USE_ARMV7_INSTRUCTIONS 66 #ifdef CAN_USE_VFP3_INSTRUCTIONS 67 if (FLAG_enable_vfp3) answer |= 1u << VFP3 | 1u << ARMv7; 68 #endif // CAN_USE_VFP3_INSTRUCTIONS 69 #ifdef CAN_USE_VFP32DREGS 70 if (FLAG_enable_32dregs) answer |= 1u << VFP32DREGS; 71 #endif // CAN_USE_VFP32DREGS 72 #ifdef CAN_USE_NEON 73 if (FLAG_enable_neon) answer |= 1u << NEON; 74 #endif // CAN_USE_VFP32DREGS 75 if ((answer & (1u << ARMv7)) && FLAG_enable_unaligned_accesses) { 76 answer |= 1u << UNALIGNED_ACCESSES; 77 } 78 79 return answer; 80 } 81 82 83 void CpuFeatures::ProbeImpl(bool cross_compile) { 84 supported_ |= CpuFeaturesImpliedByCompiler(); 85 cache_line_size_ = 64; 86 87 // Only use statically determined features for cross compile (snapshot). 88 if (cross_compile) return; 89 90 #ifndef __arm__ 91 // For the simulator build, use whatever the flags specify. 92 if (FLAG_enable_armv8) { 93 supported_ |= 1u << ARMv8; 94 // ARMv8 always features VFP and NEON. 95 supported_ |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS; 96 supported_ |= 1u << SUDIV | 1u << MLS; 97 if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; 98 } 99 if (FLAG_enable_armv7) { 100 supported_ |= 1u << ARMv7; 101 if (FLAG_enable_vfp3) supported_ |= 1u << VFP3; 102 if (FLAG_enable_neon) supported_ |= 1u << NEON | 1u << VFP32DREGS; 103 if (FLAG_enable_sudiv) supported_ |= 1u << SUDIV; 104 if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; 105 if (FLAG_enable_32dregs) supported_ |= 1u << VFP32DREGS; 106 } 107 if (FLAG_enable_mls) supported_ |= 1u << MLS; 108 if (FLAG_enable_unaligned_accesses) supported_ |= 1u << UNALIGNED_ACCESSES; 109 110 #else // __arm__ 111 // Probe for additional features at runtime. 112 base::CPU cpu; 113 if (FLAG_enable_vfp3 && cpu.has_vfp3()) { 114 // This implementation also sets the VFP flags if runtime 115 // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI 116 // 0406B, page A1-6. 117 supported_ |= 1u << VFP3 | 1u << ARMv7; 118 } 119 120 if (FLAG_enable_neon && cpu.has_neon()) supported_ |= 1u << NEON; 121 if (FLAG_enable_sudiv && cpu.has_idiva()) supported_ |= 1u << SUDIV; 122 if (FLAG_enable_mls && cpu.has_thumb2()) supported_ |= 1u << MLS; 123 124 if (cpu.architecture() >= 7) { 125 if (FLAG_enable_armv7) supported_ |= 1u << ARMv7; 126 if (FLAG_enable_armv8 && cpu.architecture() >= 8) { 127 supported_ |= 1u << ARMv8; 128 } 129 if (FLAG_enable_unaligned_accesses) supported_ |= 1u << UNALIGNED_ACCESSES; 130 // Use movw/movt for QUALCOMM ARMv7 cores. 131 if (FLAG_enable_movw_movt && cpu.implementer() == base::CPU::QUALCOMM) { 132 supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; 133 } 134 } 135 136 // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines. 137 if (cpu.implementer() == base::CPU::ARM && 138 (cpu.part() == base::CPU::ARM_CORTEX_A5 || 139 cpu.part() == base::CPU::ARM_CORTEX_A9)) { 140 cache_line_size_ = 32; 141 } 142 143 if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS; 144 145 if (cpu.implementer() == base::CPU::NVIDIA && 146 cpu.variant() == base::CPU::NVIDIA_DENVER && 147 cpu.part() <= base::CPU::NVIDIA_DENVER_V10) { 148 supported_ |= 1u << COHERENT_CACHE; 149 } 150 #endif 151 152 DCHECK(!IsSupported(VFP3) || IsSupported(ARMv7)); 153 } 154 155 156 void CpuFeatures::PrintTarget() { 157 const char* arm_arch = NULL; 158 const char* arm_target_type = ""; 159 const char* arm_no_probe = ""; 160 const char* arm_fpu = ""; 161 const char* arm_thumb = ""; 162 const char* arm_float_abi = NULL; 163 164 #if !defined __arm__ 165 arm_target_type = " simulator"; 166 #endif 167 168 #if defined ARM_TEST_NO_FEATURE_PROBE 169 arm_no_probe = " noprobe"; 170 #endif 171 172 #if defined CAN_USE_ARMV8_INSTRUCTIONS 173 arm_arch = "arm v8"; 174 #elif defined CAN_USE_ARMV7_INSTRUCTIONS 175 arm_arch = "arm v7"; 176 #else 177 arm_arch = "arm v6"; 178 #endif 179 180 #if defined CAN_USE_NEON 181 arm_fpu = " neon"; 182 #elif defined CAN_USE_VFP3_INSTRUCTIONS 183 # if defined CAN_USE_VFP32DREGS 184 arm_fpu = " vfp3"; 185 # else 186 arm_fpu = " vfp3-d16"; 187 # endif 188 #else 189 arm_fpu = " vfp2"; 190 #endif 191 192 #ifdef __arm__ 193 arm_float_abi = base::OS::ArmUsingHardFloat() ? "hard" : "softfp"; 194 #elif USE_EABI_HARDFLOAT 195 arm_float_abi = "hard"; 196 #else 197 arm_float_abi = "softfp"; 198 #endif 199 200 #if defined __arm__ && (defined __thumb__) || (defined __thumb2__) 201 arm_thumb = " thumb"; 202 #endif 203 204 printf("target%s%s %s%s%s %s\n", 205 arm_target_type, arm_no_probe, arm_arch, arm_fpu, arm_thumb, 206 arm_float_abi); 207 } 208 209 210 void CpuFeatures::PrintFeatures() { 211 printf( 212 "ARMv8=%d ARMv7=%d VFP3=%d VFP32DREGS=%d NEON=%d SUDIV=%d MLS=%d" 213 "UNALIGNED_ACCESSES=%d MOVW_MOVT_IMMEDIATE_LOADS=%d COHERENT_CACHE=%d", 214 CpuFeatures::IsSupported(ARMv8), 215 CpuFeatures::IsSupported(ARMv7), 216 CpuFeatures::IsSupported(VFP3), 217 CpuFeatures::IsSupported(VFP32DREGS), 218 CpuFeatures::IsSupported(NEON), 219 CpuFeatures::IsSupported(SUDIV), 220 CpuFeatures::IsSupported(MLS), 221 CpuFeatures::IsSupported(UNALIGNED_ACCESSES), 222 CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS), 223 CpuFeatures::IsSupported(COHERENT_CACHE)); 224 #ifdef __arm__ 225 bool eabi_hardfloat = base::OS::ArmUsingHardFloat(); 226 #elif USE_EABI_HARDFLOAT 227 bool eabi_hardfloat = true; 228 #else 229 bool eabi_hardfloat = false; 230 #endif 231 printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat); 232 } 233 234 235 // ----------------------------------------------------------------------------- 236 // Implementation of RelocInfo 237 238 // static 239 const int RelocInfo::kApplyMask = 0; 240 241 242 bool RelocInfo::IsCodedSpecially() { 243 // The deserializer needs to know whether a pointer is specially coded. Being 244 // specially coded on ARM means that it is a movw/movt instruction, or is an 245 // embedded constant pool entry. These only occur if 246 // FLAG_enable_embedded_constant_pool is true. 247 return FLAG_enable_embedded_constant_pool; 248 } 249 250 251 bool RelocInfo::IsInConstantPool() { 252 return Assembler::is_constant_pool_load(pc_); 253 } 254 255 256 // ----------------------------------------------------------------------------- 257 // Implementation of Operand and MemOperand 258 // See assembler-arm-inl.h for inlined constructors 259 260 Operand::Operand(Handle<Object> handle) { 261 AllowDeferredHandleDereference using_raw_address; 262 rm_ = no_reg; 263 // Verify all Objects referred by code are NOT in new space. 264 Object* obj = *handle; 265 if (obj->IsHeapObject()) { 266 DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); 267 imm32_ = reinterpret_cast<intptr_t>(handle.location()); 268 rmode_ = RelocInfo::EMBEDDED_OBJECT; 269 } else { 270 // no relocation needed 271 imm32_ = reinterpret_cast<intptr_t>(obj); 272 rmode_ = RelocInfo::NONE32; 273 } 274 } 275 276 277 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { 278 DCHECK(is_uint5(shift_imm)); 279 280 rm_ = rm; 281 rs_ = no_reg; 282 shift_op_ = shift_op; 283 shift_imm_ = shift_imm & 31; 284 285 if ((shift_op == ROR) && (shift_imm == 0)) { 286 // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode 287 // RRX as ROR #0 (See below). 288 shift_op = LSL; 289 } else if (shift_op == RRX) { 290 // encoded as ROR with shift_imm == 0 291 DCHECK(shift_imm == 0); 292 shift_op_ = ROR; 293 shift_imm_ = 0; 294 } 295 } 296 297 298 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) { 299 DCHECK(shift_op != RRX); 300 rm_ = rm; 301 rs_ = no_reg; 302 shift_op_ = shift_op; 303 rs_ = rs; 304 } 305 306 307 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) { 308 rn_ = rn; 309 rm_ = no_reg; 310 offset_ = offset; 311 am_ = am; 312 313 // Accesses below the stack pointer are not safe, and are prohibited by the 314 // ABI. We can check obvious violations here. 315 if (rn.is(sp)) { 316 if (am == Offset) DCHECK_LE(0, offset); 317 if (am == NegOffset) DCHECK_GE(0, offset); 318 } 319 } 320 321 322 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) { 323 rn_ = rn; 324 rm_ = rm; 325 shift_op_ = LSL; 326 shift_imm_ = 0; 327 am_ = am; 328 } 329 330 331 MemOperand::MemOperand(Register rn, Register rm, 332 ShiftOp shift_op, int shift_imm, AddrMode am) { 333 DCHECK(is_uint5(shift_imm)); 334 rn_ = rn; 335 rm_ = rm; 336 shift_op_ = shift_op; 337 shift_imm_ = shift_imm & 31; 338 am_ = am; 339 } 340 341 342 NeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) { 343 DCHECK((am == Offset) || (am == PostIndex)); 344 rn_ = rn; 345 rm_ = (am == Offset) ? pc : sp; 346 SetAlignment(align); 347 } 348 349 350 NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) { 351 rn_ = rn; 352 rm_ = rm; 353 SetAlignment(align); 354 } 355 356 357 void NeonMemOperand::SetAlignment(int align) { 358 switch (align) { 359 case 0: 360 align_ = 0; 361 break; 362 case 64: 363 align_ = 1; 364 break; 365 case 128: 366 align_ = 2; 367 break; 368 case 256: 369 align_ = 3; 370 break; 371 default: 372 UNREACHABLE(); 373 align_ = 0; 374 break; 375 } 376 } 377 378 379 NeonListOperand::NeonListOperand(DoubleRegister base, int registers_count) { 380 base_ = base; 381 switch (registers_count) { 382 case 1: 383 type_ = nlt_1; 384 break; 385 case 2: 386 type_ = nlt_2; 387 break; 388 case 3: 389 type_ = nlt_3; 390 break; 391 case 4: 392 type_ = nlt_4; 393 break; 394 default: 395 UNREACHABLE(); 396 type_ = nlt_1; 397 break; 398 } 399 } 400 401 402 // ----------------------------------------------------------------------------- 403 // Specific instructions, constants, and masks. 404 405 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) 406 // register r is not encoded. 407 const Instr kPushRegPattern = 408 al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16; 409 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) 410 // register r is not encoded. 411 const Instr kPopRegPattern = 412 al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16; 413 // ldr rd, [pc, #offset] 414 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16; 415 const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16; 416 // ldr rd, [pp, #offset] 417 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16; 418 const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16; 419 // ldr rd, [pp, rn] 420 const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16; 421 const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16; 422 // vldr dd, [pc, #offset] 423 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; 424 const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8; 425 // vldr dd, [pp, #offset] 426 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; 427 const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8; 428 // blxcc rm 429 const Instr kBlxRegMask = 430 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; 431 const Instr kBlxRegPattern = 432 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX; 433 const Instr kBlxIp = al | kBlxRegPattern | ip.code(); 434 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16; 435 const Instr kMovMvnPattern = 0xd * B21; 436 const Instr kMovMvnFlip = B22; 437 const Instr kMovLeaveCCMask = 0xdff * B16; 438 const Instr kMovLeaveCCPattern = 0x1a0 * B16; 439 const Instr kMovwPattern = 0x30 * B20; 440 const Instr kMovtPattern = 0x34 * B20; 441 const Instr kMovwLeaveCCFlip = 0x5 * B21; 442 const Instr kMovImmedMask = 0x7f * B21; 443 const Instr kMovImmedPattern = 0x1d * B21; 444 const Instr kOrrImmedMask = 0x7f * B21; 445 const Instr kOrrImmedPattern = 0x1c * B21; 446 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12; 447 const Instr kCmpCmnPattern = 0x15 * B20; 448 const Instr kCmpCmnFlip = B21; 449 const Instr kAddSubFlip = 0x6 * B21; 450 const Instr kAndBicFlip = 0xe * B21; 451 452 // A mask for the Rd register for push, pop, ldr, str instructions. 453 const Instr kLdrRegFpOffsetPattern = 454 al | B26 | L | Offset | Register::kCode_fp * B16; 455 const Instr kStrRegFpOffsetPattern = 456 al | B26 | Offset | Register::kCode_fp * B16; 457 const Instr kLdrRegFpNegOffsetPattern = 458 al | B26 | L | NegOffset | Register::kCode_fp * B16; 459 const Instr kStrRegFpNegOffsetPattern = 460 al | B26 | NegOffset | Register::kCode_fp * B16; 461 const Instr kLdrStrInstrTypeMask = 0xffff0000; 462 463 464 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) 465 : AssemblerBase(isolate, buffer, buffer_size), 466 recorded_ast_id_(TypeFeedbackId::None()), 467 pending_32_bit_constants_(&pending_32_bit_constants_buffer_[0]), 468 pending_64_bit_constants_(&pending_64_bit_constants_buffer_[0]), 469 constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits), 470 positions_recorder_(this) { 471 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); 472 num_pending_32_bit_constants_ = 0; 473 num_pending_64_bit_constants_ = 0; 474 next_buffer_check_ = 0; 475 const_pool_blocked_nesting_ = 0; 476 no_const_pool_before_ = 0; 477 first_const_pool_32_use_ = -1; 478 first_const_pool_64_use_ = -1; 479 last_bound_pos_ = 0; 480 ClearRecordedAstId(); 481 } 482 483 484 Assembler::~Assembler() { 485 DCHECK(const_pool_blocked_nesting_ == 0); 486 if (pending_32_bit_constants_ != &pending_32_bit_constants_buffer_[0]) { 487 delete[] pending_32_bit_constants_; 488 } 489 if (pending_64_bit_constants_ != &pending_64_bit_constants_buffer_[0]) { 490 delete[] pending_64_bit_constants_; 491 } 492 } 493 494 495 void Assembler::GetCode(CodeDesc* desc) { 496 reloc_info_writer.Finish(); 497 498 // Emit constant pool if necessary. 499 int constant_pool_offset = 0; 500 if (FLAG_enable_embedded_constant_pool) { 501 constant_pool_offset = EmitEmbeddedConstantPool(); 502 } else { 503 CheckConstPool(true, false); 504 DCHECK(num_pending_32_bit_constants_ == 0); 505 DCHECK(num_pending_64_bit_constants_ == 0); 506 } 507 // Set up code descriptor. 508 desc->buffer = buffer_; 509 desc->buffer_size = buffer_size_; 510 desc->instr_size = pc_offset(); 511 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 512 desc->constant_pool_size = 513 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0); 514 desc->origin = this; 515 } 516 517 518 void Assembler::Align(int m) { 519 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); 520 DCHECK((pc_offset() & (kInstrSize - 1)) == 0); 521 while ((pc_offset() & (m - 1)) != 0) { 522 nop(); 523 } 524 } 525 526 527 void Assembler::CodeTargetAlign() { 528 // Preferred alignment of jump targets on some ARM chips. 529 Align(8); 530 } 531 532 533 Condition Assembler::GetCondition(Instr instr) { 534 return Instruction::ConditionField(instr); 535 } 536 537 538 bool Assembler::IsBranch(Instr instr) { 539 return (instr & (B27 | B25)) == (B27 | B25); 540 } 541 542 543 int Assembler::GetBranchOffset(Instr instr) { 544 DCHECK(IsBranch(instr)); 545 // Take the jump offset in the lower 24 bits, sign extend it and multiply it 546 // with 4 to get the offset in bytes. 547 return ((instr & kImm24Mask) << 8) >> 6; 548 } 549 550 551 bool Assembler::IsLdrRegisterImmediate(Instr instr) { 552 return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20); 553 } 554 555 556 bool Assembler::IsVldrDRegisterImmediate(Instr instr) { 557 return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8); 558 } 559 560 561 int Assembler::GetLdrRegisterImmediateOffset(Instr instr) { 562 DCHECK(IsLdrRegisterImmediate(instr)); 563 bool positive = (instr & B23) == B23; 564 int offset = instr & kOff12Mask; // Zero extended offset. 565 return positive ? offset : -offset; 566 } 567 568 569 int Assembler::GetVldrDRegisterImmediateOffset(Instr instr) { 570 DCHECK(IsVldrDRegisterImmediate(instr)); 571 bool positive = (instr & B23) == B23; 572 int offset = instr & kOff8Mask; // Zero extended offset. 573 offset <<= 2; 574 return positive ? offset : -offset; 575 } 576 577 578 Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) { 579 DCHECK(IsLdrRegisterImmediate(instr)); 580 bool positive = offset >= 0; 581 if (!positive) offset = -offset; 582 DCHECK(is_uint12(offset)); 583 // Set bit indicating whether the offset should be added. 584 instr = (instr & ~B23) | (positive ? B23 : 0); 585 // Set the actual offset. 586 return (instr & ~kOff12Mask) | offset; 587 } 588 589 590 Instr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) { 591 DCHECK(IsVldrDRegisterImmediate(instr)); 592 DCHECK((offset & ~3) == offset); // Must be 64-bit aligned. 593 bool positive = offset >= 0; 594 if (!positive) offset = -offset; 595 DCHECK(is_uint10(offset)); 596 // Set bit indicating whether the offset should be added. 597 instr = (instr & ~B23) | (positive ? B23 : 0); 598 // Set the actual offset. Its bottom 2 bits are zero. 599 return (instr & ~kOff8Mask) | (offset >> 2); 600 } 601 602 603 bool Assembler::IsStrRegisterImmediate(Instr instr) { 604 return (instr & (B27 | B26 | B25 | B22 | B20)) == B26; 605 } 606 607 608 Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) { 609 DCHECK(IsStrRegisterImmediate(instr)); 610 bool positive = offset >= 0; 611 if (!positive) offset = -offset; 612 DCHECK(is_uint12(offset)); 613 // Set bit indicating whether the offset should be added. 614 instr = (instr & ~B23) | (positive ? B23 : 0); 615 // Set the actual offset. 616 return (instr & ~kOff12Mask) | offset; 617 } 618 619 620 bool Assembler::IsAddRegisterImmediate(Instr instr) { 621 return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23); 622 } 623 624 625 Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) { 626 DCHECK(IsAddRegisterImmediate(instr)); 627 DCHECK(offset >= 0); 628 DCHECK(is_uint12(offset)); 629 // Set the offset. 630 return (instr & ~kOff12Mask) | offset; 631 } 632 633 634 Register Assembler::GetRd(Instr instr) { 635 Register reg; 636 reg.reg_code = Instruction::RdValue(instr); 637 return reg; 638 } 639 640 641 Register Assembler::GetRn(Instr instr) { 642 Register reg; 643 reg.reg_code = Instruction::RnValue(instr); 644 return reg; 645 } 646 647 648 Register Assembler::GetRm(Instr instr) { 649 Register reg; 650 reg.reg_code = Instruction::RmValue(instr); 651 return reg; 652 } 653 654 655 Instr Assembler::GetConsantPoolLoadPattern() { 656 if (FLAG_enable_embedded_constant_pool) { 657 return kLdrPpImmedPattern; 658 } else { 659 return kLdrPCImmedPattern; 660 } 661 } 662 663 664 Instr Assembler::GetConsantPoolLoadMask() { 665 if (FLAG_enable_embedded_constant_pool) { 666 return kLdrPpImmedMask; 667 } else { 668 return kLdrPCImmedMask; 669 } 670 } 671 672 673 bool Assembler::IsPush(Instr instr) { 674 return ((instr & ~kRdMask) == kPushRegPattern); 675 } 676 677 678 bool Assembler::IsPop(Instr instr) { 679 return ((instr & ~kRdMask) == kPopRegPattern); 680 } 681 682 683 bool Assembler::IsStrRegFpOffset(Instr instr) { 684 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern); 685 } 686 687 688 bool Assembler::IsLdrRegFpOffset(Instr instr) { 689 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern); 690 } 691 692 693 bool Assembler::IsStrRegFpNegOffset(Instr instr) { 694 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern); 695 } 696 697 698 bool Assembler::IsLdrRegFpNegOffset(Instr instr) { 699 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern); 700 } 701 702 703 bool Assembler::IsLdrPcImmediateOffset(Instr instr) { 704 // Check the instruction is indeed a 705 // ldr<cond> <Rd>, [pc +/- offset_12]. 706 return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern; 707 } 708 709 710 bool Assembler::IsLdrPpImmediateOffset(Instr instr) { 711 // Check the instruction is indeed a 712 // ldr<cond> <Rd>, [pp +/- offset_12]. 713 return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern; 714 } 715 716 717 bool Assembler::IsLdrPpRegOffset(Instr instr) { 718 // Check the instruction is indeed a 719 // ldr<cond> <Rd>, [pp, +/- <Rm>]. 720 return (instr & kLdrPpRegMask) == kLdrPpRegPattern; 721 } 722 723 724 Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; } 725 726 727 bool Assembler::IsVldrDPcImmediateOffset(Instr instr) { 728 // Check the instruction is indeed a 729 // vldr<cond> <Dd>, [pc +/- offset_10]. 730 return (instr & kVldrDPCMask) == kVldrDPCPattern; 731 } 732 733 734 bool Assembler::IsVldrDPpImmediateOffset(Instr instr) { 735 // Check the instruction is indeed a 736 // vldr<cond> <Dd>, [pp +/- offset_10]. 737 return (instr & kVldrDPpMask) == kVldrDPpPattern; 738 } 739 740 741 bool Assembler::IsBlxReg(Instr instr) { 742 // Check the instruction is indeed a 743 // blxcc <Rm> 744 return (instr & kBlxRegMask) == kBlxRegPattern; 745 } 746 747 748 bool Assembler::IsBlxIp(Instr instr) { 749 // Check the instruction is indeed a 750 // blx ip 751 return instr == kBlxIp; 752 } 753 754 755 bool Assembler::IsTstImmediate(Instr instr) { 756 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == 757 (I | TST | S); 758 } 759 760 761 bool Assembler::IsCmpRegister(Instr instr) { 762 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) == 763 (CMP | S); 764 } 765 766 767 bool Assembler::IsCmpImmediate(Instr instr) { 768 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == 769 (I | CMP | S); 770 } 771 772 773 Register Assembler::GetCmpImmediateRegister(Instr instr) { 774 DCHECK(IsCmpImmediate(instr)); 775 return GetRn(instr); 776 } 777 778 779 int Assembler::GetCmpImmediateRawImmediate(Instr instr) { 780 DCHECK(IsCmpImmediate(instr)); 781 return instr & kOff12Mask; 782 } 783 784 785 // Labels refer to positions in the (to be) generated code. 786 // There are bound, linked, and unused labels. 787 // 788 // Bound labels refer to known positions in the already 789 // generated code. pos() is the position the label refers to. 790 // 791 // Linked labels refer to unknown positions in the code 792 // to be generated; pos() is the position of the last 793 // instruction using the label. 794 // 795 // The linked labels form a link chain by making the branch offset 796 // in the instruction steam to point to the previous branch 797 // instruction using the same label. 798 // 799 // The link chain is terminated by a branch offset pointing to the 800 // same position. 801 802 803 int Assembler::target_at(int pos) { 804 Instr instr = instr_at(pos); 805 if (is_uint24(instr)) { 806 // Emitted link to a label, not part of a branch. 807 return instr; 808 } 809 DCHECK_EQ(5 * B25, instr & 7 * B25); // b, bl, or blx imm24 810 int imm26 = ((instr & kImm24Mask) << 8) >> 6; 811 if ((Instruction::ConditionField(instr) == kSpecialCondition) && 812 ((instr & B24) != 0)) { 813 // blx uses bit 24 to encode bit 2 of imm26 814 imm26 += 2; 815 } 816 return pos + kPcLoadDelta + imm26; 817 } 818 819 820 void Assembler::target_at_put(int pos, int target_pos) { 821 Instr instr = instr_at(pos); 822 if (is_uint24(instr)) { 823 DCHECK(target_pos == pos || target_pos >= 0); 824 // Emitted link to a label, not part of a branch. 825 // Load the position of the label relative to the generated code object 826 // pointer in a register. 827 828 // Here are the instructions we need to emit: 829 // For ARMv7: target24 => target16_1:target16_0 830 // movw dst, #target16_0 831 // movt dst, #target16_1 832 // For ARMv6: target24 => target8_2:target8_1:target8_0 833 // mov dst, #target8_0 834 // orr dst, dst, #target8_1 << 8 835 // orr dst, dst, #target8_2 << 16 836 837 // We extract the destination register from the emitted nop instruction. 838 Register dst = Register::from_code( 839 Instruction::RmValue(instr_at(pos + kInstrSize))); 840 DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code())); 841 uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag); 842 DCHECK(is_uint24(target24)); 843 if (is_uint8(target24)) { 844 // If the target fits in a byte then only patch with a mov 845 // instruction. 846 CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 1, 847 CodePatcher::DONT_FLUSH); 848 patcher.masm()->mov(dst, Operand(target24)); 849 } else { 850 uint16_t target16_0 = target24 & kImm16Mask; 851 uint16_t target16_1 = target24 >> 16; 852 if (CpuFeatures::IsSupported(ARMv7)) { 853 // Patch with movw/movt. 854 if (target16_1 == 0) { 855 CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 856 1, CodePatcher::DONT_FLUSH); 857 patcher.masm()->movw(dst, target16_0); 858 } else { 859 CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 860 2, CodePatcher::DONT_FLUSH); 861 patcher.masm()->movw(dst, target16_0); 862 patcher.masm()->movt(dst, target16_1); 863 } 864 } else { 865 // Patch with a sequence of mov/orr/orr instructions. 866 uint8_t target8_0 = target16_0 & kImm8Mask; 867 uint8_t target8_1 = target16_0 >> 8; 868 uint8_t target8_2 = target16_1 & kImm8Mask; 869 if (target8_2 == 0) { 870 CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 871 2, CodePatcher::DONT_FLUSH); 872 patcher.masm()->mov(dst, Operand(target8_0)); 873 patcher.masm()->orr(dst, dst, Operand(target8_1 << 8)); 874 } else { 875 CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 876 3, CodePatcher::DONT_FLUSH); 877 patcher.masm()->mov(dst, Operand(target8_0)); 878 patcher.masm()->orr(dst, dst, Operand(target8_1 << 8)); 879 patcher.masm()->orr(dst, dst, Operand(target8_2 << 16)); 880 } 881 } 882 } 883 return; 884 } 885 int imm26 = target_pos - (pos + kPcLoadDelta); 886 DCHECK_EQ(5 * B25, instr & 7 * B25); // b, bl, or blx imm24 887 if (Instruction::ConditionField(instr) == kSpecialCondition) { 888 // blx uses bit 24 to encode bit 2 of imm26 889 DCHECK_EQ(0, imm26 & 1); 890 instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1) * B24; 891 } else { 892 DCHECK_EQ(0, imm26 & 3); 893 instr &= ~kImm24Mask; 894 } 895 int imm24 = imm26 >> 2; 896 DCHECK(is_int24(imm24)); 897 instr_at_put(pos, instr | (imm24 & kImm24Mask)); 898 } 899 900 901 void Assembler::print(Label* L) { 902 if (L->is_unused()) { 903 PrintF("unused label\n"); 904 } else if (L->is_bound()) { 905 PrintF("bound label to %d\n", L->pos()); 906 } else if (L->is_linked()) { 907 Label l = *L; 908 PrintF("unbound label"); 909 while (l.is_linked()) { 910 PrintF("@ %d ", l.pos()); 911 Instr instr = instr_at(l.pos()); 912 if ((instr & ~kImm24Mask) == 0) { 913 PrintF("value\n"); 914 } else { 915 DCHECK((instr & 7*B25) == 5*B25); // b, bl, or blx 916 Condition cond = Instruction::ConditionField(instr); 917 const char* b; 918 const char* c; 919 if (cond == kSpecialCondition) { 920 b = "blx"; 921 c = ""; 922 } else { 923 if ((instr & B24) != 0) 924 b = "bl"; 925 else 926 b = "b"; 927 928 switch (cond) { 929 case eq: c = "eq"; break; 930 case ne: c = "ne"; break; 931 case hs: c = "hs"; break; 932 case lo: c = "lo"; break; 933 case mi: c = "mi"; break; 934 case pl: c = "pl"; break; 935 case vs: c = "vs"; break; 936 case vc: c = "vc"; break; 937 case hi: c = "hi"; break; 938 case ls: c = "ls"; break; 939 case ge: c = "ge"; break; 940 case lt: c = "lt"; break; 941 case gt: c = "gt"; break; 942 case le: c = "le"; break; 943 case al: c = ""; break; 944 default: 945 c = ""; 946 UNREACHABLE(); 947 } 948 } 949 PrintF("%s%s\n", b, c); 950 } 951 next(&l); 952 } 953 } else { 954 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 955 } 956 } 957 958 959 void Assembler::bind_to(Label* L, int pos) { 960 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position 961 while (L->is_linked()) { 962 int fixup_pos = L->pos(); 963 next(L); // call next before overwriting link with target at fixup_pos 964 target_at_put(fixup_pos, pos); 965 } 966 L->bind_to(pos); 967 968 // Keep track of the last bound label so we don't eliminate any instructions 969 // before a bound label. 970 if (pos > last_bound_pos_) 971 last_bound_pos_ = pos; 972 } 973 974 975 void Assembler::bind(Label* L) { 976 DCHECK(!L->is_bound()); // label can only be bound once 977 bind_to(L, pc_offset()); 978 } 979 980 981 void Assembler::next(Label* L) { 982 DCHECK(L->is_linked()); 983 int link = target_at(L->pos()); 984 if (link == L->pos()) { 985 // Branch target points to the same instuction. This is the end of the link 986 // chain. 987 L->Unuse(); 988 } else { 989 DCHECK(link >= 0); 990 L->link_to(link); 991 } 992 } 993 994 995 // Low-level code emission routines depending on the addressing mode. 996 // If this returns true then you have to use the rotate_imm and immed_8 997 // that it returns, because it may have already changed the instruction 998 // to match them! 999 static bool fits_shifter(uint32_t imm32, 1000 uint32_t* rotate_imm, 1001 uint32_t* immed_8, 1002 Instr* instr) { 1003 // imm32 must be unsigned. 1004 for (int rot = 0; rot < 16; rot++) { 1005 uint32_t imm8 = base::bits::RotateLeft32(imm32, 2 * rot); 1006 if ((imm8 <= 0xff)) { 1007 *rotate_imm = rot; 1008 *immed_8 = imm8; 1009 return true; 1010 } 1011 } 1012 // If the opcode is one with a complementary version and the complementary 1013 // immediate fits, change the opcode. 1014 if (instr != NULL) { 1015 if ((*instr & kMovMvnMask) == kMovMvnPattern) { 1016 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { 1017 *instr ^= kMovMvnFlip; 1018 return true; 1019 } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) { 1020 if (CpuFeatures::IsSupported(ARMv7)) { 1021 if (imm32 < 0x10000) { 1022 *instr ^= kMovwLeaveCCFlip; 1023 *instr |= Assembler::EncodeMovwImmediate(imm32); 1024 *rotate_imm = *immed_8 = 0; // Not used for movw. 1025 return true; 1026 } 1027 } 1028 } 1029 } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) { 1030 if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) { 1031 *instr ^= kCmpCmnFlip; 1032 return true; 1033 } 1034 } else { 1035 Instr alu_insn = (*instr & kALUMask); 1036 if (alu_insn == ADD || 1037 alu_insn == SUB) { 1038 if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) { 1039 *instr ^= kAddSubFlip; 1040 return true; 1041 } 1042 } else if (alu_insn == AND || 1043 alu_insn == BIC) { 1044 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { 1045 *instr ^= kAndBicFlip; 1046 return true; 1047 } 1048 } 1049 } 1050 } 1051 return false; 1052 } 1053 1054 1055 // We have to use the temporary register for things that can be relocated even 1056 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction 1057 // space. There is no guarantee that the relocated location can be similarly 1058 // encoded. 1059 bool Operand::must_output_reloc_info(const Assembler* assembler) const { 1060 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { 1061 if (assembler != NULL && assembler->predictable_code_size()) return true; 1062 return assembler->serializer_enabled(); 1063 } else if (RelocInfo::IsNone(rmode_)) { 1064 return false; 1065 } 1066 return true; 1067 } 1068 1069 1070 static bool use_mov_immediate_load(const Operand& x, 1071 const Assembler* assembler) { 1072 if (FLAG_enable_embedded_constant_pool && assembler != NULL && 1073 !assembler->is_constant_pool_available()) { 1074 return true; 1075 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && 1076 (assembler == NULL || !assembler->predictable_code_size())) { 1077 // Prefer movw / movt to constant pool if it is more efficient on the CPU. 1078 return true; 1079 } else if (x.must_output_reloc_info(assembler)) { 1080 // Prefer constant pool if data is likely to be patched. 1081 return false; 1082 } else { 1083 // Otherwise, use immediate load if movw / movt is available. 1084 return CpuFeatures::IsSupported(ARMv7); 1085 } 1086 } 1087 1088 1089 int Operand::instructions_required(const Assembler* assembler, 1090 Instr instr) const { 1091 if (rm_.is_valid()) return 1; 1092 uint32_t dummy1, dummy2; 1093 if (must_output_reloc_info(assembler) || 1094 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { 1095 // The immediate operand cannot be encoded as a shifter operand, or use of 1096 // constant pool is required. First account for the instructions required 1097 // for the constant pool or immediate load 1098 int instructions; 1099 if (use_mov_immediate_load(*this, assembler)) { 1100 // A movw / movt or mov / orr immediate load. 1101 instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4; 1102 } else if (assembler != NULL && 1103 assembler->ConstantPoolAccessIsInOverflow()) { 1104 // An overflowed constant pool load. 1105 instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5; 1106 } else { 1107 // A small constant pool load. 1108 instructions = 1; 1109 } 1110 1111 if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set 1112 // For a mov or mvn instruction which doesn't set the condition 1113 // code, the constant pool or immediate load is enough, otherwise we need 1114 // to account for the actual instruction being requested. 1115 instructions += 1; 1116 } 1117 return instructions; 1118 } else { 1119 // No use of constant pool and the immediate operand can be encoded as a 1120 // shifter operand. 1121 return 1; 1122 } 1123 } 1124 1125 1126 void Assembler::move_32_bit_immediate(Register rd, 1127 const Operand& x, 1128 Condition cond) { 1129 uint32_t imm32 = static_cast<uint32_t>(x.imm32_); 1130 if (x.must_output_reloc_info(this)) { 1131 RecordRelocInfo(x.rmode_); 1132 } 1133 1134 if (use_mov_immediate_load(x, this)) { 1135 Register target = rd.code() == pc.code() ? ip : rd; 1136 if (CpuFeatures::IsSupported(ARMv7)) { 1137 if (!FLAG_enable_embedded_constant_pool && 1138 x.must_output_reloc_info(this)) { 1139 // Make sure the movw/movt doesn't get separated. 1140 BlockConstPoolFor(2); 1141 } 1142 movw(target, imm32 & 0xffff, cond); 1143 movt(target, imm32 >> 16, cond); 1144 } else { 1145 DCHECK(FLAG_enable_embedded_constant_pool); 1146 mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond); 1147 orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond); 1148 orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond); 1149 orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond); 1150 } 1151 if (target.code() != rd.code()) { 1152 mov(rd, target, LeaveCC, cond); 1153 } 1154 } else { 1155 DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available()); 1156 ConstantPoolEntry::Access access = 1157 ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_); 1158 if (access == ConstantPoolEntry::OVERFLOWED) { 1159 DCHECK(FLAG_enable_embedded_constant_pool); 1160 Register target = rd.code() == pc.code() ? ip : rd; 1161 // Emit instructions to load constant pool offset. 1162 if (CpuFeatures::IsSupported(ARMv7)) { 1163 movw(target, 0, cond); 1164 movt(target, 0, cond); 1165 } else { 1166 mov(target, Operand(0), LeaveCC, cond); 1167 orr(target, target, Operand(0), LeaveCC, cond); 1168 orr(target, target, Operand(0), LeaveCC, cond); 1169 orr(target, target, Operand(0), LeaveCC, cond); 1170 } 1171 // Load from constant pool at offset. 1172 ldr(rd, MemOperand(pp, target), cond); 1173 } else { 1174 DCHECK(access == ConstantPoolEntry::REGULAR); 1175 ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0), 1176 cond); 1177 } 1178 } 1179 } 1180 1181 1182 void Assembler::addrmod1(Instr instr, 1183 Register rn, 1184 Register rd, 1185 const Operand& x) { 1186 CheckBuffer(); 1187 DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0); 1188 if (!x.rm_.is_valid()) { 1189 // Immediate. 1190 uint32_t rotate_imm; 1191 uint32_t immed_8; 1192 if (x.must_output_reloc_info(this) || 1193 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { 1194 // The immediate operand cannot be encoded as a shifter operand, so load 1195 // it first to register ip and change the original instruction to use ip. 1196 // However, if the original instruction is a 'mov rd, x' (not setting the 1197 // condition code), then replace it with a 'ldr rd, [pc]'. 1198 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed 1199 Condition cond = Instruction::ConditionField(instr); 1200 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set 1201 move_32_bit_immediate(rd, x, cond); 1202 } else { 1203 mov(ip, x, LeaveCC, cond); 1204 addrmod1(instr, rn, rd, Operand(ip)); 1205 } 1206 return; 1207 } 1208 instr |= I | rotate_imm*B8 | immed_8; 1209 } else if (!x.rs_.is_valid()) { 1210 // Immediate shift. 1211 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 1212 } else { 1213 // Register shift. 1214 DCHECK(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); 1215 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); 1216 } 1217 emit(instr | rn.code()*B16 | rd.code()*B12); 1218 if (rn.is(pc) || x.rm_.is(pc)) { 1219 // Block constant pool emission for one instruction after reading pc. 1220 BlockConstPoolFor(1); 1221 } 1222 } 1223 1224 1225 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) { 1226 DCHECK((instr & ~(kCondMask | B | L)) == B26); 1227 int am = x.am_; 1228 if (!x.rm_.is_valid()) { 1229 // Immediate offset. 1230 int offset_12 = x.offset_; 1231 if (offset_12 < 0) { 1232 offset_12 = -offset_12; 1233 am ^= U; 1234 } 1235 if (!is_uint12(offset_12)) { 1236 // Immediate offset cannot be encoded, load it first to register ip 1237 // rn (and rd in a load) should never be ip, or will be trashed. 1238 DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 1239 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr)); 1240 addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_)); 1241 return; 1242 } 1243 DCHECK(offset_12 >= 0); // no masking needed 1244 instr |= offset_12; 1245 } else { 1246 // Register offset (shift_imm_ and shift_op_ are 0) or scaled 1247 // register offset the constructors make sure than both shift_imm_ 1248 // and shift_op_ are initialized. 1249 DCHECK(!x.rm_.is(pc)); 1250 instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 1251 } 1252 DCHECK((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 1253 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 1254 } 1255 1256 1257 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) { 1258 DCHECK((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7)); 1259 DCHECK(x.rn_.is_valid()); 1260 int am = x.am_; 1261 if (!x.rm_.is_valid()) { 1262 // Immediate offset. 1263 int offset_8 = x.offset_; 1264 if (offset_8 < 0) { 1265 offset_8 = -offset_8; 1266 am ^= U; 1267 } 1268 if (!is_uint8(offset_8)) { 1269 // Immediate offset cannot be encoded, load it first to register ip 1270 // rn (and rd in a load) should never be ip, or will be trashed. 1271 DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 1272 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr)); 1273 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 1274 return; 1275 } 1276 DCHECK(offset_8 >= 0); // no masking needed 1277 instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf); 1278 } else if (x.shift_imm_ != 0) { 1279 // Scaled register offset not supported, load index first 1280 // rn (and rd in a load) should never be ip, or will be trashed. 1281 DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 1282 mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC, 1283 Instruction::ConditionField(instr)); 1284 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 1285 return; 1286 } else { 1287 // Register offset. 1288 DCHECK((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback 1289 instr |= x.rm_.code(); 1290 } 1291 DCHECK((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 1292 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 1293 } 1294 1295 1296 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) { 1297 DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27); 1298 DCHECK(rl != 0); 1299 DCHECK(!rn.is(pc)); 1300 emit(instr | rn.code()*B16 | rl); 1301 } 1302 1303 1304 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) { 1305 // Unindexed addressing is not encoded by this function. 1306 DCHECK_EQ((B27 | B26), 1307 (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L))); 1308 DCHECK(x.rn_.is_valid() && !x.rm_.is_valid()); 1309 int am = x.am_; 1310 int offset_8 = x.offset_; 1311 DCHECK((offset_8 & 3) == 0); // offset must be an aligned word offset 1312 offset_8 >>= 2; 1313 if (offset_8 < 0) { 1314 offset_8 = -offset_8; 1315 am ^= U; 1316 } 1317 DCHECK(is_uint8(offset_8)); // unsigned word offset must fit in a byte 1318 DCHECK((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 1319 1320 // Post-indexed addressing requires W == 1; different than in addrmod2/3. 1321 if ((am & P) == 0) 1322 am |= W; 1323 1324 DCHECK(offset_8 >= 0); // no masking needed 1325 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); 1326 } 1327 1328 1329 int Assembler::branch_offset(Label* L) { 1330 int target_pos; 1331 if (L->is_bound()) { 1332 target_pos = L->pos(); 1333 } else { 1334 if (L->is_linked()) { 1335 // Point to previous instruction that uses the link. 1336 target_pos = L->pos(); 1337 } else { 1338 // First entry of the link chain points to itself. 1339 target_pos = pc_offset(); 1340 } 1341 L->link_to(pc_offset()); 1342 } 1343 1344 // Block the emission of the constant pool, since the branch instruction must 1345 // be emitted at the pc offset recorded by the label. 1346 if (!is_const_pool_blocked()) BlockConstPoolFor(1); 1347 1348 return target_pos - (pc_offset() + kPcLoadDelta); 1349 } 1350 1351 1352 // Branch instructions. 1353 void Assembler::b(int branch_offset, Condition cond) { 1354 DCHECK((branch_offset & 3) == 0); 1355 int imm24 = branch_offset >> 2; 1356 CHECK(is_int24(imm24)); 1357 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); 1358 1359 if (cond == al) { 1360 // Dead code is a good location to emit the constant pool. 1361 CheckConstPool(false, false); 1362 } 1363 } 1364 1365 1366 void Assembler::bl(int branch_offset, Condition cond) { 1367 positions_recorder()->WriteRecordedPositions(); 1368 DCHECK((branch_offset & 3) == 0); 1369 int imm24 = branch_offset >> 2; 1370 CHECK(is_int24(imm24)); 1371 emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask)); 1372 } 1373 1374 1375 void Assembler::blx(int branch_offset) { // v5 and above 1376 positions_recorder()->WriteRecordedPositions(); 1377 DCHECK((branch_offset & 1) == 0); 1378 int h = ((branch_offset & 2) >> 1)*B24; 1379 int imm24 = branch_offset >> 2; 1380 CHECK(is_int24(imm24)); 1381 emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask)); 1382 } 1383 1384 1385 void Assembler::blx(Register target, Condition cond) { // v5 and above 1386 positions_recorder()->WriteRecordedPositions(); 1387 DCHECK(!target.is(pc)); 1388 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code()); 1389 } 1390 1391 1392 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t 1393 positions_recorder()->WriteRecordedPositions(); 1394 DCHECK(!target.is(pc)); // use of pc is actually allowed, but discouraged 1395 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code()); 1396 } 1397 1398 1399 void Assembler::b(Label* L, Condition cond) { 1400 CheckBuffer(); 1401 b(branch_offset(L), cond); 1402 } 1403 1404 1405 void Assembler::bl(Label* L, Condition cond) { 1406 CheckBuffer(); 1407 bl(branch_offset(L), cond); 1408 } 1409 1410 1411 void Assembler::blx(Label* L) { 1412 CheckBuffer(); 1413 blx(branch_offset(L)); 1414 } 1415 1416 1417 // Data-processing instructions. 1418 1419 void Assembler::and_(Register dst, Register src1, const Operand& src2, 1420 SBit s, Condition cond) { 1421 addrmod1(cond | AND | s, src1, dst, src2); 1422 } 1423 1424 1425 void Assembler::eor(Register dst, Register src1, const Operand& src2, 1426 SBit s, Condition cond) { 1427 addrmod1(cond | EOR | s, src1, dst, src2); 1428 } 1429 1430 1431 void Assembler::sub(Register dst, Register src1, const Operand& src2, 1432 SBit s, Condition cond) { 1433 addrmod1(cond | SUB | s, src1, dst, src2); 1434 } 1435 1436 1437 void Assembler::rsb(Register dst, Register src1, const Operand& src2, 1438 SBit s, Condition cond) { 1439 addrmod1(cond | RSB | s, src1, dst, src2); 1440 } 1441 1442 1443 void Assembler::add(Register dst, Register src1, const Operand& src2, 1444 SBit s, Condition cond) { 1445 addrmod1(cond | ADD | s, src1, dst, src2); 1446 } 1447 1448 1449 void Assembler::adc(Register dst, Register src1, const Operand& src2, 1450 SBit s, Condition cond) { 1451 addrmod1(cond | ADC | s, src1, dst, src2); 1452 } 1453 1454 1455 void Assembler::sbc(Register dst, Register src1, const Operand& src2, 1456 SBit s, Condition cond) { 1457 addrmod1(cond | SBC | s, src1, dst, src2); 1458 } 1459 1460 1461 void Assembler::rsc(Register dst, Register src1, const Operand& src2, 1462 SBit s, Condition cond) { 1463 addrmod1(cond | RSC | s, src1, dst, src2); 1464 } 1465 1466 1467 void Assembler::tst(Register src1, const Operand& src2, Condition cond) { 1468 addrmod1(cond | TST | S, src1, r0, src2); 1469 } 1470 1471 1472 void Assembler::teq(Register src1, const Operand& src2, Condition cond) { 1473 addrmod1(cond | TEQ | S, src1, r0, src2); 1474 } 1475 1476 1477 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) { 1478 addrmod1(cond | CMP | S, src1, r0, src2); 1479 } 1480 1481 1482 void Assembler::cmp_raw_immediate( 1483 Register src, int raw_immediate, Condition cond) { 1484 DCHECK(is_uint12(raw_immediate)); 1485 emit(cond | I | CMP | S | src.code() << 16 | raw_immediate); 1486 } 1487 1488 1489 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) { 1490 addrmod1(cond | CMN | S, src1, r0, src2); 1491 } 1492 1493 1494 void Assembler::orr(Register dst, Register src1, const Operand& src2, 1495 SBit s, Condition cond) { 1496 addrmod1(cond | ORR | s, src1, dst, src2); 1497 } 1498 1499 1500 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { 1501 if (dst.is(pc)) { 1502 positions_recorder()->WriteRecordedPositions(); 1503 } 1504 // Don't allow nop instructions in the form mov rn, rn to be generated using 1505 // the mov instruction. They must be generated using nop(int/NopMarkerTypes) 1506 // or MarkCode(int/NopMarkerTypes) pseudo instructions. 1507 DCHECK(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); 1508 addrmod1(cond | MOV | s, r0, dst, src); 1509 } 1510 1511 1512 void Assembler::mov_label_offset(Register dst, Label* label) { 1513 if (label->is_bound()) { 1514 mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag))); 1515 } else { 1516 // Emit the link to the label in the code stream followed by extra nop 1517 // instructions. 1518 // If the label is not linked, then start a new link chain by linking it to 1519 // itself, emitting pc_offset(). 1520 int link = label->is_linked() ? label->pos() : pc_offset(); 1521 label->link_to(pc_offset()); 1522 1523 // When the label is bound, these instructions will be patched with a 1524 // sequence of movw/movt or mov/orr/orr instructions. They will load the 1525 // destination register with the position of the label from the beginning 1526 // of the code. 1527 // 1528 // The link will be extracted from the first instruction and the destination 1529 // register from the second. 1530 // For ARMv7: 1531 // link 1532 // mov dst, dst 1533 // For ARMv6: 1534 // link 1535 // mov dst, dst 1536 // mov dst, dst 1537 // 1538 // When the label gets bound: target_at extracts the link and target_at_put 1539 // patches the instructions. 1540 CHECK(is_uint24(link)); 1541 BlockConstPoolScope block_const_pool(this); 1542 emit(link); 1543 nop(dst.code()); 1544 if (!CpuFeatures::IsSupported(ARMv7)) { 1545 nop(dst.code()); 1546 } 1547 } 1548 } 1549 1550 1551 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { 1552 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1553 emit(cond | 0x30*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); 1554 } 1555 1556 1557 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) { 1558 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1559 emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); 1560 } 1561 1562 1563 void Assembler::bic(Register dst, Register src1, const Operand& src2, 1564 SBit s, Condition cond) { 1565 addrmod1(cond | BIC | s, src1, dst, src2); 1566 } 1567 1568 1569 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { 1570 addrmod1(cond | MVN | s, r0, dst, src); 1571 } 1572 1573 1574 // Multiply instructions. 1575 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, 1576 SBit s, Condition cond) { 1577 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 1578 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | 1579 src2.code()*B8 | B7 | B4 | src1.code()); 1580 } 1581 1582 1583 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA, 1584 Condition cond) { 1585 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 1586 DCHECK(IsEnabled(MLS)); 1587 emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 | 1588 src2.code()*B8 | B7 | B4 | src1.code()); 1589 } 1590 1591 1592 void Assembler::sdiv(Register dst, Register src1, Register src2, 1593 Condition cond) { 1594 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1595 DCHECK(IsEnabled(SUDIV)); 1596 emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 | 1597 src2.code()*B8 | B4 | src1.code()); 1598 } 1599 1600 1601 void Assembler::udiv(Register dst, Register src1, Register src2, 1602 Condition cond) { 1603 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1604 DCHECK(IsEnabled(SUDIV)); 1605 emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xf * B12 | 1606 src2.code() * B8 | B4 | src1.code()); 1607 } 1608 1609 1610 void Assembler::mul(Register dst, Register src1, Register src2, SBit s, 1611 Condition cond) { 1612 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1613 // dst goes in bits 16-19 for this instruction! 1614 emit(cond | s | dst.code() * B16 | src2.code() * B8 | B7 | B4 | src1.code()); 1615 } 1616 1617 1618 void Assembler::smmla(Register dst, Register src1, Register src2, Register srcA, 1619 Condition cond) { 1620 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 1621 emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 1622 srcA.code() * B12 | src2.code() * B8 | B4 | src1.code()); 1623 } 1624 1625 1626 void Assembler::smmul(Register dst, Register src1, Register src2, 1627 Condition cond) { 1628 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1629 emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 0xf * B12 | 1630 src2.code() * B8 | B4 | src1.code()); 1631 } 1632 1633 1634 void Assembler::smlal(Register dstL, 1635 Register dstH, 1636 Register src1, 1637 Register src2, 1638 SBit s, 1639 Condition cond) { 1640 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1641 DCHECK(!dstL.is(dstH)); 1642 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1643 src2.code()*B8 | B7 | B4 | src1.code()); 1644 } 1645 1646 1647 void Assembler::smull(Register dstL, 1648 Register dstH, 1649 Register src1, 1650 Register src2, 1651 SBit s, 1652 Condition cond) { 1653 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1654 DCHECK(!dstL.is(dstH)); 1655 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | 1656 src2.code()*B8 | B7 | B4 | src1.code()); 1657 } 1658 1659 1660 void Assembler::umlal(Register dstL, 1661 Register dstH, 1662 Register src1, 1663 Register src2, 1664 SBit s, 1665 Condition cond) { 1666 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1667 DCHECK(!dstL.is(dstH)); 1668 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1669 src2.code()*B8 | B7 | B4 | src1.code()); 1670 } 1671 1672 1673 void Assembler::umull(Register dstL, 1674 Register dstH, 1675 Register src1, 1676 Register src2, 1677 SBit s, 1678 Condition cond) { 1679 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1680 DCHECK(!dstL.is(dstH)); 1681 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | 1682 src2.code()*B8 | B7 | B4 | src1.code()); 1683 } 1684 1685 1686 // Miscellaneous arithmetic instructions. 1687 void Assembler::clz(Register dst, Register src, Condition cond) { 1688 // v5 and above. 1689 DCHECK(!dst.is(pc) && !src.is(pc)); 1690 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | 1691 15*B8 | CLZ | src.code()); 1692 } 1693 1694 1695 // Saturating instructions. 1696 1697 // Unsigned saturate. 1698 void Assembler::usat(Register dst, 1699 int satpos, 1700 const Operand& src, 1701 Condition cond) { 1702 // v6 and above. 1703 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1704 DCHECK(!dst.is(pc) && !src.rm_.is(pc)); 1705 DCHECK((satpos >= 0) && (satpos <= 31)); 1706 DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL)); 1707 DCHECK(src.rs_.is(no_reg)); 1708 1709 int sh = 0; 1710 if (src.shift_op_ == ASR) { 1711 sh = 1; 1712 } 1713 1714 emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 | 1715 src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code()); 1716 } 1717 1718 1719 // Bitfield manipulation instructions. 1720 1721 // Unsigned bit field extract. 1722 // Extracts #width adjacent bits from position #lsb in a register, and 1723 // writes them to the low bits of a destination register. 1724 // ubfx dst, src, #lsb, #width 1725 void Assembler::ubfx(Register dst, 1726 Register src, 1727 int lsb, 1728 int width, 1729 Condition cond) { 1730 // v7 and above. 1731 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1732 DCHECK(!dst.is(pc) && !src.is(pc)); 1733 DCHECK((lsb >= 0) && (lsb <= 31)); 1734 DCHECK((width >= 1) && (width <= (32 - lsb))); 1735 emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 | 1736 lsb*B7 | B6 | B4 | src.code()); 1737 } 1738 1739 1740 // Signed bit field extract. 1741 // Extracts #width adjacent bits from position #lsb in a register, and 1742 // writes them to the low bits of a destination register. The extracted 1743 // value is sign extended to fill the destination register. 1744 // sbfx dst, src, #lsb, #width 1745 void Assembler::sbfx(Register dst, 1746 Register src, 1747 int lsb, 1748 int width, 1749 Condition cond) { 1750 // v7 and above. 1751 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1752 DCHECK(!dst.is(pc) && !src.is(pc)); 1753 DCHECK((lsb >= 0) && (lsb <= 31)); 1754 DCHECK((width >= 1) && (width <= (32 - lsb))); 1755 emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 | 1756 lsb*B7 | B6 | B4 | src.code()); 1757 } 1758 1759 1760 // Bit field clear. 1761 // Sets #width adjacent bits at position #lsb in the destination register 1762 // to zero, preserving the value of the other bits. 1763 // bfc dst, #lsb, #width 1764 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) { 1765 // v7 and above. 1766 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1767 DCHECK(!dst.is(pc)); 1768 DCHECK((lsb >= 0) && (lsb <= 31)); 1769 DCHECK((width >= 1) && (width <= (32 - lsb))); 1770 int msb = lsb + width - 1; 1771 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf); 1772 } 1773 1774 1775 // Bit field insert. 1776 // Inserts #width adjacent bits from the low bits of the source register 1777 // into position #lsb of the destination register. 1778 // bfi dst, src, #lsb, #width 1779 void Assembler::bfi(Register dst, 1780 Register src, 1781 int lsb, 1782 int width, 1783 Condition cond) { 1784 // v7 and above. 1785 DCHECK(CpuFeatures::IsSupported(ARMv7)); 1786 DCHECK(!dst.is(pc) && !src.is(pc)); 1787 DCHECK((lsb >= 0) && (lsb <= 31)); 1788 DCHECK((width >= 1) && (width <= (32 - lsb))); 1789 int msb = lsb + width - 1; 1790 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 1791 src.code()); 1792 } 1793 1794 1795 void Assembler::pkhbt(Register dst, 1796 Register src1, 1797 const Operand& src2, 1798 Condition cond ) { 1799 // Instruction details available in ARM DDI 0406C.b, A8.8.125. 1800 // cond(31-28) | 01101000(27-20) | Rn(19-16) | 1801 // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0) 1802 DCHECK(!dst.is(pc)); 1803 DCHECK(!src1.is(pc)); 1804 DCHECK(!src2.rm().is(pc)); 1805 DCHECK(!src2.rm().is(no_reg)); 1806 DCHECK(src2.rs().is(no_reg)); 1807 DCHECK((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31)); 1808 DCHECK(src2.shift_op() == LSL); 1809 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 | 1810 src2.shift_imm_*B7 | B4 | src2.rm().code()); 1811 } 1812 1813 1814 void Assembler::pkhtb(Register dst, 1815 Register src1, 1816 const Operand& src2, 1817 Condition cond) { 1818 // Instruction details available in ARM DDI 0406C.b, A8.8.125. 1819 // cond(31-28) | 01101000(27-20) | Rn(19-16) | 1820 // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0) 1821 DCHECK(!dst.is(pc)); 1822 DCHECK(!src1.is(pc)); 1823 DCHECK(!src2.rm().is(pc)); 1824 DCHECK(!src2.rm().is(no_reg)); 1825 DCHECK(src2.rs().is(no_reg)); 1826 DCHECK((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32)); 1827 DCHECK(src2.shift_op() == ASR); 1828 int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_; 1829 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 | 1830 asr*B7 | B6 | B4 | src2.rm().code()); 1831 } 1832 1833 1834 void Assembler::sxtb(Register dst, Register src, int rotate, Condition cond) { 1835 // Instruction details available in ARM DDI 0406C.b, A8.8.233. 1836 // cond(31-28) | 01101010(27-20) | 1111(19-16) | 1837 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1838 DCHECK(!dst.is(pc)); 1839 DCHECK(!src.is(pc)); 1840 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1841 emit(cond | 0x6A * B20 | 0xF * B16 | dst.code() * B12 | 1842 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code()); 1843 } 1844 1845 1846 void Assembler::sxtab(Register dst, Register src1, Register src2, int rotate, 1847 Condition cond) { 1848 // Instruction details available in ARM DDI 0406C.b, A8.8.233. 1849 // cond(31-28) | 01101010(27-20) | Rn(19-16) | 1850 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1851 DCHECK(!dst.is(pc)); 1852 DCHECK(!src1.is(pc)); 1853 DCHECK(!src2.is(pc)); 1854 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1855 emit(cond | 0x6A * B20 | src1.code() * B16 | dst.code() * B12 | 1856 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code()); 1857 } 1858 1859 1860 void Assembler::sxth(Register dst, Register src, int rotate, Condition cond) { 1861 // Instruction details available in ARM DDI 0406C.b, A8.8.235. 1862 // cond(31-28) | 01101011(27-20) | 1111(19-16) | 1863 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1864 DCHECK(!dst.is(pc)); 1865 DCHECK(!src.is(pc)); 1866 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1867 emit(cond | 0x6B * B20 | 0xF * B16 | dst.code() * B12 | 1868 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code()); 1869 } 1870 1871 1872 void Assembler::sxtah(Register dst, Register src1, Register src2, int rotate, 1873 Condition cond) { 1874 // Instruction details available in ARM DDI 0406C.b, A8.8.235. 1875 // cond(31-28) | 01101011(27-20) | Rn(19-16) | 1876 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1877 DCHECK(!dst.is(pc)); 1878 DCHECK(!src1.is(pc)); 1879 DCHECK(!src2.is(pc)); 1880 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1881 emit(cond | 0x6B * B20 | src1.code() * B16 | dst.code() * B12 | 1882 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code()); 1883 } 1884 1885 1886 void Assembler::uxtb(Register dst, Register src, int rotate, Condition cond) { 1887 // Instruction details available in ARM DDI 0406C.b, A8.8.274. 1888 // cond(31-28) | 01101110(27-20) | 1111(19-16) | 1889 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1890 DCHECK(!dst.is(pc)); 1891 DCHECK(!src.is(pc)); 1892 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1893 emit(cond | 0x6E * B20 | 0xF * B16 | dst.code() * B12 | 1894 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code()); 1895 } 1896 1897 1898 void Assembler::uxtab(Register dst, Register src1, Register src2, int rotate, 1899 Condition cond) { 1900 // Instruction details available in ARM DDI 0406C.b, A8.8.271. 1901 // cond(31-28) | 01101110(27-20) | Rn(19-16) | 1902 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1903 DCHECK(!dst.is(pc)); 1904 DCHECK(!src1.is(pc)); 1905 DCHECK(!src2.is(pc)); 1906 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1907 emit(cond | 0x6E * B20 | src1.code() * B16 | dst.code() * B12 | 1908 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code()); 1909 } 1910 1911 1912 void Assembler::uxtb16(Register dst, Register src, int rotate, Condition cond) { 1913 // Instruction details available in ARM DDI 0406C.b, A8.8.275. 1914 // cond(31-28) | 01101100(27-20) | 1111(19-16) | 1915 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1916 DCHECK(!dst.is(pc)); 1917 DCHECK(!src.is(pc)); 1918 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1919 emit(cond | 0x6C * B20 | 0xF * B16 | dst.code() * B12 | 1920 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code()); 1921 } 1922 1923 1924 void Assembler::uxth(Register dst, Register src, int rotate, Condition cond) { 1925 // Instruction details available in ARM DDI 0406C.b, A8.8.276. 1926 // cond(31-28) | 01101111(27-20) | 1111(19-16) | 1927 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1928 DCHECK(!dst.is(pc)); 1929 DCHECK(!src.is(pc)); 1930 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1931 emit(cond | 0x6F * B20 | 0xF * B16 | dst.code() * B12 | 1932 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code()); 1933 } 1934 1935 1936 void Assembler::uxtah(Register dst, Register src1, Register src2, int rotate, 1937 Condition cond) { 1938 // Instruction details available in ARM DDI 0406C.b, A8.8.273. 1939 // cond(31-28) | 01101111(27-20) | Rn(19-16) | 1940 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1941 DCHECK(!dst.is(pc)); 1942 DCHECK(!src1.is(pc)); 1943 DCHECK(!src2.is(pc)); 1944 DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24); 1945 emit(cond | 0x6F * B20 | src1.code() * B16 | dst.code() * B12 | 1946 ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code()); 1947 } 1948 1949 1950 // Status register access instructions. 1951 void Assembler::mrs(Register dst, SRegister s, Condition cond) { 1952 DCHECK(!dst.is(pc)); 1953 emit(cond | B24 | s | 15*B16 | dst.code()*B12); 1954 } 1955 1956 1957 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, 1958 Condition cond) { 1959 DCHECK(fields >= B16 && fields < B20); // at least one field set 1960 Instr instr; 1961 if (!src.rm_.is_valid()) { 1962 // Immediate. 1963 uint32_t rotate_imm; 1964 uint32_t immed_8; 1965 if (src.must_output_reloc_info(this) || 1966 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { 1967 // Immediate operand cannot be encoded, load it first to register ip. 1968 move_32_bit_immediate(ip, src); 1969 msr(fields, Operand(ip), cond); 1970 return; 1971 } 1972 instr = I | rotate_imm*B8 | immed_8; 1973 } else { 1974 DCHECK(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed 1975 instr = src.rm_.code(); 1976 } 1977 emit(cond | instr | B24 | B21 | fields | 15*B12); 1978 } 1979 1980 1981 // Load/Store instructions. 1982 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { 1983 if (dst.is(pc)) { 1984 positions_recorder()->WriteRecordedPositions(); 1985 } 1986 addrmod2(cond | B26 | L, dst, src); 1987 } 1988 1989 1990 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { 1991 addrmod2(cond | B26, src, dst); 1992 } 1993 1994 1995 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { 1996 addrmod2(cond | B26 | B | L, dst, src); 1997 } 1998 1999 2000 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { 2001 addrmod2(cond | B26 | B, src, dst); 2002 } 2003 2004 2005 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) { 2006 addrmod3(cond | L | B7 | H | B4, dst, src); 2007 } 2008 2009 2010 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) { 2011 addrmod3(cond | B7 | H | B4, src, dst); 2012 } 2013 2014 2015 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) { 2016 addrmod3(cond | L | B7 | S6 | B4, dst, src); 2017 } 2018 2019 2020 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { 2021 addrmod3(cond | L | B7 | S6 | H | B4, dst, src); 2022 } 2023 2024 2025 void Assembler::ldrd(Register dst1, Register dst2, 2026 const MemOperand& src, Condition cond) { 2027 DCHECK(IsEnabled(ARMv7)); 2028 DCHECK(src.rm().is(no_reg)); 2029 DCHECK(!dst1.is(lr)); // r14. 2030 DCHECK_EQ(0, dst1.code() % 2); 2031 DCHECK_EQ(dst1.code() + 1, dst2.code()); 2032 addrmod3(cond | B7 | B6 | B4, dst1, src); 2033 } 2034 2035 2036 void Assembler::strd(Register src1, Register src2, 2037 const MemOperand& dst, Condition cond) { 2038 DCHECK(dst.rm().is(no_reg)); 2039 DCHECK(!src1.is(lr)); // r14. 2040 DCHECK_EQ(0, src1.code() % 2); 2041 DCHECK_EQ(src1.code() + 1, src2.code()); 2042 DCHECK(IsEnabled(ARMv7)); 2043 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); 2044 } 2045 2046 2047 // Preload instructions. 2048 void Assembler::pld(const MemOperand& address) { 2049 // Instruction details available in ARM DDI 0406C.b, A8.8.128. 2050 // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) | 2051 // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) | 2052 DCHECK(address.rm().is(no_reg)); 2053 DCHECK(address.am() == Offset); 2054 int U = B23; 2055 int offset = address.offset(); 2056 if (offset < 0) { 2057 offset = -offset; 2058 U = 0; 2059 } 2060 DCHECK(offset < 4096); 2061 emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 | 2062 0xf*B12 | offset); 2063 } 2064 2065 2066 // Load/Store multiple instructions. 2067 void Assembler::ldm(BlockAddrMode am, 2068 Register base, 2069 RegList dst, 2070 Condition cond) { 2071 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. 2072 DCHECK(base.is(sp) || (dst & sp.bit()) == 0); 2073 2074 addrmod4(cond | B27 | am | L, base, dst); 2075 2076 // Emit the constant pool after a function return implemented by ldm ..{..pc}. 2077 if (cond == al && (dst & pc.bit()) != 0) { 2078 // There is a slight chance that the ldm instruction was actually a call, 2079 // in which case it would be wrong to return into the constant pool; we 2080 // recognize this case by checking if the emission of the pool was blocked 2081 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is 2082 // the case, we emit a jump over the pool. 2083 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); 2084 } 2085 } 2086 2087 2088 void Assembler::stm(BlockAddrMode am, 2089 Register base, 2090 RegList src, 2091 Condition cond) { 2092 addrmod4(cond | B27 | am, base, src); 2093 } 2094 2095 2096 // Exception-generating instructions and debugging support. 2097 // Stops with a non-negative code less than kNumOfWatchedStops support 2098 // enabling/disabling and a counter feature. See simulator-arm.h . 2099 void Assembler::stop(const char* msg, Condition cond, int32_t code) { 2100 #ifndef __arm__ 2101 DCHECK(code >= kDefaultStopCode); 2102 { 2103 // The Simulator will handle the stop instruction and get the message 2104 // address. It expects to find the address just after the svc instruction. 2105 BlockConstPoolScope block_const_pool(this); 2106 if (code >= 0) { 2107 svc(kStopCode + code, cond); 2108 } else { 2109 svc(kStopCode + kMaxStopCode, cond); 2110 } 2111 emit(reinterpret_cast<Instr>(msg)); 2112 } 2113 #else // def __arm__ 2114 if (cond != al) { 2115 Label skip; 2116 b(&skip, NegateCondition(cond)); 2117 bkpt(0); 2118 bind(&skip); 2119 } else { 2120 bkpt(0); 2121 } 2122 #endif // def __arm__ 2123 } 2124 2125 2126 void Assembler::bkpt(uint32_t imm16) { // v5 and above 2127 DCHECK(is_uint16(imm16)); 2128 emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf)); 2129 } 2130 2131 2132 void Assembler::svc(uint32_t imm24, Condition cond) { 2133 DCHECK(is_uint24(imm24)); 2134 emit(cond | 15*B24 | imm24); 2135 } 2136 2137 2138 // Coprocessor instructions. 2139 void Assembler::cdp(Coprocessor coproc, 2140 int opcode_1, 2141 CRegister crd, 2142 CRegister crn, 2143 CRegister crm, 2144 int opcode_2, 2145 Condition cond) { 2146 DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2)); 2147 emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 | 2148 crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code()); 2149 } 2150 2151 2152 void Assembler::cdp2(Coprocessor coproc, 2153 int opcode_1, 2154 CRegister crd, 2155 CRegister crn, 2156 CRegister crm, 2157 int opcode_2) { // v5 and above 2158 cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition); 2159 } 2160 2161 2162 void Assembler::mcr(Coprocessor coproc, 2163 int opcode_1, 2164 Register rd, 2165 CRegister crn, 2166 CRegister crm, 2167 int opcode_2, 2168 Condition cond) { 2169 DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2)); 2170 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 | 2171 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 2172 } 2173 2174 2175 void Assembler::mcr2(Coprocessor coproc, 2176 int opcode_1, 2177 Register rd, 2178 CRegister crn, 2179 CRegister crm, 2180 int opcode_2) { // v5 and above 2181 mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition); 2182 } 2183 2184 2185 void Assembler::mrc(Coprocessor coproc, 2186 int opcode_1, 2187 Register rd, 2188 CRegister crn, 2189 CRegister crm, 2190 int opcode_2, 2191 Condition cond) { 2192 DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2)); 2193 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 | 2194 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 2195 } 2196 2197 2198 void Assembler::mrc2(Coprocessor coproc, 2199 int opcode_1, 2200 Register rd, 2201 CRegister crn, 2202 CRegister crm, 2203 int opcode_2) { // v5 and above 2204 mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition); 2205 } 2206 2207 2208 void Assembler::ldc(Coprocessor coproc, 2209 CRegister crd, 2210 const MemOperand& src, 2211 LFlag l, 2212 Condition cond) { 2213 addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src); 2214 } 2215 2216 2217 void Assembler::ldc(Coprocessor coproc, 2218 CRegister crd, 2219 Register rn, 2220 int option, 2221 LFlag l, 2222 Condition cond) { 2223 // Unindexed addressing. 2224 DCHECK(is_uint8(option)); 2225 emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 | 2226 coproc*B8 | (option & 255)); 2227 } 2228 2229 2230 void Assembler::ldc2(Coprocessor coproc, 2231 CRegister crd, 2232 const MemOperand& src, 2233 LFlag l) { // v5 and above 2234 ldc(coproc, crd, src, l, kSpecialCondition); 2235 } 2236 2237 2238 void Assembler::ldc2(Coprocessor coproc, 2239 CRegister crd, 2240 Register rn, 2241 int option, 2242 LFlag l) { // v5 and above 2243 ldc(coproc, crd, rn, option, l, kSpecialCondition); 2244 } 2245 2246 2247 // Support for VFP. 2248 2249 void Assembler::vldr(const DwVfpRegister dst, 2250 const Register base, 2251 int offset, 2252 const Condition cond) { 2253 // Ddst = MEM(Rbase + offset). 2254 // Instruction details available in ARM DDI 0406C.b, A8-924. 2255 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) | 2256 // Vd(15-12) | 1011(11-8) | offset 2257 int u = 1; 2258 if (offset < 0) { 2259 CHECK(offset != kMinInt); 2260 offset = -offset; 2261 u = 0; 2262 } 2263 int vd, d; 2264 dst.split_code(&vd, &d); 2265 2266 DCHECK(offset >= 0); 2267 if ((offset % 4) == 0 && (offset / 4) < 256) { 2268 emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 | 2269 0xB*B8 | ((offset / 4) & 255)); 2270 } else { 2271 // Larger offsets must be handled by computing the correct address 2272 // in the ip register. 2273 DCHECK(!base.is(ip)); 2274 if (u == 1) { 2275 add(ip, base, Operand(offset)); 2276 } else { 2277 sub(ip, base, Operand(offset)); 2278 } 2279 emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8); 2280 } 2281 } 2282 2283 2284 void Assembler::vldr(const DwVfpRegister dst, 2285 const MemOperand& operand, 2286 const Condition cond) { 2287 DCHECK(operand.am_ == Offset); 2288 if (operand.rm().is_valid()) { 2289 add(ip, operand.rn(), 2290 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2291 vldr(dst, ip, 0, cond); 2292 } else { 2293 vldr(dst, operand.rn(), operand.offset(), cond); 2294 } 2295 } 2296 2297 2298 void Assembler::vldr(const SwVfpRegister dst, 2299 const Register base, 2300 int offset, 2301 const Condition cond) { 2302 // Sdst = MEM(Rbase + offset). 2303 // Instruction details available in ARM DDI 0406A, A8-628. 2304 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | 2305 // Vdst(15-12) | 1010(11-8) | offset 2306 int u = 1; 2307 if (offset < 0) { 2308 offset = -offset; 2309 u = 0; 2310 } 2311 int sd, d; 2312 dst.split_code(&sd, &d); 2313 DCHECK(offset >= 0); 2314 2315 if ((offset % 4) == 0 && (offset / 4) < 256) { 2316 emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 | 2317 0xA*B8 | ((offset / 4) & 255)); 2318 } else { 2319 // Larger offsets must be handled by computing the correct address 2320 // in the ip register. 2321 DCHECK(!base.is(ip)); 2322 if (u == 1) { 2323 add(ip, base, Operand(offset)); 2324 } else { 2325 sub(ip, base, Operand(offset)); 2326 } 2327 emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); 2328 } 2329 } 2330 2331 2332 void Assembler::vldr(const SwVfpRegister dst, 2333 const MemOperand& operand, 2334 const Condition cond) { 2335 DCHECK(operand.am_ == Offset); 2336 if (operand.rm().is_valid()) { 2337 add(ip, operand.rn(), 2338 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2339 vldr(dst, ip, 0, cond); 2340 } else { 2341 vldr(dst, operand.rn(), operand.offset(), cond); 2342 } 2343 } 2344 2345 2346 void Assembler::vstr(const DwVfpRegister src, 2347 const Register base, 2348 int offset, 2349 const Condition cond) { 2350 // MEM(Rbase + offset) = Dsrc. 2351 // Instruction details available in ARM DDI 0406C.b, A8-1082. 2352 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) | 2353 // Vd(15-12) | 1011(11-8) | (offset/4) 2354 int u = 1; 2355 if (offset < 0) { 2356 CHECK(offset != kMinInt); 2357 offset = -offset; 2358 u = 0; 2359 } 2360 DCHECK(offset >= 0); 2361 int vd, d; 2362 src.split_code(&vd, &d); 2363 2364 if ((offset % 4) == 0 && (offset / 4) < 256) { 2365 emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 | 2366 ((offset / 4) & 255)); 2367 } else { 2368 // Larger offsets must be handled by computing the correct address 2369 // in the ip register. 2370 DCHECK(!base.is(ip)); 2371 if (u == 1) { 2372 add(ip, base, Operand(offset)); 2373 } else { 2374 sub(ip, base, Operand(offset)); 2375 } 2376 emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8); 2377 } 2378 } 2379 2380 2381 void Assembler::vstr(const DwVfpRegister src, 2382 const MemOperand& operand, 2383 const Condition cond) { 2384 DCHECK(operand.am_ == Offset); 2385 if (operand.rm().is_valid()) { 2386 add(ip, operand.rn(), 2387 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2388 vstr(src, ip, 0, cond); 2389 } else { 2390 vstr(src, operand.rn(), operand.offset(), cond); 2391 } 2392 } 2393 2394 2395 void Assembler::vstr(const SwVfpRegister src, 2396 const Register base, 2397 int offset, 2398 const Condition cond) { 2399 // MEM(Rbase + offset) = SSrc. 2400 // Instruction details available in ARM DDI 0406A, A8-786. 2401 // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) | 2402 // Vdst(15-12) | 1010(11-8) | (offset/4) 2403 int u = 1; 2404 if (offset < 0) { 2405 CHECK(offset != kMinInt); 2406 offset = -offset; 2407 u = 0; 2408 } 2409 int sd, d; 2410 src.split_code(&sd, &d); 2411 DCHECK(offset >= 0); 2412 if ((offset % 4) == 0 && (offset / 4) < 256) { 2413 emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | 2414 0xA*B8 | ((offset / 4) & 255)); 2415 } else { 2416 // Larger offsets must be handled by computing the correct address 2417 // in the ip register. 2418 DCHECK(!base.is(ip)); 2419 if (u == 1) { 2420 add(ip, base, Operand(offset)); 2421 } else { 2422 sub(ip, base, Operand(offset)); 2423 } 2424 emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); 2425 } 2426 } 2427 2428 2429 void Assembler::vstr(const SwVfpRegister src, 2430 const MemOperand& operand, 2431 const Condition cond) { 2432 DCHECK(operand.am_ == Offset); 2433 if (operand.rm().is_valid()) { 2434 add(ip, operand.rn(), 2435 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2436 vstr(src, ip, 0, cond); 2437 } else { 2438 vstr(src, operand.rn(), operand.offset(), cond); 2439 } 2440 } 2441 2442 2443 void Assembler::vldm(BlockAddrMode am, 2444 Register base, 2445 DwVfpRegister first, 2446 DwVfpRegister last, 2447 Condition cond) { 2448 // Instruction details available in ARM DDI 0406C.b, A8-922. 2449 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | 2450 // first(15-12) | 1011(11-8) | (count * 2) 2451 DCHECK_LE(first.code(), last.code()); 2452 DCHECK(am == ia || am == ia_w || am == db_w); 2453 DCHECK(!base.is(pc)); 2454 2455 int sd, d; 2456 first.split_code(&sd, &d); 2457 int count = last.code() - first.code() + 1; 2458 DCHECK(count <= 16); 2459 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | 2460 0xB*B8 | count*2); 2461 } 2462 2463 2464 void Assembler::vstm(BlockAddrMode am, 2465 Register base, 2466 DwVfpRegister first, 2467 DwVfpRegister last, 2468 Condition cond) { 2469 // Instruction details available in ARM DDI 0406C.b, A8-1080. 2470 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | 2471 // first(15-12) | 1011(11-8) | (count * 2) 2472 DCHECK_LE(first.code(), last.code()); 2473 DCHECK(am == ia || am == ia_w || am == db_w); 2474 DCHECK(!base.is(pc)); 2475 2476 int sd, d; 2477 first.split_code(&sd, &d); 2478 int count = last.code() - first.code() + 1; 2479 DCHECK(count <= 16); 2480 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 | 2481 0xB*B8 | count*2); 2482 } 2483 2484 void Assembler::vldm(BlockAddrMode am, 2485 Register base, 2486 SwVfpRegister first, 2487 SwVfpRegister last, 2488 Condition cond) { 2489 // Instruction details available in ARM DDI 0406A, A8-626. 2490 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | 2491 // first(15-12) | 1010(11-8) | (count/2) 2492 DCHECK_LE(first.code(), last.code()); 2493 DCHECK(am == ia || am == ia_w || am == db_w); 2494 DCHECK(!base.is(pc)); 2495 2496 int sd, d; 2497 first.split_code(&sd, &d); 2498 int count = last.code() - first.code() + 1; 2499 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | 2500 0xA*B8 | count); 2501 } 2502 2503 2504 void Assembler::vstm(BlockAddrMode am, 2505 Register base, 2506 SwVfpRegister first, 2507 SwVfpRegister last, 2508 Condition cond) { 2509 // Instruction details available in ARM DDI 0406A, A8-784. 2510 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | 2511 // first(15-12) | 1011(11-8) | (count/2) 2512 DCHECK_LE(first.code(), last.code()); 2513 DCHECK(am == ia || am == ia_w || am == db_w); 2514 DCHECK(!base.is(pc)); 2515 2516 int sd, d; 2517 first.split_code(&sd, &d); 2518 int count = last.code() - first.code() + 1; 2519 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 | 2520 0xA*B8 | count); 2521 } 2522 2523 2524 void Assembler::vmov(const SwVfpRegister dst, float imm) { 2525 mov(ip, Operand(bit_cast<int32_t>(imm))); 2526 vmov(dst, ip); 2527 } 2528 2529 2530 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) { 2531 uint64_t i; 2532 memcpy(&i, &d, 8); 2533 2534 *lo = i & 0xffffffff; 2535 *hi = i >> 32; 2536 } 2537 2538 2539 // Only works for little endian floating point formats. 2540 // We don't support VFP on the mixed endian floating point platform. 2541 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) { 2542 DCHECK(CpuFeatures::IsSupported(VFP3)); 2543 2544 // VMOV can accept an immediate of the form: 2545 // 2546 // +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7 2547 // 2548 // The immediate is encoded using an 8-bit quantity, comprised of two 2549 // 4-bit fields. For an 8-bit immediate of the form: 2550 // 2551 // [abcdefgh] 2552 // 2553 // where a is the MSB and h is the LSB, an immediate 64-bit double can be 2554 // created of the form: 2555 // 2556 // [aBbbbbbb,bbcdefgh,00000000,00000000, 2557 // 00000000,00000000,00000000,00000000] 2558 // 2559 // where B = ~b. 2560 // 2561 2562 uint32_t lo, hi; 2563 DoubleAsTwoUInt32(d, &lo, &hi); 2564 2565 // The most obvious constraint is the long block of zeroes. 2566 if ((lo != 0) || ((hi & 0xffff) != 0)) { 2567 return false; 2568 } 2569 2570 // Bits 62:55 must be all clear or all set. 2571 if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) { 2572 return false; 2573 } 2574 2575 // Bit 63 must be NOT bit 62. 2576 if (((hi ^ (hi << 1)) & (0x40000000)) == 0) { 2577 return false; 2578 } 2579 2580 // Create the encoded immediate in the form: 2581 // [00000000,0000abcd,00000000,0000efgh] 2582 *encoding = (hi >> 16) & 0xf; // Low nybble. 2583 *encoding |= (hi >> 4) & 0x70000; // Low three bits of the high nybble. 2584 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. 2585 2586 return true; 2587 } 2588 2589 2590 void Assembler::vmov(const DwVfpRegister dst, 2591 double imm, 2592 const Register scratch) { 2593 uint32_t enc; 2594 // If the embedded constant pool is disabled, we can use the normal, inline 2595 // constant pool. If the embedded constant pool is enabled (via 2596 // FLAG_enable_embedded_constant_pool), we can only use it where the pool 2597 // pointer (pp) is valid. 2598 bool can_use_pool = 2599 !FLAG_enable_embedded_constant_pool || is_constant_pool_available(); 2600 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { 2601 // The double can be encoded in the instruction. 2602 // 2603 // Dd = immediate 2604 // Instruction details available in ARM DDI 0406C.b, A8-936. 2605 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | 2606 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) 2607 int vd, d; 2608 dst.split_code(&vd, &d); 2609 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); 2610 } else if (FLAG_enable_vldr_imm && can_use_pool) { 2611 // TODO(jfb) Temporarily turned off until we have constant blinding or 2612 // some equivalent mitigation: an attacker can otherwise control 2613 // generated data which also happens to be executable, a Very Bad 2614 // Thing indeed. 2615 // Blinding gets tricky because we don't have xor, we probably 2616 // need to add/subtract without losing precision, which requires a 2617 // cookie value that Lithium is probably better positioned to 2618 // choose. 2619 // We could also add a few peepholes here like detecting 0.0 and 2620 // -0.0 and doing a vmov from the sequestered d14, forcing denorms 2621 // to zero (we set flush-to-zero), and normalizing NaN values. 2622 // We could also detect redundant values. 2623 // The code could also randomize the order of values, though 2624 // that's tricky because vldr has a limited reach. Furthermore 2625 // it breaks load locality. 2626 ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm); 2627 if (access == ConstantPoolEntry::OVERFLOWED) { 2628 DCHECK(FLAG_enable_embedded_constant_pool); 2629 // Emit instructions to load constant pool offset. 2630 movw(ip, 0); 2631 movt(ip, 0); 2632 // Load from constant pool at offset. 2633 vldr(dst, MemOperand(pp, ip)); 2634 } else { 2635 DCHECK(access == ConstantPoolEntry::REGULAR); 2636 vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0)); 2637 } 2638 } else { 2639 // Synthesise the double from ARM immediates. 2640 uint32_t lo, hi; 2641 DoubleAsTwoUInt32(imm, &lo, &hi); 2642 2643 if (lo == hi) { 2644 // Move the low and high parts of the double to a D register in one 2645 // instruction. 2646 mov(ip, Operand(lo)); 2647 vmov(dst, ip, ip); 2648 } else if (scratch.is(no_reg)) { 2649 mov(ip, Operand(lo)); 2650 vmov(dst, VmovIndexLo, ip); 2651 if (((lo & 0xffff) == (hi & 0xffff)) && 2652 CpuFeatures::IsSupported(ARMv7)) { 2653 movt(ip, hi >> 16); 2654 } else { 2655 mov(ip, Operand(hi)); 2656 } 2657 vmov(dst, VmovIndexHi, ip); 2658 } else { 2659 // Move the low and high parts of the double to a D register in one 2660 // instruction. 2661 mov(ip, Operand(lo)); 2662 mov(scratch, Operand(hi)); 2663 vmov(dst, ip, scratch); 2664 } 2665 } 2666 } 2667 2668 2669 void Assembler::vmov(const SwVfpRegister dst, 2670 const SwVfpRegister src, 2671 const Condition cond) { 2672 // Sd = Sm 2673 // Instruction details available in ARM DDI 0406B, A8-642. 2674 int sd, d, sm, m; 2675 dst.split_code(&sd, &d); 2676 src.split_code(&sm, &m); 2677 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); 2678 } 2679 2680 2681 void Assembler::vmov(const DwVfpRegister dst, 2682 const DwVfpRegister src, 2683 const Condition cond) { 2684 // Dd = Dm 2685 // Instruction details available in ARM DDI 0406C.b, A8-938. 2686 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | 2687 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2688 int vd, d; 2689 dst.split_code(&vd, &d); 2690 int vm, m; 2691 src.split_code(&vm, &m); 2692 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 | 2693 vm); 2694 } 2695 2696 2697 void Assembler::vmov(const DwVfpRegister dst, 2698 const VmovIndex index, 2699 const Register src, 2700 const Condition cond) { 2701 // Dd[index] = Rt 2702 // Instruction details available in ARM DDI 0406C.b, A8-940. 2703 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | 2704 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) 2705 DCHECK(index.index == 0 || index.index == 1); 2706 int vd, d; 2707 dst.split_code(&vd, &d); 2708 emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | 2709 d*B7 | B4); 2710 } 2711 2712 2713 void Assembler::vmov(const Register dst, 2714 const VmovIndex index, 2715 const DwVfpRegister src, 2716 const Condition cond) { 2717 // Dd[index] = Rt 2718 // Instruction details available in ARM DDI 0406C.b, A8.8.342. 2719 // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) | 2720 // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0) 2721 DCHECK(index.index == 0 || index.index == 1); 2722 int vn, n; 2723 src.split_code(&vn, &n); 2724 emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 | 2725 0xB*B8 | n*B7 | B4); 2726 } 2727 2728 2729 void Assembler::vmov(const DwVfpRegister dst, 2730 const Register src1, 2731 const Register src2, 2732 const Condition cond) { 2733 // Dm = <Rt,Rt2>. 2734 // Instruction details available in ARM DDI 0406C.b, A8-948. 2735 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | 2736 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 2737 DCHECK(!src1.is(pc) && !src2.is(pc)); 2738 int vm, m; 2739 dst.split_code(&vm, &m); 2740 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | 2741 src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); 2742 } 2743 2744 2745 void Assembler::vmov(const Register dst1, 2746 const Register dst2, 2747 const DwVfpRegister src, 2748 const Condition cond) { 2749 // <Rt,Rt2> = Dm. 2750 // Instruction details available in ARM DDI 0406C.b, A8-948. 2751 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | 2752 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 2753 DCHECK(!dst1.is(pc) && !dst2.is(pc)); 2754 int vm, m; 2755 src.split_code(&vm, &m); 2756 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | 2757 dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); 2758 } 2759 2760 2761 void Assembler::vmov(const SwVfpRegister dst, 2762 const Register src, 2763 const Condition cond) { 2764 // Sn = Rt. 2765 // Instruction details available in ARM DDI 0406A, A8-642. 2766 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | 2767 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 2768 DCHECK(!src.is(pc)); 2769 int sn, n; 2770 dst.split_code(&sn, &n); 2771 emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4); 2772 } 2773 2774 2775 void Assembler::vmov(const Register dst, 2776 const SwVfpRegister src, 2777 const Condition cond) { 2778 // Rt = Sn. 2779 // Instruction details available in ARM DDI 0406A, A8-642. 2780 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | 2781 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 2782 DCHECK(!dst.is(pc)); 2783 int sn, n; 2784 src.split_code(&sn, &n); 2785 emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4); 2786 } 2787 2788 2789 // Type of data to read from or write to VFP register. 2790 // Used as specifier in generic vcvt instruction. 2791 enum VFPType { S32, U32, F32, F64 }; 2792 2793 2794 static bool IsSignedVFPType(VFPType type) { 2795 switch (type) { 2796 case S32: 2797 return true; 2798 case U32: 2799 return false; 2800 default: 2801 UNREACHABLE(); 2802 return false; 2803 } 2804 } 2805 2806 2807 static bool IsIntegerVFPType(VFPType type) { 2808 switch (type) { 2809 case S32: 2810 case U32: 2811 return true; 2812 case F32: 2813 case F64: 2814 return false; 2815 default: 2816 UNREACHABLE(); 2817 return false; 2818 } 2819 } 2820 2821 2822 static bool IsDoubleVFPType(VFPType type) { 2823 switch (type) { 2824 case F32: 2825 return false; 2826 case F64: 2827 return true; 2828 default: 2829 UNREACHABLE(); 2830 return false; 2831 } 2832 } 2833 2834 2835 // Split five bit reg_code based on size of reg_type. 2836 // 32-bit register codes are Vm:M 2837 // 64-bit register codes are M:Vm 2838 // where Vm is four bits, and M is a single bit. 2839 static void SplitRegCode(VFPType reg_type, 2840 int reg_code, 2841 int* vm, 2842 int* m) { 2843 DCHECK((reg_code >= 0) && (reg_code <= 31)); 2844 if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) { 2845 // 32 bit type. 2846 *m = reg_code & 0x1; 2847 *vm = reg_code >> 1; 2848 } else { 2849 // 64 bit type. 2850 *m = (reg_code & 0x10) >> 4; 2851 *vm = reg_code & 0x0F; 2852 } 2853 } 2854 2855 2856 // Encode vcvt.src_type.dst_type instruction. 2857 static Instr EncodeVCVT(const VFPType dst_type, 2858 const int dst_code, 2859 const VFPType src_type, 2860 const int src_code, 2861 VFPConversionMode mode, 2862 const Condition cond) { 2863 DCHECK(src_type != dst_type); 2864 int D, Vd, M, Vm; 2865 SplitRegCode(src_type, src_code, &Vm, &M); 2866 SplitRegCode(dst_type, dst_code, &Vd, &D); 2867 2868 if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) { 2869 // Conversion between IEEE floating point and 32-bit integer. 2870 // Instruction details available in ARM DDI 0406B, A8.6.295. 2871 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) | 2872 // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2873 DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type)); 2874 2875 int sz, opc2, op; 2876 2877 if (IsIntegerVFPType(dst_type)) { 2878 opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4; 2879 sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0; 2880 op = mode; 2881 } else { 2882 DCHECK(IsIntegerVFPType(src_type)); 2883 opc2 = 0x0; 2884 sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0; 2885 op = IsSignedVFPType(src_type) ? 0x1 : 0x0; 2886 } 2887 2888 return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 | 2889 Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm); 2890 } else { 2891 // Conversion between IEEE double and single precision. 2892 // Instruction details available in ARM DDI 0406B, A8.6.298. 2893 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) | 2894 // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2895 int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0; 2896 return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 | 2897 Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm); 2898 } 2899 } 2900 2901 2902 void Assembler::vcvt_f64_s32(const DwVfpRegister dst, 2903 const SwVfpRegister src, 2904 VFPConversionMode mode, 2905 const Condition cond) { 2906 emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond)); 2907 } 2908 2909 2910 void Assembler::vcvt_f32_s32(const SwVfpRegister dst, 2911 const SwVfpRegister src, 2912 VFPConversionMode mode, 2913 const Condition cond) { 2914 emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond)); 2915 } 2916 2917 2918 void Assembler::vcvt_f64_u32(const DwVfpRegister dst, 2919 const SwVfpRegister src, 2920 VFPConversionMode mode, 2921 const Condition cond) { 2922 emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond)); 2923 } 2924 2925 2926 void Assembler::vcvt_s32_f64(const SwVfpRegister dst, 2927 const DwVfpRegister src, 2928 VFPConversionMode mode, 2929 const Condition cond) { 2930 emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond)); 2931 } 2932 2933 2934 void Assembler::vcvt_u32_f64(const SwVfpRegister dst, 2935 const DwVfpRegister src, 2936 VFPConversionMode mode, 2937 const Condition cond) { 2938 emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond)); 2939 } 2940 2941 2942 void Assembler::vcvt_f64_f32(const DwVfpRegister dst, 2943 const SwVfpRegister src, 2944 VFPConversionMode mode, 2945 const Condition cond) { 2946 emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond)); 2947 } 2948 2949 2950 void Assembler::vcvt_f32_f64(const SwVfpRegister dst, 2951 const DwVfpRegister src, 2952 VFPConversionMode mode, 2953 const Condition cond) { 2954 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); 2955 } 2956 2957 2958 void Assembler::vcvt_f64_s32(const DwVfpRegister dst, 2959 int fraction_bits, 2960 const Condition cond) { 2961 // Instruction details available in ARM DDI 0406C.b, A8-874. 2962 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) | 2963 // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0) 2964 DCHECK(fraction_bits > 0 && fraction_bits <= 32); 2965 DCHECK(CpuFeatures::IsSupported(VFP3)); 2966 int vd, d; 2967 dst.split_code(&vd, &d); 2968 int imm5 = 32 - fraction_bits; 2969 int i = imm5 & 1; 2970 int imm4 = (imm5 >> 1) & 0xf; 2971 emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 | 2972 vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4); 2973 } 2974 2975 2976 void Assembler::vneg(const DwVfpRegister dst, 2977 const DwVfpRegister src, 2978 const Condition cond) { 2979 // Instruction details available in ARM DDI 0406C.b, A8-968. 2980 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | 2981 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2982 int vd, d; 2983 dst.split_code(&vd, &d); 2984 int vm, m; 2985 src.split_code(&vm, &m); 2986 2987 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | 2988 m*B5 | vm); 2989 } 2990 2991 2992 void Assembler::vneg(const SwVfpRegister dst, const SwVfpRegister src, 2993 const Condition cond) { 2994 // Instruction details available in ARM DDI 0406C.b, A8-968. 2995 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | 2996 // 101(11-9) | sz=0(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2997 int vd, d; 2998 dst.split_code(&vd, &d); 2999 int vm, m; 3000 src.split_code(&vm, &m); 3001 3002 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 | 3003 B6 | m * B5 | vm); 3004 } 3005 3006 3007 void Assembler::vabs(const DwVfpRegister dst, 3008 const DwVfpRegister src, 3009 const Condition cond) { 3010 // Instruction details available in ARM DDI 0406C.b, A8-524. 3011 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | 3012 // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3013 int vd, d; 3014 dst.split_code(&vd, &d); 3015 int vm, m; 3016 src.split_code(&vm, &m); 3017 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 | 3018 m*B5 | vm); 3019 } 3020 3021 3022 void Assembler::vabs(const SwVfpRegister dst, const SwVfpRegister src, 3023 const Condition cond) { 3024 // Instruction details available in ARM DDI 0406C.b, A8-524. 3025 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | 3026 // 101(11-9) | sz=0(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3027 int vd, d; 3028 dst.split_code(&vd, &d); 3029 int vm, m; 3030 src.split_code(&vm, &m); 3031 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B7 | B6 | 3032 m * B5 | vm); 3033 } 3034 3035 3036 void Assembler::vadd(const DwVfpRegister dst, 3037 const DwVfpRegister src1, 3038 const DwVfpRegister src2, 3039 const Condition cond) { 3040 // Dd = vadd(Dn, Dm) double precision floating point addition. 3041 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 3042 // Instruction details available in ARM DDI 0406C.b, A8-830. 3043 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | 3044 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) 3045 int vd, d; 3046 dst.split_code(&vd, &d); 3047 int vn, n; 3048 src1.split_code(&vn, &n); 3049 int vm, m; 3050 src2.split_code(&vm, &m); 3051 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | 3052 n*B7 | m*B5 | vm); 3053 } 3054 3055 3056 void Assembler::vadd(const SwVfpRegister dst, const SwVfpRegister src1, 3057 const SwVfpRegister src2, const Condition cond) { 3058 // Sd = vadd(Sn, Sm) single precision floating point addition. 3059 // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm. 3060 // Instruction details available in ARM DDI 0406C.b, A8-830. 3061 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | 3062 // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) 3063 int vd, d; 3064 dst.split_code(&vd, &d); 3065 int vn, n; 3066 src1.split_code(&vn, &n); 3067 int vm, m; 3068 src2.split_code(&vm, &m); 3069 emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | 3070 0x5 * B9 | n * B7 | m * B5 | vm); 3071 } 3072 3073 3074 void Assembler::vsub(const DwVfpRegister dst, 3075 const DwVfpRegister src1, 3076 const DwVfpRegister src2, 3077 const Condition cond) { 3078 // Dd = vsub(Dn, Dm) double precision floating point subtraction. 3079 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 3080 // Instruction details available in ARM DDI 0406C.b, A8-1086. 3081 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | 3082 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3083 int vd, d; 3084 dst.split_code(&vd, &d); 3085 int vn, n; 3086 src1.split_code(&vn, &n); 3087 int vm, m; 3088 src2.split_code(&vm, &m); 3089 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | 3090 n*B7 | B6 | m*B5 | vm); 3091 } 3092 3093 3094 void Assembler::vsub(const SwVfpRegister dst, const SwVfpRegister src1, 3095 const SwVfpRegister src2, const Condition cond) { 3096 // Sd = vsub(Sn, Sm) single precision floating point subtraction. 3097 // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm. 3098 // Instruction details available in ARM DDI 0406C.b, A8-1086. 3099 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | 3100 // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3101 int vd, d; 3102 dst.split_code(&vd, &d); 3103 int vn, n; 3104 src1.split_code(&vn, &n); 3105 int vm, m; 3106 src2.split_code(&vm, &m); 3107 emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | 3108 0x5 * B9 | n * B7 | B6 | m * B5 | vm); 3109 } 3110 3111 3112 void Assembler::vmul(const DwVfpRegister dst, 3113 const DwVfpRegister src1, 3114 const DwVfpRegister src2, 3115 const Condition cond) { 3116 // Dd = vmul(Dn, Dm) double precision floating point multiplication. 3117 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 3118 // Instruction details available in ARM DDI 0406C.b, A8-960. 3119 // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) | 3120 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) 3121 int vd, d; 3122 dst.split_code(&vd, &d); 3123 int vn, n; 3124 src1.split_code(&vn, &n); 3125 int vm, m; 3126 src2.split_code(&vm, &m); 3127 emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | 3128 n*B7 | m*B5 | vm); 3129 } 3130 3131 3132 void Assembler::vmul(const SwVfpRegister dst, const SwVfpRegister src1, 3133 const SwVfpRegister src2, const Condition cond) { 3134 // Sd = vmul(Sn, Sm) single precision floating point multiplication. 3135 // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm. 3136 // Instruction details available in ARM DDI 0406C.b, A8-960. 3137 // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) | 3138 // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) 3139 int vd, d; 3140 dst.split_code(&vd, &d); 3141 int vn, n; 3142 src1.split_code(&vn, &n); 3143 int vm, m; 3144 src2.split_code(&vm, &m); 3145 emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 | 3146 0x5 * B9 | n * B7 | m * B5 | vm); 3147 } 3148 3149 3150 void Assembler::vmla(const DwVfpRegister dst, 3151 const DwVfpRegister src1, 3152 const DwVfpRegister src2, 3153 const Condition cond) { 3154 // Instruction details available in ARM DDI 0406C.b, A8-932. 3155 // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | 3156 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0) 3157 int vd, d; 3158 dst.split_code(&vd, &d); 3159 int vn, n; 3160 src1.split_code(&vn, &n); 3161 int vm, m; 3162 src2.split_code(&vm, &m); 3163 emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | 3164 vm); 3165 } 3166 3167 3168 void Assembler::vmla(const SwVfpRegister dst, const SwVfpRegister src1, 3169 const SwVfpRegister src2, const Condition cond) { 3170 // Instruction details available in ARM DDI 0406C.b, A8-932. 3171 // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | 3172 // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0) 3173 int vd, d; 3174 dst.split_code(&vd, &d); 3175 int vn, n; 3176 src1.split_code(&vn, &n); 3177 int vm, m; 3178 src2.split_code(&vm, &m); 3179 emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 | 3180 m * B5 | vm); 3181 } 3182 3183 3184 void Assembler::vmls(const DwVfpRegister dst, 3185 const DwVfpRegister src1, 3186 const DwVfpRegister src2, 3187 const Condition cond) { 3188 // Instruction details available in ARM DDI 0406C.b, A8-932. 3189 // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | 3190 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0) 3191 int vd, d; 3192 dst.split_code(&vd, &d); 3193 int vn, n; 3194 src1.split_code(&vn, &n); 3195 int vm, m; 3196 src2.split_code(&vm, &m); 3197 emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | B6 | 3198 m*B5 | vm); 3199 } 3200 3201 3202 void Assembler::vmls(const SwVfpRegister dst, const SwVfpRegister src1, 3203 const SwVfpRegister src2, const Condition cond) { 3204 // Instruction details available in ARM DDI 0406C.b, A8-932. 3205 // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | 3206 // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0) 3207 int vd, d; 3208 dst.split_code(&vd, &d); 3209 int vn, n; 3210 src1.split_code(&vn, &n); 3211 int vm, m; 3212 src2.split_code(&vm, &m); 3213 emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 | 3214 B6 | m * B5 | vm); 3215 } 3216 3217 3218 void Assembler::vdiv(const DwVfpRegister dst, 3219 const DwVfpRegister src1, 3220 const DwVfpRegister src2, 3221 const Condition cond) { 3222 // Dd = vdiv(Dn, Dm) double precision floating point division. 3223 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 3224 // Instruction details available in ARM DDI 0406C.b, A8-882. 3225 // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) | 3226 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) 3227 int vd, d; 3228 dst.split_code(&vd, &d); 3229 int vn, n; 3230 src1.split_code(&vn, &n); 3231 int vm, m; 3232 src2.split_code(&vm, &m); 3233 emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | 3234 vm); 3235 } 3236 3237 3238 void Assembler::vdiv(const SwVfpRegister dst, const SwVfpRegister src1, 3239 const SwVfpRegister src2, const Condition cond) { 3240 // Sd = vdiv(Sn, Sm) single precision floating point division. 3241 // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm. 3242 // Instruction details available in ARM DDI 0406C.b, A8-882. 3243 // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) | 3244 // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) 3245 int vd, d; 3246 dst.split_code(&vd, &d); 3247 int vn, n; 3248 src1.split_code(&vn, &n); 3249 int vm, m; 3250 src2.split_code(&vm, &m); 3251 emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 | 3252 m * B5 | vm); 3253 } 3254 3255 3256 void Assembler::vcmp(const DwVfpRegister src1, 3257 const DwVfpRegister src2, 3258 const Condition cond) { 3259 // vcmp(Dd, Dm) double precision floating point comparison. 3260 // Instruction details available in ARM DDI 0406C.b, A8-864. 3261 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) | 3262 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3263 int vd, d; 3264 src1.split_code(&vd, &d); 3265 int vm, m; 3266 src2.split_code(&vm, &m); 3267 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 | 3268 m*B5 | vm); 3269 } 3270 3271 3272 void Assembler::vcmp(const SwVfpRegister src1, const SwVfpRegister src2, 3273 const Condition cond) { 3274 // vcmp(Sd, Sm) single precision floating point comparison. 3275 // Instruction details available in ARM DDI 0406C.b, A8-864. 3276 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) | 3277 // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3278 int vd, d; 3279 src1.split_code(&vd, &d); 3280 int vm, m; 3281 src2.split_code(&vm, &m); 3282 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 | 3283 0x5 * B9 | B6 | m * B5 | vm); 3284 } 3285 3286 3287 void Assembler::vcmp(const DwVfpRegister src1, 3288 const double src2, 3289 const Condition cond) { 3290 // vcmp(Dd, #0.0) double precision floating point comparison. 3291 // Instruction details available in ARM DDI 0406C.b, A8-864. 3292 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) | 3293 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0) 3294 DCHECK(src2 == 0.0); 3295 int vd, d; 3296 src1.split_code(&vd, &d); 3297 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6); 3298 } 3299 3300 3301 void Assembler::vcmp(const SwVfpRegister src1, const float src2, 3302 const Condition cond) { 3303 // vcmp(Sd, #0.0) single precision floating point comparison. 3304 // Instruction details available in ARM DDI 0406C.b, A8-864. 3305 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) | 3306 // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0) 3307 DCHECK(src2 == 0.0); 3308 int vd, d; 3309 src1.split_code(&vd, &d); 3310 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 | 3311 0x5 * B9 | B6); 3312 } 3313 3314 3315 void Assembler::vsqrt(const DwVfpRegister dst, 3316 const DwVfpRegister src, 3317 const Condition cond) { 3318 // Instruction details available in ARM DDI 0406C.b, A8-1058. 3319 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) | 3320 // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) 3321 int vd, d; 3322 dst.split_code(&vd, &d); 3323 int vm, m; 3324 src.split_code(&vm, &m); 3325 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | 3326 m*B5 | vm); 3327 } 3328 3329 3330 void Assembler::vsqrt(const SwVfpRegister dst, const SwVfpRegister src, 3331 const Condition cond) { 3332 // Instruction details available in ARM DDI 0406C.b, A8-1058. 3333 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) | 3334 // Vd(15-12) | 101(11-9) | sz=0(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) 3335 int vd, d; 3336 dst.split_code(&vd, &d); 3337 int vm, m; 3338 src.split_code(&vm, &m); 3339 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 | 3340 0x3 * B6 | m * B5 | vm); 3341 } 3342 3343 3344 void Assembler::vmsr(Register dst, Condition cond) { 3345 // Instruction details available in ARM DDI 0406A, A8-652. 3346 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | 3347 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 3348 emit(cond | 0xE * B24 | 0xE * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4); 3349 } 3350 3351 3352 void Assembler::vmrs(Register dst, Condition cond) { 3353 // Instruction details available in ARM DDI 0406A, A8-652. 3354 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | 3355 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 3356 emit(cond | 0xE * B24 | 0xF * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4); 3357 } 3358 3359 3360 void Assembler::vrinta(const SwVfpRegister dst, const SwVfpRegister src) { 3361 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3362 // 10(19-18) | RM=00(17-16) | Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) | 3363 // M(5) | 0(4) | Vm(3-0) 3364 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3365 int vd, d; 3366 dst.split_code(&vd, &d); 3367 int vm, m; 3368 src.split_code(&vm, &m); 3369 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 | 3370 0x5 * B9 | B6 | m * B5 | vm); 3371 } 3372 3373 3374 void Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) { 3375 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3376 // 10(19-18) | RM=00(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | 3377 // M(5) | 0(4) | Vm(3-0) 3378 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3379 int vd, d; 3380 dst.split_code(&vd, &d); 3381 int vm, m; 3382 src.split_code(&vm, &m); 3383 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 | 3384 0x5 * B9 | B8 | B6 | m * B5 | vm); 3385 } 3386 3387 3388 void Assembler::vrintn(const SwVfpRegister dst, const SwVfpRegister src) { 3389 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3390 // 10(19-18) | RM=01(17-16) | Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) | 3391 // M(5) | 0(4) | Vm(3-0) 3392 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3393 int vd, d; 3394 dst.split_code(&vd, &d); 3395 int vm, m; 3396 src.split_code(&vm, &m); 3397 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 | 3398 vd * B12 | 0x5 * B9 | B6 | m * B5 | vm); 3399 } 3400 3401 3402 void Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) { 3403 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3404 // 10(19-18) | RM=01(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | 3405 // M(5) | 0(4) | Vm(3-0) 3406 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3407 int vd, d; 3408 dst.split_code(&vd, &d); 3409 int vm, m; 3410 src.split_code(&vm, &m); 3411 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 | 3412 vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm); 3413 } 3414 3415 3416 void Assembler::vrintp(const SwVfpRegister dst, const SwVfpRegister src) { 3417 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3418 // 10(19-18) | RM=10(17-16) | Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) | 3419 // M(5) | 0(4) | Vm(3-0) 3420 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3421 int vd, d; 3422 dst.split_code(&vd, &d); 3423 int vm, m; 3424 src.split_code(&vm, &m); 3425 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 | 3426 vd * B12 | 0x5 * B9 | B6 | m * B5 | vm); 3427 } 3428 3429 3430 void Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) { 3431 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3432 // 10(19-18) | RM=10(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | 3433 // M(5) | 0(4) | Vm(3-0) 3434 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3435 int vd, d; 3436 dst.split_code(&vd, &d); 3437 int vm, m; 3438 src.split_code(&vm, &m); 3439 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 | 3440 vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm); 3441 } 3442 3443 3444 void Assembler::vrintm(const SwVfpRegister dst, const SwVfpRegister src) { 3445 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3446 // 10(19-18) | RM=11(17-16) | Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) | 3447 // M(5) | 0(4) | Vm(3-0) 3448 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3449 int vd, d; 3450 dst.split_code(&vd, &d); 3451 int vm, m; 3452 src.split_code(&vm, &m); 3453 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 | 3454 vd * B12 | 0x5 * B9 | B6 | m * B5 | vm); 3455 } 3456 3457 3458 void Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) { 3459 // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) | 3460 // 10(19-18) | RM=11(17-16) | Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) | 3461 // M(5) | 0(4) | Vm(3-0) 3462 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3463 int vd, d; 3464 dst.split_code(&vd, &d); 3465 int vm, m; 3466 src.split_code(&vm, &m); 3467 emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 | 3468 vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm); 3469 } 3470 3471 3472 void Assembler::vrintz(const SwVfpRegister dst, const SwVfpRegister src, 3473 const Condition cond) { 3474 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) | 3475 // Vd(15-12) | 101(11-9) | sz=0(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3476 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3477 int vd, d; 3478 dst.split_code(&vd, &d); 3479 int vm, m; 3480 src.split_code(&vm, &m); 3481 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 | 3482 0x5 * B9 | B7 | B6 | m * B5 | vm); 3483 } 3484 3485 3486 void Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src, 3487 const Condition cond) { 3488 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) | 3489 // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 3490 DCHECK(CpuFeatures::IsSupported(ARMv8)); 3491 int vd, d; 3492 dst.split_code(&vd, &d); 3493 int vm, m; 3494 src.split_code(&vm, &m); 3495 emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 | 3496 0x5 * B9 | B8 | B7 | B6 | m * B5 | vm); 3497 } 3498 3499 3500 // Support for NEON. 3501 3502 void Assembler::vld1(NeonSize size, 3503 const NeonListOperand& dst, 3504 const NeonMemOperand& src) { 3505 // Instruction details available in ARM DDI 0406C.b, A8.8.320. 3506 // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) | 3507 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0) 3508 DCHECK(CpuFeatures::IsSupported(NEON)); 3509 int vd, d; 3510 dst.base().split_code(&vd, &d); 3511 emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 | 3512 dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code()); 3513 } 3514 3515 3516 void Assembler::vst1(NeonSize size, 3517 const NeonListOperand& src, 3518 const NeonMemOperand& dst) { 3519 // Instruction details available in ARM DDI 0406C.b, A8.8.404. 3520 // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) | 3521 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0) 3522 DCHECK(CpuFeatures::IsSupported(NEON)); 3523 int vd, d; 3524 src.base().split_code(&vd, &d); 3525 emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 | 3526 size*B6 | dst.align()*B4 | dst.rm().code()); 3527 } 3528 3529 3530 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) { 3531 // Instruction details available in ARM DDI 0406C.b, A8.8.346. 3532 // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) | 3533 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) 3534 DCHECK(CpuFeatures::IsSupported(NEON)); 3535 int vd, d; 3536 dst.split_code(&vd, &d); 3537 int vm, m; 3538 src.split_code(&vm, &m); 3539 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 | 3540 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm); 3541 } 3542 3543 3544 // Pseudo instructions. 3545 void Assembler::nop(int type) { 3546 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes 3547 // some of the CPU's pipeline and has to issue. Older ARM chips simply used 3548 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. 3549 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode 3550 // a type. 3551 DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop. 3552 emit(al | 13*B21 | type*B12 | type); 3553 } 3554 3555 3556 bool Assembler::IsMovT(Instr instr) { 3557 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions 3558 ((kNumRegisters-1)*B12) | // mask out register 3559 EncodeMovwImmediate(0xFFFF)); // mask out immediate value 3560 return instr == kMovtPattern; 3561 } 3562 3563 3564 bool Assembler::IsMovW(Instr instr) { 3565 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions 3566 ((kNumRegisters-1)*B12) | // mask out destination 3567 EncodeMovwImmediate(0xFFFF)); // mask out immediate value 3568 return instr == kMovwPattern; 3569 } 3570 3571 3572 Instr Assembler::GetMovTPattern() { return kMovtPattern; } 3573 3574 3575 Instr Assembler::GetMovWPattern() { return kMovwPattern; } 3576 3577 3578 Instr Assembler::EncodeMovwImmediate(uint32_t immediate) { 3579 DCHECK(immediate < 0x10000); 3580 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); 3581 } 3582 3583 3584 Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) { 3585 instruction &= ~EncodeMovwImmediate(0xffff); 3586 return instruction | EncodeMovwImmediate(immediate); 3587 } 3588 3589 3590 int Assembler::DecodeShiftImm(Instr instr) { 3591 int rotate = Instruction::RotateValue(instr) * 2; 3592 int immed8 = Instruction::Immed8Value(instr); 3593 return base::bits::RotateRight32(immed8, rotate); 3594 } 3595 3596 3597 Instr Assembler::PatchShiftImm(Instr instr, int immed) { 3598 uint32_t rotate_imm = 0; 3599 uint32_t immed_8 = 0; 3600 bool immed_fits = fits_shifter(immed, &rotate_imm, &immed_8, NULL); 3601 DCHECK(immed_fits); 3602 USE(immed_fits); 3603 return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8; 3604 } 3605 3606 3607 bool Assembler::IsNop(Instr instr, int type) { 3608 DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop. 3609 // Check for mov rx, rx where x = type. 3610 return instr == (al | 13*B21 | type*B12 | type); 3611 } 3612 3613 3614 bool Assembler::IsMovImmed(Instr instr) { 3615 return (instr & kMovImmedMask) == kMovImmedPattern; 3616 } 3617 3618 3619 bool Assembler::IsOrrImmed(Instr instr) { 3620 return (instr & kOrrImmedMask) == kOrrImmedPattern; 3621 } 3622 3623 3624 // static 3625 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { 3626 uint32_t dummy1; 3627 uint32_t dummy2; 3628 return fits_shifter(imm32, &dummy1, &dummy2, NULL); 3629 } 3630 3631 3632 bool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) { 3633 return is_uint12(abs(imm32)); 3634 } 3635 3636 3637 // Debugging. 3638 void Assembler::RecordConstPool(int size) { 3639 // We only need this for debugger support, to correctly compute offsets in the 3640 // code. 3641 RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); 3642 } 3643 3644 3645 void Assembler::GrowBuffer() { 3646 if (!own_buffer_) FATAL("external code buffer is too small"); 3647 3648 // Compute new buffer size. 3649 CodeDesc desc; // the new buffer 3650 if (buffer_size_ < 1 * MB) { 3651 desc.buffer_size = 2*buffer_size_; 3652 } else { 3653 desc.buffer_size = buffer_size_ + 1*MB; 3654 } 3655 CHECK_GT(desc.buffer_size, 0); // no overflow 3656 3657 // Set up new buffer. 3658 desc.buffer = NewArray<byte>(desc.buffer_size); 3659 3660 desc.instr_size = pc_offset(); 3661 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 3662 desc.origin = this; 3663 3664 // Copy the data. 3665 int pc_delta = desc.buffer - buffer_; 3666 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 3667 MemMove(desc.buffer, buffer_, desc.instr_size); 3668 MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), 3669 desc.reloc_size); 3670 3671 // Switch buffers. 3672 DeleteArray(buffer_); 3673 buffer_ = desc.buffer; 3674 buffer_size_ = desc.buffer_size; 3675 pc_ += pc_delta; 3676 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 3677 reloc_info_writer.last_pc() + pc_delta); 3678 3679 // None of our relocation types are pc relative pointing outside the code 3680 // buffer nor pc absolute pointing inside the code buffer, so there is no need 3681 // to relocate any emitted relocation entries. 3682 } 3683 3684 3685 void Assembler::db(uint8_t data) { 3686 // db is used to write raw data. The constant pool should be emitted or 3687 // blocked before using db. 3688 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); 3689 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); 3690 CheckBuffer(); 3691 *reinterpret_cast<uint8_t*>(pc_) = data; 3692 pc_ += sizeof(uint8_t); 3693 } 3694 3695 3696 void Assembler::dd(uint32_t data) { 3697 // dd is used to write raw data. The constant pool should be emitted or 3698 // blocked before using dd. 3699 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); 3700 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); 3701 CheckBuffer(); 3702 *reinterpret_cast<uint32_t*>(pc_) = data; 3703 pc_ += sizeof(uint32_t); 3704 } 3705 3706 3707 void Assembler::dq(uint64_t value) { 3708 // dq is used to write raw data. The constant pool should be emitted or 3709 // blocked before using dq. 3710 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); 3711 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); 3712 CheckBuffer(); 3713 *reinterpret_cast<uint64_t*>(pc_) = value; 3714 pc_ += sizeof(uint64_t); 3715 } 3716 3717 3718 void Assembler::emit_code_stub_address(Code* stub) { 3719 CheckBuffer(); 3720 *reinterpret_cast<uint32_t*>(pc_) = 3721 reinterpret_cast<uint32_t>(stub->instruction_start()); 3722 pc_ += sizeof(uint32_t); 3723 } 3724 3725 3726 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 3727 if (RelocInfo::IsNone(rmode) || 3728 // Don't record external references unless the heap will be serialized. 3729 (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() && 3730 !emit_debug_code())) { 3731 return; 3732 } 3733 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 3734 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 3735 data = RecordedAstId().ToInt(); 3736 ClearRecordedAstId(); 3737 } 3738 RelocInfo rinfo(isolate(), pc_, rmode, data, NULL); 3739 reloc_info_writer.Write(&rinfo); 3740 } 3741 3742 3743 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, 3744 RelocInfo::Mode rmode, 3745 intptr_t value) { 3746 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION && 3747 rmode != RelocInfo::STATEMENT_POSITION && 3748 rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64); 3749 bool sharing_ok = RelocInfo::IsNone(rmode) || 3750 !(serializer_enabled() || rmode < RelocInfo::CELL); 3751 if (FLAG_enable_embedded_constant_pool) { 3752 return constant_pool_builder_.AddEntry(position, value, sharing_ok); 3753 } else { 3754 DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants); 3755 if (num_pending_32_bit_constants_ == 0) { 3756 first_const_pool_32_use_ = position; 3757 } else if (num_pending_32_bit_constants_ == kMinNumPendingConstants && 3758 pending_32_bit_constants_ == 3759 &pending_32_bit_constants_buffer_[0]) { 3760 // Inline buffer is full, switch to dynamically allocated buffer. 3761 pending_32_bit_constants_ = 3762 new ConstantPoolEntry[kMaxNumPending32Constants]; 3763 std::copy(&pending_32_bit_constants_buffer_[0], 3764 &pending_32_bit_constants_buffer_[kMinNumPendingConstants], 3765 &pending_32_bit_constants_[0]); 3766 } 3767 ConstantPoolEntry entry(position, value, sharing_ok); 3768 pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry; 3769 3770 // Make sure the constant pool is not emitted in place of the next 3771 // instruction for which we just recorded relocation info. 3772 BlockConstPoolFor(1); 3773 return ConstantPoolEntry::REGULAR; 3774 } 3775 } 3776 3777 3778 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, 3779 double value) { 3780 if (FLAG_enable_embedded_constant_pool) { 3781 return constant_pool_builder_.AddEntry(position, value); 3782 } else { 3783 DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants); 3784 if (num_pending_64_bit_constants_ == 0) { 3785 first_const_pool_64_use_ = position; 3786 } else if (num_pending_64_bit_constants_ == kMinNumPendingConstants && 3787 pending_64_bit_constants_ == 3788 &pending_64_bit_constants_buffer_[0]) { 3789 // Inline buffer is full, switch to dynamically allocated buffer. 3790 pending_64_bit_constants_ = 3791 new ConstantPoolEntry[kMaxNumPending64Constants]; 3792 std::copy(&pending_64_bit_constants_buffer_[0], 3793 &pending_64_bit_constants_buffer_[kMinNumPendingConstants], 3794 &pending_64_bit_constants_[0]); 3795 } 3796 ConstantPoolEntry entry(position, value); 3797 pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry; 3798 3799 // Make sure the constant pool is not emitted in place of the next 3800 // instruction for which we just recorded relocation info. 3801 BlockConstPoolFor(1); 3802 return ConstantPoolEntry::REGULAR; 3803 } 3804 } 3805 3806 3807 void Assembler::BlockConstPoolFor(int instructions) { 3808 if (FLAG_enable_embedded_constant_pool) { 3809 // Should be a no-op if using an embedded constant pool. 3810 DCHECK(num_pending_32_bit_constants_ == 0); 3811 DCHECK(num_pending_64_bit_constants_ == 0); 3812 return; 3813 } 3814 3815 int pc_limit = pc_offset() + instructions * kInstrSize; 3816 if (no_const_pool_before_ < pc_limit) { 3817 // Max pool start (if we need a jump and an alignment). 3818 #ifdef DEBUG 3819 int start = pc_limit + kInstrSize + 2 * kPointerSize; 3820 DCHECK((num_pending_32_bit_constants_ == 0) || 3821 (start - first_const_pool_32_use_ + 3822 num_pending_64_bit_constants_ * kDoubleSize < 3823 kMaxDistToIntPool)); 3824 DCHECK((num_pending_64_bit_constants_ == 0) || 3825 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); 3826 #endif 3827 no_const_pool_before_ = pc_limit; 3828 } 3829 3830 if (next_buffer_check_ < no_const_pool_before_) { 3831 next_buffer_check_ = no_const_pool_before_; 3832 } 3833 } 3834 3835 3836 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { 3837 if (FLAG_enable_embedded_constant_pool) { 3838 // Should be a no-op if using an embedded constant pool. 3839 DCHECK(num_pending_32_bit_constants_ == 0); 3840 DCHECK(num_pending_64_bit_constants_ == 0); 3841 return; 3842 } 3843 3844 // Some short sequence of instruction mustn't be broken up by constant pool 3845 // emission, such sequences are protected by calls to BlockConstPoolFor and 3846 // BlockConstPoolScope. 3847 if (is_const_pool_blocked()) { 3848 // Something is wrong if emission is forced and blocked at the same time. 3849 DCHECK(!force_emit); 3850 return; 3851 } 3852 3853 // There is nothing to do if there are no pending constant pool entries. 3854 if ((num_pending_32_bit_constants_ == 0) && 3855 (num_pending_64_bit_constants_ == 0)) { 3856 // Calculate the offset of the next check. 3857 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 3858 return; 3859 } 3860 3861 // Check that the code buffer is large enough before emitting the constant 3862 // pool (include the jump over the pool and the constant pool marker and 3863 // the gap to the relocation information). 3864 int jump_instr = require_jump ? kInstrSize : 0; 3865 int size_up_to_marker = jump_instr + kInstrSize; 3866 int estimated_size_after_marker = 3867 num_pending_32_bit_constants_ * kPointerSize; 3868 bool has_int_values = (num_pending_32_bit_constants_ > 0); 3869 bool has_fp_values = (num_pending_64_bit_constants_ > 0); 3870 bool require_64_bit_align = false; 3871 if (has_fp_values) { 3872 require_64_bit_align = 3873 !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), 3874 kDoubleAlignment); 3875 if (require_64_bit_align) { 3876 estimated_size_after_marker += kInstrSize; 3877 } 3878 estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; 3879 } 3880 int estimated_size = size_up_to_marker + estimated_size_after_marker; 3881 3882 // We emit a constant pool when: 3883 // * requested to do so by parameter force_emit (e.g. after each function). 3884 // * the distance from the first instruction accessing the constant pool to 3885 // any of the constant pool entries will exceed its limit the next 3886 // time the pool is checked. This is overly restrictive, but we don't emit 3887 // constant pool entries in-order so it's conservatively correct. 3888 // * the instruction doesn't require a jump after itself to jump over the 3889 // constant pool, and we're getting close to running out of range. 3890 if (!force_emit) { 3891 DCHECK(has_fp_values || has_int_values); 3892 bool need_emit = false; 3893 if (has_fp_values) { 3894 // The 64-bit constants are always emitted before the 32-bit constants, so 3895 // we can ignore the effect of the 32-bit constants on estimated_size. 3896 int dist64 = pc_offset() + estimated_size - 3897 num_pending_32_bit_constants_ * kPointerSize - 3898 first_const_pool_64_use_; 3899 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || 3900 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { 3901 need_emit = true; 3902 } 3903 } 3904 if (has_int_values) { 3905 int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_; 3906 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || 3907 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { 3908 need_emit = true; 3909 } 3910 } 3911 if (!need_emit) return; 3912 } 3913 3914 // Deduplicate constants. 3915 int size_after_marker = estimated_size_after_marker; 3916 for (int i = 0; i < num_pending_64_bit_constants_; i++) { 3917 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; 3918 DCHECK(!entry.is_merged()); 3919 for (int j = 0; j < i; j++) { 3920 if (entry.value64() == pending_64_bit_constants_[j].value64()) { 3921 DCHECK(!pending_64_bit_constants_[j].is_merged()); 3922 entry.set_merged_index(j); 3923 size_after_marker -= kDoubleSize; 3924 break; 3925 } 3926 } 3927 } 3928 3929 for (int i = 0; i < num_pending_32_bit_constants_; i++) { 3930 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; 3931 DCHECK(!entry.is_merged()); 3932 if (!entry.sharing_ok()) continue; 3933 for (int j = 0; j < i; j++) { 3934 if (entry.value() == pending_32_bit_constants_[j].value()) { 3935 DCHECK(!pending_32_bit_constants_[j].is_merged()); 3936 entry.set_merged_index(j); 3937 size_after_marker -= kPointerSize; 3938 break; 3939 } 3940 } 3941 } 3942 3943 int size = size_up_to_marker + size_after_marker; 3944 3945 int needed_space = size + kGap; 3946 while (buffer_space() <= needed_space) GrowBuffer(); 3947 3948 { 3949 // Block recursive calls to CheckConstPool. 3950 BlockConstPoolScope block_const_pool(this); 3951 RecordComment("[ Constant Pool"); 3952 RecordConstPool(size); 3953 3954 Label size_check; 3955 bind(&size_check); 3956 3957 // Emit jump over constant pool if necessary. 3958 Label after_pool; 3959 if (require_jump) { 3960 b(&after_pool); 3961 } 3962 3963 // Put down constant pool marker "Undefined instruction". 3964 // The data size helps disassembly know what to print. 3965 emit(kConstantPoolMarker | 3966 EncodeConstantPoolLength(size_after_marker / kPointerSize)); 3967 3968 if (require_64_bit_align) { 3969 emit(kConstantPoolMarker); 3970 } 3971 3972 // Emit 64-bit constant pool entries first: their range is smaller than 3973 // 32-bit entries. 3974 for (int i = 0; i < num_pending_64_bit_constants_; i++) { 3975 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; 3976 3977 Instr instr = instr_at(entry.position()); 3978 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0. 3979 DCHECK((IsVldrDPcImmediateOffset(instr) && 3980 GetVldrDRegisterImmediateOffset(instr) == 0)); 3981 3982 int delta = pc_offset() - entry.position() - kPcLoadDelta; 3983 DCHECK(is_uint10(delta)); 3984 3985 if (entry.is_merged()) { 3986 ConstantPoolEntry& merged = 3987 pending_64_bit_constants_[entry.merged_index()]; 3988 DCHECK(entry.value64() == merged.value64()); 3989 Instr merged_instr = instr_at(merged.position()); 3990 DCHECK(IsVldrDPcImmediateOffset(merged_instr)); 3991 delta = GetVldrDRegisterImmediateOffset(merged_instr); 3992 delta += merged.position() - entry.position(); 3993 } 3994 instr_at_put(entry.position(), 3995 SetVldrDRegisterImmediateOffset(instr, delta)); 3996 if (!entry.is_merged()) { 3997 DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment)); 3998 dq(entry.value64()); 3999 } 4000 } 4001 4002 // Emit 32-bit constant pool entries. 4003 for (int i = 0; i < num_pending_32_bit_constants_; i++) { 4004 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; 4005 Instr instr = instr_at(entry.position()); 4006 4007 // 64-bit loads shouldn't get here. 4008 DCHECK(!IsVldrDPcImmediateOffset(instr)); 4009 DCHECK(!IsMovW(instr)); 4010 DCHECK(IsLdrPcImmediateOffset(instr) && 4011 GetLdrRegisterImmediateOffset(instr) == 0); 4012 4013 int delta = pc_offset() - entry.position() - kPcLoadDelta; 4014 DCHECK(is_uint12(delta)); 4015 // 0 is the smallest delta: 4016 // ldr rd, [pc, #0] 4017 // constant pool marker 4018 // data 4019 4020 if (entry.is_merged()) { 4021 DCHECK(entry.sharing_ok()); 4022 ConstantPoolEntry& merged = 4023 pending_32_bit_constants_[entry.merged_index()]; 4024 DCHECK(entry.value() == merged.value()); 4025 Instr merged_instr = instr_at(merged.position()); 4026 DCHECK(IsLdrPcImmediateOffset(merged_instr)); 4027 delta = GetLdrRegisterImmediateOffset(merged_instr); 4028 delta += merged.position() - entry.position(); 4029 } 4030 instr_at_put(entry.position(), 4031 SetLdrRegisterImmediateOffset(instr, delta)); 4032 if (!entry.is_merged()) { 4033 emit(entry.value()); 4034 } 4035 } 4036 4037 num_pending_32_bit_constants_ = 0; 4038 num_pending_64_bit_constants_ = 0; 4039 first_const_pool_32_use_ = -1; 4040 first_const_pool_64_use_ = -1; 4041 4042 RecordComment("]"); 4043 4044 DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check)); 4045 4046 if (after_pool.is_linked()) { 4047 bind(&after_pool); 4048 } 4049 } 4050 4051 // Since a constant pool was just emitted, move the check offset forward by 4052 // the standard interval. 4053 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 4054 } 4055 4056 4057 void Assembler::PatchConstantPoolAccessInstruction( 4058 int pc_offset, int offset, ConstantPoolEntry::Access access, 4059 ConstantPoolEntry::Type type) { 4060 DCHECK(FLAG_enable_embedded_constant_pool); 4061 Address pc = buffer_ + pc_offset; 4062 4063 // Patch vldr/ldr instruction with correct offset. 4064 Instr instr = instr_at(pc); 4065 if (access == ConstantPoolEntry::OVERFLOWED) { 4066 if (CpuFeatures::IsSupported(ARMv7)) { 4067 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0]. 4068 Instr next_instr = instr_at(pc + kInstrSize); 4069 DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0)); 4070 DCHECK((IsMovT(next_instr) && 4071 Instruction::ImmedMovwMovtValue(next_instr) == 0)); 4072 instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff)); 4073 instr_at_put(pc + kInstrSize, 4074 PatchMovwImmediate(next_instr, offset >> 16)); 4075 } else { 4076 // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0]. 4077 Instr instr_2 = instr_at(pc + kInstrSize); 4078 Instr instr_3 = instr_at(pc + 2 * kInstrSize); 4079 Instr instr_4 = instr_at(pc + 3 * kInstrSize); 4080 DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0)); 4081 DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) && 4082 GetRn(instr_2).is(GetRd(instr_2))); 4083 DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) && 4084 GetRn(instr_3).is(GetRd(instr_3))); 4085 DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) && 4086 GetRn(instr_4).is(GetRd(instr_4))); 4087 instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask))); 4088 instr_at_put(pc + kInstrSize, 4089 PatchShiftImm(instr_2, (offset & (kImm8Mask << 8)))); 4090 instr_at_put(pc + 2 * kInstrSize, 4091 PatchShiftImm(instr_3, (offset & (kImm8Mask << 16)))); 4092 instr_at_put(pc + 3 * kInstrSize, 4093 PatchShiftImm(instr_4, (offset & (kImm8Mask << 24)))); 4094 } 4095 } else if (type == ConstantPoolEntry::DOUBLE) { 4096 // Instruction to patch must be 'vldr rd, [pp, #0]'. 4097 DCHECK((IsVldrDPpImmediateOffset(instr) && 4098 GetVldrDRegisterImmediateOffset(instr) == 0)); 4099 DCHECK(is_uint10(offset)); 4100 instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset)); 4101 } else { 4102 // Instruction to patch must be 'ldr rd, [pp, #0]'. 4103 DCHECK((IsLdrPpImmediateOffset(instr) && 4104 GetLdrRegisterImmediateOffset(instr) == 0)); 4105 DCHECK(is_uint12(offset)); 4106 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); 4107 } 4108 } 4109 4110 4111 } // namespace internal 4112 } // namespace v8 4113 4114 #endif // V8_TARGET_ARCH_ARM 4115