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