Home | History | Annotate | Download | only in arm
      1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
      2 // All Rights Reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 //
      8 // - Redistributions of source code must retain the above copyright notice,
      9 // this list of conditions and the following disclaimer.
     10 //
     11 // - Redistribution in binary form must reproduce the above copyright
     12 // notice, this list of conditions and the following disclaimer in the
     13 // documentation and/or other materials provided with the
     14 // distribution.
     15 //
     16 // - Neither the name of Sun Microsystems or the names of contributors may
     17 // be used to endorse or promote products derived from this software without
     18 // specific prior written permission.
     19 //
     20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     31 // OF THE POSSIBILITY OF SUCH DAMAGE.
     32 
     33 // The original source code covered by the above license above has been
     34 // modified significantly by Google Inc.
     35 // Copyright 2010 the V8 project authors. All rights reserved.
     36 
     37 // A light-weight ARM Assembler
     38 // Generates user mode instructions for the ARM architecture up to version 5
     39 
     40 #ifndef V8_ARM_ASSEMBLER_THUMB2_H_
     41 #define V8_ARM_ASSEMBLER_THUMB2_H_
     42 #include <stdio.h>
     43 #include "assembler.h"
     44 #include "serialize.h"
     45 
     46 namespace v8 {
     47 namespace internal {
     48 
     49 // CPU Registers.
     50 //
     51 // 1) We would prefer to use an enum, but enum values are assignment-
     52 // compatible with int, which has caused code-generation bugs.
     53 //
     54 // 2) We would prefer to use a class instead of a struct but we don't like
     55 // the register initialization to depend on the particular initialization
     56 // order (which appears to be different on OS X, Linux, and Windows for the
     57 // installed versions of C++ we tried). Using a struct permits C-style
     58 // "initialization". Also, the Register objects cannot be const as this
     59 // forces initialization stubs in MSVC, making us dependent on initialization
     60 // order.
     61 //
     62 // 3) By not using an enum, we are possibly preventing the compiler from
     63 // doing certain constant folds, which may significantly reduce the
     64 // code generated for some assembly instructions (because they boil down
     65 // to a few constants). If this is a problem, we could change the code
     66 // such that we use an enum in optimized mode, and the struct in debug
     67 // mode. This way we get the compile-time error checking in debug mode
     68 // and best performance in optimized code.
     69 //
     70 // Core register
     71 struct Register {
     72   bool is_valid() const  { return 0 <= code_ && code_ < 16; }
     73   bool is(Register reg) const  { return code_ == reg.code_; }
     74   int code() const  {
     75     ASSERT(is_valid());
     76     return code_;
     77   }
     78   int bit() const  {
     79     ASSERT(is_valid());
     80     return 1 << code_;
     81   }
     82 
     83   // Unfortunately we can't make this private in a struct.
     84   int code_;
     85 };
     86 
     87 
     88 extern Register no_reg;
     89 extern Register r0;
     90 extern Register r1;
     91 extern Register r2;
     92 extern Register r3;
     93 extern Register r4;
     94 extern Register r5;
     95 extern Register r6;
     96 extern Register r7;
     97 extern Register r8;
     98 extern Register r9;
     99 extern Register r10;
    100 extern Register fp;
    101 extern Register ip;
    102 extern Register sp;
    103 extern Register lr;
    104 extern Register pc;
    105 
    106 
    107 // Single word VFP register.
    108 struct SwVfpRegister {
    109   bool is_valid() const  { return 0 <= code_ && code_ < 32; }
    110   bool is(SwVfpRegister reg) const  { return code_ == reg.code_; }
    111   int code() const  {
    112     ASSERT(is_valid());
    113     return code_;
    114   }
    115   int bit() const  {
    116     ASSERT(is_valid());
    117     return 1 << code_;
    118   }
    119 
    120   int code_;
    121 };
    122 
    123 
    124 // Double word VFP register.
    125 struct DwVfpRegister {
    126   // Supporting d0 to d15, can be later extended to d31.
    127   bool is_valid() const  { return 0 <= code_ && code_ < 16; }
    128   bool is(DwVfpRegister reg) const  { return code_ == reg.code_; }
    129   int code() const  {
    130     ASSERT(is_valid());
    131     return code_;
    132   }
    133   int bit() const  {
    134     ASSERT(is_valid());
    135     return 1 << code_;
    136   }
    137 
    138   int code_;
    139 };
    140 
    141 
    142 // Support for VFP registers s0 to s31 (d0 to d15).
    143 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
    144 extern SwVfpRegister s0;
    145 extern SwVfpRegister s1;
    146 extern SwVfpRegister s2;
    147 extern SwVfpRegister s3;
    148 extern SwVfpRegister s4;
    149 extern SwVfpRegister s5;
    150 extern SwVfpRegister s6;
    151 extern SwVfpRegister s7;
    152 extern SwVfpRegister s8;
    153 extern SwVfpRegister s9;
    154 extern SwVfpRegister s10;
    155 extern SwVfpRegister s11;
    156 extern SwVfpRegister s12;
    157 extern SwVfpRegister s13;
    158 extern SwVfpRegister s14;
    159 extern SwVfpRegister s15;
    160 extern SwVfpRegister s16;
    161 extern SwVfpRegister s17;
    162 extern SwVfpRegister s18;
    163 extern SwVfpRegister s19;
    164 extern SwVfpRegister s20;
    165 extern SwVfpRegister s21;
    166 extern SwVfpRegister s22;
    167 extern SwVfpRegister s23;
    168 extern SwVfpRegister s24;
    169 extern SwVfpRegister s25;
    170 extern SwVfpRegister s26;
    171 extern SwVfpRegister s27;
    172 extern SwVfpRegister s28;
    173 extern SwVfpRegister s29;
    174 extern SwVfpRegister s30;
    175 extern SwVfpRegister s31;
    176 
    177 extern DwVfpRegister d0;
    178 extern DwVfpRegister d1;
    179 extern DwVfpRegister d2;
    180 extern DwVfpRegister d3;
    181 extern DwVfpRegister d4;
    182 extern DwVfpRegister d5;
    183 extern DwVfpRegister d6;
    184 extern DwVfpRegister d7;
    185 extern DwVfpRegister d8;
    186 extern DwVfpRegister d9;
    187 extern DwVfpRegister d10;
    188 extern DwVfpRegister d11;
    189 extern DwVfpRegister d12;
    190 extern DwVfpRegister d13;
    191 extern DwVfpRegister d14;
    192 extern DwVfpRegister d15;
    193 
    194 
    195 // Coprocessor register
    196 struct CRegister {
    197   bool is_valid() const  { return 0 <= code_ && code_ < 16; }
    198   bool is(CRegister creg) const  { return code_ == creg.code_; }
    199   int code() const  {
    200     ASSERT(is_valid());
    201     return code_;
    202   }
    203   int bit() const  {
    204     ASSERT(is_valid());
    205     return 1 << code_;
    206   }
    207 
    208   // Unfortunately we can't make this private in a struct.
    209   int code_;
    210 };
    211 
    212 
    213 extern CRegister no_creg;
    214 extern CRegister cr0;
    215 extern CRegister cr1;
    216 extern CRegister cr2;
    217 extern CRegister cr3;
    218 extern CRegister cr4;
    219 extern CRegister cr5;
    220 extern CRegister cr6;
    221 extern CRegister cr7;
    222 extern CRegister cr8;
    223 extern CRegister cr9;
    224 extern CRegister cr10;
    225 extern CRegister cr11;
    226 extern CRegister cr12;
    227 extern CRegister cr13;
    228 extern CRegister cr14;
    229 extern CRegister cr15;
    230 
    231 
    232 // Coprocessor number
    233 enum Coprocessor {
    234   p0  = 0,
    235   p1  = 1,
    236   p2  = 2,
    237   p3  = 3,
    238   p4  = 4,
    239   p5  = 5,
    240   p6  = 6,
    241   p7  = 7,
    242   p8  = 8,
    243   p9  = 9,
    244   p10 = 10,
    245   p11 = 11,
    246   p12 = 12,
    247   p13 = 13,
    248   p14 = 14,
    249   p15 = 15
    250 };
    251 
    252 
    253 // Condition field in instructions.
    254 enum Condition {
    255   eq =  0 << 28,  // Z set            equal.
    256   ne =  1 << 28,  // Z clear          not equal.
    257   nz =  1 << 28,  // Z clear          not zero.
    258   cs =  2 << 28,  // C set            carry set.
    259   hs =  2 << 28,  // C set            unsigned higher or same.
    260   cc =  3 << 28,  // C clear          carry clear.
    261   lo =  3 << 28,  // C clear          unsigned lower.
    262   mi =  4 << 28,  // N set            negative.
    263   pl =  5 << 28,  // N clear          positive or zero.
    264   vs =  6 << 28,  // V set            overflow.
    265   vc =  7 << 28,  // V clear          no overflow.
    266   hi =  8 << 28,  // C set, Z clear   unsigned higher.
    267   ls =  9 << 28,  // C clear or Z set unsigned lower or same.
    268   ge = 10 << 28,  // N == V           greater or equal.
    269   lt = 11 << 28,  // N != V           less than.
    270   gt = 12 << 28,  // Z clear, N == V  greater than.
    271   le = 13 << 28,  // Z set or N != V  less then or equal
    272   al = 14 << 28   //                  always.
    273 };
    274 
    275 
    276 // Returns the equivalent of !cc.
    277 INLINE(Condition NegateCondition(Condition cc));
    278 
    279 
    280 // Corresponds to transposing the operands of a comparison.
    281 inline Condition ReverseCondition(Condition cc) {
    282   switch (cc) {
    283     case lo:
    284       return hi;
    285     case hi:
    286       return lo;
    287     case hs:
    288       return ls;
    289     case ls:
    290       return hs;
    291     case lt:
    292       return gt;
    293     case gt:
    294       return lt;
    295     case ge:
    296       return le;
    297     case le:
    298       return ge;
    299     default:
    300       return cc;
    301   };
    302 }
    303 
    304 
    305 // Branch hints are not used on the ARM.  They are defined so that they can
    306 // appear in shared function signatures, but will be ignored in ARM
    307 // implementations.
    308 enum Hint { no_hint };
    309 
    310 // Hints are not used on the arm.  Negating is trivial.
    311 inline Hint NegateHint(Hint ignored) { return no_hint; }
    312 
    313 
    314 // -----------------------------------------------------------------------------
    315 // Addressing modes and instruction variants
    316 
    317 // Shifter operand shift operation
    318 enum ShiftOp {
    319   LSL = 0 << 5,
    320   LSR = 1 << 5,
    321   ASR = 2 << 5,
    322   ROR = 3 << 5,
    323   RRX = -1
    324 };
    325 
    326 
    327 // Condition code updating mode
    328 enum SBit {
    329   SetCC   = 1 << 20,  // set condition code
    330   LeaveCC = 0 << 20   // leave condition code unchanged
    331 };
    332 
    333 
    334 // Status register selection
    335 enum SRegister {
    336   CPSR = 0 << 22,
    337   SPSR = 1 << 22
    338 };
    339 
    340 
    341 // Status register fields
    342 enum SRegisterField {
    343   CPSR_c = CPSR | 1 << 16,
    344   CPSR_x = CPSR | 1 << 17,
    345   CPSR_s = CPSR | 1 << 18,
    346   CPSR_f = CPSR | 1 << 19,
    347   SPSR_c = SPSR | 1 << 16,
    348   SPSR_x = SPSR | 1 << 17,
    349   SPSR_s = SPSR | 1 << 18,
    350   SPSR_f = SPSR | 1 << 19
    351 };
    352 
    353 // Status register field mask (or'ed SRegisterField enum values)
    354 typedef uint32_t SRegisterFieldMask;
    355 
    356 
    357 // Memory operand addressing mode
    358 enum AddrMode {
    359   // bit encoding P U W
    360   Offset       = (8|4|0) << 21,  // offset (without writeback to base)
    361   PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
    362   PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
    363   NegOffset    = (8|0|0) << 21,  // negative offset (without writeback to base)
    364   NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
    365   NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
    366 };
    367 
    368 
    369 // Load/store multiple addressing mode
    370 enum BlockAddrMode {
    371   // bit encoding P U W
    372   da           = (0|0|0) << 21,  // decrement after
    373   ia           = (0|4|0) << 21,  // increment after
    374   db           = (8|0|0) << 21,  // decrement before
    375   ib           = (8|4|0) << 21,  // increment before
    376   da_w         = (0|0|1) << 21,  // decrement after with writeback to base
    377   ia_w         = (0|4|1) << 21,  // increment after with writeback to base
    378   db_w         = (8|0|1) << 21,  // decrement before with writeback to base
    379   ib_w         = (8|4|1) << 21   // increment before with writeback to base
    380 };
    381 
    382 
    383 // Coprocessor load/store operand size
    384 enum LFlag {
    385   Long  = 1 << 22,  // long load/store coprocessor
    386   Short = 0 << 22   // short load/store coprocessor
    387 };
    388 
    389 
    390 // -----------------------------------------------------------------------------
    391 // Machine instruction Operands
    392 
    393 // Class Operand represents a shifter operand in data processing instructions
    394 class Operand BASE_EMBEDDED {
    395  public:
    396   // immediate
    397   INLINE(explicit Operand(int32_t immediate,
    398          RelocInfo::Mode rmode = RelocInfo::NONE));
    399   INLINE(explicit Operand(const ExternalReference& f));
    400   INLINE(explicit Operand(const char* s));
    401   explicit Operand(Handle<Object> handle);
    402   INLINE(explicit Operand(Smi* value));
    403 
    404   // rm
    405   INLINE(explicit Operand(Register rm));
    406 
    407   // rm <shift_op> shift_imm
    408   explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
    409 
    410   // rm <shift_op> rs
    411   explicit Operand(Register rm, ShiftOp shift_op, Register rs);
    412 
    413   // Return true if this is a register operand.
    414   INLINE(bool is_reg() const);
    415 
    416   Register rm() const { return rm_; }
    417 
    418  private:
    419   Register rm_;
    420   Register rs_;
    421   ShiftOp shift_op_;
    422   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
    423   int32_t imm32_;  // valid if rm_ == no_reg
    424   RelocInfo::Mode rmode_;
    425 
    426   friend class Assembler;
    427 };
    428 
    429 
    430 // Class MemOperand represents a memory operand in load and store instructions
    431 class MemOperand BASE_EMBEDDED {
    432  public:
    433   // [rn +/- offset]      Offset/NegOffset
    434   // [rn +/- offset]!     PreIndex/NegPreIndex
    435   // [rn], +/- offset     PostIndex/NegPostIndex
    436   // offset is any signed 32-bit value; offset is first loaded to register ip if
    437   // it does not fit the addressing mode (12-bit unsigned and sign bit)
    438   explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
    439 
    440   // [rn +/- rm]          Offset/NegOffset
    441   // [rn +/- rm]!         PreIndex/NegPreIndex
    442   // [rn], +/- rm         PostIndex/NegPostIndex
    443   explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
    444 
    445   // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
    446   // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
    447   // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
    448   explicit MemOperand(Register rn, Register rm,
    449                       ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
    450 
    451  private:
    452   Register rn_;  // base
    453   Register rm_;  // register offset
    454   int32_t offset_;  // valid if rm_ == no_reg
    455   ShiftOp shift_op_;
    456   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
    457   AddrMode am_;  // bits P, U, and W
    458 
    459   friend class Assembler;
    460 };
    461 
    462 // CpuFeatures keeps track of which features are supported by the target CPU.
    463 // Supported features must be enabled by a Scope before use.
    464 class CpuFeatures : public AllStatic {
    465  public:
    466   // Detect features of the target CPU. Set safe defaults if the serializer
    467   // is enabled (snapshots must be portable).
    468   static void Probe();
    469 
    470   // Check whether a feature is supported by the target CPU.
    471   static bool IsSupported(CpuFeature f) {
    472     if (f == VFP3 && !FLAG_enable_vfp3) return false;
    473     return (supported_ & (1u << f)) != 0;
    474   }
    475 
    476   // Check whether a feature is currently enabled.
    477   static bool IsEnabled(CpuFeature f) {
    478     return (enabled_ & (1u << f)) != 0;
    479   }
    480 
    481   // Enable a specified feature within a scope.
    482   class Scope BASE_EMBEDDED {
    483 #ifdef DEBUG
    484    public:
    485     explicit Scope(CpuFeature f) {
    486       ASSERT(CpuFeatures::IsSupported(f));
    487       ASSERT(!Serializer::enabled() ||
    488              (found_by_runtime_probing_ & (1u << f)) == 0);
    489       old_enabled_ = CpuFeatures::enabled_;
    490       CpuFeatures::enabled_ |= 1u << f;
    491     }
    492     ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
    493    private:
    494     unsigned old_enabled_;
    495 #else
    496    public:
    497     explicit Scope(CpuFeature f) {}
    498 #endif
    499   };
    500 
    501  private:
    502   static unsigned supported_;
    503   static unsigned enabled_;
    504   static unsigned found_by_runtime_probing_;
    505 };
    506 
    507 
    508 typedef int32_t Instr;
    509 
    510 
    511 extern const Instr kMovLrPc;
    512 extern const Instr kLdrPCPattern;
    513 
    514 
    515 class Assembler : public Malloced {
    516  public:
    517   // Create an assembler. Instructions and relocation information are emitted
    518   // into a buffer, with the instructions starting from the beginning and the
    519   // relocation information starting from the end of the buffer. See CodeDesc
    520   // for a detailed comment on the layout (globals.h).
    521   //
    522   // If the provided buffer is NULL, the assembler allocates and grows its own
    523   // buffer, and buffer_size determines the initial buffer size. The buffer is
    524   // owned by the assembler and deallocated upon destruction of the assembler.
    525   //
    526   // If the provided buffer is not NULL, the assembler uses the provided buffer
    527   // for code generation and assumes its size to be buffer_size. If the buffer
    528   // is too small, a fatal error occurs. No deallocation of the buffer is done
    529   // upon destruction of the assembler.
    530   Assembler(void* buffer, int buffer_size);
    531   ~Assembler();
    532 
    533   // GetCode emits any pending (non-emitted) code and fills the descriptor
    534   // desc. GetCode() is idempotent; it returns the same result if no other
    535   // Assembler functions are invoked in between GetCode() calls.
    536   void GetCode(CodeDesc* desc);
    537 
    538   // Label operations & relative jumps (PPUM Appendix D)
    539   //
    540   // Takes a branch opcode (cc) and a label (L) and generates
    541   // either a backward branch or a forward branch and links it
    542   // to the label fixup chain. Usage:
    543   //
    544   // Label L;    // unbound label
    545   // j(cc, &L);  // forward branch to unbound label
    546   // bind(&L);   // bind label to the current pc
    547   // j(cc, &L);  // backward branch to bound label
    548   // bind(&L);   // illegal: a label may be bound only once
    549   //
    550   // Note: The same Label can be used for forward and backward branches
    551   // but it may be bound only once.
    552 
    553   void bind(Label* L);  // binds an unbound label L to the current code position
    554 
    555   // Returns the branch offset to the given label from the current code position
    556   // Links the label to the current position if it is still unbound
    557   // Manages the jump elimination optimization if the second parameter is true.
    558   int branch_offset(Label* L, bool jump_elimination_allowed);
    559 
    560   // Puts a labels target address at the given position.
    561   // The high 8 bits are set to zero.
    562   void label_at_put(Label* L, int at_offset);
    563 
    564   // Return the address in the constant pool of the code target address used by
    565   // the branch/call instruction at pc.
    566   INLINE(static Address target_address_address_at(Address pc));
    567 
    568   // Read/Modify the code target address in the branch/call instruction at pc.
    569   INLINE(static Address target_address_at(Address pc));
    570   INLINE(static void set_target_address_at(Address pc, Address target));
    571 
    572   // This sets the branch destination (which is in the constant pool on ARM).
    573   // This is for calls and branches within generated code.
    574   inline static void set_target_at(Address constant_pool_entry, Address target);
    575 
    576   // This sets the branch destination (which is in the constant pool on ARM).
    577   // This is for calls and branches to runtime code.
    578   inline static void set_external_target_at(Address constant_pool_entry,
    579                                             Address target) {
    580     set_target_at(constant_pool_entry, target);
    581   }
    582 
    583   // Here we are patching the address in the constant pool, not the actual call
    584   // instruction.  The address in the constant pool is the same size as a
    585   // pointer.
    586   static const int kCallTargetSize = kPointerSize;
    587   static const int kExternalTargetSize = kPointerSize;
    588 
    589   // Size of an instruction.
    590   static const int kInstrSize = sizeof(Instr);
    591 
    592   // Distance between the instruction referring to the address of the call
    593   // target (ldr pc, [target addr in const pool]) and the return address
    594   static const int kCallTargetAddressOffset = kInstrSize;
    595 
    596   // Distance between start of patched return sequence and the emitted address
    597   // to jump to.
    598   static const int kPatchReturnSequenceAddressOffset = kInstrSize;
    599 
    600   // Difference between address of current opcode and value read from pc
    601   // register.
    602   static const int kPcLoadDelta = 8;
    603 
    604   static const int kJSReturnSequenceLength = 4;
    605 
    606   // ---------------------------------------------------------------------------
    607   // Code generation
    608 
    609   // Insert the smallest number of nop instructions
    610   // possible to align the pc offset to a multiple
    611   // of m. m must be a power of 2 (>= 4).
    612   void Align(int m);
    613 
    614   // Branch instructions
    615   void b(int branch_offset, Condition cond = al);
    616   void bl(int branch_offset, Condition cond = al);
    617   void blx(int branch_offset);  // v5 and above
    618   void blx(Register target, Condition cond = al);  // v5 and above
    619   void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
    620 
    621   // Convenience branch instructions using labels
    622   void b(Label* L, Condition cond = al)  {
    623     b(branch_offset(L, cond == al), cond);
    624   }
    625   void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
    626   void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
    627   void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
    628   void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
    629 
    630   // Data-processing instructions
    631   void ubfx(Register dst, Register src1, const Operand& src2,
    632             const Operand& src3, Condition cond = al);
    633 
    634   void and_(Register dst, Register src1, const Operand& src2,
    635             SBit s = LeaveCC, Condition cond = al);
    636 
    637   void eor(Register dst, Register src1, const Operand& src2,
    638            SBit s = LeaveCC, Condition cond = al);
    639 
    640   void sub(Register dst, Register src1, const Operand& src2,
    641            SBit s = LeaveCC, Condition cond = al);
    642   void sub(Register dst, Register src1, Register src2,
    643            SBit s = LeaveCC, Condition cond = al) {
    644     sub(dst, src1, Operand(src2), s, cond);
    645   }
    646 
    647   void rsb(Register dst, Register src1, const Operand& src2,
    648            SBit s = LeaveCC, Condition cond = al);
    649 
    650   void add(Register dst, Register src1, const Operand& src2,
    651            SBit s = LeaveCC, Condition cond = al);
    652 
    653   void adc(Register dst, Register src1, const Operand& src2,
    654            SBit s = LeaveCC, Condition cond = al);
    655 
    656   void sbc(Register dst, Register src1, const Operand& src2,
    657            SBit s = LeaveCC, Condition cond = al);
    658 
    659   void rsc(Register dst, Register src1, const Operand& src2,
    660            SBit s = LeaveCC, Condition cond = al);
    661 
    662   void tst(Register src1, const Operand& src2, Condition cond = al);
    663   void tst(Register src1, Register src2, Condition cond = al) {
    664     tst(src1, Operand(src2), cond);
    665   }
    666 
    667   void teq(Register src1, const Operand& src2, Condition cond = al);
    668 
    669   void cmp(Register src1, const Operand& src2, Condition cond = al);
    670   void cmp(Register src1, Register src2, Condition cond = al) {
    671     cmp(src1, Operand(src2), cond);
    672   }
    673 
    674   void cmn(Register src1, const Operand& src2, Condition cond = al);
    675 
    676   void orr(Register dst, Register src1, const Operand& src2,
    677            SBit s = LeaveCC, Condition cond = al);
    678   void orr(Register dst, Register src1, Register src2,
    679            SBit s = LeaveCC, Condition cond = al) {
    680     orr(dst, src1, Operand(src2), s, cond);
    681   }
    682 
    683   void mov(Register dst, const Operand& src,
    684            SBit s = LeaveCC, Condition cond = al);
    685   void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
    686     mov(dst, Operand(src), s, cond);
    687   }
    688 
    689   void bic(Register dst, Register src1, const Operand& src2,
    690            SBit s = LeaveCC, Condition cond = al);
    691 
    692   void mvn(Register dst, const Operand& src,
    693            SBit s = LeaveCC, Condition cond = al);
    694 
    695   // Multiply instructions
    696 
    697   void mla(Register dst, Register src1, Register src2, Register srcA,
    698            SBit s = LeaveCC, Condition cond = al);
    699 
    700   void mul(Register dst, Register src1, Register src2,
    701            SBit s = LeaveCC, Condition cond = al);
    702 
    703   void smlal(Register dstL, Register dstH, Register src1, Register src2,
    704              SBit s = LeaveCC, Condition cond = al);
    705 
    706   void smull(Register dstL, Register dstH, Register src1, Register src2,
    707              SBit s = LeaveCC, Condition cond = al);
    708 
    709   void umlal(Register dstL, Register dstH, Register src1, Register src2,
    710              SBit s = LeaveCC, Condition cond = al);
    711 
    712   void umull(Register dstL, Register dstH, Register src1, Register src2,
    713              SBit s = LeaveCC, Condition cond = al);
    714 
    715   // Miscellaneous arithmetic instructions
    716 
    717   void clz(Register dst, Register src, Condition cond = al);  // v5 and above
    718 
    719   // Status register access instructions
    720 
    721   void mrs(Register dst, SRegister s, Condition cond = al);
    722   void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
    723 
    724   // Load/Store instructions
    725   void ldr(Register dst, const MemOperand& src, Condition cond = al);
    726   void str(Register src, const MemOperand& dst, Condition cond = al);
    727   void ldrb(Register dst, const MemOperand& src, Condition cond = al);
    728   void strb(Register src, const MemOperand& dst, Condition cond = al);
    729   void ldrh(Register dst, const MemOperand& src, Condition cond = al);
    730   void strh(Register src, const MemOperand& dst, Condition cond = al);
    731   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
    732   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
    733 
    734   // Load/Store multiple instructions
    735   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
    736   void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
    737 
    738   // Semaphore instructions
    739   void swp(Register dst, Register src, Register base, Condition cond = al);
    740   void swpb(Register dst, Register src, Register base, Condition cond = al);
    741 
    742   // Exception-generating instructions and debugging support
    743   void stop(const char* msg);
    744 
    745   void bkpt(uint32_t imm16);  // v5 and above
    746   void swi(uint32_t imm24, Condition cond = al);
    747 
    748   // Coprocessor instructions
    749 
    750   void cdp(Coprocessor coproc, int opcode_1,
    751            CRegister crd, CRegister crn, CRegister crm,
    752            int opcode_2, Condition cond = al);
    753 
    754   void cdp2(Coprocessor coproc, int opcode_1,
    755             CRegister crd, CRegister crn, CRegister crm,
    756             int opcode_2);  // v5 and above
    757 
    758   void mcr(Coprocessor coproc, int opcode_1,
    759            Register rd, CRegister crn, CRegister crm,
    760            int opcode_2 = 0, Condition cond = al);
    761 
    762   void mcr2(Coprocessor coproc, int opcode_1,
    763             Register rd, CRegister crn, CRegister crm,
    764             int opcode_2 = 0);  // v5 and above
    765 
    766   void mrc(Coprocessor coproc, int opcode_1,
    767            Register rd, CRegister crn, CRegister crm,
    768            int opcode_2 = 0, Condition cond = al);
    769 
    770   void mrc2(Coprocessor coproc, int opcode_1,
    771             Register rd, CRegister crn, CRegister crm,
    772             int opcode_2 = 0);  // v5 and above
    773 
    774   void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
    775            LFlag l = Short, Condition cond = al);
    776   void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
    777            LFlag l = Short, Condition cond = al);
    778 
    779   void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
    780             LFlag l = Short);  // v5 and above
    781   void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
    782             LFlag l = Short);  // v5 and above
    783 
    784   void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
    785            LFlag l = Short, Condition cond = al);
    786   void stc(Coprocessor coproc, CRegister crd, Register base, int option,
    787            LFlag l = Short, Condition cond = al);
    788 
    789   void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
    790             LFlag l = Short);  // v5 and above
    791   void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
    792             LFlag l = Short);  // v5 and above
    793 
    794   // Support for VFP.
    795   // All these APIs support S0 to S31 and D0 to D15.
    796   // Currently these APIs do not support extended D registers, i.e, D16 to D31.
    797   // However, some simple modifications can allow
    798   // these APIs to support D16 to D31.
    799 
    800   void vldr(const DwVfpRegister dst,
    801             const Register base,
    802             int offset,  // Offset must be a multiple of 4.
    803             const Condition cond = al);
    804   void vstr(const DwVfpRegister src,
    805             const Register base,
    806             int offset,  // Offset must be a multiple of 4.
    807             const Condition cond = al);
    808   void vmov(const DwVfpRegister dst,
    809             const Register src1,
    810             const Register src2,
    811             const Condition cond = al);
    812   void vmov(const Register dst1,
    813             const Register dst2,
    814             const DwVfpRegister src,
    815             const Condition cond = al);
    816   void vmov(const SwVfpRegister dst,
    817             const Register src,
    818             const Condition cond = al);
    819   void vmov(const Register dst,
    820             const SwVfpRegister src,
    821             const Condition cond = al);
    822   void vcvt(const DwVfpRegister dst,
    823             const SwVfpRegister src,
    824             const Condition cond = al);
    825   void vcvt(const SwVfpRegister dst,
    826             const DwVfpRegister src,
    827             const Condition cond = al);
    828 
    829   void vadd(const DwVfpRegister dst,
    830             const DwVfpRegister src1,
    831             const DwVfpRegister src2,
    832             const Condition cond = al);
    833   void vsub(const DwVfpRegister dst,
    834             const DwVfpRegister src1,
    835             const DwVfpRegister src2,
    836             const Condition cond = al);
    837   void vmul(const DwVfpRegister dst,
    838             const DwVfpRegister src1,
    839             const DwVfpRegister src2,
    840             const Condition cond = al);
    841   void vdiv(const DwVfpRegister dst,
    842             const DwVfpRegister src1,
    843             const DwVfpRegister src2,
    844             const Condition cond = al);
    845   void vcmp(const DwVfpRegister src1,
    846             const DwVfpRegister src2,
    847             const SBit s = LeaveCC,
    848             const Condition cond = al);
    849   void vmrs(const Register dst,
    850             const Condition cond = al);
    851 
    852   // Pseudo instructions
    853   void nop()  { mov(r0, Operand(r0)); }
    854 
    855   void push(Register src, Condition cond = al) {
    856     str(src, MemOperand(sp, 4, NegPreIndex), cond);
    857   }
    858 
    859   void pop(Register dst, Condition cond = al) {
    860     ldr(dst, MemOperand(sp, 4, PostIndex), cond);
    861   }
    862 
    863   void pop() {
    864     add(sp, sp, Operand(kPointerSize));
    865   }
    866 
    867   // Load effective address of memory operand x into register dst
    868   void lea(Register dst, const MemOperand& x,
    869            SBit s = LeaveCC, Condition cond = al);
    870 
    871   // Jump unconditionally to given label.
    872   void jmp(Label* L) { b(L, al); }
    873 
    874   // Check the code size generated from label to here.
    875   int InstructionsGeneratedSince(Label* l) {
    876     return (pc_offset() - l->pos()) / kInstrSize;
    877   }
    878 
    879   // Check whether an immediate fits an addressing mode 1 instruction.
    880   bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
    881 
    882   // Postpone the generation of the constant pool for the specified number of
    883   // instructions.
    884   void BlockConstPoolFor(int instructions);
    885 
    886   // Debugging
    887 
    888   // Mark address of the ExitJSFrame code.
    889   void RecordJSReturn();
    890 
    891   // Record a comment relocation entry that can be used by a disassembler.
    892   // Use --debug_code to enable.
    893   void RecordComment(const char* msg);
    894 
    895   void RecordPosition(int pos);
    896   void RecordStatementPosition(int pos);
    897   void WriteRecordedPositions();
    898 
    899   int pc_offset() const { return pc_ - buffer_; }
    900   int current_position() const { return current_position_; }
    901   int current_statement_position() const { return current_position_; }
    902 
    903  protected:
    904   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
    905 
    906   // Read/patch instructions
    907   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
    908   void instr_at_put(byte* pc, Instr instr) {
    909     *reinterpret_cast<Instr*>(pc) = instr;
    910   }
    911   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
    912   void instr_at_put(int pos, Instr instr) {
    913     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
    914   }
    915 
    916   // Decode branch instruction at pos and return branch target pos
    917   int target_at(int pos);
    918 
    919   // Patch branch instruction at pos to branch to given branch target pos
    920   void target_at_put(int pos, int target_pos);
    921 
    922   // Check if is time to emit a constant pool for pending reloc info entries
    923   void CheckConstPool(bool force_emit, bool require_jump);
    924 
    925   // Block the emission of the constant pool before pc_offset
    926   void BlockConstPoolBefore(int pc_offset) {
    927     if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
    928   }
    929 
    930  private:
    931   // Code buffer:
    932   // The buffer into which code and relocation info are generated.
    933   byte* buffer_;
    934   int buffer_size_;
    935   // True if the assembler owns the buffer, false if buffer is external.
    936   bool own_buffer_;
    937 
    938   // Buffer size and constant pool distance are checked together at regular
    939   // intervals of kBufferCheckInterval emitted bytes
    940   static const int kBufferCheckInterval = 1*KB/2;
    941   int next_buffer_check_;  // pc offset of next buffer check
    942 
    943   // Code generation
    944   // The relocation writer's position is at least kGap bytes below the end of
    945   // the generated instructions. This is so that multi-instruction sequences do
    946   // not have to check for overflow. The same is true for writes of large
    947   // relocation info entries.
    948   static const int kGap = 32;
    949   byte* pc_;  // the program counter; moves forward
    950 
    951   // Constant pool generation
    952   // Pools are emitted in the instruction stream, preferably after unconditional
    953   // jumps or after returns from functions (in dead code locations).
    954   // If a long code sequence does not contain unconditional jumps, it is
    955   // necessary to emit the constant pool before the pool gets too far from the
    956   // location it is accessed from. In this case, we emit a jump over the emitted
    957   // constant pool.
    958   // Constants in the pool may be addresses of functions that gets relocated;
    959   // if so, a relocation info entry is associated to the constant pool entry.
    960 
    961   // Repeated checking whether the constant pool should be emitted is rather
    962   // expensive. By default we only check again once a number of instructions
    963   // has been generated. That also means that the sizing of the buffers is not
    964   // an exact science, and that we rely on some slop to not overrun buffers.
    965   static const int kCheckConstIntervalInst = 32;
    966   static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
    967 
    968 
    969   // Pools are emitted after function return and in dead code at (more or less)
    970   // regular intervals of kDistBetweenPools bytes
    971   static const int kDistBetweenPools = 1*KB;
    972 
    973   // Constants in pools are accessed via pc relative addressing, which can
    974   // reach +/-4KB thereby defining a maximum distance between the instruction
    975   // and the accessed constant. We satisfy this constraint by limiting the
    976   // distance between pools.
    977   static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
    978 
    979   // Emission of the constant pool may be blocked in some code sequences
    980   int no_const_pool_before_;  // block emission before this pc offset
    981 
    982   // Keep track of the last emitted pool to guarantee a maximal distance
    983   int last_const_pool_end_;  // pc offset following the last constant pool
    984 
    985   // Relocation info generation
    986   // Each relocation is encoded as a variable size value
    987   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
    988   RelocInfoWriter reloc_info_writer;
    989   // Relocation info records are also used during code generation as temporary
    990   // containers for constants and code target addresses until they are emitted
    991   // to the constant pool. These pending relocation info records are temporarily
    992   // stored in a separate buffer until a constant pool is emitted.
    993   // If every instruction in a long sequence is accessing the pool, we need one
    994   // pending relocation entry per instruction.
    995   static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
    996   RelocInfo prinfo_[kMaxNumPRInfo];  // the buffer of pending relocation info
    997   int num_prinfo_;  // number of pending reloc info entries in the buffer
    998 
    999   // The bound position, before this we cannot do instruction elimination.
   1000   int last_bound_pos_;
   1001 
   1002   // source position information
   1003   int current_position_;
   1004   int current_statement_position_;
   1005   int written_position_;
   1006   int written_statement_position_;
   1007 
   1008   // Code emission
   1009   inline void CheckBuffer();
   1010   void GrowBuffer();
   1011   inline void emit(Instr x);
   1012 
   1013   // Instruction generation
   1014   void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
   1015   void addrmod2(Instr instr, Register rd, const MemOperand& x);
   1016   void addrmod3(Instr instr, Register rd, const MemOperand& x);
   1017   void addrmod4(Instr instr, Register rn, RegList rl);
   1018   void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
   1019 
   1020   // Labels
   1021   void print(Label* L);
   1022   void bind_to(Label* L, int pos);
   1023   void link_to(Label* L, Label* appendix);
   1024   void next(Label* L);
   1025 
   1026   // Record reloc info for current pc_
   1027   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
   1028 
   1029   friend class RegExpMacroAssemblerARM;
   1030   friend class RelocInfo;
   1031   friend class CodePatcher;
   1032 };
   1033 
   1034 } }  // namespace v8::internal
   1035 
   1036 #endif  // V8_ARM_ASSEMBLER_THUMB2_H_
   1037