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 #include "src/arm/assembler-arm.h"
     38 
     39 #if V8_TARGET_ARCH_ARM
     40 
     41 #include "src/arm/assembler-arm-inl.h"
     42 #include "src/base/bits.h"
     43 #include "src/base/cpu.h"
     44 #include "src/macro-assembler.h"
     45 
     46 namespace v8 {
     47 namespace internal {
     48 
     49 static const unsigned kArmv6 = 0u;
     50 static const unsigned kArmv7 = kArmv6 | (1u << ARMv7);
     51 static const unsigned kArmv7WithSudiv = kArmv7 | (1u << ARMv7_SUDIV);
     52 static const unsigned kArmv8 = kArmv7WithSudiv | (1u << ARMv8);
     53 
     54 static unsigned CpuFeaturesFromCommandLine() {
     55   unsigned result;
     56   if (strcmp(FLAG_arm_arch, "armv8") == 0) {
     57     result = kArmv8;
     58   } else if (strcmp(FLAG_arm_arch, "armv7+sudiv") == 0) {
     59     result = kArmv7WithSudiv;
     60   } else if (strcmp(FLAG_arm_arch, "armv7") == 0) {
     61     result = kArmv7;
     62   } else if (strcmp(FLAG_arm_arch, "armv6") == 0) {
     63     result = kArmv6;
     64   } else {
     65     fprintf(stderr, "Error: unrecognised value for --arm-arch ('%s').\n",
     66             FLAG_arm_arch);
     67     fprintf(stderr,
     68             "Supported values are:  armv8\n"
     69             "                       armv7+sudiv\n"
     70             "                       armv7\n"
     71             "                       armv6\n");
     72     CHECK(false);
     73   }
     74 
     75   // If any of the old (deprecated) flags are specified, print a warning, but
     76   // otherwise try to respect them for now.
     77   // TODO(jbramley): When all the old bots have been updated, remove this.
     78   if (FLAG_enable_armv7.has_value || FLAG_enable_vfp3.has_value ||
     79       FLAG_enable_32dregs.has_value || FLAG_enable_neon.has_value ||
     80       FLAG_enable_sudiv.has_value || FLAG_enable_armv8.has_value) {
     81     // As an approximation of the old behaviour, set the default values from the
     82     // arm_arch setting, then apply the flags over the top.
     83     bool enable_armv7 = (result & (1u << ARMv7)) != 0;
     84     bool enable_vfp3 = (result & (1u << ARMv7)) != 0;
     85     bool enable_32dregs = (result & (1u << ARMv7)) != 0;
     86     bool enable_neon = (result & (1u << ARMv7)) != 0;
     87     bool enable_sudiv = (result & (1u << ARMv7_SUDIV)) != 0;
     88     bool enable_armv8 = (result & (1u << ARMv8)) != 0;
     89     if (FLAG_enable_armv7.has_value) {
     90       fprintf(stderr,
     91               "Warning: --enable_armv7 is deprecated. "
     92               "Use --arm_arch instead.\n");
     93       enable_armv7 = FLAG_enable_armv7.value;
     94     }
     95     if (FLAG_enable_vfp3.has_value) {
     96       fprintf(stderr,
     97               "Warning: --enable_vfp3 is deprecated. "
     98               "Use --arm_arch instead.\n");
     99       enable_vfp3 = FLAG_enable_vfp3.value;
    100     }
    101     if (FLAG_enable_32dregs.has_value) {
    102       fprintf(stderr,
    103               "Warning: --enable_32dregs is deprecated. "
    104               "Use --arm_arch instead.\n");
    105       enable_32dregs = FLAG_enable_32dregs.value;
    106     }
    107     if (FLAG_enable_neon.has_value) {
    108       fprintf(stderr,
    109               "Warning: --enable_neon is deprecated. "
    110               "Use --arm_arch instead.\n");
    111       enable_neon = FLAG_enable_neon.value;
    112     }
    113     if (FLAG_enable_sudiv.has_value) {
    114       fprintf(stderr,
    115               "Warning: --enable_sudiv is deprecated. "
    116               "Use --arm_arch instead.\n");
    117       enable_sudiv = FLAG_enable_sudiv.value;
    118     }
    119     if (FLAG_enable_armv8.has_value) {
    120       fprintf(stderr,
    121               "Warning: --enable_armv8 is deprecated. "
    122               "Use --arm_arch instead.\n");
    123       enable_armv8 = FLAG_enable_armv8.value;
    124     }
    125     // Emulate the old implications.
    126     if (enable_armv8) {
    127       enable_vfp3 = true;
    128       enable_neon = true;
    129       enable_32dregs = true;
    130       enable_sudiv = true;
    131     }
    132     // Select the best available configuration.
    133     if (enable_armv7 && enable_vfp3 && enable_32dregs && enable_neon) {
    134       if (enable_sudiv) {
    135         if (enable_armv8) {
    136           result = kArmv8;
    137         } else {
    138           result = kArmv7WithSudiv;
    139         }
    140       } else {
    141         result = kArmv7;
    142       }
    143     } else {
    144       result = kArmv6;
    145     }
    146   }
    147   return result;
    148 }
    149 
    150 // Get the CPU features enabled by the build.
    151 // For cross compilation the preprocessor symbols such as
    152 // CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS can be used to
    153 // enable ARMv7 and VFPv3 instructions when building the snapshot. However,
    154 // these flags should be consistent with a supported ARM configuration:
    155 //  "armv6":       ARMv6 + VFPv2
    156 //  "armv7":       ARMv7 + VFPv3-D32 + NEON
    157 //  "armv7+sudiv": ARMv7 + VFPv4-D32 + NEON + SUDIV
    158 //  "armv8":       ARMv8 (+ all of the above)
    159 static constexpr unsigned CpuFeaturesFromCompiler() {
    160 // TODO(jbramley): Once the build flags are simplified, these tests should
    161 // also be simplified.
    162 
    163 // Check *architectural* implications.
    164 #if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
    165 #error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_ARMV7_INSTRUCTIONS"
    166 #endif
    167 #if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_SUDIV)
    168 #error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_SUDIV"
    169 #endif
    170 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) != defined(CAN_USE_VFP3_INSTRUCTIONS)
    171 // V8 requires VFP, and all ARMv7 devices with VFP have VFPv3. Similarly,
    172 // VFPv3 isn't available before ARMv7.
    173 #error "CAN_USE_ARMV7_INSTRUCTIONS should match CAN_USE_VFP3_INSTRUCTIONS"
    174 #endif
    175 #if defined(CAN_USE_NEON) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
    176 #error "CAN_USE_NEON should imply CAN_USE_ARMV7_INSTRUCTIONS"
    177 #endif
    178 
    179 // Find compiler-implied features.
    180 #if defined(CAN_USE_ARMV8_INSTRUCTIONS) &&                           \
    181     defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
    182     defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
    183   return kArmv8;
    184 #elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
    185     defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
    186   return kArmv7WithSudiv;
    187 #elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_NEON) && \
    188     defined(CAN_USE_VFP3_INSTRUCTIONS)
    189   return kArmv7;
    190 #else
    191   return kArmv6;
    192 #endif
    193 }
    194 
    195 
    196 void CpuFeatures::ProbeImpl(bool cross_compile) {
    197   dcache_line_size_ = 64;
    198 
    199   unsigned command_line = CpuFeaturesFromCommandLine();
    200   // Only use statically determined features for cross compile (snapshot).
    201   if (cross_compile) {
    202     supported_ |= command_line & CpuFeaturesFromCompiler();
    203     return;
    204   }
    205 
    206 #ifndef __arm__
    207   // For the simulator build, use whatever the flags specify.
    208   supported_ |= command_line;
    209 
    210 #else  // __arm__
    211   // Probe for additional features at runtime.
    212   base::CPU cpu;
    213   // Runtime detection is slightly fuzzy, and some inferences are necessary.
    214   unsigned runtime = kArmv6;
    215   // NEON and VFPv3 imply at least ARMv7-A.
    216   if (cpu.has_neon() && cpu.has_vfp3_d32()) {
    217     DCHECK(cpu.has_vfp3());
    218     runtime |= kArmv7;
    219     if (cpu.has_idiva()) {
    220       runtime |= kArmv7WithSudiv;
    221       if (cpu.architecture() >= 8) {
    222         runtime |= kArmv8;
    223       }
    224     }
    225   }
    226 
    227   // Use the best of the features found by CPU detection and those inferred from
    228   // the build system. In both cases, restrict available features using the
    229   // command-line. Note that the command-line flags are very permissive (kArmv8)
    230   // by default.
    231   supported_ |= command_line & CpuFeaturesFromCompiler();
    232   supported_ |= command_line & runtime;
    233 
    234   // Additional tuning options.
    235 
    236   // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
    237   if (cpu.implementer() == base::CPU::ARM &&
    238       (cpu.part() == base::CPU::ARM_CORTEX_A5 ||
    239        cpu.part() == base::CPU::ARM_CORTEX_A9)) {
    240     dcache_line_size_ = 32;
    241   }
    242 #endif
    243 
    244   DCHECK_IMPLIES(IsSupported(ARMv7_SUDIV), IsSupported(ARMv7));
    245   DCHECK_IMPLIES(IsSupported(ARMv8), IsSupported(ARMv7_SUDIV));
    246 }
    247 
    248 
    249 void CpuFeatures::PrintTarget() {
    250   const char* arm_arch = NULL;
    251   const char* arm_target_type = "";
    252   const char* arm_no_probe = "";
    253   const char* arm_fpu = "";
    254   const char* arm_thumb = "";
    255   const char* arm_float_abi = NULL;
    256 
    257 #if !defined __arm__
    258   arm_target_type = " simulator";
    259 #endif
    260 
    261 #if defined ARM_TEST_NO_FEATURE_PROBE
    262   arm_no_probe = " noprobe";
    263 #endif
    264 
    265 #if defined CAN_USE_ARMV8_INSTRUCTIONS
    266   arm_arch = "arm v8";
    267 #elif defined CAN_USE_ARMV7_INSTRUCTIONS
    268   arm_arch = "arm v7";
    269 #else
    270   arm_arch = "arm v6";
    271 #endif
    272 
    273 #if defined CAN_USE_NEON
    274   arm_fpu = " neon";
    275 #elif defined CAN_USE_VFP3_INSTRUCTIONS
    276 #  if defined CAN_USE_VFP32DREGS
    277   arm_fpu = " vfp3";
    278 #  else
    279   arm_fpu = " vfp3-d16";
    280 #  endif
    281 #else
    282   arm_fpu = " vfp2";
    283 #endif
    284 
    285 #ifdef __arm__
    286   arm_float_abi = base::OS::ArmUsingHardFloat() ? "hard" : "softfp";
    287 #elif USE_EABI_HARDFLOAT
    288   arm_float_abi = "hard";
    289 #else
    290   arm_float_abi = "softfp";
    291 #endif
    292 
    293 #if defined __arm__ && (defined __thumb__) || (defined __thumb2__)
    294   arm_thumb = " thumb";
    295 #endif
    296 
    297   printf("target%s%s %s%s%s %s\n",
    298          arm_target_type, arm_no_probe, arm_arch, arm_fpu, arm_thumb,
    299          arm_float_abi);
    300 }
    301 
    302 
    303 void CpuFeatures::PrintFeatures() {
    304   printf("ARMv8=%d ARMv7=%d VFPv3=%d VFP32DREGS=%d NEON=%d SUDIV=%d",
    305          CpuFeatures::IsSupported(ARMv8), CpuFeatures::IsSupported(ARMv7),
    306          CpuFeatures::IsSupported(VFPv3), CpuFeatures::IsSupported(VFP32DREGS),
    307          CpuFeatures::IsSupported(NEON), CpuFeatures::IsSupported(SUDIV));
    308 #ifdef __arm__
    309   bool eabi_hardfloat = base::OS::ArmUsingHardFloat();
    310 #elif USE_EABI_HARDFLOAT
    311   bool eabi_hardfloat = true;
    312 #else
    313   bool eabi_hardfloat = false;
    314 #endif
    315   printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
    316 }
    317 
    318 
    319 // -----------------------------------------------------------------------------
    320 // Implementation of RelocInfo
    321 
    322 // static
    323 const int RelocInfo::kApplyMask = 0;
    324 
    325 
    326 bool RelocInfo::IsCodedSpecially() {
    327   // The deserializer needs to know whether a pointer is specially coded. Being
    328   // specially coded on ARM means that it is a movw/movt instruction, or is an
    329   // embedded constant pool entry. These only occur if
    330   // FLAG_enable_embedded_constant_pool is true.
    331   return FLAG_enable_embedded_constant_pool;
    332 }
    333 
    334 
    335 bool RelocInfo::IsInConstantPool() {
    336   return Assembler::is_constant_pool_load(pc_);
    337 }
    338 
    339 Address RelocInfo::wasm_memory_reference() {
    340   DCHECK(IsWasmMemoryReference(rmode_));
    341   return Assembler::target_address_at(pc_, host_);
    342 }
    343 
    344 uint32_t RelocInfo::wasm_memory_size_reference() {
    345   DCHECK(IsWasmMemorySizeReference(rmode_));
    346   return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
    347 }
    348 
    349 Address RelocInfo::wasm_global_reference() {
    350   DCHECK(IsWasmGlobalReference(rmode_));
    351   return Assembler::target_address_at(pc_, host_);
    352 }
    353 
    354 uint32_t RelocInfo::wasm_function_table_size_reference() {
    355   DCHECK(IsWasmFunctionTableSizeReference(rmode_));
    356   return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
    357 }
    358 
    359 void RelocInfo::unchecked_update_wasm_memory_reference(
    360     Address address, ICacheFlushMode flush_mode) {
    361   Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
    362 }
    363 
    364 void RelocInfo::unchecked_update_wasm_size(uint32_t size,
    365                                            ICacheFlushMode flush_mode) {
    366   Assembler::set_target_address_at(isolate_, pc_, host_,
    367                                    reinterpret_cast<Address>(size), flush_mode);
    368 }
    369 
    370 // -----------------------------------------------------------------------------
    371 // Implementation of Operand and MemOperand
    372 // See assembler-arm-inl.h for inlined constructors
    373 
    374 Operand::Operand(Handle<Object> handle) {
    375   AllowDeferredHandleDereference using_raw_address;
    376   rm_ = no_reg;
    377   // Verify all Objects referred by code are NOT in new space.
    378   Object* obj = *handle;
    379   if (obj->IsHeapObject()) {
    380     imm32_ = reinterpret_cast<intptr_t>(handle.location());
    381     rmode_ = RelocInfo::EMBEDDED_OBJECT;
    382   } else {
    383     // no relocation needed
    384     imm32_ = reinterpret_cast<intptr_t>(obj);
    385     rmode_ = RelocInfo::NONE32;
    386   }
    387 }
    388 
    389 
    390 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
    391   DCHECK(is_uint5(shift_imm));
    392 
    393   rm_ = rm;
    394   rs_ = no_reg;
    395   shift_op_ = shift_op;
    396   shift_imm_ = shift_imm & 31;
    397 
    398   if ((shift_op == ROR) && (shift_imm == 0)) {
    399     // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode
    400     // RRX as ROR #0 (See below).
    401     shift_op = LSL;
    402   } else if (shift_op == RRX) {
    403     // encoded as ROR with shift_imm == 0
    404     DCHECK(shift_imm == 0);
    405     shift_op_ = ROR;
    406     shift_imm_ = 0;
    407   }
    408 }
    409 
    410 
    411 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
    412   DCHECK(shift_op != RRX);
    413   rm_ = rm;
    414   rs_ = no_reg;
    415   shift_op_ = shift_op;
    416   rs_ = rs;
    417 }
    418 
    419 
    420 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
    421   rn_ = rn;
    422   rm_ = no_reg;
    423   offset_ = offset;
    424   am_ = am;
    425 
    426   // Accesses below the stack pointer are not safe, and are prohibited by the
    427   // ABI. We can check obvious violations here.
    428   if (rn.is(sp)) {
    429     if (am == Offset) DCHECK_LE(0, offset);
    430     if (am == NegOffset) DCHECK_GE(0, offset);
    431   }
    432 }
    433 
    434 
    435 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
    436   rn_ = rn;
    437   rm_ = rm;
    438   shift_op_ = LSL;
    439   shift_imm_ = 0;
    440   am_ = am;
    441 }
    442 
    443 
    444 MemOperand::MemOperand(Register rn, Register rm,
    445                        ShiftOp shift_op, int shift_imm, AddrMode am) {
    446   DCHECK(is_uint5(shift_imm));
    447   rn_ = rn;
    448   rm_ = rm;
    449   shift_op_ = shift_op;
    450   shift_imm_ = shift_imm & 31;
    451   am_ = am;
    452 }
    453 
    454 
    455 NeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) {
    456   DCHECK((am == Offset) || (am == PostIndex));
    457   rn_ = rn;
    458   rm_ = (am == Offset) ? pc : sp;
    459   SetAlignment(align);
    460 }
    461 
    462 
    463 NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) {
    464   rn_ = rn;
    465   rm_ = rm;
    466   SetAlignment(align);
    467 }
    468 
    469 
    470 void NeonMemOperand::SetAlignment(int align) {
    471   switch (align) {
    472     case 0:
    473       align_ = 0;
    474       break;
    475     case 64:
    476       align_ = 1;
    477       break;
    478     case 128:
    479       align_ = 2;
    480       break;
    481     case 256:
    482       align_ = 3;
    483       break;
    484     default:
    485       UNREACHABLE();
    486       align_ = 0;
    487       break;
    488   }
    489 }
    490 
    491 // -----------------------------------------------------------------------------
    492 // Specific instructions, constants, and masks.
    493 
    494 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
    495 // register r is not encoded.
    496 const Instr kPushRegPattern =
    497     al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16;
    498 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
    499 // register r is not encoded.
    500 const Instr kPopRegPattern =
    501     al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
    502 // ldr rd, [pc, #offset]
    503 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
    504 const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
    505 // ldr rd, [pp, #offset]
    506 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
    507 const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
    508 // ldr rd, [pp, rn]
    509 const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
    510 const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
    511 // vldr dd, [pc, #offset]
    512 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
    513 const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
    514 // vldr dd, [pp, #offset]
    515 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
    516 const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
    517 // blxcc rm
    518 const Instr kBlxRegMask =
    519     15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
    520 const Instr kBlxRegPattern =
    521     B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
    522 const Instr kBlxIp = al | kBlxRegPattern | ip.code();
    523 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
    524 const Instr kMovMvnPattern = 0xd * B21;
    525 const Instr kMovMvnFlip = B22;
    526 const Instr kMovLeaveCCMask = 0xdff * B16;
    527 const Instr kMovLeaveCCPattern = 0x1a0 * B16;
    528 const Instr kMovwPattern = 0x30 * B20;
    529 const Instr kMovtPattern = 0x34 * B20;
    530 const Instr kMovwLeaveCCFlip = 0x5 * B21;
    531 const Instr kMovImmedMask = 0x7f * B21;
    532 const Instr kMovImmedPattern = 0x1d * B21;
    533 const Instr kOrrImmedMask = 0x7f * B21;
    534 const Instr kOrrImmedPattern = 0x1c * B21;
    535 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
    536 const Instr kCmpCmnPattern = 0x15 * B20;
    537 const Instr kCmpCmnFlip = B21;
    538 const Instr kAddSubFlip = 0x6 * B21;
    539 const Instr kAndBicFlip = 0xe * B21;
    540 
    541 // A mask for the Rd register for push, pop, ldr, str instructions.
    542 const Instr kLdrRegFpOffsetPattern =
    543     al | B26 | L | Offset | Register::kCode_fp * B16;
    544 const Instr kStrRegFpOffsetPattern =
    545     al | B26 | Offset | Register::kCode_fp * B16;
    546 const Instr kLdrRegFpNegOffsetPattern =
    547     al | B26 | L | NegOffset | Register::kCode_fp * B16;
    548 const Instr kStrRegFpNegOffsetPattern =
    549     al | B26 | NegOffset | Register::kCode_fp * B16;
    550 const Instr kLdrStrInstrTypeMask = 0xffff0000;
    551 
    552 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
    553     : AssemblerBase(isolate, buffer, buffer_size),
    554       recorded_ast_id_(TypeFeedbackId::None()),
    555       pending_32_bit_constants_(),
    556       pending_64_bit_constants_(),
    557       constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits) {
    558   pending_32_bit_constants_.reserve(kMinNumPendingConstants);
    559   pending_64_bit_constants_.reserve(kMinNumPendingConstants);
    560   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
    561   next_buffer_check_ = 0;
    562   const_pool_blocked_nesting_ = 0;
    563   no_const_pool_before_ = 0;
    564   first_const_pool_32_use_ = -1;
    565   first_const_pool_64_use_ = -1;
    566   last_bound_pos_ = 0;
    567   ClearRecordedAstId();
    568   if (CpuFeatures::IsSupported(VFP32DREGS)) {
    569     // Register objects tend to be abstracted and survive between scopes, so
    570     // it's awkward to use CpuFeatures::VFP32DREGS with CpuFeatureScope. To make
    571     // its use consistent with other features, we always enable it if we can.
    572     EnableCpuFeature(VFP32DREGS);
    573   }
    574 }
    575 
    576 
    577 Assembler::~Assembler() {
    578   DCHECK(const_pool_blocked_nesting_ == 0);
    579 }
    580 
    581 
    582 void Assembler::GetCode(CodeDesc* desc) {
    583   // Emit constant pool if necessary.
    584   int constant_pool_offset = 0;
    585   if (FLAG_enable_embedded_constant_pool) {
    586     constant_pool_offset = EmitEmbeddedConstantPool();
    587   } else {
    588     CheckConstPool(true, false);
    589     DCHECK(pending_32_bit_constants_.empty());
    590     DCHECK(pending_64_bit_constants_.empty());
    591   }
    592   // Set up code descriptor.
    593   desc->buffer = buffer_;
    594   desc->buffer_size = buffer_size_;
    595   desc->instr_size = pc_offset();
    596   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
    597   desc->constant_pool_size =
    598       (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
    599   desc->origin = this;
    600   desc->unwinding_info_size = 0;
    601   desc->unwinding_info = nullptr;
    602 }
    603 
    604 
    605 void Assembler::Align(int m) {
    606   DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
    607   DCHECK((pc_offset() & (kInstrSize - 1)) == 0);
    608   while ((pc_offset() & (m - 1)) != 0) {
    609     nop();
    610   }
    611 }
    612 
    613 
    614 void Assembler::CodeTargetAlign() {
    615   // Preferred alignment of jump targets on some ARM chips.
    616   Align(8);
    617 }
    618 
    619 
    620 Condition Assembler::GetCondition(Instr instr) {
    621   return Instruction::ConditionField(instr);
    622 }
    623 
    624 
    625 bool Assembler::IsBranch(Instr instr) {
    626   return (instr & (B27 | B25)) == (B27 | B25);
    627 }
    628 
    629 
    630 int Assembler::GetBranchOffset(Instr instr) {
    631   DCHECK(IsBranch(instr));
    632   // Take the jump offset in the lower 24 bits, sign extend it and multiply it
    633   // with 4 to get the offset in bytes.
    634   return ((instr & kImm24Mask) << 8) >> 6;
    635 }
    636 
    637 
    638 bool Assembler::IsLdrRegisterImmediate(Instr instr) {
    639   return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
    640 }
    641 
    642 
    643 bool Assembler::IsVldrDRegisterImmediate(Instr instr) {
    644   return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
    645 }
    646 
    647 
    648 int Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
    649   DCHECK(IsLdrRegisterImmediate(instr));
    650   bool positive = (instr & B23) == B23;
    651   int offset = instr & kOff12Mask;  // Zero extended offset.
    652   return positive ? offset : -offset;
    653 }
    654 
    655 
    656 int Assembler::GetVldrDRegisterImmediateOffset(Instr instr) {
    657   DCHECK(IsVldrDRegisterImmediate(instr));
    658   bool positive = (instr & B23) == B23;
    659   int offset = instr & kOff8Mask;  // Zero extended offset.
    660   offset <<= 2;
    661   return positive ? offset : -offset;
    662 }
    663 
    664 
    665 Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
    666   DCHECK(IsLdrRegisterImmediate(instr));
    667   bool positive = offset >= 0;
    668   if (!positive) offset = -offset;
    669   DCHECK(is_uint12(offset));
    670   // Set bit indicating whether the offset should be added.
    671   instr = (instr & ~B23) | (positive ? B23 : 0);
    672   // Set the actual offset.
    673   return (instr & ~kOff12Mask) | offset;
    674 }
    675 
    676 
    677 Instr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) {
    678   DCHECK(IsVldrDRegisterImmediate(instr));
    679   DCHECK((offset & ~3) == offset);  // Must be 64-bit aligned.
    680   bool positive = offset >= 0;
    681   if (!positive) offset = -offset;
    682   DCHECK(is_uint10(offset));
    683   // Set bit indicating whether the offset should be added.
    684   instr = (instr & ~B23) | (positive ? B23 : 0);
    685   // Set the actual offset. Its bottom 2 bits are zero.
    686   return (instr & ~kOff8Mask) | (offset >> 2);
    687 }
    688 
    689 
    690 bool Assembler::IsStrRegisterImmediate(Instr instr) {
    691   return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
    692 }
    693 
    694 
    695 Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
    696   DCHECK(IsStrRegisterImmediate(instr));
    697   bool positive = offset >= 0;
    698   if (!positive) offset = -offset;
    699   DCHECK(is_uint12(offset));
    700   // Set bit indicating whether the offset should be added.
    701   instr = (instr & ~B23) | (positive ? B23 : 0);
    702   // Set the actual offset.
    703   return (instr & ~kOff12Mask) | offset;
    704 }
    705 
    706 
    707 bool Assembler::IsAddRegisterImmediate(Instr instr) {
    708   return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
    709 }
    710 
    711 
    712 Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
    713   DCHECK(IsAddRegisterImmediate(instr));
    714   DCHECK(offset >= 0);
    715   DCHECK(is_uint12(offset));
    716   // Set the offset.
    717   return (instr & ~kOff12Mask) | offset;
    718 }
    719 
    720 
    721 Register Assembler::GetRd(Instr instr) {
    722   Register reg;
    723   reg.reg_code = Instruction::RdValue(instr);
    724   return reg;
    725 }
    726 
    727 
    728 Register Assembler::GetRn(Instr instr) {
    729   Register reg;
    730   reg.reg_code = Instruction::RnValue(instr);
    731   return reg;
    732 }
    733 
    734 
    735 Register Assembler::GetRm(Instr instr) {
    736   Register reg;
    737   reg.reg_code = Instruction::RmValue(instr);
    738   return reg;
    739 }
    740 
    741 
    742 Instr Assembler::GetConsantPoolLoadPattern() {
    743   if (FLAG_enable_embedded_constant_pool) {
    744     return kLdrPpImmedPattern;
    745   } else {
    746     return kLdrPCImmedPattern;
    747   }
    748 }
    749 
    750 
    751 Instr Assembler::GetConsantPoolLoadMask() {
    752   if (FLAG_enable_embedded_constant_pool) {
    753     return kLdrPpImmedMask;
    754   } else {
    755     return kLdrPCImmedMask;
    756   }
    757 }
    758 
    759 
    760 bool Assembler::IsPush(Instr instr) {
    761   return ((instr & ~kRdMask) == kPushRegPattern);
    762 }
    763 
    764 
    765 bool Assembler::IsPop(Instr instr) {
    766   return ((instr & ~kRdMask) == kPopRegPattern);
    767 }
    768 
    769 
    770 bool Assembler::IsStrRegFpOffset(Instr instr) {
    771   return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
    772 }
    773 
    774 
    775 bool Assembler::IsLdrRegFpOffset(Instr instr) {
    776   return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
    777 }
    778 
    779 
    780 bool Assembler::IsStrRegFpNegOffset(Instr instr) {
    781   return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
    782 }
    783 
    784 
    785 bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
    786   return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
    787 }
    788 
    789 
    790 bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
    791   // Check the instruction is indeed a
    792   // ldr<cond> <Rd>, [pc +/- offset_12].
    793   return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern;
    794 }
    795 
    796 
    797 bool Assembler::IsLdrPpImmediateOffset(Instr instr) {
    798   // Check the instruction is indeed a
    799   // ldr<cond> <Rd>, [pp +/- offset_12].
    800   return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern;
    801 }
    802 
    803 
    804 bool Assembler::IsLdrPpRegOffset(Instr instr) {
    805   // Check the instruction is indeed a
    806   // ldr<cond> <Rd>, [pp, +/- <Rm>].
    807   return (instr & kLdrPpRegMask) == kLdrPpRegPattern;
    808 }
    809 
    810 
    811 Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; }
    812 
    813 
    814 bool Assembler::IsVldrDPcImmediateOffset(Instr instr) {
    815   // Check the instruction is indeed a
    816   // vldr<cond> <Dd>, [pc +/- offset_10].
    817   return (instr & kVldrDPCMask) == kVldrDPCPattern;
    818 }
    819 
    820 
    821 bool Assembler::IsVldrDPpImmediateOffset(Instr instr) {
    822   // Check the instruction is indeed a
    823   // vldr<cond> <Dd>, [pp +/- offset_10].
    824   return (instr & kVldrDPpMask) == kVldrDPpPattern;
    825 }
    826 
    827 
    828 bool Assembler::IsBlxReg(Instr instr) {
    829   // Check the instruction is indeed a
    830   // blxcc <Rm>
    831   return (instr & kBlxRegMask) == kBlxRegPattern;
    832 }
    833 
    834 
    835 bool Assembler::IsBlxIp(Instr instr) {
    836   // Check the instruction is indeed a
    837   // blx ip
    838   return instr == kBlxIp;
    839 }
    840 
    841 
    842 bool Assembler::IsTstImmediate(Instr instr) {
    843   return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
    844       (I | TST | S);
    845 }
    846 
    847 
    848 bool Assembler::IsCmpRegister(Instr instr) {
    849   return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
    850       (CMP | S);
    851 }
    852 
    853 
    854 bool Assembler::IsCmpImmediate(Instr instr) {
    855   return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
    856       (I | CMP | S);
    857 }
    858 
    859 
    860 Register Assembler::GetCmpImmediateRegister(Instr instr) {
    861   DCHECK(IsCmpImmediate(instr));
    862   return GetRn(instr);
    863 }
    864 
    865 
    866 int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
    867   DCHECK(IsCmpImmediate(instr));
    868   return instr & kOff12Mask;
    869 }
    870 
    871 
    872 // Labels refer to positions in the (to be) generated code.
    873 // There are bound, linked, and unused labels.
    874 //
    875 // Bound labels refer to known positions in the already
    876 // generated code. pos() is the position the label refers to.
    877 //
    878 // Linked labels refer to unknown positions in the code
    879 // to be generated; pos() is the position of the last
    880 // instruction using the label.
    881 //
    882 // The linked labels form a link chain by making the branch offset
    883 // in the instruction steam to point to the previous branch
    884 // instruction using the same label.
    885 //
    886 // The link chain is terminated by a branch offset pointing to the
    887 // same position.
    888 
    889 
    890 int Assembler::target_at(int pos) {
    891   Instr instr = instr_at(pos);
    892   if (is_uint24(instr)) {
    893     // Emitted link to a label, not part of a branch.
    894     return instr;
    895   }
    896   DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
    897   int imm26 = ((instr & kImm24Mask) << 8) >> 6;
    898   if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
    899       ((instr & B24) != 0)) {
    900     // blx uses bit 24 to encode bit 2 of imm26
    901     imm26 += 2;
    902   }
    903   return pos + kPcLoadDelta + imm26;
    904 }
    905 
    906 
    907 void Assembler::target_at_put(int pos, int target_pos) {
    908   Instr instr = instr_at(pos);
    909   if (is_uint24(instr)) {
    910     DCHECK(target_pos == pos || target_pos >= 0);
    911     // Emitted link to a label, not part of a branch.
    912     // Load the position of the label relative to the generated code object
    913     // pointer in a register.
    914 
    915     // The existing code must be a single 24-bit label chain link, followed by
    916     // nops encoding the destination register. See mov_label_offset.
    917 
    918     // Extract the destination register from the first nop instructions.
    919     Register dst =
    920         Register::from_code(Instruction::RmValue(instr_at(pos + kInstrSize)));
    921     // In addition to the 24-bit label chain link, we expect to find one nop for
    922     // ARMv7 and above, or two nops for ARMv6. See mov_label_offset.
    923     DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
    924     if (!CpuFeatures::IsSupported(ARMv7)) {
    925       DCHECK(IsNop(instr_at(pos + 2 * kInstrSize), dst.code()));
    926     }
    927 
    928     // Here are the instructions we need to emit:
    929     //   For ARMv7: target24 => target16_1:target16_0
    930     //      movw dst, #target16_0
    931     //      movt dst, #target16_1
    932     //   For ARMv6: target24 => target8_2:target8_1:target8_0
    933     //      mov dst, #target8_0
    934     //      orr dst, dst, #target8_1 << 8
    935     //      orr dst, dst, #target8_2 << 16
    936 
    937     uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
    938     DCHECK(is_uint24(target24));
    939     if (is_uint8(target24)) {
    940       // If the target fits in a byte then only patch with a mov
    941       // instruction.
    942       CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 1,
    943                           CodePatcher::DONT_FLUSH);
    944       patcher.masm()->mov(dst, Operand(target24));
    945     } else {
    946       uint16_t target16_0 = target24 & kImm16Mask;
    947       uint16_t target16_1 = target24 >> 16;
    948       if (CpuFeatures::IsSupported(ARMv7)) {
    949         // Patch with movw/movt.
    950         if (target16_1 == 0) {
    951           CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
    952                               1, CodePatcher::DONT_FLUSH);
    953           CpuFeatureScope scope(patcher.masm(), ARMv7);
    954           patcher.masm()->movw(dst, target16_0);
    955         } else {
    956           CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
    957                               2, CodePatcher::DONT_FLUSH);
    958           CpuFeatureScope scope(patcher.masm(), ARMv7);
    959           patcher.masm()->movw(dst, target16_0);
    960           patcher.masm()->movt(dst, target16_1);
    961         }
    962       } else {
    963         // Patch with a sequence of mov/orr/orr instructions.
    964         uint8_t target8_0 = target16_0 & kImm8Mask;
    965         uint8_t target8_1 = target16_0 >> 8;
    966         uint8_t target8_2 = target16_1 & kImm8Mask;
    967         if (target8_2 == 0) {
    968           CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
    969                               2, CodePatcher::DONT_FLUSH);
    970           patcher.masm()->mov(dst, Operand(target8_0));
    971           patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
    972         } else {
    973           CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
    974                               3, CodePatcher::DONT_FLUSH);
    975           patcher.masm()->mov(dst, Operand(target8_0));
    976           patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
    977           patcher.masm()->orr(dst, dst, Operand(target8_2 << 16));
    978         }
    979       }
    980     }
    981     return;
    982   }
    983   int imm26 = target_pos - (pos + kPcLoadDelta);
    984   DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
    985   if (Instruction::ConditionField(instr) == kSpecialCondition) {
    986     // blx uses bit 24 to encode bit 2 of imm26
    987     DCHECK_EQ(0, imm26 & 1);
    988     instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1) * B24;
    989   } else {
    990     DCHECK_EQ(0, imm26 & 3);
    991     instr &= ~kImm24Mask;
    992   }
    993   int imm24 = imm26 >> 2;
    994   DCHECK(is_int24(imm24));
    995   instr_at_put(pos, instr | (imm24 & kImm24Mask));
    996 }
    997 
    998 
    999 void Assembler::print(Label* L) {
   1000   if (L->is_unused()) {
   1001     PrintF("unused label\n");
   1002   } else if (L->is_bound()) {
   1003     PrintF("bound label to %d\n", L->pos());
   1004   } else if (L->is_linked()) {
   1005     Label l = *L;
   1006     PrintF("unbound label");
   1007     while (l.is_linked()) {
   1008       PrintF("@ %d ", l.pos());
   1009       Instr instr = instr_at(l.pos());
   1010       if ((instr & ~kImm24Mask) == 0) {
   1011         PrintF("value\n");
   1012       } else {
   1013         DCHECK((instr & 7*B25) == 5*B25);  // b, bl, or blx
   1014         Condition cond = Instruction::ConditionField(instr);
   1015         const char* b;
   1016         const char* c;
   1017         if (cond == kSpecialCondition) {
   1018           b = "blx";
   1019           c = "";
   1020         } else {
   1021           if ((instr & B24) != 0)
   1022             b = "bl";
   1023           else
   1024             b = "b";
   1025 
   1026           switch (cond) {
   1027             case eq: c = "eq"; break;
   1028             case ne: c = "ne"; break;
   1029             case hs: c = "hs"; break;
   1030             case lo: c = "lo"; break;
   1031             case mi: c = "mi"; break;
   1032             case pl: c = "pl"; break;
   1033             case vs: c = "vs"; break;
   1034             case vc: c = "vc"; break;
   1035             case hi: c = "hi"; break;
   1036             case ls: c = "ls"; break;
   1037             case ge: c = "ge"; break;
   1038             case lt: c = "lt"; break;
   1039             case gt: c = "gt"; break;
   1040             case le: c = "le"; break;
   1041             case al: c = ""; break;
   1042             default:
   1043               c = "";
   1044               UNREACHABLE();
   1045           }
   1046         }
   1047         PrintF("%s%s\n", b, c);
   1048       }
   1049       next(&l);
   1050     }
   1051   } else {
   1052     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
   1053   }
   1054 }
   1055 
   1056 
   1057 void Assembler::bind_to(Label* L, int pos) {
   1058   DCHECK(0 <= pos && pos <= pc_offset());  // must have a valid binding position
   1059   while (L->is_linked()) {
   1060     int fixup_pos = L->pos();
   1061     next(L);  // call next before overwriting link with target at fixup_pos
   1062     target_at_put(fixup_pos, pos);
   1063   }
   1064   L->bind_to(pos);
   1065 
   1066   // Keep track of the last bound label so we don't eliminate any instructions
   1067   // before a bound label.
   1068   if (pos > last_bound_pos_)
   1069     last_bound_pos_ = pos;
   1070 }
   1071 
   1072 
   1073 void Assembler::bind(Label* L) {
   1074   DCHECK(!L->is_bound());  // label can only be bound once
   1075   bind_to(L, pc_offset());
   1076 }
   1077 
   1078 
   1079 void Assembler::next(Label* L) {
   1080   DCHECK(L->is_linked());
   1081   int link = target_at(L->pos());
   1082   if (link == L->pos()) {
   1083     // Branch target points to the same instuction. This is the end of the link
   1084     // chain.
   1085     L->Unuse();
   1086   } else {
   1087     DCHECK(link >= 0);
   1088     L->link_to(link);
   1089   }
   1090 }
   1091 
   1092 
   1093 // Low-level code emission routines depending on the addressing mode.
   1094 // If this returns true then you have to use the rotate_imm and immed_8
   1095 // that it returns, because it may have already changed the instruction
   1096 // to match them!
   1097 static bool fits_shifter(uint32_t imm32,
   1098                          uint32_t* rotate_imm,
   1099                          uint32_t* immed_8,
   1100                          Instr* instr) {
   1101   // imm32 must be unsigned.
   1102   for (int rot = 0; rot < 16; rot++) {
   1103     uint32_t imm8 = base::bits::RotateLeft32(imm32, 2 * rot);
   1104     if ((imm8 <= 0xff)) {
   1105       *rotate_imm = rot;
   1106       *immed_8 = imm8;
   1107       return true;
   1108     }
   1109   }
   1110   // If the opcode is one with a complementary version and the complementary
   1111   // immediate fits, change the opcode.
   1112   if (instr != NULL) {
   1113     if ((*instr & kMovMvnMask) == kMovMvnPattern) {
   1114       if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
   1115         *instr ^= kMovMvnFlip;
   1116         return true;
   1117       } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
   1118         if (CpuFeatures::IsSupported(ARMv7)) {
   1119           if (imm32 < 0x10000) {
   1120             *instr ^= kMovwLeaveCCFlip;
   1121             *instr |= Assembler::EncodeMovwImmediate(imm32);
   1122             *rotate_imm = *immed_8 = 0;  // Not used for movw.
   1123             return true;
   1124           }
   1125         }
   1126       }
   1127     } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
   1128       if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
   1129         *instr ^= kCmpCmnFlip;
   1130         return true;
   1131       }
   1132     } else {
   1133       Instr alu_insn = (*instr & kALUMask);
   1134       if (alu_insn == ADD ||
   1135           alu_insn == SUB) {
   1136         if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
   1137           *instr ^= kAddSubFlip;
   1138           return true;
   1139         }
   1140       } else if (alu_insn == AND ||
   1141                  alu_insn == BIC) {
   1142         if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
   1143           *instr ^= kAndBicFlip;
   1144           return true;
   1145         }
   1146       }
   1147     }
   1148   }
   1149   return false;
   1150 }
   1151 
   1152 
   1153 // We have to use the temporary register for things that can be relocated even
   1154 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction
   1155 // space.  There is no guarantee that the relocated location can be similarly
   1156 // encoded.
   1157 bool Operand::must_output_reloc_info(const Assembler* assembler) const {
   1158   if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
   1159     if (assembler != NULL && assembler->predictable_code_size()) return true;
   1160     return assembler->serializer_enabled();
   1161   } else if (RelocInfo::IsNone(rmode_)) {
   1162     return false;
   1163   }
   1164   return true;
   1165 }
   1166 
   1167 
   1168 static bool use_mov_immediate_load(const Operand& x,
   1169                                    const Assembler* assembler) {
   1170   DCHECK(assembler != nullptr);
   1171   if (FLAG_enable_embedded_constant_pool &&
   1172       !assembler->is_constant_pool_available()) {
   1173     return true;
   1174   } else if (x.must_output_reloc_info(assembler)) {
   1175     // Prefer constant pool if data is likely to be patched.
   1176     return false;
   1177   } else {
   1178     // Otherwise, use immediate load if movw / movt is available.
   1179     return CpuFeatures::IsSupported(ARMv7);
   1180   }
   1181 }
   1182 
   1183 
   1184 int Operand::instructions_required(const Assembler* assembler,
   1185                                    Instr instr) const {
   1186   DCHECK(assembler != nullptr);
   1187   if (rm_.is_valid()) return 1;
   1188   uint32_t dummy1, dummy2;
   1189   if (must_output_reloc_info(assembler) ||
   1190       !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
   1191     // The immediate operand cannot be encoded as a shifter operand, or use of
   1192     // constant pool is required.  First account for the instructions required
   1193     // for the constant pool or immediate load
   1194     int instructions;
   1195     if (use_mov_immediate_load(*this, assembler)) {
   1196       // A movw / movt or mov / orr immediate load.
   1197       instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
   1198     } else if (assembler->ConstantPoolAccessIsInOverflow()) {
   1199       // An overflowed constant pool load.
   1200       instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
   1201     } else {
   1202       // A small constant pool load.
   1203       instructions = 1;
   1204     }
   1205 
   1206     if ((instr & ~kCondMask) != 13 * B21) {  // mov, S not set
   1207       // For a mov or mvn instruction which doesn't set the condition
   1208       // code, the constant pool or immediate load is enough, otherwise we need
   1209       // to account for the actual instruction being requested.
   1210       instructions += 1;
   1211     }
   1212     return instructions;
   1213   } else {
   1214     // No use of constant pool and the immediate operand can be encoded as a
   1215     // shifter operand.
   1216     return 1;
   1217   }
   1218 }
   1219 
   1220 
   1221 void Assembler::move_32_bit_immediate(Register rd,
   1222                                       const Operand& x,
   1223                                       Condition cond) {
   1224   uint32_t imm32 = static_cast<uint32_t>(x.imm32_);
   1225   if (x.must_output_reloc_info(this)) {
   1226     RecordRelocInfo(x.rmode_);
   1227   }
   1228 
   1229   if (use_mov_immediate_load(x, this)) {
   1230     Register target = rd.code() == pc.code() ? ip : rd;
   1231     if (CpuFeatures::IsSupported(ARMv7)) {
   1232       CpuFeatureScope scope(this, ARMv7);
   1233       if (!FLAG_enable_embedded_constant_pool &&
   1234           x.must_output_reloc_info(this)) {
   1235         // Make sure the movw/movt doesn't get separated.
   1236         BlockConstPoolFor(2);
   1237       }
   1238       movw(target, imm32 & 0xffff, cond);
   1239       movt(target, imm32 >> 16, cond);
   1240     } else {
   1241       DCHECK(FLAG_enable_embedded_constant_pool);
   1242       mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
   1243       orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
   1244       orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
   1245       orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond);
   1246     }
   1247     if (target.code() != rd.code()) {
   1248       mov(rd, target, LeaveCC, cond);
   1249     }
   1250   } else {
   1251     DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available());
   1252     ConstantPoolEntry::Access access =
   1253         ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_);
   1254     if (access == ConstantPoolEntry::OVERFLOWED) {
   1255       DCHECK(FLAG_enable_embedded_constant_pool);
   1256       Register target = rd.code() == pc.code() ? ip : rd;
   1257       // Emit instructions to load constant pool offset.
   1258       if (CpuFeatures::IsSupported(ARMv7)) {
   1259         CpuFeatureScope scope(this, ARMv7);
   1260         movw(target, 0, cond);
   1261         movt(target, 0, cond);
   1262       } else {
   1263         mov(target, Operand(0), LeaveCC, cond);
   1264         orr(target, target, Operand(0), LeaveCC, cond);
   1265         orr(target, target, Operand(0), LeaveCC, cond);
   1266         orr(target, target, Operand(0), LeaveCC, cond);
   1267       }
   1268       // Load from constant pool at offset.
   1269       ldr(rd, MemOperand(pp, target), cond);
   1270     } else {
   1271       DCHECK(access == ConstantPoolEntry::REGULAR);
   1272       ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0),
   1273           cond);
   1274     }
   1275   }
   1276 }
   1277 
   1278 
   1279 void Assembler::addrmod1(Instr instr,
   1280                          Register rn,
   1281                          Register rd,
   1282                          const Operand& x) {
   1283   CheckBuffer();
   1284   DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
   1285   if (!x.rm_.is_valid()) {
   1286     // Immediate.
   1287     uint32_t rotate_imm;
   1288     uint32_t immed_8;
   1289     if (x.must_output_reloc_info(this) ||
   1290         !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
   1291       // The immediate operand cannot be encoded as a shifter operand, so load
   1292       // it first to register ip and change the original instruction to use ip.
   1293       // However, if the original instruction is a 'mov rd, x' (not setting the
   1294       // condition code), then replace it with a 'ldr rd, [pc]'.
   1295       CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
   1296       Condition cond = Instruction::ConditionField(instr);
   1297       if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
   1298         move_32_bit_immediate(rd, x, cond);
   1299       } else {
   1300         mov(ip, x, LeaveCC, cond);
   1301         addrmod1(instr, rn, rd, Operand(ip));
   1302       }
   1303       return;
   1304     }
   1305     instr |= I | rotate_imm*B8 | immed_8;
   1306   } else if (!x.rs_.is_valid()) {
   1307     // Immediate shift.
   1308     instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
   1309   } else {
   1310     // Register shift.
   1311     DCHECK(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
   1312     instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
   1313   }
   1314   emit(instr | rn.code()*B16 | rd.code()*B12);
   1315   if (rn.is(pc) || x.rm_.is(pc)) {
   1316     // Block constant pool emission for one instruction after reading pc.
   1317     BlockConstPoolFor(1);
   1318   }
   1319 }
   1320 
   1321 
   1322 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
   1323   DCHECK((instr & ~(kCondMask | B | L)) == B26);
   1324   int am = x.am_;
   1325   if (!x.rm_.is_valid()) {
   1326     // Immediate offset.
   1327     int offset_12 = x.offset_;
   1328     if (offset_12 < 0) {
   1329       offset_12 = -offset_12;
   1330       am ^= U;
   1331     }
   1332     if (!is_uint12(offset_12)) {
   1333       // Immediate offset cannot be encoded, load it first to register ip
   1334       // rn (and rd in a load) should never be ip, or will be trashed.
   1335       DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
   1336       mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
   1337       addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
   1338       return;
   1339     }
   1340     DCHECK(offset_12 >= 0);  // no masking needed
   1341     instr |= offset_12;
   1342   } else {
   1343     // Register offset (shift_imm_ and shift_op_ are 0) or scaled
   1344     // register offset the constructors make sure than both shift_imm_
   1345     // and shift_op_ are initialized.
   1346     DCHECK(!x.rm_.is(pc));
   1347     instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
   1348   }
   1349   DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
   1350   emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
   1351 }
   1352 
   1353 
   1354 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
   1355   DCHECK((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
   1356   DCHECK(x.rn_.is_valid());
   1357   int am = x.am_;
   1358   if (!x.rm_.is_valid()) {
   1359     // Immediate offset.
   1360     int offset_8 = x.offset_;
   1361     if (offset_8 < 0) {
   1362       offset_8 = -offset_8;
   1363       am ^= U;
   1364     }
   1365     if (!is_uint8(offset_8)) {
   1366       // Immediate offset cannot be encoded, load it first to register ip
   1367       // rn (and rd in a load) should never be ip, or will be trashed.
   1368       DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
   1369       mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
   1370       addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
   1371       return;
   1372     }
   1373     DCHECK(offset_8 >= 0);  // no masking needed
   1374     instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
   1375   } else if (x.shift_imm_ != 0) {
   1376     // Scaled register offset not supported, load index first
   1377     // rn (and rd in a load) should never be ip, or will be trashed.
   1378     DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
   1379     mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
   1380         Instruction::ConditionField(instr));
   1381     addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
   1382     return;
   1383   } else {
   1384     // Register offset.
   1385     DCHECK((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
   1386     instr |= x.rm_.code();
   1387   }
   1388   DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
   1389   emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
   1390 }
   1391 
   1392 
   1393 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
   1394   DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
   1395   DCHECK(rl != 0);
   1396   DCHECK(!rn.is(pc));
   1397   emit(instr | rn.code()*B16 | rl);
   1398 }
   1399 
   1400 
   1401 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
   1402   // Unindexed addressing is not encoded by this function.
   1403   DCHECK_EQ((B27 | B26),
   1404             (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
   1405   DCHECK(x.rn_.is_valid() && !x.rm_.is_valid());
   1406   int am = x.am_;
   1407   int offset_8 = x.offset_;
   1408   DCHECK((offset_8 & 3) == 0);  // offset must be an aligned word offset
   1409   offset_8 >>= 2;
   1410   if (offset_8 < 0) {
   1411     offset_8 = -offset_8;
   1412     am ^= U;
   1413   }
   1414   DCHECK(is_uint8(offset_8));  // unsigned word offset must fit in a byte
   1415   DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
   1416 
   1417   // Post-indexed addressing requires W == 1; different than in addrmod2/3.
   1418   if ((am & P) == 0)
   1419     am |= W;
   1420 
   1421   DCHECK(offset_8 >= 0);  // no masking needed
   1422   emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
   1423 }
   1424 
   1425 
   1426 int Assembler::branch_offset(Label* L) {
   1427   int target_pos;
   1428   if (L->is_bound()) {
   1429     target_pos = L->pos();
   1430   } else {
   1431     if (L->is_linked()) {
   1432       // Point to previous instruction that uses the link.
   1433       target_pos = L->pos();
   1434     } else {
   1435       // First entry of the link chain points to itself.
   1436       target_pos = pc_offset();
   1437     }
   1438     L->link_to(pc_offset());
   1439   }
   1440 
   1441   // Block the emission of the constant pool, since the branch instruction must
   1442   // be emitted at the pc offset recorded by the label.
   1443   if (!is_const_pool_blocked()) BlockConstPoolFor(1);
   1444 
   1445   return target_pos - (pc_offset() + kPcLoadDelta);
   1446 }
   1447 
   1448 
   1449 // Branch instructions.
   1450 void Assembler::b(int branch_offset, Condition cond) {
   1451   DCHECK((branch_offset & 3) == 0);
   1452   int imm24 = branch_offset >> 2;
   1453   CHECK(is_int24(imm24));
   1454   emit(cond | B27 | B25 | (imm24 & kImm24Mask));
   1455 
   1456   if (cond == al) {
   1457     // Dead code is a good location to emit the constant pool.
   1458     CheckConstPool(false, false);
   1459   }
   1460 }
   1461 
   1462 
   1463 void Assembler::bl(int branch_offset, Condition cond) {
   1464   DCHECK((branch_offset & 3) == 0);
   1465   int imm24 = branch_offset >> 2;
   1466   CHECK(is_int24(imm24));
   1467   emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
   1468 }
   1469 
   1470 void Assembler::blx(int branch_offset) {
   1471   DCHECK((branch_offset & 1) == 0);
   1472   int h = ((branch_offset & 2) >> 1)*B24;
   1473   int imm24 = branch_offset >> 2;
   1474   CHECK(is_int24(imm24));
   1475   emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
   1476 }
   1477 
   1478 void Assembler::blx(Register target, Condition cond) {
   1479   DCHECK(!target.is(pc));
   1480   emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
   1481 }
   1482 
   1483 void Assembler::bx(Register target, Condition cond) {
   1484   DCHECK(!target.is(pc));  // use of pc is actually allowed, but discouraged
   1485   emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
   1486 }
   1487 
   1488 
   1489 void Assembler::b(Label* L, Condition cond) {
   1490   CheckBuffer();
   1491   b(branch_offset(L), cond);
   1492 }
   1493 
   1494 
   1495 void Assembler::bl(Label* L, Condition cond) {
   1496   CheckBuffer();
   1497   bl(branch_offset(L), cond);
   1498 }
   1499 
   1500 
   1501 void Assembler::blx(Label* L) {
   1502   CheckBuffer();
   1503   blx(branch_offset(L));
   1504 }
   1505 
   1506 
   1507 // Data-processing instructions.
   1508 
   1509 void Assembler::and_(Register dst, Register src1, const Operand& src2,
   1510                      SBit s, Condition cond) {
   1511   addrmod1(cond | AND | s, src1, dst, src2);
   1512 }
   1513 
   1514 
   1515 void Assembler::eor(Register dst, Register src1, const Operand& src2,
   1516                     SBit s, Condition cond) {
   1517   addrmod1(cond | EOR | s, src1, dst, src2);
   1518 }
   1519 
   1520 
   1521 void Assembler::sub(Register dst, Register src1, const Operand& src2,
   1522                     SBit s, Condition cond) {
   1523   addrmod1(cond | SUB | s, src1, dst, src2);
   1524 }
   1525 
   1526 
   1527 void Assembler::rsb(Register dst, Register src1, const Operand& src2,
   1528                     SBit s, Condition cond) {
   1529   addrmod1(cond | RSB | s, src1, dst, src2);
   1530 }
   1531 
   1532 
   1533 void Assembler::add(Register dst, Register src1, const Operand& src2,
   1534                     SBit s, Condition cond) {
   1535   addrmod1(cond | ADD | s, src1, dst, src2);
   1536 }
   1537 
   1538 
   1539 void Assembler::adc(Register dst, Register src1, const Operand& src2,
   1540                     SBit s, Condition cond) {
   1541   addrmod1(cond | ADC | s, src1, dst, src2);
   1542 }
   1543 
   1544 
   1545 void Assembler::sbc(Register dst, Register src1, const Operand& src2,
   1546                     SBit s, Condition cond) {
   1547   addrmod1(cond | SBC | s, src1, dst, src2);
   1548 }
   1549 
   1550 
   1551 void Assembler::rsc(Register dst, Register src1, const Operand& src2,
   1552                     SBit s, Condition cond) {
   1553   addrmod1(cond | RSC | s, src1, dst, src2);
   1554 }
   1555 
   1556 
   1557 void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
   1558   addrmod1(cond | TST | S, src1, r0, src2);
   1559 }
   1560 
   1561 
   1562 void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
   1563   addrmod1(cond | TEQ | S, src1, r0, src2);
   1564 }
   1565 
   1566 
   1567 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
   1568   addrmod1(cond | CMP | S, src1, r0, src2);
   1569 }
   1570 
   1571 
   1572 void Assembler::cmp_raw_immediate(
   1573     Register src, int raw_immediate, Condition cond) {
   1574   DCHECK(is_uint12(raw_immediate));
   1575   emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
   1576 }
   1577 
   1578 
   1579 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
   1580   addrmod1(cond | CMN | S, src1, r0, src2);
   1581 }
   1582 
   1583 
   1584 void Assembler::orr(Register dst, Register src1, const Operand& src2,
   1585                     SBit s, Condition cond) {
   1586   addrmod1(cond | ORR | s, src1, dst, src2);
   1587 }
   1588 
   1589 
   1590 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
   1591   // Don't allow nop instructions in the form mov rn, rn to be generated using
   1592   // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
   1593   // or MarkCode(int/NopMarkerTypes) pseudo instructions.
   1594   DCHECK(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
   1595   addrmod1(cond | MOV | s, r0, dst, src);
   1596 }
   1597 
   1598 
   1599 void Assembler::mov_label_offset(Register dst, Label* label) {
   1600   if (label->is_bound()) {
   1601     mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag)));
   1602   } else {
   1603     // Emit the link to the label in the code stream followed by extra nop
   1604     // instructions.
   1605     // If the label is not linked, then start a new link chain by linking it to
   1606     // itself, emitting pc_offset().
   1607     int link = label->is_linked() ? label->pos() : pc_offset();
   1608     label->link_to(pc_offset());
   1609 
   1610     // When the label is bound, these instructions will be patched with a
   1611     // sequence of movw/movt or mov/orr/orr instructions. They will load the
   1612     // destination register with the position of the label from the beginning
   1613     // of the code.
   1614     //
   1615     // The link will be extracted from the first instruction and the destination
   1616     // register from the second.
   1617     //   For ARMv7:
   1618     //      link
   1619     //      mov dst, dst
   1620     //   For ARMv6:
   1621     //      link
   1622     //      mov dst, dst
   1623     //      mov dst, dst
   1624     //
   1625     // When the label gets bound: target_at extracts the link and target_at_put
   1626     // patches the instructions.
   1627     CHECK(is_uint24(link));
   1628     BlockConstPoolScope block_const_pool(this);
   1629     emit(link);
   1630     nop(dst.code());
   1631     if (!CpuFeatures::IsSupported(ARMv7)) {
   1632       nop(dst.code());
   1633     }
   1634   }
   1635 }
   1636 
   1637 
   1638 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
   1639   DCHECK(IsEnabled(ARMv7));
   1640   emit(cond | 0x30*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
   1641 }
   1642 
   1643 
   1644 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
   1645   DCHECK(IsEnabled(ARMv7));
   1646   emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
   1647 }
   1648 
   1649 
   1650 void Assembler::bic(Register dst, Register src1, const Operand& src2,
   1651                     SBit s, Condition cond) {
   1652   addrmod1(cond | BIC | s, src1, dst, src2);
   1653 }
   1654 
   1655 
   1656 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
   1657   addrmod1(cond | MVN | s, r0, dst, src);
   1658 }
   1659 
   1660 
   1661 // Multiply instructions.
   1662 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
   1663                     SBit s, Condition cond) {
   1664   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
   1665   emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
   1666        src2.code()*B8 | B7 | B4 | src1.code());
   1667 }
   1668 
   1669 
   1670 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
   1671                     Condition cond) {
   1672   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
   1673   DCHECK(IsEnabled(ARMv7));
   1674   emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 |
   1675        src2.code()*B8 | B7 | B4 | src1.code());
   1676 }
   1677 
   1678 
   1679 void Assembler::sdiv(Register dst, Register src1, Register src2,
   1680                      Condition cond) {
   1681   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
   1682   DCHECK(IsEnabled(SUDIV));
   1683   emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 |
   1684        src2.code()*B8 | B4 | src1.code());
   1685 }
   1686 
   1687 
   1688 void Assembler::udiv(Register dst, Register src1, Register src2,
   1689                      Condition cond) {
   1690   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
   1691   DCHECK(IsEnabled(SUDIV));
   1692   emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xf * B12 |
   1693        src2.code() * B8 | B4 | src1.code());
   1694 }
   1695 
   1696 
   1697 void Assembler::mul(Register dst, Register src1, Register src2, SBit s,
   1698                     Condition cond) {
   1699   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
   1700   // dst goes in bits 16-19 for this instruction!
   1701   emit(cond | s | dst.code() * B16 | src2.code() * B8 | B7 | B4 | src1.code());
   1702 }
   1703 
   1704 
   1705 void Assembler::smmla(Register dst, Register src1, Register src2, Register srcA,
   1706                       Condition cond) {
   1707   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
   1708   emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 |
   1709        srcA.code() * B12 | src2.code() * B8 | B4 | src1.code());
   1710 }
   1711 
   1712 
   1713 void Assembler::smmul(Register dst, Register src1, Register src2,
   1714                       Condition cond) {
   1715   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
   1716   emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 0xf * B12 |
   1717        src2.code() * B8 | B4 | src1.code());
   1718 }
   1719 
   1720 
   1721 void Assembler::smlal(Register dstL,
   1722                       Register dstH,
   1723                       Register src1,
   1724                       Register src2,
   1725                       SBit s,
   1726                       Condition cond) {
   1727   DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
   1728   DCHECK(!dstL.is(dstH));
   1729   emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
   1730        src2.code()*B8 | B7 | B4 | src1.code());
   1731 }
   1732 
   1733 
   1734 void Assembler::smull(Register dstL,
   1735                       Register dstH,
   1736                       Register src1,
   1737                       Register src2,
   1738                       SBit s,
   1739                       Condition cond) {
   1740   DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
   1741   DCHECK(!dstL.is(dstH));
   1742   emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
   1743        src2.code()*B8 | B7 | B4 | src1.code());
   1744 }
   1745 
   1746 
   1747 void Assembler::umlal(Register dstL,
   1748                       Register dstH,
   1749                       Register src1,
   1750                       Register src2,
   1751                       SBit s,
   1752                       Condition cond) {
   1753   DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
   1754   DCHECK(!dstL.is(dstH));
   1755   emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
   1756        src2.code()*B8 | B7 | B4 | src1.code());
   1757 }
   1758 
   1759 
   1760 void Assembler::umull(Register dstL,
   1761                       Register dstH,
   1762                       Register src1,
   1763                       Register src2,
   1764                       SBit s,
   1765                       Condition cond) {
   1766   DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
   1767   DCHECK(!dstL.is(dstH));
   1768   emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
   1769        src2.code()*B8 | B7 | B4 | src1.code());
   1770 }
   1771 
   1772 
   1773 // Miscellaneous arithmetic instructions.
   1774 void Assembler::clz(Register dst, Register src, Condition cond) {
   1775   DCHECK(!dst.is(pc) && !src.is(pc));
   1776   emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
   1777        15*B8 | CLZ | src.code());
   1778 }
   1779 
   1780 
   1781 // Saturating instructions.
   1782 
   1783 // Unsigned saturate.
   1784 void Assembler::usat(Register dst,
   1785                      int satpos,
   1786                      const Operand& src,
   1787                      Condition cond) {
   1788   DCHECK(!dst.is(pc) && !src.rm_.is(pc));
   1789   DCHECK((satpos >= 0) && (satpos <= 31));
   1790   DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
   1791   DCHECK(src.rs_.is(no_reg));
   1792 
   1793   int sh = 0;
   1794   if (src.shift_op_ == ASR) {
   1795       sh = 1;
   1796   }
   1797 
   1798   emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
   1799        src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
   1800 }
   1801 
   1802 
   1803 // Bitfield manipulation instructions.
   1804 
   1805 // Unsigned bit field extract.
   1806 // Extracts #width adjacent bits from position #lsb in a register, and
   1807 // writes them to the low bits of a destination register.
   1808 //   ubfx dst, src, #lsb, #width
   1809 void Assembler::ubfx(Register dst,
   1810                      Register src,
   1811                      int lsb,
   1812                      int width,
   1813                      Condition cond) {
   1814   DCHECK(IsEnabled(ARMv7));
   1815   DCHECK(!dst.is(pc) && !src.is(pc));
   1816   DCHECK((lsb >= 0) && (lsb <= 31));
   1817   DCHECK((width >= 1) && (width <= (32 - lsb)));
   1818   emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
   1819        lsb*B7 | B6 | B4 | src.code());
   1820 }
   1821 
   1822 
   1823 // Signed bit field extract.
   1824 // Extracts #width adjacent bits from position #lsb in a register, and
   1825 // writes them to the low bits of a destination register. The extracted
   1826 // value is sign extended to fill the destination register.
   1827 //   sbfx dst, src, #lsb, #width
   1828 void Assembler::sbfx(Register dst,
   1829                      Register src,
   1830                      int lsb,
   1831                      int width,
   1832                      Condition cond) {
   1833   DCHECK(IsEnabled(ARMv7));
   1834   DCHECK(!dst.is(pc) && !src.is(pc));
   1835   DCHECK((lsb >= 0) && (lsb <= 31));
   1836   DCHECK((width >= 1) && (width <= (32 - lsb)));
   1837   emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
   1838        lsb*B7 | B6 | B4 | src.code());
   1839 }
   1840 
   1841 
   1842 // Bit field clear.
   1843 // Sets #width adjacent bits at position #lsb in the destination register
   1844 // to zero, preserving the value of the other bits.
   1845 //   bfc dst, #lsb, #width
   1846 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
   1847   DCHECK(IsEnabled(ARMv7));
   1848   DCHECK(!dst.is(pc));
   1849   DCHECK((lsb >= 0) && (lsb <= 31));
   1850   DCHECK((width >= 1) && (width <= (32 - lsb)));
   1851   int msb = lsb + width - 1;
   1852   emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
   1853 }
   1854 
   1855 
   1856 // Bit field insert.
   1857 // Inserts #width adjacent bits from the low bits of the source register
   1858 // into position #lsb of the destination register.
   1859 //   bfi dst, src, #lsb, #width
   1860 void Assembler::bfi(Register dst,
   1861                     Register src,
   1862                     int lsb,
   1863                     int width,
   1864                     Condition cond) {
   1865   DCHECK(IsEnabled(ARMv7));
   1866   DCHECK(!dst.is(pc) && !src.is(pc));
   1867   DCHECK((lsb >= 0) && (lsb <= 31));
   1868   DCHECK((width >= 1) && (width <= (32 - lsb)));
   1869   int msb = lsb + width - 1;
   1870   emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
   1871        src.code());
   1872 }
   1873 
   1874 
   1875 void Assembler::pkhbt(Register dst,
   1876                       Register src1,
   1877                       const Operand& src2,
   1878                       Condition cond ) {
   1879   // Instruction details available in ARM DDI 0406C.b, A8.8.125.
   1880   // cond(31-28) | 01101000(27-20) | Rn(19-16) |
   1881   // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0)
   1882   DCHECK(!dst.is(pc));
   1883   DCHECK(!src1.is(pc));
   1884   DCHECK(!src2.rm().is(pc));
   1885   DCHECK(!src2.rm().is(no_reg));
   1886   DCHECK(src2.rs().is(no_reg));
   1887   DCHECK((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31));
   1888   DCHECK(src2.shift_op() == LSL);
   1889   emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
   1890        src2.shift_imm_*B7 | B4 | src2.rm().code());
   1891 }
   1892 
   1893 
   1894 void Assembler::pkhtb(Register dst,
   1895                       Register src1,
   1896                       const Operand& src2,
   1897                       Condition cond) {
   1898   // Instruction details available in ARM DDI 0406C.b, A8.8.125.
   1899   // cond(31-28) | 01101000(27-20) | Rn(19-16) |
   1900   // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0)
   1901   DCHECK(!dst.is(pc));
   1902   DCHECK(!src1.is(pc));
   1903   DCHECK(!src2.rm().is(pc));
   1904   DCHECK(!src2.rm().is(no_reg));
   1905   DCHECK(src2.rs().is(no_reg));
   1906   DCHECK((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32));
   1907   DCHECK(src2.shift_op() == ASR);
   1908   int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_;
   1909   emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
   1910        asr*B7 | B6 | B4 | src2.rm().code());
   1911 }
   1912 
   1913 
   1914 void Assembler::sxtb(Register dst, Register src, int rotate, Condition cond) {
   1915   // Instruction details available in ARM DDI 0406C.b, A8.8.233.
   1916   // cond(31-28) | 01101010(27-20) | 1111(19-16) |
   1917   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1918   DCHECK(!dst.is(pc));
   1919   DCHECK(!src.is(pc));
   1920   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1921   emit(cond | 0x6A * B20 | 0xF * B16 | dst.code() * B12 |
   1922        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
   1923 }
   1924 
   1925 
   1926 void Assembler::sxtab(Register dst, Register src1, Register src2, int rotate,
   1927                       Condition cond) {
   1928   // Instruction details available in ARM DDI 0406C.b, A8.8.233.
   1929   // cond(31-28) | 01101010(27-20) | Rn(19-16) |
   1930   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1931   DCHECK(!dst.is(pc));
   1932   DCHECK(!src1.is(pc));
   1933   DCHECK(!src2.is(pc));
   1934   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1935   emit(cond | 0x6A * B20 | src1.code() * B16 | dst.code() * B12 |
   1936        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
   1937 }
   1938 
   1939 
   1940 void Assembler::sxth(Register dst, Register src, int rotate, Condition cond) {
   1941   // Instruction details available in ARM DDI 0406C.b, A8.8.235.
   1942   // cond(31-28) | 01101011(27-20) | 1111(19-16) |
   1943   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1944   DCHECK(!dst.is(pc));
   1945   DCHECK(!src.is(pc));
   1946   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1947   emit(cond | 0x6B * B20 | 0xF * B16 | dst.code() * B12 |
   1948        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
   1949 }
   1950 
   1951 
   1952 void Assembler::sxtah(Register dst, Register src1, Register src2, int rotate,
   1953                       Condition cond) {
   1954   // Instruction details available in ARM DDI 0406C.b, A8.8.235.
   1955   // cond(31-28) | 01101011(27-20) | Rn(19-16) |
   1956   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1957   DCHECK(!dst.is(pc));
   1958   DCHECK(!src1.is(pc));
   1959   DCHECK(!src2.is(pc));
   1960   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1961   emit(cond | 0x6B * B20 | src1.code() * B16 | dst.code() * B12 |
   1962        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
   1963 }
   1964 
   1965 
   1966 void Assembler::uxtb(Register dst, Register src, int rotate, Condition cond) {
   1967   // Instruction details available in ARM DDI 0406C.b, A8.8.274.
   1968   // cond(31-28) | 01101110(27-20) | 1111(19-16) |
   1969   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1970   DCHECK(!dst.is(pc));
   1971   DCHECK(!src.is(pc));
   1972   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1973   emit(cond | 0x6E * B20 | 0xF * B16 | dst.code() * B12 |
   1974        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
   1975 }
   1976 
   1977 
   1978 void Assembler::uxtab(Register dst, Register src1, Register src2, int rotate,
   1979                       Condition cond) {
   1980   // Instruction details available in ARM DDI 0406C.b, A8.8.271.
   1981   // cond(31-28) | 01101110(27-20) | Rn(19-16) |
   1982   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1983   DCHECK(!dst.is(pc));
   1984   DCHECK(!src1.is(pc));
   1985   DCHECK(!src2.is(pc));
   1986   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1987   emit(cond | 0x6E * B20 | src1.code() * B16 | dst.code() * B12 |
   1988        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
   1989 }
   1990 
   1991 
   1992 void Assembler::uxtb16(Register dst, Register src, int rotate, Condition cond) {
   1993   // Instruction details available in ARM DDI 0406C.b, A8.8.275.
   1994   // cond(31-28) | 01101100(27-20) | 1111(19-16) |
   1995   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   1996   DCHECK(!dst.is(pc));
   1997   DCHECK(!src.is(pc));
   1998   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   1999   emit(cond | 0x6C * B20 | 0xF * B16 | dst.code() * B12 |
   2000        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
   2001 }
   2002 
   2003 
   2004 void Assembler::uxth(Register dst, Register src, int rotate, Condition cond) {
   2005   // Instruction details available in ARM DDI 0406C.b, A8.8.276.
   2006   // cond(31-28) | 01101111(27-20) | 1111(19-16) |
   2007   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   2008   DCHECK(!dst.is(pc));
   2009   DCHECK(!src.is(pc));
   2010   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   2011   emit(cond | 0x6F * B20 | 0xF * B16 | dst.code() * B12 |
   2012        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
   2013 }
   2014 
   2015 
   2016 void Assembler::uxtah(Register dst, Register src1, Register src2, int rotate,
   2017                       Condition cond) {
   2018   // Instruction details available in ARM DDI 0406C.b, A8.8.273.
   2019   // cond(31-28) | 01101111(27-20) | Rn(19-16) |
   2020   // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
   2021   DCHECK(!dst.is(pc));
   2022   DCHECK(!src1.is(pc));
   2023   DCHECK(!src2.is(pc));
   2024   DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
   2025   emit(cond | 0x6F * B20 | src1.code() * B16 | dst.code() * B12 |
   2026        ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
   2027 }
   2028 
   2029 
   2030 void Assembler::rbit(Register dst, Register src, Condition cond) {
   2031   // Instruction details available in ARM DDI 0406C.b, A8.8.144.
   2032   // cond(31-28) | 011011111111(27-16) | Rd(15-12) | 11110011(11-4) | Rm(3-0)
   2033   DCHECK(IsEnabled(ARMv7));
   2034   DCHECK(!dst.is(pc));
   2035   DCHECK(!src.is(pc));
   2036   emit(cond | 0x6FF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
   2037 }
   2038 
   2039 
   2040 // Status register access instructions.
   2041 void Assembler::mrs(Register dst, SRegister s, Condition cond) {
   2042   DCHECK(!dst.is(pc));
   2043   emit(cond | B24 | s | 15*B16 | dst.code()*B12);
   2044 }
   2045 
   2046 
   2047 void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
   2048                     Condition cond) {
   2049   DCHECK((fields & 0x000f0000) != 0);  // At least one field must be set.
   2050   DCHECK(((fields & 0xfff0ffff) == CPSR) || ((fields & 0xfff0ffff) == SPSR));
   2051   Instr instr;
   2052   if (!src.rm_.is_valid()) {
   2053     // Immediate.
   2054     uint32_t rotate_imm;
   2055     uint32_t immed_8;
   2056     if (src.must_output_reloc_info(this) ||
   2057         !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
   2058       // Immediate operand cannot be encoded, load it first to register ip.
   2059       move_32_bit_immediate(ip, src);
   2060       msr(fields, Operand(ip), cond);
   2061       return;
   2062     }
   2063     instr = I | rotate_imm*B8 | immed_8;
   2064   } else {
   2065     DCHECK(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
   2066     instr = src.rm_.code();
   2067   }
   2068   emit(cond | instr | B24 | B21 | fields | 15*B12);
   2069 }
   2070 
   2071 
   2072 // Load/Store instructions.
   2073 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
   2074   addrmod2(cond | B26 | L, dst, src);
   2075 }
   2076 
   2077 
   2078 void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
   2079   addrmod2(cond | B26, src, dst);
   2080 }
   2081 
   2082 
   2083 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
   2084   addrmod2(cond | B26 | B | L, dst, src);
   2085 }
   2086 
   2087 
   2088 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
   2089   addrmod2(cond | B26 | B, src, dst);
   2090 }
   2091 
   2092 
   2093 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
   2094   addrmod3(cond | L | B7 | H | B4, dst, src);
   2095 }
   2096 
   2097 
   2098 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
   2099   addrmod3(cond | B7 | H | B4, src, dst);
   2100 }
   2101 
   2102 
   2103 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
   2104   addrmod3(cond | L | B7 | S6 | B4, dst, src);
   2105 }
   2106 
   2107 
   2108 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
   2109   addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
   2110 }
   2111 
   2112 
   2113 void Assembler::ldrd(Register dst1, Register dst2,
   2114                      const MemOperand& src, Condition cond) {
   2115   DCHECK(src.rm().is(no_reg));
   2116   DCHECK(!dst1.is(lr));  // r14.
   2117   DCHECK_EQ(0, dst1.code() % 2);
   2118   DCHECK_EQ(dst1.code() + 1, dst2.code());
   2119   addrmod3(cond | B7 | B6 | B4, dst1, src);
   2120 }
   2121 
   2122 
   2123 void Assembler::strd(Register src1, Register src2,
   2124                      const MemOperand& dst, Condition cond) {
   2125   DCHECK(dst.rm().is(no_reg));
   2126   DCHECK(!src1.is(lr));  // r14.
   2127   DCHECK_EQ(0, src1.code() % 2);
   2128   DCHECK_EQ(src1.code() + 1, src2.code());
   2129   addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
   2130 }
   2131 
   2132 // Load/Store exclusive instructions.
   2133 void Assembler::ldrex(Register dst, Register src, Condition cond) {
   2134   // Instruction details available in ARM DDI 0406C.b, A8.8.75.
   2135   // cond(31-28) | 00011001(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
   2136   emit(cond | B24 | B23 | B20 | src.code() * B16 | dst.code() * B12 | 0xf9f);
   2137 }
   2138 
   2139 void Assembler::strex(Register src1, Register src2, Register dst,
   2140                       Condition cond) {
   2141   // Instruction details available in ARM DDI 0406C.b, A8.8.212.
   2142   // cond(31-28) | 00011000(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
   2143   // Rt(3-0)
   2144   emit(cond | B24 | B23 | dst.code() * B16 | src1.code() * B12 | 0xf9 * B4 |
   2145        src2.code());
   2146 }
   2147 
   2148 void Assembler::ldrexb(Register dst, Register src, Condition cond) {
   2149   // Instruction details available in ARM DDI 0406C.b, A8.8.76.
   2150   // cond(31-28) | 00011101(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
   2151   emit(cond | B24 | B23 | B22 | B20 | src.code() * B16 | dst.code() * B12 |
   2152        0xf9f);
   2153 }
   2154 
   2155 void Assembler::strexb(Register src1, Register src2, Register dst,
   2156                        Condition cond) {
   2157   // Instruction details available in ARM DDI 0406C.b, A8.8.213.
   2158   // cond(31-28) | 00011100(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
   2159   // Rt(3-0)
   2160   emit(cond | B24 | B23 | B22 | dst.code() * B16 | src1.code() * B12 |
   2161        0xf9 * B4 | src2.code());
   2162 }
   2163 
   2164 void Assembler::ldrexh(Register dst, Register src, Condition cond) {
   2165   // Instruction details available in ARM DDI 0406C.b, A8.8.78.
   2166   // cond(31-28) | 00011111(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
   2167   emit(cond | B24 | B23 | B22 | B21 | B20 | src.code() * B16 |
   2168        dst.code() * B12 | 0xf9f);
   2169 }
   2170 
   2171 void Assembler::strexh(Register src1, Register src2, Register dst,
   2172                        Condition cond) {
   2173   // Instruction details available in ARM DDI 0406C.b, A8.8.215.
   2174   // cond(31-28) | 00011110(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
   2175   // Rt(3-0)
   2176   emit(cond | B24 | B23 | B22 | B21 | dst.code() * B16 | src1.code() * B12 |
   2177        0xf9 * B4 | src2.code());
   2178 }
   2179 
   2180 // Preload instructions.
   2181 void Assembler::pld(const MemOperand& address) {
   2182   // Instruction details available in ARM DDI 0406C.b, A8.8.128.
   2183   // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) |
   2184   // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) |
   2185   DCHECK(address.rm().is(no_reg));
   2186   DCHECK(address.am() == Offset);
   2187   int U = B23;
   2188   int offset = address.offset();
   2189   if (offset < 0) {
   2190     offset = -offset;
   2191     U = 0;
   2192   }
   2193   DCHECK(offset < 4096);
   2194   emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 |
   2195        0xf*B12 | offset);
   2196 }
   2197 
   2198 
   2199 // Load/Store multiple instructions.
   2200 void Assembler::ldm(BlockAddrMode am,
   2201                     Register base,
   2202                     RegList dst,
   2203                     Condition cond) {
   2204   // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
   2205   DCHECK(base.is(sp) || (dst & sp.bit()) == 0);
   2206 
   2207   addrmod4(cond | B27 | am | L, base, dst);
   2208 
   2209   // Emit the constant pool after a function return implemented by ldm ..{..pc}.
   2210   if (cond == al && (dst & pc.bit()) != 0) {
   2211     // There is a slight chance that the ldm instruction was actually a call,
   2212     // in which case it would be wrong to return into the constant pool; we
   2213     // recognize this case by checking if the emission of the pool was blocked
   2214     // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
   2215     // the case, we emit a jump over the pool.
   2216     CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
   2217   }
   2218 }
   2219 
   2220 
   2221 void Assembler::stm(BlockAddrMode am,
   2222                     Register base,
   2223                     RegList src,
   2224                     Condition cond) {
   2225   addrmod4(cond | B27 | am, base, src);
   2226 }
   2227 
   2228 
   2229 // Exception-generating instructions and debugging support.
   2230 // Stops with a non-negative code less than kNumOfWatchedStops support
   2231 // enabling/disabling and a counter feature. See simulator-arm.h .
   2232 void Assembler::stop(const char* msg, Condition cond, int32_t code) {
   2233 #ifndef __arm__
   2234   DCHECK(code >= kDefaultStopCode);
   2235   {
   2236     // The Simulator will handle the stop instruction and get the message
   2237     // address. It expects to find the address just after the svc instruction.
   2238     BlockConstPoolScope block_const_pool(this);
   2239     if (code >= 0) {
   2240       svc(kStopCode + code, cond);
   2241     } else {
   2242       svc(kStopCode + kMaxStopCode, cond);
   2243     }
   2244     // Do not embed the message string address! We used to do this, but that
   2245     // made snapshots created from position-independent executable builds
   2246     // non-deterministic.
   2247     // TODO(yangguo): remove this field entirely.
   2248     nop();
   2249   }
   2250 #else  // def __arm__
   2251   if (cond != al) {
   2252     Label skip;
   2253     b(&skip, NegateCondition(cond));
   2254     bkpt(0);
   2255     bind(&skip);
   2256   } else {
   2257     bkpt(0);
   2258   }
   2259 #endif  // def __arm__
   2260 }
   2261 
   2262 void Assembler::bkpt(uint32_t imm16) {
   2263   DCHECK(is_uint16(imm16));
   2264   emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
   2265 }
   2266 
   2267 
   2268 void Assembler::svc(uint32_t imm24, Condition cond) {
   2269   DCHECK(is_uint24(imm24));
   2270   emit(cond | 15*B24 | imm24);
   2271 }
   2272 
   2273 
   2274 void Assembler::dmb(BarrierOption option) {
   2275   if (CpuFeatures::IsSupported(ARMv7)) {
   2276     // Details available in ARM DDI 0406C.b, A8-378.
   2277     emit(kSpecialCondition | 0x57ff * B12 | 5 * B4 | option);
   2278   } else {
   2279     // Details available in ARM DDI 0406C.b, B3-1750.
   2280     // CP15DMB: CRn=c7, opc1=0, CRm=c10, opc2=5, Rt is ignored.
   2281     mcr(p15, 0, r0, cr7, cr10, 5);
   2282   }
   2283 }
   2284 
   2285 
   2286 void Assembler::dsb(BarrierOption option) {
   2287   if (CpuFeatures::IsSupported(ARMv7)) {
   2288     // Details available in ARM DDI 0406C.b, A8-380.
   2289     emit(kSpecialCondition | 0x57ff * B12 | 4 * B4 | option);
   2290   } else {
   2291     // Details available in ARM DDI 0406C.b, B3-1750.
   2292     // CP15DSB: CRn=c7, opc1=0, CRm=c10, opc2=4, Rt is ignored.
   2293     mcr(p15, 0, r0, cr7, cr10, 4);
   2294   }
   2295 }
   2296 
   2297 
   2298 void Assembler::isb(BarrierOption option) {
   2299   if (CpuFeatures::IsSupported(ARMv7)) {
   2300     // Details available in ARM DDI 0406C.b, A8-389.
   2301     emit(kSpecialCondition | 0x57ff * B12 | 6 * B4 | option);
   2302   } else {
   2303     // Details available in ARM DDI 0406C.b, B3-1750.
   2304     // CP15ISB: CRn=c7, opc1=0, CRm=c5, opc2=4, Rt is ignored.
   2305     mcr(p15, 0, r0, cr7, cr5, 4);
   2306   }
   2307 }
   2308 
   2309 
   2310 // Coprocessor instructions.
   2311 void Assembler::cdp(Coprocessor coproc,
   2312                     int opcode_1,
   2313                     CRegister crd,
   2314                     CRegister crn,
   2315                     CRegister crm,
   2316                     int opcode_2,
   2317                     Condition cond) {
   2318   DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2));
   2319   emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
   2320        crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
   2321 }
   2322 
   2323 void Assembler::cdp2(Coprocessor coproc, int opcode_1, CRegister crd,
   2324                      CRegister crn, CRegister crm, int opcode_2) {
   2325   cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
   2326 }
   2327 
   2328 
   2329 void Assembler::mcr(Coprocessor coproc,
   2330                     int opcode_1,
   2331                     Register rd,
   2332                     CRegister crn,
   2333                     CRegister crm,
   2334                     int opcode_2,
   2335                     Condition cond) {
   2336   DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
   2337   emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
   2338        rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
   2339 }
   2340 
   2341 void Assembler::mcr2(Coprocessor coproc, int opcode_1, Register rd,
   2342                      CRegister crn, CRegister crm, int opcode_2) {
   2343   mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
   2344 }
   2345 
   2346 
   2347 void Assembler::mrc(Coprocessor coproc,
   2348                     int opcode_1,
   2349                     Register rd,
   2350                     CRegister crn,
   2351                     CRegister crm,
   2352                     int opcode_2,
   2353                     Condition cond) {
   2354   DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
   2355   emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
   2356        rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
   2357 }
   2358 
   2359 void Assembler::mrc2(Coprocessor coproc, int opcode_1, Register rd,
   2360                      CRegister crn, CRegister crm, int opcode_2) {
   2361   mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
   2362 }
   2363 
   2364 
   2365 void Assembler::ldc(Coprocessor coproc,
   2366                     CRegister crd,
   2367                     const MemOperand& src,
   2368                     LFlag l,
   2369                     Condition cond) {
   2370   addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
   2371 }
   2372 
   2373 
   2374 void Assembler::ldc(Coprocessor coproc,
   2375                     CRegister crd,
   2376                     Register rn,
   2377                     int option,
   2378                     LFlag l,
   2379                     Condition cond) {
   2380   // Unindexed addressing.
   2381   DCHECK(is_uint8(option));
   2382   emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
   2383        coproc*B8 | (option & 255));
   2384 }
   2385 
   2386 void Assembler::ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
   2387                      LFlag l) {
   2388   ldc(coproc, crd, src, l, kSpecialCondition);
   2389 }
   2390 
   2391 void Assembler::ldc2(Coprocessor coproc, CRegister crd, Register rn, int option,
   2392                      LFlag l) {
   2393   ldc(coproc, crd, rn, option, l, kSpecialCondition);
   2394 }
   2395 
   2396 
   2397 // Support for VFP.
   2398 
   2399 void Assembler::vldr(const DwVfpRegister dst,
   2400                      const Register base,
   2401                      int offset,
   2402                      const Condition cond) {
   2403   // Ddst = MEM(Rbase + offset).
   2404   // Instruction details available in ARM DDI 0406C.b, A8-924.
   2405   // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
   2406   // Vd(15-12) | 1011(11-8) | offset
   2407   DCHECK(VfpRegisterIsAvailable(dst));
   2408   int u = 1;
   2409   if (offset < 0) {
   2410     CHECK(offset != kMinInt);
   2411     offset = -offset;
   2412     u = 0;
   2413   }
   2414   int vd, d;
   2415   dst.split_code(&vd, &d);
   2416 
   2417   DCHECK(offset >= 0);
   2418   if ((offset % 4) == 0 && (offset / 4) < 256) {
   2419     emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 |
   2420          0xB*B8 | ((offset / 4) & 255));
   2421   } else {
   2422     // Larger offsets must be handled by computing the correct address
   2423     // in the ip register.
   2424     DCHECK(!base.is(ip));
   2425     if (u == 1) {
   2426       add(ip, base, Operand(offset));
   2427     } else {
   2428       sub(ip, base, Operand(offset));
   2429     }
   2430     emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8);
   2431   }
   2432 }
   2433 
   2434 
   2435 void Assembler::vldr(const DwVfpRegister dst,
   2436                      const MemOperand& operand,
   2437                      const Condition cond) {
   2438   DCHECK(VfpRegisterIsAvailable(dst));
   2439   DCHECK(operand.am_ == Offset);
   2440   if (operand.rm().is_valid()) {
   2441     add(ip, operand.rn(),
   2442         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
   2443     vldr(dst, ip, 0, cond);
   2444   } else {
   2445     vldr(dst, operand.rn(), operand.offset(), cond);
   2446   }
   2447 }
   2448 
   2449 
   2450 void Assembler::vldr(const SwVfpRegister dst,
   2451                      const Register base,
   2452                      int offset,
   2453                      const Condition cond) {
   2454   // Sdst = MEM(Rbase + offset).
   2455   // Instruction details available in ARM DDI 0406A, A8-628.
   2456   // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
   2457   // Vdst(15-12) | 1010(11-8) | offset
   2458   int u = 1;
   2459   if (offset < 0) {
   2460     offset = -offset;
   2461     u = 0;
   2462   }
   2463   int sd, d;
   2464   dst.split_code(&sd, &d);
   2465   DCHECK(offset >= 0);
   2466 
   2467   if ((offset % 4) == 0 && (offset / 4) < 256) {
   2468   emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
   2469        0xA*B8 | ((offset / 4) & 255));
   2470   } else {
   2471     // Larger offsets must be handled by computing the correct address
   2472     // in the ip register.
   2473     DCHECK(!base.is(ip));
   2474     if (u == 1) {
   2475       add(ip, base, Operand(offset));
   2476     } else {
   2477       sub(ip, base, Operand(offset));
   2478     }
   2479     emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
   2480   }
   2481 }
   2482 
   2483 
   2484 void Assembler::vldr(const SwVfpRegister dst,
   2485                      const MemOperand& operand,
   2486                      const Condition cond) {
   2487   DCHECK(operand.am_ == Offset);
   2488   if (operand.rm().is_valid()) {
   2489     add(ip, operand.rn(),
   2490         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
   2491     vldr(dst, ip, 0, cond);
   2492   } else {
   2493     vldr(dst, operand.rn(), operand.offset(), cond);
   2494   }
   2495 }
   2496 
   2497 
   2498 void Assembler::vstr(const DwVfpRegister src,
   2499                      const Register base,
   2500                      int offset,
   2501                      const Condition cond) {
   2502   // MEM(Rbase + offset) = Dsrc.
   2503   // Instruction details available in ARM DDI 0406C.b, A8-1082.
   2504   // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
   2505   // Vd(15-12) | 1011(11-8) | (offset/4)
   2506   DCHECK(VfpRegisterIsAvailable(src));
   2507   int u = 1;
   2508   if (offset < 0) {
   2509     CHECK(offset != kMinInt);
   2510     offset = -offset;
   2511     u = 0;
   2512   }
   2513   DCHECK(offset >= 0);
   2514   int vd, d;
   2515   src.split_code(&vd, &d);
   2516 
   2517   if ((offset % 4) == 0 && (offset / 4) < 256) {
   2518     emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 |
   2519          ((offset / 4) & 255));
   2520   } else {
   2521     // Larger offsets must be handled by computing the correct address
   2522     // in the ip register.
   2523     DCHECK(!base.is(ip));
   2524     if (u == 1) {
   2525       add(ip, base, Operand(offset));
   2526     } else {
   2527       sub(ip, base, Operand(offset));
   2528     }
   2529     emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8);
   2530   }
   2531 }
   2532 
   2533 
   2534 void Assembler::vstr(const DwVfpRegister src,
   2535                      const MemOperand& operand,
   2536                      const Condition cond) {
   2537   DCHECK(VfpRegisterIsAvailable(src));
   2538   DCHECK(operand.am_ == Offset);
   2539   if (operand.rm().is_valid()) {
   2540     add(ip, operand.rn(),
   2541         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
   2542     vstr(src, ip, 0, cond);
   2543   } else {
   2544     vstr(src, operand.rn(), operand.offset(), cond);
   2545   }
   2546 }
   2547 
   2548 
   2549 void Assembler::vstr(const SwVfpRegister src,
   2550                      const Register base,
   2551                      int offset,
   2552                      const Condition cond) {
   2553   // MEM(Rbase + offset) = SSrc.
   2554   // Instruction details available in ARM DDI 0406A, A8-786.
   2555   // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
   2556   // Vdst(15-12) | 1010(11-8) | (offset/4)
   2557   int u = 1;
   2558   if (offset < 0) {
   2559     CHECK(offset != kMinInt);
   2560     offset = -offset;
   2561     u = 0;
   2562   }
   2563   int sd, d;
   2564   src.split_code(&sd, &d);
   2565   DCHECK(offset >= 0);
   2566   if ((offset % 4) == 0 && (offset / 4) < 256) {
   2567     emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
   2568          0xA*B8 | ((offset / 4) & 255));
   2569   } else {
   2570     // Larger offsets must be handled by computing the correct address
   2571     // in the ip register.
   2572     DCHECK(!base.is(ip));
   2573     if (u == 1) {
   2574       add(ip, base, Operand(offset));
   2575     } else {
   2576       sub(ip, base, Operand(offset));
   2577     }
   2578     emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
   2579   }
   2580 }
   2581 
   2582 
   2583 void Assembler::vstr(const SwVfpRegister src,
   2584                      const MemOperand& operand,
   2585                      const Condition cond) {
   2586   DCHECK(operand.am_ == Offset);
   2587   if (operand.rm().is_valid()) {
   2588     add(ip, operand.rn(),
   2589         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
   2590     vstr(src, ip, 0, cond);
   2591   } else {
   2592     vstr(src, operand.rn(), operand.offset(), cond);
   2593   }
   2594 }
   2595 
   2596 void Assembler::vldm(BlockAddrMode am, Register base, DwVfpRegister first,
   2597                      DwVfpRegister last, Condition cond) {
   2598   // Instruction details available in ARM DDI 0406C.b, A8-922.
   2599   // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
   2600   // first(15-12) | 1011(11-8) | (count * 2)
   2601   DCHECK_LE(first.code(), last.code());
   2602   DCHECK(VfpRegisterIsAvailable(last));
   2603   DCHECK(am == ia || am == ia_w || am == db_w);
   2604   DCHECK(!base.is(pc));
   2605 
   2606   int sd, d;
   2607   first.split_code(&sd, &d);
   2608   int count = last.code() - first.code() + 1;
   2609   DCHECK(count <= 16);
   2610   emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
   2611        0xB*B8 | count*2);
   2612 }
   2613 
   2614 void Assembler::vstm(BlockAddrMode am, Register base, DwVfpRegister first,
   2615                      DwVfpRegister last, Condition cond) {
   2616   // Instruction details available in ARM DDI 0406C.b, A8-1080.
   2617   // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
   2618   // first(15-12) | 1011(11-8) | (count * 2)
   2619   DCHECK_LE(first.code(), last.code());
   2620   DCHECK(VfpRegisterIsAvailable(last));
   2621   DCHECK(am == ia || am == ia_w || am == db_w);
   2622   DCHECK(!base.is(pc));
   2623 
   2624   int sd, d;
   2625   first.split_code(&sd, &d);
   2626   int count = last.code() - first.code() + 1;
   2627   DCHECK(count <= 16);
   2628   emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
   2629        0xB*B8 | count*2);
   2630 }
   2631 
   2632 void Assembler::vldm(BlockAddrMode am, Register base, SwVfpRegister first,
   2633                      SwVfpRegister last, Condition cond) {
   2634   // Instruction details available in ARM DDI 0406A, A8-626.
   2635   // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
   2636   // first(15-12) | 1010(11-8) | (count/2)
   2637   DCHECK_LE(first.code(), last.code());
   2638   DCHECK(am == ia || am == ia_w || am == db_w);
   2639   DCHECK(!base.is(pc));
   2640 
   2641   int sd, d;
   2642   first.split_code(&sd, &d);
   2643   int count = last.code() - first.code() + 1;
   2644   emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
   2645        0xA*B8 | count);
   2646 }
   2647 
   2648 void Assembler::vstm(BlockAddrMode am, Register base, SwVfpRegister first,
   2649                      SwVfpRegister last, Condition cond) {
   2650   // Instruction details available in ARM DDI 0406A, A8-784.
   2651   // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
   2652   // first(15-12) | 1011(11-8) | (count/2)
   2653   DCHECK_LE(first.code(), last.code());
   2654   DCHECK(am == ia || am == ia_w || am == db_w);
   2655   DCHECK(!base.is(pc));
   2656 
   2657   int sd, d;
   2658   first.split_code(&sd, &d);
   2659   int count = last.code() - first.code() + 1;
   2660   emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
   2661        0xA*B8 | count);
   2662 }
   2663 
   2664 
   2665 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
   2666   uint64_t i;
   2667   memcpy(&i, &d, 8);
   2668 
   2669   *lo = i & 0xffffffff;
   2670   *hi = i >> 32;
   2671 }
   2672 
   2673 
   2674 // Only works for little endian floating point formats.
   2675 // We don't support VFP on the mixed endian floating point platform.
   2676 static bool FitsVmovFPImmediate(double d, uint32_t* encoding) {
   2677   // VMOV can accept an immediate of the form:
   2678   //
   2679   //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
   2680   //
   2681   // The immediate is encoded using an 8-bit quantity, comprised of two
   2682   // 4-bit fields. For an 8-bit immediate of the form:
   2683   //
   2684   //  [abcdefgh]
   2685   //
   2686   // where a is the MSB and h is the LSB, an immediate 64-bit double can be
   2687   // created of the form:
   2688   //
   2689   //  [aBbbbbbb,bbcdefgh,00000000,00000000,
   2690   //      00000000,00000000,00000000,00000000]
   2691   //
   2692   // where B = ~b.
   2693   //
   2694 
   2695   uint32_t lo, hi;
   2696   DoubleAsTwoUInt32(d, &lo, &hi);
   2697 
   2698   // The most obvious constraint is the long block of zeroes.
   2699   if ((lo != 0) || ((hi & 0xffff) != 0)) {
   2700     return false;
   2701   }
   2702 
   2703   // Bits 61:54 must be all clear or all set.
   2704   if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
   2705     return false;
   2706   }
   2707 
   2708   // Bit 62 must be NOT bit 61.
   2709   if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
   2710     return false;
   2711   }
   2712 
   2713   // Create the encoded immediate in the form:
   2714   //  [00000000,0000abcd,00000000,0000efgh]
   2715   *encoding  = (hi >> 16) & 0xf;      // Low nybble.
   2716   *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
   2717   *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
   2718 
   2719   return true;
   2720 }
   2721 
   2722 
   2723 void Assembler::vmov(const SwVfpRegister dst, float imm) {
   2724   uint32_t enc;
   2725   if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) {
   2726     CpuFeatureScope scope(this, VFPv3);
   2727     // The float can be encoded in the instruction.
   2728     //
   2729     // Sd = immediate
   2730     // Instruction details available in ARM DDI 0406C.b, A8-936.
   2731     // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
   2732     // Vd(15-12) | 101(11-9) | sz=0(8) | imm4L(3-0)
   2733     int vd, d;
   2734     dst.split_code(&vd, &d);
   2735     emit(al | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | enc);
   2736   } else {
   2737     mov(ip, Operand(bit_cast<int32_t>(imm)));
   2738     vmov(dst, ip);
   2739   }
   2740 }
   2741 
   2742 
   2743 void Assembler::vmov(const DwVfpRegister dst,
   2744                      double imm,
   2745                      const Register scratch) {
   2746   DCHECK(VfpRegisterIsAvailable(dst));
   2747   DCHECK(!scratch.is(ip));
   2748   uint32_t enc;
   2749   // If the embedded constant pool is disabled, we can use the normal, inline
   2750   // constant pool. If the embedded constant pool is enabled (via
   2751   // FLAG_enable_embedded_constant_pool), we can only use it where the pool
   2752   // pointer (pp) is valid.
   2753   bool can_use_pool =
   2754       !FLAG_enable_embedded_constant_pool || is_constant_pool_available();
   2755   if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) {
   2756     CpuFeatureScope scope(this, VFPv3);
   2757     // The double can be encoded in the instruction.
   2758     //
   2759     // Dd = immediate
   2760     // Instruction details available in ARM DDI 0406C.b, A8-936.
   2761     // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
   2762     // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0)
   2763     int vd, d;
   2764     dst.split_code(&vd, &d);
   2765     emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
   2766   } else if (CpuFeatures::IsSupported(ARMv7) && FLAG_enable_vldr_imm &&
   2767              can_use_pool) {
   2768     CpuFeatureScope scope(this, ARMv7);
   2769     // TODO(jfb) Temporarily turned off until we have constant blinding or
   2770     //           some equivalent mitigation: an attacker can otherwise control
   2771     //           generated data which also happens to be executable, a Very Bad
   2772     //           Thing indeed.
   2773     //           Blinding gets tricky because we don't have xor, we probably
   2774     //           need to add/subtract without losing precision, which requires a
   2775     //           cookie value that Lithium is probably better positioned to
   2776     //           choose.
   2777     //           We could also add a few peepholes here like detecting 0.0 and
   2778     //           -0.0 and doing a vmov from the sequestered d14, forcing denorms
   2779     //           to zero (we set flush-to-zero), and normalizing NaN values.
   2780     //           We could also detect redundant values.
   2781     //           The code could also randomize the order of values, though
   2782     //           that's tricky because vldr has a limited reach. Furthermore
   2783     //           it breaks load locality.
   2784     ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm);
   2785     if (access == ConstantPoolEntry::OVERFLOWED) {
   2786       DCHECK(FLAG_enable_embedded_constant_pool);
   2787       // Emit instructions to load constant pool offset.
   2788       movw(ip, 0);
   2789       movt(ip, 0);
   2790       // Load from constant pool at offset.
   2791       vldr(dst, MemOperand(pp, ip));
   2792     } else {
   2793       DCHECK(access == ConstantPoolEntry::REGULAR);
   2794       vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0));
   2795     }
   2796   } else {
   2797     // Synthesise the double from ARM immediates.
   2798     uint32_t lo, hi;
   2799     DoubleAsTwoUInt32(imm, &lo, &hi);
   2800 
   2801     if (lo == hi) {
   2802       // Move the low and high parts of the double to a D register in one
   2803       // instruction.
   2804       mov(ip, Operand(lo));
   2805       vmov(dst, ip, ip);
   2806     } else if (scratch.is(no_reg)) {
   2807       mov(ip, Operand(lo));
   2808       vmov(dst, VmovIndexLo, ip);
   2809       if (((lo & 0xffff) == (hi & 0xffff)) &&
   2810           CpuFeatures::IsSupported(ARMv7)) {
   2811         CpuFeatureScope scope(this, ARMv7);
   2812         movt(ip, hi >> 16);
   2813       } else {
   2814         mov(ip, Operand(hi));
   2815       }
   2816       vmov(dst, VmovIndexHi, ip);
   2817     } else {
   2818       // Move the low and high parts of the double to a D register in one
   2819       // instruction.
   2820       mov(ip, Operand(lo));
   2821       mov(scratch, Operand(hi));
   2822       vmov(dst, ip, scratch);
   2823     }
   2824   }
   2825 }
   2826 
   2827 
   2828 void Assembler::vmov(const SwVfpRegister dst,
   2829                      const SwVfpRegister src,
   2830                      const Condition cond) {
   2831   // Sd = Sm
   2832   // Instruction details available in ARM DDI 0406B, A8-642.
   2833   int sd, d, sm, m;
   2834   dst.split_code(&sd, &d);
   2835   src.split_code(&sm, &m);
   2836   emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
   2837 }
   2838 
   2839 
   2840 void Assembler::vmov(const DwVfpRegister dst,
   2841                      const DwVfpRegister src,
   2842                      const Condition cond) {
   2843   // Dd = Dm
   2844   // Instruction details available in ARM DDI 0406C.b, A8-938.
   2845   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
   2846   // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   2847   DCHECK(VfpRegisterIsAvailable(dst));
   2848   DCHECK(VfpRegisterIsAvailable(src));
   2849   int vd, d;
   2850   dst.split_code(&vd, &d);
   2851   int vm, m;
   2852   src.split_code(&vm, &m);
   2853   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 |
   2854        vm);
   2855 }
   2856 
   2857 void Assembler::vmov(const DwVfpRegister dst,
   2858                      const VmovIndex index,
   2859                      const Register src,
   2860                      const Condition cond) {
   2861   // Dd[index] = Rt
   2862   // Instruction details available in ARM DDI 0406C.b, A8-940.
   2863   // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
   2864   // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
   2865   DCHECK(VfpRegisterIsAvailable(dst));
   2866   DCHECK(index.index == 0 || index.index == 1);
   2867   int vd, d;
   2868   dst.split_code(&vd, &d);
   2869   emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
   2870        d*B7 | B4);
   2871 }
   2872 
   2873 
   2874 void Assembler::vmov(const Register dst,
   2875                      const VmovIndex index,
   2876                      const DwVfpRegister src,
   2877                      const Condition cond) {
   2878   // Dd[index] = Rt
   2879   // Instruction details available in ARM DDI 0406C.b, A8.8.342.
   2880   // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) |
   2881   // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
   2882   DCHECK(VfpRegisterIsAvailable(src));
   2883   DCHECK(index.index == 0 || index.index == 1);
   2884   int vn, n;
   2885   src.split_code(&vn, &n);
   2886   emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 |
   2887        0xB*B8 | n*B7 | B4);
   2888 }
   2889 
   2890 
   2891 void Assembler::vmov(const DwVfpRegister dst,
   2892                      const Register src1,
   2893                      const Register src2,
   2894                      const Condition cond) {
   2895   // Dm = <Rt,Rt2>.
   2896   // Instruction details available in ARM DDI 0406C.b, A8-948.
   2897   // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
   2898   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
   2899   DCHECK(VfpRegisterIsAvailable(dst));
   2900   DCHECK(!src1.is(pc) && !src2.is(pc));
   2901   int vm, m;
   2902   dst.split_code(&vm, &m);
   2903   emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
   2904        src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
   2905 }
   2906 
   2907 
   2908 void Assembler::vmov(const Register dst1,
   2909                      const Register dst2,
   2910                      const DwVfpRegister src,
   2911                      const Condition cond) {
   2912   // <Rt,Rt2> = Dm.
   2913   // Instruction details available in ARM DDI 0406C.b, A8-948.
   2914   // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
   2915   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
   2916   DCHECK(VfpRegisterIsAvailable(src));
   2917   DCHECK(!dst1.is(pc) && !dst2.is(pc));
   2918   int vm, m;
   2919   src.split_code(&vm, &m);
   2920   emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
   2921        dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
   2922 }
   2923 
   2924 
   2925 void Assembler::vmov(const SwVfpRegister dst,
   2926                      const Register src,
   2927                      const Condition cond) {
   2928   // Sn = Rt.
   2929   // Instruction details available in ARM DDI 0406A, A8-642.
   2930   // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
   2931   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
   2932   DCHECK(!src.is(pc));
   2933   int sn, n;
   2934   dst.split_code(&sn, &n);
   2935   emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
   2936 }
   2937 
   2938 
   2939 void Assembler::vmov(const Register dst,
   2940                      const SwVfpRegister src,
   2941                      const Condition cond) {
   2942   // Rt = Sn.
   2943   // Instruction details available in ARM DDI 0406A, A8-642.
   2944   // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
   2945   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
   2946   DCHECK(!dst.is(pc));
   2947   int sn, n;
   2948   src.split_code(&sn, &n);
   2949   emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
   2950 }
   2951 
   2952 // Type of data to read from or write to VFP register.
   2953 // Used as specifier in generic vcvt instruction.
   2954 enum VFPType { S32, U32, F32, F64 };
   2955 
   2956 
   2957 static bool IsSignedVFPType(VFPType type) {
   2958   switch (type) {
   2959     case S32:
   2960       return true;
   2961     case U32:
   2962       return false;
   2963     default:
   2964       UNREACHABLE();
   2965       return false;
   2966   }
   2967 }
   2968 
   2969 
   2970 static bool IsIntegerVFPType(VFPType type) {
   2971   switch (type) {
   2972     case S32:
   2973     case U32:
   2974       return true;
   2975     case F32:
   2976     case F64:
   2977       return false;
   2978     default:
   2979       UNREACHABLE();
   2980       return false;
   2981   }
   2982 }
   2983 
   2984 
   2985 static bool IsDoubleVFPType(VFPType type) {
   2986   switch (type) {
   2987     case F32:
   2988       return false;
   2989     case F64:
   2990       return true;
   2991     default:
   2992       UNREACHABLE();
   2993       return false;
   2994   }
   2995 }
   2996 
   2997 
   2998 // Split five bit reg_code based on size of reg_type.
   2999 //  32-bit register codes are Vm:M
   3000 //  64-bit register codes are M:Vm
   3001 // where Vm is four bits, and M is a single bit.
   3002 static void SplitRegCode(VFPType reg_type,
   3003                          int reg_code,
   3004                          int* vm,
   3005                          int* m) {
   3006   DCHECK((reg_code >= 0) && (reg_code <= 31));
   3007   if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
   3008     // 32 bit type.
   3009     *m  = reg_code & 0x1;
   3010     *vm = reg_code >> 1;
   3011   } else {
   3012     // 64 bit type.
   3013     *m  = (reg_code & 0x10) >> 4;
   3014     *vm = reg_code & 0x0F;
   3015   }
   3016 }
   3017 
   3018 
   3019 // Encode vcvt.src_type.dst_type instruction.
   3020 static Instr EncodeVCVT(const VFPType dst_type,
   3021                         const int dst_code,
   3022                         const VFPType src_type,
   3023                         const int src_code,
   3024                         VFPConversionMode mode,
   3025                         const Condition cond) {
   3026   DCHECK(src_type != dst_type);
   3027   int D, Vd, M, Vm;
   3028   SplitRegCode(src_type, src_code, &Vm, &M);
   3029   SplitRegCode(dst_type, dst_code, &Vd, &D);
   3030 
   3031   if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
   3032     // Conversion between IEEE floating point and 32-bit integer.
   3033     // Instruction details available in ARM DDI 0406B, A8.6.295.
   3034     // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
   3035     // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3036     DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
   3037 
   3038     int sz, opc2, op;
   3039 
   3040     if (IsIntegerVFPType(dst_type)) {
   3041       opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
   3042       sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
   3043       op = mode;
   3044     } else {
   3045       DCHECK(IsIntegerVFPType(src_type));
   3046       opc2 = 0x0;
   3047       sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
   3048       op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
   3049     }
   3050 
   3051     return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
   3052             Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
   3053   } else {
   3054     // Conversion between IEEE double and single precision.
   3055     // Instruction details available in ARM DDI 0406B, A8.6.298.
   3056     // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
   3057     // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3058     int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
   3059     return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
   3060             Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
   3061   }
   3062 }
   3063 
   3064 
   3065 void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
   3066                              const SwVfpRegister src,
   3067                              VFPConversionMode mode,
   3068                              const Condition cond) {
   3069   DCHECK(VfpRegisterIsAvailable(dst));
   3070   emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
   3071 }
   3072 
   3073 
   3074 void Assembler::vcvt_f32_s32(const SwVfpRegister dst,
   3075                              const SwVfpRegister src,
   3076                              VFPConversionMode mode,
   3077                              const Condition cond) {
   3078   emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
   3079 }
   3080 
   3081 
   3082 void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
   3083                              const SwVfpRegister src,
   3084                              VFPConversionMode mode,
   3085                              const Condition cond) {
   3086   DCHECK(VfpRegisterIsAvailable(dst));
   3087   emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
   3088 }
   3089 
   3090 
   3091 void Assembler::vcvt_f32_u32(const SwVfpRegister dst, const SwVfpRegister src,
   3092                              VFPConversionMode mode, const Condition cond) {
   3093   emit(EncodeVCVT(F32, dst.code(), U32, src.code(), mode, cond));
   3094 }
   3095 
   3096 
   3097 void Assembler::vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
   3098                              VFPConversionMode mode, const Condition cond) {
   3099   emit(EncodeVCVT(S32, dst.code(), F32, src.code(), mode, cond));
   3100 }
   3101 
   3102 
   3103 void Assembler::vcvt_u32_f32(const SwVfpRegister dst, const SwVfpRegister src,
   3104                              VFPConversionMode mode, const Condition cond) {
   3105   emit(EncodeVCVT(U32, dst.code(), F32, src.code(), mode, cond));
   3106 }
   3107 
   3108 
   3109 void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
   3110                              const DwVfpRegister src,
   3111                              VFPConversionMode mode,
   3112                              const Condition cond) {
   3113   DCHECK(VfpRegisterIsAvailable(src));
   3114   emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
   3115 }
   3116 
   3117 
   3118 void Assembler::vcvt_u32_f64(const SwVfpRegister dst,
   3119                              const DwVfpRegister src,
   3120                              VFPConversionMode mode,
   3121                              const Condition cond) {
   3122   DCHECK(VfpRegisterIsAvailable(src));
   3123   emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
   3124 }
   3125 
   3126 
   3127 void Assembler::vcvt_f64_f32(const DwVfpRegister dst,
   3128                              const SwVfpRegister src,
   3129                              VFPConversionMode mode,
   3130                              const Condition cond) {
   3131   DCHECK(VfpRegisterIsAvailable(dst));
   3132   emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
   3133 }
   3134 
   3135 
   3136 void Assembler::vcvt_f32_f64(const SwVfpRegister dst,
   3137                              const DwVfpRegister src,
   3138                              VFPConversionMode mode,
   3139                              const Condition cond) {
   3140   DCHECK(VfpRegisterIsAvailable(src));
   3141   emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
   3142 }
   3143 
   3144 
   3145 void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
   3146                              int fraction_bits,
   3147                              const Condition cond) {
   3148   // Instruction details available in ARM DDI 0406C.b, A8-874.
   3149   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) |
   3150   // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0)
   3151   DCHECK(IsEnabled(VFPv3));
   3152   DCHECK(VfpRegisterIsAvailable(dst));
   3153   DCHECK(fraction_bits > 0 && fraction_bits <= 32);
   3154   int vd, d;
   3155   dst.split_code(&vd, &d);
   3156   int imm5 = 32 - fraction_bits;
   3157   int i = imm5 & 1;
   3158   int imm4 = (imm5 >> 1) & 0xf;
   3159   emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 |
   3160        vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4);
   3161 }
   3162 
   3163 
   3164 void Assembler::vneg(const DwVfpRegister dst,
   3165                      const DwVfpRegister src,
   3166                      const Condition cond) {
   3167   // Instruction details available in ARM DDI 0406C.b, A8-968.
   3168   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
   3169   // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3170   DCHECK(VfpRegisterIsAvailable(dst));
   3171   DCHECK(VfpRegisterIsAvailable(src));
   3172   int vd, d;
   3173   dst.split_code(&vd, &d);
   3174   int vm, m;
   3175   src.split_code(&vm, &m);
   3176 
   3177   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 |
   3178        m*B5 | vm);
   3179 }
   3180 
   3181 
   3182 void Assembler::vneg(const SwVfpRegister dst, const SwVfpRegister src,
   3183                      const Condition cond) {
   3184   // Instruction details available in ARM DDI 0406C.b, A8-968.
   3185   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
   3186   // 101(11-9) | sz=0(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3187   int vd, d;
   3188   dst.split_code(&vd, &d);
   3189   int vm, m;
   3190   src.split_code(&vm, &m);
   3191 
   3192   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
   3193        B6 | m * B5 | vm);
   3194 }
   3195 
   3196 
   3197 void Assembler::vabs(const DwVfpRegister dst,
   3198                      const DwVfpRegister src,
   3199                      const Condition cond) {
   3200   // Instruction details available in ARM DDI 0406C.b, A8-524.
   3201   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
   3202   // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3203   DCHECK(VfpRegisterIsAvailable(dst));
   3204   DCHECK(VfpRegisterIsAvailable(src));
   3205   int vd, d;
   3206   dst.split_code(&vd, &d);
   3207   int vm, m;
   3208   src.split_code(&vm, &m);
   3209   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 |
   3210        m*B5 | vm);
   3211 }
   3212 
   3213 
   3214 void Assembler::vabs(const SwVfpRegister dst, const SwVfpRegister src,
   3215                      const Condition cond) {
   3216   // Instruction details available in ARM DDI 0406C.b, A8-524.
   3217   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
   3218   // 101(11-9) | sz=0(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3219   int vd, d;
   3220   dst.split_code(&vd, &d);
   3221   int vm, m;
   3222   src.split_code(&vm, &m);
   3223   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B7 | B6 |
   3224        m * B5 | vm);
   3225 }
   3226 
   3227 
   3228 void Assembler::vadd(const DwVfpRegister dst,
   3229                      const DwVfpRegister src1,
   3230                      const DwVfpRegister src2,
   3231                      const Condition cond) {
   3232   // Dd = vadd(Dn, Dm) double precision floating point addition.
   3233   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
   3234   // Instruction details available in ARM DDI 0406C.b, A8-830.
   3235   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
   3236   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3237   DCHECK(VfpRegisterIsAvailable(dst));
   3238   DCHECK(VfpRegisterIsAvailable(src1));
   3239   DCHECK(VfpRegisterIsAvailable(src2));
   3240   int vd, d;
   3241   dst.split_code(&vd, &d);
   3242   int vn, n;
   3243   src1.split_code(&vn, &n);
   3244   int vm, m;
   3245   src2.split_code(&vm, &m);
   3246   emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
   3247        n*B7 | m*B5 | vm);
   3248 }
   3249 
   3250 
   3251 void Assembler::vadd(const SwVfpRegister dst, const SwVfpRegister src1,
   3252                      const SwVfpRegister src2, const Condition cond) {
   3253   // Sd = vadd(Sn, Sm) single precision floating point addition.
   3254   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
   3255   // Instruction details available in ARM DDI 0406C.b, A8-830.
   3256   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
   3257   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3258   int vd, d;
   3259   dst.split_code(&vd, &d);
   3260   int vn, n;
   3261   src1.split_code(&vn, &n);
   3262   int vm, m;
   3263   src2.split_code(&vm, &m);
   3264   emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
   3265        0x5 * B9 | n * B7 | m * B5 | vm);
   3266 }
   3267 
   3268 
   3269 void Assembler::vsub(const DwVfpRegister dst,
   3270                      const DwVfpRegister src1,
   3271                      const DwVfpRegister src2,
   3272                      const Condition cond) {
   3273   // Dd = vsub(Dn, Dm) double precision floating point subtraction.
   3274   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
   3275   // Instruction details available in ARM DDI 0406C.b, A8-1086.
   3276   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
   3277   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3278   DCHECK(VfpRegisterIsAvailable(dst));
   3279   DCHECK(VfpRegisterIsAvailable(src1));
   3280   DCHECK(VfpRegisterIsAvailable(src2));
   3281   int vd, d;
   3282   dst.split_code(&vd, &d);
   3283   int vn, n;
   3284   src1.split_code(&vn, &n);
   3285   int vm, m;
   3286   src2.split_code(&vm, &m);
   3287   emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
   3288        n*B7 | B6 | m*B5 | vm);
   3289 }
   3290 
   3291 
   3292 void Assembler::vsub(const SwVfpRegister dst, const SwVfpRegister src1,
   3293                      const SwVfpRegister src2, const Condition cond) {
   3294   // Sd = vsub(Sn, Sm) single precision floating point subtraction.
   3295   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
   3296   // Instruction details available in ARM DDI 0406C.b, A8-1086.
   3297   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
   3298   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3299   int vd, d;
   3300   dst.split_code(&vd, &d);
   3301   int vn, n;
   3302   src1.split_code(&vn, &n);
   3303   int vm, m;
   3304   src2.split_code(&vm, &m);
   3305   emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
   3306        0x5 * B9 | n * B7 | B6 | m * B5 | vm);
   3307 }
   3308 
   3309 
   3310 void Assembler::vmul(const DwVfpRegister dst,
   3311                      const DwVfpRegister src1,
   3312                      const DwVfpRegister src2,
   3313                      const Condition cond) {
   3314   // Dd = vmul(Dn, Dm) double precision floating point multiplication.
   3315   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
   3316   // Instruction details available in ARM DDI 0406C.b, A8-960.
   3317   // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
   3318   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3319   DCHECK(VfpRegisterIsAvailable(dst));
   3320   DCHECK(VfpRegisterIsAvailable(src1));
   3321   DCHECK(VfpRegisterIsAvailable(src2));
   3322   int vd, d;
   3323   dst.split_code(&vd, &d);
   3324   int vn, n;
   3325   src1.split_code(&vn, &n);
   3326   int vm, m;
   3327   src2.split_code(&vm, &m);
   3328   emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
   3329        n*B7 | m*B5 | vm);
   3330 }
   3331 
   3332 
   3333 void Assembler::vmul(const SwVfpRegister dst, const SwVfpRegister src1,
   3334                      const SwVfpRegister src2, const Condition cond) {
   3335   // Sd = vmul(Sn, Sm) single precision floating point multiplication.
   3336   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
   3337   // Instruction details available in ARM DDI 0406C.b, A8-960.
   3338   // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
   3339   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3340   int vd, d;
   3341   dst.split_code(&vd, &d);
   3342   int vn, n;
   3343   src1.split_code(&vn, &n);
   3344   int vm, m;
   3345   src2.split_code(&vm, &m);
   3346   emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 |
   3347        0x5 * B9 | n * B7 | m * B5 | vm);
   3348 }
   3349 
   3350 
   3351 void Assembler::vmla(const DwVfpRegister dst,
   3352                      const DwVfpRegister src1,
   3353                      const DwVfpRegister src2,
   3354                      const Condition cond) {
   3355   // Instruction details available in ARM DDI 0406C.b, A8-932.
   3356   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3357   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
   3358   DCHECK(VfpRegisterIsAvailable(dst));
   3359   DCHECK(VfpRegisterIsAvailable(src1));
   3360   DCHECK(VfpRegisterIsAvailable(src2));
   3361   int vd, d;
   3362   dst.split_code(&vd, &d);
   3363   int vn, n;
   3364   src1.split_code(&vn, &n);
   3365   int vm, m;
   3366   src2.split_code(&vm, &m);
   3367   emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
   3368        vm);
   3369 }
   3370 
   3371 
   3372 void Assembler::vmla(const SwVfpRegister dst, const SwVfpRegister src1,
   3373                      const SwVfpRegister src2, const Condition cond) {
   3374   // Instruction details available in ARM DDI 0406C.b, A8-932.
   3375   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3376   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
   3377   int vd, d;
   3378   dst.split_code(&vd, &d);
   3379   int vn, n;
   3380   src1.split_code(&vn, &n);
   3381   int vm, m;
   3382   src2.split_code(&vm, &m);
   3383   emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
   3384        m * B5 | vm);
   3385 }
   3386 
   3387 
   3388 void Assembler::vmls(const DwVfpRegister dst,
   3389                      const DwVfpRegister src1,
   3390                      const DwVfpRegister src2,
   3391                      const Condition cond) {
   3392   // Instruction details available in ARM DDI 0406C.b, A8-932.
   3393   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3394   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
   3395   DCHECK(VfpRegisterIsAvailable(dst));
   3396   DCHECK(VfpRegisterIsAvailable(src1));
   3397   DCHECK(VfpRegisterIsAvailable(src2));
   3398   int vd, d;
   3399   dst.split_code(&vd, &d);
   3400   int vn, n;
   3401   src1.split_code(&vn, &n);
   3402   int vm, m;
   3403   src2.split_code(&vm, &m);
   3404   emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | B6 |
   3405        m*B5 | vm);
   3406 }
   3407 
   3408 
   3409 void Assembler::vmls(const SwVfpRegister dst, const SwVfpRegister src1,
   3410                      const SwVfpRegister src2, const Condition cond) {
   3411   // Instruction details available in ARM DDI 0406C.b, A8-932.
   3412   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3413   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
   3414   int vd, d;
   3415   dst.split_code(&vd, &d);
   3416   int vn, n;
   3417   src1.split_code(&vn, &n);
   3418   int vm, m;
   3419   src2.split_code(&vm, &m);
   3420   emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
   3421        B6 | m * B5 | vm);
   3422 }
   3423 
   3424 
   3425 void Assembler::vdiv(const DwVfpRegister dst,
   3426                      const DwVfpRegister src1,
   3427                      const DwVfpRegister src2,
   3428                      const Condition cond) {
   3429   // Dd = vdiv(Dn, Dm) double precision floating point division.
   3430   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
   3431   // Instruction details available in ARM DDI 0406C.b, A8-882.
   3432   // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
   3433   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3434   DCHECK(VfpRegisterIsAvailable(dst));
   3435   DCHECK(VfpRegisterIsAvailable(src1));
   3436   DCHECK(VfpRegisterIsAvailable(src2));
   3437   int vd, d;
   3438   dst.split_code(&vd, &d);
   3439   int vn, n;
   3440   src1.split_code(&vn, &n);
   3441   int vm, m;
   3442   src2.split_code(&vm, &m);
   3443   emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
   3444        vm);
   3445 }
   3446 
   3447 
   3448 void Assembler::vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
   3449                      const SwVfpRegister src2, const Condition cond) {
   3450   // Sd = vdiv(Sn, Sm) single precision floating point division.
   3451   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
   3452   // Instruction details available in ARM DDI 0406C.b, A8-882.
   3453   // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
   3454   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3455   int vd, d;
   3456   dst.split_code(&vd, &d);
   3457   int vn, n;
   3458   src1.split_code(&vn, &n);
   3459   int vm, m;
   3460   src2.split_code(&vm, &m);
   3461   emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
   3462        m * B5 | vm);
   3463 }
   3464 
   3465 
   3466 void Assembler::vcmp(const DwVfpRegister src1,
   3467                      const DwVfpRegister src2,
   3468                      const Condition cond) {
   3469   // vcmp(Dd, Dm) double precision floating point comparison.
   3470   // Instruction details available in ARM DDI 0406C.b, A8-864.
   3471   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
   3472   // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3473   DCHECK(VfpRegisterIsAvailable(src1));
   3474   DCHECK(VfpRegisterIsAvailable(src2));
   3475   int vd, d;
   3476   src1.split_code(&vd, &d);
   3477   int vm, m;
   3478   src2.split_code(&vm, &m);
   3479   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 |
   3480        m*B5 | vm);
   3481 }
   3482 
   3483 
   3484 void Assembler::vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
   3485                      const Condition cond) {
   3486   // vcmp(Sd, Sm) single precision floating point comparison.
   3487   // Instruction details available in ARM DDI 0406C.b, A8-864.
   3488   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
   3489   // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3490   int vd, d;
   3491   src1.split_code(&vd, &d);
   3492   int vm, m;
   3493   src2.split_code(&vm, &m);
   3494   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 |
   3495        0x5 * B9 | B6 | m * B5 | vm);
   3496 }
   3497 
   3498 
   3499 void Assembler::vcmp(const DwVfpRegister src1,
   3500                      const double src2,
   3501                      const Condition cond) {
   3502   // vcmp(Dd, #0.0) double precision floating point comparison.
   3503   // Instruction details available in ARM DDI 0406C.b, A8-864.
   3504   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
   3505   // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
   3506   DCHECK(VfpRegisterIsAvailable(src1));
   3507   DCHECK(src2 == 0.0);
   3508   int vd, d;
   3509   src1.split_code(&vd, &d);
   3510   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6);
   3511 }
   3512 
   3513 
   3514 void Assembler::vcmp(const SwVfpRegister src1, const float src2,
   3515                      const Condition cond) {
   3516   // vcmp(Sd, #0.0) single precision floating point comparison.
   3517   // Instruction details available in ARM DDI 0406C.b, A8-864.
   3518   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
   3519   // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
   3520   DCHECK(src2 == 0.0);
   3521   int vd, d;
   3522   src1.split_code(&vd, &d);
   3523   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 |
   3524        0x5 * B9 | B6);
   3525 }
   3526 
   3527 void Assembler::vmaxnm(const DwVfpRegister dst, const DwVfpRegister src1,
   3528                        const DwVfpRegister src2) {
   3529   // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3530   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3531   DCHECK(IsEnabled(ARMv8));
   3532   int vd, d;
   3533   dst.split_code(&vd, &d);
   3534   int vn, n;
   3535   src1.split_code(&vn, &n);
   3536   int vm, m;
   3537   src2.split_code(&vm, &m);
   3538 
   3539   emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
   3540        0x5 * B9 | B8 | n * B7 | m * B5 | vm);
   3541 }
   3542 
   3543 void Assembler::vmaxnm(const SwVfpRegister dst, const SwVfpRegister src1,
   3544                        const SwVfpRegister src2) {
   3545   // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3546   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
   3547   DCHECK(IsEnabled(ARMv8));
   3548   int vd, d;
   3549   dst.split_code(&vd, &d);
   3550   int vn, n;
   3551   src1.split_code(&vn, &n);
   3552   int vm, m;
   3553   src2.split_code(&vm, &m);
   3554 
   3555   emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
   3556        0x5 * B9 | n * B7 | m * B5 | vm);
   3557 }
   3558 
   3559 void Assembler::vminnm(const DwVfpRegister dst, const DwVfpRegister src1,
   3560                        const DwVfpRegister src2) {
   3561   // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3562   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3563   DCHECK(IsEnabled(ARMv8));
   3564   int vd, d;
   3565   dst.split_code(&vd, &d);
   3566   int vn, n;
   3567   src1.split_code(&vn, &n);
   3568   int vm, m;
   3569   src2.split_code(&vm, &m);
   3570 
   3571   emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
   3572        0x5 * B9 | B8 | n * B7 | B6 | m * B5 | vm);
   3573 }
   3574 
   3575 void Assembler::vminnm(const SwVfpRegister dst, const SwVfpRegister src1,
   3576                        const SwVfpRegister src2) {
   3577   // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
   3578   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3579   DCHECK(IsEnabled(ARMv8));
   3580   int vd, d;
   3581   dst.split_code(&vd, &d);
   3582   int vn, n;
   3583   src1.split_code(&vn, &n);
   3584   int vm, m;
   3585   src2.split_code(&vm, &m);
   3586 
   3587   emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
   3588        0x5 * B9 | n * B7 | B6 | m * B5 | vm);
   3589 }
   3590 
   3591 void Assembler::vsel(Condition cond, const DwVfpRegister dst,
   3592                      const DwVfpRegister src1, const DwVfpRegister src2) {
   3593   // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
   3594   // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=1(8) | N(7) |
   3595   // 0(6) | M(5) | 0(4) | Vm(3-0)
   3596   DCHECK(IsEnabled(ARMv8));
   3597   int vd, d;
   3598   dst.split_code(&vd, &d);
   3599   int vn, n;
   3600   src1.split_code(&vn, &n);
   3601   int vm, m;
   3602   src2.split_code(&vm, &m);
   3603   int sz = 1;
   3604 
   3605   // VSEL has a special (restricted) condition encoding.
   3606   //   eq(0b0000)... -> 0b00
   3607   //   ge(0b1010)... -> 0b10
   3608   //   gt(0b1100)... -> 0b11
   3609   //   vs(0b0110)... -> 0b01
   3610   // No other conditions are supported.
   3611   int vsel_cond = (cond >> 30) & 0x3;
   3612   if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
   3613     // We can implement some other conditions by swapping the inputs.
   3614     DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
   3615     std::swap(vn, vm);
   3616     std::swap(n, m);
   3617   }
   3618 
   3619   emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
   3620        vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
   3621 }
   3622 
   3623 void Assembler::vsel(Condition cond, const SwVfpRegister dst,
   3624                      const SwVfpRegister src1, const SwVfpRegister src2) {
   3625   // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
   3626   // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=0(8) | N(7) |
   3627   // 0(6) | M(5) | 0(4) | Vm(3-0)
   3628   DCHECK(IsEnabled(ARMv8));
   3629   int vd, d;
   3630   dst.split_code(&vd, &d);
   3631   int vn, n;
   3632   src1.split_code(&vn, &n);
   3633   int vm, m;
   3634   src2.split_code(&vm, &m);
   3635   int sz = 0;
   3636 
   3637   // VSEL has a special (restricted) condition encoding.
   3638   //   eq(0b0000)... -> 0b00
   3639   //   ge(0b1010)... -> 0b10
   3640   //   gt(0b1100)... -> 0b11
   3641   //   vs(0b0110)... -> 0b01
   3642   // No other conditions are supported.
   3643   int vsel_cond = (cond >> 30) & 0x3;
   3644   if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
   3645     // We can implement some other conditions by swapping the inputs.
   3646     DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
   3647     std::swap(vn, vm);
   3648     std::swap(n, m);
   3649   }
   3650 
   3651   emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
   3652        vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
   3653 }
   3654 
   3655 void Assembler::vsqrt(const DwVfpRegister dst,
   3656                       const DwVfpRegister src,
   3657                       const Condition cond) {
   3658   // Instruction details available in ARM DDI 0406C.b, A8-1058.
   3659   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
   3660   // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
   3661   DCHECK(VfpRegisterIsAvailable(dst));
   3662   DCHECK(VfpRegisterIsAvailable(src));
   3663   int vd, d;
   3664   dst.split_code(&vd, &d);
   3665   int vm, m;
   3666   src.split_code(&vm, &m);
   3667   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 |
   3668        m*B5 | vm);
   3669 }
   3670 
   3671 
   3672 void Assembler::vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
   3673                       const Condition cond) {
   3674   // Instruction details available in ARM DDI 0406C.b, A8-1058.
   3675   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
   3676   // Vd(15-12) | 101(11-9) | sz=0(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
   3677   int vd, d;
   3678   dst.split_code(&vd, &d);
   3679   int vm, m;
   3680   src.split_code(&vm, &m);
   3681   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
   3682        0x3 * B6 | m * B5 | vm);
   3683 }
   3684 
   3685 
   3686 void Assembler::vmsr(Register dst, Condition cond) {
   3687   // Instruction details available in ARM DDI 0406A, A8-652.
   3688   // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
   3689   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
   3690   emit(cond | 0xE * B24 | 0xE * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
   3691 }
   3692 
   3693 
   3694 void Assembler::vmrs(Register dst, Condition cond) {
   3695   // Instruction details available in ARM DDI 0406A, A8-652.
   3696   // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
   3697   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
   3698   emit(cond | 0xE * B24 | 0xF * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
   3699 }
   3700 
   3701 
   3702 void Assembler::vrinta(const SwVfpRegister dst, const SwVfpRegister src) {
   3703   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3704   // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
   3705   // M(5) | 0(4) | Vm(3-0)
   3706   DCHECK(IsEnabled(ARMv8));
   3707   int vd, d;
   3708   dst.split_code(&vd, &d);
   3709   int vm, m;
   3710   src.split_code(&vm, &m);
   3711   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
   3712        0x5 * B9 | B6 | m * B5 | vm);
   3713 }
   3714 
   3715 
   3716 void Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) {
   3717   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3718   // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
   3719   // M(5) | 0(4) | Vm(3-0)
   3720   DCHECK(IsEnabled(ARMv8));
   3721   int vd, d;
   3722   dst.split_code(&vd, &d);
   3723   int vm, m;
   3724   src.split_code(&vm, &m);
   3725   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
   3726        0x5 * B9 | B8 | B6 | m * B5 | vm);
   3727 }
   3728 
   3729 
   3730 void Assembler::vrintn(const SwVfpRegister dst, const SwVfpRegister src) {
   3731   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3732   // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
   3733   // M(5) | 0(4) | Vm(3-0)
   3734   DCHECK(IsEnabled(ARMv8));
   3735   int vd, d;
   3736   dst.split_code(&vd, &d);
   3737   int vm, m;
   3738   src.split_code(&vm, &m);
   3739   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
   3740        vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
   3741 }
   3742 
   3743 
   3744 void Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) {
   3745   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3746   // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
   3747   // M(5) | 0(4) | Vm(3-0)
   3748   DCHECK(IsEnabled(ARMv8));
   3749   int vd, d;
   3750   dst.split_code(&vd, &d);
   3751   int vm, m;
   3752   src.split_code(&vm, &m);
   3753   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
   3754        vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
   3755 }
   3756 
   3757 
   3758 void Assembler::vrintp(const SwVfpRegister dst, const SwVfpRegister src) {
   3759   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3760   // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
   3761   // M(5) | 0(4) | Vm(3-0)
   3762   DCHECK(IsEnabled(ARMv8));
   3763   int vd, d;
   3764   dst.split_code(&vd, &d);
   3765   int vm, m;
   3766   src.split_code(&vm, &m);
   3767   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
   3768        vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
   3769 }
   3770 
   3771 
   3772 void Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) {
   3773   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3774   // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
   3775   // M(5) | 0(4) | Vm(3-0)
   3776   DCHECK(IsEnabled(ARMv8));
   3777   int vd, d;
   3778   dst.split_code(&vd, &d);
   3779   int vm, m;
   3780   src.split_code(&vm, &m);
   3781   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
   3782        vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
   3783 }
   3784 
   3785 
   3786 void Assembler::vrintm(const SwVfpRegister dst, const SwVfpRegister src) {
   3787   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3788   // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
   3789   // M(5) | 0(4) | Vm(3-0)
   3790   DCHECK(IsEnabled(ARMv8));
   3791   int vd, d;
   3792   dst.split_code(&vd, &d);
   3793   int vm, m;
   3794   src.split_code(&vm, &m);
   3795   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
   3796        vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
   3797 }
   3798 
   3799 
   3800 void Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) {
   3801   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
   3802   // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
   3803   // M(5) | 0(4) | Vm(3-0)
   3804   DCHECK(IsEnabled(ARMv8));
   3805   int vd, d;
   3806   dst.split_code(&vd, &d);
   3807   int vm, m;
   3808   src.split_code(&vm, &m);
   3809   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
   3810        vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
   3811 }
   3812 
   3813 
   3814 void Assembler::vrintz(const SwVfpRegister dst, const SwVfpRegister src,
   3815                        const Condition cond) {
   3816   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
   3817   // Vd(15-12) | 101(11-9) | sz=0(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3818   DCHECK(IsEnabled(ARMv8));
   3819   int vd, d;
   3820   dst.split_code(&vd, &d);
   3821   int vm, m;
   3822   src.split_code(&vm, &m);
   3823   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
   3824        0x5 * B9 | B7 | B6 | m * B5 | vm);
   3825 }
   3826 
   3827 
   3828 void Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src,
   3829                        const Condition cond) {
   3830   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
   3831   // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
   3832   DCHECK(IsEnabled(ARMv8));
   3833   int vd, d;
   3834   dst.split_code(&vd, &d);
   3835   int vm, m;
   3836   src.split_code(&vm, &m);
   3837   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
   3838        0x5 * B9 | B8 | B7 | B6 | m * B5 | vm);
   3839 }
   3840 
   3841 
   3842 // Support for NEON.
   3843 
   3844 void Assembler::vld1(NeonSize size,
   3845                      const NeonListOperand& dst,
   3846                      const NeonMemOperand& src) {
   3847   // Instruction details available in ARM DDI 0406C.b, A8.8.320.
   3848   // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) |
   3849   // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
   3850   DCHECK(IsEnabled(NEON));
   3851   int vd, d;
   3852   dst.base().split_code(&vd, &d);
   3853   emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 |
   3854        dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code());
   3855 }
   3856 
   3857 
   3858 void Assembler::vst1(NeonSize size,
   3859                      const NeonListOperand& src,
   3860                      const NeonMemOperand& dst) {
   3861   // Instruction details available in ARM DDI 0406C.b, A8.8.404.
   3862   // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
   3863   // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
   3864   DCHECK(IsEnabled(NEON));
   3865   int vd, d;
   3866   src.base().split_code(&vd, &d);
   3867   emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 |
   3868        size*B6 | dst.align()*B4 | dst.rm().code());
   3869 }
   3870 
   3871 
   3872 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) {
   3873   // Instruction details available in ARM DDI 0406C.b, A8.8.346.
   3874   // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) |
   3875   // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0)
   3876   DCHECK(IsEnabled(NEON));
   3877   int vd, d;
   3878   dst.split_code(&vd, &d);
   3879   int vm, m;
   3880   src.split_code(&vm, &m);
   3881   int U = NeonU(dt);
   3882   int imm3 = 1 << NeonSz(dt);
   3883   emit(0xFU * B28 | B25 | U * B24 | B23 | d * B22 | imm3 * B19 | vd * B12 |
   3884        0xA * B8 | m * B5 | B4 | vm);
   3885 }
   3886 
   3887 static int EncodeScalar(NeonDataType dt, int index) {
   3888   int opc1_opc2 = 0;
   3889   DCHECK_LE(0, index);
   3890   switch (dt) {
   3891     case NeonS8:
   3892     case NeonU8:
   3893       DCHECK_GT(8, index);
   3894       opc1_opc2 = 0x8 | index;
   3895       break;
   3896     case NeonS16:
   3897     case NeonU16:
   3898       DCHECK_GT(4, index);
   3899       opc1_opc2 = 0x1 | (index << 1);
   3900       break;
   3901     case NeonS32:
   3902     case NeonU32:
   3903       DCHECK_GT(2, index);
   3904       opc1_opc2 = index << 2;
   3905       break;
   3906     default:
   3907       UNREACHABLE();
   3908       break;
   3909   }
   3910   return (opc1_opc2 >> 2) * B21 | (opc1_opc2 & 0x3) * B5;
   3911 }
   3912 
   3913 void Assembler::vmov(NeonDataType dt, DwVfpRegister dst, int index,
   3914                      Register src) {
   3915   // Instruction details available in ARM DDI 0406C.b, A8.8.940.
   3916   // vmov ARM core register to scalar.
   3917   DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON));
   3918   int vd, d;
   3919   dst.split_code(&vd, &d);
   3920   int opc1_opc2 = EncodeScalar(dt, index);
   3921   emit(0xEEu * B24 | vd * B16 | src.code() * B12 | 0xB * B8 | d * B7 | B4 |
   3922        opc1_opc2);
   3923 }
   3924 
   3925 void Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src,
   3926                      int index) {
   3927   // Instruction details available in ARM DDI 0406C.b, A8.8.942.
   3928   // vmov Arm scalar to core register.
   3929   DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON));
   3930   int vn, n;
   3931   src.split_code(&vn, &n);
   3932   int opc1_opc2 = EncodeScalar(dt, index);
   3933   int u = NeonU(dt);
   3934   emit(0xEEu * B24 | u * B23 | B20 | vn * B16 | dst.code() * B12 | 0xB * B8 |
   3935        n * B7 | B4 | opc1_opc2);
   3936 }
   3937 
   3938 void Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) {
   3939   // Instruction details available in ARM DDI 0406C.b, A8-938.
   3940   // vmov is encoded as vorr.
   3941   vorr(dst, src, src);
   3942 }
   3943 
   3944 void Assembler::vmvn(const QwNeonRegister dst, const QwNeonRegister src) {
   3945   DCHECK(IsEnabled(NEON));
   3946   // Instruction details available in ARM DDI 0406C.b, A8-966.
   3947   DCHECK(VfpRegisterIsAvailable(dst));
   3948   DCHECK(VfpRegisterIsAvailable(src));
   3949   int vd, d;
   3950   dst.split_code(&vd, &d);
   3951   int vm, m;
   3952   src.split_code(&vm, &m);
   3953   emit(0x1E7U * B23 | d * B22 | 3 * B20 | vd * B12 | 0x17 * B6 | m * B5 | vm);
   3954 }
   3955 
   3956 void Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) {
   3957   // Instruction details available in ARM DDI 0406C.b, A8.8.418.
   3958   // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) |
   3959   // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0)
   3960   DCHECK(IsEnabled(NEON));
   3961   int vd, d;
   3962   dst.split_code(&vd, &d);
   3963   int vm, m;
   3964   src.split_code(&vm, &m);
   3965   emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | m * B5 | vm);
   3966 }
   3967 
   3968 void Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) {
   3969   // Instruction details available in ARM DDI 0406C.b, A8.8.418.
   3970   // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) |
   3971   // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0)
   3972   DCHECK(IsEnabled(NEON));
   3973   int vd, d;
   3974   dst.split_code(&vd, &d);
   3975   int vm, m;
   3976   src.split_code(&vm, &m);
   3977   emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | B6 | m * B5 |
   3978        vm);
   3979 }
   3980 
   3981 void Assembler::vdup(NeonSize size, const QwNeonRegister dst,
   3982                      const Register src) {
   3983   DCHECK(IsEnabled(NEON));
   3984   // Instruction details available in ARM DDI 0406C.b, A8-886.
   3985   int B = 0, E = 0;
   3986   switch (size) {
   3987     case Neon8:
   3988       B = 1;
   3989       break;
   3990     case Neon16:
   3991       E = 1;
   3992       break;
   3993     case Neon32:
   3994       break;
   3995     default:
   3996       UNREACHABLE();
   3997       break;
   3998   }
   3999   int vd, d;
   4000   dst.split_code(&vd, &d);
   4001 
   4002   emit(al | 0x1D * B23 | B * B22 | B21 | vd * B16 | src.code() * B12 |
   4003        0xB * B8 | d * B7 | E * B5 | B4);
   4004 }
   4005 
   4006 void Assembler::vdup(const QwNeonRegister dst, const SwVfpRegister src) {
   4007   DCHECK(IsEnabled(NEON));
   4008   // Instruction details available in ARM DDI 0406C.b, A8-884.
   4009   int index = src.code() & 1;
   4010   int d_reg = src.code() / 2;
   4011   int imm4 = 4 | index << 3;  // esize = 32, index in bit 3.
   4012   int vd, d;
   4013   dst.split_code(&vd, &d);
   4014   int vm, m;
   4015   DwVfpRegister::from_code(d_reg).split_code(&vm, &m);
   4016 
   4017   emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 | 0x18 * B7 |
   4018        B6 | m * B5 | vm);
   4019 }
   4020 
   4021 // Encode NEON vcvt.src_type.dst_type instruction.
   4022 static Instr EncodeNeonVCVT(const VFPType dst_type, const QwNeonRegister dst,
   4023                             const VFPType src_type, const QwNeonRegister src) {
   4024   DCHECK(src_type != dst_type);
   4025   DCHECK(src_type == F32 || dst_type == F32);
   4026   // Instruction details available in ARM DDI 0406C.b, A8.8.868.
   4027   int vd, d;
   4028   dst.split_code(&vd, &d);
   4029   int vm, m;
   4030   src.split_code(&vm, &m);
   4031 
   4032   int op = 0;
   4033   if (src_type == F32) {
   4034     DCHECK(dst_type == S32 || dst_type == U32);
   4035     op = dst_type == U32 ? 3 : 2;
   4036   } else {
   4037     DCHECK(src_type == S32 || src_type == U32);
   4038     op = src_type == U32 ? 1 : 0;
   4039   }
   4040 
   4041   return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x3 * B9 | op * B7 |
   4042          B6 | m * B5 | vm;
   4043 }
   4044 
   4045 void Assembler::vcvt_f32_s32(const QwNeonRegister dst,
   4046                              const QwNeonRegister src) {
   4047   DCHECK(IsEnabled(NEON));
   4048   DCHECK(VfpRegisterIsAvailable(dst));
   4049   DCHECK(VfpRegisterIsAvailable(src));
   4050   emit(EncodeNeonVCVT(F32, dst, S32, src));
   4051 }
   4052 
   4053 void Assembler::vcvt_f32_u32(const QwNeonRegister dst,
   4054                              const QwNeonRegister src) {
   4055   DCHECK(IsEnabled(NEON));
   4056   DCHECK(VfpRegisterIsAvailable(dst));
   4057   DCHECK(VfpRegisterIsAvailable(src));
   4058   emit(EncodeNeonVCVT(F32, dst, U32, src));
   4059 }
   4060 
   4061 void Assembler::vcvt_s32_f32(const QwNeonRegister dst,
   4062                              const QwNeonRegister src) {
   4063   DCHECK(IsEnabled(NEON));
   4064   DCHECK(VfpRegisterIsAvailable(dst));
   4065   DCHECK(VfpRegisterIsAvailable(src));
   4066   emit(EncodeNeonVCVT(S32, dst, F32, src));
   4067 }
   4068 
   4069 void Assembler::vcvt_u32_f32(const QwNeonRegister dst,
   4070                              const QwNeonRegister src) {
   4071   DCHECK(IsEnabled(NEON));
   4072   DCHECK(VfpRegisterIsAvailable(dst));
   4073   DCHECK(VfpRegisterIsAvailable(src));
   4074   emit(EncodeNeonVCVT(U32, dst, F32, src));
   4075 }
   4076 
   4077 // op is instr->Bits(11, 7).
   4078 static Instr EncodeNeonUnaryOp(int op, bool is_float, NeonSize size,
   4079                                const QwNeonRegister dst,
   4080                                const QwNeonRegister src) {
   4081   DCHECK_IMPLIES(is_float, size == Neon32);
   4082   int vd, d;
   4083   dst.split_code(&vd, &d);
   4084   int vm, m;
   4085   src.split_code(&vm, &m);
   4086   int F = is_float ? 1 : 0;
   4087   return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | B16 | vd * B12 |
   4088          F * B10 | B8 | op * B7 | B6 | m * B5 | vm;
   4089 }
   4090 
   4091 void Assembler::vabs(const QwNeonRegister dst, const QwNeonRegister src) {
   4092   // Qd = vabs.f<size>(Qn, Qm) SIMD floating point absolute value.
   4093   // Instruction details available in ARM DDI 0406C.b, A8.8.824.
   4094   DCHECK(IsEnabled(NEON));
   4095   emit(EncodeNeonUnaryOp(0x6, true, Neon32, dst, src));
   4096 }
   4097 
   4098 void Assembler::vabs(NeonSize size, const QwNeonRegister dst,
   4099                      const QwNeonRegister src) {
   4100   // Qd = vabs.s<size>(Qn, Qm) SIMD integer absolute value.
   4101   // Instruction details available in ARM DDI 0406C.b, A8.8.824.
   4102   DCHECK(IsEnabled(NEON));
   4103   emit(EncodeNeonUnaryOp(0x6, false, size, dst, src));
   4104 }
   4105 
   4106 void Assembler::vneg(const QwNeonRegister dst, const QwNeonRegister src) {
   4107   // Qd = vabs.f<size>(Qn, Qm) SIMD floating point negate.
   4108   // Instruction details available in ARM DDI 0406C.b, A8.8.968.
   4109   DCHECK(IsEnabled(NEON));
   4110   emit(EncodeNeonUnaryOp(0x7, true, Neon32, dst, src));
   4111 }
   4112 
   4113 void Assembler::vneg(NeonSize size, const QwNeonRegister dst,
   4114                      const QwNeonRegister src) {
   4115   // Qd = vabs.s<size>(Qn, Qm) SIMD integer negate.
   4116   // Instruction details available in ARM DDI 0406C.b, A8.8.968.
   4117   DCHECK(IsEnabled(NEON));
   4118   emit(EncodeNeonUnaryOp(0x7, false, size, dst, src));
   4119 }
   4120 
   4121 void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1,
   4122                      DwVfpRegister src2) {
   4123   // Dd = veor(Dn, Dm) 64 bit integer exclusive OR.
   4124   // Instruction details available in ARM DDI 0406C.b, A8.8.888.
   4125   DCHECK(IsEnabled(NEON));
   4126   int vd, d;
   4127   dst.split_code(&vd, &d);
   4128   int vn, n;
   4129   src1.split_code(&vn, &n);
   4130   int vm, m;
   4131   src2.split_code(&vm, &m);
   4132   emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | m * B5 |
   4133        B4 | vm);
   4134 }
   4135 
   4136 enum BinaryBitwiseOp { VAND, VBIC, VBIF, VBIT, VBSL, VEOR, VORR, VORN };
   4137 
   4138 static Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op,
   4139                                        const QwNeonRegister dst,
   4140                                        const QwNeonRegister src1,
   4141                                        const QwNeonRegister src2) {
   4142   int op_encoding = 0;
   4143   switch (op) {
   4144     case VBIC:
   4145       op_encoding = 0x1 * B20;
   4146       break;
   4147     case VBIF:
   4148       op_encoding = B24 | 0x3 * B20;
   4149       break;
   4150     case VBIT:
   4151       op_encoding = B24 | 0x2 * B20;
   4152       break;
   4153     case VBSL:
   4154       op_encoding = B24 | 0x1 * B20;
   4155       break;
   4156     case VEOR:
   4157       op_encoding = B24;
   4158       break;
   4159     case VORR:
   4160       op_encoding = 0x2 * B20;
   4161       break;
   4162     case VORN:
   4163       op_encoding = 0x3 * B20;
   4164       break;
   4165     case VAND:
   4166       // op_encoding is 0.
   4167       break;
   4168     default:
   4169       UNREACHABLE();
   4170       break;
   4171   }
   4172   int vd, d;
   4173   dst.split_code(&vd, &d);
   4174   int vn, n;
   4175   src1.split_code(&vn, &n);
   4176   int vm, m;
   4177   src2.split_code(&vm, &m);
   4178   return 0x1E4U * B23 | op_encoding | d * B22 | vn * B16 | vd * B12 | B8 |
   4179          n * B7 | B6 | m * B5 | B4 | vm;
   4180 }
   4181 
   4182 void Assembler::vand(QwNeonRegister dst, QwNeonRegister src1,
   4183                      QwNeonRegister src2) {
   4184   // Qd = vand(Qn, Qm) SIMD AND.
   4185   // Instruction details available in ARM DDI 0406C.b, A8.8.836.
   4186   DCHECK(IsEnabled(NEON));
   4187   emit(EncodeNeonBinaryBitwiseOp(VAND, dst, src1, src2));
   4188 }
   4189 
   4190 void Assembler::vbsl(QwNeonRegister dst, const QwNeonRegister src1,
   4191                      const QwNeonRegister src2) {
   4192   DCHECK(IsEnabled(NEON));
   4193   // Qd = vbsl(Qn, Qm) SIMD bitwise select.
   4194   // Instruction details available in ARM DDI 0406C.b, A8-844.
   4195   emit(EncodeNeonBinaryBitwiseOp(VBSL, dst, src1, src2));
   4196 }
   4197 
   4198 void Assembler::veor(QwNeonRegister dst, QwNeonRegister src1,
   4199                      QwNeonRegister src2) {
   4200   // Qd = veor(Qn, Qm) SIMD exclusive OR.
   4201   // Instruction details available in ARM DDI 0406C.b, A8.8.888.
   4202   DCHECK(IsEnabled(NEON));
   4203   emit(EncodeNeonBinaryBitwiseOp(VEOR, dst, src1, src2));
   4204 }
   4205 
   4206 void Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1,
   4207                      QwNeonRegister src2) {
   4208   // Qd = vorr(Qn, Qm) SIMD OR.
   4209   // Instruction details available in ARM DDI 0406C.b, A8.8.976.
   4210   DCHECK(IsEnabled(NEON));
   4211   emit(EncodeNeonBinaryBitwiseOp(VORR, dst, src1, src2));
   4212 }
   4213 
   4214 enum FPBinOp {
   4215   VADDF,
   4216   VSUBF,
   4217   VMULF,
   4218   VMINF,
   4219   VMAXF,
   4220   VRECPS,
   4221   VRSQRTS,
   4222   VCEQF,
   4223   VCGEF,
   4224   VCGTF
   4225 };
   4226 
   4227 static Instr EncodeNeonBinOp(FPBinOp op, QwNeonRegister dst,
   4228                              QwNeonRegister src1, QwNeonRegister src2) {
   4229   int op_encoding = 0;
   4230   switch (op) {
   4231     case VADDF:
   4232       op_encoding = 0xD * B8;
   4233       break;
   4234     case VSUBF:
   4235       op_encoding = B21 | 0xD * B8;
   4236       break;
   4237     case VMULF:
   4238       op_encoding = B24 | 0xD * B8 | B4;
   4239       break;
   4240     case VMINF:
   4241       op_encoding = B21 | 0xF * B8;
   4242       break;
   4243     case VMAXF:
   4244       op_encoding = 0xF * B8;
   4245       break;
   4246     case VRECPS:
   4247       op_encoding = 0xF * B8 | B4;
   4248       break;
   4249     case VRSQRTS:
   4250       op_encoding = B21 | 0xF * B8 | B4;
   4251       break;
   4252     case VCEQF:
   4253       op_encoding = 0xE * B8;
   4254       break;
   4255     case VCGEF:
   4256       op_encoding = B24 | 0xE * B8;
   4257       break;
   4258     case VCGTF:
   4259       op_encoding = B24 | B21 | 0xE * B8;
   4260       break;
   4261     default:
   4262       UNREACHABLE();
   4263       break;
   4264   }
   4265   int vd, d;
   4266   dst.split_code(&vd, &d);
   4267   int vn, n;
   4268   src1.split_code(&vn, &n);
   4269   int vm, m;
   4270   src2.split_code(&vm, &m);
   4271   return 0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | n * B7 | B6 | m * B5 |
   4272          vm | op_encoding;
   4273 }
   4274 
   4275 enum IntegerBinOp {
   4276   VADD,
   4277   VQADD,
   4278   VSUB,
   4279   VQSUB,
   4280   VMUL,
   4281   VMIN,
   4282   VMAX,
   4283   VTST,
   4284   VCEQ,
   4285   VCGE,
   4286   VCGT
   4287 };
   4288 
   4289 static Instr EncodeNeonBinOp(IntegerBinOp op, NeonDataType dt,
   4290                              const QwNeonRegister dst,
   4291                              const QwNeonRegister src1,
   4292                              const QwNeonRegister src2) {
   4293   int op_encoding = 0;
   4294   switch (op) {
   4295     case VADD:
   4296       op_encoding = 0x8 * B8;
   4297       break;
   4298     case VQADD:
   4299       op_encoding = B4;
   4300       break;
   4301     case VSUB:
   4302       op_encoding = B24 | 0x8 * B8;
   4303       break;
   4304     case VQSUB:
   4305       op_encoding = 0x2 * B8 | B4;
   4306       break;
   4307     case VMUL:
   4308       op_encoding = 0x9 * B8 | B4;
   4309       break;
   4310     case VMIN:
   4311       op_encoding = 0x6 * B8 | B4;
   4312       break;
   4313     case VMAX:
   4314       op_encoding = 0x6 * B8;
   4315       break;
   4316     case VTST:
   4317       op_encoding = 0x8 * B8 | B4;
   4318       break;
   4319     case VCEQ:
   4320       op_encoding = B24 | 0x8 * B8 | B4;
   4321       break;
   4322     case VCGE:
   4323       op_encoding = 0x3 * B8 | B4;
   4324       break;
   4325     case VCGT:
   4326       op_encoding = 0x3 * B8;
   4327       break;
   4328     default:
   4329       UNREACHABLE();
   4330       break;
   4331   }
   4332   int vd, d;
   4333   dst.split_code(&vd, &d);
   4334   int vn, n;
   4335   src1.split_code(&vn, &n);
   4336   int vm, m;
   4337   src2.split_code(&vm, &m);
   4338   int size = NeonSz(dt);
   4339   int u = NeonU(dt);
   4340   return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 |
   4341          n * B7 | B6 | m * B5 | vm | op_encoding;
   4342 }
   4343 
   4344 static Instr EncodeNeonBinOp(IntegerBinOp op, NeonSize size,
   4345                              const QwNeonRegister dst,
   4346                              const QwNeonRegister src1,
   4347                              const QwNeonRegister src2) {
   4348   // Map NeonSize values to the signed values in NeonDataType, so the U bit
   4349   // will be 0.
   4350   return EncodeNeonBinOp(op, static_cast<NeonDataType>(size), dst, src1, src2);
   4351 }
   4352 
   4353 void Assembler::vadd(QwNeonRegister dst, QwNeonRegister src1,
   4354                      QwNeonRegister src2) {
   4355   DCHECK(IsEnabled(NEON));
   4356   // Qd = vadd(Qn, Qm) SIMD floating point addition.
   4357   // Instruction details available in ARM DDI 0406C.b, A8-830.
   4358   emit(EncodeNeonBinOp(VADDF, dst, src1, src2));
   4359 }
   4360 
   4361 void Assembler::vadd(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
   4362                      QwNeonRegister src2) {
   4363   DCHECK(IsEnabled(NEON));
   4364   // Qd = vadd(Qn, Qm) SIMD integer addition.
   4365   // Instruction details available in ARM DDI 0406C.b, A8-828.
   4366   emit(EncodeNeonBinOp(VADD, size, dst, src1, src2));
   4367 }
   4368 
   4369 void Assembler::vqadd(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
   4370                       QwNeonRegister src2) {
   4371   DCHECK(IsEnabled(NEON));
   4372   // Qd = vqadd(Qn, Qm) SIMD integer saturating addition.
   4373   // Instruction details available in ARM DDI 0406C.b, A8-996.
   4374   emit(EncodeNeonBinOp(VQADD, dt, dst, src1, src2));
   4375 }
   4376 
   4377 void Assembler::vsub(QwNeonRegister dst, QwNeonRegister src1,
   4378                      QwNeonRegister src2) {
   4379   DCHECK(IsEnabled(NEON));
   4380   // Qd = vsub(Qn, Qm) SIMD floating point subtraction.
   4381   // Instruction details available in ARM DDI 0406C.b, A8-1086.
   4382   emit(EncodeNeonBinOp(VSUBF, dst, src1, src2));
   4383 }
   4384 
   4385 void Assembler::vsub(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
   4386                      QwNeonRegister src2) {
   4387   DCHECK(IsEnabled(NEON));
   4388   // Qd = vsub(Qn, Qm) SIMD integer subtraction.
   4389   // Instruction details available in ARM DDI 0406C.b, A8-1084.
   4390   emit(EncodeNeonBinOp(VSUB, size, dst, src1, src2));
   4391 }
   4392 
   4393 void Assembler::vqsub(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
   4394                       QwNeonRegister src2) {
   4395   DCHECK(IsEnabled(NEON));
   4396   // Qd = vqsub(Qn, Qm) SIMD integer saturating subtraction.
   4397   // Instruction details available in ARM DDI 0406C.b, A8-1020.
   4398   emit(EncodeNeonBinOp(VQSUB, dt, dst, src1, src2));
   4399 }
   4400 
   4401 void Assembler::vmul(QwNeonRegister dst, QwNeonRegister src1,
   4402                      QwNeonRegister src2) {
   4403   DCHECK(IsEnabled(NEON));
   4404   // Qd = vadd(Qn, Qm) SIMD floating point multiply.
   4405   // Instruction details available in ARM DDI 0406C.b, A8-958.
   4406   emit(EncodeNeonBinOp(VMULF, dst, src1, src2));
   4407 }
   4408 
   4409 void Assembler::vmul(NeonSize size, QwNeonRegister dst,
   4410                      const QwNeonRegister src1, const QwNeonRegister src2) {
   4411   DCHECK(IsEnabled(NEON));
   4412   // Qd = vadd(Qn, Qm) SIMD integer multiply.
   4413   // Instruction details available in ARM DDI 0406C.b, A8-960.
   4414   emit(EncodeNeonBinOp(VMUL, size, dst, src1, src2));
   4415 }
   4416 
   4417 void Assembler::vmin(const QwNeonRegister dst, const QwNeonRegister src1,
   4418                      const QwNeonRegister src2) {
   4419   DCHECK(IsEnabled(NEON));
   4420   // Qd = vmin(Qn, Qm) SIMD floating point MIN.
   4421   // Instruction details available in ARM DDI 0406C.b, A8-928.
   4422   emit(EncodeNeonBinOp(VMINF, dst, src1, src2));
   4423 }
   4424 
   4425 void Assembler::vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
   4426                      QwNeonRegister src2) {
   4427   DCHECK(IsEnabled(NEON));
   4428   // Qd = vmin(Qn, Qm) SIMD integer MIN.
   4429   // Instruction details available in ARM DDI 0406C.b, A8-926.
   4430   emit(EncodeNeonBinOp(VMIN, dt, dst, src1, src2));
   4431 }
   4432 
   4433 void Assembler::vmax(QwNeonRegister dst, QwNeonRegister src1,
   4434                      QwNeonRegister src2) {
   4435   DCHECK(IsEnabled(NEON));
   4436   // Qd = vmax(Qn, Qm) SIMD floating point MAX.
   4437   // Instruction details available in ARM DDI 0406C.b, A8-928.
   4438   emit(EncodeNeonBinOp(VMAXF, dst, src1, src2));
   4439 }
   4440 
   4441 void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
   4442                      QwNeonRegister src2) {
   4443   DCHECK(IsEnabled(NEON));
   4444   // Qd = vmax(Qn, Qm) SIMD integer MAX.
   4445   // Instruction details available in ARM DDI 0406C.b, A8-926.
   4446   emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2));
   4447 }
   4448 
   4449 enum NeonShiftOp { VSHL, VSHR };
   4450 
   4451 static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonDataType dt,
   4452                                QwNeonRegister dst, QwNeonRegister src,
   4453                                int shift) {
   4454   int vd, d;
   4455   dst.split_code(&vd, &d);
   4456   int vm, m;
   4457   src.split_code(&vm, &m);
   4458   int size_in_bits = kBitsPerByte << NeonSz(dt);
   4459   int op_encoding = 0;
   4460   int imm6 = 0;
   4461   if (op == VSHL) {
   4462     DCHECK(shift >= 0 && size_in_bits > shift);
   4463     imm6 = size_in_bits + shift;
   4464     op_encoding = 0x5 * B8;
   4465   } else {
   4466     DCHECK_EQ(VSHR, op);
   4467     DCHECK(shift > 0 && size_in_bits >= shift);
   4468     imm6 = 2 * size_in_bits - shift;
   4469     op_encoding = NeonU(dt) * B24;
   4470   }
   4471   return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | B6 | m * B5 | B4 |
   4472          vm | op_encoding;
   4473 }
   4474 
   4475 void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
   4476                      int shift) {
   4477   DCHECK(IsEnabled(NEON));
   4478   // Qd = vshl(Qm, bits) SIMD shift left immediate.
   4479   // Instruction details available in ARM DDI 0406C.b, A8-1046.
   4480   emit(EncodeNeonShiftOp(VSHL, dt, dst, src, shift));
   4481 }
   4482 
   4483 void Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
   4484                      int shift) {
   4485   DCHECK(IsEnabled(NEON));
   4486   // Qd = vshl(Qm, bits) SIMD shift right immediate.
   4487   // Instruction details available in ARM DDI 0406C.b, A8-1052.
   4488   emit(EncodeNeonShiftOp(VSHR, dt, dst, src, shift));
   4489 }
   4490 
   4491 static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst,
   4492                                   QwNeonRegister src) {
   4493   int vd, d;
   4494   dst.split_code(&vd, &d);
   4495   int vm, m;
   4496   src.split_code(&vm, &m);
   4497   int rsqrt = is_rsqrt ? 1 : 0;
   4498   return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 |
   4499          rsqrt * B7 | B6 | m * B5 | vm;
   4500 }
   4501 
   4502 void Assembler::vrecpe(QwNeonRegister dst, QwNeonRegister src) {
   4503   DCHECK(IsEnabled(NEON));
   4504   // Qd = vrecpe(Qm) SIMD reciprocal estimate.
   4505   // Instruction details available in ARM DDI 0406C.b, A8-1024.
   4506   emit(EncodeNeonEstimateOp(false, dst, src));
   4507 }
   4508 
   4509 void Assembler::vrsqrte(QwNeonRegister dst, QwNeonRegister src) {
   4510   DCHECK(IsEnabled(NEON));
   4511   // Qd = vrsqrte(Qm) SIMD reciprocal square root estimate.
   4512   // Instruction details available in ARM DDI 0406C.b, A8-1038.
   4513   emit(EncodeNeonEstimateOp(true, dst, src));
   4514 }
   4515 
   4516 void Assembler::vrecps(QwNeonRegister dst, QwNeonRegister src1,
   4517                        QwNeonRegister src2) {
   4518   DCHECK(IsEnabled(NEON));
   4519   // Qd = vrecps(Qn, Qm) SIMD reciprocal refinement step.
   4520   // Instruction details available in ARM DDI 0406C.b, A8-1026.
   4521   emit(EncodeNeonBinOp(VRECPS, dst, src1, src2));
   4522 }
   4523 
   4524 void Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1,
   4525                         QwNeonRegister src2) {
   4526   DCHECK(IsEnabled(NEON));
   4527   // Qd = vrsqrts(Qn, Qm) SIMD reciprocal square root refinement step.
   4528   // Instruction details available in ARM DDI 0406C.b, A8-1040.
   4529   emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2));
   4530 }
   4531 
   4532 void Assembler::vtst(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
   4533                      QwNeonRegister src2) {
   4534   DCHECK(IsEnabled(NEON));
   4535   // Qd = vtst(Qn, Qm) SIMD test integer operands.
   4536   // Instruction details available in ARM DDI 0406C.b, A8-1098.
   4537   emit(EncodeNeonBinOp(VTST, size, dst, src1, src2));
   4538 }
   4539 
   4540 void Assembler::vceq(QwNeonRegister dst, QwNeonRegister src1,
   4541                      QwNeonRegister src2) {
   4542   DCHECK(IsEnabled(NEON));
   4543   // Qd = vceq(Qn, Qm) SIMD floating point compare equal.
   4544   // Instruction details available in ARM DDI 0406C.b, A8-844.
   4545   emit(EncodeNeonBinOp(VCEQF, dst, src1, src2));
   4546 }
   4547 
   4548 void Assembler::vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
   4549                      QwNeonRegister src2) {
   4550   DCHECK(IsEnabled(NEON));
   4551   // Qd = vceq(Qn, Qm) SIMD integer compare equal.
   4552   // Instruction details available in ARM DDI 0406C.b, A8-844.
   4553   emit(EncodeNeonBinOp(VCEQ, size, dst, src1, src2));
   4554 }
   4555 
   4556 void Assembler::vcge(QwNeonRegister dst, QwNeonRegister src1,
   4557                      QwNeonRegister src2) {
   4558   DCHECK(IsEnabled(NEON));
   4559   // Qd = vcge(Qn, Qm) SIMD floating point compare greater or equal.
   4560   // Instruction details available in ARM DDI 0406C.b, A8-848.
   4561   emit(EncodeNeonBinOp(VCGEF, dst, src1, src2));
   4562 }
   4563 
   4564 void Assembler::vcge(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
   4565                      QwNeonRegister src2) {
   4566   DCHECK(IsEnabled(NEON));
   4567   // Qd = vcge(Qn, Qm) SIMD integer compare greater or equal.
   4568   // Instruction details available in ARM DDI 0406C.b, A8-848.
   4569   emit(EncodeNeonBinOp(VCGE, dt, dst, src1, src2));
   4570 }
   4571 
   4572 void Assembler::vcgt(QwNeonRegister dst, QwNeonRegister src1,
   4573                      QwNeonRegister src2) {
   4574   DCHECK(IsEnabled(NEON));
   4575   // Qd = vcgt(Qn, Qm) SIMD floating point compare greater than.
   4576   // Instruction details available in ARM DDI 0406C.b, A8-852.
   4577   emit(EncodeNeonBinOp(VCGTF, dst, src1, src2));
   4578 }
   4579 
   4580 void Assembler::vcgt(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
   4581                      QwNeonRegister src2) {
   4582   DCHECK(IsEnabled(NEON));
   4583   // Qd = vcgt(Qn, Qm) SIMD integer compare greater than.
   4584   // Instruction details available in ARM DDI 0406C.b, A8-852.
   4585   emit(EncodeNeonBinOp(VCGT, dt, dst, src1, src2));
   4586 }
   4587 
   4588 void Assembler::vext(QwNeonRegister dst, const QwNeonRegister src1,
   4589                      const QwNeonRegister src2, int bytes) {
   4590   DCHECK(IsEnabled(NEON));
   4591   // Qd = vext(Qn, Qm) SIMD byte extract.
   4592   // Instruction details available in ARM DDI 0406C.b, A8-890.
   4593   int vd, d;
   4594   dst.split_code(&vd, &d);
   4595   int vn, n;
   4596   src1.split_code(&vn, &n);
   4597   int vm, m;
   4598   src2.split_code(&vm, &m);
   4599   DCHECK_GT(16, bytes);
   4600   emit(0x1E5U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | bytes * B8 |
   4601        n * B7 | B6 | m * B5 | vm);
   4602 }
   4603 
   4604 void Assembler::vzip(NeonSize size, QwNeonRegister dst,
   4605                      const QwNeonRegister src) {
   4606   DCHECK(IsEnabled(NEON));
   4607   // Qd = vzip.<size>(Qn, Qm) SIMD zip (interleave).
   4608   // Instruction details available in ARM DDI 0406C.b, A8-1102.
   4609   int vd, d;
   4610   dst.split_code(&vd, &d);
   4611   int vm, m;
   4612   src.split_code(&vm, &m);
   4613   int sz = static_cast<int>(size);
   4614   emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | 2 * B16 | vd * B12 |
   4615        0x3 * B7 | B6 | m * B5 | vm);
   4616 }
   4617 
   4618 static Instr EncodeNeonVREV(NeonSize op_size, NeonSize size,
   4619                             const QwNeonRegister dst,
   4620                             const QwNeonRegister src) {
   4621   // Qd = vrev<op_size>.<size>(Qn, Qm) SIMD scalar reverse.
   4622   // Instruction details available in ARM DDI 0406C.b, A8-1028.
   4623   DCHECK_GT(op_size, static_cast<int>(size));
   4624   int vd, d;
   4625   dst.split_code(&vd, &d);
   4626   int vm, m;
   4627   src.split_code(&vm, &m);
   4628   int sz = static_cast<int>(size);
   4629   int op = static_cast<int>(Neon64) - static_cast<int>(op_size);
   4630   return 0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | vd * B12 | op * B7 |
   4631          B6 | m * B5 | vm;
   4632 }
   4633 
   4634 void Assembler::vrev16(NeonSize size, const QwNeonRegister dst,
   4635                        const QwNeonRegister src) {
   4636   DCHECK(IsEnabled(NEON));
   4637   emit(EncodeNeonVREV(Neon16, size, dst, src));
   4638 }
   4639 
   4640 void Assembler::vrev32(NeonSize size, const QwNeonRegister dst,
   4641                        const QwNeonRegister src) {
   4642   DCHECK(IsEnabled(NEON));
   4643   emit(EncodeNeonVREV(Neon32, size, dst, src));
   4644 }
   4645 
   4646 void Assembler::vrev64(NeonSize size, const QwNeonRegister dst,
   4647                        const QwNeonRegister src) {
   4648   DCHECK(IsEnabled(NEON));
   4649   emit(EncodeNeonVREV(Neon64, size, dst, src));
   4650 }
   4651 
   4652 // Encode NEON vtbl / vtbx instruction.
   4653 static Instr EncodeNeonVTB(const DwVfpRegister dst, const NeonListOperand& list,
   4654                            const DwVfpRegister index, bool vtbx) {
   4655   // Dd = vtbl(table, Dm) SIMD vector permute, zero at out of range indices.
   4656   // Instruction details available in ARM DDI 0406C.b, A8-1094.
   4657   // Dd = vtbx(table, Dm) SIMD vector permute, skip out of range indices.
   4658   // Instruction details available in ARM DDI 0406C.b, A8-1094.
   4659   int vd, d;
   4660   dst.split_code(&vd, &d);
   4661   int vn, n;
   4662   list.base().split_code(&vn, &n);
   4663   int vm, m;
   4664   index.split_code(&vm, &m);
   4665   int op = vtbx ? 1 : 0;  // vtbl = 0, vtbx = 1.
   4666   return 0x1E7U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | 0x2 * B10 |
   4667          list.length() * B8 | n * B7 | op * B6 | m * B5 | vm;
   4668 }
   4669 
   4670 void Assembler::vtbl(const DwVfpRegister dst, const NeonListOperand& list,
   4671                      const DwVfpRegister index) {
   4672   DCHECK(IsEnabled(NEON));
   4673   emit(EncodeNeonVTB(dst, list, index, false));
   4674 }
   4675 
   4676 void Assembler::vtbx(const DwVfpRegister dst, const NeonListOperand& list,
   4677                      const DwVfpRegister index) {
   4678   DCHECK(IsEnabled(NEON));
   4679   emit(EncodeNeonVTB(dst, list, index, true));
   4680 }
   4681 
   4682 // Pseudo instructions.
   4683 void Assembler::nop(int type) {
   4684   // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes
   4685   // some of the CPU's pipeline and has to issue. Older ARM chips simply used
   4686   // MOV Rx, Rx as NOP and it performs better even in newer CPUs.
   4687   // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
   4688   // a type.
   4689   DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
   4690   emit(al | 13*B21 | type*B12 | type);
   4691 }
   4692 
   4693 
   4694 bool Assembler::IsMovT(Instr instr) {
   4695   instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
   4696              ((kNumRegisters-1)*B12) |            // mask out register
   4697              EncodeMovwImmediate(0xFFFF));        // mask out immediate value
   4698   return instr == kMovtPattern;
   4699 }
   4700 
   4701 
   4702 bool Assembler::IsMovW(Instr instr) {
   4703   instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
   4704              ((kNumRegisters-1)*B12) |            // mask out destination
   4705              EncodeMovwImmediate(0xFFFF));        // mask out immediate value
   4706   return instr == kMovwPattern;
   4707 }
   4708 
   4709 
   4710 Instr Assembler::GetMovTPattern() { return kMovtPattern; }
   4711 
   4712 
   4713 Instr Assembler::GetMovWPattern() { return kMovwPattern; }
   4714 
   4715 
   4716 Instr Assembler::EncodeMovwImmediate(uint32_t immediate) {
   4717   DCHECK(immediate < 0x10000);
   4718   return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
   4719 }
   4720 
   4721 
   4722 Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
   4723   instruction &= ~EncodeMovwImmediate(0xffff);
   4724   return instruction | EncodeMovwImmediate(immediate);
   4725 }
   4726 
   4727 
   4728 int Assembler::DecodeShiftImm(Instr instr) {
   4729   int rotate = Instruction::RotateValue(instr) * 2;
   4730   int immed8 = Instruction::Immed8Value(instr);
   4731   return base::bits::RotateRight32(immed8, rotate);
   4732 }
   4733 
   4734 
   4735 Instr Assembler::PatchShiftImm(Instr instr, int immed) {
   4736   uint32_t rotate_imm = 0;
   4737   uint32_t immed_8 = 0;
   4738   bool immed_fits = fits_shifter(immed, &rotate_imm, &immed_8, NULL);
   4739   DCHECK(immed_fits);
   4740   USE(immed_fits);
   4741   return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8;
   4742 }
   4743 
   4744 
   4745 bool Assembler::IsNop(Instr instr, int type) {
   4746   DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
   4747   // Check for mov rx, rx where x = type.
   4748   return instr == (al | 13*B21 | type*B12 | type);
   4749 }
   4750 
   4751 
   4752 bool Assembler::IsMovImmed(Instr instr) {
   4753   return (instr & kMovImmedMask) == kMovImmedPattern;
   4754 }
   4755 
   4756 
   4757 bool Assembler::IsOrrImmed(Instr instr) {
   4758   return (instr & kOrrImmedMask) == kOrrImmedPattern;
   4759 }
   4760 
   4761 
   4762 // static
   4763 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
   4764   uint32_t dummy1;
   4765   uint32_t dummy2;
   4766   return fits_shifter(imm32, &dummy1, &dummy2, NULL);
   4767 }
   4768 
   4769 
   4770 bool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) {
   4771   return is_uint12(abs(imm32));
   4772 }
   4773 
   4774 
   4775 // Debugging.
   4776 void Assembler::RecordConstPool(int size) {
   4777   // We only need this for debugger support, to correctly compute offsets in the
   4778   // code.
   4779   RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
   4780 }
   4781 
   4782 
   4783 void Assembler::GrowBuffer() {
   4784   if (!own_buffer_) FATAL("external code buffer is too small");
   4785 
   4786   // Compute new buffer size.
   4787   CodeDesc desc;  // the new buffer
   4788   if (buffer_size_ < 1 * MB) {
   4789     desc.buffer_size = 2*buffer_size_;
   4790   } else {
   4791     desc.buffer_size = buffer_size_ + 1*MB;
   4792   }
   4793   CHECK_GT(desc.buffer_size, 0);  // no overflow
   4794 
   4795   // Set up new buffer.
   4796   desc.buffer = NewArray<byte>(desc.buffer_size);
   4797 
   4798   desc.instr_size = pc_offset();
   4799   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   4800   desc.origin = this;
   4801 
   4802   // Copy the data.
   4803   int pc_delta = desc.buffer - buffer_;
   4804   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
   4805   MemMove(desc.buffer, buffer_, desc.instr_size);
   4806   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
   4807           desc.reloc_size);
   4808 
   4809   // Switch buffers.
   4810   DeleteArray(buffer_);
   4811   buffer_ = desc.buffer;
   4812   buffer_size_ = desc.buffer_size;
   4813   pc_ += pc_delta;
   4814   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
   4815                                reloc_info_writer.last_pc() + pc_delta);
   4816 
   4817   // None of our relocation types are pc relative pointing outside the code
   4818   // buffer nor pc absolute pointing inside the code buffer, so there is no need
   4819   // to relocate any emitted relocation entries.
   4820 }
   4821 
   4822 
   4823 void Assembler::db(uint8_t data) {
   4824   // db is used to write raw data. The constant pool should be emitted or
   4825   // blocked before using db.
   4826   DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
   4827   DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
   4828   CheckBuffer();
   4829   *reinterpret_cast<uint8_t*>(pc_) = data;
   4830   pc_ += sizeof(uint8_t);
   4831 }
   4832 
   4833 
   4834 void Assembler::dd(uint32_t data) {
   4835   // dd is used to write raw data. The constant pool should be emitted or
   4836   // blocked before using dd.
   4837   DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
   4838   DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
   4839   CheckBuffer();
   4840   *reinterpret_cast<uint32_t*>(pc_) = data;
   4841   pc_ += sizeof(uint32_t);
   4842 }
   4843 
   4844 
   4845 void Assembler::dq(uint64_t value) {
   4846   // dq is used to write raw data. The constant pool should be emitted or
   4847   // blocked before using dq.
   4848   DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
   4849   DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
   4850   CheckBuffer();
   4851   *reinterpret_cast<uint64_t*>(pc_) = value;
   4852   pc_ += sizeof(uint64_t);
   4853 }
   4854 
   4855 
   4856 void Assembler::emit_code_stub_address(Code* stub) {
   4857   CheckBuffer();
   4858   *reinterpret_cast<uint32_t*>(pc_) =
   4859       reinterpret_cast<uint32_t>(stub->instruction_start());
   4860   pc_ += sizeof(uint32_t);
   4861 }
   4862 
   4863 
   4864 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
   4865   if (RelocInfo::IsNone(rmode) ||
   4866       // Don't record external references unless the heap will be serialized.
   4867       (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
   4868        !emit_debug_code())) {
   4869     return;
   4870   }
   4871   DCHECK(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
   4872   if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
   4873     data = RecordedAstId().ToInt();
   4874     ClearRecordedAstId();
   4875   }
   4876   RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
   4877   reloc_info_writer.Write(&rinfo);
   4878 }
   4879 
   4880 
   4881 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
   4882                                                           RelocInfo::Mode rmode,
   4883                                                           intptr_t value) {
   4884   DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::CONST_POOL &&
   4885          rmode != RelocInfo::NONE64);
   4886   bool sharing_ok = RelocInfo::IsNone(rmode) ||
   4887                     !(serializer_enabled() || rmode < RelocInfo::CELL);
   4888   if (FLAG_enable_embedded_constant_pool) {
   4889     return constant_pool_builder_.AddEntry(position, value, sharing_ok);
   4890   } else {
   4891     DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants);
   4892     if (pending_32_bit_constants_.empty()) {
   4893       first_const_pool_32_use_ = position;
   4894     }
   4895     ConstantPoolEntry entry(position, value, sharing_ok);
   4896     pending_32_bit_constants_.push_back(entry);
   4897 
   4898     // Make sure the constant pool is not emitted in place of the next
   4899     // instruction for which we just recorded relocation info.
   4900     BlockConstPoolFor(1);
   4901     return ConstantPoolEntry::REGULAR;
   4902   }
   4903 }
   4904 
   4905 
   4906 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
   4907                                                           double value) {
   4908   if (FLAG_enable_embedded_constant_pool) {
   4909     return constant_pool_builder_.AddEntry(position, value);
   4910   } else {
   4911     DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants);
   4912     if (pending_64_bit_constants_.empty()) {
   4913       first_const_pool_64_use_ = position;
   4914     }
   4915     ConstantPoolEntry entry(position, value);
   4916     pending_64_bit_constants_.push_back(entry);
   4917 
   4918     // Make sure the constant pool is not emitted in place of the next
   4919     // instruction for which we just recorded relocation info.
   4920     BlockConstPoolFor(1);
   4921     return ConstantPoolEntry::REGULAR;
   4922   }
   4923 }
   4924 
   4925 
   4926 void Assembler::BlockConstPoolFor(int instructions) {
   4927   if (FLAG_enable_embedded_constant_pool) {
   4928     // Should be a no-op if using an embedded constant pool.
   4929     DCHECK(pending_32_bit_constants_.empty());
   4930     DCHECK(pending_64_bit_constants_.empty());
   4931     return;
   4932   }
   4933 
   4934   int pc_limit = pc_offset() + instructions * kInstrSize;
   4935   if (no_const_pool_before_ < pc_limit) {
   4936     // Max pool start (if we need a jump and an alignment).
   4937 #ifdef DEBUG
   4938     int start = pc_limit + kInstrSize + 2 * kPointerSize;
   4939     DCHECK(pending_32_bit_constants_.empty() ||
   4940            (start - first_const_pool_32_use_ +
   4941                 pending_64_bit_constants_.size() * kDoubleSize <
   4942             kMaxDistToIntPool));
   4943     DCHECK(pending_64_bit_constants_.empty() ||
   4944            (start - first_const_pool_64_use_ < kMaxDistToFPPool));
   4945 #endif
   4946     no_const_pool_before_ = pc_limit;
   4947   }
   4948 
   4949   if (next_buffer_check_ < no_const_pool_before_) {
   4950     next_buffer_check_ = no_const_pool_before_;
   4951   }
   4952 }
   4953 
   4954 
   4955 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
   4956   if (FLAG_enable_embedded_constant_pool) {
   4957     // Should be a no-op if using an embedded constant pool.
   4958     DCHECK(pending_32_bit_constants_.empty());
   4959     DCHECK(pending_64_bit_constants_.empty());
   4960     return;
   4961   }
   4962 
   4963   // Some short sequence of instruction mustn't be broken up by constant pool
   4964   // emission, such sequences are protected by calls to BlockConstPoolFor and
   4965   // BlockConstPoolScope.
   4966   if (is_const_pool_blocked()) {
   4967     // Something is wrong if emission is forced and blocked at the same time.
   4968     DCHECK(!force_emit);
   4969     return;
   4970   }
   4971 
   4972   // There is nothing to do if there are no pending constant pool entries.
   4973   if (pending_32_bit_constants_.empty() && pending_64_bit_constants_.empty()) {
   4974     // Calculate the offset of the next check.
   4975     next_buffer_check_ = pc_offset() + kCheckPoolInterval;
   4976     return;
   4977   }
   4978 
   4979   // Check that the code buffer is large enough before emitting the constant
   4980   // pool (include the jump over the pool and the constant pool marker and
   4981   // the gap to the relocation information).
   4982   int jump_instr = require_jump ? kInstrSize : 0;
   4983   int size_up_to_marker = jump_instr + kInstrSize;
   4984   int estimated_size_after_marker =
   4985       pending_32_bit_constants_.size() * kPointerSize;
   4986   bool has_int_values = !pending_32_bit_constants_.empty();
   4987   bool has_fp_values = !pending_64_bit_constants_.empty();
   4988   bool require_64_bit_align = false;
   4989   if (has_fp_values) {
   4990     require_64_bit_align =
   4991         !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker),
   4992                    kDoubleAlignment);
   4993     if (require_64_bit_align) {
   4994       estimated_size_after_marker += kInstrSize;
   4995     }
   4996     estimated_size_after_marker +=
   4997         pending_64_bit_constants_.size() * kDoubleSize;
   4998   }
   4999   int estimated_size = size_up_to_marker + estimated_size_after_marker;
   5000 
   5001   // We emit a constant pool when:
   5002   //  * requested to do so by parameter force_emit (e.g. after each function).
   5003   //  * the distance from the first instruction accessing the constant pool to
   5004   //    any of the constant pool entries will exceed its limit the next
   5005   //    time the pool is checked. This is overly restrictive, but we don't emit
   5006   //    constant pool entries in-order so it's conservatively correct.
   5007   //  * the instruction doesn't require a jump after itself to jump over the
   5008   //    constant pool, and we're getting close to running out of range.
   5009   if (!force_emit) {
   5010     DCHECK(has_fp_values || has_int_values);
   5011     bool need_emit = false;
   5012     if (has_fp_values) {
   5013       // The 64-bit constants are always emitted before the 32-bit constants, so
   5014       // we can ignore the effect of the 32-bit constants on estimated_size.
   5015       int dist64 = pc_offset() + estimated_size -
   5016                    pending_32_bit_constants_.size() * kPointerSize -
   5017                    first_const_pool_64_use_;
   5018       if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
   5019           (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
   5020         need_emit = true;
   5021       }
   5022     }
   5023     if (has_int_values) {
   5024       int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_;
   5025       if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
   5026           (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
   5027         need_emit = true;
   5028       }
   5029     }
   5030     if (!need_emit) return;
   5031   }
   5032 
   5033   // Deduplicate constants.
   5034   int size_after_marker = estimated_size_after_marker;
   5035   for (size_t i = 0; i < pending_64_bit_constants_.size(); i++) {
   5036     ConstantPoolEntry& entry = pending_64_bit_constants_[i];
   5037     DCHECK(!entry.is_merged());
   5038     for (size_t j = 0; j < i; j++) {
   5039       if (entry.value64() == pending_64_bit_constants_[j].value64()) {
   5040         DCHECK(!pending_64_bit_constants_[j].is_merged());
   5041         entry.set_merged_index(j);
   5042         size_after_marker -= kDoubleSize;
   5043         break;
   5044       }
   5045     }
   5046   }
   5047 
   5048   for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
   5049     ConstantPoolEntry& entry = pending_32_bit_constants_[i];
   5050     DCHECK(!entry.is_merged());
   5051     if (!entry.sharing_ok()) continue;
   5052     for (size_t j = 0; j < i; j++) {
   5053       if (entry.value() == pending_32_bit_constants_[j].value()) {
   5054         DCHECK(!pending_32_bit_constants_[j].is_merged());
   5055         entry.set_merged_index(j);
   5056         size_after_marker -= kPointerSize;
   5057         break;
   5058       }
   5059     }
   5060   }
   5061 
   5062   int size = size_up_to_marker + size_after_marker;
   5063 
   5064   int needed_space = size + kGap;
   5065   while (buffer_space() <= needed_space) GrowBuffer();
   5066 
   5067   {
   5068     // Block recursive calls to CheckConstPool.
   5069     BlockConstPoolScope block_const_pool(this);
   5070     RecordComment("[ Constant Pool");
   5071     RecordConstPool(size);
   5072 
   5073     Label size_check;
   5074     bind(&size_check);
   5075 
   5076     // Emit jump over constant pool if necessary.
   5077     Label after_pool;
   5078     if (require_jump) {
   5079       b(&after_pool);
   5080     }
   5081 
   5082     // Put down constant pool marker "Undefined instruction".
   5083     // The data size helps disassembly know what to print.
   5084     emit(kConstantPoolMarker |
   5085          EncodeConstantPoolLength(size_after_marker / kPointerSize));
   5086 
   5087     if (require_64_bit_align) {
   5088       emit(kConstantPoolMarker);
   5089     }
   5090 
   5091     // Emit 64-bit constant pool entries first: their range is smaller than
   5092     // 32-bit entries.
   5093     for (size_t i = 0; i < pending_64_bit_constants_.size(); i++) {
   5094       ConstantPoolEntry& entry = pending_64_bit_constants_[i];
   5095 
   5096       Instr instr = instr_at(entry.position());
   5097       // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
   5098       DCHECK((IsVldrDPcImmediateOffset(instr) &&
   5099               GetVldrDRegisterImmediateOffset(instr) == 0));
   5100 
   5101       int delta = pc_offset() - entry.position() - kPcLoadDelta;
   5102       DCHECK(is_uint10(delta));
   5103 
   5104       if (entry.is_merged()) {
   5105         ConstantPoolEntry& merged =
   5106             pending_64_bit_constants_[entry.merged_index()];
   5107         DCHECK(entry.value64() == merged.value64());
   5108         Instr merged_instr = instr_at(merged.position());
   5109         DCHECK(IsVldrDPcImmediateOffset(merged_instr));
   5110         delta = GetVldrDRegisterImmediateOffset(merged_instr);
   5111         delta += merged.position() - entry.position();
   5112       }
   5113       instr_at_put(entry.position(),
   5114                    SetVldrDRegisterImmediateOffset(instr, delta));
   5115       if (!entry.is_merged()) {
   5116         DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment));
   5117         dq(entry.value64());
   5118       }
   5119     }
   5120 
   5121     // Emit 32-bit constant pool entries.
   5122     for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
   5123       ConstantPoolEntry& entry = pending_32_bit_constants_[i];
   5124       Instr instr = instr_at(entry.position());
   5125 
   5126       // 64-bit loads shouldn't get here.
   5127       DCHECK(!IsVldrDPcImmediateOffset(instr));
   5128       DCHECK(!IsMovW(instr));
   5129       DCHECK(IsLdrPcImmediateOffset(instr) &&
   5130              GetLdrRegisterImmediateOffset(instr) == 0);
   5131 
   5132       int delta = pc_offset() - entry.position() - kPcLoadDelta;
   5133       DCHECK(is_uint12(delta));
   5134       // 0 is the smallest delta:
   5135       //   ldr rd, [pc, #0]
   5136       //   constant pool marker
   5137       //   data
   5138 
   5139       if (entry.is_merged()) {
   5140         DCHECK(entry.sharing_ok());
   5141         ConstantPoolEntry& merged =
   5142             pending_32_bit_constants_[entry.merged_index()];
   5143         DCHECK(entry.value() == merged.value());
   5144         Instr merged_instr = instr_at(merged.position());
   5145         DCHECK(IsLdrPcImmediateOffset(merged_instr));
   5146         delta = GetLdrRegisterImmediateOffset(merged_instr);
   5147         delta += merged.position() - entry.position();
   5148       }
   5149       instr_at_put(entry.position(),
   5150                    SetLdrRegisterImmediateOffset(instr, delta));
   5151       if (!entry.is_merged()) {
   5152         emit(entry.value());
   5153       }
   5154     }
   5155 
   5156     pending_32_bit_constants_.clear();
   5157     pending_64_bit_constants_.clear();
   5158     first_const_pool_32_use_ = -1;
   5159     first_const_pool_64_use_ = -1;
   5160 
   5161     RecordComment("]");
   5162 
   5163     DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check));
   5164 
   5165     if (after_pool.is_linked()) {
   5166       bind(&after_pool);
   5167     }
   5168   }
   5169 
   5170   // Since a constant pool was just emitted, move the check offset forward by
   5171   // the standard interval.
   5172   next_buffer_check_ = pc_offset() + kCheckPoolInterval;
   5173 }
   5174 
   5175 
   5176 void Assembler::PatchConstantPoolAccessInstruction(
   5177     int pc_offset, int offset, ConstantPoolEntry::Access access,
   5178     ConstantPoolEntry::Type type) {
   5179   DCHECK(FLAG_enable_embedded_constant_pool);
   5180   Address pc = buffer_ + pc_offset;
   5181 
   5182   // Patch vldr/ldr instruction with correct offset.
   5183   Instr instr = instr_at(pc);
   5184   if (access == ConstantPoolEntry::OVERFLOWED) {
   5185     if (CpuFeatures::IsSupported(ARMv7)) {
   5186       CpuFeatureScope scope(this, ARMv7);
   5187       // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
   5188       Instr next_instr = instr_at(pc + kInstrSize);
   5189       DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0));
   5190       DCHECK((IsMovT(next_instr) &&
   5191               Instruction::ImmedMovwMovtValue(next_instr) == 0));
   5192       instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff));
   5193       instr_at_put(pc + kInstrSize,
   5194                    PatchMovwImmediate(next_instr, offset >> 16));
   5195     } else {
   5196       // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
   5197       Instr instr_2 = instr_at(pc + kInstrSize);
   5198       Instr instr_3 = instr_at(pc + 2 * kInstrSize);
   5199       Instr instr_4 = instr_at(pc + 3 * kInstrSize);
   5200       DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0));
   5201       DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) &&
   5202              GetRn(instr_2).is(GetRd(instr_2)));
   5203       DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) &&
   5204              GetRn(instr_3).is(GetRd(instr_3)));
   5205       DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) &&
   5206              GetRn(instr_4).is(GetRd(instr_4)));
   5207       instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask)));
   5208       instr_at_put(pc + kInstrSize,
   5209                    PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
   5210       instr_at_put(pc + 2 * kInstrSize,
   5211                    PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
   5212       instr_at_put(pc + 3 * kInstrSize,
   5213                    PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
   5214     }
   5215   } else if (type == ConstantPoolEntry::DOUBLE) {
   5216     // Instruction to patch must be 'vldr rd, [pp, #0]'.
   5217     DCHECK((IsVldrDPpImmediateOffset(instr) &&
   5218             GetVldrDRegisterImmediateOffset(instr) == 0));
   5219     DCHECK(is_uint10(offset));
   5220     instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset));
   5221   } else {
   5222     // Instruction to patch must be 'ldr rd, [pp, #0]'.
   5223     DCHECK((IsLdrPpImmediateOffset(instr) &&
   5224             GetLdrRegisterImmediateOffset(instr) == 0));
   5225     DCHECK(is_uint12(offset));
   5226     instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset));
   5227   }
   5228 }
   5229 
   5230 
   5231 }  // namespace internal
   5232 }  // namespace v8
   5233 
   5234 #endif  // V8_TARGET_ARCH_ARM
   5235