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 #ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_ 18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_ 19 20 #include <type_traits> 21 #include <vector> 22 23 #include "base/arena_allocator.h" 24 #include "base/arena_containers.h" 25 #include "base/bit_utils.h" 26 #include "base/logging.h" 27 #include "base/stl_util.h" 28 #include "base/value_object.h" 29 #include "constants_arm.h" 30 #include "utils/arm/managed_register_arm.h" 31 #include "utils/assembler.h" 32 #include "offsets.h" 33 34 namespace art { 35 namespace arm { 36 37 class Arm32Assembler; 38 class Thumb2Assembler; 39 40 // Assembler literal is a value embedded in code, retrieved using a PC-relative load. 41 class Literal { 42 public: 43 static constexpr size_t kMaxSize = 8; 44 Literal(uint32_t size,const uint8_t * data)45 Literal(uint32_t size, const uint8_t* data) 46 : label_(), size_(size) { 47 DCHECK_LE(size, Literal::kMaxSize); 48 memcpy(data_, data, size); 49 } 50 51 template <typename T> GetValue()52 T GetValue() const { 53 DCHECK_EQ(size_, sizeof(T)); 54 T value; 55 memcpy(&value, data_, sizeof(T)); 56 return value; 57 } 58 GetSize()59 uint32_t GetSize() const { 60 return size_; 61 } 62 GetData()63 const uint8_t* GetData() const { 64 return data_; 65 } 66 GetLabel()67 Label* GetLabel() { 68 return &label_; 69 } 70 GetLabel()71 const Label* GetLabel() const { 72 return &label_; 73 } 74 75 private: 76 Label label_; 77 const uint32_t size_; 78 uint8_t data_[kMaxSize]; 79 80 DISALLOW_COPY_AND_ASSIGN(Literal); 81 }; 82 83 // Jump table: table of labels emitted after the literals. Similar to literals. 84 class JumpTable { 85 public: JumpTable(std::vector<Label * > && labels)86 explicit JumpTable(std::vector<Label*>&& labels) 87 : label_(), anchor_label_(), labels_(std::move(labels)) { 88 } 89 GetSize()90 uint32_t GetSize() const { 91 return static_cast<uint32_t>(labels_.size()) * sizeof(uint32_t); 92 } 93 GetData()94 const std::vector<Label*>& GetData() const { 95 return labels_; 96 } 97 GetLabel()98 Label* GetLabel() { 99 return &label_; 100 } 101 GetLabel()102 const Label* GetLabel() const { 103 return &label_; 104 } 105 GetAnchorLabel()106 Label* GetAnchorLabel() { 107 return &anchor_label_; 108 } 109 GetAnchorLabel()110 const Label* GetAnchorLabel() const { 111 return &anchor_label_; 112 } 113 114 private: 115 Label label_; 116 Label anchor_label_; 117 std::vector<Label*> labels_; 118 119 DISALLOW_COPY_AND_ASSIGN(JumpTable); 120 }; 121 122 class ShifterOperand { 123 public: ShifterOperand()124 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister), 125 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { 126 } 127 128 explicit ShifterOperand(uint32_t immed); 129 130 // Data-processing operands - Register ShifterOperand(Register rm)131 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister), 132 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { 133 } 134 ShifterOperand(uint32_t rotate,uint32_t immed8)135 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister), 136 rs_(kNoRegister), 137 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) { 138 } 139 type_(kRegister)140 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm), 141 rs_(kNoRegister), 142 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) { 143 } 144 145 // Data-processing operands - Logical shift/rotate by register ShifterOperand(Register rm,Shift shift,Register rs)146 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm), 147 rs_(rs), 148 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) { 149 } 150 is_valid()151 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); } 152 type()153 uint32_t type() const { 154 CHECK(is_valid()); 155 return type_; 156 } 157 158 uint32_t encodingArm() const; 159 uint32_t encodingThumb() const; 160 IsEmpty()161 bool IsEmpty() const { 162 return type_ == kUnknown; 163 } 164 IsImmediate()165 bool IsImmediate() const { 166 return type_ == kImmediate; 167 } 168 IsRegister()169 bool IsRegister() const { 170 return type_ == kRegister; 171 } 172 IsShift()173 bool IsShift() const { 174 return is_shift_; 175 } 176 GetImmediate()177 uint32_t GetImmediate() const { 178 return immed_; 179 } 180 GetShift()181 Shift GetShift() const { 182 return shift_; 183 } 184 GetRegister()185 Register GetRegister() const { 186 return rm_; 187 } 188 GetSecondRegister()189 Register GetSecondRegister() const { 190 return rs_; 191 } 192 193 enum Type { 194 kUnknown = -1, 195 kRegister, 196 kImmediate 197 }; 198 199 private: 200 Type type_; 201 Register rm_; 202 Register rs_; 203 bool is_rotate_; 204 bool is_shift_; 205 Shift shift_; 206 uint32_t rotate_; 207 uint32_t immed_; 208 209 friend class Arm32Assembler; 210 friend class Thumb2Assembler; 211 212 #ifdef SOURCE_ASSEMBLER_SUPPORT 213 friend class BinaryAssembler; 214 #endif 215 }; 216 217 218 enum LoadOperandType { 219 kLoadSignedByte, 220 kLoadUnsignedByte, 221 kLoadSignedHalfword, 222 kLoadUnsignedHalfword, 223 kLoadWord, 224 kLoadWordPair, 225 kLoadSWord, 226 kLoadDWord 227 }; 228 229 230 enum StoreOperandType { 231 kStoreByte, 232 kStoreHalfword, 233 kStoreWord, 234 kStoreWordPair, 235 kStoreSWord, 236 kStoreDWord 237 }; 238 239 240 // Load/store multiple addressing mode. 241 enum BlockAddressMode { 242 // bit encoding P U W 243 DA = (0|0|0) << 21, // decrement after 244 IA = (0|4|0) << 21, // increment after 245 DB = (8|0|0) << 21, // decrement before 246 IB = (8|4|0) << 21, // increment before 247 DA_W = (0|0|1) << 21, // decrement after with writeback to base 248 IA_W = (0|4|1) << 21, // increment after with writeback to base 249 DB_W = (8|0|1) << 21, // decrement before with writeback to base 250 IB_W = (8|4|1) << 21 // increment before with writeback to base 251 }; 252 inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) { 253 os << static_cast<int>(rhs); 254 return os; 255 } 256 257 class Address : public ValueObject { 258 public: 259 // Memory operand addressing mode (in ARM encoding form. For others we need 260 // to adjust) 261 enum Mode { 262 // bit encoding P U W 263 Offset = (8|4|0) << 21, // offset (w/o writeback to base) 264 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback 265 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback 266 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base) 267 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback 268 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback 269 }; 270 rn_(rn)271 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0), 272 offset_(offset), 273 am_(am), is_immed_offset_(true), shift_(LSL) { 274 } 275 rn_(rn)276 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0), 277 am_(am), is_immed_offset_(false), shift_(LSL) { 278 CHECK_NE(rm, PC); 279 } 280 281 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) : rn_(rn)282 rn_(rn), rm_(rm), offset_(count), 283 am_(am), is_immed_offset_(false), shift_(shift) { 284 CHECK_NE(rm, PC); 285 } 286 287 // LDR(literal) - pc relative load. Address(int32_t offset)288 explicit Address(int32_t offset) : 289 rn_(PC), rm_(R0), offset_(offset), 290 am_(Offset), is_immed_offset_(false), shift_(LSL) { 291 } 292 293 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset); 294 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset); 295 296 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset); 297 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset); 298 299 uint32_t encodingArm() const; 300 uint32_t encodingThumb(bool is_32bit) const; 301 302 uint32_t encoding3() const; 303 uint32_t vencoding() const; 304 305 uint32_t encodingThumbLdrdStrd() const; 306 GetRegister()307 Register GetRegister() const { 308 return rn_; 309 } 310 GetRegisterOffset()311 Register GetRegisterOffset() const { 312 return rm_; 313 } 314 GetOffset()315 int32_t GetOffset() const { 316 return offset_; 317 } 318 GetMode()319 Mode GetMode() const { 320 return am_; 321 } 322 IsImmediate()323 bool IsImmediate() const { 324 return is_immed_offset_; 325 } 326 GetShift()327 Shift GetShift() const { 328 return shift_; 329 } 330 GetShiftCount()331 int32_t GetShiftCount() const { 332 CHECK(!is_immed_offset_); 333 return offset_; 334 } 335 336 private: 337 const Register rn_; 338 const Register rm_; 339 const int32_t offset_; // Used as shift amount for register offset. 340 const Mode am_; 341 const bool is_immed_offset_; 342 const Shift shift_; 343 }; 344 inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) { 345 os << static_cast<int>(rhs); 346 return os; 347 } 348 349 // Instruction encoding bits. 350 enum { 351 H = 1 << 5, // halfword (or byte) 352 L = 1 << 20, // load (or store) 353 S = 1 << 20, // set condition code (or leave unchanged) 354 W = 1 << 21, // writeback base register (or leave unchanged) 355 A = 1 << 21, // accumulate in multiply instruction (or not) 356 B = 1 << 22, // unsigned byte (or word) 357 N = 1 << 22, // long (or short) 358 U = 1 << 23, // positive (or negative) offset/index 359 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) 360 I = 1 << 25, // immediate shifter operand (or not) 361 362 B0 = 1, 363 B1 = 1 << 1, 364 B2 = 1 << 2, 365 B3 = 1 << 3, 366 B4 = 1 << 4, 367 B5 = 1 << 5, 368 B6 = 1 << 6, 369 B7 = 1 << 7, 370 B8 = 1 << 8, 371 B9 = 1 << 9, 372 B10 = 1 << 10, 373 B11 = 1 << 11, 374 B12 = 1 << 12, 375 B13 = 1 << 13, 376 B14 = 1 << 14, 377 B15 = 1 << 15, 378 B16 = 1 << 16, 379 B17 = 1 << 17, 380 B18 = 1 << 18, 381 B19 = 1 << 19, 382 B20 = 1 << 20, 383 B21 = 1 << 21, 384 B22 = 1 << 22, 385 B23 = 1 << 23, 386 B24 = 1 << 24, 387 B25 = 1 << 25, 388 B26 = 1 << 26, 389 B27 = 1 << 27, 390 B28 = 1 << 28, 391 B29 = 1 << 29, 392 B30 = 1 << 30, 393 B31 = 1 << 31, 394 395 // Instruction bit masks. 396 RdMask = 15 << 12, // in str instruction 397 CondMask = 15 << 28, 398 CoprocessorMask = 15 << 8, 399 OpCodeMask = 15 << 21, // in data-processing instructions 400 Imm24Mask = (1 << 24) - 1, 401 Off12Mask = (1 << 12) - 1, 402 403 // ldrex/strex register field encodings. 404 kLdExRnShift = 16, 405 kLdExRtShift = 12, 406 kStrExRnShift = 16, 407 kStrExRdShift = 12, 408 kStrExRtShift = 0, 409 }; 410 411 // IfThen state for IT instructions. 412 enum ItState { 413 kItOmitted, 414 kItThen, 415 kItT = kItThen, 416 kItElse, 417 kItE = kItElse 418 }; 419 420 // Set condition codes request. 421 enum SetCc { 422 kCcDontCare, // Allows prioritizing 16-bit instructions on Thumb2 whether they set CCs or not. 423 kCcSet, 424 kCcKeep, 425 }; 426 427 constexpr uint32_t kNoItCondition = 3; 428 constexpr uint32_t kInvalidModifiedImmediate = -1; 429 430 extern const char* kRegisterNames[]; 431 extern const char* kConditionNames[]; 432 433 // This is an abstract ARM assembler. Subclasses provide assemblers for the individual 434 // instruction sets (ARM32, Thumb2, etc.) 435 // 436 class ArmAssembler : public Assembler { 437 public: ~ArmAssembler()438 virtual ~ArmAssembler() {} 439 440 // Is this assembler for the thumb instruction set? 441 virtual bool IsThumb() const = 0; 442 443 // Data-processing instructions. 444 virtual void and_(Register rd, Register rn, const ShifterOperand& so, 445 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 446 447 virtual void ands(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 448 and_(rd, rn, so, cond, kCcSet); 449 } 450 451 virtual void eor(Register rd, Register rn, const ShifterOperand& so, 452 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 453 454 virtual void eors(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 455 eor(rd, rn, so, cond, kCcSet); 456 } 457 458 virtual void sub(Register rd, Register rn, const ShifterOperand& so, 459 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 460 461 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 462 sub(rd, rn, so, cond, kCcSet); 463 } 464 465 virtual void rsb(Register rd, Register rn, const ShifterOperand& so, 466 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 467 468 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 469 rsb(rd, rn, so, cond, kCcSet); 470 } 471 472 virtual void add(Register rd, Register rn, const ShifterOperand& so, 473 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 474 475 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 476 add(rd, rn, so, cond, kCcSet); 477 } 478 479 virtual void adc(Register rd, Register rn, const ShifterOperand& so, 480 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 481 482 virtual void adcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 483 adc(rd, rn, so, cond, kCcSet); 484 } 485 486 virtual void sbc(Register rd, Register rn, const ShifterOperand& so, 487 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 488 489 virtual void sbcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 490 sbc(rd, rn, so, cond, kCcSet); 491 } 492 493 virtual void rsc(Register rd, Register rn, const ShifterOperand& so, 494 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 495 496 virtual void rscs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 497 rsc(rd, rn, so, cond, kCcSet); 498 } 499 500 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 501 502 virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 503 504 virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 505 506 // Note: CMN updates flags based on addition of its operands. Do not confuse 507 // the "N" suffix with bitwise inversion performed by MVN. 508 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 509 510 virtual void orr(Register rd, Register rn, const ShifterOperand& so, 511 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 512 513 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 514 orr(rd, rn, so, cond, kCcSet); 515 } 516 517 virtual void orn(Register rd, Register rn, const ShifterOperand& so, 518 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 519 520 virtual void orns(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 521 orn(rd, rn, so, cond, kCcSet); 522 } 523 524 virtual void mov(Register rd, const ShifterOperand& so, 525 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 526 527 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) { 528 mov(rd, so, cond, kCcSet); 529 } 530 531 virtual void bic(Register rd, Register rn, const ShifterOperand& so, 532 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 533 534 virtual void bics(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) { 535 bic(rd, rn, so, cond, kCcSet); 536 } 537 538 virtual void mvn(Register rd, const ShifterOperand& so, 539 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 540 541 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) { 542 mvn(rd, so, cond, kCcSet); 543 } 544 545 // Miscellaneous data-processing instructions. 546 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0; 547 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0; 548 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0; 549 virtual void rbit(Register rd, Register rm, Condition cond = AL) = 0; 550 virtual void rev(Register rd, Register rm, Condition cond = AL) = 0; 551 virtual void rev16(Register rd, Register rm, Condition cond = AL) = 0; 552 virtual void revsh(Register rd, Register rm, Condition cond = AL) = 0; 553 554 // Multiply instructions. 555 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0; 556 virtual void mla(Register rd, Register rn, Register rm, Register ra, 557 Condition cond = AL) = 0; 558 virtual void mls(Register rd, Register rn, Register rm, Register ra, 559 Condition cond = AL) = 0; 560 virtual void smull(Register rd_lo, Register rd_hi, Register rn, Register rm, 561 Condition cond = AL) = 0; 562 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, 563 Condition cond = AL) = 0; 564 565 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0; 566 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0; 567 568 // Bit field extract instructions. 569 virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, 570 Condition cond = AL) = 0; 571 virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, 572 Condition cond = AL) = 0; 573 574 // Load/store instructions. 575 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0; 576 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0; 577 578 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0; 579 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0; 580 581 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0; 582 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0; 583 584 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0; 585 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0; 586 587 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0; 588 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0; 589 590 virtual void ldm(BlockAddressMode am, Register base, 591 RegList regs, Condition cond = AL) = 0; 592 virtual void stm(BlockAddressMode am, Register base, 593 RegList regs, Condition cond = AL) = 0; 594 595 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0; 596 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0; 597 virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0; 598 virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0; 599 600 // Miscellaneous instructions. 601 virtual void clrex(Condition cond = AL) = 0; 602 virtual void nop(Condition cond = AL) = 0; 603 604 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. 605 virtual void bkpt(uint16_t imm16) = 0; 606 virtual void svc(uint32_t imm24) = 0; 607 608 virtual void it(Condition firstcond ATTRIBUTE_UNUSED, 609 ItState i1 ATTRIBUTE_UNUSED = kItOmitted, 610 ItState i2 ATTRIBUTE_UNUSED = kItOmitted, 611 ItState i3 ATTRIBUTE_UNUSED = kItOmitted) { 612 // Ignored if not supported. 613 } 614 615 virtual void cbz(Register rn, Label* target) = 0; 616 virtual void cbnz(Register rn, Label* target) = 0; 617 618 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). 619 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0; 620 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0; 621 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0; 622 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0; 623 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0; 624 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0; 625 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0; 626 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 627 628 // Returns false if the immediate cannot be encoded. 629 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0; 630 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0; 631 632 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0; 633 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0; 634 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0; 635 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0; 636 637 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 638 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 639 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 640 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 641 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 642 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 643 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 644 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 645 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 646 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 647 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 648 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 649 650 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0; 651 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 652 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0; 653 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 654 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0; 655 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 656 657 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0; 658 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0; 659 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0; 660 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0; 661 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0; 662 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0; 663 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0; 664 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0; 665 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0; 666 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0; 667 668 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0; 669 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 670 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0; 671 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0; 672 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR 673 674 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0; 675 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0; 676 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0; 677 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0; 678 679 // Branch instructions. 680 virtual void b(Label* label, Condition cond = AL) = 0; 681 virtual void bl(Label* label, Condition cond = AL) = 0; 682 virtual void blx(Register rm, Condition cond = AL) = 0; 683 virtual void bx(Register rm, Condition cond = AL) = 0; 684 685 // Memory barriers. 686 virtual void dmb(DmbOptions flavor) = 0; 687 688 void Pad(uint32_t bytes); 689 690 // Adjust label position. AdjustLabelPosition(Label * label)691 void AdjustLabelPosition(Label* label) { 692 DCHECK(label->IsBound()); 693 uint32_t old_position = static_cast<uint32_t>(label->Position()); 694 uint32_t new_position = GetAdjustedPosition(old_position); 695 label->Reinitialize(); 696 DCHECK_GE(static_cast<int>(new_position), 0); 697 label->BindTo(static_cast<int>(new_position)); 698 } 699 700 // Get the final position of a label after local fixup based on the old position 701 // recorded before FinalizeCode(). 702 virtual uint32_t GetAdjustedPosition(uint32_t old_position) = 0; 703 704 // Macros. 705 // Most of these are pure virtual as they need to be implemented per instruction set. 706 707 // Create a new literal with a given value. 708 // NOTE: Force the template parameter to be explicitly specified. 709 template <typename T> NewLiteral(typename Identity<T>::type value)710 Literal* NewLiteral(typename Identity<T>::type value) { 711 static_assert(std::is_integral<T>::value, "T must be an integral type."); 712 return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value)); 713 } 714 715 // Create a new literal with the given data. 716 virtual Literal* NewLiteral(size_t size, const uint8_t* data) = 0; 717 718 // Load literal. 719 virtual void LoadLiteral(Register rt, Literal* literal) = 0; 720 virtual void LoadLiteral(Register rt, Register rt2, Literal* literal) = 0; 721 virtual void LoadLiteral(SRegister sd, Literal* literal) = 0; 722 virtual void LoadLiteral(DRegister dd, Literal* literal) = 0; 723 724 // Add signed constant value to rd. May clobber IP. 725 virtual void AddConstant(Register rd, Register rn, int32_t value, 726 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 727 void AddConstantSetFlags(Register rd, Register rn, int32_t value, Condition cond = AL) { 728 AddConstant(rd, rn, value, cond, kCcSet); 729 } 730 void AddConstant(Register rd, int32_t value, Condition cond = AL, SetCc set_cc = kCcDontCare) { 731 AddConstant(rd, rd, value, cond, set_cc); 732 } 733 734 virtual void CmpConstant(Register rn, int32_t value, Condition cond = AL) = 0; 735 736 // Load and Store. May clobber IP. 737 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0; 738 void LoadSImmediate(SRegister sd, float value, Condition cond = AL) { 739 if (!vmovs(sd, value, cond)) { 740 int32_t int_value = bit_cast<int32_t, float>(value); 741 if (int_value == bit_cast<int32_t, float>(0.0f)) { 742 // 0.0 is quite common, so we special case it by loading 743 // 2.0 in `sd` and then substracting it. 744 bool success = vmovs(sd, 2.0, cond); 745 CHECK(success); 746 vsubs(sd, sd, sd, cond); 747 } else { 748 LoadImmediate(IP, int_value, cond); 749 vmovsr(sd, IP, cond); 750 } 751 } 752 } 753 754 void LoadDImmediate(DRegister sd, double value, Condition cond = AL) { 755 if (!vmovd(sd, value, cond)) { 756 uint64_t int_value = bit_cast<uint64_t, double>(value); 757 if (int_value == bit_cast<uint64_t, double>(0.0)) { 758 // 0.0 is quite common, so we special case it by loading 759 // 2.0 in `sd` and then substracting it. 760 bool success = vmovd(sd, 2.0, cond); 761 CHECK(success); 762 vsubd(sd, sd, sd, cond); 763 } else { 764 if (sd < 16) { 765 SRegister low = static_cast<SRegister>(sd << 1); 766 SRegister high = static_cast<SRegister>(low + 1); 767 LoadSImmediate(low, bit_cast<float, uint32_t>(Low32Bits(int_value)), cond); 768 if (High32Bits(int_value) == Low32Bits(int_value)) { 769 vmovs(high, low); 770 } else { 771 LoadSImmediate(high, bit_cast<float, uint32_t>(High32Bits(int_value)), cond); 772 } 773 } else { 774 LOG(FATAL) << "Unimplemented loading of double into a D register " 775 << "that cannot be split into two S registers"; 776 } 777 } 778 } 779 } 780 781 virtual void MarkExceptionHandler(Label* label) = 0; 782 virtual void LoadFromOffset(LoadOperandType type, 783 Register reg, 784 Register base, 785 int32_t offset, 786 Condition cond = AL) = 0; 787 virtual void StoreToOffset(StoreOperandType type, 788 Register reg, 789 Register base, 790 int32_t offset, 791 Condition cond = AL) = 0; 792 virtual void LoadSFromOffset(SRegister reg, 793 Register base, 794 int32_t offset, 795 Condition cond = AL) = 0; 796 virtual void StoreSToOffset(SRegister reg, 797 Register base, 798 int32_t offset, 799 Condition cond = AL) = 0; 800 virtual void LoadDFromOffset(DRegister reg, 801 Register base, 802 int32_t offset, 803 Condition cond = AL) = 0; 804 virtual void StoreDToOffset(DRegister reg, 805 Register base, 806 int32_t offset, 807 Condition cond = AL) = 0; 808 809 virtual void Push(Register rd, Condition cond = AL) = 0; 810 virtual void Pop(Register rd, Condition cond = AL) = 0; 811 812 virtual void PushList(RegList regs, Condition cond = AL) = 0; 813 virtual void PopList(RegList regs, Condition cond = AL) = 0; 814 815 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0; 816 817 // Convenience shift instructions. Use mov instruction with shifter operand 818 // for variants setting the status flags or using a register shift count. 819 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, 820 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 821 822 void Lsls(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) { 823 Lsl(rd, rm, shift_imm, cond, kCcSet); 824 } 825 826 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, 827 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 828 829 void Lsrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) { 830 Lsr(rd, rm, shift_imm, cond, kCcSet); 831 } 832 833 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, 834 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 835 836 void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) { 837 Asr(rd, rm, shift_imm, cond, kCcSet); 838 } 839 840 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, 841 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 842 843 void Rors(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) { 844 Ror(rd, rm, shift_imm, cond, kCcSet); 845 } 846 847 virtual void Rrx(Register rd, Register rm, 848 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 849 850 void Rrxs(Register rd, Register rm, Condition cond = AL) { 851 Rrx(rd, rm, cond, kCcSet); 852 } 853 854 virtual void Lsl(Register rd, Register rm, Register rn, 855 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 856 857 void Lsls(Register rd, Register rm, Register rn, Condition cond = AL) { 858 Lsl(rd, rm, rn, cond, kCcSet); 859 } 860 861 virtual void Lsr(Register rd, Register rm, Register rn, 862 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 863 864 void Lsrs(Register rd, Register rm, Register rn, Condition cond = AL) { 865 Lsr(rd, rm, rn, cond, kCcSet); 866 } 867 868 virtual void Asr(Register rd, Register rm, Register rn, 869 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 870 871 void Asrs(Register rd, Register rm, Register rn, Condition cond = AL) { 872 Asr(rd, rm, rn, cond, kCcSet); 873 } 874 875 virtual void Ror(Register rd, Register rm, Register rn, 876 Condition cond = AL, SetCc set_cc = kCcDontCare) = 0; 877 878 void Rors(Register rd, Register rm, Register rn, Condition cond = AL) { 879 Ror(rd, rm, rn, cond, kCcSet); 880 } 881 882 // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes, 883 // `shifter_op` contains the operand. 884 virtual bool ShifterOperandCanHold(Register rd, 885 Register rn, 886 Opcode opcode, 887 uint32_t immediate, 888 SetCc set_cc, 889 ShifterOperand* shifter_op) = 0; ShifterOperandCanHold(Register rd,Register rn,Opcode opcode,uint32_t immediate,ShifterOperand * shifter_op)890 bool ShifterOperandCanHold(Register rd, 891 Register rn, 892 Opcode opcode, 893 uint32_t immediate, 894 ShifterOperand* shifter_op) { 895 return ShifterOperandCanHold(rd, rn, opcode, immediate, kCcDontCare, shifter_op); 896 } 897 898 virtual bool ShifterOperandCanAlwaysHold(uint32_t immediate) = 0; 899 900 static bool IsInstructionForExceptionHandling(uintptr_t pc); 901 902 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0; 903 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0; 904 905 // 906 // Overridden common assembler high-level functionality 907 // 908 909 // Emit code that will create an activation on the stack 910 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 911 const std::vector<ManagedRegister>& callee_save_regs, 912 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 913 914 // Emit code that will remove an activation from the stack 915 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) 916 OVERRIDE; 917 918 void IncreaseFrameSize(size_t adjust) OVERRIDE; 919 void DecreaseFrameSize(size_t adjust) OVERRIDE; 920 921 // Store routines 922 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE; 923 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE; 924 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE; 925 926 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE; 927 928 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch) 929 OVERRIDE; 930 931 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, 932 ManagedRegister scratch) OVERRIDE; 933 934 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE; 935 936 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off, 937 ManagedRegister scratch) OVERRIDE; 938 939 // Load routines 940 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE; 941 942 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE; 943 944 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 945 946 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs, 947 bool unpoison_reference) OVERRIDE; 948 949 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE; 950 951 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE; 952 953 // Copying routines 954 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE; 955 956 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs, 957 ManagedRegister scratch) OVERRIDE; 958 959 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch) 960 OVERRIDE; 961 962 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE; 963 964 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE; 965 966 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch, 967 size_t size) OVERRIDE; 968 969 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch, 970 size_t size) OVERRIDE; 971 972 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch, 973 size_t size) OVERRIDE; 974 975 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 976 ManagedRegister scratch, size_t size) OVERRIDE; 977 978 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 979 ManagedRegister scratch, size_t size) OVERRIDE; 980 981 // Sign extension 982 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 983 984 // Zero extension 985 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 986 987 // Exploit fast access in managed code to Thread::Current() 988 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 989 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE; 990 991 // Set up out_reg to hold a Object** into the handle scope, or to be null if the 992 // value is null and null_allowed. in_reg holds a possibly stale reference 993 // that can be used to avoid loading the handle scope entry to see if the value is 994 // null. 995 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, 996 ManagedRegister in_reg, bool null_allowed) OVERRIDE; 997 998 // Set up out_off to hold a Object** into the handle scope, or to be null if the 999 // value is null and null_allowed. 1000 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, 1001 ManagedRegister scratch, bool null_allowed) OVERRIDE; 1002 1003 // src holds a handle scope entry (Object**) load this into dst 1004 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE; 1005 1006 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 1007 // know that src may not be null. 1008 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 1009 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 1010 1011 // Call to address held at [base+offset] 1012 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE; 1013 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE; 1014 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE; 1015 1016 // Generate code to check if Thread::Current()->exception_ is non-null 1017 // and branch to a ExceptionSlowPath if it is. 1018 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; 1019 1020 static uint32_t ModifiedImmediate(uint32_t value); 1021 IsLowRegister(Register r)1022 static bool IsLowRegister(Register r) { 1023 return r < R8; 1024 } 1025 IsHighRegister(Register r)1026 static bool IsHighRegister(Register r) { 1027 return r >= R8; 1028 } 1029 1030 // 1031 // Heap poisoning. 1032 // 1033 1034 // Poison a heap reference contained in `reg`. PoisonHeapReference(Register reg)1035 void PoisonHeapReference(Register reg) { 1036 // reg = -reg. 1037 rsb(reg, reg, ShifterOperand(0)); 1038 } 1039 // Unpoison a heap reference contained in `reg`. UnpoisonHeapReference(Register reg)1040 void UnpoisonHeapReference(Register reg) { 1041 // reg = -reg. 1042 rsb(reg, reg, ShifterOperand(0)); 1043 } 1044 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled. MaybeUnpoisonHeapReference(Register reg)1045 void MaybeUnpoisonHeapReference(Register reg) { 1046 if (kPoisonHeapReferences) { 1047 UnpoisonHeapReference(reg); 1048 } 1049 } 1050 Jump(Label * label)1051 void Jump(Label* label) OVERRIDE { 1052 b(label); 1053 } 1054 1055 // Jump table support. This is split into three functions: 1056 // 1057 // * CreateJumpTable creates the internal metadata to track the jump targets, and emits code to 1058 // load the base address of the jump table. 1059 // 1060 // * EmitJumpTableDispatch emits the code to actually jump, assuming that the right table value 1061 // has been loaded into a register already. 1062 // 1063 // * FinalizeTables emits the jump table into the literal pool. This can only be called after the 1064 // labels for the jump targets have been finalized. 1065 1066 // Create a jump table for the given labels that will be emitted when finalizing. Create a load 1067 // sequence (or placeholder) that stores the base address into the given register. When the table 1068 // is emitted, offsets will be relative to the location EmitJumpTableDispatch was called on (the 1069 // anchor). 1070 virtual JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) = 0; 1071 1072 // Emit the jump-table jump, assuming that the right value was loaded into displacement_reg. 1073 virtual void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) = 0; 1074 1075 // Bind a Label that needs to be updated by the assembler in FinalizeCode() if its position 1076 // changes due to branch/literal fixup. BindTrackedLabel(Label * label)1077 void BindTrackedLabel(Label* label) { 1078 Bind(label); 1079 tracked_labels_.push_back(label); 1080 } 1081 1082 protected: ArmAssembler(ArenaAllocator * arena)1083 explicit ArmAssembler(ArenaAllocator* arena) 1084 : Assembler(arena), tracked_labels_(arena->Adapter(kArenaAllocAssembler)) {} 1085 1086 // Returns whether or not the given register is used for passing parameters. RegisterCompare(const Register * reg1,const Register * reg2)1087 static int RegisterCompare(const Register* reg1, const Register* reg2) { 1088 return *reg1 - *reg2; 1089 } 1090 1091 void FinalizeTrackedLabels(); 1092 1093 // Tracked labels. Use a vector, as we need to sort before adjusting. 1094 ArenaVector<Label*> tracked_labels_; 1095 }; 1096 1097 // Slowpath entered when Thread::Current()->_exception is non-null 1098 class ArmExceptionSlowPath FINAL : public SlowPath { 1099 public: ArmExceptionSlowPath(ArmManagedRegister scratch,size_t stack_adjust)1100 ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust) 1101 : scratch_(scratch), stack_adjust_(stack_adjust) { 1102 } 1103 void Emit(Assembler *sp_asm) OVERRIDE; 1104 private: 1105 const ArmManagedRegister scratch_; 1106 const size_t stack_adjust_; 1107 }; 1108 1109 } // namespace arm 1110 } // namespace art 1111 1112 #endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_ 1113