assembler_arm.cc revision 7655f29fabc0a12765de828914a18314382e5a35
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "assembler_arm.h" 18 19#include "base/logging.h" 20#include "entrypoints/quick/quick_entrypoints.h" 21#include "offsets.h" 22#include "thread.h" 23#include "utils.h" 24 25namespace art { 26namespace arm { 27 28// Instruction encoding bits. 29enum { 30 H = 1 << 5, // halfword (or byte) 31 L = 1 << 20, // load (or store) 32 S = 1 << 20, // set condition code (or leave unchanged) 33 W = 1 << 21, // writeback base register (or leave unchanged) 34 A = 1 << 21, // accumulate in multiply instruction (or not) 35 B = 1 << 22, // unsigned byte (or word) 36 N = 1 << 22, // long (or short) 37 U = 1 << 23, // positive (or negative) offset/index 38 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) 39 I = 1 << 25, // immediate shifter operand (or not) 40 41 B0 = 1, 42 B1 = 1 << 1, 43 B2 = 1 << 2, 44 B3 = 1 << 3, 45 B4 = 1 << 4, 46 B5 = 1 << 5, 47 B6 = 1 << 6, 48 B7 = 1 << 7, 49 B8 = 1 << 8, 50 B9 = 1 << 9, 51 B10 = 1 << 10, 52 B11 = 1 << 11, 53 B12 = 1 << 12, 54 B16 = 1 << 16, 55 B17 = 1 << 17, 56 B18 = 1 << 18, 57 B19 = 1 << 19, 58 B20 = 1 << 20, 59 B21 = 1 << 21, 60 B22 = 1 << 22, 61 B23 = 1 << 23, 62 B24 = 1 << 24, 63 B25 = 1 << 25, 64 B26 = 1 << 26, 65 B27 = 1 << 27, 66 67 // Instruction bit masks. 68 RdMask = 15 << 12, // in str instruction 69 CondMask = 15 << 28, 70 CoprocessorMask = 15 << 8, 71 OpCodeMask = 15 << 21, // in data-processing instructions 72 Imm24Mask = (1 << 24) - 1, 73 Off12Mask = (1 << 12) - 1, 74 75 // ldrex/strex register field encodings. 76 kLdExRnShift = 16, 77 kLdExRtShift = 12, 78 kStrExRnShift = 16, 79 kStrExRdShift = 12, 80 kStrExRtShift = 0, 81}; 82 83 84static const char* kRegisterNames[] = { 85 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 86 "fp", "ip", "sp", "lr", "pc" 87}; 88std::ostream& operator<<(std::ostream& os, const Register& rhs) { 89 if (rhs >= R0 && rhs <= PC) { 90 os << kRegisterNames[rhs]; 91 } else { 92 os << "Register[" << static_cast<int>(rhs) << "]"; 93 } 94 return os; 95} 96 97 98std::ostream& operator<<(std::ostream& os, const SRegister& rhs) { 99 if (rhs >= S0 && rhs < kNumberOfSRegisters) { 100 os << "s" << static_cast<int>(rhs); 101 } else { 102 os << "SRegister[" << static_cast<int>(rhs) << "]"; 103 } 104 return os; 105} 106 107 108std::ostream& operator<<(std::ostream& os, const DRegister& rhs) { 109 if (rhs >= D0 && rhs < kNumberOfDRegisters) { 110 os << "d" << static_cast<int>(rhs); 111 } else { 112 os << "DRegister[" << static_cast<int>(rhs) << "]"; 113 } 114 return os; 115} 116 117 118static const char* kConditionNames[] = { 119 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", 120 "LE", "AL", 121}; 122std::ostream& operator<<(std::ostream& os, const Condition& rhs) { 123 if (rhs >= EQ && rhs <= AL) { 124 os << kConditionNames[rhs]; 125 } else { 126 os << "Condition[" << static_cast<int>(rhs) << "]"; 127 } 128 return os; 129} 130 131void ArmAssembler::Emit(int32_t value) { 132 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 133 buffer_.Emit<int32_t>(value); 134} 135 136 137void ArmAssembler::EmitType01(Condition cond, 138 int type, 139 Opcode opcode, 140 int set_cc, 141 Register rn, 142 Register rd, 143 ShifterOperand so) { 144 CHECK_NE(rd, kNoRegister); 145 CHECK_NE(cond, kNoCondition); 146 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | 147 type << kTypeShift | 148 static_cast<int32_t>(opcode) << kOpcodeShift | 149 set_cc << kSShift | 150 static_cast<int32_t>(rn) << kRnShift | 151 static_cast<int32_t>(rd) << kRdShift | 152 so.encoding(); 153 Emit(encoding); 154} 155 156 157void ArmAssembler::EmitType5(Condition cond, int offset, bool link) { 158 CHECK_NE(cond, kNoCondition); 159 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | 160 5 << kTypeShift | 161 (link ? 1 : 0) << kLinkShift; 162 Emit(ArmAssembler::EncodeBranchOffset(offset, encoding)); 163} 164 165 166void ArmAssembler::EmitMemOp(Condition cond, 167 bool load, 168 bool byte, 169 Register rd, 170 Address ad) { 171 CHECK_NE(rd, kNoRegister); 172 CHECK_NE(cond, kNoCondition); 173 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 174 B26 | 175 (load ? L : 0) | 176 (byte ? B : 0) | 177 (static_cast<int32_t>(rd) << kRdShift) | 178 ad.encoding(); 179 Emit(encoding); 180} 181 182 183void ArmAssembler::EmitMemOpAddressMode3(Condition cond, 184 int32_t mode, 185 Register rd, 186 Address ad) { 187 CHECK_NE(rd, kNoRegister); 188 CHECK_NE(cond, kNoCondition); 189 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 190 B22 | 191 mode | 192 (static_cast<int32_t>(rd) << kRdShift) | 193 ad.encoding3(); 194 Emit(encoding); 195} 196 197 198void ArmAssembler::EmitMultiMemOp(Condition cond, 199 BlockAddressMode am, 200 bool load, 201 Register base, 202 RegList regs) { 203 CHECK_NE(base, kNoRegister); 204 CHECK_NE(cond, kNoCondition); 205 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 206 B27 | 207 am | 208 (load ? L : 0) | 209 (static_cast<int32_t>(base) << kRnShift) | 210 regs; 211 Emit(encoding); 212} 213 214 215void ArmAssembler::EmitShiftImmediate(Condition cond, 216 Shift opcode, 217 Register rd, 218 Register rm, 219 ShifterOperand so) { 220 CHECK_NE(cond, kNoCondition); 221 CHECK_EQ(so.type(), 1U); 222 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | 223 static_cast<int32_t>(MOV) << kOpcodeShift | 224 static_cast<int32_t>(rd) << kRdShift | 225 so.encoding() << kShiftImmShift | 226 static_cast<int32_t>(opcode) << kShiftShift | 227 static_cast<int32_t>(rm); 228 Emit(encoding); 229} 230 231 232void ArmAssembler::EmitShiftRegister(Condition cond, 233 Shift opcode, 234 Register rd, 235 Register rm, 236 ShifterOperand so) { 237 CHECK_NE(cond, kNoCondition); 238 CHECK_EQ(so.type(), 0U); 239 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | 240 static_cast<int32_t>(MOV) << kOpcodeShift | 241 static_cast<int32_t>(rd) << kRdShift | 242 so.encoding() << kShiftRegisterShift | 243 static_cast<int32_t>(opcode) << kShiftShift | 244 B4 | 245 static_cast<int32_t>(rm); 246 Emit(encoding); 247} 248 249 250void ArmAssembler::EmitBranch(Condition cond, Label* label, bool link) { 251 if (label->IsBound()) { 252 EmitType5(cond, label->Position() - buffer_.Size(), link); 253 } else { 254 int position = buffer_.Size(); 255 // Use the offset field of the branch instruction for linking the sites. 256 EmitType5(cond, label->position_, link); 257 label->LinkTo(position); 258 } 259} 260 261void ArmAssembler::and_(Register rd, Register rn, ShifterOperand so, 262 Condition cond) { 263 EmitType01(cond, so.type(), AND, 0, rn, rd, so); 264} 265 266 267void ArmAssembler::eor(Register rd, Register rn, ShifterOperand so, 268 Condition cond) { 269 EmitType01(cond, so.type(), EOR, 0, rn, rd, so); 270} 271 272 273void ArmAssembler::sub(Register rd, Register rn, ShifterOperand so, 274 Condition cond) { 275 EmitType01(cond, so.type(), SUB, 0, rn, rd, so); 276} 277 278void ArmAssembler::rsb(Register rd, Register rn, ShifterOperand so, 279 Condition cond) { 280 EmitType01(cond, so.type(), RSB, 0, rn, rd, so); 281} 282 283void ArmAssembler::rsbs(Register rd, Register rn, ShifterOperand so, 284 Condition cond) { 285 EmitType01(cond, so.type(), RSB, 1, rn, rd, so); 286} 287 288 289void ArmAssembler::add(Register rd, Register rn, ShifterOperand so, 290 Condition cond) { 291 EmitType01(cond, so.type(), ADD, 0, rn, rd, so); 292} 293 294 295void ArmAssembler::adds(Register rd, Register rn, ShifterOperand so, 296 Condition cond) { 297 EmitType01(cond, so.type(), ADD, 1, rn, rd, so); 298} 299 300 301void ArmAssembler::subs(Register rd, Register rn, ShifterOperand so, 302 Condition cond) { 303 EmitType01(cond, so.type(), SUB, 1, rn, rd, so); 304} 305 306 307void ArmAssembler::adc(Register rd, Register rn, ShifterOperand so, 308 Condition cond) { 309 EmitType01(cond, so.type(), ADC, 0, rn, rd, so); 310} 311 312 313void ArmAssembler::sbc(Register rd, Register rn, ShifterOperand so, 314 Condition cond) { 315 EmitType01(cond, so.type(), SBC, 0, rn, rd, so); 316} 317 318 319void ArmAssembler::rsc(Register rd, Register rn, ShifterOperand so, 320 Condition cond) { 321 EmitType01(cond, so.type(), RSC, 0, rn, rd, so); 322} 323 324 325void ArmAssembler::tst(Register rn, ShifterOperand so, Condition cond) { 326 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker. 327 EmitType01(cond, so.type(), TST, 1, rn, R0, so); 328} 329 330 331void ArmAssembler::teq(Register rn, ShifterOperand so, Condition cond) { 332 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker. 333 EmitType01(cond, so.type(), TEQ, 1, rn, R0, so); 334} 335 336 337void ArmAssembler::cmp(Register rn, ShifterOperand so, Condition cond) { 338 EmitType01(cond, so.type(), CMP, 1, rn, R0, so); 339} 340 341 342void ArmAssembler::cmn(Register rn, ShifterOperand so, Condition cond) { 343 EmitType01(cond, so.type(), CMN, 1, rn, R0, so); 344} 345 346 347void ArmAssembler::orr(Register rd, Register rn, 348 ShifterOperand so, Condition cond) { 349 EmitType01(cond, so.type(), ORR, 0, rn, rd, so); 350} 351 352 353void ArmAssembler::orrs(Register rd, Register rn, 354 ShifterOperand so, Condition cond) { 355 EmitType01(cond, so.type(), ORR, 1, rn, rd, so); 356} 357 358 359void ArmAssembler::mov(Register rd, ShifterOperand so, Condition cond) { 360 EmitType01(cond, so.type(), MOV, 0, R0, rd, so); 361} 362 363 364void ArmAssembler::movs(Register rd, ShifterOperand so, Condition cond) { 365 EmitType01(cond, so.type(), MOV, 1, R0, rd, so); 366} 367 368 369void ArmAssembler::bic(Register rd, Register rn, ShifterOperand so, 370 Condition cond) { 371 EmitType01(cond, so.type(), BIC, 0, rn, rd, so); 372} 373 374 375void ArmAssembler::mvn(Register rd, ShifterOperand so, Condition cond) { 376 EmitType01(cond, so.type(), MVN, 0, R0, rd, so); 377} 378 379 380void ArmAssembler::mvns(Register rd, ShifterOperand so, Condition cond) { 381 EmitType01(cond, so.type(), MVN, 1, R0, rd, so); 382} 383 384 385void ArmAssembler::clz(Register rd, Register rm, Condition cond) { 386 CHECK_NE(rd, kNoRegister); 387 CHECK_NE(rm, kNoRegister); 388 CHECK_NE(cond, kNoCondition); 389 CHECK_NE(rd, PC); 390 CHECK_NE(rm, PC); 391 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 392 B24 | B22 | B21 | (0xf << 16) | 393 (static_cast<int32_t>(rd) << kRdShift) | 394 (0xf << 8) | B4 | static_cast<int32_t>(rm); 395 Emit(encoding); 396} 397 398 399void ArmAssembler::movw(Register rd, uint16_t imm16, Condition cond) { 400 CHECK_NE(cond, kNoCondition); 401 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | 402 B25 | B24 | ((imm16 >> 12) << 16) | 403 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff); 404 Emit(encoding); 405} 406 407 408void ArmAssembler::movt(Register rd, uint16_t imm16, Condition cond) { 409 CHECK_NE(cond, kNoCondition); 410 int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | 411 B25 | B24 | B22 | ((imm16 >> 12) << 16) | 412 static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff); 413 Emit(encoding); 414} 415 416 417void ArmAssembler::EmitMulOp(Condition cond, int32_t opcode, 418 Register rd, Register rn, 419 Register rm, Register rs) { 420 CHECK_NE(rd, kNoRegister); 421 CHECK_NE(rn, kNoRegister); 422 CHECK_NE(rm, kNoRegister); 423 CHECK_NE(rs, kNoRegister); 424 CHECK_NE(cond, kNoCondition); 425 int32_t encoding = opcode | 426 (static_cast<int32_t>(cond) << kConditionShift) | 427 (static_cast<int32_t>(rn) << kRnShift) | 428 (static_cast<int32_t>(rd) << kRdShift) | 429 (static_cast<int32_t>(rs) << kRsShift) | 430 B7 | B4 | 431 (static_cast<int32_t>(rm) << kRmShift); 432 Emit(encoding); 433} 434 435 436void ArmAssembler::mul(Register rd, Register rn, Register rm, Condition cond) { 437 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. 438 EmitMulOp(cond, 0, R0, rd, rn, rm); 439} 440 441 442void ArmAssembler::mla(Register rd, Register rn, Register rm, Register ra, 443 Condition cond) { 444 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. 445 EmitMulOp(cond, B21, ra, rd, rn, rm); 446} 447 448 449void ArmAssembler::mls(Register rd, Register rn, Register rm, Register ra, 450 Condition cond) { 451 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. 452 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm); 453} 454 455 456void ArmAssembler::umull(Register rd_lo, Register rd_hi, Register rn, 457 Register rm, Condition cond) { 458 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. 459 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm); 460} 461 462 463void ArmAssembler::ldr(Register rd, Address ad, Condition cond) { 464 EmitMemOp(cond, true, false, rd, ad); 465} 466 467 468void ArmAssembler::str(Register rd, Address ad, Condition cond) { 469 EmitMemOp(cond, false, false, rd, ad); 470} 471 472 473void ArmAssembler::ldrb(Register rd, Address ad, Condition cond) { 474 EmitMemOp(cond, true, true, rd, ad); 475} 476 477 478void ArmAssembler::strb(Register rd, Address ad, Condition cond) { 479 EmitMemOp(cond, false, true, rd, ad); 480} 481 482 483void ArmAssembler::ldrh(Register rd, Address ad, Condition cond) { 484 EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad); 485} 486 487 488void ArmAssembler::strh(Register rd, Address ad, Condition cond) { 489 EmitMemOpAddressMode3(cond, B7 | H | B4, rd, ad); 490} 491 492 493void ArmAssembler::ldrsb(Register rd, Address ad, Condition cond) { 494 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad); 495} 496 497 498void ArmAssembler::ldrsh(Register rd, Address ad, Condition cond) { 499 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad); 500} 501 502 503void ArmAssembler::ldrd(Register rd, Address ad, Condition cond) { 504 CHECK_EQ(rd % 2, 0); 505 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad); 506} 507 508 509void ArmAssembler::strd(Register rd, Address ad, Condition cond) { 510 CHECK_EQ(rd % 2, 0); 511 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad); 512} 513 514 515void ArmAssembler::ldm(BlockAddressMode am, 516 Register base, 517 RegList regs, 518 Condition cond) { 519 EmitMultiMemOp(cond, am, true, base, regs); 520} 521 522 523void ArmAssembler::stm(BlockAddressMode am, 524 Register base, 525 RegList regs, 526 Condition cond) { 527 EmitMultiMemOp(cond, am, false, base, regs); 528} 529 530 531void ArmAssembler::ldrex(Register rt, Register rn, Condition cond) { 532 CHECK_NE(rn, kNoRegister); 533 CHECK_NE(rt, kNoRegister); 534 CHECK_NE(cond, kNoCondition); 535 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 536 B24 | 537 B23 | 538 L | 539 (static_cast<int32_t>(rn) << kLdExRnShift) | 540 (static_cast<int32_t>(rt) << kLdExRtShift) | 541 B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0; 542 Emit(encoding); 543} 544 545 546void ArmAssembler::strex(Register rd, 547 Register rt, 548 Register rn, 549 Condition cond) { 550 CHECK_NE(rn, kNoRegister); 551 CHECK_NE(rd, kNoRegister); 552 CHECK_NE(rt, kNoRegister); 553 CHECK_NE(cond, kNoCondition); 554 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 555 B24 | 556 B23 | 557 (static_cast<int32_t>(rn) << kStrExRnShift) | 558 (static_cast<int32_t>(rd) << kStrExRdShift) | 559 B11 | B10 | B9 | B8 | B7 | B4 | 560 (static_cast<int32_t>(rt) << kStrExRtShift); 561 Emit(encoding); 562} 563 564 565void ArmAssembler::clrex() { 566 int32_t encoding = (kSpecialCondition << kConditionShift) | 567 B26 | B24 | B22 | B21 | B20 | (0xff << 12) | B4 | 0xf; 568 Emit(encoding); 569} 570 571 572void ArmAssembler::nop(Condition cond) { 573 CHECK_NE(cond, kNoCondition); 574 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 575 B25 | B24 | B21 | (0xf << 12); 576 Emit(encoding); 577} 578 579 580void ArmAssembler::vmovsr(SRegister sn, Register rt, Condition cond) { 581 CHECK_NE(sn, kNoSRegister); 582 CHECK_NE(rt, kNoRegister); 583 CHECK_NE(rt, SP); 584 CHECK_NE(rt, PC); 585 CHECK_NE(cond, kNoCondition); 586 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 587 B27 | B26 | B25 | 588 ((static_cast<int32_t>(sn) >> 1)*B16) | 589 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 590 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 591 Emit(encoding); 592} 593 594 595void ArmAssembler::vmovrs(Register rt, SRegister sn, Condition cond) { 596 CHECK_NE(sn, kNoSRegister); 597 CHECK_NE(rt, kNoRegister); 598 CHECK_NE(rt, SP); 599 CHECK_NE(rt, PC); 600 CHECK_NE(cond, kNoCondition); 601 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 602 B27 | B26 | B25 | B20 | 603 ((static_cast<int32_t>(sn) >> 1)*B16) | 604 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 605 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 606 Emit(encoding); 607} 608 609 610void ArmAssembler::vmovsrr(SRegister sm, Register rt, Register rt2, 611 Condition cond) { 612 CHECK_NE(sm, kNoSRegister); 613 CHECK_NE(sm, S31); 614 CHECK_NE(rt, kNoRegister); 615 CHECK_NE(rt, SP); 616 CHECK_NE(rt, PC); 617 CHECK_NE(rt2, kNoRegister); 618 CHECK_NE(rt2, SP); 619 CHECK_NE(rt2, PC); 620 CHECK_NE(cond, kNoCondition); 621 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 622 B27 | B26 | B22 | 623 (static_cast<int32_t>(rt2)*B16) | 624 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 625 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 626 (static_cast<int32_t>(sm) >> 1); 627 Emit(encoding); 628} 629 630 631void ArmAssembler::vmovrrs(Register rt, Register rt2, SRegister sm, 632 Condition cond) { 633 CHECK_NE(sm, kNoSRegister); 634 CHECK_NE(sm, S31); 635 CHECK_NE(rt, kNoRegister); 636 CHECK_NE(rt, SP); 637 CHECK_NE(rt, PC); 638 CHECK_NE(rt2, kNoRegister); 639 CHECK_NE(rt2, SP); 640 CHECK_NE(rt2, PC); 641 CHECK_NE(rt, rt2); 642 CHECK_NE(cond, kNoCondition); 643 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 644 B27 | B26 | B22 | B20 | 645 (static_cast<int32_t>(rt2)*B16) | 646 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 647 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 648 (static_cast<int32_t>(sm) >> 1); 649 Emit(encoding); 650} 651 652 653void ArmAssembler::vmovdrr(DRegister dm, Register rt, Register rt2, 654 Condition cond) { 655 CHECK_NE(dm, kNoDRegister); 656 CHECK_NE(rt, kNoRegister); 657 CHECK_NE(rt, SP); 658 CHECK_NE(rt, PC); 659 CHECK_NE(rt2, kNoRegister); 660 CHECK_NE(rt2, SP); 661 CHECK_NE(rt2, PC); 662 CHECK_NE(cond, kNoCondition); 663 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 664 B27 | B26 | B22 | 665 (static_cast<int32_t>(rt2)*B16) | 666 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 667 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 668 (static_cast<int32_t>(dm) & 0xf); 669 Emit(encoding); 670} 671 672 673void ArmAssembler::vmovrrd(Register rt, Register rt2, DRegister dm, 674 Condition cond) { 675 CHECK_NE(dm, kNoDRegister); 676 CHECK_NE(rt, kNoRegister); 677 CHECK_NE(rt, SP); 678 CHECK_NE(rt, PC); 679 CHECK_NE(rt2, kNoRegister); 680 CHECK_NE(rt2, SP); 681 CHECK_NE(rt2, PC); 682 CHECK_NE(rt, rt2); 683 CHECK_NE(cond, kNoCondition); 684 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 685 B27 | B26 | B22 | B20 | 686 (static_cast<int32_t>(rt2)*B16) | 687 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 688 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 689 (static_cast<int32_t>(dm) & 0xf); 690 Emit(encoding); 691} 692 693 694void ArmAssembler::vldrs(SRegister sd, Address ad, Condition cond) { 695 CHECK_NE(sd, kNoSRegister); 696 CHECK_NE(cond, kNoCondition); 697 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 698 B27 | B26 | B24 | B20 | 699 ((static_cast<int32_t>(sd) & 1)*B22) | 700 ((static_cast<int32_t>(sd) >> 1)*B12) | 701 B11 | B9 | ad.vencoding(); 702 Emit(encoding); 703} 704 705 706void ArmAssembler::vstrs(SRegister sd, Address ad, Condition cond) { 707 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC); 708 CHECK_NE(sd, kNoSRegister); 709 CHECK_NE(cond, kNoCondition); 710 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 711 B27 | B26 | B24 | 712 ((static_cast<int32_t>(sd) & 1)*B22) | 713 ((static_cast<int32_t>(sd) >> 1)*B12) | 714 B11 | B9 | ad.vencoding(); 715 Emit(encoding); 716} 717 718 719void ArmAssembler::vldrd(DRegister dd, Address ad, Condition cond) { 720 CHECK_NE(dd, kNoDRegister); 721 CHECK_NE(cond, kNoCondition); 722 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 723 B27 | B26 | B24 | B20 | 724 ((static_cast<int32_t>(dd) >> 4)*B22) | 725 ((static_cast<int32_t>(dd) & 0xf)*B12) | 726 B11 | B9 | B8 | ad.vencoding(); 727 Emit(encoding); 728} 729 730 731void ArmAssembler::vstrd(DRegister dd, Address ad, Condition cond) { 732 CHECK_NE(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)), PC); 733 CHECK_NE(dd, kNoDRegister); 734 CHECK_NE(cond, kNoCondition); 735 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 736 B27 | B26 | B24 | 737 ((static_cast<int32_t>(dd) >> 4)*B22) | 738 ((static_cast<int32_t>(dd) & 0xf)*B12) | 739 B11 | B9 | B8 | ad.vencoding(); 740 Emit(encoding); 741} 742 743 744void ArmAssembler::EmitVFPsss(Condition cond, int32_t opcode, 745 SRegister sd, SRegister sn, SRegister sm) { 746 CHECK_NE(sd, kNoSRegister); 747 CHECK_NE(sn, kNoSRegister); 748 CHECK_NE(sm, kNoSRegister); 749 CHECK_NE(cond, kNoCondition); 750 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 751 B27 | B26 | B25 | B11 | B9 | opcode | 752 ((static_cast<int32_t>(sd) & 1)*B22) | 753 ((static_cast<int32_t>(sn) >> 1)*B16) | 754 ((static_cast<int32_t>(sd) >> 1)*B12) | 755 ((static_cast<int32_t>(sn) & 1)*B7) | 756 ((static_cast<int32_t>(sm) & 1)*B5) | 757 (static_cast<int32_t>(sm) >> 1); 758 Emit(encoding); 759} 760 761 762void ArmAssembler::EmitVFPddd(Condition cond, int32_t opcode, 763 DRegister dd, DRegister dn, DRegister dm) { 764 CHECK_NE(dd, kNoDRegister); 765 CHECK_NE(dn, kNoDRegister); 766 CHECK_NE(dm, kNoDRegister); 767 CHECK_NE(cond, kNoCondition); 768 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 769 B27 | B26 | B25 | B11 | B9 | B8 | opcode | 770 ((static_cast<int32_t>(dd) >> 4)*B22) | 771 ((static_cast<int32_t>(dn) & 0xf)*B16) | 772 ((static_cast<int32_t>(dd) & 0xf)*B12) | 773 ((static_cast<int32_t>(dn) >> 4)*B7) | 774 ((static_cast<int32_t>(dm) >> 4)*B5) | 775 (static_cast<int32_t>(dm) & 0xf); 776 Emit(encoding); 777} 778 779 780void ArmAssembler::vmovs(SRegister sd, SRegister sm, Condition cond) { 781 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm); 782} 783 784 785void ArmAssembler::vmovd(DRegister dd, DRegister dm, Condition cond) { 786 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm); 787} 788 789 790bool ArmAssembler::vmovs(SRegister sd, float s_imm, Condition cond) { 791 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm); 792 if (((imm32 & ((1 << 19) - 1)) == 0) && 793 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) || 794 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) { 795 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) | 796 ((imm32 >> 19) & ((1 << 6) -1)); 797 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf), 798 sd, S0, S0); 799 return true; 800 } 801 return false; 802} 803 804 805bool ArmAssembler::vmovd(DRegister dd, double d_imm, Condition cond) { 806 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm); 807 if (((imm64 & ((1LL << 48) - 1)) == 0) && 808 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) || 809 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) { 810 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) | 811 ((imm64 >> 48) & ((1 << 6) -1)); 812 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf), 813 dd, D0, D0); 814 return true; 815 } 816 return false; 817} 818 819 820void ArmAssembler::vadds(SRegister sd, SRegister sn, SRegister sm, 821 Condition cond) { 822 EmitVFPsss(cond, B21 | B20, sd, sn, sm); 823} 824 825 826void ArmAssembler::vaddd(DRegister dd, DRegister dn, DRegister dm, 827 Condition cond) { 828 EmitVFPddd(cond, B21 | B20, dd, dn, dm); 829} 830 831 832void ArmAssembler::vsubs(SRegister sd, SRegister sn, SRegister sm, 833 Condition cond) { 834 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm); 835} 836 837 838void ArmAssembler::vsubd(DRegister dd, DRegister dn, DRegister dm, 839 Condition cond) { 840 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm); 841} 842 843 844void ArmAssembler::vmuls(SRegister sd, SRegister sn, SRegister sm, 845 Condition cond) { 846 EmitVFPsss(cond, B21, sd, sn, sm); 847} 848 849 850void ArmAssembler::vmuld(DRegister dd, DRegister dn, DRegister dm, 851 Condition cond) { 852 EmitVFPddd(cond, B21, dd, dn, dm); 853} 854 855 856void ArmAssembler::vmlas(SRegister sd, SRegister sn, SRegister sm, 857 Condition cond) { 858 EmitVFPsss(cond, 0, sd, sn, sm); 859} 860 861 862void ArmAssembler::vmlad(DRegister dd, DRegister dn, DRegister dm, 863 Condition cond) { 864 EmitVFPddd(cond, 0, dd, dn, dm); 865} 866 867 868void ArmAssembler::vmlss(SRegister sd, SRegister sn, SRegister sm, 869 Condition cond) { 870 EmitVFPsss(cond, B6, sd, sn, sm); 871} 872 873 874void ArmAssembler::vmlsd(DRegister dd, DRegister dn, DRegister dm, 875 Condition cond) { 876 EmitVFPddd(cond, B6, dd, dn, dm); 877} 878 879 880void ArmAssembler::vdivs(SRegister sd, SRegister sn, SRegister sm, 881 Condition cond) { 882 EmitVFPsss(cond, B23, sd, sn, sm); 883} 884 885 886void ArmAssembler::vdivd(DRegister dd, DRegister dn, DRegister dm, 887 Condition cond) { 888 EmitVFPddd(cond, B23, dd, dn, dm); 889} 890 891 892void ArmAssembler::vabss(SRegister sd, SRegister sm, Condition cond) { 893 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm); 894} 895 896 897void ArmAssembler::vabsd(DRegister dd, DRegister dm, Condition cond) { 898 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm); 899} 900 901 902void ArmAssembler::vnegs(SRegister sd, SRegister sm, Condition cond) { 903 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm); 904} 905 906 907void ArmAssembler::vnegd(DRegister dd, DRegister dm, Condition cond) { 908 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm); 909} 910 911 912void ArmAssembler::vsqrts(SRegister sd, SRegister sm, Condition cond) { 913 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm); 914} 915 916void ArmAssembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) { 917 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm); 918} 919 920 921void ArmAssembler::EmitVFPsd(Condition cond, int32_t opcode, 922 SRegister sd, DRegister dm) { 923 CHECK_NE(sd, kNoSRegister); 924 CHECK_NE(dm, kNoDRegister); 925 CHECK_NE(cond, kNoCondition); 926 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 927 B27 | B26 | B25 | B11 | B9 | opcode | 928 ((static_cast<int32_t>(sd) & 1)*B22) | 929 ((static_cast<int32_t>(sd) >> 1)*B12) | 930 ((static_cast<int32_t>(dm) >> 4)*B5) | 931 (static_cast<int32_t>(dm) & 0xf); 932 Emit(encoding); 933} 934 935 936void ArmAssembler::EmitVFPds(Condition cond, int32_t opcode, 937 DRegister dd, SRegister sm) { 938 CHECK_NE(dd, kNoDRegister); 939 CHECK_NE(sm, kNoSRegister); 940 CHECK_NE(cond, kNoCondition); 941 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 942 B27 | B26 | B25 | B11 | B9 | opcode | 943 ((static_cast<int32_t>(dd) >> 4)*B22) | 944 ((static_cast<int32_t>(dd) & 0xf)*B12) | 945 ((static_cast<int32_t>(sm) & 1)*B5) | 946 (static_cast<int32_t>(sm) >> 1); 947 Emit(encoding); 948} 949 950 951void ArmAssembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) { 952 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm); 953} 954 955 956void ArmAssembler::vcvtds(DRegister dd, SRegister sm, Condition cond) { 957 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm); 958} 959 960 961void ArmAssembler::vcvtis(SRegister sd, SRegister sm, Condition cond) { 962 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm); 963} 964 965 966void ArmAssembler::vcvtid(SRegister sd, DRegister dm, Condition cond) { 967 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm); 968} 969 970 971void ArmAssembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) { 972 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm); 973} 974 975 976void ArmAssembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) { 977 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm); 978} 979 980 981void ArmAssembler::vcvtus(SRegister sd, SRegister sm, Condition cond) { 982 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm); 983} 984 985 986void ArmAssembler::vcvtud(SRegister sd, DRegister dm, Condition cond) { 987 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm); 988} 989 990 991void ArmAssembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) { 992 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm); 993} 994 995 996void ArmAssembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) { 997 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm); 998} 999 1000 1001void ArmAssembler::vcmps(SRegister sd, SRegister sm, Condition cond) { 1002 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm); 1003} 1004 1005 1006void ArmAssembler::vcmpd(DRegister dd, DRegister dm, Condition cond) { 1007 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm); 1008} 1009 1010 1011void ArmAssembler::vcmpsz(SRegister sd, Condition cond) { 1012 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0); 1013} 1014 1015 1016void ArmAssembler::vcmpdz(DRegister dd, Condition cond) { 1017 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0); 1018} 1019 1020 1021void ArmAssembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR 1022 CHECK_NE(cond, kNoCondition); 1023 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1024 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | 1025 (static_cast<int32_t>(PC)*B12) | 1026 B11 | B9 | B4; 1027 Emit(encoding); 1028} 1029 1030 1031void ArmAssembler::svc(uint32_t imm24) { 1032 CHECK(IsUint(24, imm24)) << imm24; 1033 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24; 1034 Emit(encoding); 1035} 1036 1037 1038void ArmAssembler::bkpt(uint16_t imm16) { 1039 int32_t encoding = (AL << kConditionShift) | B24 | B21 | 1040 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); 1041 Emit(encoding); 1042} 1043 1044 1045void ArmAssembler::b(Label* label, Condition cond) { 1046 EmitBranch(cond, label, false); 1047} 1048 1049 1050void ArmAssembler::bl(Label* label, Condition cond) { 1051 EmitBranch(cond, label, true); 1052} 1053 1054 1055void ArmAssembler::blx(Register rm, Condition cond) { 1056 CHECK_NE(rm, kNoRegister); 1057 CHECK_NE(cond, kNoCondition); 1058 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1059 B24 | B21 | (0xfff << 8) | B5 | B4 | 1060 (static_cast<int32_t>(rm) << kRmShift); 1061 Emit(encoding); 1062} 1063 1064void ArmAssembler::bx(Register rm, Condition cond) { 1065 CHECK_NE(rm, kNoRegister); 1066 CHECK_NE(cond, kNoCondition); 1067 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1068 B24 | B21 | (0xfff << 8) | B4 | 1069 (static_cast<int32_t>(rm) << kRmShift); 1070 Emit(encoding); 1071} 1072 1073void ArmAssembler::MarkExceptionHandler(Label* label) { 1074 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0)); 1075 Label l; 1076 b(&l); 1077 EmitBranch(AL, label, false); 1078 Bind(&l); 1079} 1080 1081 1082void ArmAssembler::Bind(Label* label) { 1083 CHECK(!label->IsBound()); 1084 int bound_pc = buffer_.Size(); 1085 while (label->IsLinked()) { 1086 int32_t position = label->Position(); 1087 int32_t next = buffer_.Load<int32_t>(position); 1088 int32_t encoded = ArmAssembler::EncodeBranchOffset(bound_pc - position, next); 1089 buffer_.Store<int32_t>(position, encoded); 1090 label->position_ = ArmAssembler::DecodeBranchOffset(next); 1091 } 1092 label->BindTo(bound_pc); 1093} 1094 1095 1096void ArmAssembler::EncodeUint32InTstInstructions(uint32_t data) { 1097 // TODO: Consider using movw ip, <16 bits>. 1098 while (!IsUint(8, data)) { 1099 tst(R0, ShifterOperand(data & 0xFF), VS); 1100 data >>= 8; 1101 } 1102 tst(R0, ShifterOperand(data), MI); 1103} 1104 1105 1106int32_t ArmAssembler::EncodeBranchOffset(int offset, int32_t inst) { 1107 // The offset is off by 8 due to the way the ARM CPUs read PC. 1108 offset -= 8; 1109 CHECK_ALIGNED(offset, 4); 1110 CHECK(IsInt(CountOneBits(kBranchOffsetMask), offset)) << offset; 1111 1112 // Properly preserve only the bits supported in the instruction. 1113 offset >>= 2; 1114 offset &= kBranchOffsetMask; 1115 return (inst & ~kBranchOffsetMask) | offset; 1116} 1117 1118 1119int ArmAssembler::DecodeBranchOffset(int32_t inst) { 1120 // Sign-extend, left-shift by 2, then add 8. 1121 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); 1122} 1123 1124void ArmAssembler::AddConstant(Register rd, int32_t value, Condition cond) { 1125 AddConstant(rd, rd, value, cond); 1126} 1127 1128 1129void ArmAssembler::AddConstant(Register rd, Register rn, int32_t value, 1130 Condition cond) { 1131 if (value == 0) { 1132 if (rd != rn) { 1133 mov(rd, ShifterOperand(rn), cond); 1134 } 1135 return; 1136 } 1137 // We prefer to select the shorter code sequence rather than selecting add for 1138 // positive values and sub for negatives ones, which would slightly improve 1139 // the readability of generated code for some constants. 1140 ShifterOperand shifter_op; 1141 if (ShifterOperand::CanHold(value, &shifter_op)) { 1142 add(rd, rn, shifter_op, cond); 1143 } else if (ShifterOperand::CanHold(-value, &shifter_op)) { 1144 sub(rd, rn, shifter_op, cond); 1145 } else { 1146 CHECK(rn != IP); 1147 if (ShifterOperand::CanHold(~value, &shifter_op)) { 1148 mvn(IP, shifter_op, cond); 1149 add(rd, rn, ShifterOperand(IP), cond); 1150 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) { 1151 mvn(IP, shifter_op, cond); 1152 sub(rd, rn, ShifterOperand(IP), cond); 1153 } else { 1154 movw(IP, Low16Bits(value), cond); 1155 uint16_t value_high = High16Bits(value); 1156 if (value_high != 0) { 1157 movt(IP, value_high, cond); 1158 } 1159 add(rd, rn, ShifterOperand(IP), cond); 1160 } 1161 } 1162} 1163 1164 1165void ArmAssembler::AddConstantSetFlags(Register rd, Register rn, int32_t value, 1166 Condition cond) { 1167 ShifterOperand shifter_op; 1168 if (ShifterOperand::CanHold(value, &shifter_op)) { 1169 adds(rd, rn, shifter_op, cond); 1170 } else if (ShifterOperand::CanHold(-value, &shifter_op)) { 1171 subs(rd, rn, shifter_op, cond); 1172 } else { 1173 CHECK(rn != IP); 1174 if (ShifterOperand::CanHold(~value, &shifter_op)) { 1175 mvn(IP, shifter_op, cond); 1176 adds(rd, rn, ShifterOperand(IP), cond); 1177 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) { 1178 mvn(IP, shifter_op, cond); 1179 subs(rd, rn, ShifterOperand(IP), cond); 1180 } else { 1181 movw(IP, Low16Bits(value), cond); 1182 uint16_t value_high = High16Bits(value); 1183 if (value_high != 0) { 1184 movt(IP, value_high, cond); 1185 } 1186 adds(rd, rn, ShifterOperand(IP), cond); 1187 } 1188 } 1189} 1190 1191 1192void ArmAssembler::LoadImmediate(Register rd, int32_t value, Condition cond) { 1193 ShifterOperand shifter_op; 1194 if (ShifterOperand::CanHold(value, &shifter_op)) { 1195 mov(rd, shifter_op, cond); 1196 } else if (ShifterOperand::CanHold(~value, &shifter_op)) { 1197 mvn(rd, shifter_op, cond); 1198 } else { 1199 movw(rd, Low16Bits(value), cond); 1200 uint16_t value_high = High16Bits(value); 1201 if (value_high != 0) { 1202 movt(rd, value_high, cond); 1203 } 1204 } 1205} 1206 1207 1208bool Address::CanHoldLoadOffset(LoadOperandType type, int offset) { 1209 switch (type) { 1210 case kLoadSignedByte: 1211 case kLoadSignedHalfword: 1212 case kLoadUnsignedHalfword: 1213 case kLoadWordPair: 1214 return IsAbsoluteUint(8, offset); // Addressing mode 3. 1215 case kLoadUnsignedByte: 1216 case kLoadWord: 1217 return IsAbsoluteUint(12, offset); // Addressing mode 2. 1218 case kLoadSWord: 1219 case kLoadDWord: 1220 return IsAbsoluteUint(10, offset); // VFP addressing mode. 1221 default: 1222 LOG(FATAL) << "UNREACHABLE"; 1223 return false; 1224 } 1225} 1226 1227 1228bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) { 1229 switch (type) { 1230 case kStoreHalfword: 1231 case kStoreWordPair: 1232 return IsAbsoluteUint(8, offset); // Addressing mode 3. 1233 case kStoreByte: 1234 case kStoreWord: 1235 return IsAbsoluteUint(12, offset); // Addressing mode 2. 1236 case kStoreSWord: 1237 case kStoreDWord: 1238 return IsAbsoluteUint(10, offset); // VFP addressing mode. 1239 default: 1240 LOG(FATAL) << "UNREACHABLE"; 1241 return false; 1242 } 1243} 1244 1245 1246// Implementation note: this method must emit at most one instruction when 1247// Address::CanHoldLoadOffset. 1248void ArmAssembler::LoadFromOffset(LoadOperandType type, 1249 Register reg, 1250 Register base, 1251 int32_t offset, 1252 Condition cond) { 1253 if (!Address::CanHoldLoadOffset(type, offset)) { 1254 CHECK(base != IP); 1255 LoadImmediate(IP, offset, cond); 1256 add(IP, IP, ShifterOperand(base), cond); 1257 base = IP; 1258 offset = 0; 1259 } 1260 CHECK(Address::CanHoldLoadOffset(type, offset)); 1261 switch (type) { 1262 case kLoadSignedByte: 1263 ldrsb(reg, Address(base, offset), cond); 1264 break; 1265 case kLoadUnsignedByte: 1266 ldrb(reg, Address(base, offset), cond); 1267 break; 1268 case kLoadSignedHalfword: 1269 ldrsh(reg, Address(base, offset), cond); 1270 break; 1271 case kLoadUnsignedHalfword: 1272 ldrh(reg, Address(base, offset), cond); 1273 break; 1274 case kLoadWord: 1275 ldr(reg, Address(base, offset), cond); 1276 break; 1277 case kLoadWordPair: 1278 ldrd(reg, Address(base, offset), cond); 1279 break; 1280 default: 1281 LOG(FATAL) << "UNREACHABLE"; 1282 } 1283} 1284 1285// Implementation note: this method must emit at most one instruction when 1286// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset. 1287void ArmAssembler::LoadSFromOffset(SRegister reg, 1288 Register base, 1289 int32_t offset, 1290 Condition cond) { 1291 if (!Address::CanHoldLoadOffset(kLoadSWord, offset)) { 1292 CHECK_NE(base, IP); 1293 LoadImmediate(IP, offset, cond); 1294 add(IP, IP, ShifterOperand(base), cond); 1295 base = IP; 1296 offset = 0; 1297 } 1298 CHECK(Address::CanHoldLoadOffset(kLoadSWord, offset)); 1299 vldrs(reg, Address(base, offset), cond); 1300} 1301 1302// Implementation note: this method must emit at most one instruction when 1303// Address::CanHoldLoadOffset, as expected by JIT::GuardedLoadFromOffset. 1304void ArmAssembler::LoadDFromOffset(DRegister reg, 1305 Register base, 1306 int32_t offset, 1307 Condition cond) { 1308 if (!Address::CanHoldLoadOffset(kLoadDWord, offset)) { 1309 CHECK_NE(base, IP); 1310 LoadImmediate(IP, offset, cond); 1311 add(IP, IP, ShifterOperand(base), cond); 1312 base = IP; 1313 offset = 0; 1314 } 1315 CHECK(Address::CanHoldLoadOffset(kLoadDWord, offset)); 1316 vldrd(reg, Address(base, offset), cond); 1317} 1318 1319// Implementation note: this method must emit at most one instruction when 1320// Address::CanHoldStoreOffset. 1321void ArmAssembler::StoreToOffset(StoreOperandType type, 1322 Register reg, 1323 Register base, 1324 int32_t offset, 1325 Condition cond) { 1326 if (!Address::CanHoldStoreOffset(type, offset)) { 1327 CHECK(reg != IP); 1328 CHECK(base != IP); 1329 LoadImmediate(IP, offset, cond); 1330 add(IP, IP, ShifterOperand(base), cond); 1331 base = IP; 1332 offset = 0; 1333 } 1334 CHECK(Address::CanHoldStoreOffset(type, offset)); 1335 switch (type) { 1336 case kStoreByte: 1337 strb(reg, Address(base, offset), cond); 1338 break; 1339 case kStoreHalfword: 1340 strh(reg, Address(base, offset), cond); 1341 break; 1342 case kStoreWord: 1343 str(reg, Address(base, offset), cond); 1344 break; 1345 case kStoreWordPair: 1346 strd(reg, Address(base, offset), cond); 1347 break; 1348 default: 1349 LOG(FATAL) << "UNREACHABLE"; 1350 } 1351} 1352 1353// Implementation note: this method must emit at most one instruction when 1354// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreToOffset. 1355void ArmAssembler::StoreSToOffset(SRegister reg, 1356 Register base, 1357 int32_t offset, 1358 Condition cond) { 1359 if (!Address::CanHoldStoreOffset(kStoreSWord, offset)) { 1360 CHECK_NE(base, IP); 1361 LoadImmediate(IP, offset, cond); 1362 add(IP, IP, ShifterOperand(base), cond); 1363 base = IP; 1364 offset = 0; 1365 } 1366 CHECK(Address::CanHoldStoreOffset(kStoreSWord, offset)); 1367 vstrs(reg, Address(base, offset), cond); 1368} 1369 1370// Implementation note: this method must emit at most one instruction when 1371// Address::CanHoldStoreOffset, as expected by JIT::GuardedStoreSToOffset. 1372void ArmAssembler::StoreDToOffset(DRegister reg, 1373 Register base, 1374 int32_t offset, 1375 Condition cond) { 1376 if (!Address::CanHoldStoreOffset(kStoreDWord, offset)) { 1377 CHECK_NE(base, IP); 1378 LoadImmediate(IP, offset, cond); 1379 add(IP, IP, ShifterOperand(base), cond); 1380 base = IP; 1381 offset = 0; 1382 } 1383 CHECK(Address::CanHoldStoreOffset(kStoreDWord, offset)); 1384 vstrd(reg, Address(base, offset), cond); 1385} 1386 1387void ArmAssembler::Push(Register rd, Condition cond) { 1388 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond); 1389} 1390 1391void ArmAssembler::Pop(Register rd, Condition cond) { 1392 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond); 1393} 1394 1395void ArmAssembler::PushList(RegList regs, Condition cond) { 1396 stm(DB_W, SP, regs, cond); 1397} 1398 1399void ArmAssembler::PopList(RegList regs, Condition cond) { 1400 ldm(IA_W, SP, regs, cond); 1401} 1402 1403void ArmAssembler::Mov(Register rd, Register rm, Condition cond) { 1404 if (rd != rm) { 1405 mov(rd, ShifterOperand(rm), cond); 1406 } 1407} 1408 1409void ArmAssembler::Lsl(Register rd, Register rm, uint32_t shift_imm, 1410 Condition cond) { 1411 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. 1412 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond); 1413} 1414 1415void ArmAssembler::Lsr(Register rd, Register rm, uint32_t shift_imm, 1416 Condition cond) { 1417 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. 1418 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 1419 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond); 1420} 1421 1422void ArmAssembler::Asr(Register rd, Register rm, uint32_t shift_imm, 1423 Condition cond) { 1424 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. 1425 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 1426 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond); 1427} 1428 1429void ArmAssembler::Ror(Register rd, Register rm, uint32_t shift_imm, 1430 Condition cond) { 1431 CHECK_NE(shift_imm, 0u); // Use Rrx instruction. 1432 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond); 1433} 1434 1435void ArmAssembler::Rrx(Register rd, Register rm, Condition cond) { 1436 mov(rd, ShifterOperand(rm, ROR, 0), cond); 1437} 1438 1439void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg, 1440 const std::vector<ManagedRegister>& callee_save_regs, 1441 const std::vector<ManagedRegister>& entry_spills) { 1442 CHECK_ALIGNED(frame_size, kStackAlignment); 1443 CHECK_EQ(R0, method_reg.AsArm().AsCoreRegister()); 1444 1445 // Push callee saves and link register. 1446 RegList push_list = 1 << LR; 1447 size_t pushed_values = 1; 1448 for (size_t i = 0; i < callee_save_regs.size(); i++) { 1449 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister(); 1450 push_list |= 1 << reg; 1451 pushed_values++; 1452 } 1453 PushList(push_list); 1454 1455 // Increase frame to required size. 1456 CHECK_GT(frame_size, pushed_values * kPointerSize); // Must be at least space to push Method* 1457 size_t adjust = frame_size - (pushed_values * kPointerSize); 1458 IncreaseFrameSize(adjust); 1459 1460 // Write out Method*. 1461 StoreToOffset(kStoreWord, R0, SP, 0); 1462 1463 // Write out entry spills. 1464 for (size_t i = 0; i < entry_spills.size(); ++i) { 1465 Register reg = entry_spills.at(i).AsArm().AsCoreRegister(); 1466 StoreToOffset(kStoreWord, reg, SP, frame_size + kPointerSize + (i * kPointerSize)); 1467 } 1468} 1469 1470void ArmAssembler::RemoveFrame(size_t frame_size, 1471 const std::vector<ManagedRegister>& callee_save_regs) { 1472 CHECK_ALIGNED(frame_size, kStackAlignment); 1473 // Compute callee saves to pop and PC 1474 RegList pop_list = 1 << PC; 1475 size_t pop_values = 1; 1476 for (size_t i = 0; i < callee_save_regs.size(); i++) { 1477 Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister(); 1478 pop_list |= 1 << reg; 1479 pop_values++; 1480 } 1481 1482 // Decrease frame to start of callee saves 1483 CHECK_GT(frame_size, pop_values * kPointerSize); 1484 size_t adjust = frame_size - (pop_values * kPointerSize); 1485 DecreaseFrameSize(adjust); 1486 1487 // Pop callee saves and PC 1488 PopList(pop_list); 1489} 1490 1491void ArmAssembler::IncreaseFrameSize(size_t adjust) { 1492 AddConstant(SP, -adjust); 1493} 1494 1495void ArmAssembler::DecreaseFrameSize(size_t adjust) { 1496 AddConstant(SP, adjust); 1497} 1498 1499void ArmAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) { 1500 ArmManagedRegister src = msrc.AsArm(); 1501 if (src.IsNoRegister()) { 1502 CHECK_EQ(0u, size); 1503 } else if (src.IsCoreRegister()) { 1504 CHECK_EQ(4u, size); 1505 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 1506 } else if (src.IsRegisterPair()) { 1507 CHECK_EQ(8u, size); 1508 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value()); 1509 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(), 1510 SP, dest.Int32Value() + 4); 1511 } else if (src.IsSRegister()) { 1512 StoreSToOffset(src.AsSRegister(), SP, dest.Int32Value()); 1513 } else { 1514 CHECK(src.IsDRegister()) << src; 1515 StoreDToOffset(src.AsDRegister(), SP, dest.Int32Value()); 1516 } 1517} 1518 1519void ArmAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) { 1520 ArmManagedRegister src = msrc.AsArm(); 1521 CHECK(src.IsCoreRegister()) << src; 1522 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 1523} 1524 1525void ArmAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) { 1526 ArmManagedRegister src = msrc.AsArm(); 1527 CHECK(src.IsCoreRegister()) << src; 1528 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 1529} 1530 1531void ArmAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc, 1532 FrameOffset in_off, ManagedRegister mscratch) { 1533 ArmManagedRegister src = msrc.AsArm(); 1534 ArmManagedRegister scratch = mscratch.AsArm(); 1535 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 1536 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value()); 1537 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4); 1538} 1539 1540void ArmAssembler::CopyRef(FrameOffset dest, FrameOffset src, 1541 ManagedRegister mscratch) { 1542 ArmManagedRegister scratch = mscratch.AsArm(); 1543 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value()); 1544 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 1545} 1546 1547void ArmAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, 1548 MemberOffset offs) { 1549 ArmManagedRegister dst = mdest.AsArm(); 1550 CHECK(dst.IsCoreRegister() && dst.IsCoreRegister()) << dst; 1551 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), 1552 base.AsArm().AsCoreRegister(), offs.Int32Value()); 1553} 1554 1555void ArmAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) { 1556 ArmManagedRegister dst = mdest.AsArm(); 1557 CHECK(dst.IsCoreRegister()) << dst; 1558 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), SP, src.Int32Value()); 1559} 1560 1561void ArmAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, 1562 Offset offs) { 1563 ArmManagedRegister dst = mdest.AsArm(); 1564 CHECK(dst.IsCoreRegister() && dst.IsCoreRegister()) << dst; 1565 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), 1566 base.AsArm().AsCoreRegister(), offs.Int32Value()); 1567} 1568 1569void ArmAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 1570 ManagedRegister mscratch) { 1571 ArmManagedRegister scratch = mscratch.AsArm(); 1572 CHECK(scratch.IsCoreRegister()) << scratch; 1573 LoadImmediate(scratch.AsCoreRegister(), imm); 1574 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 1575} 1576 1577void ArmAssembler::StoreImmediateToThread(ThreadOffset dest, uint32_t imm, 1578 ManagedRegister mscratch) { 1579 ArmManagedRegister scratch = mscratch.AsArm(); 1580 CHECK(scratch.IsCoreRegister()) << scratch; 1581 LoadImmediate(scratch.AsCoreRegister(), imm); 1582 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), TR, dest.Int32Value()); 1583} 1584 1585static void EmitLoad(ArmAssembler* assembler, ManagedRegister m_dst, 1586 Register src_register, int32_t src_offset, size_t size) { 1587 ArmManagedRegister dst = m_dst.AsArm(); 1588 if (dst.IsNoRegister()) { 1589 CHECK_EQ(0u, size) << dst; 1590 } else if (dst.IsCoreRegister()) { 1591 CHECK_EQ(4u, size) << dst; 1592 assembler->LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset); 1593 } else if (dst.IsRegisterPair()) { 1594 CHECK_EQ(8u, size) << dst; 1595 assembler->LoadFromOffset(kLoadWord, dst.AsRegisterPairLow(), src_register, src_offset); 1596 assembler->LoadFromOffset(kLoadWord, dst.AsRegisterPairHigh(), src_register, src_offset + 4); 1597 } else if (dst.IsSRegister()) { 1598 assembler->LoadSFromOffset(dst.AsSRegister(), src_register, src_offset); 1599 } else { 1600 CHECK(dst.IsDRegister()) << dst; 1601 assembler->LoadDFromOffset(dst.AsDRegister(), src_register, src_offset); 1602 } 1603} 1604 1605void ArmAssembler::Load(ManagedRegister m_dst, FrameOffset src, size_t size) { 1606 return EmitLoad(this, m_dst, SP, src.Int32Value(), size); 1607} 1608 1609void ArmAssembler::Load(ManagedRegister m_dst, ThreadOffset src, size_t size) { 1610 return EmitLoad(this, m_dst, TR, src.Int32Value(), size); 1611} 1612 1613void ArmAssembler::LoadRawPtrFromThread(ManagedRegister m_dst, ThreadOffset offs) { 1614 ArmManagedRegister dst = m_dst.AsArm(); 1615 CHECK(dst.IsCoreRegister()) << dst; 1616 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), TR, offs.Int32Value()); 1617} 1618 1619void ArmAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, 1620 ThreadOffset thr_offs, 1621 ManagedRegister mscratch) { 1622 ArmManagedRegister scratch = mscratch.AsArm(); 1623 CHECK(scratch.IsCoreRegister()) << scratch; 1624 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 1625 TR, thr_offs.Int32Value()); 1626 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), 1627 SP, fr_offs.Int32Value()); 1628} 1629 1630void ArmAssembler::CopyRawPtrToThread(ThreadOffset thr_offs, 1631 FrameOffset fr_offs, 1632 ManagedRegister mscratch) { 1633 ArmManagedRegister scratch = mscratch.AsArm(); 1634 CHECK(scratch.IsCoreRegister()) << scratch; 1635 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 1636 SP, fr_offs.Int32Value()); 1637 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), 1638 TR, thr_offs.Int32Value()); 1639} 1640 1641void ArmAssembler::StoreStackOffsetToThread(ThreadOffset thr_offs, 1642 FrameOffset fr_offs, 1643 ManagedRegister mscratch) { 1644 ArmManagedRegister scratch = mscratch.AsArm(); 1645 CHECK(scratch.IsCoreRegister()) << scratch; 1646 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value(), AL); 1647 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), 1648 TR, thr_offs.Int32Value()); 1649} 1650 1651void ArmAssembler::StoreStackPointerToThread(ThreadOffset thr_offs) { 1652 StoreToOffset(kStoreWord, SP, TR, thr_offs.Int32Value()); 1653} 1654 1655void ArmAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) { 1656 UNIMPLEMENTED(FATAL) << "no sign extension necessary for arm"; 1657} 1658 1659void ArmAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) { 1660 UNIMPLEMENTED(FATAL) << "no zero extension necessary for arm"; 1661} 1662 1663void ArmAssembler::Move(ManagedRegister m_dst, ManagedRegister m_src, size_t /*size*/) { 1664 ArmManagedRegister dst = m_dst.AsArm(); 1665 ArmManagedRegister src = m_src.AsArm(); 1666 if (!dst.Equals(src)) { 1667 if (dst.IsCoreRegister()) { 1668 CHECK(src.IsCoreRegister()) << src; 1669 mov(dst.AsCoreRegister(), ShifterOperand(src.AsCoreRegister())); 1670 } else if (dst.IsDRegister()) { 1671 CHECK(src.IsDRegister()) << src; 1672 vmovd(dst.AsDRegister(), src.AsDRegister()); 1673 } else if (dst.IsSRegister()) { 1674 CHECK(src.IsSRegister()) << src; 1675 vmovs(dst.AsSRegister(), src.AsSRegister()); 1676 } else { 1677 CHECK(dst.IsRegisterPair()) << dst; 1678 CHECK(src.IsRegisterPair()) << src; 1679 // Ensure that the first move doesn't clobber the input of the second 1680 if (src.AsRegisterPairHigh() != dst.AsRegisterPairLow()) { 1681 mov(dst.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow())); 1682 mov(dst.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh())); 1683 } else { 1684 mov(dst.AsRegisterPairHigh(), ShifterOperand(src.AsRegisterPairHigh())); 1685 mov(dst.AsRegisterPairLow(), ShifterOperand(src.AsRegisterPairLow())); 1686 } 1687 } 1688 } 1689} 1690 1691void ArmAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) { 1692 ArmManagedRegister scratch = mscratch.AsArm(); 1693 CHECK(scratch.IsCoreRegister()) << scratch; 1694 CHECK(size == 4 || size == 8) << size; 1695 if (size == 4) { 1696 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value()); 1697 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 1698 } else if (size == 8) { 1699 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value()); 1700 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 1701 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + 4); 1702 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4); 1703 } 1704} 1705 1706void ArmAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 1707 ManagedRegister mscratch, size_t size) { 1708 Register scratch = mscratch.AsArm().AsCoreRegister(); 1709 CHECK_EQ(size, 4u); 1710 LoadFromOffset(kLoadWord, scratch, src_base.AsArm().AsCoreRegister(), src_offset.Int32Value()); 1711 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value()); 1712} 1713 1714void ArmAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 1715 ManagedRegister mscratch, size_t size) { 1716 Register scratch = mscratch.AsArm().AsCoreRegister(); 1717 CHECK_EQ(size, 4u); 1718 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value()); 1719 StoreToOffset(kStoreWord, scratch, dest_base.AsArm().AsCoreRegister(), dest_offset.Int32Value()); 1720} 1721 1722void ArmAssembler::Copy(FrameOffset /*dst*/, FrameOffset /*src_base*/, Offset /*src_offset*/, 1723 ManagedRegister /*mscratch*/, size_t /*size*/) { 1724 UNIMPLEMENTED(FATAL); 1725} 1726 1727void ArmAssembler::Copy(ManagedRegister dest, Offset dest_offset, 1728 ManagedRegister src, Offset src_offset, 1729 ManagedRegister mscratch, size_t size) { 1730 CHECK_EQ(size, 4u); 1731 Register scratch = mscratch.AsArm().AsCoreRegister(); 1732 LoadFromOffset(kLoadWord, scratch, src.AsArm().AsCoreRegister(), src_offset.Int32Value()); 1733 StoreToOffset(kStoreWord, scratch, dest.AsArm().AsCoreRegister(), dest_offset.Int32Value()); 1734} 1735 1736void ArmAssembler::Copy(FrameOffset /*dst*/, Offset /*dest_offset*/, FrameOffset /*src*/, Offset /*src_offset*/, 1737 ManagedRegister /*scratch*/, size_t /*size*/) { 1738 UNIMPLEMENTED(FATAL); 1739} 1740 1741 1742void ArmAssembler::MemoryBarrier(ManagedRegister mscratch) { 1743 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12); 1744#if ANDROID_SMP != 0 1745#if defined(__ARM_HAVE_DMB) 1746 int32_t encoding = 0xf57ff05f; // dmb 1747 Emit(encoding); 1748#elif defined(__ARM_HAVE_LDREX_STREX) 1749 LoadImmediate(R12, 0); 1750 int32_t encoding = 0xee07cfba; // mcr p15, 0, r12, c7, c10, 5 1751 Emit(encoding); 1752#else 1753 LoadImmediate(R12, 0xffff0fa0); // kuser_memory_barrier 1754 blx(R12); 1755#endif 1756#endif 1757} 1758 1759void ArmAssembler::CreateSirtEntry(ManagedRegister mout_reg, 1760 FrameOffset sirt_offset, 1761 ManagedRegister min_reg, bool null_allowed) { 1762 ArmManagedRegister out_reg = mout_reg.AsArm(); 1763 ArmManagedRegister in_reg = min_reg.AsArm(); 1764 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg; 1765 CHECK(out_reg.IsCoreRegister()) << out_reg; 1766 if (null_allowed) { 1767 // Null values get a SIRT entry value of 0. Otherwise, the SIRT entry is 1768 // the address in the SIRT holding the reference. 1769 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset) 1770 if (in_reg.IsNoRegister()) { 1771 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(), 1772 SP, sirt_offset.Int32Value()); 1773 in_reg = out_reg; 1774 } 1775 cmp(in_reg.AsCoreRegister(), ShifterOperand(0)); 1776 if (!out_reg.Equals(in_reg)) { 1777 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ); 1778 } 1779 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE); 1780 } else { 1781 AddConstant(out_reg.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL); 1782 } 1783} 1784 1785void ArmAssembler::CreateSirtEntry(FrameOffset out_off, 1786 FrameOffset sirt_offset, 1787 ManagedRegister mscratch, 1788 bool null_allowed) { 1789 ArmManagedRegister scratch = mscratch.AsArm(); 1790 CHECK(scratch.IsCoreRegister()) << scratch; 1791 if (null_allowed) { 1792 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, 1793 sirt_offset.Int32Value()); 1794 // Null values get a SIRT entry value of 0. Otherwise, the sirt entry is 1795 // the address in the SIRT holding the reference. 1796 // e.g. scratch = (scratch == 0) ? 0 : (SP+sirt_offset) 1797 cmp(scratch.AsCoreRegister(), ShifterOperand(0)); 1798 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), NE); 1799 } else { 1800 AddConstant(scratch.AsCoreRegister(), SP, sirt_offset.Int32Value(), AL); 1801 } 1802 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value()); 1803} 1804 1805void ArmAssembler::LoadReferenceFromSirt(ManagedRegister mout_reg, 1806 ManagedRegister min_reg) { 1807 ArmManagedRegister out_reg = mout_reg.AsArm(); 1808 ArmManagedRegister in_reg = min_reg.AsArm(); 1809 CHECK(out_reg.IsCoreRegister()) << out_reg; 1810 CHECK(in_reg.IsCoreRegister()) << in_reg; 1811 Label null_arg; 1812 if (!out_reg.Equals(in_reg)) { 1813 LoadImmediate(out_reg.AsCoreRegister(), 0, EQ); 1814 } 1815 cmp(in_reg.AsCoreRegister(), ShifterOperand(0)); 1816 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(), 1817 in_reg.AsCoreRegister(), 0, NE); 1818} 1819 1820void ArmAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) { 1821 // TODO: not validating references 1822} 1823 1824void ArmAssembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) { 1825 // TODO: not validating references 1826} 1827 1828void ArmAssembler::Call(ManagedRegister mbase, Offset offset, 1829 ManagedRegister mscratch) { 1830 ArmManagedRegister base = mbase.AsArm(); 1831 ArmManagedRegister scratch = mscratch.AsArm(); 1832 CHECK(base.IsCoreRegister()) << base; 1833 CHECK(scratch.IsCoreRegister()) << scratch; 1834 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 1835 base.AsCoreRegister(), offset.Int32Value()); 1836 blx(scratch.AsCoreRegister()); 1837 // TODO: place reference map on call 1838} 1839 1840void ArmAssembler::Call(FrameOffset base, Offset offset, 1841 ManagedRegister mscratch) { 1842 ArmManagedRegister scratch = mscratch.AsArm(); 1843 CHECK(scratch.IsCoreRegister()) << scratch; 1844 // Call *(*(SP + base) + offset) 1845 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 1846 SP, base.Int32Value()); 1847 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 1848 scratch.AsCoreRegister(), offset.Int32Value()); 1849 blx(scratch.AsCoreRegister()); 1850 // TODO: place reference map on call 1851} 1852 1853void ArmAssembler::Call(ThreadOffset /*offset*/, ManagedRegister /*scratch*/) { 1854 UNIMPLEMENTED(FATAL); 1855} 1856 1857void ArmAssembler::GetCurrentThread(ManagedRegister tr) { 1858 mov(tr.AsArm().AsCoreRegister(), ShifterOperand(TR)); 1859} 1860 1861void ArmAssembler::GetCurrentThread(FrameOffset offset, 1862 ManagedRegister /*scratch*/) { 1863 StoreToOffset(kStoreWord, TR, SP, offset.Int32Value(), AL); 1864} 1865 1866void ArmAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) { 1867 ArmManagedRegister scratch = mscratch.AsArm(); 1868 ArmExceptionSlowPath* slow = new ArmExceptionSlowPath(scratch, stack_adjust); 1869 buffer_.EnqueueSlowPath(slow); 1870 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 1871 TR, Thread::ExceptionOffset().Int32Value()); 1872 cmp(scratch.AsCoreRegister(), ShifterOperand(0)); 1873 b(slow->Entry(), NE); 1874} 1875 1876void ArmExceptionSlowPath::Emit(Assembler* sasm) { 1877 ArmAssembler* sp_asm = down_cast<ArmAssembler*>(sasm); 1878#define __ sp_asm-> 1879 __ Bind(&entry_); 1880 if (stack_adjust_ != 0) { // Fix up the frame. 1881 __ DecreaseFrameSize(stack_adjust_); 1882 } 1883 // Pass exception object as argument 1884 // Don't care about preserving R0 as this call won't return 1885 __ mov(R0, ShifterOperand(scratch_.AsCoreRegister())); 1886 // Set up call to Thread::Current()->pDeliverException 1887 __ LoadFromOffset(kLoadWord, R12, TR, QUICK_ENTRYPOINT_OFFSET(pDeliverException)); 1888 __ blx(R12); 1889 // Call never returns 1890 __ bkpt(0); 1891#undef __ 1892} 1893 1894} // namespace arm 1895} // namespace art 1896