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 2012 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_ARM_H_
     41 #define V8_ARM_ASSEMBLER_ARM_H_
     42 #include <stdio.h>
     43 #include "assembler.h"
     44 #include "constants-arm.h"
     45 #include "serialize.h"
     46 
     47 namespace v8 {
     48 namespace internal {
     49 
     50 // CpuFeatures keeps track of which features are supported by the target CPU.
     51 // Supported features must be enabled by a CpuFeatureScope before use.
     52 class CpuFeatures : public AllStatic {
     53  public:
     54   // Detect features of the target CPU. Set safe defaults if the serializer
     55   // is enabled (snapshots must be portable).
     56   static void Probe();
     57 
     58   // Display target use when compiling.
     59   static void PrintTarget();
     60 
     61   // Display features.
     62   static void PrintFeatures();
     63 
     64   // Check whether a feature is supported by the target CPU.
     65   static bool IsSupported(CpuFeature f) {
     66     ASSERT(initialized_);
     67     return (supported_ & (1u << f)) != 0;
     68   }
     69 
     70   static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
     71     ASSERT(initialized_);
     72     return (found_by_runtime_probing_only_ &
     73             (static_cast<uint64_t>(1) << f)) != 0;
     74   }
     75 
     76   static bool IsSafeForSnapshot(CpuFeature f) {
     77     return (IsSupported(f) &&
     78             (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
     79   }
     80 
     81   static unsigned cache_line_size() { return cache_line_size_; }
     82 
     83  private:
     84 #ifdef DEBUG
     85   static bool initialized_;
     86 #endif
     87   static unsigned supported_;
     88   static unsigned found_by_runtime_probing_only_;
     89   static unsigned cache_line_size_;
     90 
     91   friend class ExternalReference;
     92   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
     93 };
     94 
     95 
     96 // CPU Registers.
     97 //
     98 // 1) We would prefer to use an enum, but enum values are assignment-
     99 // compatible with int, which has caused code-generation bugs.
    100 //
    101 // 2) We would prefer to use a class instead of a struct but we don't like
    102 // the register initialization to depend on the particular initialization
    103 // order (which appears to be different on OS X, Linux, and Windows for the
    104 // installed versions of C++ we tried). Using a struct permits C-style
    105 // "initialization". Also, the Register objects cannot be const as this
    106 // forces initialization stubs in MSVC, making us dependent on initialization
    107 // order.
    108 //
    109 // 3) By not using an enum, we are possibly preventing the compiler from
    110 // doing certain constant folds, which may significantly reduce the
    111 // code generated for some assembly instructions (because they boil down
    112 // to a few constants). If this is a problem, we could change the code
    113 // such that we use an enum in optimized mode, and the struct in debug
    114 // mode. This way we get the compile-time error checking in debug mode
    115 // and best performance in optimized code.
    116 
    117 // Core register
    118 struct Register {
    119   static const int kNumRegisters = 16;
    120   static const int kMaxNumAllocatableRegisters = 8;
    121   static const int kSizeInBytes = 4;
    122 
    123   inline static int NumAllocatableRegisters();
    124 
    125   static int ToAllocationIndex(Register reg) {
    126     ASSERT(reg.code() < kMaxNumAllocatableRegisters);
    127     return reg.code();
    128   }
    129 
    130   static Register FromAllocationIndex(int index) {
    131     ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
    132     return from_code(index);
    133   }
    134 
    135   static const char* AllocationIndexToString(int index) {
    136     ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
    137     const char* const names[] = {
    138       "r0",
    139       "r1",
    140       "r2",
    141       "r3",
    142       "r4",
    143       "r5",
    144       "r6",
    145       "r7",
    146     };
    147     return names[index];
    148   }
    149 
    150   static Register from_code(int code) {
    151     Register r = { code };
    152     return r;
    153   }
    154 
    155   bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
    156   bool is(Register reg) const { return code_ == reg.code_; }
    157   int code() const {
    158     ASSERT(is_valid());
    159     return code_;
    160   }
    161   int bit() const {
    162     ASSERT(is_valid());
    163     return 1 << code_;
    164   }
    165 
    166   void set_code(int code) {
    167     code_ = code;
    168     ASSERT(is_valid());
    169   }
    170 
    171   // Unfortunately we can't make this private in a struct.
    172   int code_;
    173 };
    174 
    175 // These constants are used in several locations, including static initializers
    176 const int kRegister_no_reg_Code = -1;
    177 const int kRegister_r0_Code = 0;
    178 const int kRegister_r1_Code = 1;
    179 const int kRegister_r2_Code = 2;
    180 const int kRegister_r3_Code = 3;
    181 const int kRegister_r4_Code = 4;
    182 const int kRegister_r5_Code = 5;
    183 const int kRegister_r6_Code = 6;
    184 const int kRegister_r7_Code = 7;
    185 const int kRegister_r8_Code = 8;
    186 const int kRegister_r9_Code = 9;
    187 const int kRegister_r10_Code = 10;
    188 const int kRegister_fp_Code = 11;
    189 const int kRegister_ip_Code = 12;
    190 const int kRegister_sp_Code = 13;
    191 const int kRegister_lr_Code = 14;
    192 const int kRegister_pc_Code = 15;
    193 
    194 const Register no_reg = { kRegister_no_reg_Code };
    195 
    196 const Register r0  = { kRegister_r0_Code };
    197 const Register r1  = { kRegister_r1_Code };
    198 const Register r2  = { kRegister_r2_Code };
    199 const Register r3  = { kRegister_r3_Code };
    200 const Register r4  = { kRegister_r4_Code };
    201 const Register r5  = { kRegister_r5_Code };
    202 const Register r6  = { kRegister_r6_Code };
    203 const Register r7  = { kRegister_r7_Code };
    204 // Used as context register.
    205 const Register r8  = { kRegister_r8_Code };
    206 // Used as lithium codegen scratch register.
    207 const Register r9  = { kRegister_r9_Code };
    208 // Used as roots register.
    209 const Register r10 = { kRegister_r10_Code };
    210 const Register fp  = { kRegister_fp_Code };
    211 const Register ip  = { kRegister_ip_Code };
    212 const Register sp  = { kRegister_sp_Code };
    213 const Register lr  = { kRegister_lr_Code };
    214 const Register pc  = { kRegister_pc_Code };
    215 
    216 // Single word VFP register.
    217 struct SwVfpRegister {
    218   static const int kSizeInBytes = 4;
    219   bool is_valid() const { return 0 <= code_ && code_ < 32; }
    220   bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
    221   int code() const {
    222     ASSERT(is_valid());
    223     return code_;
    224   }
    225   int bit() const {
    226     ASSERT(is_valid());
    227     return 1 << code_;
    228   }
    229   void split_code(int* vm, int* m) const {
    230     ASSERT(is_valid());
    231     *m = code_ & 0x1;
    232     *vm = code_ >> 1;
    233   }
    234 
    235   int code_;
    236 };
    237 
    238 
    239 // Double word VFP register.
    240 struct DwVfpRegister {
    241   static const int kMaxNumRegisters = 32;
    242   // A few double registers are reserved: one as a scratch register and one to
    243   // hold 0.0, that does not fit in the immediate field of vmov instructions.
    244   //  d14: 0.0
    245   //  d15: scratch register.
    246   static const int kNumReservedRegisters = 2;
    247   static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
    248       kNumReservedRegisters;
    249   static const int kSizeInBytes = 8;
    250 
    251   // Note: the number of registers can be different at snapshot and run-time.
    252   // Any code included in the snapshot must be able to run both with 16 or 32
    253   // registers.
    254   inline static int NumRegisters();
    255   inline static int NumAllocatableRegisters();
    256 
    257   inline static int ToAllocationIndex(DwVfpRegister reg);
    258   static const char* AllocationIndexToString(int index);
    259   inline static DwVfpRegister FromAllocationIndex(int index);
    260 
    261   static DwVfpRegister from_code(int code) {
    262     DwVfpRegister r = { code };
    263     return r;
    264   }
    265 
    266   bool is_valid() const {
    267     return 0 <= code_ && code_ < kMaxNumRegisters;
    268   }
    269   bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
    270   int code() const {
    271     ASSERT(is_valid());
    272     return code_;
    273   }
    274   int bit() const {
    275     ASSERT(is_valid());
    276     return 1 << code_;
    277   }
    278   void split_code(int* vm, int* m) const {
    279     ASSERT(is_valid());
    280     *m = (code_ & 0x10) >> 4;
    281     *vm = code_ & 0x0F;
    282   }
    283 
    284   int code_;
    285 };
    286 
    287 
    288 typedef DwVfpRegister DoubleRegister;
    289 
    290 
    291 // Double word VFP register d0-15.
    292 struct LowDwVfpRegister {
    293  public:
    294   static const int kMaxNumLowRegisters = 16;
    295   operator DwVfpRegister() const {
    296     DwVfpRegister r = { code_ };
    297     return r;
    298   }
    299   static LowDwVfpRegister from_code(int code) {
    300     LowDwVfpRegister r = { code };
    301     return r;
    302   }
    303 
    304   bool is_valid() const {
    305     return 0 <= code_ && code_ < kMaxNumLowRegisters;
    306   }
    307   bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
    308   bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
    309   int code() const {
    310     ASSERT(is_valid());
    311     return code_;
    312   }
    313   SwVfpRegister low() const {
    314     SwVfpRegister reg;
    315     reg.code_ = code_ * 2;
    316 
    317     ASSERT(reg.is_valid());
    318     return reg;
    319   }
    320   SwVfpRegister high() const {
    321     SwVfpRegister reg;
    322     reg.code_ = (code_ * 2) + 1;
    323 
    324     ASSERT(reg.is_valid());
    325     return reg;
    326   }
    327 
    328   int code_;
    329 };
    330 
    331 
    332 // Quad word NEON register.
    333 struct QwNeonRegister {
    334   static const int kMaxNumRegisters = 16;
    335 
    336   static QwNeonRegister from_code(int code) {
    337     QwNeonRegister r = { code };
    338     return r;
    339   }
    340 
    341   bool is_valid() const {
    342     return (0 <= code_) && (code_ < kMaxNumRegisters);
    343   }
    344   bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
    345   int code() const {
    346     ASSERT(is_valid());
    347     return code_;
    348   }
    349   void split_code(int* vm, int* m) const {
    350     ASSERT(is_valid());
    351     *m = (code_ & 0x10) >> 4;
    352     *vm = code_ & 0x0F;
    353   }
    354 
    355   int code_;
    356 };
    357 
    358 
    359 typedef QwNeonRegister QuadRegister;
    360 
    361 
    362 // Support for the VFP registers s0 to s31 (d0 to d15).
    363 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
    364 const SwVfpRegister s0  = {  0 };
    365 const SwVfpRegister s1  = {  1 };
    366 const SwVfpRegister s2  = {  2 };
    367 const SwVfpRegister s3  = {  3 };
    368 const SwVfpRegister s4  = {  4 };
    369 const SwVfpRegister s5  = {  5 };
    370 const SwVfpRegister s6  = {  6 };
    371 const SwVfpRegister s7  = {  7 };
    372 const SwVfpRegister s8  = {  8 };
    373 const SwVfpRegister s9  = {  9 };
    374 const SwVfpRegister s10 = { 10 };
    375 const SwVfpRegister s11 = { 11 };
    376 const SwVfpRegister s12 = { 12 };
    377 const SwVfpRegister s13 = { 13 };
    378 const SwVfpRegister s14 = { 14 };
    379 const SwVfpRegister s15 = { 15 };
    380 const SwVfpRegister s16 = { 16 };
    381 const SwVfpRegister s17 = { 17 };
    382 const SwVfpRegister s18 = { 18 };
    383 const SwVfpRegister s19 = { 19 };
    384 const SwVfpRegister s20 = { 20 };
    385 const SwVfpRegister s21 = { 21 };
    386 const SwVfpRegister s22 = { 22 };
    387 const SwVfpRegister s23 = { 23 };
    388 const SwVfpRegister s24 = { 24 };
    389 const SwVfpRegister s25 = { 25 };
    390 const SwVfpRegister s26 = { 26 };
    391 const SwVfpRegister s27 = { 27 };
    392 const SwVfpRegister s28 = { 28 };
    393 const SwVfpRegister s29 = { 29 };
    394 const SwVfpRegister s30 = { 30 };
    395 const SwVfpRegister s31 = { 31 };
    396 
    397 const DwVfpRegister no_dreg = { -1 };
    398 const LowDwVfpRegister d0 = { 0 };
    399 const LowDwVfpRegister d1 = { 1 };
    400 const LowDwVfpRegister d2 = { 2 };
    401 const LowDwVfpRegister d3 = { 3 };
    402 const LowDwVfpRegister d4 = { 4 };
    403 const LowDwVfpRegister d5 = { 5 };
    404 const LowDwVfpRegister d6 = { 6 };
    405 const LowDwVfpRegister d7 = { 7 };
    406 const LowDwVfpRegister d8 = { 8 };
    407 const LowDwVfpRegister d9 = { 9 };
    408 const LowDwVfpRegister d10 = { 10 };
    409 const LowDwVfpRegister d11 = { 11 };
    410 const LowDwVfpRegister d12 = { 12 };
    411 const LowDwVfpRegister d13 = { 13 };
    412 const LowDwVfpRegister d14 = { 14 };
    413 const LowDwVfpRegister d15 = { 15 };
    414 const DwVfpRegister d16 = { 16 };
    415 const DwVfpRegister d17 = { 17 };
    416 const DwVfpRegister d18 = { 18 };
    417 const DwVfpRegister d19 = { 19 };
    418 const DwVfpRegister d20 = { 20 };
    419 const DwVfpRegister d21 = { 21 };
    420 const DwVfpRegister d22 = { 22 };
    421 const DwVfpRegister d23 = { 23 };
    422 const DwVfpRegister d24 = { 24 };
    423 const DwVfpRegister d25 = { 25 };
    424 const DwVfpRegister d26 = { 26 };
    425 const DwVfpRegister d27 = { 27 };
    426 const DwVfpRegister d28 = { 28 };
    427 const DwVfpRegister d29 = { 29 };
    428 const DwVfpRegister d30 = { 30 };
    429 const DwVfpRegister d31 = { 31 };
    430 
    431 const QwNeonRegister q0  = {  0 };
    432 const QwNeonRegister q1  = {  1 };
    433 const QwNeonRegister q2  = {  2 };
    434 const QwNeonRegister q3  = {  3 };
    435 const QwNeonRegister q4  = {  4 };
    436 const QwNeonRegister q5  = {  5 };
    437 const QwNeonRegister q6  = {  6 };
    438 const QwNeonRegister q7  = {  7 };
    439 const QwNeonRegister q8  = {  8 };
    440 const QwNeonRegister q9  = {  9 };
    441 const QwNeonRegister q10 = { 10 };
    442 const QwNeonRegister q11 = { 11 };
    443 const QwNeonRegister q12 = { 12 };
    444 const QwNeonRegister q13 = { 13 };
    445 const QwNeonRegister q14 = { 14 };
    446 const QwNeonRegister q15 = { 15 };
    447 
    448 
    449 // Aliases for double registers.  Defined using #define instead of
    450 // "static const DwVfpRegister&" because Clang complains otherwise when a
    451 // compilation unit that includes this header doesn't use the variables.
    452 #define kFirstCalleeSavedDoubleReg d8
    453 #define kLastCalleeSavedDoubleReg d15
    454 #define kDoubleRegZero d14
    455 #define kScratchDoubleReg d15
    456 
    457 
    458 // Coprocessor register
    459 struct CRegister {
    460   bool is_valid() const { return 0 <= code_ && code_ < 16; }
    461   bool is(CRegister creg) const { return code_ == creg.code_; }
    462   int code() const {
    463     ASSERT(is_valid());
    464     return code_;
    465   }
    466   int bit() const {
    467     ASSERT(is_valid());
    468     return 1 << code_;
    469   }
    470 
    471   // Unfortunately we can't make this private in a struct.
    472   int code_;
    473 };
    474 
    475 
    476 const CRegister no_creg = { -1 };
    477 
    478 const CRegister cr0  = {  0 };
    479 const CRegister cr1  = {  1 };
    480 const CRegister cr2  = {  2 };
    481 const CRegister cr3  = {  3 };
    482 const CRegister cr4  = {  4 };
    483 const CRegister cr5  = {  5 };
    484 const CRegister cr6  = {  6 };
    485 const CRegister cr7  = {  7 };
    486 const CRegister cr8  = {  8 };
    487 const CRegister cr9  = {  9 };
    488 const CRegister cr10 = { 10 };
    489 const CRegister cr11 = { 11 };
    490 const CRegister cr12 = { 12 };
    491 const CRegister cr13 = { 13 };
    492 const CRegister cr14 = { 14 };
    493 const CRegister cr15 = { 15 };
    494 
    495 
    496 // Coprocessor number
    497 enum Coprocessor {
    498   p0  = 0,
    499   p1  = 1,
    500   p2  = 2,
    501   p3  = 3,
    502   p4  = 4,
    503   p5  = 5,
    504   p6  = 6,
    505   p7  = 7,
    506   p8  = 8,
    507   p9  = 9,
    508   p10 = 10,
    509   p11 = 11,
    510   p12 = 12,
    511   p13 = 13,
    512   p14 = 14,
    513   p15 = 15
    514 };
    515 
    516 
    517 // -----------------------------------------------------------------------------
    518 // Machine instruction Operands
    519 
    520 // Class Operand represents a shifter operand in data processing instructions
    521 class Operand BASE_EMBEDDED {
    522  public:
    523   // immediate
    524   INLINE(explicit Operand(int32_t immediate,
    525          RelocInfo::Mode rmode = RelocInfo::NONE32));
    526   INLINE(static Operand Zero()) {
    527     return Operand(static_cast<int32_t>(0));
    528   }
    529   INLINE(explicit Operand(const ExternalReference& f));
    530   explicit Operand(Handle<Object> handle);
    531   INLINE(explicit Operand(Smi* value));
    532 
    533   // rm
    534   INLINE(explicit Operand(Register rm));
    535 
    536   // rm <shift_op> shift_imm
    537   explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
    538   INLINE(static Operand SmiUntag(Register rm)) {
    539     return Operand(rm, ASR, kSmiTagSize);
    540   }
    541   INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
    542     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
    543     return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
    544   }
    545   INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
    546     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
    547     return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
    548   }
    549 
    550   // rm <shift_op> rs
    551   explicit Operand(Register rm, ShiftOp shift_op, Register rs);
    552 
    553   // Return true if this is a register operand.
    554   INLINE(bool is_reg() const);
    555 
    556   // Return true if this operand fits in one instruction so that no
    557   // 2-instruction solution with a load into the ip register is necessary. If
    558   // the instruction this operand is used for is a MOV or MVN instruction the
    559   // actual instruction to use is required for this calculation. For other
    560   // instructions instr is ignored.
    561   bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const;
    562   bool must_output_reloc_info(const Assembler* assembler) const;
    563 
    564   inline int32_t immediate() const {
    565     ASSERT(!rm_.is_valid());
    566     return imm32_;
    567   }
    568 
    569   Register rm() const { return rm_; }
    570   Register rs() const { return rs_; }
    571   ShiftOp shift_op() const { return shift_op_; }
    572 
    573  private:
    574   Register rm_;
    575   Register rs_;
    576   ShiftOp shift_op_;
    577   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
    578   int32_t imm32_;  // valid if rm_ == no_reg
    579   RelocInfo::Mode rmode_;
    580 
    581   friend class Assembler;
    582 };
    583 
    584 
    585 // Class MemOperand represents a memory operand in load and store instructions
    586 class MemOperand BASE_EMBEDDED {
    587  public:
    588   // [rn +/- offset]      Offset/NegOffset
    589   // [rn +/- offset]!     PreIndex/NegPreIndex
    590   // [rn], +/- offset     PostIndex/NegPostIndex
    591   // offset is any signed 32-bit value; offset is first loaded to register ip if
    592   // it does not fit the addressing mode (12-bit unsigned and sign bit)
    593   explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
    594 
    595   // [rn +/- rm]          Offset/NegOffset
    596   // [rn +/- rm]!         PreIndex/NegPreIndex
    597   // [rn], +/- rm         PostIndex/NegPostIndex
    598   explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
    599 
    600   // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
    601   // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
    602   // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
    603   explicit MemOperand(Register rn, Register rm,
    604                       ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
    605   INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
    606                                                     Register key,
    607                                                     AddrMode am = Offset)) {
    608     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
    609     return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
    610   }
    611 
    612   void set_offset(int32_t offset) {
    613       ASSERT(rm_.is(no_reg));
    614       offset_ = offset;
    615   }
    616 
    617   uint32_t offset() const {
    618       ASSERT(rm_.is(no_reg));
    619       return offset_;
    620   }
    621 
    622   Register rn() const { return rn_; }
    623   Register rm() const { return rm_; }
    624   AddrMode am() const { return am_; }
    625 
    626   bool OffsetIsUint12Encodable() const {
    627     return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
    628   }
    629 
    630  private:
    631   Register rn_;  // base
    632   Register rm_;  // register offset
    633   int32_t offset_;  // valid if rm_ == no_reg
    634   ShiftOp shift_op_;
    635   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
    636   AddrMode am_;  // bits P, U, and W
    637 
    638   friend class Assembler;
    639 };
    640 
    641 
    642 // Class NeonMemOperand represents a memory operand in load and
    643 // store NEON instructions
    644 class NeonMemOperand BASE_EMBEDDED {
    645  public:
    646   // [rn {:align}]       Offset
    647   // [rn {:align}]!      PostIndex
    648   explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
    649 
    650   // [rn {:align}], rm   PostIndex
    651   explicit NeonMemOperand(Register rn, Register rm, int align = 0);
    652 
    653   Register rn() const { return rn_; }
    654   Register rm() const { return rm_; }
    655   int align() const { return align_; }
    656 
    657  private:
    658   void SetAlignment(int align);
    659 
    660   Register rn_;  // base
    661   Register rm_;  // register increment
    662   int align_;
    663 };
    664 
    665 
    666 // Class NeonListOperand represents a list of NEON registers
    667 class NeonListOperand BASE_EMBEDDED {
    668  public:
    669   explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
    670   DoubleRegister base() const { return base_; }
    671   NeonListType type() const { return type_; }
    672  private:
    673   DoubleRegister base_;
    674   NeonListType type_;
    675 };
    676 
    677 extern const Instr kMovLrPc;
    678 extern const Instr kLdrPCMask;
    679 extern const Instr kLdrPCPattern;
    680 extern const Instr kBlxRegMask;
    681 extern const Instr kBlxRegPattern;
    682 extern const Instr kBlxIp;
    683 
    684 extern const Instr kMovMvnMask;
    685 extern const Instr kMovMvnPattern;
    686 extern const Instr kMovMvnFlip;
    687 
    688 extern const Instr kMovLeaveCCMask;
    689 extern const Instr kMovLeaveCCPattern;
    690 extern const Instr kMovwMask;
    691 extern const Instr kMovwPattern;
    692 extern const Instr kMovwLeaveCCFlip;
    693 
    694 extern const Instr kCmpCmnMask;
    695 extern const Instr kCmpCmnPattern;
    696 extern const Instr kCmpCmnFlip;
    697 extern const Instr kAddSubFlip;
    698 extern const Instr kAndBicFlip;
    699 
    700 struct VmovIndex {
    701   unsigned char index;
    702 };
    703 const VmovIndex VmovIndexLo = { 0 };
    704 const VmovIndex VmovIndexHi = { 1 };
    705 
    706 class Assembler : public AssemblerBase {
    707  public:
    708   // Create an assembler. Instructions and relocation information are emitted
    709   // into a buffer, with the instructions starting from the beginning and the
    710   // relocation information starting from the end of the buffer. See CodeDesc
    711   // for a detailed comment on the layout (globals.h).
    712   //
    713   // If the provided buffer is NULL, the assembler allocates and grows its own
    714   // buffer, and buffer_size determines the initial buffer size. The buffer is
    715   // owned by the assembler and deallocated upon destruction of the assembler.
    716   //
    717   // If the provided buffer is not NULL, the assembler uses the provided buffer
    718   // for code generation and assumes its size to be buffer_size. If the buffer
    719   // is too small, a fatal error occurs. No deallocation of the buffer is done
    720   // upon destruction of the assembler.
    721   Assembler(Isolate* isolate, void* buffer, int buffer_size);
    722   virtual ~Assembler();
    723 
    724   // GetCode emits any pending (non-emitted) code and fills the descriptor
    725   // desc. GetCode() is idempotent; it returns the same result if no other
    726   // Assembler functions are invoked in between GetCode() calls.
    727   void GetCode(CodeDesc* desc);
    728 
    729   // Label operations & relative jumps (PPUM Appendix D)
    730   //
    731   // Takes a branch opcode (cc) and a label (L) and generates
    732   // either a backward branch or a forward branch and links it
    733   // to the label fixup chain. Usage:
    734   //
    735   // Label L;    // unbound label
    736   // j(cc, &L);  // forward branch to unbound label
    737   // bind(&L);   // bind label to the current pc
    738   // j(cc, &L);  // backward branch to bound label
    739   // bind(&L);   // illegal: a label may be bound only once
    740   //
    741   // Note: The same Label can be used for forward and backward branches
    742   // but it may be bound only once.
    743 
    744   void bind(Label* L);  // binds an unbound label L to the current code position
    745 
    746   // Returns the branch offset to the given label from the current code position
    747   // Links the label to the current position if it is still unbound
    748   // Manages the jump elimination optimization if the second parameter is true.
    749   int branch_offset(Label* L, bool jump_elimination_allowed);
    750 
    751   // Puts a labels target address at the given position.
    752   // The high 8 bits are set to zero.
    753   void label_at_put(Label* L, int at_offset);
    754 
    755   // Return the address in the constant pool of the code target address used by
    756   // the branch/call instruction at pc, or the object in a mov.
    757   INLINE(static Address target_pointer_address_at(Address pc));
    758 
    759   // Read/Modify the pointer in the branch/call/move instruction at pc.
    760   INLINE(static Address target_pointer_at(Address pc));
    761   INLINE(static void set_target_pointer_at(Address pc, Address target));
    762 
    763   // Read/Modify the code target address in the branch/call instruction at pc.
    764   INLINE(static Address target_address_at(Address pc));
    765   INLINE(static void set_target_address_at(Address pc, Address target));
    766 
    767   // Return the code target address at a call site from the return address
    768   // of that call in the instruction stream.
    769   INLINE(static Address target_address_from_return_address(Address pc));
    770 
    771   // Given the address of the beginning of a call, return the address
    772   // in the instruction stream that the call will return from.
    773   INLINE(static Address return_address_from_call_start(Address pc));
    774 
    775   // This sets the branch destination (which is in the constant pool on ARM).
    776   // This is for calls and branches within generated code.
    777   inline static void deserialization_set_special_target_at(
    778       Address constant_pool_entry, Address target);
    779 
    780   // This sets the branch destination (which is in the constant pool on ARM).
    781   // This is for calls and branches to runtime code.
    782   inline static void set_external_target_at(Address constant_pool_entry,
    783                                             Address target);
    784 
    785   // Here we are patching the address in the constant pool, not the actual call
    786   // instruction.  The address in the constant pool is the same size as a
    787   // pointer.
    788   static const int kSpecialTargetSize = kPointerSize;
    789 
    790   // Size of an instruction.
    791   static const int kInstrSize = sizeof(Instr);
    792 
    793   // Distance between start of patched return sequence and the emitted address
    794   // to jump to.
    795   // Patched return sequence is:
    796   //  ldr  ip, [pc, #0]   @ emited address and start
    797   //  blx  ip
    798   static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
    799 
    800   // Distance between start of patched debug break slot and the emitted address
    801   // to jump to.
    802   // Patched debug break slot code is:
    803   //  ldr  ip, [pc, #0]   @ emited address and start
    804   //  blx  ip
    805   static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
    806 
    807   static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
    808 
    809   // Difference between address of current opcode and value read from pc
    810   // register.
    811   static const int kPcLoadDelta = 8;
    812 
    813   static const int kJSReturnSequenceInstructions = 4;
    814   static const int kDebugBreakSlotInstructions = 3;
    815   static const int kDebugBreakSlotLength =
    816       kDebugBreakSlotInstructions * kInstrSize;
    817 
    818   // ---------------------------------------------------------------------------
    819   // Code generation
    820 
    821   // Insert the smallest number of nop instructions
    822   // possible to align the pc offset to a multiple
    823   // of m. m must be a power of 2 (>= 4).
    824   void Align(int m);
    825   // Aligns code to something that's optimal for a jump target for the platform.
    826   void CodeTargetAlign();
    827 
    828   // Branch instructions
    829   void b(int branch_offset, Condition cond = al);
    830   void bl(int branch_offset, Condition cond = al);
    831   void blx(int branch_offset);  // v5 and above
    832   void blx(Register target, Condition cond = al);  // v5 and above
    833   void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
    834 
    835   // Convenience branch instructions using labels
    836   void b(Label* L, Condition cond = al)  {
    837     b(branch_offset(L, cond == al), cond);
    838   }
    839   void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
    840   void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
    841   void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
    842   void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
    843 
    844   // Data-processing instructions
    845 
    846   void and_(Register dst, Register src1, const Operand& src2,
    847             SBit s = LeaveCC, Condition cond = al);
    848 
    849   void eor(Register dst, Register src1, const Operand& src2,
    850            SBit s = LeaveCC, Condition cond = al);
    851 
    852   void sub(Register dst, Register src1, const Operand& src2,
    853            SBit s = LeaveCC, Condition cond = al);
    854   void sub(Register dst, Register src1, Register src2,
    855            SBit s = LeaveCC, Condition cond = al) {
    856     sub(dst, src1, Operand(src2), s, cond);
    857   }
    858 
    859   void rsb(Register dst, Register src1, const Operand& src2,
    860            SBit s = LeaveCC, Condition cond = al);
    861 
    862   void add(Register dst, Register src1, const Operand& src2,
    863            SBit s = LeaveCC, Condition cond = al);
    864   void add(Register dst, Register src1, Register src2,
    865            SBit s = LeaveCC, Condition cond = al) {
    866     add(dst, src1, Operand(src2), s, cond);
    867   }
    868 
    869   void adc(Register dst, Register src1, const Operand& src2,
    870            SBit s = LeaveCC, Condition cond = al);
    871 
    872   void sbc(Register dst, Register src1, const Operand& src2,
    873            SBit s = LeaveCC, Condition cond = al);
    874 
    875   void rsc(Register dst, Register src1, const Operand& src2,
    876            SBit s = LeaveCC, Condition cond = al);
    877 
    878   void tst(Register src1, const Operand& src2, Condition cond = al);
    879   void tst(Register src1, Register src2, Condition cond = al) {
    880     tst(src1, Operand(src2), cond);
    881   }
    882 
    883   void teq(Register src1, const Operand& src2, Condition cond = al);
    884 
    885   void cmp(Register src1, const Operand& src2, Condition cond = al);
    886   void cmp(Register src1, Register src2, Condition cond = al) {
    887     cmp(src1, Operand(src2), cond);
    888   }
    889   void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
    890 
    891   void cmn(Register src1, const Operand& src2, Condition cond = al);
    892 
    893   void orr(Register dst, Register src1, const Operand& src2,
    894            SBit s = LeaveCC, Condition cond = al);
    895   void orr(Register dst, Register src1, Register src2,
    896            SBit s = LeaveCC, Condition cond = al) {
    897     orr(dst, src1, Operand(src2), s, cond);
    898   }
    899 
    900   void mov(Register dst, const Operand& src,
    901            SBit s = LeaveCC, Condition cond = al);
    902   void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
    903     mov(dst, Operand(src), s, cond);
    904   }
    905 
    906   // ARMv7 instructions for loading a 32 bit immediate in two instructions.
    907   // This may actually emit a different mov instruction, but on an ARMv7 it
    908   // is guaranteed to only emit one instruction.
    909   void movw(Register reg, uint32_t immediate, Condition cond = al);
    910   // The constant for movt should be in the range 0-0xffff.
    911   void movt(Register reg, uint32_t immediate, Condition cond = al);
    912 
    913   void bic(Register dst, Register src1, const Operand& src2,
    914            SBit s = LeaveCC, Condition cond = al);
    915 
    916   void mvn(Register dst, const Operand& src,
    917            SBit s = LeaveCC, Condition cond = al);
    918 
    919   // Multiply instructions
    920 
    921   void mla(Register dst, Register src1, Register src2, Register srcA,
    922            SBit s = LeaveCC, Condition cond = al);
    923 
    924   void mls(Register dst, Register src1, Register src2, Register srcA,
    925            Condition cond = al);
    926 
    927   void sdiv(Register dst, Register src1, Register src2,
    928             Condition cond = al);
    929 
    930   void mul(Register dst, Register src1, Register src2,
    931            SBit s = LeaveCC, Condition cond = al);
    932 
    933   void smlal(Register dstL, Register dstH, Register src1, Register src2,
    934              SBit s = LeaveCC, Condition cond = al);
    935 
    936   void smull(Register dstL, Register dstH, Register src1, Register src2,
    937              SBit s = LeaveCC, Condition cond = al);
    938 
    939   void umlal(Register dstL, Register dstH, Register src1, Register src2,
    940              SBit s = LeaveCC, Condition cond = al);
    941 
    942   void umull(Register dstL, Register dstH, Register src1, Register src2,
    943              SBit s = LeaveCC, Condition cond = al);
    944 
    945   // Miscellaneous arithmetic instructions
    946 
    947   void clz(Register dst, Register src, Condition cond = al);  // v5 and above
    948 
    949   // Saturating instructions. v6 and above.
    950 
    951   // Unsigned saturate.
    952   //
    953   // Saturate an optionally shifted signed value to an unsigned range.
    954   //
    955   //   usat dst, #satpos, src
    956   //   usat dst, #satpos, src, lsl #sh
    957   //   usat dst, #satpos, src, asr #sh
    958   //
    959   // Register dst will contain:
    960   //
    961   //   0,                 if s < 0
    962   //   (1 << satpos) - 1, if s > ((1 << satpos) - 1)
    963   //   s,                 otherwise
    964   //
    965   // where s is the contents of src after shifting (if used.)
    966   void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
    967 
    968   // Bitfield manipulation instructions. v7 and above.
    969 
    970   void ubfx(Register dst, Register src, int lsb, int width,
    971             Condition cond = al);
    972 
    973   void sbfx(Register dst, Register src, int lsb, int width,
    974             Condition cond = al);
    975 
    976   void bfc(Register dst, int lsb, int width, Condition cond = al);
    977 
    978   void bfi(Register dst, Register src, int lsb, int width,
    979            Condition cond = al);
    980 
    981   void pkhbt(Register dst, Register src1, const Operand& src2,
    982              Condition cond = al);
    983 
    984   void pkhtb(Register dst, Register src1, const Operand& src2,
    985              Condition cond = al);
    986 
    987   void uxtb(Register dst, const Operand& src, Condition cond = al);
    988 
    989   void uxtab(Register dst, Register src1, const Operand& src2,
    990              Condition cond = al);
    991 
    992   void uxtb16(Register dst, const Operand& src, Condition cond = al);
    993 
    994   // Status register access instructions
    995 
    996   void mrs(Register dst, SRegister s, Condition cond = al);
    997   void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
    998 
    999   // Load/Store instructions
   1000   void ldr(Register dst, const MemOperand& src, Condition cond = al);
   1001   void str(Register src, const MemOperand& dst, Condition cond = al);
   1002   void ldrb(Register dst, const MemOperand& src, Condition cond = al);
   1003   void strb(Register src, const MemOperand& dst, Condition cond = al);
   1004   void ldrh(Register dst, const MemOperand& src, Condition cond = al);
   1005   void strh(Register src, const MemOperand& dst, Condition cond = al);
   1006   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
   1007   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
   1008   void ldrd(Register dst1,
   1009             Register dst2,
   1010             const MemOperand& src, Condition cond = al);
   1011   void strd(Register src1,
   1012             Register src2,
   1013             const MemOperand& dst, Condition cond = al);
   1014 
   1015   // Preload instructions
   1016   void pld(const MemOperand& address);
   1017 
   1018   // Load/Store multiple instructions
   1019   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
   1020   void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
   1021 
   1022   // Exception-generating instructions and debugging support
   1023   void stop(const char* msg,
   1024             Condition cond = al,
   1025             int32_t code = kDefaultStopCode);
   1026 
   1027   void bkpt(uint32_t imm16);  // v5 and above
   1028   void svc(uint32_t imm24, Condition cond = al);
   1029 
   1030   // Coprocessor instructions
   1031 
   1032   void cdp(Coprocessor coproc, int opcode_1,
   1033            CRegister crd, CRegister crn, CRegister crm,
   1034            int opcode_2, Condition cond = al);
   1035 
   1036   void cdp2(Coprocessor coproc, int opcode_1,
   1037             CRegister crd, CRegister crn, CRegister crm,
   1038             int opcode_2);  // v5 and above
   1039 
   1040   void mcr(Coprocessor coproc, int opcode_1,
   1041            Register rd, CRegister crn, CRegister crm,
   1042            int opcode_2 = 0, Condition cond = al);
   1043 
   1044   void mcr2(Coprocessor coproc, int opcode_1,
   1045             Register rd, CRegister crn, CRegister crm,
   1046             int opcode_2 = 0);  // v5 and above
   1047 
   1048   void mrc(Coprocessor coproc, int opcode_1,
   1049            Register rd, CRegister crn, CRegister crm,
   1050            int opcode_2 = 0, Condition cond = al);
   1051 
   1052   void mrc2(Coprocessor coproc, int opcode_1,
   1053             Register rd, CRegister crn, CRegister crm,
   1054             int opcode_2 = 0);  // v5 and above
   1055 
   1056   void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
   1057            LFlag l = Short, Condition cond = al);
   1058   void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
   1059            LFlag l = Short, Condition cond = al);
   1060 
   1061   void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
   1062             LFlag l = Short);  // v5 and above
   1063   void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
   1064             LFlag l = Short);  // v5 and above
   1065 
   1066   // Support for VFP.
   1067   // All these APIs support S0 to S31 and D0 to D31.
   1068 
   1069   void vldr(const DwVfpRegister dst,
   1070             const Register base,
   1071             int offset,
   1072             const Condition cond = al);
   1073   void vldr(const DwVfpRegister dst,
   1074             const MemOperand& src,
   1075             const Condition cond = al);
   1076 
   1077   void vldr(const SwVfpRegister dst,
   1078             const Register base,
   1079             int offset,
   1080             const Condition cond = al);
   1081   void vldr(const SwVfpRegister dst,
   1082             const MemOperand& src,
   1083             const Condition cond = al);
   1084 
   1085   void vstr(const DwVfpRegister src,
   1086             const Register base,
   1087             int offset,
   1088             const Condition cond = al);
   1089   void vstr(const DwVfpRegister src,
   1090             const MemOperand& dst,
   1091             const Condition cond = al);
   1092 
   1093   void vstr(const SwVfpRegister src,
   1094             const Register base,
   1095             int offset,
   1096             const Condition cond = al);
   1097   void vstr(const SwVfpRegister src,
   1098             const MemOperand& dst,
   1099             const Condition cond = al);
   1100 
   1101   void vldm(BlockAddrMode am,
   1102             Register base,
   1103             DwVfpRegister first,
   1104             DwVfpRegister last,
   1105             Condition cond = al);
   1106 
   1107   void vstm(BlockAddrMode am,
   1108             Register base,
   1109             DwVfpRegister first,
   1110             DwVfpRegister last,
   1111             Condition cond = al);
   1112 
   1113   void vldm(BlockAddrMode am,
   1114             Register base,
   1115             SwVfpRegister first,
   1116             SwVfpRegister last,
   1117             Condition cond = al);
   1118 
   1119   void vstm(BlockAddrMode am,
   1120             Register base,
   1121             SwVfpRegister first,
   1122             SwVfpRegister last,
   1123             Condition cond = al);
   1124 
   1125   void vmov(const DwVfpRegister dst,
   1126             double imm,
   1127             const Register scratch = no_reg);
   1128   void vmov(const SwVfpRegister dst,
   1129             const SwVfpRegister src,
   1130             const Condition cond = al);
   1131   void vmov(const DwVfpRegister dst,
   1132             const DwVfpRegister src,
   1133             const Condition cond = al);
   1134   void vmov(const DwVfpRegister dst,
   1135             const VmovIndex index,
   1136             const Register src,
   1137             const Condition cond = al);
   1138   void vmov(const Register dst,
   1139             const VmovIndex index,
   1140             const DwVfpRegister src,
   1141             const Condition cond = al);
   1142   void vmov(const DwVfpRegister dst,
   1143             const Register src1,
   1144             const Register src2,
   1145             const Condition cond = al);
   1146   void vmov(const Register dst1,
   1147             const Register dst2,
   1148             const DwVfpRegister src,
   1149             const Condition cond = al);
   1150   void vmov(const SwVfpRegister dst,
   1151             const Register src,
   1152             const Condition cond = al);
   1153   void vmov(const Register dst,
   1154             const SwVfpRegister src,
   1155             const Condition cond = al);
   1156   void vcvt_f64_s32(const DwVfpRegister dst,
   1157                     const SwVfpRegister src,
   1158                     VFPConversionMode mode = kDefaultRoundToZero,
   1159                     const Condition cond = al);
   1160   void vcvt_f32_s32(const SwVfpRegister dst,
   1161                     const SwVfpRegister src,
   1162                     VFPConversionMode mode = kDefaultRoundToZero,
   1163                     const Condition cond = al);
   1164   void vcvt_f64_u32(const DwVfpRegister dst,
   1165                     const SwVfpRegister src,
   1166                     VFPConversionMode mode = kDefaultRoundToZero,
   1167                     const Condition cond = al);
   1168   void vcvt_s32_f64(const SwVfpRegister dst,
   1169                     const DwVfpRegister src,
   1170                     VFPConversionMode mode = kDefaultRoundToZero,
   1171                     const Condition cond = al);
   1172   void vcvt_u32_f64(const SwVfpRegister dst,
   1173                     const DwVfpRegister src,
   1174                     VFPConversionMode mode = kDefaultRoundToZero,
   1175                     const Condition cond = al);
   1176   void vcvt_f64_f32(const DwVfpRegister dst,
   1177                     const SwVfpRegister src,
   1178                     VFPConversionMode mode = kDefaultRoundToZero,
   1179                     const Condition cond = al);
   1180   void vcvt_f32_f64(const SwVfpRegister dst,
   1181                     const DwVfpRegister src,
   1182                     VFPConversionMode mode = kDefaultRoundToZero,
   1183                     const Condition cond = al);
   1184   void vcvt_f64_s32(const DwVfpRegister dst,
   1185                     int fraction_bits,
   1186                     const Condition cond = al);
   1187 
   1188   void vneg(const DwVfpRegister dst,
   1189             const DwVfpRegister src,
   1190             const Condition cond = al);
   1191   void vabs(const DwVfpRegister dst,
   1192             const DwVfpRegister src,
   1193             const Condition cond = al);
   1194   void vadd(const DwVfpRegister dst,
   1195             const DwVfpRegister src1,
   1196             const DwVfpRegister src2,
   1197             const Condition cond = al);
   1198   void vsub(const DwVfpRegister dst,
   1199             const DwVfpRegister src1,
   1200             const DwVfpRegister src2,
   1201             const Condition cond = al);
   1202   void vmul(const DwVfpRegister dst,
   1203             const DwVfpRegister src1,
   1204             const DwVfpRegister src2,
   1205             const Condition cond = al);
   1206   void vmla(const DwVfpRegister dst,
   1207             const DwVfpRegister src1,
   1208             const DwVfpRegister src2,
   1209             const Condition cond = al);
   1210   void vmls(const DwVfpRegister dst,
   1211             const DwVfpRegister src1,
   1212             const DwVfpRegister src2,
   1213             const Condition cond = al);
   1214   void vdiv(const DwVfpRegister dst,
   1215             const DwVfpRegister src1,
   1216             const DwVfpRegister src2,
   1217             const Condition cond = al);
   1218   void vcmp(const DwVfpRegister src1,
   1219             const DwVfpRegister src2,
   1220             const Condition cond = al);
   1221   void vcmp(const DwVfpRegister src1,
   1222             const double src2,
   1223             const Condition cond = al);
   1224   void vmrs(const Register dst,
   1225             const Condition cond = al);
   1226   void vmsr(const Register dst,
   1227             const Condition cond = al);
   1228   void vsqrt(const DwVfpRegister dst,
   1229              const DwVfpRegister src,
   1230              const Condition cond = al);
   1231 
   1232   // Support for NEON.
   1233   // All these APIs support D0 to D31 and Q0 to Q15.
   1234 
   1235   void vld1(NeonSize size,
   1236             const NeonListOperand& dst,
   1237             const NeonMemOperand& src);
   1238   void vst1(NeonSize size,
   1239             const NeonListOperand& src,
   1240             const NeonMemOperand& dst);
   1241   void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
   1242 
   1243   // Pseudo instructions
   1244 
   1245   // Different nop operations are used by the code generator to detect certain
   1246   // states of the generated code.
   1247   enum NopMarkerTypes {
   1248     NON_MARKING_NOP = 0,
   1249     DEBUG_BREAK_NOP,
   1250     // IC markers.
   1251     PROPERTY_ACCESS_INLINED,
   1252     PROPERTY_ACCESS_INLINED_CONTEXT,
   1253     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
   1254     // Helper values.
   1255     LAST_CODE_MARKER,
   1256     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
   1257   };
   1258 
   1259   void nop(int type = 0);   // 0 is the default non-marking type.
   1260 
   1261   void push(Register src, Condition cond = al) {
   1262     str(src, MemOperand(sp, 4, NegPreIndex), cond);
   1263   }
   1264 
   1265   void pop(Register dst, Condition cond = al) {
   1266     ldr(dst, MemOperand(sp, 4, PostIndex), cond);
   1267   }
   1268 
   1269   void pop() {
   1270     add(sp, sp, Operand(kPointerSize));
   1271   }
   1272 
   1273   // Jump unconditionally to given label.
   1274   void jmp(Label* L) { b(L, al); }
   1275 
   1276   static bool use_immediate_embedded_pointer_loads(
   1277       const Assembler* assembler) {
   1278     return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
   1279         (assembler == NULL || !assembler->predictable_code_size());
   1280   }
   1281 
   1282   // Check the code size generated from label to here.
   1283   int SizeOfCodeGeneratedSince(Label* label) {
   1284     return pc_offset() - label->pos();
   1285   }
   1286 
   1287   // Check the number of instructions generated from label to here.
   1288   int InstructionsGeneratedSince(Label* label) {
   1289     return SizeOfCodeGeneratedSince(label) / kInstrSize;
   1290   }
   1291 
   1292   // Check whether an immediate fits an addressing mode 1 instruction.
   1293   bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
   1294 
   1295   // Class for scoping postponing the constant pool generation.
   1296   class BlockConstPoolScope {
   1297    public:
   1298     explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
   1299       assem_->StartBlockConstPool();
   1300     }
   1301     ~BlockConstPoolScope() {
   1302       assem_->EndBlockConstPool();
   1303     }
   1304 
   1305    private:
   1306     Assembler* assem_;
   1307 
   1308     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
   1309   };
   1310 
   1311   // Debugging
   1312 
   1313   // Mark address of the ExitJSFrame code.
   1314   void RecordJSReturn();
   1315 
   1316   // Mark address of a debug break slot.
   1317   void RecordDebugBreakSlot();
   1318 
   1319   // Record the AST id of the CallIC being compiled, so that it can be placed
   1320   // in the relocation information.
   1321   void SetRecordedAstId(TypeFeedbackId ast_id) {
   1322     ASSERT(recorded_ast_id_.IsNone());
   1323     recorded_ast_id_ = ast_id;
   1324   }
   1325 
   1326   TypeFeedbackId RecordedAstId() {
   1327     ASSERT(!recorded_ast_id_.IsNone());
   1328     return recorded_ast_id_;
   1329   }
   1330 
   1331   void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
   1332 
   1333   // Record a comment relocation entry that can be used by a disassembler.
   1334   // Use --code-comments to enable.
   1335   void RecordComment(const char* msg);
   1336 
   1337   // Record the emission of a constant pool.
   1338   //
   1339   // The emission of constant pool depends on the size of the code generated and
   1340   // the number of RelocInfo recorded.
   1341   // The Debug mechanism needs to map code offsets between two versions of a
   1342   // function, compiled with and without debugger support (see for example
   1343   // Debug::PrepareForBreakPoints()).
   1344   // Compiling functions with debugger support generates additional code
   1345   // (Debug::GenerateSlot()). This may affect the emission of the constant
   1346   // pools and cause the version of the code with debugger support to have
   1347   // constant pools generated in different places.
   1348   // Recording the position and size of emitted constant pools allows to
   1349   // correctly compute the offset mappings between the different versions of a
   1350   // function in all situations.
   1351   //
   1352   // The parameter indicates the size of the constant pool (in bytes), including
   1353   // the marker and branch over the data.
   1354   void RecordConstPool(int size);
   1355 
   1356   // Writes a single byte or word of data in the code stream.  Used
   1357   // for inline tables, e.g., jump-tables. The constant pool should be
   1358   // emitted before any use of db and dd to ensure that constant pools
   1359   // are not emitted as part of the tables generated.
   1360   void db(uint8_t data);
   1361   void dd(uint32_t data);
   1362 
   1363   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
   1364 
   1365   // Read/patch instructions
   1366   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
   1367   void instr_at_put(int pos, Instr instr) {
   1368     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
   1369   }
   1370   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
   1371   static void instr_at_put(byte* pc, Instr instr) {
   1372     *reinterpret_cast<Instr*>(pc) = instr;
   1373   }
   1374   static Condition GetCondition(Instr instr);
   1375   static bool IsBranch(Instr instr);
   1376   static int GetBranchOffset(Instr instr);
   1377   static bool IsLdrRegisterImmediate(Instr instr);
   1378   static bool IsVldrDRegisterImmediate(Instr instr);
   1379   static int GetLdrRegisterImmediateOffset(Instr instr);
   1380   static int GetVldrDRegisterImmediateOffset(Instr instr);
   1381   static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
   1382   static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
   1383   static bool IsStrRegisterImmediate(Instr instr);
   1384   static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
   1385   static bool IsAddRegisterImmediate(Instr instr);
   1386   static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
   1387   static Register GetRd(Instr instr);
   1388   static Register GetRn(Instr instr);
   1389   static Register GetRm(Instr instr);
   1390   static bool IsPush(Instr instr);
   1391   static bool IsPop(Instr instr);
   1392   static bool IsStrRegFpOffset(Instr instr);
   1393   static bool IsLdrRegFpOffset(Instr instr);
   1394   static bool IsStrRegFpNegOffset(Instr instr);
   1395   static bool IsLdrRegFpNegOffset(Instr instr);
   1396   static bool IsLdrPcImmediateOffset(Instr instr);
   1397   static bool IsVldrDPcImmediateOffset(Instr instr);
   1398   static bool IsTstImmediate(Instr instr);
   1399   static bool IsCmpRegister(Instr instr);
   1400   static bool IsCmpImmediate(Instr instr);
   1401   static Register GetCmpImmediateRegister(Instr instr);
   1402   static int GetCmpImmediateRawImmediate(Instr instr);
   1403   static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
   1404   static bool IsMovT(Instr instr);
   1405   static bool IsMovW(Instr instr);
   1406 
   1407   // Constants in pools are accessed via pc relative addressing, which can
   1408   // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
   1409   // PC-relative loads, thereby defining a maximum distance between the
   1410   // instruction and the accessed constant.
   1411   static const int kMaxDistToIntPool = 4*KB;
   1412   static const int kMaxDistToFPPool = 1*KB;
   1413   // All relocations could be integer, it therefore acts as the limit.
   1414   static const int kMaxNumPendingRelocInfo = kMaxDistToIntPool/kInstrSize;
   1415 
   1416   // Postpone the generation of the constant pool for the specified number of
   1417   // instructions.
   1418   void BlockConstPoolFor(int instructions);
   1419 
   1420   // Check if is time to emit a constant pool.
   1421   void CheckConstPool(bool force_emit, bool require_jump);
   1422 
   1423  protected:
   1424   // Relocation for a type-recording IC has the AST id added to it.  This
   1425   // member variable is a way to pass the information from the call site to
   1426   // the relocation info.
   1427   TypeFeedbackId recorded_ast_id_;
   1428 
   1429   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
   1430 
   1431   // Decode branch instruction at pos and return branch target pos
   1432   int target_at(int pos);
   1433 
   1434   // Patch branch instruction at pos to branch to given branch target pos
   1435   void target_at_put(int pos, int target_pos);
   1436 
   1437   // Prevent contant pool emission until EndBlockConstPool is called.
   1438   // Call to this function can be nested but must be followed by an equal
   1439   // number of call to EndBlockConstpool.
   1440   void StartBlockConstPool() {
   1441     if (const_pool_blocked_nesting_++ == 0) {
   1442       // Prevent constant pool checks happening by setting the next check to
   1443       // the biggest possible offset.
   1444       next_buffer_check_ = kMaxInt;
   1445     }
   1446   }
   1447 
   1448   // Resume constant pool emission. Need to be called as many time as
   1449   // StartBlockConstPool to have an effect.
   1450   void EndBlockConstPool() {
   1451     if (--const_pool_blocked_nesting_ == 0) {
   1452       // Check the constant pool hasn't been blocked for too long.
   1453       ASSERT((num_pending_reloc_info_ == 0) ||
   1454              (pc_offset() < (first_const_pool_use_ + kMaxDistToIntPool)));
   1455       ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
   1456              (pc_offset() < (first_const_pool_use_ + kMaxDistToFPPool)));
   1457       // Two cases:
   1458       //  * no_const_pool_before_ >= next_buffer_check_ and the emission is
   1459       //    still blocked
   1460       //  * no_const_pool_before_ < next_buffer_check_ and the next emit will
   1461       //    trigger a check.
   1462       next_buffer_check_ = no_const_pool_before_;
   1463     }
   1464   }
   1465 
   1466   bool is_const_pool_blocked() const {
   1467     return (const_pool_blocked_nesting_ > 0) ||
   1468            (pc_offset() < no_const_pool_before_);
   1469   }
   1470 
   1471  private:
   1472   int next_buffer_check_;  // pc offset of next buffer check
   1473 
   1474   // Code generation
   1475   // The relocation writer's position is at least kGap bytes below the end of
   1476   // the generated instructions. This is so that multi-instruction sequences do
   1477   // not have to check for overflow. The same is true for writes of large
   1478   // relocation info entries.
   1479   static const int kGap = 32;
   1480 
   1481   // Constant pool generation
   1482   // Pools are emitted in the instruction stream, preferably after unconditional
   1483   // jumps or after returns from functions (in dead code locations).
   1484   // If a long code sequence does not contain unconditional jumps, it is
   1485   // necessary to emit the constant pool before the pool gets too far from the
   1486   // location it is accessed from. In this case, we emit a jump over the emitted
   1487   // constant pool.
   1488   // Constants in the pool may be addresses of functions that gets relocated;
   1489   // if so, a relocation info entry is associated to the constant pool entry.
   1490 
   1491   // Repeated checking whether the constant pool should be emitted is rather
   1492   // expensive. By default we only check again once a number of instructions
   1493   // has been generated. That also means that the sizing of the buffers is not
   1494   // an exact science, and that we rely on some slop to not overrun buffers.
   1495   static const int kCheckPoolIntervalInst = 32;
   1496   static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
   1497 
   1498 
   1499   // Emission of the constant pool may be blocked in some code sequences.
   1500   int const_pool_blocked_nesting_;  // Block emission if this is not zero.
   1501   int no_const_pool_before_;  // Block emission before this pc offset.
   1502 
   1503   // Keep track of the first instruction requiring a constant pool entry
   1504   // since the previous constant pool was emitted.
   1505   int first_const_pool_use_;
   1506 
   1507   // Relocation info generation
   1508   // Each relocation is encoded as a variable size value
   1509   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
   1510   RelocInfoWriter reloc_info_writer;
   1511 
   1512   // Relocation info records are also used during code generation as temporary
   1513   // containers for constants and code target addresses until they are emitted
   1514   // to the constant pool. These pending relocation info records are temporarily
   1515   // stored in a separate buffer until a constant pool is emitted.
   1516   // If every instruction in a long sequence is accessing the pool, we need one
   1517   // pending relocation entry per instruction.
   1518 
   1519   // the buffer of pending relocation info
   1520   RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
   1521   // number of pending reloc info entries in the buffer
   1522   int num_pending_reloc_info_;
   1523   // Number of pending reloc info entries included above which also happen to
   1524   // be 64-bit.
   1525   int num_pending_64_bit_reloc_info_;
   1526 
   1527   // The bound position, before this we cannot do instruction elimination.
   1528   int last_bound_pos_;
   1529 
   1530   // Code emission
   1531   inline void CheckBuffer();
   1532   void GrowBuffer();
   1533   inline void emit(Instr x);
   1534 
   1535   // 32-bit immediate values
   1536   void move_32_bit_immediate(Condition cond,
   1537                              Register rd,
   1538                              SBit s,
   1539                              const Operand& x);
   1540 
   1541   // Instruction generation
   1542   void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
   1543   void addrmod2(Instr instr, Register rd, const MemOperand& x);
   1544   void addrmod3(Instr instr, Register rd, const MemOperand& x);
   1545   void addrmod4(Instr instr, Register rn, RegList rl);
   1546   void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
   1547 
   1548   // Labels
   1549   void print(Label* L);
   1550   void bind_to(Label* L, int pos);
   1551   void next(Label* L);
   1552 
   1553   enum UseConstantPoolMode {
   1554     USE_CONSTANT_POOL,
   1555     DONT_USE_CONSTANT_POOL
   1556   };
   1557 
   1558   // Record reloc info for current pc_
   1559   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0,
   1560                        UseConstantPoolMode mode = USE_CONSTANT_POOL);
   1561   void RecordRelocInfo(double data);
   1562   void RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo);
   1563 
   1564   friend class RegExpMacroAssemblerARM;
   1565   friend class RelocInfo;
   1566   friend class CodePatcher;
   1567   friend class BlockConstPoolScope;
   1568 
   1569   PositionsRecorder positions_recorder_;
   1570   friend class PositionsRecorder;
   1571   friend class EnsureSpace;
   1572 };
   1573 
   1574 
   1575 class EnsureSpace BASE_EMBEDDED {
   1576  public:
   1577   explicit EnsureSpace(Assembler* assembler) {
   1578     assembler->CheckBuffer();
   1579   }
   1580 };
   1581 
   1582 
   1583 } }  // namespace v8::internal
   1584 
   1585 #endif  // V8_ARM_ASSEMBLER_ARM_H_
   1586