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