Home | History | Annotate | Download | only in arm
      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
     36   ShifterOperand() {
     37     type_ = -1;
     38   }
     39 
     40   // Data-processing operands - 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
     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
     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
     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
     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 
     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:
     97   bool is_valid() const { return (type_ == 0) || (type_ == 1); }
     98 
     99   uint32_t type() const {
    100     CHECK(is_valid());
    101     return type_;
    102   }
    103 
    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:
    182   uint32_t encoding() const { return encoding_; }
    183 
    184   // Encoding for addressing mode 3.
    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.
    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:
    215   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.
    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:
    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