Home | History | Annotate | Download | only in arm
      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 
     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>
     54   T GetValue() const {
     55     DCHECK_EQ(size_, sizeof(T));
     56     T value;
     57     memcpy(&value, data_, sizeof(T));
     58     return value;
     59   }
     60 
     61   uint32_t GetSize() const {
     62     return size_;
     63   }
     64 
     65   const uint8_t* GetData() const {
     66     return data_;
     67   }
     68 
     69   Label* GetLabel() {
     70     return &label_;
     71   }
     72 
     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:
     88   explicit JumpTable(std::vector<Label*>&& labels)
     89       : label_(), anchor_label_(), labels_(std::move(labels)) {
     90   }
     91 
     92   uint32_t GetSize() const {
     93     return static_cast<uint32_t>(labels_.size()) * sizeof(uint32_t);
     94   }
     95 
     96   const std::vector<Label*>& GetData() const {
     97     return labels_;
     98   }
     99 
    100   Label* GetLabel() {
    101     return &label_;
    102   }
    103 
    104   const Label* GetLabel() const {
    105     return &label_;
    106   }
    107 
    108   Label* GetAnchorLabel() {
    109     return &anchor_label_;
    110   }
    111 
    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:
    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
    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 
    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 
    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
    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 
    153   bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
    154 
    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 
    163   bool IsEmpty() const {
    164     return type_ == kUnknown;
    165   }
    166 
    167   bool IsImmediate() const {
    168     return type_ == kImmediate;
    169   }
    170 
    171   bool IsRegister() const {
    172     return type_ == kRegister;
    173   }
    174 
    175   bool IsShift() const {
    176     return is_shift_;
    177   }
    178 
    179   uint32_t GetImmediate() const {
    180     return immed_;
    181   }
    182 
    183   Shift GetShift() const {
    184     return shift_;
    185   }
    186 
    187   Register GetRegister() const {
    188     return rm_;
    189   }
    190 
    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 
    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 
    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) :
    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 
    279   Register GetRegister() const {
    280     return rn_;
    281   }
    282 
    283   Register GetRegisterOffset() const {
    284     return rm_;
    285   }
    286 
    287   int32_t GetOffset() const {
    288     return offset_;
    289   }
    290 
    291   Mode GetMode() const {
    292     return am_;
    293   }
    294 
    295   bool IsImmediate() const {
    296     return is_immed_offset_;
    297   }
    298 
    299   Shift GetShift() const {
    300     return shift_;
    301   }
    302 
    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:
    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.
    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>
    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;
    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 
    855   static bool IsLowRegister(Register r) {
    856     return r < R8;
    857   }
    858 
    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`.
    868   void PoisonHeapReference(Register reg) {
    869     // reg = -reg.
    870     rsb(reg, reg, ShifterOperand(0));
    871   }
    872   // Unpoison a heap reference contained in `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.
    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.
    884   void MaybeUnpoisonHeapReference(Register reg) {
    885     if (kPoisonHeapReferences) {
    886       UnpoisonHeapReference(reg);
    887     }
    888   }
    889 
    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.
    916   void BindTrackedLabel(Label* label) {
    917     Bind(label);
    918     tracked_labels_.push_back(label);
    919   }
    920 
    921  protected:
    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.
    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