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)
force_32bit_branches_(force_32bit_branches)35       : force_32bit_branches_(force_32bit_branches),
36         force_32bit_(false),
37         it_cond_index_(kNoItCondition),
38         next_condition_(AL) {
39   }
40 
~Thumb2Assembler()41   virtual ~Thumb2Assembler() {
42     for (auto& branch : branches_) {
43       delete branch;
44     }
45   }
46 
IsThumb()47   bool IsThumb() const OVERRIDE {
48     return true;
49   }
50 
IsForced32Bit()51   bool IsForced32Bit() const {
52     return force_32bit_;
53   }
54 
IsForced32BitBranches()55   bool IsForced32BitBranches() const {
56     return force_32bit_branches_;
57   }
58 
FinalizeInstructions(const MemoryRegion & region)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.
Force32Bit()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 
CheckCondition(Condition cond)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 
CheckConditionLastIt(Condition cond)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) :
assembler_(assembler)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.
Branch(const Thumb2Assembler * assembler,Type type,uint32_t location,Register rn)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) :
assembler_(assembler)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 
IsCompareAndBranch()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.
Resolve(uint32_t target)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.
Move(int32_t delta)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.
Relocate(uint32_t oldlocation,int32_t delta)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 
GetSize()580     Size GetSize() const {
581       return size_;
582     }
583 
GetType()584     Type GetType() const {
585       return type_;
586     }
587 
GetLocation()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>
ResetTypeAndCondition(Type type,Condition 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 
GetRegister()605     Register GetRegister() const {
606       return rn_;
607     }
608 
ResetSize(Size size)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.
CalculateSize()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.
AddBranch(Branch::Type type,uint32_t location,Register rn)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 
GetBranch(uint16_t branchid)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