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