assembler-arm.cc revision 8389745919cae02139ddc085a63c00d024269cf2
1// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
35// Copyright 2012 the V8 project authors. All rights reserved.
36
37#include "src/arm/assembler-arm.h"
38
39#if V8_TARGET_ARCH_ARM
40
41#include "src/arm/assembler-arm-inl.h"
42#include "src/base/bits.h"
43#include "src/base/cpu.h"
44#include "src/macro-assembler.h"
45
46namespace v8 {
47namespace internal {
48
49// Get the CPU features enabled by the build. For cross compilation the
50// preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS
51// can be defined to enable ARMv7 and VFPv3 instructions when building the
52// snapshot.
53static unsigned CpuFeaturesImpliedByCompiler() {
54  unsigned answer = 0;
55#ifdef CAN_USE_ARMV8_INSTRUCTIONS
56  if (FLAG_enable_armv8) {
57    answer |= 1u << ARMv8;
58    // ARMv8 always features VFP and NEON.
59    answer |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS;
60    answer |= 1u << SUDIV | 1u << MLS;
61  }
62#endif  // CAN_USE_ARMV8_INSTRUCTIONS
63#ifdef CAN_USE_ARMV7_INSTRUCTIONS
64  if (FLAG_enable_armv7) answer |= 1u << ARMv7;
65#endif  // CAN_USE_ARMV7_INSTRUCTIONS
66#ifdef CAN_USE_VFP3_INSTRUCTIONS
67  if (FLAG_enable_vfp3) answer |= 1u << VFP3 | 1u << ARMv7;
68#endif  // CAN_USE_VFP3_INSTRUCTIONS
69#ifdef CAN_USE_VFP32DREGS
70  if (FLAG_enable_32dregs) answer |= 1u << VFP32DREGS;
71#endif  // CAN_USE_VFP32DREGS
72#ifdef CAN_USE_NEON
73  if (FLAG_enable_neon) answer |= 1u << NEON;
74#endif  // CAN_USE_VFP32DREGS
75  if ((answer & (1u << ARMv7)) && FLAG_enable_unaligned_accesses) {
76    answer |= 1u << UNALIGNED_ACCESSES;
77  }
78
79  return answer;
80}
81
82
83void CpuFeatures::ProbeImpl(bool cross_compile) {
84  supported_ |= CpuFeaturesImpliedByCompiler();
85  dcache_line_size_ = 64;
86
87  // Only use statically determined features for cross compile (snapshot).
88  if (cross_compile) return;
89
90#ifndef __arm__
91  // For the simulator build, use whatever the flags specify.
92  if (FLAG_enable_armv8) {
93    supported_ |= 1u << ARMv8;
94    // ARMv8 always features VFP and NEON.
95    supported_ |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS;
96    supported_ |= 1u << SUDIV | 1u << MLS;
97    if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
98  }
99  if (FLAG_enable_armv7) {
100    supported_ |= 1u << ARMv7;
101    if (FLAG_enable_vfp3) supported_ |= 1u << VFP3;
102    if (FLAG_enable_neon) supported_ |= 1u << NEON | 1u << VFP32DREGS;
103    if (FLAG_enable_sudiv) supported_ |= 1u << SUDIV;
104    if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
105    if (FLAG_enable_32dregs) supported_ |= 1u << VFP32DREGS;
106  }
107  if (FLAG_enable_mls) supported_ |= 1u << MLS;
108  if (FLAG_enable_unaligned_accesses) supported_ |= 1u << UNALIGNED_ACCESSES;
109
110#else  // __arm__
111  // Probe for additional features at runtime.
112  base::CPU cpu;
113  if (FLAG_enable_vfp3 && cpu.has_vfp3()) {
114    // This implementation also sets the VFP flags if runtime
115    // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
116    // 0406B, page A1-6.
117    supported_ |= 1u << VFP3 | 1u << ARMv7;
118  }
119
120  if (FLAG_enable_neon && cpu.has_neon()) supported_ |= 1u << NEON;
121  if (FLAG_enable_sudiv && cpu.has_idiva()) supported_ |= 1u << SUDIV;
122  if (FLAG_enable_mls && cpu.has_thumb2()) supported_ |= 1u << MLS;
123
124  if (cpu.architecture() >= 7) {
125    if (FLAG_enable_armv7) supported_ |= 1u << ARMv7;
126    if (FLAG_enable_armv8 && cpu.architecture() >= 8) {
127      supported_ |= 1u << ARMv8;
128    }
129    if (FLAG_enable_unaligned_accesses) supported_ |= 1u << UNALIGNED_ACCESSES;
130    // Use movw/movt for QUALCOMM ARMv7 cores.
131    if (FLAG_enable_movw_movt && cpu.implementer() == base::CPU::QUALCOMM) {
132      supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
133    }
134  }
135
136  // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
137  if (cpu.implementer() == base::CPU::ARM &&
138      (cpu.part() == base::CPU::ARM_CORTEX_A5 ||
139       cpu.part() == base::CPU::ARM_CORTEX_A9)) {
140    dcache_line_size_ = 32;
141  }
142
143  if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS;
144
145  if (cpu.implementer() == base::CPU::NVIDIA &&
146      cpu.variant() == base::CPU::NVIDIA_DENVER &&
147      cpu.part() <= base::CPU::NVIDIA_DENVER_V10) {
148    supported_ |= 1u << COHERENT_CACHE;
149  }
150#endif
151
152  DCHECK(!IsSupported(VFP3) || IsSupported(ARMv7));
153}
154
155
156void CpuFeatures::PrintTarget() {
157  const char* arm_arch = NULL;
158  const char* arm_target_type = "";
159  const char* arm_no_probe = "";
160  const char* arm_fpu = "";
161  const char* arm_thumb = "";
162  const char* arm_float_abi = NULL;
163
164#if !defined __arm__
165  arm_target_type = " simulator";
166#endif
167
168#if defined ARM_TEST_NO_FEATURE_PROBE
169  arm_no_probe = " noprobe";
170#endif
171
172#if defined CAN_USE_ARMV8_INSTRUCTIONS
173  arm_arch = "arm v8";
174#elif defined CAN_USE_ARMV7_INSTRUCTIONS
175  arm_arch = "arm v7";
176#else
177  arm_arch = "arm v6";
178#endif
179
180#if defined CAN_USE_NEON
181  arm_fpu = " neon";
182#elif defined CAN_USE_VFP3_INSTRUCTIONS
183#  if defined CAN_USE_VFP32DREGS
184  arm_fpu = " vfp3";
185#  else
186  arm_fpu = " vfp3-d16";
187#  endif
188#else
189  arm_fpu = " vfp2";
190#endif
191
192#ifdef __arm__
193  arm_float_abi = base::OS::ArmUsingHardFloat() ? "hard" : "softfp";
194#elif USE_EABI_HARDFLOAT
195  arm_float_abi = "hard";
196#else
197  arm_float_abi = "softfp";
198#endif
199
200#if defined __arm__ && (defined __thumb__) || (defined __thumb2__)
201  arm_thumb = " thumb";
202#endif
203
204  printf("target%s%s %s%s%s %s\n",
205         arm_target_type, arm_no_probe, arm_arch, arm_fpu, arm_thumb,
206         arm_float_abi);
207}
208
209
210void CpuFeatures::PrintFeatures() {
211  printf(
212    "ARMv8=%d ARMv7=%d VFP3=%d VFP32DREGS=%d NEON=%d SUDIV=%d MLS=%d"
213    "UNALIGNED_ACCESSES=%d MOVW_MOVT_IMMEDIATE_LOADS=%d COHERENT_CACHE=%d",
214    CpuFeatures::IsSupported(ARMv8),
215    CpuFeatures::IsSupported(ARMv7),
216    CpuFeatures::IsSupported(VFP3),
217    CpuFeatures::IsSupported(VFP32DREGS),
218    CpuFeatures::IsSupported(NEON),
219    CpuFeatures::IsSupported(SUDIV),
220    CpuFeatures::IsSupported(MLS),
221    CpuFeatures::IsSupported(UNALIGNED_ACCESSES),
222    CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS),
223    CpuFeatures::IsSupported(COHERENT_CACHE));
224#ifdef __arm__
225  bool eabi_hardfloat = base::OS::ArmUsingHardFloat();
226#elif USE_EABI_HARDFLOAT
227  bool eabi_hardfloat = true;
228#else
229  bool eabi_hardfloat = false;
230#endif
231    printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
232}
233
234
235// -----------------------------------------------------------------------------
236// Implementation of RelocInfo
237
238// static
239const int RelocInfo::kApplyMask = 0;
240
241
242bool RelocInfo::IsCodedSpecially() {
243  // The deserializer needs to know whether a pointer is specially coded.  Being
244  // specially coded on ARM means that it is a movw/movt instruction, or is an
245  // embedded constant pool entry.  These only occur if
246  // FLAG_enable_embedded_constant_pool is true.
247  return FLAG_enable_embedded_constant_pool;
248}
249
250
251bool RelocInfo::IsInConstantPool() {
252  return Assembler::is_constant_pool_load(pc_);
253}
254
255
256// -----------------------------------------------------------------------------
257// Implementation of Operand and MemOperand
258// See assembler-arm-inl.h for inlined constructors
259
260Operand::Operand(Handle<Object> handle) {
261  AllowDeferredHandleDereference using_raw_address;
262  rm_ = no_reg;
263  // Verify all Objects referred by code are NOT in new space.
264  Object* obj = *handle;
265  if (obj->IsHeapObject()) {
266    DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
267    imm32_ = reinterpret_cast<intptr_t>(handle.location());
268    rmode_ = RelocInfo::EMBEDDED_OBJECT;
269  } else {
270    // no relocation needed
271    imm32_ = reinterpret_cast<intptr_t>(obj);
272    rmode_ = RelocInfo::NONE32;
273  }
274}
275
276
277Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
278  DCHECK(is_uint5(shift_imm));
279
280  rm_ = rm;
281  rs_ = no_reg;
282  shift_op_ = shift_op;
283  shift_imm_ = shift_imm & 31;
284
285  if ((shift_op == ROR) && (shift_imm == 0)) {
286    // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode
287    // RRX as ROR #0 (See below).
288    shift_op = LSL;
289  } else if (shift_op == RRX) {
290    // encoded as ROR with shift_imm == 0
291    DCHECK(shift_imm == 0);
292    shift_op_ = ROR;
293    shift_imm_ = 0;
294  }
295}
296
297
298Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
299  DCHECK(shift_op != RRX);
300  rm_ = rm;
301  rs_ = no_reg;
302  shift_op_ = shift_op;
303  rs_ = rs;
304}
305
306
307MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
308  rn_ = rn;
309  rm_ = no_reg;
310  offset_ = offset;
311  am_ = am;
312
313  // Accesses below the stack pointer are not safe, and are prohibited by the
314  // ABI. We can check obvious violations here.
315  if (rn.is(sp)) {
316    if (am == Offset) DCHECK_LE(0, offset);
317    if (am == NegOffset) DCHECK_GE(0, offset);
318  }
319}
320
321
322MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
323  rn_ = rn;
324  rm_ = rm;
325  shift_op_ = LSL;
326  shift_imm_ = 0;
327  am_ = am;
328}
329
330
331MemOperand::MemOperand(Register rn, Register rm,
332                       ShiftOp shift_op, int shift_imm, AddrMode am) {
333  DCHECK(is_uint5(shift_imm));
334  rn_ = rn;
335  rm_ = rm;
336  shift_op_ = shift_op;
337  shift_imm_ = shift_imm & 31;
338  am_ = am;
339}
340
341
342NeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) {
343  DCHECK((am == Offset) || (am == PostIndex));
344  rn_ = rn;
345  rm_ = (am == Offset) ? pc : sp;
346  SetAlignment(align);
347}
348
349
350NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) {
351  rn_ = rn;
352  rm_ = rm;
353  SetAlignment(align);
354}
355
356
357void NeonMemOperand::SetAlignment(int align) {
358  switch (align) {
359    case 0:
360      align_ = 0;
361      break;
362    case 64:
363      align_ = 1;
364      break;
365    case 128:
366      align_ = 2;
367      break;
368    case 256:
369      align_ = 3;
370      break;
371    default:
372      UNREACHABLE();
373      align_ = 0;
374      break;
375  }
376}
377
378
379NeonListOperand::NeonListOperand(DoubleRegister base, int registers_count) {
380  base_ = base;
381  switch (registers_count) {
382    case 1:
383      type_ = nlt_1;
384      break;
385    case 2:
386      type_ = nlt_2;
387      break;
388    case 3:
389      type_ = nlt_3;
390      break;
391    case 4:
392      type_ = nlt_4;
393      break;
394    default:
395      UNREACHABLE();
396      type_ = nlt_1;
397      break;
398  }
399}
400
401
402// -----------------------------------------------------------------------------
403// Specific instructions, constants, and masks.
404
405// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
406// register r is not encoded.
407const Instr kPushRegPattern =
408    al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16;
409// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
410// register r is not encoded.
411const Instr kPopRegPattern =
412    al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
413// ldr rd, [pc, #offset]
414const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
415const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
416// ldr rd, [pp, #offset]
417const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
418const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
419// ldr rd, [pp, rn]
420const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
421const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
422// vldr dd, [pc, #offset]
423const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
424const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
425// vldr dd, [pp, #offset]
426const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
427const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
428// blxcc rm
429const Instr kBlxRegMask =
430    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
431const Instr kBlxRegPattern =
432    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
433const Instr kBlxIp = al | kBlxRegPattern | ip.code();
434const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
435const Instr kMovMvnPattern = 0xd * B21;
436const Instr kMovMvnFlip = B22;
437const Instr kMovLeaveCCMask = 0xdff * B16;
438const Instr kMovLeaveCCPattern = 0x1a0 * B16;
439const Instr kMovwPattern = 0x30 * B20;
440const Instr kMovtPattern = 0x34 * B20;
441const Instr kMovwLeaveCCFlip = 0x5 * B21;
442const Instr kMovImmedMask = 0x7f * B21;
443const Instr kMovImmedPattern = 0x1d * B21;
444const Instr kOrrImmedMask = 0x7f * B21;
445const Instr kOrrImmedPattern = 0x1c * B21;
446const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
447const Instr kCmpCmnPattern = 0x15 * B20;
448const Instr kCmpCmnFlip = B21;
449const Instr kAddSubFlip = 0x6 * B21;
450const Instr kAndBicFlip = 0xe * B21;
451
452// A mask for the Rd register for push, pop, ldr, str instructions.
453const Instr kLdrRegFpOffsetPattern =
454    al | B26 | L | Offset | Register::kCode_fp * B16;
455const Instr kStrRegFpOffsetPattern =
456    al | B26 | Offset | Register::kCode_fp * B16;
457const Instr kLdrRegFpNegOffsetPattern =
458    al | B26 | L | NegOffset | Register::kCode_fp * B16;
459const Instr kStrRegFpNegOffsetPattern =
460    al | B26 | NegOffset | Register::kCode_fp * B16;
461const Instr kLdrStrInstrTypeMask = 0xffff0000;
462
463
464Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
465    : AssemblerBase(isolate, buffer, buffer_size),
466      recorded_ast_id_(TypeFeedbackId::None()),
467      pending_32_bit_constants_(&pending_32_bit_constants_buffer_[0]),
468      pending_64_bit_constants_(&pending_64_bit_constants_buffer_[0]),
469      constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits),
470      positions_recorder_(this) {
471  reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
472  num_pending_32_bit_constants_ = 0;
473  num_pending_64_bit_constants_ = 0;
474  next_buffer_check_ = 0;
475  const_pool_blocked_nesting_ = 0;
476  no_const_pool_before_ = 0;
477  first_const_pool_32_use_ = -1;
478  first_const_pool_64_use_ = -1;
479  last_bound_pos_ = 0;
480  ClearRecordedAstId();
481}
482
483
484Assembler::~Assembler() {
485  DCHECK(const_pool_blocked_nesting_ == 0);
486  if (pending_32_bit_constants_ != &pending_32_bit_constants_buffer_[0]) {
487    delete[] pending_32_bit_constants_;
488  }
489  if (pending_64_bit_constants_ != &pending_64_bit_constants_buffer_[0]) {
490    delete[] pending_64_bit_constants_;
491  }
492}
493
494
495void Assembler::GetCode(CodeDesc* desc) {
496  reloc_info_writer.Finish();
497
498  // Emit constant pool if necessary.
499  int constant_pool_offset = 0;
500  if (FLAG_enable_embedded_constant_pool) {
501    constant_pool_offset = EmitEmbeddedConstantPool();
502  } else {
503    CheckConstPool(true, false);
504    DCHECK(num_pending_32_bit_constants_ == 0);
505    DCHECK(num_pending_64_bit_constants_ == 0);
506  }
507  // Set up code descriptor.
508  desc->buffer = buffer_;
509  desc->buffer_size = buffer_size_;
510  desc->instr_size = pc_offset();
511  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
512  desc->constant_pool_size =
513      (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
514  desc->origin = this;
515}
516
517
518void Assembler::Align(int m) {
519  DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
520  DCHECK((pc_offset() & (kInstrSize - 1)) == 0);
521  while ((pc_offset() & (m - 1)) != 0) {
522    nop();
523  }
524}
525
526
527void Assembler::CodeTargetAlign() {
528  // Preferred alignment of jump targets on some ARM chips.
529  Align(8);
530}
531
532
533Condition Assembler::GetCondition(Instr instr) {
534  return Instruction::ConditionField(instr);
535}
536
537
538bool Assembler::IsBranch(Instr instr) {
539  return (instr & (B27 | B25)) == (B27 | B25);
540}
541
542
543int Assembler::GetBranchOffset(Instr instr) {
544  DCHECK(IsBranch(instr));
545  // Take the jump offset in the lower 24 bits, sign extend it and multiply it
546  // with 4 to get the offset in bytes.
547  return ((instr & kImm24Mask) << 8) >> 6;
548}
549
550
551bool Assembler::IsLdrRegisterImmediate(Instr instr) {
552  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
553}
554
555
556bool Assembler::IsVldrDRegisterImmediate(Instr instr) {
557  return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
558}
559
560
561int Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
562  DCHECK(IsLdrRegisterImmediate(instr));
563  bool positive = (instr & B23) == B23;
564  int offset = instr & kOff12Mask;  // Zero extended offset.
565  return positive ? offset : -offset;
566}
567
568
569int Assembler::GetVldrDRegisterImmediateOffset(Instr instr) {
570  DCHECK(IsVldrDRegisterImmediate(instr));
571  bool positive = (instr & B23) == B23;
572  int offset = instr & kOff8Mask;  // Zero extended offset.
573  offset <<= 2;
574  return positive ? offset : -offset;
575}
576
577
578Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
579  DCHECK(IsLdrRegisterImmediate(instr));
580  bool positive = offset >= 0;
581  if (!positive) offset = -offset;
582  DCHECK(is_uint12(offset));
583  // Set bit indicating whether the offset should be added.
584  instr = (instr & ~B23) | (positive ? B23 : 0);
585  // Set the actual offset.
586  return (instr & ~kOff12Mask) | offset;
587}
588
589
590Instr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) {
591  DCHECK(IsVldrDRegisterImmediate(instr));
592  DCHECK((offset & ~3) == offset);  // Must be 64-bit aligned.
593  bool positive = offset >= 0;
594  if (!positive) offset = -offset;
595  DCHECK(is_uint10(offset));
596  // Set bit indicating whether the offset should be added.
597  instr = (instr & ~B23) | (positive ? B23 : 0);
598  // Set the actual offset. Its bottom 2 bits are zero.
599  return (instr & ~kOff8Mask) | (offset >> 2);
600}
601
602
603bool Assembler::IsStrRegisterImmediate(Instr instr) {
604  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
605}
606
607
608Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
609  DCHECK(IsStrRegisterImmediate(instr));
610  bool positive = offset >= 0;
611  if (!positive) offset = -offset;
612  DCHECK(is_uint12(offset));
613  // Set bit indicating whether the offset should be added.
614  instr = (instr & ~B23) | (positive ? B23 : 0);
615  // Set the actual offset.
616  return (instr & ~kOff12Mask) | offset;
617}
618
619
620bool Assembler::IsAddRegisterImmediate(Instr instr) {
621  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
622}
623
624
625Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
626  DCHECK(IsAddRegisterImmediate(instr));
627  DCHECK(offset >= 0);
628  DCHECK(is_uint12(offset));
629  // Set the offset.
630  return (instr & ~kOff12Mask) | offset;
631}
632
633
634Register Assembler::GetRd(Instr instr) {
635  Register reg;
636  reg.reg_code = Instruction::RdValue(instr);
637  return reg;
638}
639
640
641Register Assembler::GetRn(Instr instr) {
642  Register reg;
643  reg.reg_code = Instruction::RnValue(instr);
644  return reg;
645}
646
647
648Register Assembler::GetRm(Instr instr) {
649  Register reg;
650  reg.reg_code = Instruction::RmValue(instr);
651  return reg;
652}
653
654
655Instr Assembler::GetConsantPoolLoadPattern() {
656  if (FLAG_enable_embedded_constant_pool) {
657    return kLdrPpImmedPattern;
658  } else {
659    return kLdrPCImmedPattern;
660  }
661}
662
663
664Instr Assembler::GetConsantPoolLoadMask() {
665  if (FLAG_enable_embedded_constant_pool) {
666    return kLdrPpImmedMask;
667  } else {
668    return kLdrPCImmedMask;
669  }
670}
671
672
673bool Assembler::IsPush(Instr instr) {
674  return ((instr & ~kRdMask) == kPushRegPattern);
675}
676
677
678bool Assembler::IsPop(Instr instr) {
679  return ((instr & ~kRdMask) == kPopRegPattern);
680}
681
682
683bool Assembler::IsStrRegFpOffset(Instr instr) {
684  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
685}
686
687
688bool Assembler::IsLdrRegFpOffset(Instr instr) {
689  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
690}
691
692
693bool Assembler::IsStrRegFpNegOffset(Instr instr) {
694  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
695}
696
697
698bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
699  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
700}
701
702
703bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
704  // Check the instruction is indeed a
705  // ldr<cond> <Rd>, [pc +/- offset_12].
706  return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern;
707}
708
709
710bool Assembler::IsLdrPpImmediateOffset(Instr instr) {
711  // Check the instruction is indeed a
712  // ldr<cond> <Rd>, [pp +/- offset_12].
713  return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern;
714}
715
716
717bool Assembler::IsLdrPpRegOffset(Instr instr) {
718  // Check the instruction is indeed a
719  // ldr<cond> <Rd>, [pp, +/- <Rm>].
720  return (instr & kLdrPpRegMask) == kLdrPpRegPattern;
721}
722
723
724Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; }
725
726
727bool Assembler::IsVldrDPcImmediateOffset(Instr instr) {
728  // Check the instruction is indeed a
729  // vldr<cond> <Dd>, [pc +/- offset_10].
730  return (instr & kVldrDPCMask) == kVldrDPCPattern;
731}
732
733
734bool Assembler::IsVldrDPpImmediateOffset(Instr instr) {
735  // Check the instruction is indeed a
736  // vldr<cond> <Dd>, [pp +/- offset_10].
737  return (instr & kVldrDPpMask) == kVldrDPpPattern;
738}
739
740
741bool Assembler::IsBlxReg(Instr instr) {
742  // Check the instruction is indeed a
743  // blxcc <Rm>
744  return (instr & kBlxRegMask) == kBlxRegPattern;
745}
746
747
748bool Assembler::IsBlxIp(Instr instr) {
749  // Check the instruction is indeed a
750  // blx ip
751  return instr == kBlxIp;
752}
753
754
755bool Assembler::IsTstImmediate(Instr instr) {
756  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
757      (I | TST | S);
758}
759
760
761bool Assembler::IsCmpRegister(Instr instr) {
762  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
763      (CMP | S);
764}
765
766
767bool Assembler::IsCmpImmediate(Instr instr) {
768  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
769      (I | CMP | S);
770}
771
772
773Register Assembler::GetCmpImmediateRegister(Instr instr) {
774  DCHECK(IsCmpImmediate(instr));
775  return GetRn(instr);
776}
777
778
779int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
780  DCHECK(IsCmpImmediate(instr));
781  return instr & kOff12Mask;
782}
783
784
785// Labels refer to positions in the (to be) generated code.
786// There are bound, linked, and unused labels.
787//
788// Bound labels refer to known positions in the already
789// generated code. pos() is the position the label refers to.
790//
791// Linked labels refer to unknown positions in the code
792// to be generated; pos() is the position of the last
793// instruction using the label.
794//
795// The linked labels form a link chain by making the branch offset
796// in the instruction steam to point to the previous branch
797// instruction using the same label.
798//
799// The link chain is terminated by a branch offset pointing to the
800// same position.
801
802
803int Assembler::target_at(int pos) {
804  Instr instr = instr_at(pos);
805  if (is_uint24(instr)) {
806    // Emitted link to a label, not part of a branch.
807    return instr;
808  }
809  DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
810  int imm26 = ((instr & kImm24Mask) << 8) >> 6;
811  if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
812      ((instr & B24) != 0)) {
813    // blx uses bit 24 to encode bit 2 of imm26
814    imm26 += 2;
815  }
816  return pos + kPcLoadDelta + imm26;
817}
818
819
820void Assembler::target_at_put(int pos, int target_pos) {
821  Instr instr = instr_at(pos);
822  if (is_uint24(instr)) {
823    DCHECK(target_pos == pos || target_pos >= 0);
824    // Emitted link to a label, not part of a branch.
825    // Load the position of the label relative to the generated code object
826    // pointer in a register.
827
828    // Here are the instructions we need to emit:
829    //   For ARMv7: target24 => target16_1:target16_0
830    //      movw dst, #target16_0
831    //      movt dst, #target16_1
832    //   For ARMv6: target24 => target8_2:target8_1:target8_0
833    //      mov dst, #target8_0
834    //      orr dst, dst, #target8_1 << 8
835    //      orr dst, dst, #target8_2 << 16
836
837    // We extract the destination register from the emitted nop instruction.
838    Register dst = Register::from_code(
839        Instruction::RmValue(instr_at(pos + kInstrSize)));
840    DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
841    uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
842    DCHECK(is_uint24(target24));
843    if (is_uint8(target24)) {
844      // If the target fits in a byte then only patch with a mov
845      // instruction.
846      CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 1,
847                          CodePatcher::DONT_FLUSH);
848      patcher.masm()->mov(dst, Operand(target24));
849    } else {
850      uint16_t target16_0 = target24 & kImm16Mask;
851      uint16_t target16_1 = target24 >> 16;
852      if (CpuFeatures::IsSupported(ARMv7)) {
853        // Patch with movw/movt.
854        if (target16_1 == 0) {
855          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
856                              1, CodePatcher::DONT_FLUSH);
857          patcher.masm()->movw(dst, target16_0);
858        } else {
859          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
860                              2, CodePatcher::DONT_FLUSH);
861          patcher.masm()->movw(dst, target16_0);
862          patcher.masm()->movt(dst, target16_1);
863        }
864      } else {
865        // Patch with a sequence of mov/orr/orr instructions.
866        uint8_t target8_0 = target16_0 & kImm8Mask;
867        uint8_t target8_1 = target16_0 >> 8;
868        uint8_t target8_2 = target16_1 & kImm8Mask;
869        if (target8_2 == 0) {
870          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
871                              2, CodePatcher::DONT_FLUSH);
872          patcher.masm()->mov(dst, Operand(target8_0));
873          patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
874        } else {
875          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
876                              3, CodePatcher::DONT_FLUSH);
877          patcher.masm()->mov(dst, Operand(target8_0));
878          patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
879          patcher.masm()->orr(dst, dst, Operand(target8_2 << 16));
880        }
881      }
882    }
883    return;
884  }
885  int imm26 = target_pos - (pos + kPcLoadDelta);
886  DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
887  if (Instruction::ConditionField(instr) == kSpecialCondition) {
888    // blx uses bit 24 to encode bit 2 of imm26
889    DCHECK_EQ(0, imm26 & 1);
890    instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1) * B24;
891  } else {
892    DCHECK_EQ(0, imm26 & 3);
893    instr &= ~kImm24Mask;
894  }
895  int imm24 = imm26 >> 2;
896  DCHECK(is_int24(imm24));
897  instr_at_put(pos, instr | (imm24 & kImm24Mask));
898}
899
900
901void Assembler::print(Label* L) {
902  if (L->is_unused()) {
903    PrintF("unused label\n");
904  } else if (L->is_bound()) {
905    PrintF("bound label to %d\n", L->pos());
906  } else if (L->is_linked()) {
907    Label l = *L;
908    PrintF("unbound label");
909    while (l.is_linked()) {
910      PrintF("@ %d ", l.pos());
911      Instr instr = instr_at(l.pos());
912      if ((instr & ~kImm24Mask) == 0) {
913        PrintF("value\n");
914      } else {
915        DCHECK((instr & 7*B25) == 5*B25);  // b, bl, or blx
916        Condition cond = Instruction::ConditionField(instr);
917        const char* b;
918        const char* c;
919        if (cond == kSpecialCondition) {
920          b = "blx";
921          c = "";
922        } else {
923          if ((instr & B24) != 0)
924            b = "bl";
925          else
926            b = "b";
927
928          switch (cond) {
929            case eq: c = "eq"; break;
930            case ne: c = "ne"; break;
931            case hs: c = "hs"; break;
932            case lo: c = "lo"; break;
933            case mi: c = "mi"; break;
934            case pl: c = "pl"; break;
935            case vs: c = "vs"; break;
936            case vc: c = "vc"; break;
937            case hi: c = "hi"; break;
938            case ls: c = "ls"; break;
939            case ge: c = "ge"; break;
940            case lt: c = "lt"; break;
941            case gt: c = "gt"; break;
942            case le: c = "le"; break;
943            case al: c = ""; break;
944            default:
945              c = "";
946              UNREACHABLE();
947          }
948        }
949        PrintF("%s%s\n", b, c);
950      }
951      next(&l);
952    }
953  } else {
954    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
955  }
956}
957
958
959void Assembler::bind_to(Label* L, int pos) {
960  DCHECK(0 <= pos && pos <= pc_offset());  // must have a valid binding position
961  while (L->is_linked()) {
962    int fixup_pos = L->pos();
963    next(L);  // call next before overwriting link with target at fixup_pos
964    target_at_put(fixup_pos, pos);
965  }
966  L->bind_to(pos);
967
968  // Keep track of the last bound label so we don't eliminate any instructions
969  // before a bound label.
970  if (pos > last_bound_pos_)
971    last_bound_pos_ = pos;
972}
973
974
975void Assembler::bind(Label* L) {
976  DCHECK(!L->is_bound());  // label can only be bound once
977  bind_to(L, pc_offset());
978}
979
980
981void Assembler::next(Label* L) {
982  DCHECK(L->is_linked());
983  int link = target_at(L->pos());
984  if (link == L->pos()) {
985    // Branch target points to the same instuction. This is the end of the link
986    // chain.
987    L->Unuse();
988  } else {
989    DCHECK(link >= 0);
990    L->link_to(link);
991  }
992}
993
994
995// Low-level code emission routines depending on the addressing mode.
996// If this returns true then you have to use the rotate_imm and immed_8
997// that it returns, because it may have already changed the instruction
998// to match them!
999static bool fits_shifter(uint32_t imm32,
1000                         uint32_t* rotate_imm,
1001                         uint32_t* immed_8,
1002                         Instr* instr) {
1003  // imm32 must be unsigned.
1004  for (int rot = 0; rot < 16; rot++) {
1005    uint32_t imm8 = base::bits::RotateLeft32(imm32, 2 * rot);
1006    if ((imm8 <= 0xff)) {
1007      *rotate_imm = rot;
1008      *immed_8 = imm8;
1009      return true;
1010    }
1011  }
1012  // If the opcode is one with a complementary version and the complementary
1013  // immediate fits, change the opcode.
1014  if (instr != NULL) {
1015    if ((*instr & kMovMvnMask) == kMovMvnPattern) {
1016      if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
1017        *instr ^= kMovMvnFlip;
1018        return true;
1019      } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
1020        if (CpuFeatures::IsSupported(ARMv7)) {
1021          if (imm32 < 0x10000) {
1022            *instr ^= kMovwLeaveCCFlip;
1023            *instr |= Assembler::EncodeMovwImmediate(imm32);
1024            *rotate_imm = *immed_8 = 0;  // Not used for movw.
1025            return true;
1026          }
1027        }
1028      }
1029    } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
1030      if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
1031        *instr ^= kCmpCmnFlip;
1032        return true;
1033      }
1034    } else {
1035      Instr alu_insn = (*instr & kALUMask);
1036      if (alu_insn == ADD ||
1037          alu_insn == SUB) {
1038        if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
1039          *instr ^= kAddSubFlip;
1040          return true;
1041        }
1042      } else if (alu_insn == AND ||
1043                 alu_insn == BIC) {
1044        if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
1045          *instr ^= kAndBicFlip;
1046          return true;
1047        }
1048      }
1049    }
1050  }
1051  return false;
1052}
1053
1054
1055// We have to use the temporary register for things that can be relocated even
1056// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
1057// space.  There is no guarantee that the relocated location can be similarly
1058// encoded.
1059bool Operand::must_output_reloc_info(const Assembler* assembler) const {
1060  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
1061    if (assembler != NULL && assembler->predictable_code_size()) return true;
1062    return assembler->serializer_enabled();
1063  } else if (RelocInfo::IsNone(rmode_)) {
1064    return false;
1065  }
1066  return true;
1067}
1068
1069
1070static bool use_mov_immediate_load(const Operand& x,
1071                                   const Assembler* assembler) {
1072  if (FLAG_enable_embedded_constant_pool && assembler != NULL &&
1073      !assembler->is_constant_pool_available()) {
1074    return true;
1075  } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1076             (assembler == NULL || !assembler->predictable_code_size())) {
1077    // Prefer movw / movt to constant pool if it is more efficient on the CPU.
1078    return true;
1079  } else if (x.must_output_reloc_info(assembler)) {
1080    // Prefer constant pool if data is likely to be patched.
1081    return false;
1082  } else {
1083    // Otherwise, use immediate load if movw / movt is available.
1084    return CpuFeatures::IsSupported(ARMv7);
1085  }
1086}
1087
1088
1089int Operand::instructions_required(const Assembler* assembler,
1090                                   Instr instr) const {
1091  if (rm_.is_valid()) return 1;
1092  uint32_t dummy1, dummy2;
1093  if (must_output_reloc_info(assembler) ||
1094      !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
1095    // The immediate operand cannot be encoded as a shifter operand, or use of
1096    // constant pool is required.  First account for the instructions required
1097    // for the constant pool or immediate load
1098    int instructions;
1099    if (use_mov_immediate_load(*this, assembler)) {
1100      // A movw / movt or mov / orr immediate load.
1101      instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
1102    } else if (assembler != NULL &&
1103               assembler->ConstantPoolAccessIsInOverflow()) {
1104      // An overflowed constant pool load.
1105      instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
1106    } else {
1107      // A small constant pool load.
1108      instructions = 1;
1109    }
1110
1111    if ((instr & ~kCondMask) != 13 * B21) {  // mov, S not set
1112      // For a mov or mvn instruction which doesn't set the condition
1113      // code, the constant pool or immediate load is enough, otherwise we need
1114      // to account for the actual instruction being requested.
1115      instructions += 1;
1116    }
1117    return instructions;
1118  } else {
1119    // No use of constant pool and the immediate operand can be encoded as a
1120    // shifter operand.
1121    return 1;
1122  }
1123}
1124
1125
1126void Assembler::move_32_bit_immediate(Register rd,
1127                                      const Operand& x,
1128                                      Condition cond) {
1129  uint32_t imm32 = static_cast<uint32_t>(x.imm32_);
1130  if (x.must_output_reloc_info(this)) {
1131    RecordRelocInfo(x.rmode_);
1132  }
1133
1134  if (use_mov_immediate_load(x, this)) {
1135    Register target = rd.code() == pc.code() ? ip : rd;
1136    if (CpuFeatures::IsSupported(ARMv7)) {
1137      if (!FLAG_enable_embedded_constant_pool &&
1138          x.must_output_reloc_info(this)) {
1139        // Make sure the movw/movt doesn't get separated.
1140        BlockConstPoolFor(2);
1141      }
1142      movw(target, imm32 & 0xffff, cond);
1143      movt(target, imm32 >> 16, cond);
1144    } else {
1145      DCHECK(FLAG_enable_embedded_constant_pool);
1146      mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
1147      orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
1148      orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
1149      orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond);
1150    }
1151    if (target.code() != rd.code()) {
1152      mov(rd, target, LeaveCC, cond);
1153    }
1154  } else {
1155    DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available());
1156    ConstantPoolEntry::Access access =
1157        ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_);
1158    if (access == ConstantPoolEntry::OVERFLOWED) {
1159      DCHECK(FLAG_enable_embedded_constant_pool);
1160      Register target = rd.code() == pc.code() ? ip : rd;
1161      // Emit instructions to load constant pool offset.
1162      if (CpuFeatures::IsSupported(ARMv7)) {
1163        movw(target, 0, cond);
1164        movt(target, 0, cond);
1165      } else {
1166        mov(target, Operand(0), LeaveCC, cond);
1167        orr(target, target, Operand(0), LeaveCC, cond);
1168        orr(target, target, Operand(0), LeaveCC, cond);
1169        orr(target, target, Operand(0), LeaveCC, cond);
1170      }
1171      // Load from constant pool at offset.
1172      ldr(rd, MemOperand(pp, target), cond);
1173    } else {
1174      DCHECK(access == ConstantPoolEntry::REGULAR);
1175      ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0),
1176          cond);
1177    }
1178  }
1179}
1180
1181
1182void Assembler::addrmod1(Instr instr,
1183                         Register rn,
1184                         Register rd,
1185                         const Operand& x) {
1186  CheckBuffer();
1187  DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
1188  if (!x.rm_.is_valid()) {
1189    // Immediate.
1190    uint32_t rotate_imm;
1191    uint32_t immed_8;
1192    if (x.must_output_reloc_info(this) ||
1193        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
1194      // The immediate operand cannot be encoded as a shifter operand, so load
1195      // it first to register ip and change the original instruction to use ip.
1196      // However, if the original instruction is a 'mov rd, x' (not setting the
1197      // condition code), then replace it with a 'ldr rd, [pc]'.
1198      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
1199      Condition cond = Instruction::ConditionField(instr);
1200      if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
1201        move_32_bit_immediate(rd, x, cond);
1202      } else {
1203        mov(ip, x, LeaveCC, cond);
1204        addrmod1(instr, rn, rd, Operand(ip));
1205      }
1206      return;
1207    }
1208    instr |= I | rotate_imm*B8 | immed_8;
1209  } else if (!x.rs_.is_valid()) {
1210    // Immediate shift.
1211    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
1212  } else {
1213    // Register shift.
1214    DCHECK(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
1215    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
1216  }
1217  emit(instr | rn.code()*B16 | rd.code()*B12);
1218  if (rn.is(pc) || x.rm_.is(pc)) {
1219    // Block constant pool emission for one instruction after reading pc.
1220    BlockConstPoolFor(1);
1221  }
1222}
1223
1224
1225void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
1226  DCHECK((instr & ~(kCondMask | B | L)) == B26);
1227  int am = x.am_;
1228  if (!x.rm_.is_valid()) {
1229    // Immediate offset.
1230    int offset_12 = x.offset_;
1231    if (offset_12 < 0) {
1232      offset_12 = -offset_12;
1233      am ^= U;
1234    }
1235    if (!is_uint12(offset_12)) {
1236      // Immediate offset cannot be encoded, load it first to register ip
1237      // rn (and rd in a load) should never be ip, or will be trashed.
1238      DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1239      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
1240      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
1241      return;
1242    }
1243    DCHECK(offset_12 >= 0);  // no masking needed
1244    instr |= offset_12;
1245  } else {
1246    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
1247    // register offset the constructors make sure than both shift_imm_
1248    // and shift_op_ are initialized.
1249    DCHECK(!x.rm_.is(pc));
1250    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
1251  }
1252  DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
1253  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
1254}
1255
1256
1257void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
1258  DCHECK((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
1259  DCHECK(x.rn_.is_valid());
1260  int am = x.am_;
1261  if (!x.rm_.is_valid()) {
1262    // Immediate offset.
1263    int offset_8 = x.offset_;
1264    if (offset_8 < 0) {
1265      offset_8 = -offset_8;
1266      am ^= U;
1267    }
1268    if (!is_uint8(offset_8)) {
1269      // Immediate offset cannot be encoded, load it first to register ip
1270      // rn (and rd in a load) should never be ip, or will be trashed.
1271      DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1272      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
1273      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
1274      return;
1275    }
1276    DCHECK(offset_8 >= 0);  // no masking needed
1277    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
1278  } else if (x.shift_imm_ != 0) {
1279    // Scaled register offset not supported, load index first
1280    // rn (and rd in a load) should never be ip, or will be trashed.
1281    DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1282    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
1283        Instruction::ConditionField(instr));
1284    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
1285    return;
1286  } else {
1287    // Register offset.
1288    DCHECK((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
1289    instr |= x.rm_.code();
1290  }
1291  DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
1292  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
1293}
1294
1295
1296void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
1297  DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
1298  DCHECK(rl != 0);
1299  DCHECK(!rn.is(pc));
1300  emit(instr | rn.code()*B16 | rl);
1301}
1302
1303
1304void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
1305  // Unindexed addressing is not encoded by this function.
1306  DCHECK_EQ((B27 | B26),
1307            (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
1308  DCHECK(x.rn_.is_valid() && !x.rm_.is_valid());
1309  int am = x.am_;
1310  int offset_8 = x.offset_;
1311  DCHECK((offset_8 & 3) == 0);  // offset must be an aligned word offset
1312  offset_8 >>= 2;
1313  if (offset_8 < 0) {
1314    offset_8 = -offset_8;
1315    am ^= U;
1316  }
1317  DCHECK(is_uint8(offset_8));  // unsigned word offset must fit in a byte
1318  DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
1319
1320  // Post-indexed addressing requires W == 1; different than in addrmod2/3.
1321  if ((am & P) == 0)
1322    am |= W;
1323
1324  DCHECK(offset_8 >= 0);  // no masking needed
1325  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
1326}
1327
1328
1329int Assembler::branch_offset(Label* L) {
1330  int target_pos;
1331  if (L->is_bound()) {
1332    target_pos = L->pos();
1333  } else {
1334    if (L->is_linked()) {
1335      // Point to previous instruction that uses the link.
1336      target_pos = L->pos();
1337    } else {
1338      // First entry of the link chain points to itself.
1339      target_pos = pc_offset();
1340    }
1341    L->link_to(pc_offset());
1342  }
1343
1344  // Block the emission of the constant pool, since the branch instruction must
1345  // be emitted at the pc offset recorded by the label.
1346  if (!is_const_pool_blocked()) BlockConstPoolFor(1);
1347
1348  return target_pos - (pc_offset() + kPcLoadDelta);
1349}
1350
1351
1352// Branch instructions.
1353void Assembler::b(int branch_offset, Condition cond) {
1354  DCHECK((branch_offset & 3) == 0);
1355  int imm24 = branch_offset >> 2;
1356  CHECK(is_int24(imm24));
1357  emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1358
1359  if (cond == al) {
1360    // Dead code is a good location to emit the constant pool.
1361    CheckConstPool(false, false);
1362  }
1363}
1364
1365
1366void Assembler::bl(int branch_offset, Condition cond) {
1367  positions_recorder()->WriteRecordedPositions();
1368  DCHECK((branch_offset & 3) == 0);
1369  int imm24 = branch_offset >> 2;
1370  CHECK(is_int24(imm24));
1371  emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
1372}
1373
1374
1375void Assembler::blx(int branch_offset) {  // v5 and above
1376  positions_recorder()->WriteRecordedPositions();
1377  DCHECK((branch_offset & 1) == 0);
1378  int h = ((branch_offset & 2) >> 1)*B24;
1379  int imm24 = branch_offset >> 2;
1380  CHECK(is_int24(imm24));
1381  emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
1382}
1383
1384
1385void Assembler::blx(Register target, Condition cond) {  // v5 and above
1386  positions_recorder()->WriteRecordedPositions();
1387  DCHECK(!target.is(pc));
1388  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
1389}
1390
1391
1392void Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
1393  positions_recorder()->WriteRecordedPositions();
1394  DCHECK(!target.is(pc));  // use of pc is actually allowed, but discouraged
1395  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
1396}
1397
1398
1399void Assembler::b(Label* L, Condition cond) {
1400  CheckBuffer();
1401  b(branch_offset(L), cond);
1402}
1403
1404
1405void Assembler::bl(Label* L, Condition cond) {
1406  CheckBuffer();
1407  bl(branch_offset(L), cond);
1408}
1409
1410
1411void Assembler::blx(Label* L) {
1412  CheckBuffer();
1413  blx(branch_offset(L));
1414}
1415
1416
1417// Data-processing instructions.
1418
1419void Assembler::and_(Register dst, Register src1, const Operand& src2,
1420                     SBit s, Condition cond) {
1421  addrmod1(cond | AND | s, src1, dst, src2);
1422}
1423
1424
1425void Assembler::eor(Register dst, Register src1, const Operand& src2,
1426                    SBit s, Condition cond) {
1427  addrmod1(cond | EOR | s, src1, dst, src2);
1428}
1429
1430
1431void Assembler::sub(Register dst, Register src1, const Operand& src2,
1432                    SBit s, Condition cond) {
1433  addrmod1(cond | SUB | s, src1, dst, src2);
1434}
1435
1436
1437void Assembler::rsb(Register dst, Register src1, const Operand& src2,
1438                    SBit s, Condition cond) {
1439  addrmod1(cond | RSB | s, src1, dst, src2);
1440}
1441
1442
1443void Assembler::add(Register dst, Register src1, const Operand& src2,
1444                    SBit s, Condition cond) {
1445  addrmod1(cond | ADD | s, src1, dst, src2);
1446}
1447
1448
1449void Assembler::adc(Register dst, Register src1, const Operand& src2,
1450                    SBit s, Condition cond) {
1451  addrmod1(cond | ADC | s, src1, dst, src2);
1452}
1453
1454
1455void Assembler::sbc(Register dst, Register src1, const Operand& src2,
1456                    SBit s, Condition cond) {
1457  addrmod1(cond | SBC | s, src1, dst, src2);
1458}
1459
1460
1461void Assembler::rsc(Register dst, Register src1, const Operand& src2,
1462                    SBit s, Condition cond) {
1463  addrmod1(cond | RSC | s, src1, dst, src2);
1464}
1465
1466
1467void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
1468  addrmod1(cond | TST | S, src1, r0, src2);
1469}
1470
1471
1472void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
1473  addrmod1(cond | TEQ | S, src1, r0, src2);
1474}
1475
1476
1477void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
1478  addrmod1(cond | CMP | S, src1, r0, src2);
1479}
1480
1481
1482void Assembler::cmp_raw_immediate(
1483    Register src, int raw_immediate, Condition cond) {
1484  DCHECK(is_uint12(raw_immediate));
1485  emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
1486}
1487
1488
1489void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
1490  addrmod1(cond | CMN | S, src1, r0, src2);
1491}
1492
1493
1494void Assembler::orr(Register dst, Register src1, const Operand& src2,
1495                    SBit s, Condition cond) {
1496  addrmod1(cond | ORR | s, src1, dst, src2);
1497}
1498
1499
1500void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
1501  if (dst.is(pc)) {
1502    positions_recorder()->WriteRecordedPositions();
1503  }
1504  // Don't allow nop instructions in the form mov rn, rn to be generated using
1505  // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
1506  // or MarkCode(int/NopMarkerTypes) pseudo instructions.
1507  DCHECK(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
1508  addrmod1(cond | MOV | s, r0, dst, src);
1509}
1510
1511
1512void Assembler::mov_label_offset(Register dst, Label* label) {
1513  if (label->is_bound()) {
1514    mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag)));
1515  } else {
1516    // Emit the link to the label in the code stream followed by extra nop
1517    // instructions.
1518    // If the label is not linked, then start a new link chain by linking it to
1519    // itself, emitting pc_offset().
1520    int link = label->is_linked() ? label->pos() : pc_offset();
1521    label->link_to(pc_offset());
1522
1523    // When the label is bound, these instructions will be patched with a
1524    // sequence of movw/movt or mov/orr/orr instructions. They will load the
1525    // destination register with the position of the label from the beginning
1526    // of the code.
1527    //
1528    // The link will be extracted from the first instruction and the destination
1529    // register from the second.
1530    //   For ARMv7:
1531    //      link
1532    //      mov dst, dst
1533    //   For ARMv6:
1534    //      link
1535    //      mov dst, dst
1536    //      mov dst, dst
1537    //
1538    // When the label gets bound: target_at extracts the link and target_at_put
1539    // patches the instructions.
1540    CHECK(is_uint24(link));
1541    BlockConstPoolScope block_const_pool(this);
1542    emit(link);
1543    nop(dst.code());
1544    if (!CpuFeatures::IsSupported(ARMv7)) {
1545      nop(dst.code());
1546    }
1547  }
1548}
1549
1550
1551void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
1552  DCHECK(CpuFeatures::IsSupported(ARMv7));
1553  emit(cond | 0x30*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
1554}
1555
1556
1557void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
1558  DCHECK(CpuFeatures::IsSupported(ARMv7));
1559  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
1560}
1561
1562
1563void Assembler::bic(Register dst, Register src1, const Operand& src2,
1564                    SBit s, Condition cond) {
1565  addrmod1(cond | BIC | s, src1, dst, src2);
1566}
1567
1568
1569void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
1570  addrmod1(cond | MVN | s, r0, dst, src);
1571}
1572
1573
1574// Multiply instructions.
1575void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1576                    SBit s, Condition cond) {
1577  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1578  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
1579       src2.code()*B8 | B7 | B4 | src1.code());
1580}
1581
1582
1583void Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
1584                    Condition cond) {
1585  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1586  DCHECK(IsEnabled(MLS));
1587  emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 |
1588       src2.code()*B8 | B7 | B4 | src1.code());
1589}
1590
1591
1592void Assembler::sdiv(Register dst, Register src1, Register src2,
1593                     Condition cond) {
1594  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1595  DCHECK(IsEnabled(SUDIV));
1596  emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 |
1597       src2.code()*B8 | B4 | src1.code());
1598}
1599
1600
1601void Assembler::udiv(Register dst, Register src1, Register src2,
1602                     Condition cond) {
1603  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1604  DCHECK(IsEnabled(SUDIV));
1605  emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xf * B12 |
1606       src2.code() * B8 | B4 | src1.code());
1607}
1608
1609
1610void Assembler::mul(Register dst, Register src1, Register src2, SBit s,
1611                    Condition cond) {
1612  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1613  // dst goes in bits 16-19 for this instruction!
1614  emit(cond | s | dst.code() * B16 | src2.code() * B8 | B7 | B4 | src1.code());
1615}
1616
1617
1618void Assembler::smmla(Register dst, Register src1, Register src2, Register srcA,
1619                      Condition cond) {
1620  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1621  emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 |
1622       srcA.code() * B12 | src2.code() * B8 | B4 | src1.code());
1623}
1624
1625
1626void Assembler::smmul(Register dst, Register src1, Register src2,
1627                      Condition cond) {
1628  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1629  emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 0xf * B12 |
1630       src2.code() * B8 | B4 | src1.code());
1631}
1632
1633
1634void Assembler::smlal(Register dstL,
1635                      Register dstH,
1636                      Register src1,
1637                      Register src2,
1638                      SBit s,
1639                      Condition cond) {
1640  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1641  DCHECK(!dstL.is(dstH));
1642  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1643       src2.code()*B8 | B7 | B4 | src1.code());
1644}
1645
1646
1647void Assembler::smull(Register dstL,
1648                      Register dstH,
1649                      Register src1,
1650                      Register src2,
1651                      SBit s,
1652                      Condition cond) {
1653  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1654  DCHECK(!dstL.is(dstH));
1655  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1656       src2.code()*B8 | B7 | B4 | src1.code());
1657}
1658
1659
1660void Assembler::umlal(Register dstL,
1661                      Register dstH,
1662                      Register src1,
1663                      Register src2,
1664                      SBit s,
1665                      Condition cond) {
1666  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1667  DCHECK(!dstL.is(dstH));
1668  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1669       src2.code()*B8 | B7 | B4 | src1.code());
1670}
1671
1672
1673void Assembler::umull(Register dstL,
1674                      Register dstH,
1675                      Register src1,
1676                      Register src2,
1677                      SBit s,
1678                      Condition cond) {
1679  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1680  DCHECK(!dstL.is(dstH));
1681  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1682       src2.code()*B8 | B7 | B4 | src1.code());
1683}
1684
1685
1686// Miscellaneous arithmetic instructions.
1687void Assembler::clz(Register dst, Register src, Condition cond) {
1688  // v5 and above.
1689  DCHECK(!dst.is(pc) && !src.is(pc));
1690  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
1691       15*B8 | CLZ | src.code());
1692}
1693
1694
1695// Saturating instructions.
1696
1697// Unsigned saturate.
1698void Assembler::usat(Register dst,
1699                     int satpos,
1700                     const Operand& src,
1701                     Condition cond) {
1702  // v6 and above.
1703  DCHECK(CpuFeatures::IsSupported(ARMv7));
1704  DCHECK(!dst.is(pc) && !src.rm_.is(pc));
1705  DCHECK((satpos >= 0) && (satpos <= 31));
1706  DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
1707  DCHECK(src.rs_.is(no_reg));
1708
1709  int sh = 0;
1710  if (src.shift_op_ == ASR) {
1711      sh = 1;
1712  }
1713
1714  emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
1715       src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
1716}
1717
1718
1719// Bitfield manipulation instructions.
1720
1721// Unsigned bit field extract.
1722// Extracts #width adjacent bits from position #lsb in a register, and
1723// writes them to the low bits of a destination register.
1724//   ubfx dst, src, #lsb, #width
1725void Assembler::ubfx(Register dst,
1726                     Register src,
1727                     int lsb,
1728                     int width,
1729                     Condition cond) {
1730  // v7 and above.
1731  DCHECK(CpuFeatures::IsSupported(ARMv7));
1732  DCHECK(!dst.is(pc) && !src.is(pc));
1733  DCHECK((lsb >= 0) && (lsb <= 31));
1734  DCHECK((width >= 1) && (width <= (32 - lsb)));
1735  emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
1736       lsb*B7 | B6 | B4 | src.code());
1737}
1738
1739
1740// Signed bit field extract.
1741// Extracts #width adjacent bits from position #lsb in a register, and
1742// writes them to the low bits of a destination register. The extracted
1743// value is sign extended to fill the destination register.
1744//   sbfx dst, src, #lsb, #width
1745void Assembler::sbfx(Register dst,
1746                     Register src,
1747                     int lsb,
1748                     int width,
1749                     Condition cond) {
1750  // v7 and above.
1751  DCHECK(CpuFeatures::IsSupported(ARMv7));
1752  DCHECK(!dst.is(pc) && !src.is(pc));
1753  DCHECK((lsb >= 0) && (lsb <= 31));
1754  DCHECK((width >= 1) && (width <= (32 - lsb)));
1755  emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
1756       lsb*B7 | B6 | B4 | src.code());
1757}
1758
1759
1760// Bit field clear.
1761// Sets #width adjacent bits at position #lsb in the destination register
1762// to zero, preserving the value of the other bits.
1763//   bfc dst, #lsb, #width
1764void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
1765  // v7 and above.
1766  DCHECK(CpuFeatures::IsSupported(ARMv7));
1767  DCHECK(!dst.is(pc));
1768  DCHECK((lsb >= 0) && (lsb <= 31));
1769  DCHECK((width >= 1) && (width <= (32 - lsb)));
1770  int msb = lsb + width - 1;
1771  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
1772}
1773
1774
1775// Bit field insert.
1776// Inserts #width adjacent bits from the low bits of the source register
1777// into position #lsb of the destination register.
1778//   bfi dst, src, #lsb, #width
1779void Assembler::bfi(Register dst,
1780                    Register src,
1781                    int lsb,
1782                    int width,
1783                    Condition cond) {
1784  // v7 and above.
1785  DCHECK(CpuFeatures::IsSupported(ARMv7));
1786  DCHECK(!dst.is(pc) && !src.is(pc));
1787  DCHECK((lsb >= 0) && (lsb <= 31));
1788  DCHECK((width >= 1) && (width <= (32 - lsb)));
1789  int msb = lsb + width - 1;
1790  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
1791       src.code());
1792}
1793
1794
1795void Assembler::pkhbt(Register dst,
1796                      Register src1,
1797                      const Operand& src2,
1798                      Condition cond ) {
1799  // Instruction details available in ARM DDI 0406C.b, A8.8.125.
1800  // cond(31-28) | 01101000(27-20) | Rn(19-16) |
1801  // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0)
1802  DCHECK(!dst.is(pc));
1803  DCHECK(!src1.is(pc));
1804  DCHECK(!src2.rm().is(pc));
1805  DCHECK(!src2.rm().is(no_reg));
1806  DCHECK(src2.rs().is(no_reg));
1807  DCHECK((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31));
1808  DCHECK(src2.shift_op() == LSL);
1809  emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
1810       src2.shift_imm_*B7 | B4 | src2.rm().code());
1811}
1812
1813
1814void Assembler::pkhtb(Register dst,
1815                      Register src1,
1816                      const Operand& src2,
1817                      Condition cond) {
1818  // Instruction details available in ARM DDI 0406C.b, A8.8.125.
1819  // cond(31-28) | 01101000(27-20) | Rn(19-16) |
1820  // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0)
1821  DCHECK(!dst.is(pc));
1822  DCHECK(!src1.is(pc));
1823  DCHECK(!src2.rm().is(pc));
1824  DCHECK(!src2.rm().is(no_reg));
1825  DCHECK(src2.rs().is(no_reg));
1826  DCHECK((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32));
1827  DCHECK(src2.shift_op() == ASR);
1828  int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_;
1829  emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
1830       asr*B7 | B6 | B4 | src2.rm().code());
1831}
1832
1833
1834void Assembler::sxtb(Register dst, Register src, int rotate, Condition cond) {
1835  // Instruction details available in ARM DDI 0406C.b, A8.8.233.
1836  // cond(31-28) | 01101010(27-20) | 1111(19-16) |
1837  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1838  DCHECK(!dst.is(pc));
1839  DCHECK(!src.is(pc));
1840  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1841  emit(cond | 0x6A * B20 | 0xF * B16 | dst.code() * B12 |
1842       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1843}
1844
1845
1846void Assembler::sxtab(Register dst, Register src1, Register src2, int rotate,
1847                      Condition cond) {
1848  // Instruction details available in ARM DDI 0406C.b, A8.8.233.
1849  // cond(31-28) | 01101010(27-20) | Rn(19-16) |
1850  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1851  DCHECK(!dst.is(pc));
1852  DCHECK(!src1.is(pc));
1853  DCHECK(!src2.is(pc));
1854  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1855  emit(cond | 0x6A * B20 | src1.code() * B16 | dst.code() * B12 |
1856       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1857}
1858
1859
1860void Assembler::sxth(Register dst, Register src, int rotate, Condition cond) {
1861  // Instruction details available in ARM DDI 0406C.b, A8.8.235.
1862  // cond(31-28) | 01101011(27-20) | 1111(19-16) |
1863  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1864  DCHECK(!dst.is(pc));
1865  DCHECK(!src.is(pc));
1866  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1867  emit(cond | 0x6B * B20 | 0xF * B16 | dst.code() * B12 |
1868       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1869}
1870
1871
1872void Assembler::sxtah(Register dst, Register src1, Register src2, int rotate,
1873                      Condition cond) {
1874  // Instruction details available in ARM DDI 0406C.b, A8.8.235.
1875  // cond(31-28) | 01101011(27-20) | Rn(19-16) |
1876  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1877  DCHECK(!dst.is(pc));
1878  DCHECK(!src1.is(pc));
1879  DCHECK(!src2.is(pc));
1880  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1881  emit(cond | 0x6B * B20 | src1.code() * B16 | dst.code() * B12 |
1882       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1883}
1884
1885
1886void Assembler::uxtb(Register dst, Register src, int rotate, Condition cond) {
1887  // Instruction details available in ARM DDI 0406C.b, A8.8.274.
1888  // cond(31-28) | 01101110(27-20) | 1111(19-16) |
1889  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1890  DCHECK(!dst.is(pc));
1891  DCHECK(!src.is(pc));
1892  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1893  emit(cond | 0x6E * B20 | 0xF * B16 | dst.code() * B12 |
1894       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1895}
1896
1897
1898void Assembler::uxtab(Register dst, Register src1, Register src2, int rotate,
1899                      Condition cond) {
1900  // Instruction details available in ARM DDI 0406C.b, A8.8.271.
1901  // cond(31-28) | 01101110(27-20) | Rn(19-16) |
1902  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1903  DCHECK(!dst.is(pc));
1904  DCHECK(!src1.is(pc));
1905  DCHECK(!src2.is(pc));
1906  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1907  emit(cond | 0x6E * B20 | src1.code() * B16 | dst.code() * B12 |
1908       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1909}
1910
1911
1912void Assembler::uxtb16(Register dst, Register src, int rotate, Condition cond) {
1913  // Instruction details available in ARM DDI 0406C.b, A8.8.275.
1914  // cond(31-28) | 01101100(27-20) | 1111(19-16) |
1915  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1916  DCHECK(!dst.is(pc));
1917  DCHECK(!src.is(pc));
1918  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1919  emit(cond | 0x6C * B20 | 0xF * B16 | dst.code() * B12 |
1920       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1921}
1922
1923
1924void Assembler::uxth(Register dst, Register src, int rotate, Condition cond) {
1925  // Instruction details available in ARM DDI 0406C.b, A8.8.276.
1926  // cond(31-28) | 01101111(27-20) | 1111(19-16) |
1927  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1928  DCHECK(!dst.is(pc));
1929  DCHECK(!src.is(pc));
1930  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1931  emit(cond | 0x6F * B20 | 0xF * B16 | dst.code() * B12 |
1932       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1933}
1934
1935
1936void Assembler::uxtah(Register dst, Register src1, Register src2, int rotate,
1937                      Condition cond) {
1938  // Instruction details available in ARM DDI 0406C.b, A8.8.273.
1939  // cond(31-28) | 01101111(27-20) | Rn(19-16) |
1940  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1941  DCHECK(!dst.is(pc));
1942  DCHECK(!src1.is(pc));
1943  DCHECK(!src2.is(pc));
1944  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1945  emit(cond | 0x6F * B20 | src1.code() * B16 | dst.code() * B12 |
1946       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1947}
1948
1949
1950void Assembler::rbit(Register dst, Register src, Condition cond) {
1951  // Instruction details available in ARM DDI 0406C.b, A8.8.144.
1952  // cond(31-28) | 011011111111(27-16) | Rd(15-12) | 11110011(11-4) | Rm(3-0)
1953  DCHECK(IsEnabled(ARMv7));
1954  DCHECK(!dst.is(pc));
1955  DCHECK(!src.is(pc));
1956  emit(cond | 0x6FF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
1957}
1958
1959
1960// Status register access instructions.
1961void Assembler::mrs(Register dst, SRegister s, Condition cond) {
1962  DCHECK(!dst.is(pc));
1963  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1964}
1965
1966
1967void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1968                    Condition cond) {
1969  DCHECK(fields >= B16 && fields < B20);  // at least one field set
1970  Instr instr;
1971  if (!src.rm_.is_valid()) {
1972    // Immediate.
1973    uint32_t rotate_imm;
1974    uint32_t immed_8;
1975    if (src.must_output_reloc_info(this) ||
1976        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
1977      // Immediate operand cannot be encoded, load it first to register ip.
1978      move_32_bit_immediate(ip, src);
1979      msr(fields, Operand(ip), cond);
1980      return;
1981    }
1982    instr = I | rotate_imm*B8 | immed_8;
1983  } else {
1984    DCHECK(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
1985    instr = src.rm_.code();
1986  }
1987  emit(cond | instr | B24 | B21 | fields | 15*B12);
1988}
1989
1990
1991// Load/Store instructions.
1992void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1993  if (dst.is(pc)) {
1994    positions_recorder()->WriteRecordedPositions();
1995  }
1996  addrmod2(cond | B26 | L, dst, src);
1997}
1998
1999
2000void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
2001  addrmod2(cond | B26, src, dst);
2002}
2003
2004
2005void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
2006  addrmod2(cond | B26 | B | L, dst, src);
2007}
2008
2009
2010void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
2011  addrmod2(cond | B26 | B, src, dst);
2012}
2013
2014
2015void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
2016  addrmod3(cond | L | B7 | H | B4, dst, src);
2017}
2018
2019
2020void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
2021  addrmod3(cond | B7 | H | B4, src, dst);
2022}
2023
2024
2025void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
2026  addrmod3(cond | L | B7 | S6 | B4, dst, src);
2027}
2028
2029
2030void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
2031  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
2032}
2033
2034
2035void Assembler::ldrd(Register dst1, Register dst2,
2036                     const MemOperand& src, Condition cond) {
2037  DCHECK(IsEnabled(ARMv7));
2038  DCHECK(src.rm().is(no_reg));
2039  DCHECK(!dst1.is(lr));  // r14.
2040  DCHECK_EQ(0, dst1.code() % 2);
2041  DCHECK_EQ(dst1.code() + 1, dst2.code());
2042  addrmod3(cond | B7 | B6 | B4, dst1, src);
2043}
2044
2045
2046void Assembler::strd(Register src1, Register src2,
2047                     const MemOperand& dst, Condition cond) {
2048  DCHECK(dst.rm().is(no_reg));
2049  DCHECK(!src1.is(lr));  // r14.
2050  DCHECK_EQ(0, src1.code() % 2);
2051  DCHECK_EQ(src1.code() + 1, src2.code());
2052  DCHECK(IsEnabled(ARMv7));
2053  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
2054}
2055
2056
2057// Preload instructions.
2058void Assembler::pld(const MemOperand& address) {
2059  // Instruction details available in ARM DDI 0406C.b, A8.8.128.
2060  // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) |
2061  // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) |
2062  DCHECK(address.rm().is(no_reg));
2063  DCHECK(address.am() == Offset);
2064  int U = B23;
2065  int offset = address.offset();
2066  if (offset < 0) {
2067    offset = -offset;
2068    U = 0;
2069  }
2070  DCHECK(offset < 4096);
2071  emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 |
2072       0xf*B12 | offset);
2073}
2074
2075
2076// Load/Store multiple instructions.
2077void Assembler::ldm(BlockAddrMode am,
2078                    Register base,
2079                    RegList dst,
2080                    Condition cond) {
2081  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
2082  DCHECK(base.is(sp) || (dst & sp.bit()) == 0);
2083
2084  addrmod4(cond | B27 | am | L, base, dst);
2085
2086  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
2087  if (cond == al && (dst & pc.bit()) != 0) {
2088    // There is a slight chance that the ldm instruction was actually a call,
2089    // in which case it would be wrong to return into the constant pool; we
2090    // recognize this case by checking if the emission of the pool was blocked
2091    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
2092    // the case, we emit a jump over the pool.
2093    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
2094  }
2095}
2096
2097
2098void Assembler::stm(BlockAddrMode am,
2099                    Register base,
2100                    RegList src,
2101                    Condition cond) {
2102  addrmod4(cond | B27 | am, base, src);
2103}
2104
2105
2106// Exception-generating instructions and debugging support.
2107// Stops with a non-negative code less than kNumOfWatchedStops support
2108// enabling/disabling and a counter feature. See simulator-arm.h .
2109void Assembler::stop(const char* msg, Condition cond, int32_t code) {
2110#ifndef __arm__
2111  DCHECK(code >= kDefaultStopCode);
2112  {
2113    // The Simulator will handle the stop instruction and get the message
2114    // address. It expects to find the address just after the svc instruction.
2115    BlockConstPoolScope block_const_pool(this);
2116    if (code >= 0) {
2117      svc(kStopCode + code, cond);
2118    } else {
2119      svc(kStopCode + kMaxStopCode, cond);
2120    }
2121    emit(reinterpret_cast<Instr>(msg));
2122  }
2123#else  // def __arm__
2124  if (cond != al) {
2125    Label skip;
2126    b(&skip, NegateCondition(cond));
2127    bkpt(0);
2128    bind(&skip);
2129  } else {
2130    bkpt(0);
2131  }
2132#endif  // def __arm__
2133}
2134
2135
2136void Assembler::bkpt(uint32_t imm16) {  // v5 and above
2137  DCHECK(is_uint16(imm16));
2138  emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
2139}
2140
2141
2142void Assembler::svc(uint32_t imm24, Condition cond) {
2143  DCHECK(is_uint24(imm24));
2144  emit(cond | 15*B24 | imm24);
2145}
2146
2147
2148void Assembler::dmb(BarrierOption option) {
2149  emit(kSpecialCondition | 0x57ff*B12 | 5*B4 | option);
2150}
2151
2152
2153void Assembler::dsb(BarrierOption option) {
2154  emit(kSpecialCondition | 0x57ff*B12 | 4*B4 | option);
2155}
2156
2157
2158void Assembler::isb(BarrierOption option) {
2159  emit(kSpecialCondition | 0x57ff*B12 | 6*B4 | option);
2160}
2161
2162
2163// Coprocessor instructions.
2164void Assembler::cdp(Coprocessor coproc,
2165                    int opcode_1,
2166                    CRegister crd,
2167                    CRegister crn,
2168                    CRegister crm,
2169                    int opcode_2,
2170                    Condition cond) {
2171  DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2));
2172  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
2173       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
2174}
2175
2176
2177void Assembler::cdp2(Coprocessor coproc,
2178                     int opcode_1,
2179                     CRegister crd,
2180                     CRegister crn,
2181                     CRegister crm,
2182                     int opcode_2) {  // v5 and above
2183  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
2184}
2185
2186
2187void Assembler::mcr(Coprocessor coproc,
2188                    int opcode_1,
2189                    Register rd,
2190                    CRegister crn,
2191                    CRegister crm,
2192                    int opcode_2,
2193                    Condition cond) {
2194  DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2195  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
2196       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2197}
2198
2199
2200void Assembler::mcr2(Coprocessor coproc,
2201                     int opcode_1,
2202                     Register rd,
2203                     CRegister crn,
2204                     CRegister crm,
2205                     int opcode_2) {  // v5 and above
2206  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2207}
2208
2209
2210void Assembler::mrc(Coprocessor coproc,
2211                    int opcode_1,
2212                    Register rd,
2213                    CRegister crn,
2214                    CRegister crm,
2215                    int opcode_2,
2216                    Condition cond) {
2217  DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2218  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
2219       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2220}
2221
2222
2223void Assembler::mrc2(Coprocessor coproc,
2224                     int opcode_1,
2225                     Register rd,
2226                     CRegister crn,
2227                     CRegister crm,
2228                     int opcode_2) {  // v5 and above
2229  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2230}
2231
2232
2233void Assembler::ldc(Coprocessor coproc,
2234                    CRegister crd,
2235                    const MemOperand& src,
2236                    LFlag l,
2237                    Condition cond) {
2238  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
2239}
2240
2241
2242void Assembler::ldc(Coprocessor coproc,
2243                    CRegister crd,
2244                    Register rn,
2245                    int option,
2246                    LFlag l,
2247                    Condition cond) {
2248  // Unindexed addressing.
2249  DCHECK(is_uint8(option));
2250  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
2251       coproc*B8 | (option & 255));
2252}
2253
2254
2255void Assembler::ldc2(Coprocessor coproc,
2256                     CRegister crd,
2257                     const MemOperand& src,
2258                     LFlag l) {  // v5 and above
2259  ldc(coproc, crd, src, l, kSpecialCondition);
2260}
2261
2262
2263void Assembler::ldc2(Coprocessor coproc,
2264                     CRegister crd,
2265                     Register rn,
2266                     int option,
2267                     LFlag l) {  // v5 and above
2268  ldc(coproc, crd, rn, option, l, kSpecialCondition);
2269}
2270
2271
2272// Support for VFP.
2273
2274void Assembler::vldr(const DwVfpRegister dst,
2275                     const Register base,
2276                     int offset,
2277                     const Condition cond) {
2278  // Ddst = MEM(Rbase + offset).
2279  // Instruction details available in ARM DDI 0406C.b, A8-924.
2280  // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
2281  // Vd(15-12) | 1011(11-8) | offset
2282  int u = 1;
2283  if (offset < 0) {
2284    CHECK(offset != kMinInt);
2285    offset = -offset;
2286    u = 0;
2287  }
2288  int vd, d;
2289  dst.split_code(&vd, &d);
2290
2291  DCHECK(offset >= 0);
2292  if ((offset % 4) == 0 && (offset / 4) < 256) {
2293    emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 |
2294         0xB*B8 | ((offset / 4) & 255));
2295  } else {
2296    // Larger offsets must be handled by computing the correct address
2297    // in the ip register.
2298    DCHECK(!base.is(ip));
2299    if (u == 1) {
2300      add(ip, base, Operand(offset));
2301    } else {
2302      sub(ip, base, Operand(offset));
2303    }
2304    emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8);
2305  }
2306}
2307
2308
2309void Assembler::vldr(const DwVfpRegister dst,
2310                     const MemOperand& operand,
2311                     const Condition cond) {
2312  DCHECK(operand.am_ == Offset);
2313  if (operand.rm().is_valid()) {
2314    add(ip, operand.rn(),
2315        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2316    vldr(dst, ip, 0, cond);
2317  } else {
2318    vldr(dst, operand.rn(), operand.offset(), cond);
2319  }
2320}
2321
2322
2323void Assembler::vldr(const SwVfpRegister dst,
2324                     const Register base,
2325                     int offset,
2326                     const Condition cond) {
2327  // Sdst = MEM(Rbase + offset).
2328  // Instruction details available in ARM DDI 0406A, A8-628.
2329  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
2330  // Vdst(15-12) | 1010(11-8) | offset
2331  int u = 1;
2332  if (offset < 0) {
2333    offset = -offset;
2334    u = 0;
2335  }
2336  int sd, d;
2337  dst.split_code(&sd, &d);
2338  DCHECK(offset >= 0);
2339
2340  if ((offset % 4) == 0 && (offset / 4) < 256) {
2341  emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
2342       0xA*B8 | ((offset / 4) & 255));
2343  } else {
2344    // Larger offsets must be handled by computing the correct address
2345    // in the ip register.
2346    DCHECK(!base.is(ip));
2347    if (u == 1) {
2348      add(ip, base, Operand(offset));
2349    } else {
2350      sub(ip, base, Operand(offset));
2351    }
2352    emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2353  }
2354}
2355
2356
2357void Assembler::vldr(const SwVfpRegister dst,
2358                     const MemOperand& operand,
2359                     const Condition cond) {
2360  DCHECK(operand.am_ == Offset);
2361  if (operand.rm().is_valid()) {
2362    add(ip, operand.rn(),
2363        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2364    vldr(dst, ip, 0, cond);
2365  } else {
2366    vldr(dst, operand.rn(), operand.offset(), cond);
2367  }
2368}
2369
2370
2371void Assembler::vstr(const DwVfpRegister src,
2372                     const Register base,
2373                     int offset,
2374                     const Condition cond) {
2375  // MEM(Rbase + offset) = Dsrc.
2376  // Instruction details available in ARM DDI 0406C.b, A8-1082.
2377  // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
2378  // Vd(15-12) | 1011(11-8) | (offset/4)
2379  int u = 1;
2380  if (offset < 0) {
2381    CHECK(offset != kMinInt);
2382    offset = -offset;
2383    u = 0;
2384  }
2385  DCHECK(offset >= 0);
2386  int vd, d;
2387  src.split_code(&vd, &d);
2388
2389  if ((offset % 4) == 0 && (offset / 4) < 256) {
2390    emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 |
2391         ((offset / 4) & 255));
2392  } else {
2393    // Larger offsets must be handled by computing the correct address
2394    // in the ip register.
2395    DCHECK(!base.is(ip));
2396    if (u == 1) {
2397      add(ip, base, Operand(offset));
2398    } else {
2399      sub(ip, base, Operand(offset));
2400    }
2401    emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8);
2402  }
2403}
2404
2405
2406void Assembler::vstr(const DwVfpRegister src,
2407                     const MemOperand& operand,
2408                     const Condition cond) {
2409  DCHECK(operand.am_ == Offset);
2410  if (operand.rm().is_valid()) {
2411    add(ip, operand.rn(),
2412        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2413    vstr(src, ip, 0, cond);
2414  } else {
2415    vstr(src, operand.rn(), operand.offset(), cond);
2416  }
2417}
2418
2419
2420void Assembler::vstr(const SwVfpRegister src,
2421                     const Register base,
2422                     int offset,
2423                     const Condition cond) {
2424  // MEM(Rbase + offset) = SSrc.
2425  // Instruction details available in ARM DDI 0406A, A8-786.
2426  // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
2427  // Vdst(15-12) | 1010(11-8) | (offset/4)
2428  int u = 1;
2429  if (offset < 0) {
2430    CHECK(offset != kMinInt);
2431    offset = -offset;
2432    u = 0;
2433  }
2434  int sd, d;
2435  src.split_code(&sd, &d);
2436  DCHECK(offset >= 0);
2437  if ((offset % 4) == 0 && (offset / 4) < 256) {
2438    emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
2439         0xA*B8 | ((offset / 4) & 255));
2440  } else {
2441    // Larger offsets must be handled by computing the correct address
2442    // in the ip register.
2443    DCHECK(!base.is(ip));
2444    if (u == 1) {
2445      add(ip, base, Operand(offset));
2446    } else {
2447      sub(ip, base, Operand(offset));
2448    }
2449    emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2450  }
2451}
2452
2453
2454void Assembler::vstr(const SwVfpRegister src,
2455                     const MemOperand& operand,
2456                     const Condition cond) {
2457  DCHECK(operand.am_ == Offset);
2458  if (operand.rm().is_valid()) {
2459    add(ip, operand.rn(),
2460        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2461    vstr(src, ip, 0, cond);
2462  } else {
2463    vstr(src, operand.rn(), operand.offset(), cond);
2464  }
2465}
2466
2467
2468void  Assembler::vldm(BlockAddrMode am,
2469                      Register base,
2470                      DwVfpRegister first,
2471                      DwVfpRegister last,
2472                      Condition cond) {
2473  // Instruction details available in ARM DDI 0406C.b, A8-922.
2474  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2475  // first(15-12) | 1011(11-8) | (count * 2)
2476  DCHECK_LE(first.code(), last.code());
2477  DCHECK(am == ia || am == ia_w || am == db_w);
2478  DCHECK(!base.is(pc));
2479
2480  int sd, d;
2481  first.split_code(&sd, &d);
2482  int count = last.code() - first.code() + 1;
2483  DCHECK(count <= 16);
2484  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
2485       0xB*B8 | count*2);
2486}
2487
2488
2489void  Assembler::vstm(BlockAddrMode am,
2490                      Register base,
2491                      DwVfpRegister first,
2492                      DwVfpRegister last,
2493                      Condition cond) {
2494  // Instruction details available in ARM DDI 0406C.b, A8-1080.
2495  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
2496  // first(15-12) | 1011(11-8) | (count * 2)
2497  DCHECK_LE(first.code(), last.code());
2498  DCHECK(am == ia || am == ia_w || am == db_w);
2499  DCHECK(!base.is(pc));
2500
2501  int sd, d;
2502  first.split_code(&sd, &d);
2503  int count = last.code() - first.code() + 1;
2504  DCHECK(count <= 16);
2505  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
2506       0xB*B8 | count*2);
2507}
2508
2509void  Assembler::vldm(BlockAddrMode am,
2510                      Register base,
2511                      SwVfpRegister first,
2512                      SwVfpRegister last,
2513                      Condition cond) {
2514  // Instruction details available in ARM DDI 0406A, A8-626.
2515  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2516  // first(15-12) | 1010(11-8) | (count/2)
2517  DCHECK_LE(first.code(), last.code());
2518  DCHECK(am == ia || am == ia_w || am == db_w);
2519  DCHECK(!base.is(pc));
2520
2521  int sd, d;
2522  first.split_code(&sd, &d);
2523  int count = last.code() - first.code() + 1;
2524  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
2525       0xA*B8 | count);
2526}
2527
2528
2529void  Assembler::vstm(BlockAddrMode am,
2530                      Register base,
2531                      SwVfpRegister first,
2532                      SwVfpRegister last,
2533                      Condition cond) {
2534  // Instruction details available in ARM DDI 0406A, A8-784.
2535  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
2536  // first(15-12) | 1011(11-8) | (count/2)
2537  DCHECK_LE(first.code(), last.code());
2538  DCHECK(am == ia || am == ia_w || am == db_w);
2539  DCHECK(!base.is(pc));
2540
2541  int sd, d;
2542  first.split_code(&sd, &d);
2543  int count = last.code() - first.code() + 1;
2544  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
2545       0xA*B8 | count);
2546}
2547
2548
2549void Assembler::vmov(const SwVfpRegister dst, float imm) {
2550  mov(ip, Operand(bit_cast<int32_t>(imm)));
2551  vmov(dst, ip);
2552}
2553
2554
2555static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
2556  uint64_t i;
2557  memcpy(&i, &d, 8);
2558
2559  *lo = i & 0xffffffff;
2560  *hi = i >> 32;
2561}
2562
2563
2564// Only works for little endian floating point formats.
2565// We don't support VFP on the mixed endian floating point platform.
2566static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
2567  DCHECK(CpuFeatures::IsSupported(VFP3));
2568
2569  // VMOV can accept an immediate of the form:
2570  //
2571  //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
2572  //
2573  // The immediate is encoded using an 8-bit quantity, comprised of two
2574  // 4-bit fields. For an 8-bit immediate of the form:
2575  //
2576  //  [abcdefgh]
2577  //
2578  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
2579  // created of the form:
2580  //
2581  //  [aBbbbbbb,bbcdefgh,00000000,00000000,
2582  //      00000000,00000000,00000000,00000000]
2583  //
2584  // where B = ~b.
2585  //
2586
2587  uint32_t lo, hi;
2588  DoubleAsTwoUInt32(d, &lo, &hi);
2589
2590  // The most obvious constraint is the long block of zeroes.
2591  if ((lo != 0) || ((hi & 0xffff) != 0)) {
2592    return false;
2593  }
2594
2595  // Bits 62:55 must be all clear or all set.
2596  if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
2597    return false;
2598  }
2599
2600  // Bit 63 must be NOT bit 62.
2601  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
2602    return false;
2603  }
2604
2605  // Create the encoded immediate in the form:
2606  //  [00000000,0000abcd,00000000,0000efgh]
2607  *encoding  = (hi >> 16) & 0xf;      // Low nybble.
2608  *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
2609  *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
2610
2611  return true;
2612}
2613
2614
2615void Assembler::vmov(const DwVfpRegister dst,
2616                     double imm,
2617                     const Register scratch) {
2618  uint32_t enc;
2619  // If the embedded constant pool is disabled, we can use the normal, inline
2620  // constant pool. If the embedded constant pool is enabled (via
2621  // FLAG_enable_embedded_constant_pool), we can only use it where the pool
2622  // pointer (pp) is valid.
2623  bool can_use_pool =
2624      !FLAG_enable_embedded_constant_pool || is_constant_pool_available();
2625  if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) {
2626    // The double can be encoded in the instruction.
2627    //
2628    // Dd = immediate
2629    // Instruction details available in ARM DDI 0406C.b, A8-936.
2630    // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
2631    // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0)
2632    int vd, d;
2633    dst.split_code(&vd, &d);
2634    emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
2635  } else if (FLAG_enable_vldr_imm && can_use_pool) {
2636    // TODO(jfb) Temporarily turned off until we have constant blinding or
2637    //           some equivalent mitigation: an attacker can otherwise control
2638    //           generated data which also happens to be executable, a Very Bad
2639    //           Thing indeed.
2640    //           Blinding gets tricky because we don't have xor, we probably
2641    //           need to add/subtract without losing precision, which requires a
2642    //           cookie value that Lithium is probably better positioned to
2643    //           choose.
2644    //           We could also add a few peepholes here like detecting 0.0 and
2645    //           -0.0 and doing a vmov from the sequestered d14, forcing denorms
2646    //           to zero (we set flush-to-zero), and normalizing NaN values.
2647    //           We could also detect redundant values.
2648    //           The code could also randomize the order of values, though
2649    //           that's tricky because vldr has a limited reach. Furthermore
2650    //           it breaks load locality.
2651    ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm);
2652    if (access == ConstantPoolEntry::OVERFLOWED) {
2653      DCHECK(FLAG_enable_embedded_constant_pool);
2654      // Emit instructions to load constant pool offset.
2655      movw(ip, 0);
2656      movt(ip, 0);
2657      // Load from constant pool at offset.
2658      vldr(dst, MemOperand(pp, ip));
2659    } else {
2660      DCHECK(access == ConstantPoolEntry::REGULAR);
2661      vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0));
2662    }
2663  } else {
2664    // Synthesise the double from ARM immediates.
2665    uint32_t lo, hi;
2666    DoubleAsTwoUInt32(imm, &lo, &hi);
2667
2668    if (lo == hi) {
2669      // Move the low and high parts of the double to a D register in one
2670      // instruction.
2671      mov(ip, Operand(lo));
2672      vmov(dst, ip, ip);
2673    } else if (scratch.is(no_reg)) {
2674      mov(ip, Operand(lo));
2675      vmov(dst, VmovIndexLo, ip);
2676      if (((lo & 0xffff) == (hi & 0xffff)) &&
2677          CpuFeatures::IsSupported(ARMv7)) {
2678        movt(ip, hi >> 16);
2679      } else {
2680        mov(ip, Operand(hi));
2681      }
2682      vmov(dst, VmovIndexHi, ip);
2683    } else {
2684      // Move the low and high parts of the double to a D register in one
2685      // instruction.
2686      mov(ip, Operand(lo));
2687      mov(scratch, Operand(hi));
2688      vmov(dst, ip, scratch);
2689    }
2690  }
2691}
2692
2693
2694void Assembler::vmov(const SwVfpRegister dst,
2695                     const SwVfpRegister src,
2696                     const Condition cond) {
2697  // Sd = Sm
2698  // Instruction details available in ARM DDI 0406B, A8-642.
2699  int sd, d, sm, m;
2700  dst.split_code(&sd, &d);
2701  src.split_code(&sm, &m);
2702  emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
2703}
2704
2705
2706void Assembler::vmov(const DwVfpRegister dst,
2707                     const DwVfpRegister src,
2708                     const Condition cond) {
2709  // Dd = Dm
2710  // Instruction details available in ARM DDI 0406C.b, A8-938.
2711  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
2712  // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2713  int vd, d;
2714  dst.split_code(&vd, &d);
2715  int vm, m;
2716  src.split_code(&vm, &m);
2717  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 |
2718       vm);
2719}
2720
2721
2722void Assembler::vmov(const DwVfpRegister dst,
2723                     const VmovIndex index,
2724                     const Register src,
2725                     const Condition cond) {
2726  // Dd[index] = Rt
2727  // Instruction details available in ARM DDI 0406C.b, A8-940.
2728  // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
2729  // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2730  DCHECK(index.index == 0 || index.index == 1);
2731  int vd, d;
2732  dst.split_code(&vd, &d);
2733  emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
2734       d*B7 | B4);
2735}
2736
2737
2738void Assembler::vmov(const Register dst,
2739                     const VmovIndex index,
2740                     const DwVfpRegister src,
2741                     const Condition cond) {
2742  // Dd[index] = Rt
2743  // Instruction details available in ARM DDI 0406C.b, A8.8.342.
2744  // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) |
2745  // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2746  DCHECK(index.index == 0 || index.index == 1);
2747  int vn, n;
2748  src.split_code(&vn, &n);
2749  emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 |
2750       0xB*B8 | n*B7 | B4);
2751}
2752
2753
2754void Assembler::vmov(const DwVfpRegister dst,
2755                     const Register src1,
2756                     const Register src2,
2757                     const Condition cond) {
2758  // Dm = <Rt,Rt2>.
2759  // Instruction details available in ARM DDI 0406C.b, A8-948.
2760  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2761  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2762  DCHECK(!src1.is(pc) && !src2.is(pc));
2763  int vm, m;
2764  dst.split_code(&vm, &m);
2765  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2766       src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2767}
2768
2769
2770void Assembler::vmov(const Register dst1,
2771                     const Register dst2,
2772                     const DwVfpRegister src,
2773                     const Condition cond) {
2774  // <Rt,Rt2> = Dm.
2775  // Instruction details available in ARM DDI 0406C.b, A8-948.
2776  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2777  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2778  DCHECK(!dst1.is(pc) && !dst2.is(pc));
2779  int vm, m;
2780  src.split_code(&vm, &m);
2781  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2782       dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2783}
2784
2785
2786void Assembler::vmov(const SwVfpRegister dst,
2787                     const Register src,
2788                     const Condition cond) {
2789  // Sn = Rt.
2790  // Instruction details available in ARM DDI 0406A, A8-642.
2791  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2792  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2793  DCHECK(!src.is(pc));
2794  int sn, n;
2795  dst.split_code(&sn, &n);
2796  emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2797}
2798
2799
2800void Assembler::vmov(const Register dst,
2801                     const SwVfpRegister src,
2802                     const Condition cond) {
2803  // Rt = Sn.
2804  // Instruction details available in ARM DDI 0406A, A8-642.
2805  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2806  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2807  DCHECK(!dst.is(pc));
2808  int sn, n;
2809  src.split_code(&sn, &n);
2810  emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2811}
2812
2813
2814// Type of data to read from or write to VFP register.
2815// Used as specifier in generic vcvt instruction.
2816enum VFPType { S32, U32, F32, F64 };
2817
2818
2819static bool IsSignedVFPType(VFPType type) {
2820  switch (type) {
2821    case S32:
2822      return true;
2823    case U32:
2824      return false;
2825    default:
2826      UNREACHABLE();
2827      return false;
2828  }
2829}
2830
2831
2832static bool IsIntegerVFPType(VFPType type) {
2833  switch (type) {
2834    case S32:
2835    case U32:
2836      return true;
2837    case F32:
2838    case F64:
2839      return false;
2840    default:
2841      UNREACHABLE();
2842      return false;
2843  }
2844}
2845
2846
2847static bool IsDoubleVFPType(VFPType type) {
2848  switch (type) {
2849    case F32:
2850      return false;
2851    case F64:
2852      return true;
2853    default:
2854      UNREACHABLE();
2855      return false;
2856  }
2857}
2858
2859
2860// Split five bit reg_code based on size of reg_type.
2861//  32-bit register codes are Vm:M
2862//  64-bit register codes are M:Vm
2863// where Vm is four bits, and M is a single bit.
2864static void SplitRegCode(VFPType reg_type,
2865                         int reg_code,
2866                         int* vm,
2867                         int* m) {
2868  DCHECK((reg_code >= 0) && (reg_code <= 31));
2869  if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
2870    // 32 bit type.
2871    *m  = reg_code & 0x1;
2872    *vm = reg_code >> 1;
2873  } else {
2874    // 64 bit type.
2875    *m  = (reg_code & 0x10) >> 4;
2876    *vm = reg_code & 0x0F;
2877  }
2878}
2879
2880
2881// Encode vcvt.src_type.dst_type instruction.
2882static Instr EncodeVCVT(const VFPType dst_type,
2883                        const int dst_code,
2884                        const VFPType src_type,
2885                        const int src_code,
2886                        VFPConversionMode mode,
2887                        const Condition cond) {
2888  DCHECK(src_type != dst_type);
2889  int D, Vd, M, Vm;
2890  SplitRegCode(src_type, src_code, &Vm, &M);
2891  SplitRegCode(dst_type, dst_code, &Vd, &D);
2892
2893  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
2894    // Conversion between IEEE floating point and 32-bit integer.
2895    // Instruction details available in ARM DDI 0406B, A8.6.295.
2896    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
2897    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2898    DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
2899
2900    int sz, opc2, op;
2901
2902    if (IsIntegerVFPType(dst_type)) {
2903      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
2904      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2905      op = mode;
2906    } else {
2907      DCHECK(IsIntegerVFPType(src_type));
2908      opc2 = 0x0;
2909      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
2910      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
2911    }
2912
2913    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
2914            Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
2915  } else {
2916    // Conversion between IEEE double and single precision.
2917    // Instruction details available in ARM DDI 0406B, A8.6.298.
2918    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
2919    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2920    int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2921    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
2922            Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
2923  }
2924}
2925
2926
2927void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
2928                             const SwVfpRegister src,
2929                             VFPConversionMode mode,
2930                             const Condition cond) {
2931  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
2932}
2933
2934
2935void Assembler::vcvt_f32_s32(const SwVfpRegister dst,
2936                             const SwVfpRegister src,
2937                             VFPConversionMode mode,
2938                             const Condition cond) {
2939  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
2940}
2941
2942
2943void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
2944                             const SwVfpRegister src,
2945                             VFPConversionMode mode,
2946                             const Condition cond) {
2947  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
2948}
2949
2950
2951void Assembler::vcvt_f32_u32(const SwVfpRegister dst, const SwVfpRegister src,
2952                             VFPConversionMode mode, const Condition cond) {
2953  emit(EncodeVCVT(F32, dst.code(), U32, src.code(), mode, cond));
2954}
2955
2956
2957void Assembler::vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
2958                             VFPConversionMode mode, const Condition cond) {
2959  emit(EncodeVCVT(S32, dst.code(), F32, src.code(), mode, cond));
2960}
2961
2962
2963void Assembler::vcvt_u32_f32(const SwVfpRegister dst, const SwVfpRegister src,
2964                             VFPConversionMode mode, const Condition cond) {
2965  emit(EncodeVCVT(U32, dst.code(), F32, src.code(), mode, cond));
2966}
2967
2968
2969void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
2970                             const DwVfpRegister src,
2971                             VFPConversionMode mode,
2972                             const Condition cond) {
2973  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
2974}
2975
2976
2977void Assembler::vcvt_u32_f64(const SwVfpRegister dst,
2978                             const DwVfpRegister src,
2979                             VFPConversionMode mode,
2980                             const Condition cond) {
2981  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
2982}
2983
2984
2985void Assembler::vcvt_f64_f32(const DwVfpRegister dst,
2986                             const SwVfpRegister src,
2987                             VFPConversionMode mode,
2988                             const Condition cond) {
2989  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
2990}
2991
2992
2993void Assembler::vcvt_f32_f64(const SwVfpRegister dst,
2994                             const DwVfpRegister src,
2995                             VFPConversionMode mode,
2996                             const Condition cond) {
2997  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2998}
2999
3000
3001void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
3002                             int fraction_bits,
3003                             const Condition cond) {
3004  // Instruction details available in ARM DDI 0406C.b, A8-874.
3005  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) |
3006  // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0)
3007  DCHECK(fraction_bits > 0 && fraction_bits <= 32);
3008  DCHECK(CpuFeatures::IsSupported(VFP3));
3009  int vd, d;
3010  dst.split_code(&vd, &d);
3011  int imm5 = 32 - fraction_bits;
3012  int i = imm5 & 1;
3013  int imm4 = (imm5 >> 1) & 0xf;
3014  emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 |
3015       vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4);
3016}
3017
3018
3019void Assembler::vneg(const DwVfpRegister dst,
3020                     const DwVfpRegister src,
3021                     const Condition cond) {
3022  // Instruction details available in ARM DDI 0406C.b, A8-968.
3023  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
3024  // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3025  int vd, d;
3026  dst.split_code(&vd, &d);
3027  int vm, m;
3028  src.split_code(&vm, &m);
3029
3030  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 |
3031       m*B5 | vm);
3032}
3033
3034
3035void Assembler::vneg(const SwVfpRegister dst, const SwVfpRegister src,
3036                     const Condition cond) {
3037  // Instruction details available in ARM DDI 0406C.b, A8-968.
3038  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
3039  // 101(11-9) | sz=0(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3040  int vd, d;
3041  dst.split_code(&vd, &d);
3042  int vm, m;
3043  src.split_code(&vm, &m);
3044
3045  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
3046       B6 | m * B5 | vm);
3047}
3048
3049
3050void Assembler::vabs(const DwVfpRegister dst,
3051                     const DwVfpRegister src,
3052                     const Condition cond) {
3053  // Instruction details available in ARM DDI 0406C.b, A8-524.
3054  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
3055  // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3056  int vd, d;
3057  dst.split_code(&vd, &d);
3058  int vm, m;
3059  src.split_code(&vm, &m);
3060  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 |
3061       m*B5 | vm);
3062}
3063
3064
3065void Assembler::vabs(const SwVfpRegister dst, const SwVfpRegister src,
3066                     const Condition cond) {
3067  // Instruction details available in ARM DDI 0406C.b, A8-524.
3068  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
3069  // 101(11-9) | sz=0(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3070  int vd, d;
3071  dst.split_code(&vd, &d);
3072  int vm, m;
3073  src.split_code(&vm, &m);
3074  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B7 | B6 |
3075       m * B5 | vm);
3076}
3077
3078
3079void Assembler::vadd(const DwVfpRegister dst,
3080                     const DwVfpRegister src1,
3081                     const DwVfpRegister src2,
3082                     const Condition cond) {
3083  // Dd = vadd(Dn, Dm) double precision floating point addition.
3084  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3085  // Instruction details available in ARM DDI 0406C.b, A8-830.
3086  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3087  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3088  int vd, d;
3089  dst.split_code(&vd, &d);
3090  int vn, n;
3091  src1.split_code(&vn, &n);
3092  int vm, m;
3093  src2.split_code(&vm, &m);
3094  emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3095       n*B7 | m*B5 | vm);
3096}
3097
3098
3099void Assembler::vadd(const SwVfpRegister dst, const SwVfpRegister src1,
3100                     const SwVfpRegister src2, const Condition cond) {
3101  // Sd = vadd(Sn, Sm) single precision floating point addition.
3102  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3103  // Instruction details available in ARM DDI 0406C.b, A8-830.
3104  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3105  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3106  int vd, d;
3107  dst.split_code(&vd, &d);
3108  int vn, n;
3109  src1.split_code(&vn, &n);
3110  int vm, m;
3111  src2.split_code(&vm, &m);
3112  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
3113       0x5 * B9 | n * B7 | m * B5 | vm);
3114}
3115
3116
3117void Assembler::vsub(const DwVfpRegister dst,
3118                     const DwVfpRegister src1,
3119                     const DwVfpRegister src2,
3120                     const Condition cond) {
3121  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
3122  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3123  // Instruction details available in ARM DDI 0406C.b, A8-1086.
3124  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3125  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3126  int vd, d;
3127  dst.split_code(&vd, &d);
3128  int vn, n;
3129  src1.split_code(&vn, &n);
3130  int vm, m;
3131  src2.split_code(&vm, &m);
3132  emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3133       n*B7 | B6 | m*B5 | vm);
3134}
3135
3136
3137void Assembler::vsub(const SwVfpRegister dst, const SwVfpRegister src1,
3138                     const SwVfpRegister src2, const Condition cond) {
3139  // Sd = vsub(Sn, Sm) single precision floating point subtraction.
3140  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3141  // Instruction details available in ARM DDI 0406C.b, A8-1086.
3142  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3143  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3144  int vd, d;
3145  dst.split_code(&vd, &d);
3146  int vn, n;
3147  src1.split_code(&vn, &n);
3148  int vm, m;
3149  src2.split_code(&vm, &m);
3150  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
3151       0x5 * B9 | n * B7 | B6 | m * B5 | vm);
3152}
3153
3154
3155void Assembler::vmul(const DwVfpRegister dst,
3156                     const DwVfpRegister src1,
3157                     const DwVfpRegister src2,
3158                     const Condition cond) {
3159  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
3160  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3161  // Instruction details available in ARM DDI 0406C.b, A8-960.
3162  // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
3163  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3164  int vd, d;
3165  dst.split_code(&vd, &d);
3166  int vn, n;
3167  src1.split_code(&vn, &n);
3168  int vm, m;
3169  src2.split_code(&vm, &m);
3170  emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3171       n*B7 | m*B5 | vm);
3172}
3173
3174
3175void Assembler::vmul(const SwVfpRegister dst, const SwVfpRegister src1,
3176                     const SwVfpRegister src2, const Condition cond) {
3177  // Sd = vmul(Sn, Sm) single precision floating point multiplication.
3178  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3179  // Instruction details available in ARM DDI 0406C.b, A8-960.
3180  // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
3181  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3182  int vd, d;
3183  dst.split_code(&vd, &d);
3184  int vn, n;
3185  src1.split_code(&vn, &n);
3186  int vm, m;
3187  src2.split_code(&vm, &m);
3188  emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 |
3189       0x5 * B9 | n * B7 | m * B5 | vm);
3190}
3191
3192
3193void Assembler::vmla(const DwVfpRegister dst,
3194                     const DwVfpRegister src1,
3195                     const DwVfpRegister src2,
3196                     const Condition cond) {
3197  // Instruction details available in ARM DDI 0406C.b, A8-932.
3198  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3199  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
3200  int vd, d;
3201  dst.split_code(&vd, &d);
3202  int vn, n;
3203  src1.split_code(&vn, &n);
3204  int vm, m;
3205  src2.split_code(&vm, &m);
3206  emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
3207       vm);
3208}
3209
3210
3211void Assembler::vmla(const SwVfpRegister dst, const SwVfpRegister src1,
3212                     const SwVfpRegister src2, const Condition cond) {
3213  // Instruction details available in ARM DDI 0406C.b, A8-932.
3214  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3215  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
3216  int vd, d;
3217  dst.split_code(&vd, &d);
3218  int vn, n;
3219  src1.split_code(&vn, &n);
3220  int vm, m;
3221  src2.split_code(&vm, &m);
3222  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3223       m * B5 | vm);
3224}
3225
3226
3227void Assembler::vmls(const DwVfpRegister dst,
3228                     const DwVfpRegister src1,
3229                     const DwVfpRegister src2,
3230                     const Condition cond) {
3231  // Instruction details available in ARM DDI 0406C.b, A8-932.
3232  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3233  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
3234  int vd, d;
3235  dst.split_code(&vd, &d);
3236  int vn, n;
3237  src1.split_code(&vn, &n);
3238  int vm, m;
3239  src2.split_code(&vm, &m);
3240  emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | B6 |
3241       m*B5 | vm);
3242}
3243
3244
3245void Assembler::vmls(const SwVfpRegister dst, const SwVfpRegister src1,
3246                     const SwVfpRegister src2, const Condition cond) {
3247  // Instruction details available in ARM DDI 0406C.b, A8-932.
3248  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3249  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
3250  int vd, d;
3251  dst.split_code(&vd, &d);
3252  int vn, n;
3253  src1.split_code(&vn, &n);
3254  int vm, m;
3255  src2.split_code(&vm, &m);
3256  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3257       B6 | m * B5 | vm);
3258}
3259
3260
3261void Assembler::vdiv(const DwVfpRegister dst,
3262                     const DwVfpRegister src1,
3263                     const DwVfpRegister src2,
3264                     const Condition cond) {
3265  // Dd = vdiv(Dn, Dm) double precision floating point division.
3266  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3267  // Instruction details available in ARM DDI 0406C.b, A8-882.
3268  // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
3269  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3270  int vd, d;
3271  dst.split_code(&vd, &d);
3272  int vn, n;
3273  src1.split_code(&vn, &n);
3274  int vm, m;
3275  src2.split_code(&vm, &m);
3276  emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
3277       vm);
3278}
3279
3280
3281void Assembler::vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
3282                     const SwVfpRegister src2, const Condition cond) {
3283  // Sd = vdiv(Sn, Sm) single precision floating point division.
3284  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3285  // Instruction details available in ARM DDI 0406C.b, A8-882.
3286  // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
3287  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3288  int vd, d;
3289  dst.split_code(&vd, &d);
3290  int vn, n;
3291  src1.split_code(&vn, &n);
3292  int vm, m;
3293  src2.split_code(&vm, &m);
3294  emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3295       m * B5 | vm);
3296}
3297
3298
3299void Assembler::vcmp(const DwVfpRegister src1,
3300                     const DwVfpRegister src2,
3301                     const Condition cond) {
3302  // vcmp(Dd, Dm) double precision floating point comparison.
3303  // Instruction details available in ARM DDI 0406C.b, A8-864.
3304  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
3305  // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3306  int vd, d;
3307  src1.split_code(&vd, &d);
3308  int vm, m;
3309  src2.split_code(&vm, &m);
3310  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 |
3311       m*B5 | vm);
3312}
3313
3314
3315void Assembler::vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
3316                     const Condition cond) {
3317  // vcmp(Sd, Sm) single precision floating point comparison.
3318  // Instruction details available in ARM DDI 0406C.b, A8-864.
3319  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
3320  // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3321  int vd, d;
3322  src1.split_code(&vd, &d);
3323  int vm, m;
3324  src2.split_code(&vm, &m);
3325  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 |
3326       0x5 * B9 | B6 | m * B5 | vm);
3327}
3328
3329
3330void Assembler::vcmp(const DwVfpRegister src1,
3331                     const double src2,
3332                     const Condition cond) {
3333  // vcmp(Dd, #0.0) double precision floating point comparison.
3334  // Instruction details available in ARM DDI 0406C.b, A8-864.
3335  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3336  // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3337  DCHECK(src2 == 0.0);
3338  int vd, d;
3339  src1.split_code(&vd, &d);
3340  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6);
3341}
3342
3343
3344void Assembler::vcmp(const SwVfpRegister src1, const float src2,
3345                     const Condition cond) {
3346  // vcmp(Sd, #0.0) single precision floating point comparison.
3347  // Instruction details available in ARM DDI 0406C.b, A8-864.
3348  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3349  // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3350  DCHECK(src2 == 0.0);
3351  int vd, d;
3352  src1.split_code(&vd, &d);
3353  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 |
3354       0x5 * B9 | B6);
3355}
3356
3357
3358void Assembler::vsqrt(const DwVfpRegister dst,
3359                      const DwVfpRegister src,
3360                      const Condition cond) {
3361  // Instruction details available in ARM DDI 0406C.b, A8-1058.
3362  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
3363  // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
3364  int vd, d;
3365  dst.split_code(&vd, &d);
3366  int vm, m;
3367  src.split_code(&vm, &m);
3368  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 |
3369       m*B5 | vm);
3370}
3371
3372
3373void Assembler::vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
3374                      const Condition cond) {
3375  // Instruction details available in ARM DDI 0406C.b, A8-1058.
3376  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
3377  // Vd(15-12) | 101(11-9) | sz=0(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
3378  int vd, d;
3379  dst.split_code(&vd, &d);
3380  int vm, m;
3381  src.split_code(&vm, &m);
3382  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
3383       0x3 * B6 | m * B5 | vm);
3384}
3385
3386
3387void Assembler::vmsr(Register dst, Condition cond) {
3388  // Instruction details available in ARM DDI 0406A, A8-652.
3389  // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
3390  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
3391  emit(cond | 0xE * B24 | 0xE * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
3392}
3393
3394
3395void Assembler::vmrs(Register dst, Condition cond) {
3396  // Instruction details available in ARM DDI 0406A, A8-652.
3397  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
3398  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
3399  emit(cond | 0xE * B24 | 0xF * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
3400}
3401
3402
3403void Assembler::vrinta(const SwVfpRegister dst, const SwVfpRegister src) {
3404  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3405  // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3406  // M(5) | 0(4) | Vm(3-0)
3407  DCHECK(CpuFeatures::IsSupported(ARMv8));
3408  int vd, d;
3409  dst.split_code(&vd, &d);
3410  int vm, m;
3411  src.split_code(&vm, &m);
3412  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
3413       0x5 * B9 | B6 | m * B5 | vm);
3414}
3415
3416
3417void Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) {
3418  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3419  // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3420  // M(5) | 0(4) | Vm(3-0)
3421  DCHECK(CpuFeatures::IsSupported(ARMv8));
3422  int vd, d;
3423  dst.split_code(&vd, &d);
3424  int vm, m;
3425  src.split_code(&vm, &m);
3426  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
3427       0x5 * B9 | B8 | B6 | m * B5 | vm);
3428}
3429
3430
3431void Assembler::vrintn(const SwVfpRegister dst, const SwVfpRegister src) {
3432  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3433  // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3434  // M(5) | 0(4) | Vm(3-0)
3435  DCHECK(CpuFeatures::IsSupported(ARMv8));
3436  int vd, d;
3437  dst.split_code(&vd, &d);
3438  int vm, m;
3439  src.split_code(&vm, &m);
3440  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
3441       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3442}
3443
3444
3445void Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) {
3446  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3447  // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3448  // M(5) | 0(4) | Vm(3-0)
3449  DCHECK(CpuFeatures::IsSupported(ARMv8));
3450  int vd, d;
3451  dst.split_code(&vd, &d);
3452  int vm, m;
3453  src.split_code(&vm, &m);
3454  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
3455       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3456}
3457
3458
3459void Assembler::vrintp(const SwVfpRegister dst, const SwVfpRegister src) {
3460  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3461  // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3462  // M(5) | 0(4) | Vm(3-0)
3463  DCHECK(CpuFeatures::IsSupported(ARMv8));
3464  int vd, d;
3465  dst.split_code(&vd, &d);
3466  int vm, m;
3467  src.split_code(&vm, &m);
3468  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
3469       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3470}
3471
3472
3473void Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) {
3474  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3475  // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3476  // M(5) | 0(4) | Vm(3-0)
3477  DCHECK(CpuFeatures::IsSupported(ARMv8));
3478  int vd, d;
3479  dst.split_code(&vd, &d);
3480  int vm, m;
3481  src.split_code(&vm, &m);
3482  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
3483       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3484}
3485
3486
3487void Assembler::vrintm(const SwVfpRegister dst, const SwVfpRegister src) {
3488  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3489  // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3490  // M(5) | 0(4) | Vm(3-0)
3491  DCHECK(CpuFeatures::IsSupported(ARMv8));
3492  int vd, d;
3493  dst.split_code(&vd, &d);
3494  int vm, m;
3495  src.split_code(&vm, &m);
3496  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
3497       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3498}
3499
3500
3501void Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) {
3502  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3503  // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3504  // M(5) | 0(4) | Vm(3-0)
3505  DCHECK(CpuFeatures::IsSupported(ARMv8));
3506  int vd, d;
3507  dst.split_code(&vd, &d);
3508  int vm, m;
3509  src.split_code(&vm, &m);
3510  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
3511       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3512}
3513
3514
3515void Assembler::vrintz(const SwVfpRegister dst, const SwVfpRegister src,
3516                       const Condition cond) {
3517  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
3518  // Vd(15-12) | 101(11-9) | sz=0(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3519  DCHECK(CpuFeatures::IsSupported(ARMv8));
3520  int vd, d;
3521  dst.split_code(&vd, &d);
3522  int vm, m;
3523  src.split_code(&vm, &m);
3524  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
3525       0x5 * B9 | B7 | B6 | m * B5 | vm);
3526}
3527
3528
3529void Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src,
3530                       const Condition cond) {
3531  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
3532  // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3533  DCHECK(CpuFeatures::IsSupported(ARMv8));
3534  int vd, d;
3535  dst.split_code(&vd, &d);
3536  int vm, m;
3537  src.split_code(&vm, &m);
3538  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
3539       0x5 * B9 | B8 | B7 | B6 | m * B5 | vm);
3540}
3541
3542
3543// Support for NEON.
3544
3545void Assembler::vld1(NeonSize size,
3546                     const NeonListOperand& dst,
3547                     const NeonMemOperand& src) {
3548  // Instruction details available in ARM DDI 0406C.b, A8.8.320.
3549  // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) |
3550  // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3551  DCHECK(CpuFeatures::IsSupported(NEON));
3552  int vd, d;
3553  dst.base().split_code(&vd, &d);
3554  emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 |
3555       dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code());
3556}
3557
3558
3559void Assembler::vst1(NeonSize size,
3560                     const NeonListOperand& src,
3561                     const NeonMemOperand& dst) {
3562  // Instruction details available in ARM DDI 0406C.b, A8.8.404.
3563  // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
3564  // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3565  DCHECK(CpuFeatures::IsSupported(NEON));
3566  int vd, d;
3567  src.base().split_code(&vd, &d);
3568  emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 |
3569       size*B6 | dst.align()*B4 | dst.rm().code());
3570}
3571
3572
3573void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) {
3574  // Instruction details available in ARM DDI 0406C.b, A8.8.346.
3575  // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) |
3576  // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0)
3577  DCHECK(CpuFeatures::IsSupported(NEON));
3578  int vd, d;
3579  dst.split_code(&vd, &d);
3580  int vm, m;
3581  src.split_code(&vm, &m);
3582  emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 |
3583        (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm);
3584}
3585
3586
3587// Pseudo instructions.
3588void Assembler::nop(int type) {
3589  // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes
3590  // some of the CPU's pipeline and has to issue. Older ARM chips simply used
3591  // MOV Rx, Rx as NOP and it performs better even in newer CPUs.
3592  // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
3593  // a type.
3594  DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
3595  emit(al | 13*B21 | type*B12 | type);
3596}
3597
3598
3599bool Assembler::IsMovT(Instr instr) {
3600  instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
3601             ((kNumRegisters-1)*B12) |            // mask out register
3602             EncodeMovwImmediate(0xFFFF));        // mask out immediate value
3603  return instr == kMovtPattern;
3604}
3605
3606
3607bool Assembler::IsMovW(Instr instr) {
3608  instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
3609             ((kNumRegisters-1)*B12) |            // mask out destination
3610             EncodeMovwImmediate(0xFFFF));        // mask out immediate value
3611  return instr == kMovwPattern;
3612}
3613
3614
3615Instr Assembler::GetMovTPattern() { return kMovtPattern; }
3616
3617
3618Instr Assembler::GetMovWPattern() { return kMovwPattern; }
3619
3620
3621Instr Assembler::EncodeMovwImmediate(uint32_t immediate) {
3622  DCHECK(immediate < 0x10000);
3623  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
3624}
3625
3626
3627Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
3628  instruction &= ~EncodeMovwImmediate(0xffff);
3629  return instruction | EncodeMovwImmediate(immediate);
3630}
3631
3632
3633int Assembler::DecodeShiftImm(Instr instr) {
3634  int rotate = Instruction::RotateValue(instr) * 2;
3635  int immed8 = Instruction::Immed8Value(instr);
3636  return base::bits::RotateRight32(immed8, rotate);
3637}
3638
3639
3640Instr Assembler::PatchShiftImm(Instr instr, int immed) {
3641  uint32_t rotate_imm = 0;
3642  uint32_t immed_8 = 0;
3643  bool immed_fits = fits_shifter(immed, &rotate_imm, &immed_8, NULL);
3644  DCHECK(immed_fits);
3645  USE(immed_fits);
3646  return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8;
3647}
3648
3649
3650bool Assembler::IsNop(Instr instr, int type) {
3651  DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
3652  // Check for mov rx, rx where x = type.
3653  return instr == (al | 13*B21 | type*B12 | type);
3654}
3655
3656
3657bool Assembler::IsMovImmed(Instr instr) {
3658  return (instr & kMovImmedMask) == kMovImmedPattern;
3659}
3660
3661
3662bool Assembler::IsOrrImmed(Instr instr) {
3663  return (instr & kOrrImmedMask) == kOrrImmedPattern;
3664}
3665
3666
3667// static
3668bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
3669  uint32_t dummy1;
3670  uint32_t dummy2;
3671  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
3672}
3673
3674
3675bool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) {
3676  return is_uint12(abs(imm32));
3677}
3678
3679
3680// Debugging.
3681void Assembler::RecordConstPool(int size) {
3682  // We only need this for debugger support, to correctly compute offsets in the
3683  // code.
3684  RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
3685}
3686
3687
3688void Assembler::GrowBuffer() {
3689  if (!own_buffer_) FATAL("external code buffer is too small");
3690
3691  // Compute new buffer size.
3692  CodeDesc desc;  // the new buffer
3693  if (buffer_size_ < 1 * MB) {
3694    desc.buffer_size = 2*buffer_size_;
3695  } else {
3696    desc.buffer_size = buffer_size_ + 1*MB;
3697  }
3698  CHECK_GT(desc.buffer_size, 0);  // no overflow
3699
3700  // Set up new buffer.
3701  desc.buffer = NewArray<byte>(desc.buffer_size);
3702
3703  desc.instr_size = pc_offset();
3704  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
3705  desc.origin = this;
3706
3707  // Copy the data.
3708  int pc_delta = desc.buffer - buffer_;
3709  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
3710  MemMove(desc.buffer, buffer_, desc.instr_size);
3711  MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
3712          desc.reloc_size);
3713
3714  // Switch buffers.
3715  DeleteArray(buffer_);
3716  buffer_ = desc.buffer;
3717  buffer_size_ = desc.buffer_size;
3718  pc_ += pc_delta;
3719  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3720                               reloc_info_writer.last_pc() + pc_delta);
3721
3722  // None of our relocation types are pc relative pointing outside the code
3723  // buffer nor pc absolute pointing inside the code buffer, so there is no need
3724  // to relocate any emitted relocation entries.
3725}
3726
3727
3728void Assembler::db(uint8_t data) {
3729  // db is used to write raw data. The constant pool should be emitted or
3730  // blocked before using db.
3731  DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
3732  DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
3733  CheckBuffer();
3734  *reinterpret_cast<uint8_t*>(pc_) = data;
3735  pc_ += sizeof(uint8_t);
3736}
3737
3738
3739void Assembler::dd(uint32_t data) {
3740  // dd is used to write raw data. The constant pool should be emitted or
3741  // blocked before using dd.
3742  DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
3743  DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
3744  CheckBuffer();
3745  *reinterpret_cast<uint32_t*>(pc_) = data;
3746  pc_ += sizeof(uint32_t);
3747}
3748
3749
3750void Assembler::dq(uint64_t value) {
3751  // dq is used to write raw data. The constant pool should be emitted or
3752  // blocked before using dq.
3753  DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
3754  DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
3755  CheckBuffer();
3756  *reinterpret_cast<uint64_t*>(pc_) = value;
3757  pc_ += sizeof(uint64_t);
3758}
3759
3760
3761void Assembler::emit_code_stub_address(Code* stub) {
3762  CheckBuffer();
3763  *reinterpret_cast<uint32_t*>(pc_) =
3764      reinterpret_cast<uint32_t>(stub->instruction_start());
3765  pc_ += sizeof(uint32_t);
3766}
3767
3768
3769void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3770  if (RelocInfo::IsNone(rmode) ||
3771      // Don't record external references unless the heap will be serialized.
3772      (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
3773       !emit_debug_code())) {
3774    return;
3775  }
3776  DCHECK(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
3777  if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
3778    data = RecordedAstId().ToInt();
3779    ClearRecordedAstId();
3780  }
3781  RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
3782  reloc_info_writer.Write(&rinfo);
3783}
3784
3785
3786ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
3787                                                          RelocInfo::Mode rmode,
3788                                                          intptr_t value) {
3789  DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION &&
3790         rmode != RelocInfo::STATEMENT_POSITION &&
3791         rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64);
3792  bool sharing_ok = RelocInfo::IsNone(rmode) ||
3793                    !(serializer_enabled() || rmode < RelocInfo::CELL);
3794  if (FLAG_enable_embedded_constant_pool) {
3795    return constant_pool_builder_.AddEntry(position, value, sharing_ok);
3796  } else {
3797    DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants);
3798    if (num_pending_32_bit_constants_ == 0) {
3799      first_const_pool_32_use_ = position;
3800    } else if (num_pending_32_bit_constants_ == kMinNumPendingConstants &&
3801               pending_32_bit_constants_ ==
3802                   &pending_32_bit_constants_buffer_[0]) {
3803      // Inline buffer is full, switch to dynamically allocated buffer.
3804      pending_32_bit_constants_ =
3805          new ConstantPoolEntry[kMaxNumPending32Constants];
3806      std::copy(&pending_32_bit_constants_buffer_[0],
3807                &pending_32_bit_constants_buffer_[kMinNumPendingConstants],
3808                &pending_32_bit_constants_[0]);
3809    }
3810    ConstantPoolEntry entry(position, value, sharing_ok);
3811    pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry;
3812
3813    // Make sure the constant pool is not emitted in place of the next
3814    // instruction for which we just recorded relocation info.
3815    BlockConstPoolFor(1);
3816    return ConstantPoolEntry::REGULAR;
3817  }
3818}
3819
3820
3821ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
3822                                                          double value) {
3823  if (FLAG_enable_embedded_constant_pool) {
3824    return constant_pool_builder_.AddEntry(position, value);
3825  } else {
3826    DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants);
3827    if (num_pending_64_bit_constants_ == 0) {
3828      first_const_pool_64_use_ = position;
3829    } else if (num_pending_64_bit_constants_ == kMinNumPendingConstants &&
3830               pending_64_bit_constants_ ==
3831                   &pending_64_bit_constants_buffer_[0]) {
3832      // Inline buffer is full, switch to dynamically allocated buffer.
3833      pending_64_bit_constants_ =
3834          new ConstantPoolEntry[kMaxNumPending64Constants];
3835      std::copy(&pending_64_bit_constants_buffer_[0],
3836                &pending_64_bit_constants_buffer_[kMinNumPendingConstants],
3837                &pending_64_bit_constants_[0]);
3838    }
3839    ConstantPoolEntry entry(position, value);
3840    pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry;
3841
3842    // Make sure the constant pool is not emitted in place of the next
3843    // instruction for which we just recorded relocation info.
3844    BlockConstPoolFor(1);
3845    return ConstantPoolEntry::REGULAR;
3846  }
3847}
3848
3849
3850void Assembler::BlockConstPoolFor(int instructions) {
3851  if (FLAG_enable_embedded_constant_pool) {
3852    // Should be a no-op if using an embedded constant pool.
3853    DCHECK(num_pending_32_bit_constants_ == 0);
3854    DCHECK(num_pending_64_bit_constants_ == 0);
3855    return;
3856  }
3857
3858  int pc_limit = pc_offset() + instructions * kInstrSize;
3859  if (no_const_pool_before_ < pc_limit) {
3860    // Max pool start (if we need a jump and an alignment).
3861#ifdef DEBUG
3862    int start = pc_limit + kInstrSize + 2 * kPointerSize;
3863    DCHECK((num_pending_32_bit_constants_ == 0) ||
3864           (start - first_const_pool_32_use_ +
3865                num_pending_64_bit_constants_ * kDoubleSize <
3866            kMaxDistToIntPool));
3867    DCHECK((num_pending_64_bit_constants_ == 0) ||
3868           (start - first_const_pool_64_use_ < kMaxDistToFPPool));
3869#endif
3870    no_const_pool_before_ = pc_limit;
3871  }
3872
3873  if (next_buffer_check_ < no_const_pool_before_) {
3874    next_buffer_check_ = no_const_pool_before_;
3875  }
3876}
3877
3878
3879void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
3880  if (FLAG_enable_embedded_constant_pool) {
3881    // Should be a no-op if using an embedded constant pool.
3882    DCHECK(num_pending_32_bit_constants_ == 0);
3883    DCHECK(num_pending_64_bit_constants_ == 0);
3884    return;
3885  }
3886
3887  // Some short sequence of instruction mustn't be broken up by constant pool
3888  // emission, such sequences are protected by calls to BlockConstPoolFor and
3889  // BlockConstPoolScope.
3890  if (is_const_pool_blocked()) {
3891    // Something is wrong if emission is forced and blocked at the same time.
3892    DCHECK(!force_emit);
3893    return;
3894  }
3895
3896  // There is nothing to do if there are no pending constant pool entries.
3897  if ((num_pending_32_bit_constants_ == 0) &&
3898      (num_pending_64_bit_constants_ == 0)) {
3899    // Calculate the offset of the next check.
3900    next_buffer_check_ = pc_offset() + kCheckPoolInterval;
3901    return;
3902  }
3903
3904  // Check that the code buffer is large enough before emitting the constant
3905  // pool (include the jump over the pool and the constant pool marker and
3906  // the gap to the relocation information).
3907  int jump_instr = require_jump ? kInstrSize : 0;
3908  int size_up_to_marker = jump_instr + kInstrSize;
3909  int estimated_size_after_marker =
3910      num_pending_32_bit_constants_ * kPointerSize;
3911  bool has_int_values = (num_pending_32_bit_constants_ > 0);
3912  bool has_fp_values = (num_pending_64_bit_constants_ > 0);
3913  bool require_64_bit_align = false;
3914  if (has_fp_values) {
3915    require_64_bit_align =
3916        !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker),
3917                   kDoubleAlignment);
3918    if (require_64_bit_align) {
3919      estimated_size_after_marker += kInstrSize;
3920    }
3921    estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize;
3922  }
3923  int estimated_size = size_up_to_marker + estimated_size_after_marker;
3924
3925  // We emit a constant pool when:
3926  //  * requested to do so by parameter force_emit (e.g. after each function).
3927  //  * the distance from the first instruction accessing the constant pool to
3928  //    any of the constant pool entries will exceed its limit the next
3929  //    time the pool is checked. This is overly restrictive, but we don't emit
3930  //    constant pool entries in-order so it's conservatively correct.
3931  //  * the instruction doesn't require a jump after itself to jump over the
3932  //    constant pool, and we're getting close to running out of range.
3933  if (!force_emit) {
3934    DCHECK(has_fp_values || has_int_values);
3935    bool need_emit = false;
3936    if (has_fp_values) {
3937      // The 64-bit constants are always emitted before the 32-bit constants, so
3938      // we can ignore the effect of the 32-bit constants on estimated_size.
3939      int dist64 = pc_offset() + estimated_size -
3940                   num_pending_32_bit_constants_ * kPointerSize -
3941                   first_const_pool_64_use_;
3942      if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
3943          (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
3944        need_emit = true;
3945      }
3946    }
3947    if (has_int_values) {
3948      int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_;
3949      if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
3950          (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
3951        need_emit = true;
3952      }
3953    }
3954    if (!need_emit) return;
3955  }
3956
3957  // Deduplicate constants.
3958  int size_after_marker = estimated_size_after_marker;
3959  for (int i = 0; i < num_pending_64_bit_constants_; i++) {
3960    ConstantPoolEntry& entry = pending_64_bit_constants_[i];
3961    DCHECK(!entry.is_merged());
3962    for (int j = 0; j < i; j++) {
3963      if (entry.value64() == pending_64_bit_constants_[j].value64()) {
3964        DCHECK(!pending_64_bit_constants_[j].is_merged());
3965        entry.set_merged_index(j);
3966        size_after_marker -= kDoubleSize;
3967        break;
3968      }
3969    }
3970  }
3971
3972  for (int i = 0; i < num_pending_32_bit_constants_; i++) {
3973    ConstantPoolEntry& entry = pending_32_bit_constants_[i];
3974    DCHECK(!entry.is_merged());
3975    if (!entry.sharing_ok()) continue;
3976    for (int j = 0; j < i; j++) {
3977      if (entry.value() == pending_32_bit_constants_[j].value()) {
3978        DCHECK(!pending_32_bit_constants_[j].is_merged());
3979        entry.set_merged_index(j);
3980        size_after_marker -= kPointerSize;
3981        break;
3982      }
3983    }
3984  }
3985
3986  int size = size_up_to_marker + size_after_marker;
3987
3988  int needed_space = size + kGap;
3989  while (buffer_space() <= needed_space) GrowBuffer();
3990
3991  {
3992    // Block recursive calls to CheckConstPool.
3993    BlockConstPoolScope block_const_pool(this);
3994    RecordComment("[ Constant Pool");
3995    RecordConstPool(size);
3996
3997    Label size_check;
3998    bind(&size_check);
3999
4000    // Emit jump over constant pool if necessary.
4001    Label after_pool;
4002    if (require_jump) {
4003      b(&after_pool);
4004    }
4005
4006    // Put down constant pool marker "Undefined instruction".
4007    // The data size helps disassembly know what to print.
4008    emit(kConstantPoolMarker |
4009         EncodeConstantPoolLength(size_after_marker / kPointerSize));
4010
4011    if (require_64_bit_align) {
4012      emit(kConstantPoolMarker);
4013    }
4014
4015    // Emit 64-bit constant pool entries first: their range is smaller than
4016    // 32-bit entries.
4017    for (int i = 0; i < num_pending_64_bit_constants_; i++) {
4018      ConstantPoolEntry& entry = pending_64_bit_constants_[i];
4019
4020      Instr instr = instr_at(entry.position());
4021      // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
4022      DCHECK((IsVldrDPcImmediateOffset(instr) &&
4023              GetVldrDRegisterImmediateOffset(instr) == 0));
4024
4025      int delta = pc_offset() - entry.position() - kPcLoadDelta;
4026      DCHECK(is_uint10(delta));
4027
4028      if (entry.is_merged()) {
4029        ConstantPoolEntry& merged =
4030            pending_64_bit_constants_[entry.merged_index()];
4031        DCHECK(entry.value64() == merged.value64());
4032        Instr merged_instr = instr_at(merged.position());
4033        DCHECK(IsVldrDPcImmediateOffset(merged_instr));
4034        delta = GetVldrDRegisterImmediateOffset(merged_instr);
4035        delta += merged.position() - entry.position();
4036      }
4037      instr_at_put(entry.position(),
4038                   SetVldrDRegisterImmediateOffset(instr, delta));
4039      if (!entry.is_merged()) {
4040        DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment));
4041        dq(entry.value64());
4042      }
4043    }
4044
4045    // Emit 32-bit constant pool entries.
4046    for (int i = 0; i < num_pending_32_bit_constants_; i++) {
4047      ConstantPoolEntry& entry = pending_32_bit_constants_[i];
4048      Instr instr = instr_at(entry.position());
4049
4050      // 64-bit loads shouldn't get here.
4051      DCHECK(!IsVldrDPcImmediateOffset(instr));
4052      DCHECK(!IsMovW(instr));
4053      DCHECK(IsLdrPcImmediateOffset(instr) &&
4054             GetLdrRegisterImmediateOffset(instr) == 0);
4055
4056      int delta = pc_offset() - entry.position() - kPcLoadDelta;
4057      DCHECK(is_uint12(delta));
4058      // 0 is the smallest delta:
4059      //   ldr rd, [pc, #0]
4060      //   constant pool marker
4061      //   data
4062
4063      if (entry.is_merged()) {
4064        DCHECK(entry.sharing_ok());
4065        ConstantPoolEntry& merged =
4066            pending_32_bit_constants_[entry.merged_index()];
4067        DCHECK(entry.value() == merged.value());
4068        Instr merged_instr = instr_at(merged.position());
4069        DCHECK(IsLdrPcImmediateOffset(merged_instr));
4070        delta = GetLdrRegisterImmediateOffset(merged_instr);
4071        delta += merged.position() - entry.position();
4072      }
4073      instr_at_put(entry.position(),
4074                   SetLdrRegisterImmediateOffset(instr, delta));
4075      if (!entry.is_merged()) {
4076        emit(entry.value());
4077      }
4078    }
4079
4080    num_pending_32_bit_constants_ = 0;
4081    num_pending_64_bit_constants_ = 0;
4082    first_const_pool_32_use_ = -1;
4083    first_const_pool_64_use_ = -1;
4084
4085    RecordComment("]");
4086
4087    DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check));
4088
4089    if (after_pool.is_linked()) {
4090      bind(&after_pool);
4091    }
4092  }
4093
4094  // Since a constant pool was just emitted, move the check offset forward by
4095  // the standard interval.
4096  next_buffer_check_ = pc_offset() + kCheckPoolInterval;
4097}
4098
4099
4100void Assembler::PatchConstantPoolAccessInstruction(
4101    int pc_offset, int offset, ConstantPoolEntry::Access access,
4102    ConstantPoolEntry::Type type) {
4103  DCHECK(FLAG_enable_embedded_constant_pool);
4104  Address pc = buffer_ + pc_offset;
4105
4106  // Patch vldr/ldr instruction with correct offset.
4107  Instr instr = instr_at(pc);
4108  if (access == ConstantPoolEntry::OVERFLOWED) {
4109    if (CpuFeatures::IsSupported(ARMv7)) {
4110      // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
4111      Instr next_instr = instr_at(pc + kInstrSize);
4112      DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0));
4113      DCHECK((IsMovT(next_instr) &&
4114              Instruction::ImmedMovwMovtValue(next_instr) == 0));
4115      instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff));
4116      instr_at_put(pc + kInstrSize,
4117                   PatchMovwImmediate(next_instr, offset >> 16));
4118    } else {
4119      // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
4120      Instr instr_2 = instr_at(pc + kInstrSize);
4121      Instr instr_3 = instr_at(pc + 2 * kInstrSize);
4122      Instr instr_4 = instr_at(pc + 3 * kInstrSize);
4123      DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0));
4124      DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) &&
4125             GetRn(instr_2).is(GetRd(instr_2)));
4126      DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) &&
4127             GetRn(instr_3).is(GetRd(instr_3)));
4128      DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) &&
4129             GetRn(instr_4).is(GetRd(instr_4)));
4130      instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask)));
4131      instr_at_put(pc + kInstrSize,
4132                   PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
4133      instr_at_put(pc + 2 * kInstrSize,
4134                   PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
4135      instr_at_put(pc + 3 * kInstrSize,
4136                   PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
4137    }
4138  } else if (type == ConstantPoolEntry::DOUBLE) {
4139    // Instruction to patch must be 'vldr rd, [pp, #0]'.
4140    DCHECK((IsVldrDPpImmediateOffset(instr) &&
4141            GetVldrDRegisterImmediateOffset(instr) == 0));
4142    DCHECK(is_uint10(offset));
4143    instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset));
4144  } else {
4145    // Instruction to patch must be 'ldr rd, [pp, #0]'.
4146    DCHECK((IsLdrPpImmediateOffset(instr) &&
4147            GetLdrRegisterImmediateOffset(instr) == 0));
4148    DCHECK(is_uint12(offset));
4149    instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset));
4150  }
4151}
4152
4153
4154}  // namespace internal
4155}  // namespace v8
4156
4157#endif  // V8_TARGET_ARCH_ARM
4158