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 2011 the V8 project authors. All rights reserved. 36 37 #include "v8.h" 38 39 #if defined(V8_TARGET_ARCH_ARM) 40 41 #include "arm/assembler-arm-inl.h" 42 #include "serialize.h" 43 44 namespace v8 { 45 namespace internal { 46 47 #ifdef DEBUG 48 bool CpuFeatures::initialized_ = false; 49 #endif 50 unsigned CpuFeatures::supported_ = 0; 51 unsigned CpuFeatures::found_by_runtime_probing_ = 0; 52 53 54 // Get the CPU features enabled by the build. For cross compilation the 55 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP_INSTRUCTIONS 56 // can be defined to enable ARMv7 and VFPv3 instructions when building the 57 // snapshot. 58 static uint64_t CpuFeaturesImpliedByCompiler() { 59 uint64_t answer = 0; 60 #ifdef CAN_USE_ARMV7_INSTRUCTIONS 61 answer |= 1u << ARMv7; 62 #endif // def CAN_USE_ARMV7_INSTRUCTIONS 63 #ifdef CAN_USE_VFP_INSTRUCTIONS 64 answer |= 1u << VFP3 | 1u << ARMv7; 65 #endif // def CAN_USE_VFP_INSTRUCTIONS 66 67 #ifdef __arm__ 68 // If the compiler is allowed to use VFP then we can use VFP too in our code 69 // generation even when generating snapshots. ARMv7 and hardware floating 70 // point support implies VFPv3, see ARM DDI 0406B, page A1-6. 71 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \ 72 && !defined(__SOFTFP__) 73 answer |= 1u << VFP3 | 1u << ARMv7; 74 #endif // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) 75 // && !defined(__SOFTFP__) 76 #endif // def __arm__ 77 78 return answer; 79 } 80 81 82 void CpuFeatures::Probe() { 83 unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() | 84 CpuFeaturesImpliedByCompiler()); 85 ASSERT(supported_ == 0 || supported_ == standard_features); 86 #ifdef DEBUG 87 initialized_ = true; 88 #endif 89 90 // Get the features implied by the OS and the compiler settings. This is the 91 // minimal set of features which is also alowed for generated code in the 92 // snapshot. 93 supported_ |= standard_features; 94 95 if (Serializer::enabled()) { 96 // No probing for features if we might serialize (generate snapshot). 97 return; 98 } 99 100 #ifndef __arm__ 101 // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is 102 // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6. 103 if (FLAG_enable_vfp3) { 104 supported_ |= 1u << VFP3 | 1u << ARMv7; 105 } 106 // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled 107 if (FLAG_enable_armv7) { 108 supported_ |= 1u << ARMv7; 109 } 110 #else // def __arm__ 111 // Probe for additional features not already known to be available. 112 if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) { 113 // This implementation also sets the VFP flags if runtime 114 // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI 115 // 0406B, page A1-6. 116 supported_ |= 1u << VFP3 | 1u << ARMv7; 117 found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7; 118 } 119 120 if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) { 121 supported_ |= 1u << ARMv7; 122 found_by_runtime_probing_ |= 1u << ARMv7; 123 } 124 #endif 125 } 126 127 128 // ----------------------------------------------------------------------------- 129 // Implementation of RelocInfo 130 131 const int RelocInfo::kApplyMask = 0; 132 133 134 bool RelocInfo::IsCodedSpecially() { 135 // The deserializer needs to know whether a pointer is specially coded. Being 136 // specially coded on ARM means that it is a movw/movt instruction. We don't 137 // generate those yet. 138 return false; 139 } 140 141 142 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { 143 // Patch the code at the current address with the supplied instructions. 144 Instr* pc = reinterpret_cast<Instr*>(pc_); 145 Instr* instr = reinterpret_cast<Instr*>(instructions); 146 for (int i = 0; i < instruction_count; i++) { 147 *(pc + i) = *(instr + i); 148 } 149 150 // Indicate that code has changed. 151 CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize); 152 } 153 154 155 // Patch the code at the current PC with a call to the target address. 156 // Additional guard instructions can be added if required. 157 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 158 // Patch the code at the current address with a call to the target. 159 UNIMPLEMENTED(); 160 } 161 162 163 // ----------------------------------------------------------------------------- 164 // Implementation of Operand and MemOperand 165 // See assembler-arm-inl.h for inlined constructors 166 167 Operand::Operand(Handle<Object> handle) { 168 rm_ = no_reg; 169 // Verify all Objects referred by code are NOT in new space. 170 Object* obj = *handle; 171 ASSERT(!HEAP->InNewSpace(obj)); 172 if (obj->IsHeapObject()) { 173 imm32_ = reinterpret_cast<intptr_t>(handle.location()); 174 rmode_ = RelocInfo::EMBEDDED_OBJECT; 175 } else { 176 // no relocation needed 177 imm32_ = reinterpret_cast<intptr_t>(obj); 178 rmode_ = RelocInfo::NONE; 179 } 180 } 181 182 183 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { 184 ASSERT(is_uint5(shift_imm)); 185 ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it 186 rm_ = rm; 187 rs_ = no_reg; 188 shift_op_ = shift_op; 189 shift_imm_ = shift_imm & 31; 190 if (shift_op == RRX) { 191 // encoded as ROR with shift_imm == 0 192 ASSERT(shift_imm == 0); 193 shift_op_ = ROR; 194 shift_imm_ = 0; 195 } 196 } 197 198 199 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) { 200 ASSERT(shift_op != RRX); 201 rm_ = rm; 202 rs_ = no_reg; 203 shift_op_ = shift_op; 204 rs_ = rs; 205 } 206 207 208 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) { 209 rn_ = rn; 210 rm_ = no_reg; 211 offset_ = offset; 212 am_ = am; 213 } 214 215 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) { 216 rn_ = rn; 217 rm_ = rm; 218 shift_op_ = LSL; 219 shift_imm_ = 0; 220 am_ = am; 221 } 222 223 224 MemOperand::MemOperand(Register rn, Register rm, 225 ShiftOp shift_op, int shift_imm, AddrMode am) { 226 ASSERT(is_uint5(shift_imm)); 227 rn_ = rn; 228 rm_ = rm; 229 shift_op_ = shift_op; 230 shift_imm_ = shift_imm & 31; 231 am_ = am; 232 } 233 234 235 // ----------------------------------------------------------------------------- 236 // Specific instructions, constants, and masks. 237 238 // add(sp, sp, 4) instruction (aka Pop()) 239 const Instr kPopInstruction = 240 al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 | 241 kRegister_sp_Code * B12; 242 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) 243 // register r is not encoded. 244 const Instr kPushRegPattern = 245 al | B26 | 4 | NegPreIndex | kRegister_sp_Code * B16; 246 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) 247 // register r is not encoded. 248 const Instr kPopRegPattern = 249 al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16; 250 // mov lr, pc 251 const Instr kMovLrPc = al | MOV | kRegister_pc_Code | kRegister_lr_Code * B12; 252 // ldr rd, [pc, #offset] 253 const Instr kLdrPCMask = kCondMask | 15 * B24 | 7 * B20 | 15 * B16; 254 const Instr kLdrPCPattern = al | 5 * B24 | L | kRegister_pc_Code * B16; 255 // blxcc rm 256 const Instr kBlxRegMask = 257 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; 258 const Instr kBlxRegPattern = 259 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX; 260 const Instr kBlxIp = al | kBlxRegPattern | ip.code(); 261 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16; 262 const Instr kMovMvnPattern = 0xd * B21; 263 const Instr kMovMvnFlip = B22; 264 const Instr kMovLeaveCCMask = 0xdff * B16; 265 const Instr kMovLeaveCCPattern = 0x1a0 * B16; 266 const Instr kMovwMask = 0xff * B20; 267 const Instr kMovwPattern = 0x30 * B20; 268 const Instr kMovwLeaveCCFlip = 0x5 * B21; 269 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12; 270 const Instr kCmpCmnPattern = 0x15 * B20; 271 const Instr kCmpCmnFlip = B21; 272 const Instr kAddSubFlip = 0x6 * B21; 273 const Instr kAndBicFlip = 0xe * B21; 274 275 // A mask for the Rd register for push, pop, ldr, str instructions. 276 const Instr kLdrRegFpOffsetPattern = 277 al | B26 | L | Offset | kRegister_fp_Code * B16; 278 const Instr kStrRegFpOffsetPattern = 279 al | B26 | Offset | kRegister_fp_Code * B16; 280 const Instr kLdrRegFpNegOffsetPattern = 281 al | B26 | L | NegOffset | kRegister_fp_Code * B16; 282 const Instr kStrRegFpNegOffsetPattern = 283 al | B26 | NegOffset | kRegister_fp_Code * B16; 284 const Instr kLdrStrInstrTypeMask = 0xffff0000; 285 const Instr kLdrStrInstrArgumentMask = 0x0000ffff; 286 const Instr kLdrStrOffsetMask = 0x00000fff; 287 288 289 // Spare buffer. 290 static const int kMinimalBufferSize = 4*KB; 291 292 293 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) 294 : AssemblerBase(arg_isolate), 295 positions_recorder_(this), 296 emit_debug_code_(FLAG_debug_code) { 297 if (buffer == NULL) { 298 // Do our own buffer management. 299 if (buffer_size <= kMinimalBufferSize) { 300 buffer_size = kMinimalBufferSize; 301 302 if (isolate()->assembler_spare_buffer() != NULL) { 303 buffer = isolate()->assembler_spare_buffer(); 304 isolate()->set_assembler_spare_buffer(NULL); 305 } 306 } 307 if (buffer == NULL) { 308 buffer_ = NewArray<byte>(buffer_size); 309 } else { 310 buffer_ = static_cast<byte*>(buffer); 311 } 312 buffer_size_ = buffer_size; 313 own_buffer_ = true; 314 315 } else { 316 // Use externally provided buffer instead. 317 ASSERT(buffer_size > 0); 318 buffer_ = static_cast<byte*>(buffer); 319 buffer_size_ = buffer_size; 320 own_buffer_ = false; 321 } 322 323 // Set up buffer pointers. 324 ASSERT(buffer_ != NULL); 325 pc_ = buffer_; 326 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 327 num_pending_reloc_info_ = 0; 328 next_buffer_check_ = 0; 329 const_pool_blocked_nesting_ = 0; 330 no_const_pool_before_ = 0; 331 first_const_pool_use_ = -1; 332 last_bound_pos_ = 0; 333 ClearRecordedAstId(); 334 } 335 336 337 Assembler::~Assembler() { 338 ASSERT(const_pool_blocked_nesting_ == 0); 339 if (own_buffer_) { 340 if (isolate()->assembler_spare_buffer() == NULL && 341 buffer_size_ == kMinimalBufferSize) { 342 isolate()->set_assembler_spare_buffer(buffer_); 343 } else { 344 DeleteArray(buffer_); 345 } 346 } 347 } 348 349 350 void Assembler::GetCode(CodeDesc* desc) { 351 // Emit constant pool if necessary. 352 CheckConstPool(true, false); 353 ASSERT(num_pending_reloc_info_ == 0); 354 355 // Set up code descriptor. 356 desc->buffer = buffer_; 357 desc->buffer_size = buffer_size_; 358 desc->instr_size = pc_offset(); 359 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 360 } 361 362 363 void Assembler::Align(int m) { 364 ASSERT(m >= 4 && IsPowerOf2(m)); 365 while ((pc_offset() & (m - 1)) != 0) { 366 nop(); 367 } 368 } 369 370 371 void Assembler::CodeTargetAlign() { 372 // Preferred alignment of jump targets on some ARM chips. 373 Align(8); 374 } 375 376 377 Condition Assembler::GetCondition(Instr instr) { 378 return Instruction::ConditionField(instr); 379 } 380 381 382 bool Assembler::IsBranch(Instr instr) { 383 return (instr & (B27 | B25)) == (B27 | B25); 384 } 385 386 387 int Assembler::GetBranchOffset(Instr instr) { 388 ASSERT(IsBranch(instr)); 389 // Take the jump offset in the lower 24 bits, sign extend it and multiply it 390 // with 4 to get the offset in bytes. 391 return ((instr & kImm24Mask) << 8) >> 6; 392 } 393 394 395 bool Assembler::IsLdrRegisterImmediate(Instr instr) { 396 return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20); 397 } 398 399 400 int Assembler::GetLdrRegisterImmediateOffset(Instr instr) { 401 ASSERT(IsLdrRegisterImmediate(instr)); 402 bool positive = (instr & B23) == B23; 403 int offset = instr & kOff12Mask; // Zero extended offset. 404 return positive ? offset : -offset; 405 } 406 407 408 Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) { 409 ASSERT(IsLdrRegisterImmediate(instr)); 410 bool positive = offset >= 0; 411 if (!positive) offset = -offset; 412 ASSERT(is_uint12(offset)); 413 // Set bit indicating whether the offset should be added. 414 instr = (instr & ~B23) | (positive ? B23 : 0); 415 // Set the actual offset. 416 return (instr & ~kOff12Mask) | offset; 417 } 418 419 420 bool Assembler::IsStrRegisterImmediate(Instr instr) { 421 return (instr & (B27 | B26 | B25 | B22 | B20)) == B26; 422 } 423 424 425 Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) { 426 ASSERT(IsStrRegisterImmediate(instr)); 427 bool positive = offset >= 0; 428 if (!positive) offset = -offset; 429 ASSERT(is_uint12(offset)); 430 // Set bit indicating whether the offset should be added. 431 instr = (instr & ~B23) | (positive ? B23 : 0); 432 // Set the actual offset. 433 return (instr & ~kOff12Mask) | offset; 434 } 435 436 437 bool Assembler::IsAddRegisterImmediate(Instr instr) { 438 return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23); 439 } 440 441 442 Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) { 443 ASSERT(IsAddRegisterImmediate(instr)); 444 ASSERT(offset >= 0); 445 ASSERT(is_uint12(offset)); 446 // Set the offset. 447 return (instr & ~kOff12Mask) | offset; 448 } 449 450 451 Register Assembler::GetRd(Instr instr) { 452 Register reg; 453 reg.code_ = Instruction::RdValue(instr); 454 return reg; 455 } 456 457 458 Register Assembler::GetRn(Instr instr) { 459 Register reg; 460 reg.code_ = Instruction::RnValue(instr); 461 return reg; 462 } 463 464 465 Register Assembler::GetRm(Instr instr) { 466 Register reg; 467 reg.code_ = Instruction::RmValue(instr); 468 return reg; 469 } 470 471 472 bool Assembler::IsPush(Instr instr) { 473 return ((instr & ~kRdMask) == kPushRegPattern); 474 } 475 476 477 bool Assembler::IsPop(Instr instr) { 478 return ((instr & ~kRdMask) == kPopRegPattern); 479 } 480 481 482 bool Assembler::IsStrRegFpOffset(Instr instr) { 483 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern); 484 } 485 486 487 bool Assembler::IsLdrRegFpOffset(Instr instr) { 488 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern); 489 } 490 491 492 bool Assembler::IsStrRegFpNegOffset(Instr instr) { 493 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern); 494 } 495 496 497 bool Assembler::IsLdrRegFpNegOffset(Instr instr) { 498 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern); 499 } 500 501 502 bool Assembler::IsLdrPcImmediateOffset(Instr instr) { 503 // Check the instruction is indeed a 504 // ldr<cond> <Rd>, [pc +/- offset_12]. 505 return (instr & (kLdrPCMask & ~kCondMask)) == 0x051f0000; 506 } 507 508 509 bool Assembler::IsTstImmediate(Instr instr) { 510 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == 511 (I | TST | S); 512 } 513 514 515 bool Assembler::IsCmpRegister(Instr instr) { 516 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) == 517 (CMP | S); 518 } 519 520 521 bool Assembler::IsCmpImmediate(Instr instr) { 522 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == 523 (I | CMP | S); 524 } 525 526 527 Register Assembler::GetCmpImmediateRegister(Instr instr) { 528 ASSERT(IsCmpImmediate(instr)); 529 return GetRn(instr); 530 } 531 532 533 int Assembler::GetCmpImmediateRawImmediate(Instr instr) { 534 ASSERT(IsCmpImmediate(instr)); 535 return instr & kOff12Mask; 536 } 537 538 // Labels refer to positions in the (to be) generated code. 539 // There are bound, linked, and unused labels. 540 // 541 // Bound labels refer to known positions in the already 542 // generated code. pos() is the position the label refers to. 543 // 544 // Linked labels refer to unknown positions in the code 545 // to be generated; pos() is the position of the last 546 // instruction using the label. 547 548 549 // The link chain is terminated by a negative code position (must be aligned) 550 const int kEndOfChain = -4; 551 552 553 int Assembler::target_at(int pos) { 554 Instr instr = instr_at(pos); 555 if ((instr & ~kImm24Mask) == 0) { 556 // Emitted label constant, not part of a branch. 557 return instr - (Code::kHeaderSize - kHeapObjectTag); 558 } 559 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 560 int imm26 = ((instr & kImm24Mask) << 8) >> 6; 561 if ((Instruction::ConditionField(instr) == kSpecialCondition) && 562 ((instr & B24) != 0)) { 563 // blx uses bit 24 to encode bit 2 of imm26 564 imm26 += 2; 565 } 566 return pos + kPcLoadDelta + imm26; 567 } 568 569 570 void Assembler::target_at_put(int pos, int target_pos) { 571 Instr instr = instr_at(pos); 572 if ((instr & ~kImm24Mask) == 0) { 573 ASSERT(target_pos == kEndOfChain || target_pos >= 0); 574 // Emitted label constant, not part of a branch. 575 // Make label relative to Code* of generated Code object. 576 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 577 return; 578 } 579 int imm26 = target_pos - (pos + kPcLoadDelta); 580 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 581 if (Instruction::ConditionField(instr) == kSpecialCondition) { 582 // blx uses bit 24 to encode bit 2 of imm26 583 ASSERT((imm26 & 1) == 0); 584 instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24; 585 } else { 586 ASSERT((imm26 & 3) == 0); 587 instr &= ~kImm24Mask; 588 } 589 int imm24 = imm26 >> 2; 590 ASSERT(is_int24(imm24)); 591 instr_at_put(pos, instr | (imm24 & kImm24Mask)); 592 } 593 594 595 void Assembler::print(Label* L) { 596 if (L->is_unused()) { 597 PrintF("unused label\n"); 598 } else if (L->is_bound()) { 599 PrintF("bound label to %d\n", L->pos()); 600 } else if (L->is_linked()) { 601 Label l = *L; 602 PrintF("unbound label"); 603 while (l.is_linked()) { 604 PrintF("@ %d ", l.pos()); 605 Instr instr = instr_at(l.pos()); 606 if ((instr & ~kImm24Mask) == 0) { 607 PrintF("value\n"); 608 } else { 609 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx 610 Condition cond = Instruction::ConditionField(instr); 611 const char* b; 612 const char* c; 613 if (cond == kSpecialCondition) { 614 b = "blx"; 615 c = ""; 616 } else { 617 if ((instr & B24) != 0) 618 b = "bl"; 619 else 620 b = "b"; 621 622 switch (cond) { 623 case eq: c = "eq"; break; 624 case ne: c = "ne"; break; 625 case hs: c = "hs"; break; 626 case lo: c = "lo"; break; 627 case mi: c = "mi"; break; 628 case pl: c = "pl"; break; 629 case vs: c = "vs"; break; 630 case vc: c = "vc"; break; 631 case hi: c = "hi"; break; 632 case ls: c = "ls"; break; 633 case ge: c = "ge"; break; 634 case lt: c = "lt"; break; 635 case gt: c = "gt"; break; 636 case le: c = "le"; break; 637 case al: c = ""; break; 638 default: 639 c = ""; 640 UNREACHABLE(); 641 } 642 } 643 PrintF("%s%s\n", b, c); 644 } 645 next(&l); 646 } 647 } else { 648 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 649 } 650 } 651 652 653 void Assembler::bind_to(Label* L, int pos) { 654 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position 655 while (L->is_linked()) { 656 int fixup_pos = L->pos(); 657 next(L); // call next before overwriting link with target at fixup_pos 658 target_at_put(fixup_pos, pos); 659 } 660 L->bind_to(pos); 661 662 // Keep track of the last bound label so we don't eliminate any instructions 663 // before a bound label. 664 if (pos > last_bound_pos_) 665 last_bound_pos_ = pos; 666 } 667 668 669 void Assembler::link_to(Label* L, Label* appendix) { 670 if (appendix->is_linked()) { 671 if (L->is_linked()) { 672 // Append appendix to L's list. 673 int fixup_pos; 674 int link = L->pos(); 675 do { 676 fixup_pos = link; 677 link = target_at(fixup_pos); 678 } while (link > 0); 679 ASSERT(link == kEndOfChain); 680 target_at_put(fixup_pos, appendix->pos()); 681 } else { 682 // L is empty, simply use appendix. 683 *L = *appendix; 684 } 685 } 686 appendix->Unuse(); // appendix should not be used anymore 687 } 688 689 690 void Assembler::bind(Label* L) { 691 ASSERT(!L->is_bound()); // label can only be bound once 692 bind_to(L, pc_offset()); 693 } 694 695 696 void Assembler::next(Label* L) { 697 ASSERT(L->is_linked()); 698 int link = target_at(L->pos()); 699 if (link == kEndOfChain) { 700 L->Unuse(); 701 } else { 702 ASSERT(link >= 0); 703 L->link_to(link); 704 } 705 } 706 707 708 static Instr EncodeMovwImmediate(uint32_t immediate) { 709 ASSERT(immediate < 0x10000); 710 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); 711 } 712 713 714 // Low-level code emission routines depending on the addressing mode. 715 // If this returns true then you have to use the rotate_imm and immed_8 716 // that it returns, because it may have already changed the instruction 717 // to match them! 718 static bool fits_shifter(uint32_t imm32, 719 uint32_t* rotate_imm, 720 uint32_t* immed_8, 721 Instr* instr) { 722 // imm32 must be unsigned. 723 for (int rot = 0; rot < 16; rot++) { 724 uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot)); 725 if ((imm8 <= 0xff)) { 726 *rotate_imm = rot; 727 *immed_8 = imm8; 728 return true; 729 } 730 } 731 // If the opcode is one with a complementary version and the complementary 732 // immediate fits, change the opcode. 733 if (instr != NULL) { 734 if ((*instr & kMovMvnMask) == kMovMvnPattern) { 735 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { 736 *instr ^= kMovMvnFlip; 737 return true; 738 } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) { 739 if (CpuFeatures::IsSupported(ARMv7)) { 740 if (imm32 < 0x10000) { 741 *instr ^= kMovwLeaveCCFlip; 742 *instr |= EncodeMovwImmediate(imm32); 743 *rotate_imm = *immed_8 = 0; // Not used for movw. 744 return true; 745 } 746 } 747 } 748 } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) { 749 if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) { 750 *instr ^= kCmpCmnFlip; 751 return true; 752 } 753 } else { 754 Instr alu_insn = (*instr & kALUMask); 755 if (alu_insn == ADD || 756 alu_insn == SUB) { 757 if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) { 758 *instr ^= kAddSubFlip; 759 return true; 760 } 761 } else if (alu_insn == AND || 762 alu_insn == BIC) { 763 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { 764 *instr ^= kAndBicFlip; 765 return true; 766 } 767 } 768 } 769 } 770 return false; 771 } 772 773 774 // We have to use the temporary register for things that can be relocated even 775 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction 776 // space. There is no guarantee that the relocated location can be similarly 777 // encoded. 778 bool Operand::must_use_constant_pool() const { 779 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { 780 #ifdef DEBUG 781 if (!Serializer::enabled()) { 782 Serializer::TooLateToEnableNow(); 783 } 784 #endif // def DEBUG 785 return Serializer::enabled(); 786 } else if (rmode_ == RelocInfo::NONE) { 787 return false; 788 } 789 return true; 790 } 791 792 793 bool Operand::is_single_instruction(Instr instr) const { 794 if (rm_.is_valid()) return true; 795 uint32_t dummy1, dummy2; 796 if (must_use_constant_pool() || 797 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { 798 // The immediate operand cannot be encoded as a shifter operand, or use of 799 // constant pool is required. For a mov instruction not setting the 800 // condition code additional instruction conventions can be used. 801 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set 802 if (must_use_constant_pool() || 803 !CpuFeatures::IsSupported(ARMv7)) { 804 // mov instruction will be an ldr from constant pool (one instruction). 805 return true; 806 } else { 807 // mov instruction will be a mov or movw followed by movt (two 808 // instructions). 809 return false; 810 } 811 } else { 812 // If this is not a mov or mvn instruction there will always an additional 813 // instructions - either mov or ldr. The mov might actually be two 814 // instructions mov or movw followed by movt so including the actual 815 // instruction two or three instructions will be generated. 816 return false; 817 } 818 } else { 819 // No use of constant pool and the immediate operand can be encoded as a 820 // shifter operand. 821 return true; 822 } 823 } 824 825 826 void Assembler::addrmod1(Instr instr, 827 Register rn, 828 Register rd, 829 const Operand& x) { 830 CheckBuffer(); 831 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); 832 if (!x.rm_.is_valid()) { 833 // Immediate. 834 uint32_t rotate_imm; 835 uint32_t immed_8; 836 if (x.must_use_constant_pool() || 837 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { 838 // The immediate operand cannot be encoded as a shifter operand, so load 839 // it first to register ip and change the original instruction to use ip. 840 // However, if the original instruction is a 'mov rd, x' (not setting the 841 // condition code), then replace it with a 'ldr rd, [pc]'. 842 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed 843 Condition cond = Instruction::ConditionField(instr); 844 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set 845 if (x.must_use_constant_pool() || 846 !CpuFeatures::IsSupported(ARMv7)) { 847 RecordRelocInfo(x.rmode_, x.imm32_); 848 ldr(rd, MemOperand(pc, 0), cond); 849 } else { 850 // Will probably use movw, will certainly not use constant pool. 851 mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond); 852 movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond); 853 } 854 } else { 855 // If this is not a mov or mvn instruction we may still be able to avoid 856 // a constant pool entry by using mvn or movw. 857 if (!x.must_use_constant_pool() && 858 (instr & kMovMvnMask) != kMovMvnPattern) { 859 mov(ip, x, LeaveCC, cond); 860 } else { 861 RecordRelocInfo(x.rmode_, x.imm32_); 862 ldr(ip, MemOperand(pc, 0), cond); 863 } 864 addrmod1(instr, rn, rd, Operand(ip)); 865 } 866 return; 867 } 868 instr |= I | rotate_imm*B8 | immed_8; 869 } else if (!x.rs_.is_valid()) { 870 // Immediate shift. 871 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 872 } else { 873 // Register shift. 874 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); 875 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); 876 } 877 emit(instr | rn.code()*B16 | rd.code()*B12); 878 if (rn.is(pc) || x.rm_.is(pc)) { 879 // Block constant pool emission for one instruction after reading pc. 880 BlockConstPoolFor(1); 881 } 882 } 883 884 885 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) { 886 ASSERT((instr & ~(kCondMask | B | L)) == B26); 887 int am = x.am_; 888 if (!x.rm_.is_valid()) { 889 // Immediate offset. 890 int offset_12 = x.offset_; 891 if (offset_12 < 0) { 892 offset_12 = -offset_12; 893 am ^= U; 894 } 895 if (!is_uint12(offset_12)) { 896 // Immediate offset cannot be encoded, load it first to register ip 897 // rn (and rd in a load) should never be ip, or will be trashed. 898 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 899 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr)); 900 addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_)); 901 return; 902 } 903 ASSERT(offset_12 >= 0); // no masking needed 904 instr |= offset_12; 905 } else { 906 // Register offset (shift_imm_ and shift_op_ are 0) or scaled 907 // register offset the constructors make sure than both shift_imm_ 908 // and shift_op_ are initialized. 909 ASSERT(!x.rm_.is(pc)); 910 instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 911 } 912 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 913 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 914 } 915 916 917 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) { 918 ASSERT((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7)); 919 ASSERT(x.rn_.is_valid()); 920 int am = x.am_; 921 if (!x.rm_.is_valid()) { 922 // Immediate offset. 923 int offset_8 = x.offset_; 924 if (offset_8 < 0) { 925 offset_8 = -offset_8; 926 am ^= U; 927 } 928 if (!is_uint8(offset_8)) { 929 // Immediate offset cannot be encoded, load it first to register ip 930 // rn (and rd in a load) should never be ip, or will be trashed. 931 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 932 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr)); 933 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 934 return; 935 } 936 ASSERT(offset_8 >= 0); // no masking needed 937 instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf); 938 } else if (x.shift_imm_ != 0) { 939 // Scaled register offset not supported, load index first 940 // rn (and rd in a load) should never be ip, or will be trashed. 941 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 942 mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC, 943 Instruction::ConditionField(instr)); 944 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 945 return; 946 } else { 947 // Register offset. 948 ASSERT((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback 949 instr |= x.rm_.code(); 950 } 951 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 952 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 953 } 954 955 956 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) { 957 ASSERT((instr & ~(kCondMask | P | U | W | L)) == B27); 958 ASSERT(rl != 0); 959 ASSERT(!rn.is(pc)); 960 emit(instr | rn.code()*B16 | rl); 961 } 962 963 964 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) { 965 // Unindexed addressing is not encoded by this function. 966 ASSERT_EQ((B27 | B26), 967 (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L))); 968 ASSERT(x.rn_.is_valid() && !x.rm_.is_valid()); 969 int am = x.am_; 970 int offset_8 = x.offset_; 971 ASSERT((offset_8 & 3) == 0); // offset must be an aligned word offset 972 offset_8 >>= 2; 973 if (offset_8 < 0) { 974 offset_8 = -offset_8; 975 am ^= U; 976 } 977 ASSERT(is_uint8(offset_8)); // unsigned word offset must fit in a byte 978 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 979 980 // Post-indexed addressing requires W == 1; different than in addrmod2/3. 981 if ((am & P) == 0) 982 am |= W; 983 984 ASSERT(offset_8 >= 0); // no masking needed 985 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); 986 } 987 988 989 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 990 int target_pos; 991 if (L->is_bound()) { 992 target_pos = L->pos(); 993 } else { 994 if (L->is_linked()) { 995 target_pos = L->pos(); // L's link 996 } else { 997 target_pos = kEndOfChain; 998 } 999 L->link_to(pc_offset()); 1000 } 1001 1002 // Block the emission of the constant pool, since the branch instruction must 1003 // be emitted at the pc offset recorded by the label. 1004 BlockConstPoolFor(1); 1005 return target_pos - (pc_offset() + kPcLoadDelta); 1006 } 1007 1008 1009 void Assembler::label_at_put(Label* L, int at_offset) { 1010 int target_pos; 1011 if (L->is_bound()) { 1012 target_pos = L->pos(); 1013 } else { 1014 if (L->is_linked()) { 1015 target_pos = L->pos(); // L's link 1016 } else { 1017 target_pos = kEndOfChain; 1018 } 1019 L->link_to(at_offset); 1020 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 1021 } 1022 } 1023 1024 1025 // Branch instructions. 1026 void Assembler::b(int branch_offset, Condition cond) { 1027 ASSERT((branch_offset & 3) == 0); 1028 int imm24 = branch_offset >> 2; 1029 ASSERT(is_int24(imm24)); 1030 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); 1031 1032 if (cond == al) { 1033 // Dead code is a good location to emit the constant pool. 1034 CheckConstPool(false, false); 1035 } 1036 } 1037 1038 1039 void Assembler::bl(int branch_offset, Condition cond) { 1040 positions_recorder()->WriteRecordedPositions(); 1041 ASSERT((branch_offset & 3) == 0); 1042 int imm24 = branch_offset >> 2; 1043 ASSERT(is_int24(imm24)); 1044 emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask)); 1045 } 1046 1047 1048 void Assembler::blx(int branch_offset) { // v5 and above 1049 positions_recorder()->WriteRecordedPositions(); 1050 ASSERT((branch_offset & 1) == 0); 1051 int h = ((branch_offset & 2) >> 1)*B24; 1052 int imm24 = branch_offset >> 2; 1053 ASSERT(is_int24(imm24)); 1054 emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask)); 1055 } 1056 1057 1058 void Assembler::blx(Register target, Condition cond) { // v5 and above 1059 positions_recorder()->WriteRecordedPositions(); 1060 ASSERT(!target.is(pc)); 1061 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code()); 1062 } 1063 1064 1065 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t 1066 positions_recorder()->WriteRecordedPositions(); 1067 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged 1068 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code()); 1069 } 1070 1071 1072 // Data-processing instructions. 1073 1074 void Assembler::and_(Register dst, Register src1, const Operand& src2, 1075 SBit s, Condition cond) { 1076 addrmod1(cond | AND | s, src1, dst, src2); 1077 } 1078 1079 1080 void Assembler::eor(Register dst, Register src1, const Operand& src2, 1081 SBit s, Condition cond) { 1082 addrmod1(cond | EOR | s, src1, dst, src2); 1083 } 1084 1085 1086 void Assembler::sub(Register dst, Register src1, const Operand& src2, 1087 SBit s, Condition cond) { 1088 addrmod1(cond | SUB | s, src1, dst, src2); 1089 } 1090 1091 1092 void Assembler::rsb(Register dst, Register src1, const Operand& src2, 1093 SBit s, Condition cond) { 1094 addrmod1(cond | RSB | s, src1, dst, src2); 1095 } 1096 1097 1098 void Assembler::add(Register dst, Register src1, const Operand& src2, 1099 SBit s, Condition cond) { 1100 addrmod1(cond | ADD | s, src1, dst, src2); 1101 } 1102 1103 1104 void Assembler::adc(Register dst, Register src1, const Operand& src2, 1105 SBit s, Condition cond) { 1106 addrmod1(cond | ADC | s, src1, dst, src2); 1107 } 1108 1109 1110 void Assembler::sbc(Register dst, Register src1, const Operand& src2, 1111 SBit s, Condition cond) { 1112 addrmod1(cond | SBC | s, src1, dst, src2); 1113 } 1114 1115 1116 void Assembler::rsc(Register dst, Register src1, const Operand& src2, 1117 SBit s, Condition cond) { 1118 addrmod1(cond | RSC | s, src1, dst, src2); 1119 } 1120 1121 1122 void Assembler::tst(Register src1, const Operand& src2, Condition cond) { 1123 addrmod1(cond | TST | S, src1, r0, src2); 1124 } 1125 1126 1127 void Assembler::teq(Register src1, const Operand& src2, Condition cond) { 1128 addrmod1(cond | TEQ | S, src1, r0, src2); 1129 } 1130 1131 1132 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) { 1133 addrmod1(cond | CMP | S, src1, r0, src2); 1134 } 1135 1136 1137 void Assembler::cmp_raw_immediate( 1138 Register src, int raw_immediate, Condition cond) { 1139 ASSERT(is_uint12(raw_immediate)); 1140 emit(cond | I | CMP | S | src.code() << 16 | raw_immediate); 1141 } 1142 1143 1144 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) { 1145 addrmod1(cond | CMN | S, src1, r0, src2); 1146 } 1147 1148 1149 void Assembler::orr(Register dst, Register src1, const Operand& src2, 1150 SBit s, Condition cond) { 1151 addrmod1(cond | ORR | s, src1, dst, src2); 1152 } 1153 1154 1155 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { 1156 if (dst.is(pc)) { 1157 positions_recorder()->WriteRecordedPositions(); 1158 } 1159 // Don't allow nop instructions in the form mov rn, rn to be generated using 1160 // the mov instruction. They must be generated using nop(int/NopMarkerTypes) 1161 // or MarkCode(int/NopMarkerTypes) pseudo instructions. 1162 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); 1163 addrmod1(cond | MOV | s, r0, dst, src); 1164 } 1165 1166 1167 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { 1168 ASSERT(immediate < 0x10000); 1169 mov(reg, Operand(immediate), LeaveCC, cond); 1170 } 1171 1172 1173 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) { 1174 emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); 1175 } 1176 1177 1178 void Assembler::bic(Register dst, Register src1, const Operand& src2, 1179 SBit s, Condition cond) { 1180 addrmod1(cond | BIC | s, src1, dst, src2); 1181 } 1182 1183 1184 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { 1185 addrmod1(cond | MVN | s, r0, dst, src); 1186 } 1187 1188 1189 // Multiply instructions. 1190 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, 1191 SBit s, Condition cond) { 1192 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 1193 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | 1194 src2.code()*B8 | B7 | B4 | src1.code()); 1195 } 1196 1197 1198 void Assembler::mul(Register dst, Register src1, Register src2, 1199 SBit s, Condition cond) { 1200 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1201 // dst goes in bits 16-19 for this instruction! 1202 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); 1203 } 1204 1205 1206 void Assembler::smlal(Register dstL, 1207 Register dstH, 1208 Register src1, 1209 Register src2, 1210 SBit s, 1211 Condition cond) { 1212 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1213 ASSERT(!dstL.is(dstH)); 1214 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1215 src2.code()*B8 | B7 | B4 | src1.code()); 1216 } 1217 1218 1219 void Assembler::smull(Register dstL, 1220 Register dstH, 1221 Register src1, 1222 Register src2, 1223 SBit s, 1224 Condition cond) { 1225 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1226 ASSERT(!dstL.is(dstH)); 1227 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | 1228 src2.code()*B8 | B7 | B4 | src1.code()); 1229 } 1230 1231 1232 void Assembler::umlal(Register dstL, 1233 Register dstH, 1234 Register src1, 1235 Register src2, 1236 SBit s, 1237 Condition cond) { 1238 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1239 ASSERT(!dstL.is(dstH)); 1240 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1241 src2.code()*B8 | B7 | B4 | src1.code()); 1242 } 1243 1244 1245 void Assembler::umull(Register dstL, 1246 Register dstH, 1247 Register src1, 1248 Register src2, 1249 SBit s, 1250 Condition cond) { 1251 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1252 ASSERT(!dstL.is(dstH)); 1253 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | 1254 src2.code()*B8 | B7 | B4 | src1.code()); 1255 } 1256 1257 1258 // Miscellaneous arithmetic instructions. 1259 void Assembler::clz(Register dst, Register src, Condition cond) { 1260 // v5 and above. 1261 ASSERT(!dst.is(pc) && !src.is(pc)); 1262 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | 1263 15*B8 | CLZ | src.code()); 1264 } 1265 1266 1267 // Saturating instructions. 1268 1269 // Unsigned saturate. 1270 void Assembler::usat(Register dst, 1271 int satpos, 1272 const Operand& src, 1273 Condition cond) { 1274 // v6 and above. 1275 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1276 ASSERT(!dst.is(pc) && !src.rm_.is(pc)); 1277 ASSERT((satpos >= 0) && (satpos <= 31)); 1278 ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL)); 1279 ASSERT(src.rs_.is(no_reg)); 1280 1281 int sh = 0; 1282 if (src.shift_op_ == ASR) { 1283 sh = 1; 1284 } 1285 1286 emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 | 1287 src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code()); 1288 } 1289 1290 1291 // Bitfield manipulation instructions. 1292 1293 // Unsigned bit field extract. 1294 // Extracts #width adjacent bits from position #lsb in a register, and 1295 // writes them to the low bits of a destination register. 1296 // ubfx dst, src, #lsb, #width 1297 void Assembler::ubfx(Register dst, 1298 Register src, 1299 int lsb, 1300 int width, 1301 Condition cond) { 1302 // v7 and above. 1303 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1304 ASSERT(!dst.is(pc) && !src.is(pc)); 1305 ASSERT((lsb >= 0) && (lsb <= 31)); 1306 ASSERT((width >= 1) && (width <= (32 - lsb))); 1307 emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 | 1308 lsb*B7 | B6 | B4 | src.code()); 1309 } 1310 1311 1312 // Signed bit field extract. 1313 // Extracts #width adjacent bits from position #lsb in a register, and 1314 // writes them to the low bits of a destination register. The extracted 1315 // value is sign extended to fill the destination register. 1316 // sbfx dst, src, #lsb, #width 1317 void Assembler::sbfx(Register dst, 1318 Register src, 1319 int lsb, 1320 int width, 1321 Condition cond) { 1322 // v7 and above. 1323 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1324 ASSERT(!dst.is(pc) && !src.is(pc)); 1325 ASSERT((lsb >= 0) && (lsb <= 31)); 1326 ASSERT((width >= 1) && (width <= (32 - lsb))); 1327 emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 | 1328 lsb*B7 | B6 | B4 | src.code()); 1329 } 1330 1331 1332 // Bit field clear. 1333 // Sets #width adjacent bits at position #lsb in the destination register 1334 // to zero, preserving the value of the other bits. 1335 // bfc dst, #lsb, #width 1336 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) { 1337 // v7 and above. 1338 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1339 ASSERT(!dst.is(pc)); 1340 ASSERT((lsb >= 0) && (lsb <= 31)); 1341 ASSERT((width >= 1) && (width <= (32 - lsb))); 1342 int msb = lsb + width - 1; 1343 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf); 1344 } 1345 1346 1347 // Bit field insert. 1348 // Inserts #width adjacent bits from the low bits of the source register 1349 // into position #lsb of the destination register. 1350 // bfi dst, src, #lsb, #width 1351 void Assembler::bfi(Register dst, 1352 Register src, 1353 int lsb, 1354 int width, 1355 Condition cond) { 1356 // v7 and above. 1357 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1358 ASSERT(!dst.is(pc) && !src.is(pc)); 1359 ASSERT((lsb >= 0) && (lsb <= 31)); 1360 ASSERT((width >= 1) && (width <= (32 - lsb))); 1361 int msb = lsb + width - 1; 1362 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 1363 src.code()); 1364 } 1365 1366 1367 // Status register access instructions. 1368 void Assembler::mrs(Register dst, SRegister s, Condition cond) { 1369 ASSERT(!dst.is(pc)); 1370 emit(cond | B24 | s | 15*B16 | dst.code()*B12); 1371 } 1372 1373 1374 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, 1375 Condition cond) { 1376 ASSERT(fields >= B16 && fields < B20); // at least one field set 1377 Instr instr; 1378 if (!src.rm_.is_valid()) { 1379 // Immediate. 1380 uint32_t rotate_imm; 1381 uint32_t immed_8; 1382 if (src.must_use_constant_pool() || 1383 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { 1384 // Immediate operand cannot be encoded, load it first to register ip. 1385 RecordRelocInfo(src.rmode_, src.imm32_); 1386 ldr(ip, MemOperand(pc, 0), cond); 1387 msr(fields, Operand(ip), cond); 1388 return; 1389 } 1390 instr = I | rotate_imm*B8 | immed_8; 1391 } else { 1392 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed 1393 instr = src.rm_.code(); 1394 } 1395 emit(cond | instr | B24 | B21 | fields | 15*B12); 1396 } 1397 1398 1399 // Load/Store instructions. 1400 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { 1401 if (dst.is(pc)) { 1402 positions_recorder()->WriteRecordedPositions(); 1403 } 1404 addrmod2(cond | B26 | L, dst, src); 1405 } 1406 1407 1408 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { 1409 addrmod2(cond | B26, src, dst); 1410 } 1411 1412 1413 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { 1414 addrmod2(cond | B26 | B | L, dst, src); 1415 } 1416 1417 1418 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { 1419 addrmod2(cond | B26 | B, src, dst); 1420 } 1421 1422 1423 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) { 1424 addrmod3(cond | L | B7 | H | B4, dst, src); 1425 } 1426 1427 1428 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) { 1429 addrmod3(cond | B7 | H | B4, src, dst); 1430 } 1431 1432 1433 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) { 1434 addrmod3(cond | L | B7 | S6 | B4, dst, src); 1435 } 1436 1437 1438 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { 1439 addrmod3(cond | L | B7 | S6 | H | B4, dst, src); 1440 } 1441 1442 1443 void Assembler::ldrd(Register dst1, Register dst2, 1444 const MemOperand& src, Condition cond) { 1445 ASSERT(CpuFeatures::IsEnabled(ARMv7)); 1446 ASSERT(src.rm().is(no_reg)); 1447 ASSERT(!dst1.is(lr)); // r14. 1448 ASSERT_EQ(0, dst1.code() % 2); 1449 ASSERT_EQ(dst1.code() + 1, dst2.code()); 1450 addrmod3(cond | B7 | B6 | B4, dst1, src); 1451 } 1452 1453 1454 void Assembler::strd(Register src1, Register src2, 1455 const MemOperand& dst, Condition cond) { 1456 ASSERT(dst.rm().is(no_reg)); 1457 ASSERT(!src1.is(lr)); // r14. 1458 ASSERT_EQ(0, src1.code() % 2); 1459 ASSERT_EQ(src1.code() + 1, src2.code()); 1460 ASSERT(CpuFeatures::IsEnabled(ARMv7)); 1461 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); 1462 } 1463 1464 // Load/Store multiple instructions. 1465 void Assembler::ldm(BlockAddrMode am, 1466 Register base, 1467 RegList dst, 1468 Condition cond) { 1469 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. 1470 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); 1471 1472 addrmod4(cond | B27 | am | L, base, dst); 1473 1474 // Emit the constant pool after a function return implemented by ldm ..{..pc}. 1475 if (cond == al && (dst & pc.bit()) != 0) { 1476 // There is a slight chance that the ldm instruction was actually a call, 1477 // in which case it would be wrong to return into the constant pool; we 1478 // recognize this case by checking if the emission of the pool was blocked 1479 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is 1480 // the case, we emit a jump over the pool. 1481 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); 1482 } 1483 } 1484 1485 1486 void Assembler::stm(BlockAddrMode am, 1487 Register base, 1488 RegList src, 1489 Condition cond) { 1490 addrmod4(cond | B27 | am, base, src); 1491 } 1492 1493 1494 // Exception-generating instructions and debugging support. 1495 // Stops with a non-negative code less than kNumOfWatchedStops support 1496 // enabling/disabling and a counter feature. See simulator-arm.h . 1497 void Assembler::stop(const char* msg, Condition cond, int32_t code) { 1498 #ifndef __arm__ 1499 ASSERT(code >= kDefaultStopCode); 1500 { 1501 // The Simulator will handle the stop instruction and get the message 1502 // address. It expects to find the address just after the svc instruction. 1503 BlockConstPoolScope block_const_pool(this); 1504 if (code >= 0) { 1505 svc(kStopCode + code, cond); 1506 } else { 1507 svc(kStopCode + kMaxStopCode, cond); 1508 } 1509 emit(reinterpret_cast<Instr>(msg)); 1510 } 1511 #else // def __arm__ 1512 #ifdef CAN_USE_ARMV5_INSTRUCTIONS 1513 if (cond != al) { 1514 Label skip; 1515 b(&skip, NegateCondition(cond)); 1516 bkpt(0); 1517 bind(&skip); 1518 } else { 1519 bkpt(0); 1520 } 1521 #else // ndef CAN_USE_ARMV5_INSTRUCTIONS 1522 svc(0x9f0001, cond); 1523 #endif // ndef CAN_USE_ARMV5_INSTRUCTIONS 1524 #endif // def __arm__ 1525 } 1526 1527 1528 void Assembler::bkpt(uint32_t imm16) { // v5 and above 1529 ASSERT(is_uint16(imm16)); 1530 emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf)); 1531 } 1532 1533 1534 void Assembler::svc(uint32_t imm24, Condition cond) { 1535 ASSERT(is_uint24(imm24)); 1536 emit(cond | 15*B24 | imm24); 1537 } 1538 1539 1540 // Coprocessor instructions. 1541 void Assembler::cdp(Coprocessor coproc, 1542 int opcode_1, 1543 CRegister crd, 1544 CRegister crn, 1545 CRegister crm, 1546 int opcode_2, 1547 Condition cond) { 1548 ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2)); 1549 emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 | 1550 crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code()); 1551 } 1552 1553 1554 void Assembler::cdp2(Coprocessor coproc, 1555 int opcode_1, 1556 CRegister crd, 1557 CRegister crn, 1558 CRegister crm, 1559 int opcode_2) { // v5 and above 1560 cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition); 1561 } 1562 1563 1564 void Assembler::mcr(Coprocessor coproc, 1565 int opcode_1, 1566 Register rd, 1567 CRegister crn, 1568 CRegister crm, 1569 int opcode_2, 1570 Condition cond) { 1571 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 1572 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 | 1573 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 1574 } 1575 1576 1577 void Assembler::mcr2(Coprocessor coproc, 1578 int opcode_1, 1579 Register rd, 1580 CRegister crn, 1581 CRegister crm, 1582 int opcode_2) { // v5 and above 1583 mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition); 1584 } 1585 1586 1587 void Assembler::mrc(Coprocessor coproc, 1588 int opcode_1, 1589 Register rd, 1590 CRegister crn, 1591 CRegister crm, 1592 int opcode_2, 1593 Condition cond) { 1594 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 1595 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 | 1596 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 1597 } 1598 1599 1600 void Assembler::mrc2(Coprocessor coproc, 1601 int opcode_1, 1602 Register rd, 1603 CRegister crn, 1604 CRegister crm, 1605 int opcode_2) { // v5 and above 1606 mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition); 1607 } 1608 1609 1610 void Assembler::ldc(Coprocessor coproc, 1611 CRegister crd, 1612 const MemOperand& src, 1613 LFlag l, 1614 Condition cond) { 1615 addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src); 1616 } 1617 1618 1619 void Assembler::ldc(Coprocessor coproc, 1620 CRegister crd, 1621 Register rn, 1622 int option, 1623 LFlag l, 1624 Condition cond) { 1625 // Unindexed addressing. 1626 ASSERT(is_uint8(option)); 1627 emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 | 1628 coproc*B8 | (option & 255)); 1629 } 1630 1631 1632 void Assembler::ldc2(Coprocessor coproc, 1633 CRegister crd, 1634 const MemOperand& src, 1635 LFlag l) { // v5 and above 1636 ldc(coproc, crd, src, l, kSpecialCondition); 1637 } 1638 1639 1640 void Assembler::ldc2(Coprocessor coproc, 1641 CRegister crd, 1642 Register rn, 1643 int option, 1644 LFlag l) { // v5 and above 1645 ldc(coproc, crd, rn, option, l, kSpecialCondition); 1646 } 1647 1648 1649 // Support for VFP. 1650 1651 void Assembler::vldr(const DwVfpRegister dst, 1652 const Register base, 1653 int offset, 1654 const Condition cond) { 1655 // Ddst = MEM(Rbase + offset). 1656 // Instruction details available in ARM DDI 0406A, A8-628. 1657 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | 1658 // Vdst(15-12) | 1011(11-8) | offset 1659 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1660 int u = 1; 1661 if (offset < 0) { 1662 offset = -offset; 1663 u = 0; 1664 } 1665 1666 ASSERT(offset >= 0); 1667 if ((offset % 4) == 0 && (offset / 4) < 256) { 1668 emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | 1669 0xB*B8 | ((offset / 4) & 255)); 1670 } else { 1671 // Larger offsets must be handled by computing the correct address 1672 // in the ip register. 1673 ASSERT(!base.is(ip)); 1674 if (u == 1) { 1675 add(ip, base, Operand(offset)); 1676 } else { 1677 sub(ip, base, Operand(offset)); 1678 } 1679 emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8); 1680 } 1681 } 1682 1683 1684 void Assembler::vldr(const DwVfpRegister dst, 1685 const MemOperand& operand, 1686 const Condition cond) { 1687 ASSERT(!operand.rm().is_valid()); 1688 ASSERT(operand.am_ == Offset); 1689 vldr(dst, operand.rn(), operand.offset(), cond); 1690 } 1691 1692 1693 void Assembler::vldr(const SwVfpRegister dst, 1694 const Register base, 1695 int offset, 1696 const Condition cond) { 1697 // Sdst = MEM(Rbase + offset). 1698 // Instruction details available in ARM DDI 0406A, A8-628. 1699 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | 1700 // Vdst(15-12) | 1010(11-8) | offset 1701 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1702 int u = 1; 1703 if (offset < 0) { 1704 offset = -offset; 1705 u = 0; 1706 } 1707 int sd, d; 1708 dst.split_code(&sd, &d); 1709 ASSERT(offset >= 0); 1710 1711 if ((offset % 4) == 0 && (offset / 4) < 256) { 1712 emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 | 1713 0xA*B8 | ((offset / 4) & 255)); 1714 } else { 1715 // Larger offsets must be handled by computing the correct address 1716 // in the ip register. 1717 ASSERT(!base.is(ip)); 1718 if (u == 1) { 1719 add(ip, base, Operand(offset)); 1720 } else { 1721 sub(ip, base, Operand(offset)); 1722 } 1723 emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); 1724 } 1725 } 1726 1727 1728 void Assembler::vldr(const SwVfpRegister dst, 1729 const MemOperand& operand, 1730 const Condition cond) { 1731 ASSERT(!operand.rm().is_valid()); 1732 ASSERT(operand.am_ == Offset); 1733 vldr(dst, operand.rn(), operand.offset(), cond); 1734 } 1735 1736 1737 void Assembler::vstr(const DwVfpRegister src, 1738 const Register base, 1739 int offset, 1740 const Condition cond) { 1741 // MEM(Rbase + offset) = Dsrc. 1742 // Instruction details available in ARM DDI 0406A, A8-786. 1743 // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) | 1744 // Vsrc(15-12) | 1011(11-8) | (offset/4) 1745 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1746 int u = 1; 1747 if (offset < 0) { 1748 offset = -offset; 1749 u = 0; 1750 } 1751 ASSERT(offset >= 0); 1752 if ((offset % 4) == 0 && (offset / 4) < 256) { 1753 emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | 1754 0xB*B8 | ((offset / 4) & 255)); 1755 } else { 1756 // Larger offsets must be handled by computing the correct address 1757 // in the ip register. 1758 ASSERT(!base.is(ip)); 1759 if (u == 1) { 1760 add(ip, base, Operand(offset)); 1761 } else { 1762 sub(ip, base, Operand(offset)); 1763 } 1764 emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8); 1765 } 1766 } 1767 1768 1769 void Assembler::vstr(const DwVfpRegister src, 1770 const MemOperand& operand, 1771 const Condition cond) { 1772 ASSERT(!operand.rm().is_valid()); 1773 ASSERT(operand.am_ == Offset); 1774 vstr(src, operand.rn(), operand.offset(), cond); 1775 } 1776 1777 1778 void Assembler::vstr(const SwVfpRegister src, 1779 const Register base, 1780 int offset, 1781 const Condition cond) { 1782 // MEM(Rbase + offset) = SSrc. 1783 // Instruction details available in ARM DDI 0406A, A8-786. 1784 // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) | 1785 // Vdst(15-12) | 1010(11-8) | (offset/4) 1786 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1787 int u = 1; 1788 if (offset < 0) { 1789 offset = -offset; 1790 u = 0; 1791 } 1792 int sd, d; 1793 src.split_code(&sd, &d); 1794 ASSERT(offset >= 0); 1795 if ((offset % 4) == 0 && (offset / 4) < 256) { 1796 emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | 1797 0xA*B8 | ((offset / 4) & 255)); 1798 } else { 1799 // Larger offsets must be handled by computing the correct address 1800 // in the ip register. 1801 ASSERT(!base.is(ip)); 1802 if (u == 1) { 1803 add(ip, base, Operand(offset)); 1804 } else { 1805 sub(ip, base, Operand(offset)); 1806 } 1807 emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); 1808 } 1809 } 1810 1811 1812 void Assembler::vstr(const SwVfpRegister src, 1813 const MemOperand& operand, 1814 const Condition cond) { 1815 ASSERT(!operand.rm().is_valid()); 1816 ASSERT(operand.am_ == Offset); 1817 vldr(src, operand.rn(), operand.offset(), cond); 1818 } 1819 1820 1821 void Assembler::vldm(BlockAddrMode am, 1822 Register base, 1823 DwVfpRegister first, 1824 DwVfpRegister last, 1825 Condition cond) { 1826 // Instruction details available in ARM DDI 0406A, A8-626. 1827 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | 1828 // first(15-12) | 1010(11-8) | (count * 2) 1829 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1830 ASSERT_LE(first.code(), last.code()); 1831 ASSERT(am == ia || am == ia_w || am == db_w); 1832 ASSERT(!base.is(pc)); 1833 1834 int sd, d; 1835 first.split_code(&sd, &d); 1836 int count = last.code() - first.code() + 1; 1837 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | 1838 0xB*B8 | count*2); 1839 } 1840 1841 1842 void Assembler::vstm(BlockAddrMode am, 1843 Register base, 1844 DwVfpRegister first, 1845 DwVfpRegister last, 1846 Condition cond) { 1847 // Instruction details available in ARM DDI 0406A, A8-784. 1848 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | 1849 // first(15-12) | 1011(11-8) | (count * 2) 1850 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1851 ASSERT_LE(first.code(), last.code()); 1852 ASSERT(am == ia || am == ia_w || am == db_w); 1853 ASSERT(!base.is(pc)); 1854 1855 int sd, d; 1856 first.split_code(&sd, &d); 1857 int count = last.code() - first.code() + 1; 1858 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 | 1859 0xB*B8 | count*2); 1860 } 1861 1862 void Assembler::vldm(BlockAddrMode am, 1863 Register base, 1864 SwVfpRegister first, 1865 SwVfpRegister last, 1866 Condition cond) { 1867 // Instruction details available in ARM DDI 0406A, A8-626. 1868 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | 1869 // first(15-12) | 1010(11-8) | (count/2) 1870 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1871 ASSERT_LE(first.code(), last.code()); 1872 ASSERT(am == ia || am == ia_w || am == db_w); 1873 ASSERT(!base.is(pc)); 1874 1875 int sd, d; 1876 first.split_code(&sd, &d); 1877 int count = last.code() - first.code() + 1; 1878 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | 1879 0xA*B8 | count); 1880 } 1881 1882 1883 void Assembler::vstm(BlockAddrMode am, 1884 Register base, 1885 SwVfpRegister first, 1886 SwVfpRegister last, 1887 Condition cond) { 1888 // Instruction details available in ARM DDI 0406A, A8-784. 1889 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | 1890 // first(15-12) | 1011(11-8) | (count/2) 1891 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1892 ASSERT_LE(first.code(), last.code()); 1893 ASSERT(am == ia || am == ia_w || am == db_w); 1894 ASSERT(!base.is(pc)); 1895 1896 int sd, d; 1897 first.split_code(&sd, &d); 1898 int count = last.code() - first.code() + 1; 1899 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 | 1900 0xA*B8 | count); 1901 } 1902 1903 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) { 1904 uint64_t i; 1905 memcpy(&i, &d, 8); 1906 1907 *lo = i & 0xffffffff; 1908 *hi = i >> 32; 1909 } 1910 1911 // Only works for little endian floating point formats. 1912 // We don't support VFP on the mixed endian floating point platform. 1913 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) { 1914 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1915 1916 // VMOV can accept an immediate of the form: 1917 // 1918 // +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7 1919 // 1920 // The immediate is encoded using an 8-bit quantity, comprised of two 1921 // 4-bit fields. For an 8-bit immediate of the form: 1922 // 1923 // [abcdefgh] 1924 // 1925 // where a is the MSB and h is the LSB, an immediate 64-bit double can be 1926 // created of the form: 1927 // 1928 // [aBbbbbbb,bbcdefgh,00000000,00000000, 1929 // 00000000,00000000,00000000,00000000] 1930 // 1931 // where B = ~b. 1932 // 1933 1934 uint32_t lo, hi; 1935 DoubleAsTwoUInt32(d, &lo, &hi); 1936 1937 // The most obvious constraint is the long block of zeroes. 1938 if ((lo != 0) || ((hi & 0xffff) != 0)) { 1939 return false; 1940 } 1941 1942 // Bits 62:55 must be all clear or all set. 1943 if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) { 1944 return false; 1945 } 1946 1947 // Bit 63 must be NOT bit 62. 1948 if (((hi ^ (hi << 1)) & (0x40000000)) == 0) { 1949 return false; 1950 } 1951 1952 // Create the encoded immediate in the form: 1953 // [00000000,0000abcd,00000000,0000efgh] 1954 *encoding = (hi >> 16) & 0xf; // Low nybble. 1955 *encoding |= (hi >> 4) & 0x70000; // Low three bits of the high nybble. 1956 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. 1957 1958 return true; 1959 } 1960 1961 1962 void Assembler::vmov(const DwVfpRegister dst, 1963 double imm, 1964 const Condition cond) { 1965 // Dd = immediate 1966 // Instruction details available in ARM DDI 0406B, A8-640. 1967 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1968 1969 uint32_t enc; 1970 if (FitsVMOVDoubleImmediate(imm, &enc)) { 1971 // The double can be encoded in the instruction. 1972 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc); 1973 } else { 1974 // Synthesise the double from ARM immediates. This could be implemented 1975 // using vldr from a constant pool. 1976 uint32_t lo, hi; 1977 DoubleAsTwoUInt32(imm, &lo, &hi); 1978 1979 if (lo == hi) { 1980 // If the lo and hi parts of the double are equal, the literal is easier 1981 // to create. This is the case with 0.0. 1982 mov(ip, Operand(lo)); 1983 vmov(dst, ip, ip); 1984 } else { 1985 // Move the low part of the double into the lower of the corresponsing S 1986 // registers of D register dst. 1987 mov(ip, Operand(lo)); 1988 vmov(dst.low(), ip, cond); 1989 1990 // Move the high part of the double into the higher of the corresponsing S 1991 // registers of D register dst. 1992 mov(ip, Operand(hi)); 1993 vmov(dst.high(), ip, cond); 1994 } 1995 } 1996 } 1997 1998 1999 void Assembler::vmov(const SwVfpRegister dst, 2000 const SwVfpRegister src, 2001 const Condition cond) { 2002 // Sd = Sm 2003 // Instruction details available in ARM DDI 0406B, A8-642. 2004 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2005 int sd, d, sm, m; 2006 dst.split_code(&sd, &d); 2007 src.split_code(&sm, &m); 2008 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); 2009 } 2010 2011 2012 void Assembler::vmov(const DwVfpRegister dst, 2013 const DwVfpRegister src, 2014 const Condition cond) { 2015 // Dd = Dm 2016 // Instruction details available in ARM DDI 0406B, A8-642. 2017 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2018 emit(cond | 0xE*B24 | 0xB*B20 | 2019 dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code()); 2020 } 2021 2022 2023 void Assembler::vmov(const DwVfpRegister dst, 2024 const Register src1, 2025 const Register src2, 2026 const Condition cond) { 2027 // Dm = <Rt,Rt2>. 2028 // Instruction details available in ARM DDI 0406A, A8-646. 2029 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | 2030 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 2031 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2032 ASSERT(!src1.is(pc) && !src2.is(pc)); 2033 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | 2034 src1.code()*B12 | 0xB*B8 | B4 | dst.code()); 2035 } 2036 2037 2038 void Assembler::vmov(const Register dst1, 2039 const Register dst2, 2040 const DwVfpRegister src, 2041 const Condition cond) { 2042 // <Rt,Rt2> = Dm. 2043 // Instruction details available in ARM DDI 0406A, A8-646. 2044 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | 2045 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 2046 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2047 ASSERT(!dst1.is(pc) && !dst2.is(pc)); 2048 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | 2049 dst1.code()*B12 | 0xB*B8 | B4 | src.code()); 2050 } 2051 2052 2053 void Assembler::vmov(const SwVfpRegister dst, 2054 const Register src, 2055 const Condition cond) { 2056 // Sn = Rt. 2057 // Instruction details available in ARM DDI 0406A, A8-642. 2058 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | 2059 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 2060 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2061 ASSERT(!src.is(pc)); 2062 int sn, n; 2063 dst.split_code(&sn, &n); 2064 emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4); 2065 } 2066 2067 2068 void Assembler::vmov(const Register dst, 2069 const SwVfpRegister src, 2070 const Condition cond) { 2071 // Rt = Sn. 2072 // Instruction details available in ARM DDI 0406A, A8-642. 2073 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | 2074 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 2075 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2076 ASSERT(!dst.is(pc)); 2077 int sn, n; 2078 src.split_code(&sn, &n); 2079 emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4); 2080 } 2081 2082 2083 // Type of data to read from or write to VFP register. 2084 // Used as specifier in generic vcvt instruction. 2085 enum VFPType { S32, U32, F32, F64 }; 2086 2087 2088 static bool IsSignedVFPType(VFPType type) { 2089 switch (type) { 2090 case S32: 2091 return true; 2092 case U32: 2093 return false; 2094 default: 2095 UNREACHABLE(); 2096 return false; 2097 } 2098 } 2099 2100 2101 static bool IsIntegerVFPType(VFPType type) { 2102 switch (type) { 2103 case S32: 2104 case U32: 2105 return true; 2106 case F32: 2107 case F64: 2108 return false; 2109 default: 2110 UNREACHABLE(); 2111 return false; 2112 } 2113 } 2114 2115 2116 static bool IsDoubleVFPType(VFPType type) { 2117 switch (type) { 2118 case F32: 2119 return false; 2120 case F64: 2121 return true; 2122 default: 2123 UNREACHABLE(); 2124 return false; 2125 } 2126 } 2127 2128 2129 // Split five bit reg_code based on size of reg_type. 2130 // 32-bit register codes are Vm:M 2131 // 64-bit register codes are M:Vm 2132 // where Vm is four bits, and M is a single bit. 2133 static void SplitRegCode(VFPType reg_type, 2134 int reg_code, 2135 int* vm, 2136 int* m) { 2137 ASSERT((reg_code >= 0) && (reg_code <= 31)); 2138 if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) { 2139 // 32 bit type. 2140 *m = reg_code & 0x1; 2141 *vm = reg_code >> 1; 2142 } else { 2143 // 64 bit type. 2144 *m = (reg_code & 0x10) >> 4; 2145 *vm = reg_code & 0x0F; 2146 } 2147 } 2148 2149 2150 // Encode vcvt.src_type.dst_type instruction. 2151 static Instr EncodeVCVT(const VFPType dst_type, 2152 const int dst_code, 2153 const VFPType src_type, 2154 const int src_code, 2155 VFPConversionMode mode, 2156 const Condition cond) { 2157 ASSERT(src_type != dst_type); 2158 int D, Vd, M, Vm; 2159 SplitRegCode(src_type, src_code, &Vm, &M); 2160 SplitRegCode(dst_type, dst_code, &Vd, &D); 2161 2162 if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) { 2163 // Conversion between IEEE floating point and 32-bit integer. 2164 // Instruction details available in ARM DDI 0406B, A8.6.295. 2165 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) | 2166 // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2167 ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type)); 2168 2169 int sz, opc2, op; 2170 2171 if (IsIntegerVFPType(dst_type)) { 2172 opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4; 2173 sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0; 2174 op = mode; 2175 } else { 2176 ASSERT(IsIntegerVFPType(src_type)); 2177 opc2 = 0x0; 2178 sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0; 2179 op = IsSignedVFPType(src_type) ? 0x1 : 0x0; 2180 } 2181 2182 return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 | 2183 Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm); 2184 } else { 2185 // Conversion between IEEE double and single precision. 2186 // Instruction details available in ARM DDI 0406B, A8.6.298. 2187 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) | 2188 // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2189 int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0; 2190 return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 | 2191 Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm); 2192 } 2193 } 2194 2195 2196 void Assembler::vcvt_f64_s32(const DwVfpRegister dst, 2197 const SwVfpRegister src, 2198 VFPConversionMode mode, 2199 const Condition cond) { 2200 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2201 emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond)); 2202 } 2203 2204 2205 void Assembler::vcvt_f32_s32(const SwVfpRegister dst, 2206 const SwVfpRegister src, 2207 VFPConversionMode mode, 2208 const Condition cond) { 2209 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2210 emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond)); 2211 } 2212 2213 2214 void Assembler::vcvt_f64_u32(const DwVfpRegister dst, 2215 const SwVfpRegister src, 2216 VFPConversionMode mode, 2217 const Condition cond) { 2218 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2219 emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond)); 2220 } 2221 2222 2223 void Assembler::vcvt_s32_f64(const SwVfpRegister dst, 2224 const DwVfpRegister src, 2225 VFPConversionMode mode, 2226 const Condition cond) { 2227 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2228 emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond)); 2229 } 2230 2231 2232 void Assembler::vcvt_u32_f64(const SwVfpRegister dst, 2233 const DwVfpRegister src, 2234 VFPConversionMode mode, 2235 const Condition cond) { 2236 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2237 emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond)); 2238 } 2239 2240 2241 void Assembler::vcvt_f64_f32(const DwVfpRegister dst, 2242 const SwVfpRegister src, 2243 VFPConversionMode mode, 2244 const Condition cond) { 2245 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2246 emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond)); 2247 } 2248 2249 2250 void Assembler::vcvt_f32_f64(const SwVfpRegister dst, 2251 const DwVfpRegister src, 2252 VFPConversionMode mode, 2253 const Condition cond) { 2254 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2255 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); 2256 } 2257 2258 2259 void Assembler::vneg(const DwVfpRegister dst, 2260 const DwVfpRegister src, 2261 const Condition cond) { 2262 emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 | 2263 0x5*B9 | B8 | B6 | src.code()); 2264 } 2265 2266 2267 void Assembler::vabs(const DwVfpRegister dst, 2268 const DwVfpRegister src, 2269 const Condition cond) { 2270 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 2271 0x5*B9 | B8 | 0x3*B6 | src.code()); 2272 } 2273 2274 2275 void Assembler::vadd(const DwVfpRegister dst, 2276 const DwVfpRegister src1, 2277 const DwVfpRegister src2, 2278 const Condition cond) { 2279 // Dd = vadd(Dn, Dm) double precision floating point addition. 2280 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 2281 // Instruction details available in ARM DDI 0406A, A8-536. 2282 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | 2283 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) 2284 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2285 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | 2286 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 2287 } 2288 2289 2290 void Assembler::vsub(const DwVfpRegister dst, 2291 const DwVfpRegister src1, 2292 const DwVfpRegister src2, 2293 const Condition cond) { 2294 // Dd = vsub(Dn, Dm) double precision floating point subtraction. 2295 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 2296 // Instruction details available in ARM DDI 0406A, A8-784. 2297 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | 2298 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) 2299 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2300 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | 2301 dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); 2302 } 2303 2304 2305 void Assembler::vmul(const DwVfpRegister dst, 2306 const DwVfpRegister src1, 2307 const DwVfpRegister src2, 2308 const Condition cond) { 2309 // Dd = vmul(Dn, Dm) double precision floating point multiplication. 2310 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 2311 // Instruction details available in ARM DDI 0406A, A8-784. 2312 // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | 2313 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) 2314 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2315 emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | 2316 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 2317 } 2318 2319 2320 void Assembler::vdiv(const DwVfpRegister dst, 2321 const DwVfpRegister src1, 2322 const DwVfpRegister src2, 2323 const Condition cond) { 2324 // Dd = vdiv(Dn, Dm) double precision floating point division. 2325 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 2326 // Instruction details available in ARM DDI 0406A, A8-584. 2327 // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | 2328 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) 2329 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2330 emit(cond | 0xE*B24 | B23 | src1.code()*B16 | 2331 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 2332 } 2333 2334 2335 void Assembler::vcmp(const DwVfpRegister src1, 2336 const DwVfpRegister src2, 2337 const Condition cond) { 2338 // vcmp(Dd, Dm) double precision floating point comparison. 2339 // Instruction details available in ARM DDI 0406A, A8-570. 2340 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | 2341 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0) 2342 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2343 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | 2344 src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); 2345 } 2346 2347 2348 void Assembler::vcmp(const DwVfpRegister src1, 2349 const double src2, 2350 const Condition cond) { 2351 // vcmp(Dd, Dm) double precision floating point comparison. 2352 // Instruction details available in ARM DDI 0406A, A8-570. 2353 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) | 2354 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0) 2355 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2356 ASSERT(src2 == 0.0); 2357 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 | 2358 src1.code()*B12 | 0x5*B9 | B8 | B6); 2359 } 2360 2361 2362 void Assembler::vmsr(Register dst, Condition cond) { 2363 // Instruction details available in ARM DDI 0406A, A8-652. 2364 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | 2365 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 2366 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2367 emit(cond | 0xE*B24 | 0xE*B20 | B16 | 2368 dst.code()*B12 | 0xA*B8 | B4); 2369 } 2370 2371 2372 void Assembler::vmrs(Register dst, Condition cond) { 2373 // Instruction details available in ARM DDI 0406A, A8-652. 2374 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | 2375 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 2376 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2377 emit(cond | 0xE*B24 | 0xF*B20 | B16 | 2378 dst.code()*B12 | 0xA*B8 | B4); 2379 } 2380 2381 2382 void Assembler::vsqrt(const DwVfpRegister dst, 2383 const DwVfpRegister src, 2384 const Condition cond) { 2385 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) | 2386 // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0) 2387 ASSERT(CpuFeatures::IsEnabled(VFP3)); 2388 emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 | 2389 dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code()); 2390 } 2391 2392 2393 // Pseudo instructions. 2394 void Assembler::nop(int type) { 2395 // This is mov rx, rx. 2396 ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop. 2397 emit(al | 13*B21 | type*B12 | type); 2398 } 2399 2400 2401 bool Assembler::IsNop(Instr instr, int type) { 2402 // Check for mov rx, rx where x = type. 2403 ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop. 2404 return instr == (al | 13*B21 | type*B12 | type); 2405 } 2406 2407 2408 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { 2409 uint32_t dummy1; 2410 uint32_t dummy2; 2411 return fits_shifter(imm32, &dummy1, &dummy2, NULL); 2412 } 2413 2414 2415 // Debugging. 2416 void Assembler::RecordJSReturn() { 2417 positions_recorder()->WriteRecordedPositions(); 2418 CheckBuffer(); 2419 RecordRelocInfo(RelocInfo::JS_RETURN); 2420 } 2421 2422 2423 void Assembler::RecordDebugBreakSlot() { 2424 positions_recorder()->WriteRecordedPositions(); 2425 CheckBuffer(); 2426 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); 2427 } 2428 2429 2430 void Assembler::RecordComment(const char* msg) { 2431 if (FLAG_code_comments) { 2432 CheckBuffer(); 2433 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 2434 } 2435 } 2436 2437 2438 void Assembler::GrowBuffer() { 2439 if (!own_buffer_) FATAL("external code buffer is too small"); 2440 2441 // Compute new buffer size. 2442 CodeDesc desc; // the new buffer 2443 if (buffer_size_ < 4*KB) { 2444 desc.buffer_size = 4*KB; 2445 } else if (buffer_size_ < 1*MB) { 2446 desc.buffer_size = 2*buffer_size_; 2447 } else { 2448 desc.buffer_size = buffer_size_ + 1*MB; 2449 } 2450 CHECK_GT(desc.buffer_size, 0); // no overflow 2451 2452 // Set up new buffer. 2453 desc.buffer = NewArray<byte>(desc.buffer_size); 2454 2455 desc.instr_size = pc_offset(); 2456 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 2457 2458 // Copy the data. 2459 int pc_delta = desc.buffer - buffer_; 2460 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 2461 memmove(desc.buffer, buffer_, desc.instr_size); 2462 memmove(reloc_info_writer.pos() + rc_delta, 2463 reloc_info_writer.pos(), desc.reloc_size); 2464 2465 // Switch buffers. 2466 DeleteArray(buffer_); 2467 buffer_ = desc.buffer; 2468 buffer_size_ = desc.buffer_size; 2469 pc_ += pc_delta; 2470 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 2471 reloc_info_writer.last_pc() + pc_delta); 2472 2473 // None of our relocation types are pc relative pointing outside the code 2474 // buffer nor pc absolute pointing inside the code buffer, so there is no need 2475 // to relocate any emitted relocation entries. 2476 2477 // Relocate pending relocation entries. 2478 for (int i = 0; i < num_pending_reloc_info_; i++) { 2479 RelocInfo& rinfo = pending_reloc_info_[i]; 2480 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 2481 rinfo.rmode() != RelocInfo::POSITION); 2482 if (rinfo.rmode() != RelocInfo::JS_RETURN) { 2483 rinfo.set_pc(rinfo.pc() + pc_delta); 2484 } 2485 } 2486 } 2487 2488 2489 void Assembler::db(uint8_t data) { 2490 // No relocation info should be pending while using db. db is used 2491 // to write pure data with no pointers and the constant pool should 2492 // be emitted before using db. 2493 ASSERT(num_pending_reloc_info_ == 0); 2494 CheckBuffer(); 2495 *reinterpret_cast<uint8_t*>(pc_) = data; 2496 pc_ += sizeof(uint8_t); 2497 } 2498 2499 2500 void Assembler::dd(uint32_t data) { 2501 // No relocation info should be pending while using dd. dd is used 2502 // to write pure data with no pointers and the constant pool should 2503 // be emitted before using dd. 2504 ASSERT(num_pending_reloc_info_ == 0); 2505 CheckBuffer(); 2506 *reinterpret_cast<uint32_t*>(pc_) = data; 2507 pc_ += sizeof(uint32_t); 2508 } 2509 2510 2511 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 2512 // We do not try to reuse pool constants. 2513 RelocInfo rinfo(pc_, rmode, data, NULL); 2514 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) { 2515 // Adjust code for new modes. 2516 ASSERT(RelocInfo::IsDebugBreakSlot(rmode) 2517 || RelocInfo::IsJSReturn(rmode) 2518 || RelocInfo::IsComment(rmode) 2519 || RelocInfo::IsPosition(rmode)); 2520 // These modes do not need an entry in the constant pool. 2521 } else { 2522 ASSERT(num_pending_reloc_info_ < kMaxNumPendingRelocInfo); 2523 if (num_pending_reloc_info_ == 0) { 2524 first_const_pool_use_ = pc_offset(); 2525 } 2526 pending_reloc_info_[num_pending_reloc_info_++] = rinfo; 2527 // Make sure the constant pool is not emitted in place of the next 2528 // instruction for which we just recorded relocation info. 2529 BlockConstPoolFor(1); 2530 } 2531 if (rinfo.rmode() != RelocInfo::NONE) { 2532 // Don't record external references unless the heap will be serialized. 2533 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 2534 #ifdef DEBUG 2535 if (!Serializer::enabled()) { 2536 Serializer::TooLateToEnableNow(); 2537 } 2538 #endif 2539 if (!Serializer::enabled() && !emit_debug_code()) { 2540 return; 2541 } 2542 } 2543 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 2544 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 2545 RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId(), NULL); 2546 ClearRecordedAstId(); 2547 reloc_info_writer.Write(&reloc_info_with_ast_id); 2548 } else { 2549 reloc_info_writer.Write(&rinfo); 2550 } 2551 } 2552 } 2553 2554 2555 void Assembler::BlockConstPoolFor(int instructions) { 2556 int pc_limit = pc_offset() + instructions * kInstrSize; 2557 if (no_const_pool_before_ < pc_limit) { 2558 // If there are some pending entries, the constant pool cannot be blocked 2559 // further than first_const_pool_use_ + kMaxDistToPool 2560 ASSERT((num_pending_reloc_info_ == 0) || 2561 (pc_limit < (first_const_pool_use_ + kMaxDistToPool))); 2562 no_const_pool_before_ = pc_limit; 2563 } 2564 2565 if (next_buffer_check_ < no_const_pool_before_) { 2566 next_buffer_check_ = no_const_pool_before_; 2567 } 2568 } 2569 2570 2571 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { 2572 // Some short sequence of instruction mustn't be broken up by constant pool 2573 // emission, such sequences are protected by calls to BlockConstPoolFor and 2574 // BlockConstPoolScope. 2575 if (is_const_pool_blocked()) { 2576 // Something is wrong if emission is forced and blocked at the same time. 2577 ASSERT(!force_emit); 2578 return; 2579 } 2580 2581 // There is nothing to do if there are no pending constant pool entries. 2582 if (num_pending_reloc_info_ == 0) { 2583 // Calculate the offset of the next check. 2584 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 2585 return; 2586 } 2587 2588 // We emit a constant pool when: 2589 // * requested to do so by parameter force_emit (e.g. after each function). 2590 // * the distance to the first instruction accessing the constant pool is 2591 // kAvgDistToPool or more. 2592 // * no jump is required and the distance to the first instruction accessing 2593 // the constant pool is at least kMaxDistToPool / 2. 2594 ASSERT(first_const_pool_use_ >= 0); 2595 int dist = pc_offset() - first_const_pool_use_; 2596 if (!force_emit && dist < kAvgDistToPool && 2597 (require_jump || (dist < (kMaxDistToPool / 2)))) { 2598 return; 2599 } 2600 2601 // Check that the code buffer is large enough before emitting the constant 2602 // pool (include the jump over the pool and the constant pool marker and 2603 // the gap to the relocation information). 2604 int jump_instr = require_jump ? kInstrSize : 0; 2605 int needed_space = jump_instr + kInstrSize + 2606 num_pending_reloc_info_ * kInstrSize + kGap; 2607 while (buffer_space() <= needed_space) GrowBuffer(); 2608 2609 { 2610 // Block recursive calls to CheckConstPool. 2611 BlockConstPoolScope block_const_pool(this); 2612 2613 // Emit jump over constant pool if necessary. 2614 Label after_pool; 2615 if (require_jump) { 2616 b(&after_pool); 2617 } 2618 2619 RecordComment("[ Constant Pool"); 2620 2621 // Put down constant pool marker "Undefined instruction" as specified by 2622 // A5.6 (ARMv7) Instruction set encoding. 2623 emit(kConstantPoolMarker | num_pending_reloc_info_); 2624 2625 // Emit constant pool entries. 2626 for (int i = 0; i < num_pending_reloc_info_; i++) { 2627 RelocInfo& rinfo = pending_reloc_info_[i]; 2628 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 2629 rinfo.rmode() != RelocInfo::POSITION && 2630 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); 2631 2632 Instr instr = instr_at(rinfo.pc()); 2633 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. 2634 ASSERT(IsLdrPcImmediateOffset(instr) && 2635 GetLdrRegisterImmediateOffset(instr) == 0); 2636 2637 int delta = pc_ - rinfo.pc() - kPcLoadDelta; 2638 // 0 is the smallest delta: 2639 // ldr rd, [pc, #0] 2640 // constant pool marker 2641 // data 2642 ASSERT(is_uint12(delta)); 2643 2644 instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta)); 2645 emit(rinfo.data()); 2646 } 2647 2648 num_pending_reloc_info_ = 0; 2649 first_const_pool_use_ = -1; 2650 2651 RecordComment("]"); 2652 2653 if (after_pool.is_linked()) { 2654 bind(&after_pool); 2655 } 2656 } 2657 2658 // Since a constant pool was just emitted, move the check offset forward by 2659 // the standard interval. 2660 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 2661 } 2662 2663 2664 } } // namespace v8::internal 2665 2666 #endif // V8_TARGET_ARCH_ARM 2667