1 // Copyright 2013, ARM Limited 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 are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 28 #include <cmath> 29 #include "a64/assembler-a64.h" 30 31 namespace vixl { 32 33 // CPURegList utilities. 34 CPURegister CPURegList::PopLowestIndex() { 35 if (IsEmpty()) { 36 return NoCPUReg; 37 } 38 int index = CountTrailingZeros(list_, kRegListSizeInBits); 39 VIXL_ASSERT((1 << index) & list_); 40 Remove(index); 41 return CPURegister(index, size_, type_); 42 } 43 44 45 CPURegister CPURegList::PopHighestIndex() { 46 VIXL_ASSERT(IsValid()); 47 if (IsEmpty()) { 48 return NoCPUReg; 49 } 50 int index = CountLeadingZeros(list_, kRegListSizeInBits); 51 index = kRegListSizeInBits - 1 - index; 52 VIXL_ASSERT((1 << index) & list_); 53 Remove(index); 54 return CPURegister(index, size_, type_); 55 } 56 57 58 bool CPURegList::IsValid() const { 59 if ((type_ == CPURegister::kRegister) || 60 (type_ == CPURegister::kFPRegister)) { 61 bool is_valid = true; 62 // Try to create a CPURegister for each element in the list. 63 for (int i = 0; i < kRegListSizeInBits; i++) { 64 if (((list_ >> i) & 1) != 0) { 65 is_valid &= CPURegister(i, size_, type_).IsValid(); 66 } 67 } 68 return is_valid; 69 } else if (type_ == CPURegister::kNoRegister) { 70 // We can't use IsEmpty here because that asserts IsValid(). 71 return list_ == 0; 72 } else { 73 return false; 74 } 75 } 76 77 78 void CPURegList::RemoveCalleeSaved() { 79 if (type() == CPURegister::kRegister) { 80 Remove(GetCalleeSaved(RegisterSizeInBits())); 81 } else if (type() == CPURegister::kFPRegister) { 82 Remove(GetCalleeSavedFP(RegisterSizeInBits())); 83 } else { 84 VIXL_ASSERT(type() == CPURegister::kNoRegister); 85 VIXL_ASSERT(IsEmpty()); 86 // The list must already be empty, so do nothing. 87 } 88 } 89 90 91 CPURegList CPURegList::GetCalleeSaved(unsigned size) { 92 return CPURegList(CPURegister::kRegister, size, 19, 29); 93 } 94 95 96 CPURegList CPURegList::GetCalleeSavedFP(unsigned size) { 97 return CPURegList(CPURegister::kFPRegister, size, 8, 15); 98 } 99 100 101 CPURegList CPURegList::GetCallerSaved(unsigned size) { 102 // Registers x0-x18 and lr (x30) are caller-saved. 103 CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18); 104 list.Combine(lr); 105 return list; 106 } 107 108 109 CPURegList CPURegList::GetCallerSavedFP(unsigned size) { 110 // Registers d0-d7 and d16-d31 are caller-saved. 111 CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7); 112 list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31)); 113 return list; 114 } 115 116 117 const CPURegList kCalleeSaved = CPURegList::GetCalleeSaved(); 118 const CPURegList kCalleeSavedFP = CPURegList::GetCalleeSavedFP(); 119 const CPURegList kCallerSaved = CPURegList::GetCallerSaved(); 120 const CPURegList kCallerSavedFP = CPURegList::GetCallerSavedFP(); 121 122 123 // Registers. 124 #define WREG(n) w##n, 125 const Register Register::wregisters[] = { 126 REGISTER_CODE_LIST(WREG) 127 }; 128 #undef WREG 129 130 #define XREG(n) x##n, 131 const Register Register::xregisters[] = { 132 REGISTER_CODE_LIST(XREG) 133 }; 134 #undef XREG 135 136 #define SREG(n) s##n, 137 const FPRegister FPRegister::sregisters[] = { 138 REGISTER_CODE_LIST(SREG) 139 }; 140 #undef SREG 141 142 #define DREG(n) d##n, 143 const FPRegister FPRegister::dregisters[] = { 144 REGISTER_CODE_LIST(DREG) 145 }; 146 #undef DREG 147 148 149 const Register& Register::WRegFromCode(unsigned code) { 150 if (code == kSPRegInternalCode) { 151 return wsp; 152 } else { 153 VIXL_ASSERT(code < kNumberOfRegisters); 154 return wregisters[code]; 155 } 156 } 157 158 159 const Register& Register::XRegFromCode(unsigned code) { 160 if (code == kSPRegInternalCode) { 161 return sp; 162 } else { 163 VIXL_ASSERT(code < kNumberOfRegisters); 164 return xregisters[code]; 165 } 166 } 167 168 169 const FPRegister& FPRegister::SRegFromCode(unsigned code) { 170 VIXL_ASSERT(code < kNumberOfFPRegisters); 171 return sregisters[code]; 172 } 173 174 175 const FPRegister& FPRegister::DRegFromCode(unsigned code) { 176 VIXL_ASSERT(code < kNumberOfFPRegisters); 177 return dregisters[code]; 178 } 179 180 181 const Register& CPURegister::W() const { 182 VIXL_ASSERT(IsValidRegister()); 183 return Register::WRegFromCode(code_); 184 } 185 186 187 const Register& CPURegister::X() const { 188 VIXL_ASSERT(IsValidRegister()); 189 return Register::XRegFromCode(code_); 190 } 191 192 193 const FPRegister& CPURegister::S() const { 194 VIXL_ASSERT(IsValidFPRegister()); 195 return FPRegister::SRegFromCode(code_); 196 } 197 198 199 const FPRegister& CPURegister::D() const { 200 VIXL_ASSERT(IsValidFPRegister()); 201 return FPRegister::DRegFromCode(code_); 202 } 203 204 205 // Operand. 206 Operand::Operand(int64_t immediate) 207 : immediate_(immediate), 208 reg_(NoReg), 209 shift_(NO_SHIFT), 210 extend_(NO_EXTEND), 211 shift_amount_(0) {} 212 213 214 Operand::Operand(Register reg, Shift shift, unsigned shift_amount) 215 : reg_(reg), 216 shift_(shift), 217 extend_(NO_EXTEND), 218 shift_amount_(shift_amount) { 219 VIXL_ASSERT(reg.Is64Bits() || (shift_amount < kWRegSize)); 220 VIXL_ASSERT(reg.Is32Bits() || (shift_amount < kXRegSize)); 221 VIXL_ASSERT(!reg.IsSP()); 222 } 223 224 225 Operand::Operand(Register reg, Extend extend, unsigned shift_amount) 226 : reg_(reg), 227 shift_(NO_SHIFT), 228 extend_(extend), 229 shift_amount_(shift_amount) { 230 VIXL_ASSERT(reg.IsValid()); 231 VIXL_ASSERT(shift_amount <= 4); 232 VIXL_ASSERT(!reg.IsSP()); 233 234 // Extend modes SXTX and UXTX require a 64-bit register. 235 VIXL_ASSERT(reg.Is64Bits() || ((extend != SXTX) && (extend != UXTX))); 236 } 237 238 239 bool Operand::IsImmediate() const { 240 return reg_.Is(NoReg); 241 } 242 243 244 bool Operand::IsShiftedRegister() const { 245 return reg_.IsValid() && (shift_ != NO_SHIFT); 246 } 247 248 249 bool Operand::IsExtendedRegister() const { 250 return reg_.IsValid() && (extend_ != NO_EXTEND); 251 } 252 253 254 bool Operand::IsZero() const { 255 if (IsImmediate()) { 256 return immediate() == 0; 257 } else { 258 return reg().IsZero(); 259 } 260 } 261 262 263 Operand Operand::ToExtendedRegister() const { 264 VIXL_ASSERT(IsShiftedRegister()); 265 VIXL_ASSERT((shift_ == LSL) && (shift_amount_ <= 4)); 266 return Operand(reg_, reg_.Is64Bits() ? UXTX : UXTW, shift_amount_); 267 } 268 269 270 // MemOperand 271 MemOperand::MemOperand(Register base, ptrdiff_t offset, AddrMode addrmode) 272 : base_(base), regoffset_(NoReg), offset_(offset), addrmode_(addrmode) { 273 VIXL_ASSERT(base.Is64Bits() && !base.IsZero()); 274 } 275 276 277 MemOperand::MemOperand(Register base, 278 Register regoffset, 279 Extend extend, 280 unsigned shift_amount) 281 : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset), 282 shift_(NO_SHIFT), extend_(extend), shift_amount_(shift_amount) { 283 VIXL_ASSERT(base.Is64Bits() && !base.IsZero()); 284 VIXL_ASSERT(!regoffset.IsSP()); 285 VIXL_ASSERT((extend == UXTW) || (extend == SXTW) || (extend == SXTX)); 286 287 // SXTX extend mode requires a 64-bit offset register. 288 VIXL_ASSERT(regoffset.Is64Bits() || (extend != SXTX)); 289 } 290 291 292 MemOperand::MemOperand(Register base, 293 Register regoffset, 294 Shift shift, 295 unsigned shift_amount) 296 : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset), 297 shift_(shift), extend_(NO_EXTEND), shift_amount_(shift_amount) { 298 VIXL_ASSERT(base.Is64Bits() && !base.IsZero()); 299 VIXL_ASSERT(regoffset.Is64Bits() && !regoffset.IsSP()); 300 VIXL_ASSERT(shift == LSL); 301 } 302 303 304 MemOperand::MemOperand(Register base, const Operand& offset, AddrMode addrmode) 305 : base_(base), regoffset_(NoReg), addrmode_(addrmode) { 306 VIXL_ASSERT(base.Is64Bits() && !base.IsZero()); 307 308 if (offset.IsImmediate()) { 309 offset_ = offset.immediate(); 310 } else if (offset.IsShiftedRegister()) { 311 VIXL_ASSERT(addrmode == Offset); 312 313 regoffset_ = offset.reg(); 314 shift_= offset.shift(); 315 shift_amount_ = offset.shift_amount(); 316 317 extend_ = NO_EXTEND; 318 offset_ = 0; 319 320 // These assertions match those in the shifted-register constructor. 321 VIXL_ASSERT(regoffset_.Is64Bits() && !regoffset_.IsSP()); 322 VIXL_ASSERT(shift_ == LSL); 323 } else { 324 VIXL_ASSERT(offset.IsExtendedRegister()); 325 VIXL_ASSERT(addrmode == Offset); 326 327 regoffset_ = offset.reg(); 328 extend_ = offset.extend(); 329 shift_amount_ = offset.shift_amount(); 330 331 shift_= NO_SHIFT; 332 offset_ = 0; 333 334 // These assertions match those in the extended-register constructor. 335 VIXL_ASSERT(!regoffset_.IsSP()); 336 VIXL_ASSERT((extend_ == UXTW) || (extend_ == SXTW) || (extend_ == SXTX)); 337 VIXL_ASSERT((regoffset_.Is64Bits() || (extend_ != SXTX))); 338 } 339 } 340 341 342 bool MemOperand::IsImmediateOffset() const { 343 return (addrmode_ == Offset) && regoffset_.Is(NoReg); 344 } 345 346 347 bool MemOperand::IsRegisterOffset() const { 348 return (addrmode_ == Offset) && !regoffset_.Is(NoReg); 349 } 350 351 352 bool MemOperand::IsPreIndex() const { 353 return addrmode_ == PreIndex; 354 } 355 356 357 bool MemOperand::IsPostIndex() const { 358 return addrmode_ == PostIndex; 359 } 360 361 362 // Assembler 363 Assembler::Assembler(byte* buffer, unsigned buffer_size) 364 : buffer_size_(buffer_size), literal_pool_monitor_(0) { 365 366 buffer_ = reinterpret_cast<Instruction*>(buffer); 367 pc_ = buffer_; 368 Reset(); 369 } 370 371 372 Assembler::~Assembler() { 373 VIXL_ASSERT(finalized_ || (pc_ == buffer_)); 374 VIXL_ASSERT(literals_.empty()); 375 } 376 377 378 void Assembler::Reset() { 379 #ifdef DEBUG 380 VIXL_ASSERT((pc_ >= buffer_) && (pc_ < buffer_ + buffer_size_)); 381 VIXL_ASSERT(literal_pool_monitor_ == 0); 382 memset(buffer_, 0, pc_ - buffer_); 383 finalized_ = false; 384 #endif 385 pc_ = buffer_; 386 literals_.clear(); 387 next_literal_pool_check_ = pc_ + kLiteralPoolCheckInterval; 388 } 389 390 391 void Assembler::FinalizeCode() { 392 EmitLiteralPool(); 393 #ifdef DEBUG 394 finalized_ = true; 395 #endif 396 } 397 398 399 void Assembler::bind(Label* label) { 400 label->is_bound_ = true; 401 label->target_ = pc_; 402 while (label->IsLinked()) { 403 // Get the address of the following instruction in the chain. 404 Instruction* next_link = label->link_->ImmPCOffsetTarget(); 405 // Update the instruction target. 406 label->link_->SetImmPCOffsetTarget(label->target_); 407 // Update the label's link. 408 // If the offset of the branch we just updated was 0 (kEndOfChain) we are 409 // done. 410 label->link_ = (label->link_ != next_link) ? next_link : NULL; 411 } 412 } 413 414 415 int Assembler::UpdateAndGetByteOffsetTo(Label* label) { 416 int offset; 417 VIXL_STATIC_ASSERT(sizeof(*pc_) == 1); 418 if (label->IsBound()) { 419 offset = label->target() - pc_; 420 } else if (label->IsLinked()) { 421 offset = label->link() - pc_; 422 } else { 423 offset = Label::kEndOfChain; 424 } 425 label->set_link(pc_); 426 return offset; 427 } 428 429 430 // Code generation. 431 void Assembler::br(const Register& xn) { 432 VIXL_ASSERT(xn.Is64Bits()); 433 Emit(BR | Rn(xn)); 434 } 435 436 437 void Assembler::blr(const Register& xn) { 438 VIXL_ASSERT(xn.Is64Bits()); 439 Emit(BLR | Rn(xn)); 440 } 441 442 443 void Assembler::ret(const Register& xn) { 444 VIXL_ASSERT(xn.Is64Bits()); 445 Emit(RET | Rn(xn)); 446 } 447 448 449 void Assembler::b(int imm26) { 450 Emit(B | ImmUncondBranch(imm26)); 451 } 452 453 454 void Assembler::b(int imm19, Condition cond) { 455 Emit(B_cond | ImmCondBranch(imm19) | cond); 456 } 457 458 459 void Assembler::b(Label* label) { 460 b(UpdateAndGetInstructionOffsetTo(label)); 461 } 462 463 464 void Assembler::b(Label* label, Condition cond) { 465 b(UpdateAndGetInstructionOffsetTo(label), cond); 466 } 467 468 469 void Assembler::bl(int imm26) { 470 Emit(BL | ImmUncondBranch(imm26)); 471 } 472 473 474 void Assembler::bl(Label* label) { 475 bl(UpdateAndGetInstructionOffsetTo(label)); 476 } 477 478 479 void Assembler::cbz(const Register& rt, 480 int imm19) { 481 Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt)); 482 } 483 484 485 void Assembler::cbz(const Register& rt, 486 Label* label) { 487 cbz(rt, UpdateAndGetInstructionOffsetTo(label)); 488 } 489 490 491 void Assembler::cbnz(const Register& rt, 492 int imm19) { 493 Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt)); 494 } 495 496 497 void Assembler::cbnz(const Register& rt, 498 Label* label) { 499 cbnz(rt, UpdateAndGetInstructionOffsetTo(label)); 500 } 501 502 503 void Assembler::tbz(const Register& rt, 504 unsigned bit_pos, 505 int imm14) { 506 VIXL_ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize))); 507 Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); 508 } 509 510 511 void Assembler::tbz(const Register& rt, 512 unsigned bit_pos, 513 Label* label) { 514 tbz(rt, bit_pos, UpdateAndGetInstructionOffsetTo(label)); 515 } 516 517 518 void Assembler::tbnz(const Register& rt, 519 unsigned bit_pos, 520 int imm14) { 521 VIXL_ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize))); 522 Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); 523 } 524 525 526 void Assembler::tbnz(const Register& rt, 527 unsigned bit_pos, 528 Label* label) { 529 tbnz(rt, bit_pos, UpdateAndGetInstructionOffsetTo(label)); 530 } 531 532 533 void Assembler::adr(const Register& rd, int imm21) { 534 VIXL_ASSERT(rd.Is64Bits()); 535 Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd)); 536 } 537 538 539 void Assembler::adr(const Register& rd, Label* label) { 540 adr(rd, UpdateAndGetByteOffsetTo(label)); 541 } 542 543 544 void Assembler::add(const Register& rd, 545 const Register& rn, 546 const Operand& operand) { 547 AddSub(rd, rn, operand, LeaveFlags, ADD); 548 } 549 550 551 void Assembler::adds(const Register& rd, 552 const Register& rn, 553 const Operand& operand) { 554 AddSub(rd, rn, operand, SetFlags, ADD); 555 } 556 557 558 void Assembler::cmn(const Register& rn, 559 const Operand& operand) { 560 Register zr = AppropriateZeroRegFor(rn); 561 adds(zr, rn, operand); 562 } 563 564 565 void Assembler::sub(const Register& rd, 566 const Register& rn, 567 const Operand& operand) { 568 AddSub(rd, rn, operand, LeaveFlags, SUB); 569 } 570 571 572 void Assembler::subs(const Register& rd, 573 const Register& rn, 574 const Operand& operand) { 575 AddSub(rd, rn, operand, SetFlags, SUB); 576 } 577 578 579 void Assembler::cmp(const Register& rn, const Operand& operand) { 580 Register zr = AppropriateZeroRegFor(rn); 581 subs(zr, rn, operand); 582 } 583 584 585 void Assembler::neg(const Register& rd, const Operand& operand) { 586 Register zr = AppropriateZeroRegFor(rd); 587 sub(rd, zr, operand); 588 } 589 590 591 void Assembler::negs(const Register& rd, const Operand& operand) { 592 Register zr = AppropriateZeroRegFor(rd); 593 subs(rd, zr, operand); 594 } 595 596 597 void Assembler::adc(const Register& rd, 598 const Register& rn, 599 const Operand& operand) { 600 AddSubWithCarry(rd, rn, operand, LeaveFlags, ADC); 601 } 602 603 604 void Assembler::adcs(const Register& rd, 605 const Register& rn, 606 const Operand& operand) { 607 AddSubWithCarry(rd, rn, operand, SetFlags, ADC); 608 } 609 610 611 void Assembler::sbc(const Register& rd, 612 const Register& rn, 613 const Operand& operand) { 614 AddSubWithCarry(rd, rn, operand, LeaveFlags, SBC); 615 } 616 617 618 void Assembler::sbcs(const Register& rd, 619 const Register& rn, 620 const Operand& operand) { 621 AddSubWithCarry(rd, rn, operand, SetFlags, SBC); 622 } 623 624 625 void Assembler::ngc(const Register& rd, const Operand& operand) { 626 Register zr = AppropriateZeroRegFor(rd); 627 sbc(rd, zr, operand); 628 } 629 630 631 void Assembler::ngcs(const Register& rd, const Operand& operand) { 632 Register zr = AppropriateZeroRegFor(rd); 633 sbcs(rd, zr, operand); 634 } 635 636 637 // Logical instructions. 638 void Assembler::and_(const Register& rd, 639 const Register& rn, 640 const Operand& operand) { 641 Logical(rd, rn, operand, AND); 642 } 643 644 645 void Assembler::ands(const Register& rd, 646 const Register& rn, 647 const Operand& operand) { 648 Logical(rd, rn, operand, ANDS); 649 } 650 651 652 void Assembler::tst(const Register& rn, 653 const Operand& operand) { 654 ands(AppropriateZeroRegFor(rn), rn, operand); 655 } 656 657 658 void Assembler::bic(const Register& rd, 659 const Register& rn, 660 const Operand& operand) { 661 Logical(rd, rn, operand, BIC); 662 } 663 664 665 void Assembler::bics(const Register& rd, 666 const Register& rn, 667 const Operand& operand) { 668 Logical(rd, rn, operand, BICS); 669 } 670 671 672 void Assembler::orr(const Register& rd, 673 const Register& rn, 674 const Operand& operand) { 675 Logical(rd, rn, operand, ORR); 676 } 677 678 679 void Assembler::orn(const Register& rd, 680 const Register& rn, 681 const Operand& operand) { 682 Logical(rd, rn, operand, ORN); 683 } 684 685 686 void Assembler::eor(const Register& rd, 687 const Register& rn, 688 const Operand& operand) { 689 Logical(rd, rn, operand, EOR); 690 } 691 692 693 void Assembler::eon(const Register& rd, 694 const Register& rn, 695 const Operand& operand) { 696 Logical(rd, rn, operand, EON); 697 } 698 699 700 void Assembler::lslv(const Register& rd, 701 const Register& rn, 702 const Register& rm) { 703 VIXL_ASSERT(rd.size() == rn.size()); 704 VIXL_ASSERT(rd.size() == rm.size()); 705 Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd)); 706 } 707 708 709 void Assembler::lsrv(const Register& rd, 710 const Register& rn, 711 const Register& rm) { 712 VIXL_ASSERT(rd.size() == rn.size()); 713 VIXL_ASSERT(rd.size() == rm.size()); 714 Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd)); 715 } 716 717 718 void Assembler::asrv(const Register& rd, 719 const Register& rn, 720 const Register& rm) { 721 VIXL_ASSERT(rd.size() == rn.size()); 722 VIXL_ASSERT(rd.size() == rm.size()); 723 Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd)); 724 } 725 726 727 void Assembler::rorv(const Register& rd, 728 const Register& rn, 729 const Register& rm) { 730 VIXL_ASSERT(rd.size() == rn.size()); 731 VIXL_ASSERT(rd.size() == rm.size()); 732 Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd)); 733 } 734 735 736 // Bitfield operations. 737 void Assembler::bfm(const Register& rd, 738 const Register& rn, 739 unsigned immr, 740 unsigned imms) { 741 VIXL_ASSERT(rd.size() == rn.size()); 742 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 743 Emit(SF(rd) | BFM | N | 744 ImmR(immr, rd.size()) | ImmS(imms, rn.size()) | Rn(rn) | Rd(rd)); 745 } 746 747 748 void Assembler::sbfm(const Register& rd, 749 const Register& rn, 750 unsigned immr, 751 unsigned imms) { 752 VIXL_ASSERT(rd.Is64Bits() || rn.Is32Bits()); 753 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 754 Emit(SF(rd) | SBFM | N | 755 ImmR(immr, rd.size()) | ImmS(imms, rn.size()) | Rn(rn) | Rd(rd)); 756 } 757 758 759 void Assembler::ubfm(const Register& rd, 760 const Register& rn, 761 unsigned immr, 762 unsigned imms) { 763 VIXL_ASSERT(rd.size() == rn.size()); 764 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 765 Emit(SF(rd) | UBFM | N | 766 ImmR(immr, rd.size()) | ImmS(imms, rn.size()) | Rn(rn) | Rd(rd)); 767 } 768 769 770 void Assembler::extr(const Register& rd, 771 const Register& rn, 772 const Register& rm, 773 unsigned lsb) { 774 VIXL_ASSERT(rd.size() == rn.size()); 775 VIXL_ASSERT(rd.size() == rm.size()); 776 Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 777 Emit(SF(rd) | EXTR | N | Rm(rm) | ImmS(lsb, rn.size()) | Rn(rn) | Rd(rd)); 778 } 779 780 781 void Assembler::csel(const Register& rd, 782 const Register& rn, 783 const Register& rm, 784 Condition cond) { 785 ConditionalSelect(rd, rn, rm, cond, CSEL); 786 } 787 788 789 void Assembler::csinc(const Register& rd, 790 const Register& rn, 791 const Register& rm, 792 Condition cond) { 793 ConditionalSelect(rd, rn, rm, cond, CSINC); 794 } 795 796 797 void Assembler::csinv(const Register& rd, 798 const Register& rn, 799 const Register& rm, 800 Condition cond) { 801 ConditionalSelect(rd, rn, rm, cond, CSINV); 802 } 803 804 805 void Assembler::csneg(const Register& rd, 806 const Register& rn, 807 const Register& rm, 808 Condition cond) { 809 ConditionalSelect(rd, rn, rm, cond, CSNEG); 810 } 811 812 813 void Assembler::cset(const Register &rd, Condition cond) { 814 VIXL_ASSERT((cond != al) && (cond != nv)); 815 Register zr = AppropriateZeroRegFor(rd); 816 csinc(rd, zr, zr, InvertCondition(cond)); 817 } 818 819 820 void Assembler::csetm(const Register &rd, Condition cond) { 821 VIXL_ASSERT((cond != al) && (cond != nv)); 822 Register zr = AppropriateZeroRegFor(rd); 823 csinv(rd, zr, zr, InvertCondition(cond)); 824 } 825 826 827 void Assembler::cinc(const Register &rd, const Register &rn, Condition cond) { 828 VIXL_ASSERT((cond != al) && (cond != nv)); 829 csinc(rd, rn, rn, InvertCondition(cond)); 830 } 831 832 833 void Assembler::cinv(const Register &rd, const Register &rn, Condition cond) { 834 VIXL_ASSERT((cond != al) && (cond != nv)); 835 csinv(rd, rn, rn, InvertCondition(cond)); 836 } 837 838 839 void Assembler::cneg(const Register &rd, const Register &rn, Condition cond) { 840 VIXL_ASSERT((cond != al) && (cond != nv)); 841 csneg(rd, rn, rn, InvertCondition(cond)); 842 } 843 844 845 void Assembler::ConditionalSelect(const Register& rd, 846 const Register& rn, 847 const Register& rm, 848 Condition cond, 849 ConditionalSelectOp op) { 850 VIXL_ASSERT(rd.size() == rn.size()); 851 VIXL_ASSERT(rd.size() == rm.size()); 852 Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd)); 853 } 854 855 856 void Assembler::ccmn(const Register& rn, 857 const Operand& operand, 858 StatusFlags nzcv, 859 Condition cond) { 860 ConditionalCompare(rn, operand, nzcv, cond, CCMN); 861 } 862 863 864 void Assembler::ccmp(const Register& rn, 865 const Operand& operand, 866 StatusFlags nzcv, 867 Condition cond) { 868 ConditionalCompare(rn, operand, nzcv, cond, CCMP); 869 } 870 871 872 void Assembler::DataProcessing3Source(const Register& rd, 873 const Register& rn, 874 const Register& rm, 875 const Register& ra, 876 DataProcessing3SourceOp op) { 877 Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd)); 878 } 879 880 881 void Assembler::mul(const Register& rd, 882 const Register& rn, 883 const Register& rm) { 884 VIXL_ASSERT(AreSameSizeAndType(rd, rn, rm)); 885 DataProcessing3Source(rd, rn, rm, AppropriateZeroRegFor(rd), MADD); 886 } 887 888 889 void Assembler::madd(const Register& rd, 890 const Register& rn, 891 const Register& rm, 892 const Register& ra) { 893 DataProcessing3Source(rd, rn, rm, ra, MADD); 894 } 895 896 897 void Assembler::mneg(const Register& rd, 898 const Register& rn, 899 const Register& rm) { 900 VIXL_ASSERT(AreSameSizeAndType(rd, rn, rm)); 901 DataProcessing3Source(rd, rn, rm, AppropriateZeroRegFor(rd), MSUB); 902 } 903 904 905 void Assembler::msub(const Register& rd, 906 const Register& rn, 907 const Register& rm, 908 const Register& ra) { 909 DataProcessing3Source(rd, rn, rm, ra, MSUB); 910 } 911 912 913 void Assembler::umaddl(const Register& rd, 914 const Register& rn, 915 const Register& rm, 916 const Register& ra) { 917 VIXL_ASSERT(rd.Is64Bits() && ra.Is64Bits()); 918 VIXL_ASSERT(rn.Is32Bits() && rm.Is32Bits()); 919 DataProcessing3Source(rd, rn, rm, ra, UMADDL_x); 920 } 921 922 923 void Assembler::smaddl(const Register& rd, 924 const Register& rn, 925 const Register& rm, 926 const Register& ra) { 927 VIXL_ASSERT(rd.Is64Bits() && ra.Is64Bits()); 928 VIXL_ASSERT(rn.Is32Bits() && rm.Is32Bits()); 929 DataProcessing3Source(rd, rn, rm, ra, SMADDL_x); 930 } 931 932 933 void Assembler::umsubl(const Register& rd, 934 const Register& rn, 935 const Register& rm, 936 const Register& ra) { 937 VIXL_ASSERT(rd.Is64Bits() && ra.Is64Bits()); 938 VIXL_ASSERT(rn.Is32Bits() && rm.Is32Bits()); 939 DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x); 940 } 941 942 943 void Assembler::smsubl(const Register& rd, 944 const Register& rn, 945 const Register& rm, 946 const Register& ra) { 947 VIXL_ASSERT(rd.Is64Bits() && ra.Is64Bits()); 948 VIXL_ASSERT(rn.Is32Bits() && rm.Is32Bits()); 949 DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x); 950 } 951 952 953 void Assembler::smull(const Register& rd, 954 const Register& rn, 955 const Register& rm) { 956 VIXL_ASSERT(rd.Is64Bits()); 957 VIXL_ASSERT(rn.Is32Bits() && rm.Is32Bits()); 958 DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x); 959 } 960 961 962 void Assembler::sdiv(const Register& rd, 963 const Register& rn, 964 const Register& rm) { 965 VIXL_ASSERT(rd.size() == rn.size()); 966 VIXL_ASSERT(rd.size() == rm.size()); 967 Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd)); 968 } 969 970 971 void Assembler::smulh(const Register& xd, 972 const Register& xn, 973 const Register& xm) { 974 VIXL_ASSERT(xd.Is64Bits() && xn.Is64Bits() && xm.Is64Bits()); 975 DataProcessing3Source(xd, xn, xm, xzr, SMULH_x); 976 } 977 978 void Assembler::udiv(const Register& rd, 979 const Register& rn, 980 const Register& rm) { 981 VIXL_ASSERT(rd.size() == rn.size()); 982 VIXL_ASSERT(rd.size() == rm.size()); 983 Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd)); 984 } 985 986 987 void Assembler::rbit(const Register& rd, 988 const Register& rn) { 989 DataProcessing1Source(rd, rn, RBIT); 990 } 991 992 993 void Assembler::rev16(const Register& rd, 994 const Register& rn) { 995 DataProcessing1Source(rd, rn, REV16); 996 } 997 998 999 void Assembler::rev32(const Register& rd, 1000 const Register& rn) { 1001 VIXL_ASSERT(rd.Is64Bits()); 1002 DataProcessing1Source(rd, rn, REV); 1003 } 1004 1005 1006 void Assembler::rev(const Register& rd, 1007 const Register& rn) { 1008 DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w); 1009 } 1010 1011 1012 void Assembler::clz(const Register& rd, 1013 const Register& rn) { 1014 DataProcessing1Source(rd, rn, CLZ); 1015 } 1016 1017 1018 void Assembler::cls(const Register& rd, 1019 const Register& rn) { 1020 DataProcessing1Source(rd, rn, CLS); 1021 } 1022 1023 1024 void Assembler::ldp(const CPURegister& rt, 1025 const CPURegister& rt2, 1026 const MemOperand& src) { 1027 LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2)); 1028 } 1029 1030 1031 void Assembler::stp(const CPURegister& rt, 1032 const CPURegister& rt2, 1033 const MemOperand& dst) { 1034 LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2)); 1035 } 1036 1037 1038 void Assembler::ldpsw(const Register& rt, 1039 const Register& rt2, 1040 const MemOperand& src) { 1041 VIXL_ASSERT(rt.Is64Bits()); 1042 LoadStorePair(rt, rt2, src, LDPSW_x); 1043 } 1044 1045 1046 void Assembler::LoadStorePair(const CPURegister& rt, 1047 const CPURegister& rt2, 1048 const MemOperand& addr, 1049 LoadStorePairOp op) { 1050 // 'rt' and 'rt2' can only be aliased for stores. 1051 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2)); 1052 VIXL_ASSERT(AreSameSizeAndType(rt, rt2)); 1053 1054 Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | 1055 ImmLSPair(addr.offset(), CalcLSPairDataSize(op)); 1056 1057 Instr addrmodeop; 1058 if (addr.IsImmediateOffset()) { 1059 addrmodeop = LoadStorePairOffsetFixed; 1060 } else { 1061 VIXL_ASSERT(addr.offset() != 0); 1062 if (addr.IsPreIndex()) { 1063 addrmodeop = LoadStorePairPreIndexFixed; 1064 } else { 1065 VIXL_ASSERT(addr.IsPostIndex()); 1066 addrmodeop = LoadStorePairPostIndexFixed; 1067 } 1068 } 1069 Emit(addrmodeop | memop); 1070 } 1071 1072 1073 void Assembler::ldnp(const CPURegister& rt, 1074 const CPURegister& rt2, 1075 const MemOperand& src) { 1076 LoadStorePairNonTemporal(rt, rt2, src, 1077 LoadPairNonTemporalOpFor(rt, rt2)); 1078 } 1079 1080 1081 void Assembler::stnp(const CPURegister& rt, 1082 const CPURegister& rt2, 1083 const MemOperand& dst) { 1084 LoadStorePairNonTemporal(rt, rt2, dst, 1085 StorePairNonTemporalOpFor(rt, rt2)); 1086 } 1087 1088 1089 void Assembler::LoadStorePairNonTemporal(const CPURegister& rt, 1090 const CPURegister& rt2, 1091 const MemOperand& addr, 1092 LoadStorePairNonTemporalOp op) { 1093 VIXL_ASSERT(!rt.Is(rt2)); 1094 VIXL_ASSERT(AreSameSizeAndType(rt, rt2)); 1095 VIXL_ASSERT(addr.IsImmediateOffset()); 1096 1097 LSDataSize size = CalcLSPairDataSize( 1098 static_cast<LoadStorePairOp>(op & LoadStorePairMask)); 1099 Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | 1100 ImmLSPair(addr.offset(), size)); 1101 } 1102 1103 1104 // Memory instructions. 1105 void Assembler::ldrb(const Register& rt, const MemOperand& src) { 1106 LoadStore(rt, src, LDRB_w); 1107 } 1108 1109 1110 void Assembler::strb(const Register& rt, const MemOperand& dst) { 1111 LoadStore(rt, dst, STRB_w); 1112 } 1113 1114 1115 void Assembler::ldrsb(const Register& rt, const MemOperand& src) { 1116 LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w); 1117 } 1118 1119 1120 void Assembler::ldrh(const Register& rt, const MemOperand& src) { 1121 LoadStore(rt, src, LDRH_w); 1122 } 1123 1124 1125 void Assembler::strh(const Register& rt, const MemOperand& dst) { 1126 LoadStore(rt, dst, STRH_w); 1127 } 1128 1129 1130 void Assembler::ldrsh(const Register& rt, const MemOperand& src) { 1131 LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w); 1132 } 1133 1134 1135 void Assembler::ldr(const CPURegister& rt, const MemOperand& src) { 1136 LoadStore(rt, src, LoadOpFor(rt)); 1137 } 1138 1139 1140 void Assembler::str(const CPURegister& rt, const MemOperand& src) { 1141 LoadStore(rt, src, StoreOpFor(rt)); 1142 } 1143 1144 1145 void Assembler::ldrsw(const Register& rt, const MemOperand& src) { 1146 VIXL_ASSERT(rt.Is64Bits()); 1147 LoadStore(rt, src, LDRSW_x); 1148 } 1149 1150 1151 void Assembler::ldr(const Register& rt, uint64_t imm) { 1152 LoadLiteral(rt, imm, rt.Is64Bits() ? LDR_x_lit : LDR_w_lit); 1153 } 1154 1155 1156 void Assembler::ldr(const FPRegister& ft, double imm) { 1157 VIXL_ASSERT(ft.Is64Bits()); 1158 LoadLiteral(ft, double_to_rawbits(imm), LDR_d_lit); 1159 } 1160 1161 1162 void Assembler::ldr(const FPRegister& ft, float imm) { 1163 VIXL_ASSERT(ft.Is32Bits()); 1164 LoadLiteral(ft, float_to_rawbits(imm), LDR_s_lit); 1165 } 1166 1167 1168 void Assembler::mov(const Register& rd, const Register& rm) { 1169 // Moves involving the stack pointer are encoded as add immediate with 1170 // second operand of zero. Otherwise, orr with first operand zr is 1171 // used. 1172 if (rd.IsSP() || rm.IsSP()) { 1173 add(rd, rm, 0); 1174 } else { 1175 orr(rd, AppropriateZeroRegFor(rd), rm); 1176 } 1177 } 1178 1179 1180 void Assembler::mvn(const Register& rd, const Operand& operand) { 1181 orn(rd, AppropriateZeroRegFor(rd), operand); 1182 } 1183 1184 1185 void Assembler::mrs(const Register& rt, SystemRegister sysreg) { 1186 VIXL_ASSERT(rt.Is64Bits()); 1187 Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt)); 1188 } 1189 1190 1191 void Assembler::msr(SystemRegister sysreg, const Register& rt) { 1192 VIXL_ASSERT(rt.Is64Bits()); 1193 Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg)); 1194 } 1195 1196 1197 void Assembler::hint(SystemHint code) { 1198 Emit(HINT | ImmHint(code) | Rt(xzr)); 1199 } 1200 1201 1202 void Assembler::dmb(BarrierDomain domain, BarrierType type) { 1203 Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type)); 1204 } 1205 1206 1207 void Assembler::dsb(BarrierDomain domain, BarrierType type) { 1208 Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type)); 1209 } 1210 1211 1212 void Assembler::isb() { 1213 Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll)); 1214 } 1215 1216 1217 void Assembler::fmov(const FPRegister& fd, double imm) { 1218 VIXL_ASSERT(fd.Is64Bits()); 1219 VIXL_ASSERT(IsImmFP64(imm)); 1220 Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm)); 1221 } 1222 1223 1224 void Assembler::fmov(const FPRegister& fd, float imm) { 1225 VIXL_ASSERT(fd.Is32Bits()); 1226 VIXL_ASSERT(IsImmFP32(imm)); 1227 Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm)); 1228 } 1229 1230 1231 void Assembler::fmov(const Register& rd, const FPRegister& fn) { 1232 VIXL_ASSERT(rd.size() == fn.size()); 1233 FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd; 1234 Emit(op | Rd(rd) | Rn(fn)); 1235 } 1236 1237 1238 void Assembler::fmov(const FPRegister& fd, const Register& rn) { 1239 VIXL_ASSERT(fd.size() == rn.size()); 1240 FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx; 1241 Emit(op | Rd(fd) | Rn(rn)); 1242 } 1243 1244 1245 void Assembler::fmov(const FPRegister& fd, const FPRegister& fn) { 1246 VIXL_ASSERT(fd.size() == fn.size()); 1247 Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn)); 1248 } 1249 1250 1251 void Assembler::fadd(const FPRegister& fd, 1252 const FPRegister& fn, 1253 const FPRegister& fm) { 1254 FPDataProcessing2Source(fd, fn, fm, FADD); 1255 } 1256 1257 1258 void Assembler::fsub(const FPRegister& fd, 1259 const FPRegister& fn, 1260 const FPRegister& fm) { 1261 FPDataProcessing2Source(fd, fn, fm, FSUB); 1262 } 1263 1264 1265 void Assembler::fmul(const FPRegister& fd, 1266 const FPRegister& fn, 1267 const FPRegister& fm) { 1268 FPDataProcessing2Source(fd, fn, fm, FMUL); 1269 } 1270 1271 1272 void Assembler::fmadd(const FPRegister& fd, 1273 const FPRegister& fn, 1274 const FPRegister& fm, 1275 const FPRegister& fa) { 1276 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d); 1277 } 1278 1279 1280 void Assembler::fmsub(const FPRegister& fd, 1281 const FPRegister& fn, 1282 const FPRegister& fm, 1283 const FPRegister& fa) { 1284 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d); 1285 } 1286 1287 1288 void Assembler::fnmadd(const FPRegister& fd, 1289 const FPRegister& fn, 1290 const FPRegister& fm, 1291 const FPRegister& fa) { 1292 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d); 1293 } 1294 1295 1296 void Assembler::fnmsub(const FPRegister& fd, 1297 const FPRegister& fn, 1298 const FPRegister& fm, 1299 const FPRegister& fa) { 1300 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d); 1301 } 1302 1303 1304 void Assembler::fdiv(const FPRegister& fd, 1305 const FPRegister& fn, 1306 const FPRegister& fm) { 1307 FPDataProcessing2Source(fd, fn, fm, FDIV); 1308 } 1309 1310 1311 void Assembler::fmax(const FPRegister& fd, 1312 const FPRegister& fn, 1313 const FPRegister& fm) { 1314 FPDataProcessing2Source(fd, fn, fm, FMAX); 1315 } 1316 1317 1318 void Assembler::fmaxnm(const FPRegister& fd, 1319 const FPRegister& fn, 1320 const FPRegister& fm) { 1321 FPDataProcessing2Source(fd, fn, fm, FMAXNM); 1322 } 1323 1324 1325 void Assembler::fmin(const FPRegister& fd, 1326 const FPRegister& fn, 1327 const FPRegister& fm) { 1328 FPDataProcessing2Source(fd, fn, fm, FMIN); 1329 } 1330 1331 1332 void Assembler::fminnm(const FPRegister& fd, 1333 const FPRegister& fn, 1334 const FPRegister& fm) { 1335 FPDataProcessing2Source(fd, fn, fm, FMINNM); 1336 } 1337 1338 1339 void Assembler::fabs(const FPRegister& fd, 1340 const FPRegister& fn) { 1341 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1342 FPDataProcessing1Source(fd, fn, FABS); 1343 } 1344 1345 1346 void Assembler::fneg(const FPRegister& fd, 1347 const FPRegister& fn) { 1348 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1349 FPDataProcessing1Source(fd, fn, FNEG); 1350 } 1351 1352 1353 void Assembler::fsqrt(const FPRegister& fd, 1354 const FPRegister& fn) { 1355 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1356 FPDataProcessing1Source(fd, fn, FSQRT); 1357 } 1358 1359 1360 void Assembler::frinta(const FPRegister& fd, 1361 const FPRegister& fn) { 1362 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1363 FPDataProcessing1Source(fd, fn, FRINTA); 1364 } 1365 1366 1367 void Assembler::frintm(const FPRegister& fd, 1368 const FPRegister& fn) { 1369 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1370 FPDataProcessing1Source(fd, fn, FRINTM); 1371 } 1372 1373 1374 void Assembler::frintn(const FPRegister& fd, 1375 const FPRegister& fn) { 1376 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1377 FPDataProcessing1Source(fd, fn, FRINTN); 1378 } 1379 1380 1381 void Assembler::frintz(const FPRegister& fd, 1382 const FPRegister& fn) { 1383 VIXL_ASSERT(fd.SizeInBits() == fn.SizeInBits()); 1384 FPDataProcessing1Source(fd, fn, FRINTZ); 1385 } 1386 1387 1388 void Assembler::fcmp(const FPRegister& fn, 1389 const FPRegister& fm) { 1390 VIXL_ASSERT(fn.size() == fm.size()); 1391 Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn)); 1392 } 1393 1394 1395 void Assembler::fcmp(const FPRegister& fn, 1396 double value) { 1397 USE(value); 1398 // Although the fcmp instruction can strictly only take an immediate value of 1399 // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't 1400 // affect the result of the comparison. 1401 VIXL_ASSERT(value == 0.0); 1402 Emit(FPType(fn) | FCMP_zero | Rn(fn)); 1403 } 1404 1405 1406 void Assembler::fccmp(const FPRegister& fn, 1407 const FPRegister& fm, 1408 StatusFlags nzcv, 1409 Condition cond) { 1410 VIXL_ASSERT(fn.size() == fm.size()); 1411 Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv)); 1412 } 1413 1414 1415 void Assembler::fcsel(const FPRegister& fd, 1416 const FPRegister& fn, 1417 const FPRegister& fm, 1418 Condition cond) { 1419 VIXL_ASSERT(fd.size() == fn.size()); 1420 VIXL_ASSERT(fd.size() == fm.size()); 1421 Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd)); 1422 } 1423 1424 1425 void Assembler::FPConvertToInt(const Register& rd, 1426 const FPRegister& fn, 1427 FPIntegerConvertOp op) { 1428 Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd)); 1429 } 1430 1431 1432 void Assembler::fcvt(const FPRegister& fd, 1433 const FPRegister& fn) { 1434 if (fd.Is64Bits()) { 1435 // Convert float to double. 1436 VIXL_ASSERT(fn.Is32Bits()); 1437 FPDataProcessing1Source(fd, fn, FCVT_ds); 1438 } else { 1439 // Convert double to float. 1440 VIXL_ASSERT(fn.Is64Bits()); 1441 FPDataProcessing1Source(fd, fn, FCVT_sd); 1442 } 1443 } 1444 1445 1446 void Assembler::fcvtau(const Register& rd, const FPRegister& fn) { 1447 FPConvertToInt(rd, fn, FCVTAU); 1448 } 1449 1450 1451 void Assembler::fcvtas(const Register& rd, const FPRegister& fn) { 1452 FPConvertToInt(rd, fn, FCVTAS); 1453 } 1454 1455 1456 void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) { 1457 FPConvertToInt(rd, fn, FCVTMU); 1458 } 1459 1460 1461 void Assembler::fcvtms(const Register& rd, const FPRegister& fn) { 1462 FPConvertToInt(rd, fn, FCVTMS); 1463 } 1464 1465 1466 void Assembler::fcvtnu(const Register& rd, const FPRegister& fn) { 1467 FPConvertToInt(rd, fn, FCVTNU); 1468 } 1469 1470 1471 void Assembler::fcvtns(const Register& rd, const FPRegister& fn) { 1472 FPConvertToInt(rd, fn, FCVTNS); 1473 } 1474 1475 1476 void Assembler::fcvtzu(const Register& rd, const FPRegister& fn) { 1477 FPConvertToInt(rd, fn, FCVTZU); 1478 } 1479 1480 1481 void Assembler::fcvtzs(const Register& rd, const FPRegister& fn) { 1482 FPConvertToInt(rd, fn, FCVTZS); 1483 } 1484 1485 1486 void Assembler::scvtf(const FPRegister& fd, 1487 const Register& rn, 1488 unsigned fbits) { 1489 if (fbits == 0) { 1490 Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd)); 1491 } else { 1492 Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | 1493 Rd(fd)); 1494 } 1495 } 1496 1497 1498 void Assembler::ucvtf(const FPRegister& fd, 1499 const Register& rn, 1500 unsigned fbits) { 1501 if (fbits == 0) { 1502 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); 1503 } else { 1504 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | 1505 Rd(fd)); 1506 } 1507 } 1508 1509 1510 // Note: 1511 // Below, a difference in case for the same letter indicates a 1512 // negated bit. 1513 // If b is 1, then B is 0. 1514 Instr Assembler::ImmFP32(float imm) { 1515 VIXL_ASSERT(IsImmFP32(imm)); 1516 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 1517 uint32_t bits = float_to_rawbits(imm); 1518 // bit7: a000.0000 1519 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; 1520 // bit6: 0b00.0000 1521 uint32_t bit6 = ((bits >> 29) & 0x1) << 6; 1522 // bit5_to_0: 00cd.efgh 1523 uint32_t bit5_to_0 = (bits >> 19) & 0x3f; 1524 1525 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; 1526 } 1527 1528 1529 Instr Assembler::ImmFP64(double imm) { 1530 VIXL_ASSERT(IsImmFP64(imm)); 1531 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 1532 // 0000.0000.0000.0000.0000.0000.0000.0000 1533 uint64_t bits = double_to_rawbits(imm); 1534 // bit7: a000.0000 1535 uint32_t bit7 = ((bits >> 63) & 0x1) << 7; 1536 // bit6: 0b00.0000 1537 uint32_t bit6 = ((bits >> 61) & 0x1) << 6; 1538 // bit5_to_0: 00cd.efgh 1539 uint32_t bit5_to_0 = (bits >> 48) & 0x3f; 1540 1541 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; 1542 } 1543 1544 1545 // Code generation helpers. 1546 void Assembler::MoveWide(const Register& rd, 1547 uint64_t imm, 1548 int shift, 1549 MoveWideImmediateOp mov_op) { 1550 if (shift >= 0) { 1551 // Explicit shift specified. 1552 VIXL_ASSERT((shift == 0) || (shift == 16) || 1553 (shift == 32) || (shift == 48)); 1554 VIXL_ASSERT(rd.Is64Bits() || (shift == 0) || (shift == 16)); 1555 shift /= 16; 1556 } else { 1557 // Calculate a new immediate and shift combination to encode the immediate 1558 // argument. 1559 shift = 0; 1560 if ((imm & UINT64_C(0xffffffffffff0000)) == 0) { 1561 // Nothing to do. 1562 } else if ((imm & UINT64_C(0xffffffff0000ffff)) == 0) { 1563 imm >>= 16; 1564 shift = 1; 1565 } else if ((imm & UINT64_C(0xffff0000ffffffff)) == 0) { 1566 VIXL_ASSERT(rd.Is64Bits()); 1567 imm >>= 32; 1568 shift = 2; 1569 } else if ((imm & UINT64_C(0x0000ffffffffffff)) == 0) { 1570 VIXL_ASSERT(rd.Is64Bits()); 1571 imm >>= 48; 1572 shift = 3; 1573 } 1574 } 1575 1576 VIXL_ASSERT(is_uint16(imm)); 1577 1578 Emit(SF(rd) | MoveWideImmediateFixed | mov_op | 1579 Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift)); 1580 } 1581 1582 1583 void Assembler::AddSub(const Register& rd, 1584 const Register& rn, 1585 const Operand& operand, 1586 FlagsUpdate S, 1587 AddSubOp op) { 1588 VIXL_ASSERT(rd.size() == rn.size()); 1589 if (operand.IsImmediate()) { 1590 int64_t immediate = operand.immediate(); 1591 VIXL_ASSERT(IsImmAddSub(immediate)); 1592 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); 1593 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) | 1594 ImmAddSub(immediate) | dest_reg | RnSP(rn)); 1595 } else if (operand.IsShiftedRegister()) { 1596 VIXL_ASSERT(operand.reg().size() == rd.size()); 1597 VIXL_ASSERT(operand.shift() != ROR); 1598 1599 // For instructions of the form: 1600 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ] 1601 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ] 1602 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ] 1603 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ] 1604 // or their 64-bit register equivalents, convert the operand from shifted to 1605 // extended register mode, and emit an add/sub extended instruction. 1606 if (rn.IsSP() || rd.IsSP()) { 1607 VIXL_ASSERT(!(rd.IsSP() && (S == SetFlags))); 1608 DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S, 1609 AddSubExtendedFixed | op); 1610 } else { 1611 DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op); 1612 } 1613 } else { 1614 VIXL_ASSERT(operand.IsExtendedRegister()); 1615 DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op); 1616 } 1617 } 1618 1619 1620 void Assembler::AddSubWithCarry(const Register& rd, 1621 const Register& rn, 1622 const Operand& operand, 1623 FlagsUpdate S, 1624 AddSubWithCarryOp op) { 1625 VIXL_ASSERT(rd.size() == rn.size()); 1626 VIXL_ASSERT(rd.size() == operand.reg().size()); 1627 VIXL_ASSERT(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); 1628 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd)); 1629 } 1630 1631 1632 void Assembler::hlt(int code) { 1633 VIXL_ASSERT(is_uint16(code)); 1634 Emit(HLT | ImmException(code)); 1635 } 1636 1637 1638 void Assembler::brk(int code) { 1639 VIXL_ASSERT(is_uint16(code)); 1640 Emit(BRK | ImmException(code)); 1641 } 1642 1643 1644 void Assembler::Logical(const Register& rd, 1645 const Register& rn, 1646 const Operand& operand, 1647 LogicalOp op) { 1648 VIXL_ASSERT(rd.size() == rn.size()); 1649 if (operand.IsImmediate()) { 1650 int64_t immediate = operand.immediate(); 1651 unsigned reg_size = rd.size(); 1652 1653 VIXL_ASSERT(immediate != 0); 1654 VIXL_ASSERT(immediate != -1); 1655 VIXL_ASSERT(rd.Is64Bits() || is_uint32(immediate)); 1656 1657 // If the operation is NOT, invert the operation and immediate. 1658 if ((op & NOT) == NOT) { 1659 op = static_cast<LogicalOp>(op & ~NOT); 1660 immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask); 1661 } 1662 1663 unsigned n, imm_s, imm_r; 1664 if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) { 1665 // Immediate can be encoded in the instruction. 1666 LogicalImmediate(rd, rn, n, imm_s, imm_r, op); 1667 } else { 1668 // This case is handled in the macro assembler. 1669 VIXL_UNREACHABLE(); 1670 } 1671 } else { 1672 VIXL_ASSERT(operand.IsShiftedRegister()); 1673 VIXL_ASSERT(operand.reg().size() == rd.size()); 1674 Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed); 1675 DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op); 1676 } 1677 } 1678 1679 1680 void Assembler::LogicalImmediate(const Register& rd, 1681 const Register& rn, 1682 unsigned n, 1683 unsigned imm_s, 1684 unsigned imm_r, 1685 LogicalOp op) { 1686 unsigned reg_size = rd.size(); 1687 Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd); 1688 Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) | 1689 ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg | 1690 Rn(rn)); 1691 } 1692 1693 1694 void Assembler::ConditionalCompare(const Register& rn, 1695 const Operand& operand, 1696 StatusFlags nzcv, 1697 Condition cond, 1698 ConditionalCompareOp op) { 1699 Instr ccmpop; 1700 if (operand.IsImmediate()) { 1701 int64_t immediate = operand.immediate(); 1702 VIXL_ASSERT(IsImmConditionalCompare(immediate)); 1703 ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate); 1704 } else { 1705 VIXL_ASSERT(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); 1706 ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg()); 1707 } 1708 Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv)); 1709 } 1710 1711 1712 void Assembler::DataProcessing1Source(const Register& rd, 1713 const Register& rn, 1714 DataProcessing1SourceOp op) { 1715 VIXL_ASSERT(rd.size() == rn.size()); 1716 Emit(SF(rn) | op | Rn(rn) | Rd(rd)); 1717 } 1718 1719 1720 void Assembler::FPDataProcessing1Source(const FPRegister& fd, 1721 const FPRegister& fn, 1722 FPDataProcessing1SourceOp op) { 1723 Emit(FPType(fn) | op | Rn(fn) | Rd(fd)); 1724 } 1725 1726 1727 void Assembler::FPDataProcessing2Source(const FPRegister& fd, 1728 const FPRegister& fn, 1729 const FPRegister& fm, 1730 FPDataProcessing2SourceOp op) { 1731 VIXL_ASSERT(fd.size() == fn.size()); 1732 VIXL_ASSERT(fd.size() == fm.size()); 1733 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd)); 1734 } 1735 1736 1737 void Assembler::FPDataProcessing3Source(const FPRegister& fd, 1738 const FPRegister& fn, 1739 const FPRegister& fm, 1740 const FPRegister& fa, 1741 FPDataProcessing3SourceOp op) { 1742 VIXL_ASSERT(AreSameSizeAndType(fd, fn, fm, fa)); 1743 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa)); 1744 } 1745 1746 1747 void Assembler::EmitShift(const Register& rd, 1748 const Register& rn, 1749 Shift shift, 1750 unsigned shift_amount) { 1751 switch (shift) { 1752 case LSL: 1753 lsl(rd, rn, shift_amount); 1754 break; 1755 case LSR: 1756 lsr(rd, rn, shift_amount); 1757 break; 1758 case ASR: 1759 asr(rd, rn, shift_amount); 1760 break; 1761 case ROR: 1762 ror(rd, rn, shift_amount); 1763 break; 1764 default: 1765 VIXL_UNREACHABLE(); 1766 } 1767 } 1768 1769 1770 void Assembler::EmitExtendShift(const Register& rd, 1771 const Register& rn, 1772 Extend extend, 1773 unsigned left_shift) { 1774 VIXL_ASSERT(rd.size() >= rn.size()); 1775 unsigned reg_size = rd.size(); 1776 // Use the correct size of register. 1777 Register rn_ = Register(rn.code(), rd.size()); 1778 // Bits extracted are high_bit:0. 1779 unsigned high_bit = (8 << (extend & 0x3)) - 1; 1780 // Number of bits left in the result that are not introduced by the shift. 1781 unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1); 1782 1783 if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) { 1784 switch (extend) { 1785 case UXTB: 1786 case UXTH: 1787 case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break; 1788 case SXTB: 1789 case SXTH: 1790 case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break; 1791 case UXTX: 1792 case SXTX: { 1793 VIXL_ASSERT(rn.size() == kXRegSize); 1794 // Nothing to extend. Just shift. 1795 lsl(rd, rn_, left_shift); 1796 break; 1797 } 1798 default: VIXL_UNREACHABLE(); 1799 } 1800 } else { 1801 // No need to extend as the extended bits would be shifted away. 1802 lsl(rd, rn_, left_shift); 1803 } 1804 } 1805 1806 1807 void Assembler::DataProcShiftedRegister(const Register& rd, 1808 const Register& rn, 1809 const Operand& operand, 1810 FlagsUpdate S, 1811 Instr op) { 1812 VIXL_ASSERT(operand.IsShiftedRegister()); 1813 VIXL_ASSERT(rn.Is64Bits() || (rn.Is32Bits() && 1814 is_uint5(operand.shift_amount()))); 1815 Emit(SF(rd) | op | Flags(S) | 1816 ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) | 1817 Rm(operand.reg()) | Rn(rn) | Rd(rd)); 1818 } 1819 1820 1821 void Assembler::DataProcExtendedRegister(const Register& rd, 1822 const Register& rn, 1823 const Operand& operand, 1824 FlagsUpdate S, 1825 Instr op) { 1826 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); 1827 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | 1828 ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) | 1829 dest_reg | RnSP(rn)); 1830 } 1831 1832 1833 bool Assembler::IsImmAddSub(int64_t immediate) { 1834 return is_uint12(immediate) || 1835 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0)); 1836 } 1837 1838 void Assembler::LoadStore(const CPURegister& rt, 1839 const MemOperand& addr, 1840 LoadStoreOp op) { 1841 Instr memop = op | Rt(rt) | RnSP(addr.base()); 1842 ptrdiff_t offset = addr.offset(); 1843 1844 if (addr.IsImmediateOffset()) { 1845 LSDataSize size = CalcLSDataSize(op); 1846 if (IsImmLSScaled(offset, size)) { 1847 // Use the scaled addressing mode. 1848 Emit(LoadStoreUnsignedOffsetFixed | memop | 1849 ImmLSUnsigned(offset >> size)); 1850 } else if (IsImmLSUnscaled(offset)) { 1851 // Use the unscaled addressing mode. 1852 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset)); 1853 } else { 1854 // This case is handled in the macro assembler. 1855 VIXL_UNREACHABLE(); 1856 } 1857 } else if (addr.IsRegisterOffset()) { 1858 Extend ext = addr.extend(); 1859 Shift shift = addr.shift(); 1860 unsigned shift_amount = addr.shift_amount(); 1861 1862 // LSL is encoded in the option field as UXTX. 1863 if (shift == LSL) { 1864 ext = UXTX; 1865 } 1866 1867 // Shifts are encoded in one bit, indicating a left shift by the memory 1868 // access size. 1869 VIXL_ASSERT((shift_amount == 0) || 1870 (shift_amount == static_cast<unsigned>(CalcLSDataSize(op)))); 1871 Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) | 1872 ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0)); 1873 } else { 1874 if (IsImmLSUnscaled(offset)) { 1875 if (addr.IsPreIndex()) { 1876 Emit(LoadStorePreIndexFixed | memop | ImmLS(offset)); 1877 } else { 1878 VIXL_ASSERT(addr.IsPostIndex()); 1879 Emit(LoadStorePostIndexFixed | memop | ImmLS(offset)); 1880 } 1881 } else { 1882 // This case is handled in the macro assembler. 1883 VIXL_UNREACHABLE(); 1884 } 1885 } 1886 } 1887 1888 1889 bool Assembler::IsImmLSUnscaled(ptrdiff_t offset) { 1890 return is_int9(offset); 1891 } 1892 1893 1894 bool Assembler::IsImmLSScaled(ptrdiff_t offset, LSDataSize size) { 1895 bool offset_is_size_multiple = (((offset >> size) << size) == offset); 1896 return offset_is_size_multiple && is_uint12(offset >> size); 1897 } 1898 1899 1900 void Assembler::LoadLiteral(const CPURegister& rt, 1901 uint64_t imm, 1902 LoadLiteralOp op) { 1903 VIXL_ASSERT(is_int32(imm) || is_uint32(imm) || (rt.Is64Bits())); 1904 1905 BlockLiteralPoolScope scope(this); 1906 RecordLiteral(imm, rt.SizeInBytes()); 1907 Emit(op | ImmLLiteral(0) | Rt(rt)); 1908 } 1909 1910 1911 // Test if a given value can be encoded in the immediate field of a logical 1912 // instruction. 1913 // If it can be encoded, the function returns true, and values pointed to by n, 1914 // imm_s and imm_r are updated with immediates encoded in the format required 1915 // by the corresponding fields in the logical instruction. 1916 // If it can not be encoded, the function returns false, and the values pointed 1917 // to by n, imm_s and imm_r are undefined. 1918 bool Assembler::IsImmLogical(uint64_t value, 1919 unsigned width, 1920 unsigned* n, 1921 unsigned* imm_s, 1922 unsigned* imm_r) { 1923 VIXL_ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL)); 1924 VIXL_ASSERT((width == kWRegSize) || (width == kXRegSize)); 1925 1926 // Logical immediates are encoded using parameters n, imm_s and imm_r using 1927 // the following table: 1928 // 1929 // N imms immr size S R 1930 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) 1931 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) 1932 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) 1933 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) 1934 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) 1935 // 0 11110s xxxxxr 2 UInt(s) UInt(r) 1936 // (s bits must not be all set) 1937 // 1938 // A pattern is constructed of size bits, where the least significant S+1 1939 // bits are set. The pattern is rotated right by R, and repeated across a 1940 // 32 or 64-bit value, depending on destination register width. 1941 // 1942 // To test if an arbitrary immediate can be encoded using this scheme, an 1943 // iterative algorithm is used. 1944 // 1945 // TODO: This code does not consider using X/W register overlap to support 1946 // 64-bit immediates where the top 32-bits are zero, and the bottom 32-bits 1947 // are an encodable logical immediate. 1948 1949 // 1. If the value has all set or all clear bits, it can't be encoded. 1950 if ((value == 0) || (value == kXRegMask) || 1951 ((width == kWRegSize) && (value == kWRegMask))) { 1952 return false; 1953 } 1954 1955 unsigned lead_zero = CountLeadingZeros(value, width); 1956 unsigned lead_one = CountLeadingZeros(~value, width); 1957 unsigned trail_zero = CountTrailingZeros(value, width); 1958 unsigned trail_one = CountTrailingZeros(~value, width); 1959 unsigned set_bits = CountSetBits(value, width); 1960 1961 // The fixed bits in the immediate s field. 1962 // If width == 64 (X reg), start at 0xFFFFFF80. 1963 // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit 1964 // widths won't be executed. 1965 int imm_s_fixed = (width == kXRegSize) ? -128 : -64; 1966 int imm_s_mask = 0x3F; 1967 1968 for (;;) { 1969 // 2. If the value is two bits wide, it can be encoded. 1970 if (width == 2) { 1971 *n = 0; 1972 *imm_s = 0x3C; 1973 *imm_r = (value & 3) - 1; 1974 return true; 1975 } 1976 1977 *n = (width == 64) ? 1 : 0; 1978 *imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask); 1979 if ((lead_zero + set_bits) == width) { 1980 *imm_r = 0; 1981 } else { 1982 *imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one; 1983 } 1984 1985 // 3. If the sum of leading zeros, trailing zeros and set bits is equal to 1986 // the bit width of the value, it can be encoded. 1987 if (lead_zero + trail_zero + set_bits == width) { 1988 return true; 1989 } 1990 1991 // 4. If the sum of leading ones, trailing ones and unset bits in the 1992 // value is equal to the bit width of the value, it can be encoded. 1993 if (lead_one + trail_one + (width - set_bits) == width) { 1994 return true; 1995 } 1996 1997 // 5. If the most-significant half of the bitwise value is equal to the 1998 // least-significant half, return to step 2 using the least-significant 1999 // half of the value. 2000 uint64_t mask = (UINT64_C(1) << (width >> 1)) - 1; 2001 if ((value & mask) == ((value >> (width >> 1)) & mask)) { 2002 width >>= 1; 2003 set_bits >>= 1; 2004 imm_s_fixed >>= 1; 2005 continue; 2006 } 2007 2008 // 6. Otherwise, the value can't be encoded. 2009 return false; 2010 } 2011 } 2012 2013 bool Assembler::IsImmConditionalCompare(int64_t immediate) { 2014 return is_uint5(immediate); 2015 } 2016 2017 2018 bool Assembler::IsImmFP32(float imm) { 2019 // Valid values will have the form: 2020 // aBbb.bbbc.defg.h000.0000.0000.0000.0000 2021 uint32_t bits = float_to_rawbits(imm); 2022 // bits[19..0] are cleared. 2023 if ((bits & 0x7ffff) != 0) { 2024 return false; 2025 } 2026 2027 // bits[29..25] are all set or all cleared. 2028 uint32_t b_pattern = (bits >> 16) & 0x3e00; 2029 if (b_pattern != 0 && b_pattern != 0x3e00) { 2030 return false; 2031 } 2032 2033 // bit[30] and bit[29] are opposite. 2034 if (((bits ^ (bits << 1)) & 0x40000000) == 0) { 2035 return false; 2036 } 2037 2038 return true; 2039 } 2040 2041 2042 bool Assembler::IsImmFP64(double imm) { 2043 // Valid values will have the form: 2044 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 2045 // 0000.0000.0000.0000.0000.0000.0000.0000 2046 uint64_t bits = double_to_rawbits(imm); 2047 // bits[47..0] are cleared. 2048 if ((bits & UINT64_C(0x0000ffffffffffff)) != 0) { 2049 return false; 2050 } 2051 2052 // bits[61..54] are all set or all cleared. 2053 uint32_t b_pattern = (bits >> 48) & 0x3fc0; 2054 if ((b_pattern != 0) && (b_pattern != 0x3fc0)) { 2055 return false; 2056 } 2057 2058 // bit[62] and bit[61] are opposite. 2059 if (((bits ^ (bits << 1)) & (UINT64_C(1) << 62)) == 0) { 2060 return false; 2061 } 2062 2063 return true; 2064 } 2065 2066 2067 LoadStoreOp Assembler::LoadOpFor(const CPURegister& rt) { 2068 VIXL_ASSERT(rt.IsValid()); 2069 if (rt.IsRegister()) { 2070 return rt.Is64Bits() ? LDR_x : LDR_w; 2071 } else { 2072 VIXL_ASSERT(rt.IsFPRegister()); 2073 return rt.Is64Bits() ? LDR_d : LDR_s; 2074 } 2075 } 2076 2077 2078 LoadStorePairOp Assembler::LoadPairOpFor(const CPURegister& rt, 2079 const CPURegister& rt2) { 2080 VIXL_ASSERT(AreSameSizeAndType(rt, rt2)); 2081 USE(rt2); 2082 if (rt.IsRegister()) { 2083 return rt.Is64Bits() ? LDP_x : LDP_w; 2084 } else { 2085 VIXL_ASSERT(rt.IsFPRegister()); 2086 return rt.Is64Bits() ? LDP_d : LDP_s; 2087 } 2088 } 2089 2090 2091 LoadStoreOp Assembler::StoreOpFor(const CPURegister& rt) { 2092 VIXL_ASSERT(rt.IsValid()); 2093 if (rt.IsRegister()) { 2094 return rt.Is64Bits() ? STR_x : STR_w; 2095 } else { 2096 VIXL_ASSERT(rt.IsFPRegister()); 2097 return rt.Is64Bits() ? STR_d : STR_s; 2098 } 2099 } 2100 2101 2102 LoadStorePairOp Assembler::StorePairOpFor(const CPURegister& rt, 2103 const CPURegister& rt2) { 2104 VIXL_ASSERT(AreSameSizeAndType(rt, rt2)); 2105 USE(rt2); 2106 if (rt.IsRegister()) { 2107 return rt.Is64Bits() ? STP_x : STP_w; 2108 } else { 2109 VIXL_ASSERT(rt.IsFPRegister()); 2110 return rt.Is64Bits() ? STP_d : STP_s; 2111 } 2112 } 2113 2114 2115 LoadStorePairNonTemporalOp Assembler::LoadPairNonTemporalOpFor( 2116 const CPURegister& rt, const CPURegister& rt2) { 2117 VIXL_ASSERT(AreSameSizeAndType(rt, rt2)); 2118 USE(rt2); 2119 if (rt.IsRegister()) { 2120 return rt.Is64Bits() ? LDNP_x : LDNP_w; 2121 } else { 2122 VIXL_ASSERT(rt.IsFPRegister()); 2123 return rt.Is64Bits() ? LDNP_d : LDNP_s; 2124 } 2125 } 2126 2127 2128 LoadStorePairNonTemporalOp Assembler::StorePairNonTemporalOpFor( 2129 const CPURegister& rt, const CPURegister& rt2) { 2130 VIXL_ASSERT(AreSameSizeAndType(rt, rt2)); 2131 USE(rt2); 2132 if (rt.IsRegister()) { 2133 return rt.Is64Bits() ? STNP_x : STNP_w; 2134 } else { 2135 VIXL_ASSERT(rt.IsFPRegister()); 2136 return rt.Is64Bits() ? STNP_d : STNP_s; 2137 } 2138 } 2139 2140 2141 void Assembler::RecordLiteral(int64_t imm, unsigned size) { 2142 literals_.push_front(new Literal(pc_, imm, size)); 2143 } 2144 2145 2146 // Check if a literal pool should be emitted. Currently a literal is emitted 2147 // when: 2148 // * the distance to the first literal load handled by this pool is greater 2149 // than the recommended distance and the literal pool can be emitted without 2150 // generating a jump over it. 2151 // * the distance to the first literal load handled by this pool is greater 2152 // than twice the recommended distance. 2153 // TODO: refine this heuristic using real world data. 2154 void Assembler::CheckLiteralPool(LiteralPoolEmitOption option) { 2155 if (IsLiteralPoolBlocked()) { 2156 // Literal pool emission is forbidden, no point in doing further checks. 2157 return; 2158 } 2159 2160 if (literals_.empty()) { 2161 // No literal pool to emit. 2162 next_literal_pool_check_ += kLiteralPoolCheckInterval; 2163 return; 2164 } 2165 2166 intptr_t distance = pc_ - literals_.back()->pc_; 2167 if ((distance < kRecommendedLiteralPoolRange) || 2168 ((option == JumpRequired) && 2169 (distance < (2 * kRecommendedLiteralPoolRange)))) { 2170 // We prefer not to have to jump over the literal pool. 2171 next_literal_pool_check_ += kLiteralPoolCheckInterval; 2172 return; 2173 } 2174 2175 EmitLiteralPool(option); 2176 } 2177 2178 2179 void Assembler::EmitLiteralPool(LiteralPoolEmitOption option) { 2180 // Prevent recursive calls while emitting the literal pool. 2181 BlockLiteralPoolScope scope(this); 2182 2183 Label marker; 2184 Label start_of_pool; 2185 Label end_of_pool; 2186 2187 if (option == JumpRequired) { 2188 b(&end_of_pool); 2189 } 2190 2191 // Leave space for a literal pool marker. This is populated later, once the 2192 // size of the pool is known. 2193 bind(&marker); 2194 nop(); 2195 2196 // Now populate the literal pool. 2197 bind(&start_of_pool); 2198 std::list<Literal*>::iterator it; 2199 for (it = literals_.begin(); it != literals_.end(); it++) { 2200 // Update the load-literal instruction to point to this pool entry. 2201 Instruction* load_literal = (*it)->pc_; 2202 load_literal->SetImmLLiteral(pc_); 2203 // Copy the data into the pool. 2204 uint64_t value= (*it)->value_; 2205 unsigned size = (*it)->size_; 2206 VIXL_ASSERT((size == kXRegSizeInBytes) || (size == kWRegSizeInBytes)); 2207 VIXL_ASSERT((pc_ + size) <= (buffer_ + buffer_size_)); 2208 memcpy(pc_, &value, size); 2209 pc_ += size; 2210 delete *it; 2211 } 2212 literals_.clear(); 2213 bind(&end_of_pool); 2214 2215 // The pool size should always be a multiple of four bytes because that is the 2216 // scaling applied by the LDR(literal) instruction, even for X-register loads. 2217 VIXL_ASSERT((SizeOfCodeGeneratedSince(&start_of_pool) % 4) == 0); 2218 uint64_t pool_size = SizeOfCodeGeneratedSince(&start_of_pool) / 4; 2219 2220 // Literal pool marker indicating the size in words of the literal pool. 2221 // We use a literal load to the zero register, the offset indicating the 2222 // size in words. This instruction can encode a large enough offset to span 2223 // the entire pool at its maximum size. 2224 Instr marker_instruction = LDR_x_lit | ImmLLiteral(pool_size) | Rt(xzr); 2225 memcpy(marker.target(), &marker_instruction, kInstructionSize); 2226 2227 next_literal_pool_check_ = pc_ + kLiteralPoolCheckInterval; 2228 } 2229 2230 2231 // Return the size in bytes, required by the literal pool entries. This does 2232 // not include any marker or branch over the literal pool itself. 2233 size_t Assembler::LiteralPoolSize() { 2234 size_t size = 0; 2235 2236 std::list<Literal*>::iterator it; 2237 for (it = literals_.begin(); it != literals_.end(); it++) { 2238 size += (*it)->size_; 2239 } 2240 2241 return size; 2242 } 2243 2244 2245 bool AreAliased(const CPURegister& reg1, const CPURegister& reg2, 2246 const CPURegister& reg3, const CPURegister& reg4, 2247 const CPURegister& reg5, const CPURegister& reg6, 2248 const CPURegister& reg7, const CPURegister& reg8) { 2249 int number_of_valid_regs = 0; 2250 int number_of_valid_fpregs = 0; 2251 2252 RegList unique_regs = 0; 2253 RegList unique_fpregs = 0; 2254 2255 const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8}; 2256 2257 for (unsigned i = 0; i < sizeof(regs) / sizeof(regs[0]); i++) { 2258 if (regs[i].IsRegister()) { 2259 number_of_valid_regs++; 2260 unique_regs |= regs[i].Bit(); 2261 } else if (regs[i].IsFPRegister()) { 2262 number_of_valid_fpregs++; 2263 unique_fpregs |= regs[i].Bit(); 2264 } else { 2265 VIXL_ASSERT(!regs[i].IsValid()); 2266 } 2267 } 2268 2269 int number_of_unique_regs = 2270 CountSetBits(unique_regs, sizeof(unique_regs) * 8); 2271 int number_of_unique_fpregs = 2272 CountSetBits(unique_fpregs, sizeof(unique_fpregs) * 8); 2273 2274 VIXL_ASSERT(number_of_valid_regs >= number_of_unique_regs); 2275 VIXL_ASSERT(number_of_valid_fpregs >= number_of_unique_fpregs); 2276 2277 return (number_of_valid_regs != number_of_unique_regs) || 2278 (number_of_valid_fpregs != number_of_unique_fpregs); 2279 } 2280 2281 2282 bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2, 2283 const CPURegister& reg3, const CPURegister& reg4, 2284 const CPURegister& reg5, const CPURegister& reg6, 2285 const CPURegister& reg7, const CPURegister& reg8) { 2286 VIXL_ASSERT(reg1.IsValid()); 2287 bool match = true; 2288 match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1); 2289 match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1); 2290 match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1); 2291 match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1); 2292 match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1); 2293 match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1); 2294 match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1); 2295 return match; 2296 } 2297 2298 2299 } // namespace vixl 2300