• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
19 
20 #include <vector>
21 
22 #include "base/logging.h"
23 #include "constants_arm.h"
24 #include "utils/arm/managed_register_arm.h"
25 #include "utils/assembler.h"
26 #include "offsets.h"
27 #include "utils.h"
28 
29 namespace art {
30 namespace arm {
31 
32 // Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1.
33 class ShifterOperand {
34  public:
35   // Data-processing operands - Uninitialized
ShifterOperand()36   ShifterOperand() {
37     type_ = -1;
38   }
39 
40   // Data-processing operands - Immediate
ShifterOperand(uint32_t immediate)41   explicit ShifterOperand(uint32_t immediate) {
42     CHECK(immediate < (1 << kImmed8Bits));
43     type_ = 1;
44     encoding_ = immediate;
45   }
46 
47   // Data-processing operands - Rotated immediate
ShifterOperand(uint32_t rotate,uint32_t immed8)48   ShifterOperand(uint32_t rotate, uint32_t immed8) {
49     CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
50     type_ = 1;
51     encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
52   }
53 
54   // Data-processing operands - Register
ShifterOperand(Register rm)55   explicit ShifterOperand(Register rm) {
56     type_ = 0;
57     encoding_ = static_cast<uint32_t>(rm);
58   }
59 
60   // Data-processing operands - Logical shift/rotate by immediate
ShifterOperand(Register rm,Shift shift,uint32_t shift_imm)61   ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
62     CHECK(shift_imm < (1 << kShiftImmBits));
63     type_ = 0;
64     encoding_ = shift_imm << kShiftImmShift |
65                 static_cast<uint32_t>(shift) << kShiftShift |
66                 static_cast<uint32_t>(rm);
67   }
68 
69   // Data-processing operands - Logical shift/rotate by register
ShifterOperand(Register rm,Shift shift,Register rs)70   ShifterOperand(Register rm, Shift shift, Register rs) {
71     type_ = 0;
72     encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
73                 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
74                 static_cast<uint32_t>(rm);
75   }
76 
CanHold(uint32_t immediate,ShifterOperand * shifter_op)77   static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
78     // Avoid the more expensive test for frequent small immediate values.
79     if (immediate < (1 << kImmed8Bits)) {
80       shifter_op->type_ = 1;
81       shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
82       return true;
83     }
84     // Note that immediate must be unsigned for the test to work correctly.
85     for (int rot = 0; rot < 16; rot++) {
86       uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
87       if (imm8 < (1 << kImmed8Bits)) {
88         shifter_op->type_ = 1;
89         shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
90         return true;
91       }
92     }
93     return false;
94   }
95 
96  private:
is_valid()97   bool is_valid() const { return (type_ == 0) || (type_ == 1); }
98 
type()99   uint32_t type() const {
100     CHECK(is_valid());
101     return type_;
102   }
103 
encoding()104   uint32_t encoding() const {
105     CHECK(is_valid());
106     return encoding_;
107   }
108 
109   uint32_t type_;  // Encodes the type field (bits 27-25) in the instruction.
110   uint32_t encoding_;
111 
112   friend class ArmAssembler;
113 #ifdef SOURCE_ASSEMBLER_SUPPORT
114   friend class BinaryAssembler;
115 #endif
116 };
117 
118 
119 enum LoadOperandType {
120   kLoadSignedByte,
121   kLoadUnsignedByte,
122   kLoadSignedHalfword,
123   kLoadUnsignedHalfword,
124   kLoadWord,
125   kLoadWordPair,
126   kLoadSWord,
127   kLoadDWord
128 };
129 
130 
131 enum StoreOperandType {
132   kStoreByte,
133   kStoreHalfword,
134   kStoreWord,
135   kStoreWordPair,
136   kStoreSWord,
137   kStoreDWord
138 };
139 
140 
141 // Load/store multiple addressing mode.
142 enum BlockAddressMode {
143   // bit encoding P U W
144   DA           = (0|0|0) << 21,  // decrement after
145   IA           = (0|4|0) << 21,  // increment after
146   DB           = (8|0|0) << 21,  // decrement before
147   IB           = (8|4|0) << 21,  // increment before
148   DA_W         = (0|0|1) << 21,  // decrement after with writeback to base
149   IA_W         = (0|4|1) << 21,  // increment after with writeback to base
150   DB_W         = (8|0|1) << 21,  // decrement before with writeback to base
151   IB_W         = (8|4|1) << 21   // increment before with writeback to base
152 };
153 
154 
155 class Address {
156  public:
157   // Memory operand addressing mode
158   enum Mode {
159     // bit encoding P U W
160     Offset       = (8|4|0) << 21,  // offset (w/o writeback to base)
161     PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
162     PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
163     NegOffset    = (8|0|0) << 21,  // negative offset (w/o writeback to base)
164     NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
165     NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
166   };
167 
168   explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
169     CHECK(IsAbsoluteUint(12, offset));
170     if (offset < 0) {
171       encoding_ = (am ^ (1 << kUShift)) | -offset;  // Flip U to adjust sign.
172     } else {
173       encoding_ = am | offset;
174     }
175     encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
176   }
177 
178   static bool CanHoldLoadOffset(LoadOperandType type, int offset);
179   static bool CanHoldStoreOffset(StoreOperandType type, int offset);
180 
181  private:
encoding()182   uint32_t encoding() const { return encoding_; }
183 
184   // Encoding for addressing mode 3.
encoding3()185   uint32_t encoding3() const {
186     const uint32_t offset_mask = (1 << 12) - 1;
187     uint32_t offset = encoding_ & offset_mask;
188     CHECK_LT(offset, 256u);
189     return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
190   }
191 
192   // Encoding for vfp load/store addressing.
vencoding()193   uint32_t vencoding() const {
194     const uint32_t offset_mask = (1 << 12) - 1;
195     uint32_t offset = encoding_ & offset_mask;
196     CHECK(IsAbsoluteUint(10, offset));  // In the range -1020 to +1020.
197     CHECK_ALIGNED(offset, 2);  // Multiple of 4.
198     int mode = encoding_ & ((8|4|1) << 21);
199     CHECK((mode == Offset) || (mode == NegOffset));
200     uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
201     if (mode == Offset) {
202       vencoding |= 1 << 23;
203     }
204     return vencoding;
205   }
206 
207   uint32_t encoding_;
208 
209   friend class ArmAssembler;
210 };
211 
212 
213 class ArmAssembler : public Assembler {
214  public:
ArmAssembler()215   ArmAssembler() {}
~ArmAssembler()216   virtual ~ArmAssembler() {}
217 
218   // Data-processing instructions.
219   void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
220 
221   void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
222 
223   void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
224   void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
225 
226   void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
227   void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
228 
229   void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
230 
231   void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
232 
233   void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
234 
235   void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
236 
237   void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
238 
239   void tst(Register rn, ShifterOperand so, Condition cond = AL);
240 
241   void teq(Register rn, ShifterOperand so, Condition cond = AL);
242 
243   void cmp(Register rn, ShifterOperand so, Condition cond = AL);
244 
245   void cmn(Register rn, ShifterOperand so, Condition cond = AL);
246 
247   void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
248   void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
249 
250   void mov(Register rd, ShifterOperand so, Condition cond = AL);
251   void movs(Register rd, ShifterOperand so, Condition cond = AL);
252 
253   void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
254 
255   void mvn(Register rd, ShifterOperand so, Condition cond = AL);
256   void mvns(Register rd, ShifterOperand so, Condition cond = AL);
257 
258   // Miscellaneous data-processing instructions.
259   void clz(Register rd, Register rm, Condition cond = AL);
260   void movw(Register rd, uint16_t imm16, Condition cond = AL);
261   void movt(Register rd, uint16_t imm16, Condition cond = AL);
262 
263   // Multiply instructions.
264   void mul(Register rd, Register rn, Register rm, Condition cond = AL);
265   void mla(Register rd, Register rn, Register rm, Register ra,
266            Condition cond = AL);
267   void mls(Register rd, Register rn, Register rm, Register ra,
268            Condition cond = AL);
269   void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
270              Condition cond = AL);
271 
272   // Load/store instructions.
273   void ldr(Register rd, Address ad, Condition cond = AL);
274   void str(Register rd, Address ad, Condition cond = AL);
275 
276   void ldrb(Register rd, Address ad, Condition cond = AL);
277   void strb(Register rd, Address ad, Condition cond = AL);
278 
279   void ldrh(Register rd, Address ad, Condition cond = AL);
280   void strh(Register rd, Address ad, Condition cond = AL);
281 
282   void ldrsb(Register rd, Address ad, Condition cond = AL);
283   void ldrsh(Register rd, Address ad, Condition cond = AL);
284 
285   void ldrd(Register rd, Address ad, Condition cond = AL);
286   void strd(Register rd, Address ad, Condition cond = AL);
287 
288   void ldm(BlockAddressMode am, Register base,
289            RegList regs, Condition cond = AL);
290   void stm(BlockAddressMode am, Register base,
291            RegList regs, Condition cond = AL);
292 
293   void ldrex(Register rd, Register rn, Condition cond = AL);
294   void strex(Register rd, Register rt, Register rn, Condition cond = AL);
295 
296   // Miscellaneous instructions.
297   void clrex();
298   void nop(Condition cond = AL);
299 
300   // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
301   void bkpt(uint16_t imm16);
302   void svc(uint32_t imm24);
303 
304   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
305   void vmovsr(SRegister sn, Register rt, Condition cond = AL);
306   void vmovrs(Register rt, SRegister sn, Condition cond = AL);
307   void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
308   void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
309   void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
310   void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
311   void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
312   void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
313 
314   // Returns false if the immediate cannot be encoded.
315   bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
316   bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
317 
318   void vldrs(SRegister sd, Address ad, Condition cond = AL);
319   void vstrs(SRegister sd, Address ad, Condition cond = AL);
320   void vldrd(DRegister dd, Address ad, Condition cond = AL);
321   void vstrd(DRegister dd, Address ad, Condition cond = AL);
322 
323   void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
324   void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
325   void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
326   void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
327   void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
328   void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
329   void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
330   void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
331   void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
332   void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
333   void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
334   void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
335 
336   void vabss(SRegister sd, SRegister sm, Condition cond = AL);
337   void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
338   void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
339   void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
340   void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
341   void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
342 
343   void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
344   void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
345   void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
346   void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
347   void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
348   void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
349   void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
350   void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
351   void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
352   void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
353 
354   void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
355   void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
356   void vcmpsz(SRegister sd, Condition cond = AL);
357   void vcmpdz(DRegister dd, Condition cond = AL);
358   void vmstat(Condition cond = AL);  // VMRS APSR_nzcv, FPSCR
359 
360   // Branch instructions.
361   void b(Label* label, Condition cond = AL);
362   void bl(Label* label, Condition cond = AL);
363   void blx(Register rm, Condition cond = AL);
364   void bx(Register rm, Condition cond = AL);
365 
366   // Macros.
367   // Add signed constant value to rd. May clobber IP.
368   void AddConstant(Register rd, int32_t value, Condition cond = AL);
369   void AddConstant(Register rd, Register rn, int32_t value,
370                    Condition cond = AL);
371   void AddConstantSetFlags(Register rd, Register rn, int32_t value,
372                            Condition cond = AL);
373   void AddConstantWithCarry(Register rd, Register rn, int32_t value,
374                             Condition cond = AL);
375 
376   // Load and Store. May clobber IP.
377   void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
378   void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
379   void LoadDImmediate(DRegister dd, double value,
380                       Register scratch, Condition cond = AL);
381   void MarkExceptionHandler(Label* label);
382   void LoadFromOffset(LoadOperandType type,
383                       Register reg,
384                       Register base,
385                       int32_t offset,
386                       Condition cond = AL);
387   void StoreToOffset(StoreOperandType type,
388                      Register reg,
389                      Register base,
390                      int32_t offset,
391                      Condition cond = AL);
392   void LoadSFromOffset(SRegister reg,
393                        Register base,
394                        int32_t offset,
395                        Condition cond = AL);
396   void StoreSToOffset(SRegister reg,
397                       Register base,
398                       int32_t offset,
399                       Condition cond = AL);
400   void LoadDFromOffset(DRegister reg,
401                        Register base,
402                        int32_t offset,
403                        Condition cond = AL);
404   void StoreDToOffset(DRegister reg,
405                       Register base,
406                       int32_t offset,
407                       Condition cond = AL);
408 
409   void Push(Register rd, Condition cond = AL);
410   void Pop(Register rd, Condition cond = AL);
411 
412   void PushList(RegList regs, Condition cond = AL);
413   void PopList(RegList regs, Condition cond = AL);
414 
415   void Mov(Register rd, Register rm, Condition cond = AL);
416 
417   // Convenience shift instructions. Use mov instruction with shifter operand
418   // for variants setting the status flags or using a register shift count.
419   void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
420   void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
421   void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
422   void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
423   void Rrx(Register rd, Register rm, Condition cond = AL);
424 
425   // Encode a signed constant in tst instructions, only affecting the flags.
426   void EncodeUint32InTstInstructions(uint32_t data);
427   // ... and decode from a pc pointing to the start of encoding instructions.
428   static uint32_t DecodeUint32FromTstInstructions(uword pc);
429   static bool IsInstructionForExceptionHandling(uword pc);
430 
431   // Emit data (e.g. encoded instruction or immediate) to the
432   // instruction stream.
433   void Emit(int32_t value);
434   void Bind(Label* label);
435 
436   //
437   // Overridden common assembler high-level functionality
438   //
439 
440   // Emit code that will create an activation on the stack
441   virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
442                           const std::vector<ManagedRegister>& callee_save_regs,
443                           const std::vector<ManagedRegister>& entry_spills);
444 
445   // Emit code that will remove an activation from the stack
446   virtual void RemoveFrame(size_t frame_size,
447                            const std::vector<ManagedRegister>& callee_save_regs);
448 
449   virtual void IncreaseFrameSize(size_t adjust);
450   virtual void DecreaseFrameSize(size_t adjust);
451 
452   // Store routines
453   virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
454   virtual void StoreRef(FrameOffset dest, ManagedRegister src);
455   virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
456 
457   virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
458                                      ManagedRegister scratch);
459 
460   virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
461                                       ManagedRegister scratch);
462 
463   virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
464                                         FrameOffset fr_offs,
465                                         ManagedRegister scratch);
466 
467   virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
468 
469   virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
470                              FrameOffset in_off, ManagedRegister scratch);
471 
472   // Load routines
473   virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
474 
475   virtual void Load(ManagedRegister dest, ThreadOffset src, size_t size);
476 
477   virtual void LoadRef(ManagedRegister dest, FrameOffset  src);
478 
479   virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
480                        MemberOffset offs);
481 
482   virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
483                           Offset offs);
484 
485   virtual void LoadRawPtrFromThread(ManagedRegister dest,
486                                     ThreadOffset offs);
487 
488   // Copying routines
489   virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size);
490 
491   virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
492                                     ManagedRegister scratch);
493 
494   virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
495                                   ManagedRegister scratch);
496 
497   virtual void CopyRef(FrameOffset dest, FrameOffset src,
498                        ManagedRegister scratch);
499 
500   virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size);
501 
502   virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
503                     ManagedRegister scratch, size_t size);
504 
505   virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
506                     ManagedRegister scratch, size_t size);
507 
508   virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
509                     ManagedRegister scratch, size_t size);
510 
511   virtual void Copy(ManagedRegister dest, Offset dest_offset,
512                     ManagedRegister src, Offset src_offset,
513                     ManagedRegister scratch, size_t size);
514 
515   virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
516                     ManagedRegister scratch, size_t size);
517 
518   virtual void MemoryBarrier(ManagedRegister scratch);
519 
520   // Sign extension
521   virtual void SignExtend(ManagedRegister mreg, size_t size);
522 
523   // Zero extension
524   virtual void ZeroExtend(ManagedRegister mreg, size_t size);
525 
526   // Exploit fast access in managed code to Thread::Current()
527   virtual void GetCurrentThread(ManagedRegister tr);
528   virtual void GetCurrentThread(FrameOffset dest_offset,
529                                 ManagedRegister scratch);
530 
531   // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
532   // value is null and null_allowed. in_reg holds a possibly stale reference
533   // that can be used to avoid loading the SIRT entry to see if the value is
534   // NULL.
535   virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
536                                ManagedRegister in_reg, bool null_allowed);
537 
538   // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
539   // value is null and null_allowed.
540   virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
541                                ManagedRegister scratch, bool null_allowed);
542 
543   // src holds a SIRT entry (Object**) load this into dst
544   virtual void LoadReferenceFromSirt(ManagedRegister dst,
545                                      ManagedRegister src);
546 
547   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
548   // know that src may not be null.
549   virtual void VerifyObject(ManagedRegister src, bool could_be_null);
550   virtual void VerifyObject(FrameOffset src, bool could_be_null);
551 
552   // Call to address held at [base+offset]
553   virtual void Call(ManagedRegister base, Offset offset,
554                     ManagedRegister scratch);
555   virtual void Call(FrameOffset base, Offset offset,
556                     ManagedRegister scratch);
557   virtual void Call(ThreadOffset offset, ManagedRegister scratch);
558 
559   // Generate code to check if Thread::Current()->exception_ is non-null
560   // and branch to a ExceptionSlowPath if it is.
561   virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust);
562 
563  private:
564   void EmitType01(Condition cond,
565                   int type,
566                   Opcode opcode,
567                   int set_cc,
568                   Register rn,
569                   Register rd,
570                   ShifterOperand so);
571 
572   void EmitType5(Condition cond, int offset, bool link);
573 
574   void EmitMemOp(Condition cond,
575                  bool load,
576                  bool byte,
577                  Register rd,
578                  Address ad);
579 
580   void EmitMemOpAddressMode3(Condition cond,
581                              int32_t mode,
582                              Register rd,
583                              Address ad);
584 
585   void EmitMultiMemOp(Condition cond,
586                       BlockAddressMode am,
587                       bool load,
588                       Register base,
589                       RegList regs);
590 
591   void EmitShiftImmediate(Condition cond,
592                           Shift opcode,
593                           Register rd,
594                           Register rm,
595                           ShifterOperand so);
596 
597   void EmitShiftRegister(Condition cond,
598                          Shift opcode,
599                          Register rd,
600                          Register rm,
601                          ShifterOperand so);
602 
603   void EmitMulOp(Condition cond,
604                  int32_t opcode,
605                  Register rd,
606                  Register rn,
607                  Register rm,
608                  Register rs);
609 
610   void EmitVFPsss(Condition cond,
611                   int32_t opcode,
612                   SRegister sd,
613                   SRegister sn,
614                   SRegister sm);
615 
616   void EmitVFPddd(Condition cond,
617                   int32_t opcode,
618                   DRegister dd,
619                   DRegister dn,
620                   DRegister dm);
621 
622   void EmitVFPsd(Condition cond,
623                  int32_t opcode,
624                  SRegister sd,
625                  DRegister dm);
626 
627   void EmitVFPds(Condition cond,
628                  int32_t opcode,
629                  DRegister dd,
630                  SRegister sm);
631 
632   void EmitBranch(Condition cond, Label* label, bool link);
633   static int32_t EncodeBranchOffset(int offset, int32_t inst);
634   static int DecodeBranchOffset(int32_t inst);
635   int32_t EncodeTstOffset(int offset, int32_t inst);
636   int DecodeTstOffset(int32_t inst);
637 
638   // Returns whether or not the given register is used for passing parameters.
RegisterCompare(const Register * reg1,const Register * reg2)639   static int RegisterCompare(const Register* reg1, const Register* reg2) {
640     return *reg1 - *reg2;
641   }
642 };
643 
644 // Slowpath entered when Thread::Current()->_exception is non-null
645 class ArmExceptionSlowPath : public SlowPath {
646  public:
ArmExceptionSlowPath(ArmManagedRegister scratch,size_t stack_adjust)647   explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust)
648       : scratch_(scratch), stack_adjust_(stack_adjust) {
649   }
650   virtual void Emit(Assembler *sp_asm);
651  private:
652   const ArmManagedRegister scratch_;
653   const size_t stack_adjust_;
654 };
655 
656 }  // namespace arm
657 }  // namespace art
658 
659 #endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_
660