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