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