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