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 <vector>
     21 
     22 #include "base/bit_utils.h"
     23 #include "base/logging.h"
     24 #include "base/value_object.h"
     25 #include "constants_arm.h"
     26 #include "utils/arm/managed_register_arm.h"
     27 #include "utils/assembler.h"
     28 #include "offsets.h"
     29 
     30 namespace art {
     31 namespace arm {
     32 
     33 class Arm32Assembler;
     34 class Thumb2Assembler;
     35 
     36 class ShifterOperand {
     37  public:
     38   ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister),
     39       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
     40   }
     41 
     42   explicit ShifterOperand(uint32_t immed);
     43 
     44   // Data-processing operands - Register
     45   explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
     46       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
     47   }
     48 
     49   ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister),
     50       rs_(kNoRegister),
     51       is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) {
     52   }
     53 
     54   ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm),
     55       rs_(kNoRegister),
     56       is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) {
     57   }
     58 
     59   // Data-processing operands - Logical shift/rotate by register
     60   ShifterOperand(Register rm, Shift shift, Register rs)  : type_(kRegister), rm_(rm),
     61       rs_(rs),
     62       is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) {
     63   }
     64 
     65   bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); }
     66 
     67   uint32_t type() const {
     68     CHECK(is_valid());
     69     return type_;
     70   }
     71 
     72   uint32_t encodingArm() const;
     73   uint32_t encodingThumb() const;
     74 
     75   bool IsEmpty() const {
     76     return type_ == kUnknown;
     77   }
     78 
     79   bool IsImmediate() const {
     80     return type_ == kImmediate;
     81   }
     82 
     83   bool IsRegister() const {
     84     return type_ == kRegister;
     85   }
     86 
     87   bool IsShift() const {
     88     return is_shift_;
     89   }
     90 
     91   uint32_t GetImmediate() const {
     92     return immed_;
     93   }
     94 
     95   Shift GetShift() const {
     96     return shift_;
     97   }
     98 
     99   Register GetRegister() const {
    100     return rm_;
    101   }
    102 
    103   Register GetSecondRegister() const {
    104     return rs_;
    105   }
    106 
    107   enum Type {
    108     kUnknown = -1,
    109     kRegister,
    110     kImmediate
    111   };
    112 
    113  private:
    114   Type type_;
    115   Register rm_;
    116   Register rs_;
    117   bool is_rotate_;
    118   bool is_shift_;
    119   Shift shift_;
    120   uint32_t rotate_;
    121   uint32_t immed_;
    122 
    123   friend class Arm32Assembler;
    124   friend class Thumb2Assembler;
    125 
    126 #ifdef SOURCE_ASSEMBLER_SUPPORT
    127   friend class BinaryAssembler;
    128 #endif
    129 };
    130 
    131 
    132 enum LoadOperandType {
    133   kLoadSignedByte,
    134   kLoadUnsignedByte,
    135   kLoadSignedHalfword,
    136   kLoadUnsignedHalfword,
    137   kLoadWord,
    138   kLoadWordPair,
    139   kLoadSWord,
    140   kLoadDWord
    141 };
    142 
    143 
    144 enum StoreOperandType {
    145   kStoreByte,
    146   kStoreHalfword,
    147   kStoreWord,
    148   kStoreWordPair,
    149   kStoreSWord,
    150   kStoreDWord
    151 };
    152 
    153 
    154 // Load/store multiple addressing mode.
    155 enum BlockAddressMode {
    156   // bit encoding P U W
    157   DA           = (0|0|0) << 21,  // decrement after
    158   IA           = (0|4|0) << 21,  // increment after
    159   DB           = (8|0|0) << 21,  // decrement before
    160   IB           = (8|4|0) << 21,  // increment before
    161   DA_W         = (0|0|1) << 21,  // decrement after with writeback to base
    162   IA_W         = (0|4|1) << 21,  // increment after with writeback to base
    163   DB_W         = (8|0|1) << 21,  // decrement before with writeback to base
    164   IB_W         = (8|4|1) << 21   // increment before with writeback to base
    165 };
    166 inline std::ostream& operator<<(std::ostream& os, const BlockAddressMode& rhs) {
    167   os << static_cast<int>(rhs);
    168   return os;
    169 }
    170 
    171 class Address : public ValueObject {
    172  public:
    173   // Memory operand addressing mode (in ARM encoding form.  For others we need
    174   // to adjust)
    175   enum Mode {
    176     // bit encoding P U W
    177     Offset       = (8|4|0) << 21,  // offset (w/o writeback to base)
    178     PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
    179     PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
    180     NegOffset    = (8|0|0) << 21,  // negative offset (w/o writeback to base)
    181     NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
    182     NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
    183   };
    184 
    185   Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0),
    186       offset_(offset),
    187       am_(am), is_immed_offset_(true), shift_(LSL) {
    188   }
    189 
    190   Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0),
    191       am_(am), is_immed_offset_(false), shift_(LSL) {
    192     CHECK_NE(rm, PC);
    193   }
    194 
    195   Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) :
    196                        rn_(rn), rm_(rm), offset_(count),
    197                        am_(am), is_immed_offset_(false), shift_(shift) {
    198     CHECK_NE(rm, PC);
    199   }
    200 
    201   // LDR(literal) - pc relative load.
    202   explicit Address(int32_t offset) :
    203                rn_(PC), rm_(R0), offset_(offset),
    204                am_(Offset), is_immed_offset_(false), shift_(LSL) {
    205   }
    206 
    207   static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset);
    208   static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset);
    209 
    210   static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset);
    211   static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset);
    212 
    213   uint32_t encodingArm() const;
    214   uint32_t encodingThumb(bool is_32bit) const;
    215 
    216   uint32_t encoding3() const;
    217   uint32_t vencoding() const;
    218 
    219   uint32_t encodingThumbLdrdStrd() const;
    220 
    221   Register GetRegister() const {
    222     return rn_;
    223   }
    224 
    225   Register GetRegisterOffset() const {
    226     return rm_;
    227   }
    228 
    229   int32_t GetOffset() const {
    230     return offset_;
    231   }
    232 
    233   Mode GetMode() const {
    234     return am_;
    235   }
    236 
    237   bool IsImmediate() const {
    238     return is_immed_offset_;
    239   }
    240 
    241   Shift GetShift() const {
    242     return shift_;
    243   }
    244 
    245   int32_t GetShiftCount() const {
    246     CHECK(!is_immed_offset_);
    247     return offset_;
    248   }
    249 
    250  private:
    251   const Register rn_;
    252   const Register rm_;
    253   const int32_t offset_;      // Used as shift amount for register offset.
    254   const Mode am_;
    255   const bool is_immed_offset_;
    256   const Shift shift_;
    257 };
    258 inline std::ostream& operator<<(std::ostream& os, const Address::Mode& rhs) {
    259   os << static_cast<int>(rhs);
    260   return os;
    261 }
    262 
    263 // Instruction encoding bits.
    264 enum {
    265   H   = 1 << 5,   // halfword (or byte)
    266   L   = 1 << 20,  // load (or store)
    267   S   = 1 << 20,  // set condition code (or leave unchanged)
    268   W   = 1 << 21,  // writeback base register (or leave unchanged)
    269   A   = 1 << 21,  // accumulate in multiply instruction (or not)
    270   B   = 1 << 22,  // unsigned byte (or word)
    271   N   = 1 << 22,  // long (or short)
    272   U   = 1 << 23,  // positive (or negative) offset/index
    273   P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
    274   I   = 1 << 25,  // immediate shifter operand (or not)
    275 
    276   B0 = 1,
    277   B1 = 1 << 1,
    278   B2 = 1 << 2,
    279   B3 = 1 << 3,
    280   B4 = 1 << 4,
    281   B5 = 1 << 5,
    282   B6 = 1 << 6,
    283   B7 = 1 << 7,
    284   B8 = 1 << 8,
    285   B9 = 1 << 9,
    286   B10 = 1 << 10,
    287   B11 = 1 << 11,
    288   B12 = 1 << 12,
    289   B13 = 1 << 13,
    290   B14 = 1 << 14,
    291   B15 = 1 << 15,
    292   B16 = 1 << 16,
    293   B17 = 1 << 17,
    294   B18 = 1 << 18,
    295   B19 = 1 << 19,
    296   B20 = 1 << 20,
    297   B21 = 1 << 21,
    298   B22 = 1 << 22,
    299   B23 = 1 << 23,
    300   B24 = 1 << 24,
    301   B25 = 1 << 25,
    302   B26 = 1 << 26,
    303   B27 = 1 << 27,
    304   B28 = 1 << 28,
    305   B29 = 1 << 29,
    306   B30 = 1 << 30,
    307   B31 = 1 << 31,
    308 
    309   // Instruction bit masks.
    310   RdMask = 15 << 12,  // in str instruction
    311   CondMask = 15 << 28,
    312   CoprocessorMask = 15 << 8,
    313   OpCodeMask = 15 << 21,  // in data-processing instructions
    314   Imm24Mask = (1 << 24) - 1,
    315   Off12Mask = (1 << 12) - 1,
    316 
    317   // ldrex/strex register field encodings.
    318   kLdExRnShift = 16,
    319   kLdExRtShift = 12,
    320   kStrExRnShift = 16,
    321   kStrExRdShift = 12,
    322   kStrExRtShift = 0,
    323 };
    324 
    325 // IfThen state for IT instructions.
    326 enum ItState {
    327   kItOmitted,
    328   kItThen,
    329   kItT = kItThen,
    330   kItElse,
    331   kItE = kItElse
    332 };
    333 
    334 constexpr uint32_t kNoItCondition = 3;
    335 constexpr uint32_t kInvalidModifiedImmediate = -1;
    336 
    337 extern const char* kRegisterNames[];
    338 extern const char* kConditionNames[];
    339 
    340 // This is an abstract ARM assembler.  Subclasses provide assemblers for the individual
    341 // instruction sets (ARM32, Thumb2, etc.)
    342 //
    343 class ArmAssembler : public Assembler {
    344  public:
    345   virtual ~ArmAssembler() {}
    346 
    347   // Is this assembler for the thumb instruction set?
    348   virtual bool IsThumb() const = 0;
    349 
    350   // Data-processing instructions.
    351   virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    352 
    353   virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    354 
    355   virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    356   virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    357 
    358   virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    359   virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    360 
    361   virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    362 
    363   virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    364 
    365   virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    366 
    367   virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    368 
    369   virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    370 
    371   virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    372 
    373   virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    374 
    375   virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    376 
    377   virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    378 
    379   virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    380   virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    381 
    382   virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
    383   virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
    384 
    385   virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
    386 
    387   virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
    388   virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
    389 
    390   // Miscellaneous data-processing instructions.
    391   virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
    392   virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
    393   virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
    394 
    395   // Multiply instructions.
    396   virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
    397   virtual void mla(Register rd, Register rn, Register rm, Register ra,
    398                    Condition cond = AL) = 0;
    399   virtual void mls(Register rd, Register rn, Register rm, Register ra,
    400                    Condition cond = AL) = 0;
    401   virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
    402                      Condition cond = AL) = 0;
    403 
    404   virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
    405   virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
    406 
    407   // Bit field extract instructions.
    408   virtual void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
    409                     Condition cond = AL) = 0;
    410   virtual void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width,
    411                     Condition cond = AL) = 0;
    412 
    413   // Load/store instructions.
    414   virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0;
    415   virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0;
    416 
    417   virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0;
    418   virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0;
    419 
    420   virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0;
    421   virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0;
    422 
    423   virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0;
    424   virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0;
    425 
    426   virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0;
    427   virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0;
    428 
    429   virtual void ldm(BlockAddressMode am, Register base,
    430                    RegList regs, Condition cond = AL) = 0;
    431   virtual void stm(BlockAddressMode am, Register base,
    432                    RegList regs, Condition cond = AL) = 0;
    433 
    434   virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0;
    435   virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0;
    436   virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
    437   virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0;
    438 
    439   // Miscellaneous instructions.
    440   virtual void clrex(Condition cond = AL) = 0;
    441   virtual void nop(Condition cond = AL) = 0;
    442 
    443   // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
    444   virtual void bkpt(uint16_t imm16) = 0;
    445   virtual void svc(uint32_t imm24) = 0;
    446 
    447   virtual void it(Condition firstcond ATTRIBUTE_UNUSED,
    448                   ItState i1 ATTRIBUTE_UNUSED = kItOmitted,
    449                   ItState i2 ATTRIBUTE_UNUSED = kItOmitted,
    450                   ItState i3 ATTRIBUTE_UNUSED = kItOmitted) {
    451     // Ignored if not supported.
    452   }
    453 
    454   virtual void cbz(Register rn, Label* target) = 0;
    455   virtual void cbnz(Register rn, Label* target) = 0;
    456 
    457   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
    458   virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0;
    459   virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0;
    460   virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0;
    461   virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0;
    462   virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0;
    463   virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0;
    464   virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    465   virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
    466 
    467   // Returns false if the immediate cannot be encoded.
    468   virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0;
    469   virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0;
    470 
    471   virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
    472   virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0;
    473   virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
    474   virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0;
    475 
    476   virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
    477   virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
    478   virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
    479   virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
    480   virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
    481   virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
    482   virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
    483   virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
    484   virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
    485   virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
    486   virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0;
    487   virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0;
    488 
    489   virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    490   virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
    491   virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    492   virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
    493   virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    494   virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
    495 
    496   virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0;
    497   virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0;
    498   virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    499   virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0;
    500   virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    501   virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0;
    502   virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    503   virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0;
    504   virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    505   virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0;
    506 
    507   virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0;
    508   virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0;
    509   virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0;
    510   virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0;
    511   virtual void vmstat(Condition cond = AL) = 0;  // VMRS APSR_nzcv, FPSCR
    512 
    513   virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0;
    514   virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0;
    515   virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0;
    516   virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0;
    517 
    518   // Branch instructions.
    519   virtual void b(Label* label, Condition cond = AL) = 0;
    520   virtual void bl(Label* label, Condition cond = AL) = 0;
    521   virtual void blx(Register rm, Condition cond = AL) = 0;
    522   virtual void bx(Register rm, Condition cond = AL) = 0;
    523 
    524   // Memory barriers.
    525   virtual void dmb(DmbOptions flavor) = 0;
    526 
    527   void Pad(uint32_t bytes);
    528 
    529   // Macros.
    530   // Most of these are pure virtual as they need to be implemented per instruction set.
    531 
    532   // Add signed constant value to rd. May clobber IP.
    533   virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0;
    534   virtual void AddConstant(Register rd, Register rn, int32_t value,
    535                            Condition cond = AL) = 0;
    536   virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value,
    537                                    Condition cond = AL) = 0;
    538 
    539   // Load and Store. May clobber IP.
    540   virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0;
    541   void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {
    542     if (!vmovs(sd, value, cond)) {
    543       int32_t int_value = bit_cast<int32_t, float>(value);
    544       if (int_value == bit_cast<int32_t, float>(0.0f)) {
    545         // 0.0 is quite common, so we special case it by loading
    546         // 2.0 in `sd` and then substracting it.
    547         bool success = vmovs(sd, 2.0, cond);
    548         CHECK(success);
    549         vsubs(sd, sd, sd, cond);
    550       } else {
    551         LoadImmediate(IP, int_value, cond);
    552         vmovsr(sd, IP, cond);
    553       }
    554     }
    555   }
    556 
    557   void LoadDImmediate(DRegister sd, double value, Condition cond = AL) {
    558     if (!vmovd(sd, value, cond)) {
    559       uint64_t int_value = bit_cast<uint64_t, double>(value);
    560       if (int_value == bit_cast<uint64_t, double>(0.0)) {
    561         // 0.0 is quite common, so we special case it by loading
    562         // 2.0 in `sd` and then substracting it.
    563         bool success = vmovd(sd, 2.0, cond);
    564         CHECK(success);
    565         vsubd(sd, sd, sd, cond);
    566       } else {
    567         if (sd < 16) {
    568           SRegister low = static_cast<SRegister>(sd << 1);
    569           SRegister high = static_cast<SRegister>(low + 1);
    570           LoadSImmediate(low, bit_cast<float, uint32_t>(Low32Bits(int_value)), cond);
    571           if (High32Bits(int_value) == Low32Bits(int_value)) {
    572             vmovs(high, low);
    573           } else {
    574             LoadSImmediate(high, bit_cast<float, uint32_t>(High32Bits(int_value)), cond);
    575           }
    576         } else {
    577           LOG(FATAL) << "Unimplemented loading of double into a D register "
    578                      << "that cannot be split into two S registers";
    579         }
    580       }
    581     }
    582   }
    583 
    584   virtual void MarkExceptionHandler(Label* label) = 0;
    585   virtual void LoadFromOffset(LoadOperandType type,
    586                               Register reg,
    587                               Register base,
    588                               int32_t offset,
    589                               Condition cond = AL) = 0;
    590   virtual void StoreToOffset(StoreOperandType type,
    591                              Register reg,
    592                              Register base,
    593                              int32_t offset,
    594                              Condition cond = AL) = 0;
    595   virtual void LoadSFromOffset(SRegister reg,
    596                                Register base,
    597                                int32_t offset,
    598                                Condition cond = AL) = 0;
    599   virtual void StoreSToOffset(SRegister reg,
    600                               Register base,
    601                               int32_t offset,
    602                               Condition cond = AL) = 0;
    603   virtual void LoadDFromOffset(DRegister reg,
    604                                Register base,
    605                                int32_t offset,
    606                                Condition cond = AL) = 0;
    607   virtual void StoreDToOffset(DRegister reg,
    608                               Register base,
    609                               int32_t offset,
    610                               Condition cond = AL) = 0;
    611 
    612   virtual void Push(Register rd, Condition cond = AL) = 0;
    613   virtual void Pop(Register rd, Condition cond = AL) = 0;
    614 
    615   virtual void PushList(RegList regs, Condition cond = AL) = 0;
    616   virtual void PopList(RegList regs, Condition cond = AL) = 0;
    617 
    618   virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
    619 
    620   // Convenience shift instructions. Use mov instruction with shifter operand
    621   // for variants setting the status flags or using a register shift count.
    622   virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    623                    Condition cond = AL) = 0;
    624   virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    625                    Condition cond = AL) = 0;
    626   virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    627                    Condition cond = AL) = 0;
    628   virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    629                    Condition cond = AL) = 0;
    630   virtual void Rrx(Register rd, Register rm, bool setcc = false,
    631                    Condition cond = AL) = 0;
    632 
    633   virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
    634                    Condition cond = AL) = 0;
    635   virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
    636                    Condition cond = AL) = 0;
    637   virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
    638                    Condition cond = AL) = 0;
    639   virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
    640                    Condition cond = AL) = 0;
    641 
    642   // Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
    643   // `shifter_op` contains the operand.
    644   virtual bool ShifterOperandCanHold(Register rd,
    645                                      Register rn,
    646                                      Opcode opcode,
    647                                      uint32_t immediate,
    648                                      ShifterOperand* shifter_op) = 0;
    649 
    650   static bool IsInstructionForExceptionHandling(uintptr_t pc);
    651 
    652   virtual void Bind(Label* label) = 0;
    653 
    654   virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
    655   virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
    656 
    657   //
    658   // Overridden common assembler high-level functionality
    659   //
    660 
    661   // Emit code that will create an activation on the stack
    662   void BuildFrame(size_t frame_size, ManagedRegister method_reg,
    663                   const std::vector<ManagedRegister>& callee_save_regs,
    664                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
    665 
    666   // Emit code that will remove an activation from the stack
    667   void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
    668     OVERRIDE;
    669 
    670   void IncreaseFrameSize(size_t adjust) OVERRIDE;
    671   void DecreaseFrameSize(size_t adjust) OVERRIDE;
    672 
    673   // Store routines
    674   void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
    675   void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
    676   void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
    677 
    678   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
    679 
    680   void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
    681       OVERRIDE;
    682 
    683   void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
    684                                   ManagedRegister scratch) OVERRIDE;
    685 
    686   void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
    687 
    688   void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
    689                      ManagedRegister scratch) OVERRIDE;
    690 
    691   // Load routines
    692   void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
    693 
    694   void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
    695 
    696   void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
    697 
    698   void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
    699                bool poison_reference) OVERRIDE;
    700 
    701   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
    702 
    703   void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
    704 
    705   // Copying routines
    706   void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
    707 
    708   void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
    709                               ManagedRegister scratch) OVERRIDE;
    710 
    711   void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
    712       OVERRIDE;
    713 
    714   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
    715 
    716   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
    717 
    718   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
    719             size_t size) OVERRIDE;
    720 
    721   void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
    722             size_t size) OVERRIDE;
    723 
    724   void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
    725             size_t size) OVERRIDE;
    726 
    727   void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
    728             ManagedRegister scratch, size_t size) OVERRIDE;
    729 
    730   void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
    731             ManagedRegister scratch, size_t size) OVERRIDE;
    732 
    733   // Sign extension
    734   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
    735 
    736   // Zero extension
    737   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
    738 
    739   // Exploit fast access in managed code to Thread::Current()
    740   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
    741   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
    742 
    743   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
    744   // value is null and null_allowed. in_reg holds a possibly stale reference
    745   // that can be used to avoid loading the handle scope entry to see if the value is
    746   // null.
    747   void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
    748                               ManagedRegister in_reg, bool null_allowed) OVERRIDE;
    749 
    750   // Set up out_off to hold a Object** into the handle scope, or to be null if the
    751   // value is null and null_allowed.
    752   void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
    753                               ManagedRegister scratch, bool null_allowed) OVERRIDE;
    754 
    755   // src holds a handle scope entry (Object**) load this into dst
    756   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
    757 
    758   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
    759   // know that src may not be null.
    760   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
    761   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
    762 
    763   // Call to address held at [base+offset]
    764   void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
    765   void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
    766   void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
    767 
    768   // Generate code to check if Thread::Current()->exception_ is non-null
    769   // and branch to a ExceptionSlowPath if it is.
    770   void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
    771 
    772   static uint32_t ModifiedImmediate(uint32_t value);
    773 
    774   static bool IsLowRegister(Register r) {
    775     return r < R8;
    776   }
    777 
    778   static bool IsHighRegister(Register r) {
    779      return r >= R8;
    780   }
    781 
    782  protected:
    783   // Returns whether or not the given register is used for passing parameters.
    784   static int RegisterCompare(const Register* reg1, const Register* reg2) {
    785     return *reg1 - *reg2;
    786   }
    787 };
    788 
    789 // Slowpath entered when Thread::Current()->_exception is non-null
    790 class ArmExceptionSlowPath FINAL : public SlowPath {
    791  public:
    792   explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
    793       : scratch_(scratch), stack_adjust_(stack_adjust) {
    794   }
    795   void Emit(Assembler *sp_asm) OVERRIDE;
    796  private:
    797   const ArmManagedRegister scratch_;
    798   const size_t stack_adjust_;
    799 };
    800 
    801 }  // namespace arm
    802 }  // namespace art
    803 
    804 #endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
    805