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