Home | History | Annotate | Download | only in arm
      1 /*
      2  * Copyright (C) 2014 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_THUMB2_H_
     18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_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/arm/assembler_arm.h"
     26 #include "offsets.h"
     27 #include "utils.h"
     28 
     29 namespace art {
     30 namespace arm {
     31 
     32 class Thumb2Assembler FINAL : public ArmAssembler {
     33  public:
     34   explicit Thumb2Assembler(bool force_32bit_branches = false)
     35       : force_32bit_branches_(force_32bit_branches),
     36         force_32bit_(false),
     37         it_cond_index_(kNoItCondition),
     38         next_condition_(AL) {
     39   }
     40 
     41   virtual ~Thumb2Assembler() {
     42     for (auto& branch : branches_) {
     43       delete branch;
     44     }
     45   }
     46 
     47   bool IsThumb() const OVERRIDE {
     48     return true;
     49   }
     50 
     51   bool IsForced32Bit() const {
     52     return force_32bit_;
     53   }
     54 
     55   bool IsForced32BitBranches() const {
     56     return force_32bit_branches_;
     57   }
     58 
     59   void FinalizeInstructions(const MemoryRegion& region) OVERRIDE {
     60     EmitBranches();
     61     Assembler::FinalizeInstructions(region);
     62   }
     63 
     64   // Data-processing instructions.
     65   void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     66 
     67   void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     68 
     69   void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     70   void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     71 
     72   void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     73   void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     74 
     75   void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     76 
     77   void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     78 
     79   void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     80 
     81   void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     82 
     83   void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     84 
     85   void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     86 
     87   void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     88 
     89   void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     90 
     91   void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     92 
     93   void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     94   void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     95 
     96   void mov(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     97   void movs(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
     98 
     99   void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
    100 
    101   void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
    102   void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
    103 
    104   // Miscellaneous data-processing instructions.
    105   void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
    106   void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
    107   void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
    108 
    109   // Multiply instructions.
    110   void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
    111   void mla(Register rd, Register rn, Register rm, Register ra,
    112            Condition cond = AL) OVERRIDE;
    113   void mls(Register rd, Register rn, Register rm, Register ra,
    114            Condition cond = AL) OVERRIDE;
    115   void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
    116              Condition cond = AL) OVERRIDE;
    117 
    118   void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
    119   void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
    120 
    121   // Load/store instructions.
    122   void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    123   void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    124 
    125   void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    126   void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    127 
    128   void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    129   void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    130 
    131   void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    132   void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    133 
    134   void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    135   void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
    136 
    137   void ldm(BlockAddressMode am, Register base,
    138            RegList regs, Condition cond = AL) OVERRIDE;
    139   void stm(BlockAddressMode am, Register base,
    140            RegList regs, Condition cond = AL) OVERRIDE;
    141 
    142   void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE;
    143   void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE;
    144 
    145   void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL);
    146   void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL);
    147 
    148 
    149   // Miscellaneous instructions.
    150   void clrex(Condition cond = AL) OVERRIDE;
    151   void nop(Condition cond = AL) OVERRIDE;
    152 
    153   void bkpt(uint16_t imm16) OVERRIDE;
    154   void svc(uint32_t imm24) OVERRIDE;
    155 
    156   // If-then
    157   void it(Condition firstcond, ItState i1 = kItOmitted,
    158         ItState i2 = kItOmitted, ItState i3 = kItOmitted) OVERRIDE;
    159 
    160   void cbz(Register rn, Label* target) OVERRIDE;
    161   void cbnz(Register rn, Label* target) OVERRIDE;
    162 
    163   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
    164   void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE;
    165   void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE;
    166   void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
    167   void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE;
    168   void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
    169   void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE;
    170   void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    171   void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
    172 
    173   // Returns false if the immediate cannot be encoded.
    174   bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE;
    175   bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE;
    176 
    177   void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
    178   void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
    179   void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
    180   void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
    181 
    182   void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
    183   void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
    184   void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
    185   void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
    186   void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
    187   void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
    188   void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
    189   void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
    190   void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
    191   void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
    192   void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
    193   void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
    194 
    195   void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    196   void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
    197   void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    198   void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
    199   void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    200   void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
    201 
    202   void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
    203   void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
    204   void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    205   void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
    206   void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    207   void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
    208   void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    209   void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
    210   void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    211   void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
    212 
    213   void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
    214   void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
    215   void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE;
    216   void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE;
    217   void vmstat(Condition cond = AL) OVERRIDE;  // VMRS APSR_nzcv, FPSCR
    218 
    219   void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
    220   void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
    221   void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
    222   void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
    223 
    224   // Branch instructions.
    225   void b(Label* label, Condition cond = AL);
    226   void bl(Label* label, Condition cond = AL);
    227   void blx(Label* label);
    228   void blx(Register rm, Condition cond = AL) OVERRIDE;
    229   void bx(Register rm, Condition cond = AL) OVERRIDE;
    230 
    231   void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    232            Condition cond = AL) OVERRIDE;
    233   void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    234            Condition cond = AL) OVERRIDE;
    235   void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    236            Condition cond = AL) OVERRIDE;
    237   void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
    238            Condition cond = AL) OVERRIDE;
    239   void Rrx(Register rd, Register rm, bool setcc = false,
    240            Condition cond = AL) OVERRIDE;
    241 
    242   void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
    243            Condition cond = AL) OVERRIDE;
    244   void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
    245            Condition cond = AL) OVERRIDE;
    246   void Asr(Register rd, Register rm, Register rn, bool setcc = false,
    247            Condition cond = AL) OVERRIDE;
    248   void Ror(Register rd, Register rm, Register rn, bool setcc = false,
    249            Condition cond = AL) OVERRIDE;
    250 
    251   void Push(Register rd, Condition cond = AL) OVERRIDE;
    252   void Pop(Register rd, Condition cond = AL) OVERRIDE;
    253 
    254   void PushList(RegList regs, Condition cond = AL) OVERRIDE;
    255   void PopList(RegList regs, Condition cond = AL) OVERRIDE;
    256 
    257   void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE;
    258 
    259   void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE;
    260   void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE;
    261 
    262   // Macros.
    263   // Add signed constant value to rd. May clobber IP.
    264   void AddConstant(Register rd, int32_t value, Condition cond = AL) OVERRIDE;
    265   void AddConstant(Register rd, Register rn, int32_t value,
    266                    Condition cond = AL) OVERRIDE;
    267   void AddConstantSetFlags(Register rd, Register rn, int32_t value,
    268                            Condition cond = AL) OVERRIDE;
    269   void AddConstantWithCarry(Register rd, Register rn, int32_t value,
    270                             Condition cond = AL) {}
    271 
    272   // Load and Store. May clobber IP.
    273   void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE;
    274   void LoadSImmediate(SRegister sd, float value, Condition cond = AL) {}
    275   void LoadDImmediate(DRegister dd, double value,
    276                       Register scratch, Condition cond = AL) {}
    277   void MarkExceptionHandler(Label* label) OVERRIDE;
    278   void LoadFromOffset(LoadOperandType type,
    279                       Register reg,
    280                       Register base,
    281                       int32_t offset,
    282                       Condition cond = AL) OVERRIDE;
    283   void StoreToOffset(StoreOperandType type,
    284                      Register reg,
    285                      Register base,
    286                      int32_t offset,
    287                      Condition cond = AL) OVERRIDE;
    288   void LoadSFromOffset(SRegister reg,
    289                        Register base,
    290                        int32_t offset,
    291                        Condition cond = AL) OVERRIDE;
    292   void StoreSToOffset(SRegister reg,
    293                       Register base,
    294                       int32_t offset,
    295                       Condition cond = AL) OVERRIDE;
    296   void LoadDFromOffset(DRegister reg,
    297                        Register base,
    298                        int32_t offset,
    299                        Condition cond = AL) OVERRIDE;
    300   void StoreDToOffset(DRegister reg,
    301                       Register base,
    302                       int32_t offset,
    303                       Condition cond = AL) OVERRIDE;
    304 
    305 
    306   static bool IsInstructionForExceptionHandling(uword pc);
    307 
    308   // Emit data (e.g. encoded instruction or immediate) to the.
    309   // instruction stream.
    310   void Emit32(int32_t value);     // Emit a 32 bit instruction in thumb format.
    311   void Emit16(int16_t value);     // Emit a 16 bit instruction in little endian format.
    312   void Bind(Label* label) OVERRIDE;
    313 
    314   void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
    315 
    316   // Force the assembler to generate 32 bit instructions.
    317   void Force32Bit() {
    318     force_32bit_ = true;
    319   }
    320 
    321  private:
    322   // Emit a single 32 or 16 bit data processing instruction.
    323   void EmitDataProcessing(Condition cond,
    324                   Opcode opcode,
    325                   int set_cc,
    326                   Register rn,
    327                   Register rd,
    328                   const ShifterOperand& so);
    329 
    330   // Must the instruction be 32 bits or can it possibly be encoded
    331   // in 16 bits?
    332   bool Is32BitDataProcessing(Condition cond,
    333                   Opcode opcode,
    334                   int set_cc,
    335                   Register rn,
    336                   Register rd,
    337                   const ShifterOperand& so);
    338 
    339   // Emit a 32 bit data processing instruction.
    340   void Emit32BitDataProcessing(Condition cond,
    341                   Opcode opcode,
    342                   int set_cc,
    343                   Register rn,
    344                   Register rd,
    345                   const ShifterOperand& so);
    346 
    347   // Emit a 16 bit data processing instruction.
    348   void Emit16BitDataProcessing(Condition cond,
    349                   Opcode opcode,
    350                   int set_cc,
    351                   Register rn,
    352                   Register rd,
    353                   const ShifterOperand& so);
    354 
    355   void Emit16BitAddSub(Condition cond,
    356                        Opcode opcode,
    357                        int set_cc,
    358                        Register rn,
    359                        Register rd,
    360                        const ShifterOperand& so);
    361 
    362   uint16_t EmitCompareAndBranch(Register rn, uint16_t prev, bool n);
    363 
    364   void EmitLoadStore(Condition cond,
    365                  bool load,
    366                  bool byte,
    367                  bool half,
    368                  bool is_signed,
    369                  Register rd,
    370                  const Address& ad);
    371 
    372   void EmitMemOpAddressMode3(Condition cond,
    373                              int32_t mode,
    374                              Register rd,
    375                              const Address& ad);
    376 
    377   void EmitMultiMemOp(Condition cond,
    378                       BlockAddressMode am,
    379                       bool load,
    380                       Register base,
    381                       RegList regs);
    382 
    383   void EmitMulOp(Condition cond,
    384                  int32_t opcode,
    385                  Register rd,
    386                  Register rn,
    387                  Register rm,
    388                  Register rs);
    389 
    390   void EmitVFPsss(Condition cond,
    391                   int32_t opcode,
    392                   SRegister sd,
    393                   SRegister sn,
    394                   SRegister sm);
    395 
    396   void EmitVFPddd(Condition cond,
    397                   int32_t opcode,
    398                   DRegister dd,
    399                   DRegister dn,
    400                   DRegister dm);
    401 
    402   void EmitVFPsd(Condition cond,
    403                  int32_t opcode,
    404                  SRegister sd,
    405                  DRegister dm);
    406 
    407   void EmitVFPds(Condition cond,
    408                  int32_t opcode,
    409                  DRegister dd,
    410                  SRegister sm);
    411 
    412   void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond);
    413 
    414   void EmitBranch(Condition cond, Label* label, bool link, bool x);
    415   static int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
    416   static int DecodeBranchOffset(int32_t inst);
    417   int32_t EncodeTstOffset(int offset, int32_t inst);
    418   int DecodeTstOffset(int32_t inst);
    419   void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false);
    420   void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false);
    421 
    422   bool force_32bit_branches_;  // Force the assembler to use 32 bit branch instructions.
    423   bool force_32bit_;           // Force the assembler to use 32 bit thumb2 instructions.
    424 
    425   // IfThen conditions.  Used to check that conditional instructions match the preceding IT.
    426   Condition it_conditions_[4];
    427   uint8_t it_cond_index_;
    428   Condition next_condition_;
    429 
    430   void SetItCondition(ItState s, Condition cond, uint8_t index);
    431 
    432   void CheckCondition(Condition cond) {
    433     CHECK_EQ(cond, next_condition_);
    434 
    435     // Move to the next condition if there is one.
    436     if (it_cond_index_ < 3) {
    437       ++it_cond_index_;
    438       next_condition_ = it_conditions_[it_cond_index_];
    439     } else {
    440       next_condition_ = AL;
    441     }
    442   }
    443 
    444   void CheckConditionLastIt(Condition cond) {
    445     if (it_cond_index_ < 3) {
    446       // Check that the next condition is AL.  This means that the
    447       // current condition is the last in the IT block.
    448       CHECK_EQ(it_conditions_[it_cond_index_ + 1], AL);
    449     }
    450     CheckCondition(cond);
    451   }
    452 
    453   // Branches.
    454   //
    455   // The thumb2 architecture allows branches to be either 16 or 32 bit instructions.  This
    456   // depends on both the type of branch and the offset to which it is branching.  When
    457   // generating code for branches we don't know the size before hand (if the branch is
    458   // going forward, because we haven't seen the target address yet), so we need to assume
    459   // that it is going to be one of 16 or 32 bits.  When we know the target (the label is 'bound')
    460   // we can determine the actual size of the branch.  However, if we had guessed wrong before
    461   // we knew the target there will be no room in the instruction sequence for the new
    462   // instruction (assume that we never decrease the size of a branch).
    463   //
    464   // To handle this, we keep a record of every branch in the program.  The actual instruction
    465   // encoding for these is delayed until we know the final size of every branch.  When we
    466   // bind a label to a branch (we then know the target address) we determine if the branch
    467   // has changed size.  If it has we need to move all the instructions in the buffer after
    468   // the branch point forward by the change in size of the branch.  This will create a gap
    469   // in the code big enough for the new branch encoding.  However, since we have moved
    470   // a chunk of code we need to relocate the branches in that code to their new address.
    471   //
    472   // Creating a hole in the code for the new branch encoding might cause another branch that was
    473   // 16 bits to become 32 bits, so we need to find this in another pass.
    474   //
    475   // We also need to deal with a cbz/cbnz instruction that becomes too big for its offset
    476   // range.  We do this by converting it to two instructions:
    477   //     cmp Rn, #0
    478   //     b<cond> target
    479   // But we also need to handle the case where the conditional branch is out of range and
    480   // becomes a 32 bit conditional branch.
    481   //
    482   // All branches have a 'branch id' which is a 16 bit unsigned number used to identify
    483   // the branch.  Unresolved labels use the branch id to link to the next unresolved branch.
    484 
    485   class Branch {
    486    public:
    487     // Branch type.
    488     enum Type {
    489       kUnconditional,             // B.
    490       kConditional,               // B<cond>.
    491       kCompareAndBranchZero,      // cbz.
    492       kCompareAndBranchNonZero,   // cbnz.
    493       kUnconditionalLink,         // BL.
    494       kUnconditionalLinkX,        // BLX.
    495       kUnconditionalX             // BX.
    496     };
    497 
    498     // Calculated size of branch instruction based on type and offset.
    499     enum Size {
    500       k16Bit,
    501       k32Bit
    502     };
    503 
    504     // Unresolved branch possibly with a condition.
    505     Branch(const Thumb2Assembler* assembler, Type type, uint32_t location, Condition cond = AL) :
    506         assembler_(assembler), type_(type), location_(location),
    507         target_(kUnresolved),
    508         cond_(cond), rn_(R0) {
    509       CHECK(!IsCompareAndBranch());
    510       size_ = CalculateSize();
    511     }
    512 
    513     // Unresolved compare-and-branch instruction with a register.
    514     Branch(const Thumb2Assembler* assembler, Type type, uint32_t location, Register rn) :
    515         assembler_(assembler), type_(type), location_(location),
    516         target_(kUnresolved), cond_(AL), rn_(rn) {
    517       CHECK(IsCompareAndBranch());
    518       size_ = CalculateSize();
    519     }
    520 
    521     // Resolved branch (can't be compare-and-branch) with a target and possibly a condition.
    522     Branch(const Thumb2Assembler* assembler, Type type, uint32_t location, uint32_t target,
    523            Condition cond = AL) :
    524            assembler_(assembler), type_(type), location_(location),
    525            target_(target), cond_(cond), rn_(R0) {
    526       CHECK(!IsCompareAndBranch());
    527       // Resolved branch.
    528       size_ = CalculateSize();
    529     }
    530 
    531     bool IsCompareAndBranch() const {
    532       return type_ == kCompareAndBranchNonZero || type_ == kCompareAndBranchZero;
    533     }
    534 
    535     // Resolve a branch when the target is known.  If this causes the
    536     // size of the branch to change return true.  Otherwise return false.
    537     bool Resolve(uint32_t target) {
    538       target_ = target;
    539       Size newsize = CalculateSize();
    540       if (size_ != newsize) {
    541         size_ = newsize;
    542         return true;
    543       }
    544       return false;
    545     }
    546 
    547     // Move a cbz/cbnz branch.  This is always forward.
    548     void Move(int32_t delta) {
    549       CHECK(IsCompareAndBranch());
    550       CHECK_GT(delta, 0);
    551       location_ += delta;
    552       target_ += delta;
    553     }
    554 
    555     // Relocate a branch by a given delta.  This changed the location and
    556     // target if they need to be changed.  It also recalculates the
    557     // size of the branch instruction.  It returns true if the branch
    558     // has changed size.
    559     bool Relocate(uint32_t oldlocation, int32_t delta) {
    560       if (location_ > oldlocation) {
    561         location_ += delta;
    562       }
    563       if (target_ != kUnresolved) {
    564         if (target_ > oldlocation) {
    565           target_ += delta;
    566         }
    567       } else {
    568         return false;       // Don't know the size yet.
    569       }
    570 
    571       // Calculate the new size.
    572       Size newsize = CalculateSize();
    573       if (size_ != newsize) {
    574         size_ = newsize;
    575         return true;
    576       }
    577       return false;
    578     }
    579 
    580     Size GetSize() const {
    581       return size_;
    582     }
    583 
    584     Type GetType() const {
    585       return type_;
    586     }
    587 
    588     uint32_t GetLocation() const {
    589       return location_;
    590     }
    591 
    592     // Emit the branch instruction into the assembler buffer.  This does the
    593     // encoding into the thumb instruction.
    594     void Emit(AssemblerBuffer* buffer) const;
    595 
    596     // Reset the type and condition to those given.  This used for
    597     // cbz/cbnz instructions when they are converted to cmp/b<cond>
    598     void ResetTypeAndCondition(Type type, Condition cond) {
    599       CHECK(IsCompareAndBranch());
    600       CHECK(cond == EQ || cond == NE);
    601       type_ = type;
    602       cond_ = cond;
    603     }
    604 
    605     Register GetRegister() const {
    606       return rn_;
    607     }
    608 
    609     void ResetSize(Size size) {
    610       size_ = size;
    611     }
    612 
    613    private:
    614     // Calculate the size of the branch instruction based on its type and offset.
    615     Size CalculateSize() const {
    616       if (assembler_->IsForced32BitBranches()) {
    617         return k32Bit;
    618       }
    619       if (target_ == kUnresolved) {
    620         if (assembler_->IsForced32Bit() && (type_ == kUnconditional || type_ == kConditional)) {
    621           return k32Bit;
    622         }
    623         return k16Bit;
    624       }
    625       int32_t delta = target_ - location_ - 4;
    626       if (delta < 0) {
    627         delta = -delta;
    628       }
    629       switch (type_) {
    630         case kUnconditional:
    631           if (assembler_->IsForced32Bit() || delta >= (1 << 11)) {
    632             return k32Bit;
    633           } else {
    634             return k16Bit;
    635           }
    636         case kConditional:
    637           if (assembler_->IsForced32Bit() || delta >= (1 << 8)) {
    638             return k32Bit;
    639           } else {
    640             return k16Bit;
    641           }
    642         case kCompareAndBranchZero:
    643         case kCompareAndBranchNonZero:
    644           if (delta >= (1 << 7)) {
    645             return k32Bit;      // Will cause this branch to become invalid.
    646           }
    647           return k16Bit;
    648 
    649         case kUnconditionalX:
    650         case kUnconditionalLinkX:
    651           return k16Bit;
    652         case kUnconditionalLink:
    653           return k32Bit;
    654       }
    655       LOG(FATAL) << "Cannot reach";
    656       return k16Bit;
    657     }
    658 
    659     static constexpr uint32_t kUnresolved = 0xffffffff;     // Value for target_ for unresolved.
    660     const Thumb2Assembler* assembler_;
    661     Type type_;
    662     uint32_t location_;     // Offset into assembler buffer in bytes.
    663     uint32_t target_;       // Offset into assembler buffer in bytes.
    664     Size size_;
    665     Condition cond_;
    666     const Register rn_;
    667   };
    668 
    669   std::vector<Branch*> branches_;
    670 
    671   // Add a resolved branch and return its size.
    672   Branch::Size AddBranch(Branch::Type type, uint32_t location, uint32_t target,
    673                          Condition cond = AL) {
    674     branches_.push_back(new Branch(this, type, location, target, cond));
    675     return branches_[branches_.size()-1]->GetSize();
    676   }
    677 
    678   // Add a compare and branch (with a register) and return its id.
    679   uint16_t AddBranch(Branch::Type type, uint32_t location, Register rn) {
    680     branches_.push_back(new Branch(this, type, location, rn));
    681     return branches_.size() - 1;
    682   }
    683 
    684   // Add an unresolved branch and return its id.
    685   uint16_t AddBranch(Branch::Type type, uint32_t location, Condition cond = AL) {
    686     branches_.push_back(new Branch(this, type, location, cond));
    687     return branches_.size() - 1;
    688   }
    689 
    690   Branch* GetBranch(uint16_t branchid) {
    691     if (branchid >= branches_.size()) {
    692       return nullptr;
    693     }
    694     return branches_[branchid];
    695   }
    696 
    697   void EmitBranches();
    698   void MakeHoleForBranch(uint32_t location, uint32_t size);
    699 };
    700 
    701 }  // namespace arm
    702 }  // namespace art
    703 
    704 #endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_
    705