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
46namespace v8 {
47namespace internal {
48
49static const unsigned kArmv6 = 0u;
50static const unsigned kArmv7 = kArmv6 | (1u << ARMv7);
51static const unsigned kArmv7WithSudiv = kArmv7 | (1u << ARMv7_SUDIV);
52static const unsigned kArmv8 = kArmv7WithSudiv | (1u << ARMv8);
53
54static 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)
159static 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
196void 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
249void 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
303void 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
323const int RelocInfo::kApplyMask = 0;
324
325
326bool 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
335bool RelocInfo::IsInConstantPool() {
336  return Assembler::is_constant_pool_load(pc_);
337}
338
339Address RelocInfo::wasm_memory_reference() {
340  DCHECK(IsWasmMemoryReference(rmode_));
341  return Assembler::target_address_at(pc_, host_);
342}
343
344uint32_t RelocInfo::wasm_memory_size_reference() {
345  DCHECK(IsWasmMemorySizeReference(rmode_));
346  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
347}
348
349Address RelocInfo::wasm_global_reference() {
350  DCHECK(IsWasmGlobalReference(rmode_));
351  return Assembler::target_address_at(pc_, host_);
352}
353
354uint32_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
359void 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
364void 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
374Operand::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
390Operand::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
411Operand::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
420MemOperand::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
435MemOperand::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
444MemOperand::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
455NeonMemOperand::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
463NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) {
464  rn_ = rn;
465  rm_ = rm;
466  SetAlignment(align);
467}
468
469
470void 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.
496const 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.
500const Instr kPopRegPattern =
501    al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
502// ldr rd, [pc, #offset]
503const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
504const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
505// ldr rd, [pp, #offset]
506const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
507const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
508// ldr rd, [pp, rn]
509const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
510const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
511// vldr dd, [pc, #offset]
512const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
513const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
514// vldr dd, [pp, #offset]
515const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
516const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
517// blxcc rm
518const Instr kBlxRegMask =
519    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
520const Instr kBlxRegPattern =
521    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
522const Instr kBlxIp = al | kBlxRegPattern | ip.code();
523const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
524const Instr kMovMvnPattern = 0xd * B21;
525const Instr kMovMvnFlip = B22;
526const Instr kMovLeaveCCMask = 0xdff * B16;
527const Instr kMovLeaveCCPattern = 0x1a0 * B16;
528const Instr kMovwPattern = 0x30 * B20;
529const Instr kMovtPattern = 0x34 * B20;
530const Instr kMovwLeaveCCFlip = 0x5 * B21;
531const Instr kMovImmedMask = 0x7f * B21;
532const Instr kMovImmedPattern = 0x1d * B21;
533const Instr kOrrImmedMask = 0x7f * B21;
534const Instr kOrrImmedPattern = 0x1c * B21;
535const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
536const Instr kCmpCmnPattern = 0x15 * B20;
537const Instr kCmpCmnFlip = B21;
538const Instr kAddSubFlip = 0x6 * B21;
539const Instr kAndBicFlip = 0xe * B21;
540
541// A mask for the Rd register for push, pop, ldr, str instructions.
542const Instr kLdrRegFpOffsetPattern =
543    al | B26 | L | Offset | Register::kCode_fp * B16;
544const Instr kStrRegFpOffsetPattern =
545    al | B26 | Offset | Register::kCode_fp * B16;
546const Instr kLdrRegFpNegOffsetPattern =
547    al | B26 | L | NegOffset | Register::kCode_fp * B16;
548const Instr kStrRegFpNegOffsetPattern =
549    al | B26 | NegOffset | Register::kCode_fp * B16;
550const Instr kLdrStrInstrTypeMask = 0xffff0000;
551
552Assembler::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
577Assembler::~Assembler() {
578  DCHECK(const_pool_blocked_nesting_ == 0);
579}
580
581
582void 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
605void 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
614void Assembler::CodeTargetAlign() {
615  // Preferred alignment of jump targets on some ARM chips.
616  Align(8);
617}
618
619
620Condition Assembler::GetCondition(Instr instr) {
621  return Instruction::ConditionField(instr);
622}
623
624
625bool Assembler::IsBranch(Instr instr) {
626  return (instr & (B27 | B25)) == (B27 | B25);
627}
628
629
630int 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
638bool Assembler::IsLdrRegisterImmediate(Instr instr) {
639  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
640}
641
642
643bool Assembler::IsVldrDRegisterImmediate(Instr instr) {
644  return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
645}
646
647
648int 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
656int 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
665Instr 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
677Instr 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
690bool Assembler::IsStrRegisterImmediate(Instr instr) {
691  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
692}
693
694
695Instr 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
707bool Assembler::IsAddRegisterImmediate(Instr instr) {
708  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
709}
710
711
712Instr 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
721Register Assembler::GetRd(Instr instr) {
722  Register reg;
723  reg.reg_code = Instruction::RdValue(instr);
724  return reg;
725}
726
727
728Register Assembler::GetRn(Instr instr) {
729  Register reg;
730  reg.reg_code = Instruction::RnValue(instr);
731  return reg;
732}
733
734
735Register Assembler::GetRm(Instr instr) {
736  Register reg;
737  reg.reg_code = Instruction::RmValue(instr);
738  return reg;
739}
740
741
742Instr Assembler::GetConsantPoolLoadPattern() {
743  if (FLAG_enable_embedded_constant_pool) {
744    return kLdrPpImmedPattern;
745  } else {
746    return kLdrPCImmedPattern;
747  }
748}
749
750
751Instr Assembler::GetConsantPoolLoadMask() {
752  if (FLAG_enable_embedded_constant_pool) {
753    return kLdrPpImmedMask;
754  } else {
755    return kLdrPCImmedMask;
756  }
757}
758
759
760bool Assembler::IsPush(Instr instr) {
761  return ((instr & ~kRdMask) == kPushRegPattern);
762}
763
764
765bool Assembler::IsPop(Instr instr) {
766  return ((instr & ~kRdMask) == kPopRegPattern);
767}
768
769
770bool Assembler::IsStrRegFpOffset(Instr instr) {
771  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
772}
773
774
775bool Assembler::IsLdrRegFpOffset(Instr instr) {
776  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
777}
778
779
780bool Assembler::IsStrRegFpNegOffset(Instr instr) {
781  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
782}
783
784
785bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
786  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
787}
788
789
790bool 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
797bool 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
804bool 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
811Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; }
812
813
814bool 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
821bool 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
828bool Assembler::IsBlxReg(Instr instr) {
829  // Check the instruction is indeed a
830  // blxcc <Rm>
831  return (instr & kBlxRegMask) == kBlxRegPattern;
832}
833
834
835bool Assembler::IsBlxIp(Instr instr) {
836  // Check the instruction is indeed a
837  // blx ip
838  return instr == kBlxIp;
839}
840
841
842bool Assembler::IsTstImmediate(Instr instr) {
843  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
844      (I | TST | S);
845}
846
847
848bool Assembler::IsCmpRegister(Instr instr) {
849  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
850      (CMP | S);
851}
852
853
854bool Assembler::IsCmpImmediate(Instr instr) {
855  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
856      (I | CMP | S);
857}
858
859
860Register Assembler::GetCmpImmediateRegister(Instr instr) {
861  DCHECK(IsCmpImmediate(instr));
862  return GetRn(instr);
863}
864
865
866int 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
890int 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
907void 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
999void 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
1057void 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
1073void Assembler::bind(Label* L) {
1074  DCHECK(!L->is_bound());  // label can only be bound once
1075  bind_to(L, pc_offset());
1076}
1077
1078
1079void 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!
1097static 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.
1157bool 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
1168static 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
1184int 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
1221void 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
1279void 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
1322void 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
1354void 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
1393void 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
1401void 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
1426int 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.
1450void 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
1463void 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
1470void 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
1478void 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
1483void 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
1489void Assembler::b(Label* L, Condition cond) {
1490  CheckBuffer();
1491  b(branch_offset(L), cond);
1492}
1493
1494
1495void Assembler::bl(Label* L, Condition cond) {
1496  CheckBuffer();
1497  bl(branch_offset(L), cond);
1498}
1499
1500
1501void Assembler::blx(Label* L) {
1502  CheckBuffer();
1503  blx(branch_offset(L));
1504}
1505
1506
1507// Data-processing instructions.
1508
1509void 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
1515void 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
1521void 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
1527void 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
1533void 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
1539void 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
1545void 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
1551void 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
1557void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
1558  addrmod1(cond | TST | S, src1, r0, src2);
1559}
1560
1561
1562void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
1563  addrmod1(cond | TEQ | S, src1, r0, src2);
1564}
1565
1566
1567void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
1568  addrmod1(cond | CMP | S, src1, r0, src2);
1569}
1570
1571
1572void 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
1579void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
1580  addrmod1(cond | CMN | S, src1, r0, src2);
1581}
1582
1583
1584void 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
1590void 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
1599void 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
1638void 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
1644void 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
1650void 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
1656void 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.
1662void 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
1670void 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
1679void 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
1688void 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
1697void 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
1705void 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
1713void 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
1721void 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
1734void 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
1747void 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
1760void 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.
1774void 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.
1784void 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
1809void 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
1828void 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
1846void 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
1860void 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
1875void 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
1894void 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
1914void 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
1926void 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
1940void 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
1952void 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
1966void 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
1978void 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
1992void 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
2004void 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
2016void 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
2030void 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.
2041void 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
2047void 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.
2073void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
2074  addrmod2(cond | B26 | L, dst, src);
2075}
2076
2077
2078void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
2079  addrmod2(cond | B26, src, dst);
2080}
2081
2082
2083void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
2084  addrmod2(cond | B26 | B | L, dst, src);
2085}
2086
2087
2088void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
2089  addrmod2(cond | B26 | B, src, dst);
2090}
2091
2092
2093void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
2094  addrmod3(cond | L | B7 | H | B4, dst, src);
2095}
2096
2097
2098void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
2099  addrmod3(cond | B7 | H | B4, src, dst);
2100}
2101
2102
2103void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
2104  addrmod3(cond | L | B7 | S6 | B4, dst, src);
2105}
2106
2107
2108void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
2109  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
2110}
2111
2112
2113void 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
2123void 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.
2133void 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
2139void 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
2148void 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
2155void 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
2164void 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
2171void 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.
2181void 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.
2200void 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
2221void 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 .
2232void 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
2262void Assembler::bkpt(uint32_t imm16) {
2263  DCHECK(is_uint16(imm16));
2264  emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
2265}
2266
2267
2268void Assembler::svc(uint32_t imm24, Condition cond) {
2269  DCHECK(is_uint24(imm24));
2270  emit(cond | 15*B24 | imm24);
2271}
2272
2273
2274void 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
2286void 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
2298void 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.
2311void 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
2323void 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
2329void 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
2341void 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
2347void 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
2359void 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
2365void 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
2374void 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
2386void Assembler::ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
2387                     LFlag l) {
2388  ldc(coproc, crd, src, l, kSpecialCondition);
2389}
2390
2391void 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
2399void 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
2435void 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
2450void 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
2484void 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
2498void 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
2534void 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
2549void 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
2583void 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
2596void 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
2614void 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
2632void 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
2648void 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
2665static 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.
2676static 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
2723void 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
2743void 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
2828void 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
2840void 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
2857void 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
2874void 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
2891void 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
2908void 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
2925void 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
2939void 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.
2954enum VFPType { S32, U32, F32, F64 };
2955
2956
2957static 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
2970static 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
2985static 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.
3002static 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.
3020static 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
3065void 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
3074void 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
3082void 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
3091void 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
3097void 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
3103void 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
3109void 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
3118void 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
3127void 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
3136void 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
3145void 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
3164void 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
3182void 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
3197void 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
3214void 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
3228void 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
3251void 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
3269void 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
3292void 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
3310void 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
3333void 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
3351void 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
3372void 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
3388void 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
3409void 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
3425void 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
3448void 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
3466void 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
3484void 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
3499void 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
3514void 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
3527void 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
3543void 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
3559void 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
3575void 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
3591void 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
3623void 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
3655void 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
3672void 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
3686void 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
3694void 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
3702void 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
3716void 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
3730void 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
3744void 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
3758void 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
3772void 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
3786void 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
3800void 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
3814void 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
3828void 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
3844void 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
3858void 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
3872void 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
3887static 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
3913void 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
3925void 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
3938void 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
3944void 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
3956void 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
3968void 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
3981void 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
4006void 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.
4022static 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
4045void 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
4053void 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
4061void 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
4069void 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).
4078static 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
4091void 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
4098void 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
4106void 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
4113void 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
4121void 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
4136enum BinaryBitwiseOp { VAND, VBIC, VBIF, VBIT, VBSL, VEOR, VORR, VORN };
4137
4138static 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
4182void 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
4190void 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
4198void 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
4206void 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
4214enum FPBinOp {
4215  VADDF,
4216  VSUBF,
4217  VMULF,
4218  VMINF,
4219  VMAXF,
4220  VRECPS,
4221  VRSQRTS,
4222  VCEQF,
4223  VCGEF,
4224  VCGTF
4225};
4226
4227static 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
4275enum 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
4289static 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
4344static 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
4353void 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
4361void 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
4369void 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
4377void 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
4385void 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
4393void 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
4401void 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
4409void 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
4417void 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
4425void 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
4433void 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
4441void 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
4449enum NeonShiftOp { VSHL, VSHR };
4450
4451static 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
4475void 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
4483void 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
4491static 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
4502void 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
4509void 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
4516void 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
4524void 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
4532void 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
4540void 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
4548void 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
4556void 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
4564void 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
4572void 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
4580void 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
4588void 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
4604void 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
4618static 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
4634void Assembler::vrev16(NeonSize size, const QwNeonRegister dst,
4635                       const QwNeonRegister src) {
4636  DCHECK(IsEnabled(NEON));
4637  emit(EncodeNeonVREV(Neon16, size, dst, src));
4638}
4639
4640void Assembler::vrev32(NeonSize size, const QwNeonRegister dst,
4641                       const QwNeonRegister src) {
4642  DCHECK(IsEnabled(NEON));
4643  emit(EncodeNeonVREV(Neon32, size, dst, src));
4644}
4645
4646void 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.
4653static 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
4670void 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
4676void 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.
4683void 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
4694bool 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
4702bool 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
4710Instr Assembler::GetMovTPattern() { return kMovtPattern; }
4711
4712
4713Instr Assembler::GetMovWPattern() { return kMovwPattern; }
4714
4715
4716Instr Assembler::EncodeMovwImmediate(uint32_t immediate) {
4717  DCHECK(immediate < 0x10000);
4718  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
4719}
4720
4721
4722Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
4723  instruction &= ~EncodeMovwImmediate(0xffff);
4724  return instruction | EncodeMovwImmediate(immediate);
4725}
4726
4727
4728int 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
4735Instr 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
4745bool 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
4752bool Assembler::IsMovImmed(Instr instr) {
4753  return (instr & kMovImmedMask) == kMovImmedPattern;
4754}
4755
4756
4757bool Assembler::IsOrrImmed(Instr instr) {
4758  return (instr & kOrrImmedMask) == kOrrImmedPattern;
4759}
4760
4761
4762// static
4763bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
4764  uint32_t dummy1;
4765  uint32_t dummy2;
4766  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
4767}
4768
4769
4770bool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) {
4771  return is_uint12(abs(imm32));
4772}
4773
4774
4775// Debugging.
4776void 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
4783void 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
4823void 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
4834void 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
4845void 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
4856void 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
4864void 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
4881ConstantPoolEntry::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
4906ConstantPoolEntry::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
4926void 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
4955void 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
5176void 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