assembler_thumb2.h revision 169277a12ed857d0d8ba1b808e0e7e414a5d0f95
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
29namespace art {
30namespace arm {
31
32class 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